From veillard at redhat.com Fri Apr 1 01:25:45 2011 From: veillard at redhat.com (Daniel Veillard) Date: Fri, 1 Apr 2011 09:25:45 +0800 Subject: [libvirt] [PATCH] Fix several formatting mistakes in doc In-Reply-To: <4D94B6B6.7000806@redhat.com> References: <1301570043-30978-1-git-send-email-mprivozn@redhat.com> <20110331135837.GM24425@redhat.com> <4D94B6B6.7000806@redhat.com> Message-ID: <20110401012545.GG24385@redhat.com> On Thu, Mar 31, 2011 at 11:15:34AM -0600, Eric Blake wrote: > On 03/31/2011 07:58 AM, Daniel P. Berrange wrote: > > > > - We run xmllint, but failures in xmllint validation > > are not causing a build failure > > We already have code in place to call 'exit 1' on xmllint failure (but > not in all places). However, in my testing, it was xsltproc that is not > throwing an error: > > $ /usr/bin/xsltproc --stringparam pagename $name --nonet --html > ../docs/site.xsl formatdomain.html.in > formatdomain.html.tmp > formatdomain.html.in:356: HTML parser error : Unexpected end tag : vcpu > required attributes, the attribute vcpu specifies > vcpu id, > ^ > $ echo $? > 0 it's because we are using --html, instructing libxml2 underneath to use teh HTML parser to load the .html.in . And the HTML parser is just reporting errors, not failing on them (as 99% of the HTML around is just buggy). > That looks like a bug in xsltproc (here from Fedora > libxslt-1.1.26-3.fc14.x86_64), since the man page states that $? should > be 6 when there is an error in the document. Well except for HTML input, remove the --html and see, maybe we could do that in the Makefile and insist on the .html.in being well formed in the first place. > I can work around it by sniffing for non-empty stderr; that will look > yucky in the makefile, but is probably worth doing. Doesn't sound that great honnestly, try dropping --html instead and see how it goes Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Fri Apr 1 01:27:52 2011 From: veillard at redhat.com (Daniel Veillard) Date: Fri, 1 Apr 2011 09:27:52 +0800 Subject: [libvirt] [PATCH] Fix several formatting mistakes in doc In-Reply-To: <4D94D495.4040503@redhat.com> References: <1301570043-30978-1-git-send-email-mprivozn@redhat.com> <20110331135837.GM24425@redhat.com> <4D94B6B6.7000806@redhat.com> <20110331171843.GR24425@redhat.com> <4D94D495.4040503@redhat.com> Message-ID: <20110401012752.GH24385@redhat.com> On Thu, Mar 31, 2011 at 01:23:01PM -0600, Eric Blake wrote: > On 03/31/2011 11:18 AM, Daniel P. Berrange wrote: > >> That looks like a bug in xsltproc (here from Fedora > >> libxslt-1.1.26-3.fc14.x86_64), since the man page states that $? should > >> be 6 when there is an error in the document. > >> > >> I can work around it by sniffing for non-empty stderr; that will look > >> yucky in the makefile, but is probably worth doing. > > > > Hmm, so we've actually got two things to validate > > > > - Welformed XML > > - HTML schema compliance > > > > The current xmllint run is doing the latter. We should also > > run xmllint before xsltproc, so we can validate wellformedness > > of the input HTML files. Thus avoiding reliance of xsltproc > > exit status > > Do you have a sample command line for how to make xmllint check that the > html.in file is well-formed XML? I just tried: > > $ SGML_CATALOG_FILES='/etc/xml/catalog' /usr/bin/xmllint --catalogs > --nonet --format --valid formatcaps.html.in >/dev/null > formatcaps.html.in:1: validity error : Validation failed: no DTD found ! > > ^ just drop --valid from the command line, xmllint usually doesn't check validity. But IMHO it's simpler to just drop the --html flag from xsltproc as suggestedon previous mail > but that's obviously not right (it works on the post-processed generated > html document, but that's why we're generating the document, to add in > the rest of the boilerplate to the xml shell that makes it valid html). Yup the input should just be expected to be well-formed not valid, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From usui at mxm.nes.nec.co.jp Fri Apr 1 01:38:33 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 1 Apr 2011 10:38:33 +0900 Subject: [libvirt] [PATCH 0/6] Add virNodeGetCpuTime() API Message-ID: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> Hi, everyone. I wrote new API called virNodeGetCpuTime(). It returns cumulative cpu time of the node from /proc/stat since node boots up. Previous discussion is here. http://www.mail-archive.com/libvir-list at redhat.com/msg32552.html Minoru Usui (6): [1/6] virNodeGetCpuTime: Expose new API [2/6] virNodeGetCpuTime: Define internal driver API [3/6] virNodeGetCpuTime: Implement public API [4/6] virNodeGetCpuTime: Implement remote protocol [5/6] virNodeGetCpuTime: Implement virsh support [6/6] virNodeGetCpuTime: Implement linux support daemon/remote.c | 23 ++++++++++++ daemon/remote_dispatch_prototypes.h | 8 ++++ daemon/remote_dispatch_ret.h | 1 + daemon/remote_dispatch_table.h | 5 +++ include/libvirt/libvirt.h.in | 26 ++++++++++++++ src/driver.h | 4 ++ src/esx/esx_driver.c | 1 + src/libvirt.c | 38 ++++++++++++++++++++ src/libvirt_private.syms | 1 + src/libvirt_public.syms | 1 + src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/nodeinfo.c | 60 +++++++++++++++++++++++++++++++ src/nodeinfo.h | 2 +- src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 27 ++++++++++++++ src/remote/remote_protocol.c | 15 ++++++++ src/remote/remote_protocol.h | 11 ++++++ src/remote/remote_protocol.x | 10 +++++- src/remote_protocol-structs | 6 +++ src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xenapi/xenapi_driver.c | 1 + tools/virsh.c | 66 +++++++++++++++++++++++++++++++++++ tools/virsh.pod | 6 +++ 30 files changed, 320 insertions(+), 2 deletions(-) -- Minoru Usui From usui at mxm.nes.nec.co.jp Fri Apr 1 01:55:48 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 1 Apr 2011 10:55:48 +0900 Subject: [libvirt] [PATCH 1/6] virNodeGetCpuTime: Expose new API In-Reply-To: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> Message-ID: <20110401105548.a78607f7.usui@mxm.nes.nec.co.jp> virNodeGetCpuTime: Expose new API include/libvirt/libvirt.h.in | 26 ++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + 2 files changed, 27 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index bd36015..b61ce9c 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -228,6 +228,21 @@ struct _virNodeInfo { unsigned int threads;/* number of threads per core */ }; +/** + * virNodeCpuTime: + * + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing + * the information for the cpu time of Node. + */ + +typedef struct _virNodeCpuTime virNodeCpuTime; + +struct _virNodeCpuTime { + unsigned long long user; + unsigned long long system; + unsigned long long idle; + unsigned long long iowait; +}; /** * virDomainSchedParameterType: @@ -460,6 +475,14 @@ int virDomainMigrateSetMaxSpeed(virDomainPtr domain, typedef virNodeInfo *virNodeInfoPtr; /** + * virNodeCpuTimePtr: + * + * a virNodeCpuTimePtr is a pointer to a virNodeCpuTime structure. + */ + +typedef virNodeCpuTime *virNodeCpuTimePtr; + +/** * virConnectFlags * * Flags when opening a connection to a hypervisor @@ -593,6 +616,9 @@ int virNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info); char * virConnectGetCapabilities (virConnectPtr conn); +int virNodeGetCpuTime (virConnectPtr conn, + virNodeCpuTimePtr cpu_time); + unsigned long long virNodeGetFreeMemory (virConnectPtr conn); int virNodeGetSecurityModel (virConnectPtr conn, diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b4aed41..53575e1 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -434,6 +434,7 @@ LIBVIRT_0.9.0 { virEventRunDefaultImpl; virStorageVolDownload; virStorageVolUpload; + virNodeGetCpuTime; } LIBVIRT_0.8.8; # .... define new API here using predicted next version number .... -- 1.7.1 -- Minoru Usui From usui at mxm.nes.nec.co.jp Fri Apr 1 01:56:45 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 1 Apr 2011 10:56:45 +0900 Subject: [libvirt] [PATCH 2/6] virNodeGetCpuTime: Define internal driver API In-Reply-To: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> Message-ID: <20110401105645.9a0e7436.usui@mxm.nes.nec.co.jp> virNodeGetCpuTime: Define internal driver API --- src/driver.h | 4 ++++ src/esx/esx_driver.c | 1 + src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 1 + src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xenapi/xenapi_driver.c | 1 + 14 files changed, 17 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index e5f91ca..f64fe31 100644 --- a/src/driver.h +++ b/src/driver.h @@ -347,6 +347,9 @@ typedef struct _virDriver virDriver; typedef virDriver *virDriverPtr; typedef int + (*virDrvNodeGetCpuTime) + (virConnectPtr conn, virNodeCpuTimePtr cpu_time); +typedef int (*virDrvNodeGetCellsFreeMemory) (virConnectPtr conn, unsigned long long *freeMems, @@ -602,6 +605,7 @@ struct _virDriver { virDrvDomainBlockPeek domainBlockPeek; virDrvDomainMemoryPeek domainMemoryPeek; virDrvDomainGetBlockInfo domainGetBlockInfo; + virDrvNodeGetCpuTime nodeGetCpuTime; virDrvNodeGetCellsFreeMemory nodeGetCellsFreeMemory; virDrvNodeGetFreeMemory getFreeMemory; virDrvDomainEventRegister domainEventRegister; diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index deda372..6e55949 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4638,6 +4638,7 @@ static virDriver esxDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ NULL, /* nodeGetCellsFreeMemory */ esxNodeGetFreeMemory, /* nodeGetFreeMemory */ NULL, /* domainEventRegister */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index e996ff6..9b5a70e 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2316,6 +2316,7 @@ static virDriver libxlDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ NULL, /* nodeGetCellsFreeMemory */ libxlNodeGetFreeMemory, /* getFreeMemory */ libxlDomainEventRegister, /* domainEventRegister */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e905302..0e0c325 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2869,6 +2869,7 @@ static virDriver lxcDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + nodeGetCpuTime, /* nodeGetCpuTime */ nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ nodeGetFreeMemory, /* getFreeMemory */ lxcDomainEventRegister, /* domainEventRegister */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index fb30c37..7335c8d 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1617,6 +1617,7 @@ static virDriver openvzDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ NULL, /* nodeGetCellsFreeMemory */ NULL, /* getFreeMemory */ NULL, /* domainEventRegister */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 51f9ff6..839649f 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -4018,6 +4018,7 @@ static virDriver phypDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ NULL, /* nodeGetCellsFreeMemory */ NULL, /* getFreeMemory */ NULL, /* domainEventRegister */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index dd12dc8..20bf4eb 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6886,6 +6886,7 @@ static virDriver qemuDriver = { qemudDomainBlockPeek, /* domainBlockPeek */ qemudDomainMemoryPeek, /* domainMemoryPeek */ qemuDomainGetBlockInfo, /* domainGetBlockInfo */ + nodeGetCpuTime, /* nodeGetCpuTime */ nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ nodeGetFreeMemory, /* getFreeMemory */ qemuDomainEventRegister, /* domainEventRegister */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index bf94e70..2393055 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -11259,6 +11259,7 @@ static virDriver remote_driver = { remoteDomainBlockPeek, /* domainBlockPeek */ remoteDomainMemoryPeek, /* domainMemoryPeek */ remoteDomainGetBlockInfo, /* domainGetBlockInfo */ + remoteNodeGetCpuTime, /* nodeGetCpuTime */ remoteNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ remoteNodeGetFreeMemory, /* getFreeMemory */ remoteDomainEventRegister, /* domainEventRegister */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 17f5ad9..f122935 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5410,6 +5410,7 @@ static virDriver testDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ NULL, /* getFreeMemory */ testDomainEventRegister, /* domainEventRegister */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index e2bd5f2..93fb59e 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2212,6 +2212,7 @@ static virDriver umlDriver = { umlDomainBlockPeek, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + nodeGetCpuTime, /* nodeGetCpuTime */ nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ nodeGetFreeMemory, /* getFreeMemory */ NULL, /* domainEventRegister */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 8bd27dd..6f2d4fe 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8600,6 +8600,7 @@ virDriver NAME(Driver) = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ nodeGetFreeMemory, /* getFreeMemory */ #if VBOX_API_VERSION == 2002 || VBOX_API_VERSION == 4000 diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index b5e416b..635aa59 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -970,6 +970,7 @@ static virDriver vmwareDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ NULL, /* nodeGetCellsFreeMemory */ NULL, /* getFreeMemory */ NULL, /* domainEventRegister */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 9f47722..af18baa 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2104,6 +2104,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedDomainBlockPeek, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ xenUnifiedNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ xenUnifiedNodeGetFreeMemory, /* getFreeMemory */ xenUnifiedDomainEventRegister, /* domainEventRegister */ diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 27206a0..7800dd1 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1848,6 +1848,7 @@ static virDriver xenapiDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ xenapiNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ xenapiNodeGetFreeMemory, /* getFreeMemory */ NULL, /* domainEventRegister */ -- 1.7.1 -- Minoru Usui From usui at mxm.nes.nec.co.jp Fri Apr 1 01:57:24 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 1 Apr 2011 10:57:24 +0900 Subject: [libvirt] [PATCH 3/6] virNodeGetCpuTime: Implement public API In-Reply-To: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> Message-ID: <20110401105724.e88dd3a3.usui@mxm.nes.nec.co.jp> virNodeGetCpuTime: Implement public API --- src/libvirt.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 38 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 9bdb4c8..f3ef6ed 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -4260,6 +4260,44 @@ error: } /** + * virNodeGetCpuTime: + * @conn: pointer to the hypervisor connection + * + * provides the cumulative CPU time, when the Node booting up. + * Note: The CPU time used in nanoseconds. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virNodeGetCpuTime(virConnectPtr conn ATTRIBUTE_UNUSED, + virNodeCpuTimePtr cpu_time) +{ + VIR_DEBUG("conn=%p", conn); + + virResetLastError(); + + if (!VIR_IS_CONNECT (conn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return 0; + } + + if (conn->driver->nodeGetCpuTime) { + int ret; + ret = conn->driver->nodeGetCpuTime(conn, cpu_time); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return 0; +} + +/** * virNodeGetFreeMemory: * @conn: pointer to the hypervisor connection * -- 1.7.1 -- Minoru Usui From usui at mxm.nes.nec.co.jp Fri Apr 1 01:58:12 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 1 Apr 2011 10:58:12 +0900 Subject: [libvirt] [PATCH 4/6] virNodeGetCpuTime: Implement remote protocol In-Reply-To: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> Message-ID: <20110401105812.5498141f.usui@mxm.nes.nec.co.jp> virNodeGetCpuTime: Implement remote protocol --- daemon/remote.c | 23 +++++++++++++++++++++++ daemon/remote_dispatch_prototypes.h | 8 ++++++++ daemon/remote_dispatch_ret.h | 1 + daemon/remote_dispatch_table.h | 5 +++++ src/remote/remote_driver.c | 26 ++++++++++++++++++++++++++ src/remote/remote_protocol.c | 15 +++++++++++++++ src/remote/remote_protocol.h | 11 +++++++++++ src/remote/remote_protocol.x | 10 +++++++++- src/remote_protocol-structs | 6 ++++++ 9 files changed, 104 insertions(+), 1 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 1700c2d..64daad8 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -679,6 +679,29 @@ remoteDispatchGetCapabilities (struct qemud_server *server ATTRIBUTE_UNUSED, } static int +remoteDispatchNodeGetCpuTime (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_node_get_cpu_time_ret *ret) +{ + virNodeCpuTime cpu_time; + + if (virNodeGetCpuTime(conn, &cpu_time) == -1) { + remoteDispatchConnError(rerr, conn); + return -1; + } + ret->user = cpu_time.user; + ret->system = cpu_time.system; + ret->idle = cpu_time.idle; + ret->iowait = cpu_time.iowait; + + return 0; +} + +static int remoteDispatchNodeGetCellsFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 18bf41d..6cfe443 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -1138,6 +1138,14 @@ static int remoteDispatchNodeGetCellsFreeMemory( remote_error *err, remote_node_get_cells_free_memory_args *args, remote_node_get_cells_free_memory_ret *ret); +static int remoteDispatchNodeGetCpuTime( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + void *args, + remote_node_get_cpu_time_ret *ret); static int remoteDispatchNodeGetFreeMemory( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_ret.h b/daemon/remote_dispatch_ret.h index 114e832..dfed98b 100644 --- a/daemon/remote_dispatch_ret.h +++ b/daemon/remote_dispatch_ret.h @@ -140,3 +140,4 @@ remote_domain_is_updated_ret val_remote_domain_is_updated_ret; remote_get_sysinfo_ret val_remote_get_sysinfo_ret; remote_domain_get_blkio_parameters_ret val_remote_domain_get_blkio_parameters_ret; + remote_node_get_cpu_time_ret val_remote_node_get_cpu_time_ret; diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index b39f7c2..3e93d3e 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1052,3 +1052,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* NodeGetCpuTime => 210 */ + .fn = (dispatch_fn) remoteDispatchNodeGetCpuTime, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_node_get_cpu_time_ret, +}, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 2393055..aba68fd 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1934,6 +1934,32 @@ done: } static int +remoteNodeGetCpuTime (virConnectPtr conn, virNodeCpuTimePtr cpu_time) +{ + int rv = -1; + remote_node_get_cpu_time_ret ret; + struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); + + memset (&ret, 0, sizeof ret); + if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_CPU_TIME, + (xdrproc_t) xdr_void, (char *) NULL, + (xdrproc_t) xdr_remote_node_get_cpu_time_ret, (char *) &ret) == -1) + goto done; + + cpu_time->user = ret.user; + cpu_time->system = ret.system; + cpu_time->idle = ret.idle; + cpu_time->iowait = ret.iowait; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int remoteNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems, int startCell, diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 5604371..eb9c4b9 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -607,6 +607,21 @@ xdr_remote_get_capabilities_ret (XDR *xdrs, remote_get_capabilities_ret *objp) } bool_t +xdr_remote_node_get_cpu_time_ret (XDR *xdrs, remote_node_get_cpu_time_ret *objp) +{ + + if (!xdr_uint64_t (xdrs, &objp->user)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->system)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->idle)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->iowait)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_node_get_cells_free_memory_args (XDR *xdrs, remote_node_get_cells_free_memory_args *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index d9bf151..c17a03b 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -304,6 +304,14 @@ struct remote_get_capabilities_ret { }; typedef struct remote_get_capabilities_ret remote_get_capabilities_ret; +struct remote_node_get_cpu_time_ret { + uint64_t user; + uint64_t system; + uint64_t idle; + uint64_t iowait; +}; +typedef struct remote_node_get_cpu_time_ret remote_node_get_cpu_time_ret; + struct remote_node_get_cells_free_memory_args { int startCell; int maxCells; @@ -2413,6 +2421,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_NODE_GET_CPU_TIME = 210, }; typedef enum remote_procedure remote_procedure; @@ -2486,6 +2495,7 @@ extern bool_t xdr_remote_get_max_vcpus_args (XDR *, remote_get_max_vcpus_args*) extern bool_t xdr_remote_get_max_vcpus_ret (XDR *, remote_get_max_vcpus_ret*); extern bool_t xdr_remote_node_get_info_ret (XDR *, remote_node_get_info_ret*); extern bool_t xdr_remote_get_capabilities_ret (XDR *, remote_get_capabilities_ret*); +extern bool_t xdr_remote_node_get_cpu_time_ret (XDR *, remote_node_get_cpu_time_ret*); extern bool_t xdr_remote_node_get_cells_free_memory_args (XDR *, remote_node_get_cells_free_memory_args*); extern bool_t xdr_remote_node_get_cells_free_memory_ret (XDR *, remote_node_get_cells_free_memory_ret*); extern bool_t xdr_remote_node_get_free_memory_ret (XDR *, remote_node_get_free_memory_ret*); @@ -2843,6 +2853,7 @@ extern bool_t xdr_remote_get_max_vcpus_args (); extern bool_t xdr_remote_get_max_vcpus_ret (); extern bool_t xdr_remote_node_get_info_ret (); extern bool_t xdr_remote_get_capabilities_ret (); +extern bool_t xdr_remote_node_get_cpu_time_ret (); extern bool_t xdr_remote_node_get_cells_free_memory_args (); extern bool_t xdr_remote_node_get_cells_free_memory_ret (); extern bool_t xdr_remote_node_get_free_memory_ret (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 675eccd..a16a74a 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -440,6 +440,13 @@ struct remote_get_capabilities_ret { remote_nonnull_string capabilities; }; +struct remote_node_get_cpu_time_ret { + unsigned hyper user; + unsigned hyper system; + unsigned hyper idle; + unsigned hyper iowait; +}; + struct remote_node_get_cells_free_memory_args { int startCell; int maxCells; @@ -2176,7 +2183,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_NODE_GET_CPU_TIME = 210 /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 944553c..415132f 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -151,6 +151,12 @@ struct remote_node_get_info_ret { struct remote_get_capabilities_ret { remote_nonnull_string capabilities; }; +struct remote_node_get_cpu_time_ret { + uint64_t user; + uint64_t system; + uint64_t idle; + uint64_t iowait; +}; struct remote_node_get_cells_free_memory_args { int startCell; int maxCells; -- 1.7.1 -- Minoru Usui From usui at mxm.nes.nec.co.jp Fri Apr 1 01:58:48 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 1 Apr 2011 10:58:48 +0900 Subject: [libvirt] [PATCH 5/6] virNodeGetCpuTime: Implement virsh support In-Reply-To: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> Message-ID: <20110401105848.6438955c.usui@mxm.nes.nec.co.jp> virNodeGetCpuTime: Implement virsh support Add nodecputime subcommand to virsh. This subcommand prints below output. # ./virsh nodecputime user : 4280000000000.0s system: 13620000000000.0s idle : 1697380000000000.0s iowait: 76120000000000.0s # ./virsh nodecputime --percent user : 6.4% system: 3.2% idle : 89.6% iowait: 0.8 --- tools/virsh.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 6 +++++ 2 files changed, 72 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index faeaf47..5da35d8 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -3387,6 +3387,71 @@ cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } /* + * "nodecputime" command + */ +static const vshCmdInfo info_nodecputime[] = { + {"help", N_("Prints cpu time of the node.")}, + {"desc", N_("Returns user/system/idle/iowait time of the node.(nsec)")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_node_cpu_time[] = { + {"percent", VSH_OT_BOOL, 0, N_("prints by percentage during 1 second.")}, + {NULL, 0, 0, NULL} +}; + +#define NSEC_TO_SEC ((double)1.0 / 1000 * 1000 * 1000) +static int +cmdNodeCpuTime(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) +{ + virNodeCpuTime cpu_time[2]; + int percent = vshCommandOptBool(cmd, "percent"); + double user, sys, idle, iowait, total; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return FALSE; + + memset(&cpu_time, 0, sizeof(cpu_time)); + + if (virNodeGetCpuTime(ctl->conn, &cpu_time[0]) < 0) { + vshError(ctl, "%s", _("failed to get cpu time of the node.")); + return FALSE; + } + + if (!percent) { + vshPrint(ctl, "%-15s %.1lfs\n", _("user :"), + cpu_time[0].user * NSEC_TO_SEC); + vshPrint(ctl, "%-15s %.1lfs\n", _("system:"), + cpu_time[0].system * NSEC_TO_SEC); + vshPrint(ctl, "%-15s %.1lfs\n", _("idle :"), + cpu_time[0].idle * NSEC_TO_SEC); + vshPrint(ctl, "%-15s %.1lfs\n", _("iowait:"), + cpu_time[0].iowait * NSEC_TO_SEC); + return TRUE; + } + + sleep(1); + + if (virNodeGetCpuTime(ctl->conn, &cpu_time[1]) < 0) { + vshError(ctl, "%s", _("failed to get cpu time of the node.")); + return FALSE; + } + + user = cpu_time[1].user - cpu_time[0].user; + sys = cpu_time[1].system - cpu_time[0].system; + idle = cpu_time[1].idle - cpu_time[0].idle; + iowait = cpu_time[1].iowait - cpu_time[0].iowait; + total = user + sys + idle + iowait; + + vshPrint(ctl, "%-15s %5.1lf%%\n", _("user :"), user / total * 100); + vshPrint(ctl, "%-15s %5.1lf%%\n", _("system:"), sys / total * 100); + vshPrint(ctl, "%-15s %5.1lf%%\n", _("idle :"), idle / total * 100); + vshPrint(ctl, "%-15s %5.1lf%%\n", _("iowait:"), iowait / total * 100); + + return TRUE; +} + +/* * "capabilities" command */ static const vshCmdInfo info_capabilities[] = { @@ -10851,6 +10916,7 @@ static const vshCmdDef hostAndHypervisorCmds[] = { {"freecell", cmdFreecell, opts_freecell, info_freecell}, {"hostname", cmdHostname, NULL, info_hostname}, {"nodeinfo", cmdNodeinfo, NULL, info_nodeinfo}, + {"nodecputime", cmdNodeCpuTime, opts_node_cpu_time, info_nodecputime}, {"qemu-monitor-command", cmdQemuMonitorCommand, opts_qemu_monitor_command, info_qemu_monitor_command}, {"sysinfo", cmdSysinfo, NULL, info_sysinfo}, {"uri", cmdURI, NULL, info_uri}, diff --git a/tools/virsh.pod b/tools/virsh.pod index e882261..244b097 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -237,6 +237,12 @@ Print the XML representation of the hypervisor sysinfo, if available. Returns basic information about the node, like number and type of CPU, and size of the physical memory. +=item B optional I<--percent> + +Returns user/system/idle/iowait cpu time of the node, if I<--percent> +is specified this will prints percentage of each kind of cpu time +during 1 second. + =item B Print an XML document describing the capabilities of the hypervisor -- 1.7.1 -- Minoru Usui From usui at mxm.nes.nec.co.jp Fri Apr 1 01:59:27 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 1 Apr 2011 10:59:27 +0900 Subject: [libvirt] [PATCH 6/6] virNodeGetCpuTime: Implement linux support In-Reply-To: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> Message-ID: <20110401105927.b5a1e641.usui@mxm.nes.nec.co.jp> virNodeGetCpuTime: Implement linux support --- src/libvirt_private.syms | 1 + src/nodeinfo.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++ src/nodeinfo.h | 2 +- 3 files changed, 62 insertions(+), 1 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 65a86d3..b879454 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -651,6 +651,7 @@ virNodeDeviceObjUnlock; # nodeinfo.h nodeCapsInitNUMA; +nodeGetCpuTime; nodeGetCellsFreeMemory; nodeGetFreeMemory; nodeGetInfo; diff --git a/src/nodeinfo.c b/src/nodeinfo.c index 5d40aca..81222ec 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -57,12 +57,15 @@ #ifdef __linux__ # define CPUINFO_PATH "/proc/cpuinfo" # define CPU_SYS_PATH "/sys/devices/system/cpu" +# define PROCSTAT_PATH "/proc/stat" /* NB, this is not static as we need to call it from the testsuite */ int linuxNodeInfoCPUPopulate(FILE *cpuinfo, virNodeInfoPtr nodeinfo, bool need_hyperthreads); +int linuxNodeCpuTime(FILE *procstat, virNodeCpuTimePtr cpu_time); + /* Return the positive decimal contents of the given * CPU_SYS_PATH/cpu%u/FILE, or -1 on error. If MISSING_OK and the * file could not be found, return 1 instead of an error; this is @@ -322,6 +325,38 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo, return 0; } +#define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK)) + +int linuxNodeCpuTime(FILE *procstat, virNodeCpuTimePtr cpu_time) +{ + char line[1024]; + unsigned long long usr, ni, sys, idle, iowait; + unsigned long long irq, softirq, steal, guest, guest_nice;; + + memset(cpu_time, 0, sizeof(*cpu_time)); + while (fgets(line, sizeof(line), procstat) != NULL) { + char *buf = line; + + if (STRPREFIX(buf, "cpu ")) { /* aka total logical CPU time */ + if (sscanf(buf, + "%*s %llu %llu %llu %llu %llu" // user ~ iowait + "%llu %llu %llu %llu %llu", // irq ~ guest_nice + &usr, &ni, &sys, &idle, &iowait, + &irq, &softirq, &steal, &guest, &guest_nice) < 4) { + return -1; + } + cpu_time->user = (usr + ni) * TICK_TO_NSEC; + cpu_time->system = (sys + irq + softirq) * TICK_TO_NSEC; + cpu_time->idle = idle * TICK_TO_NSEC; + cpu_time->iowait = iowait * TICK_TO_NSEC; + + return 0; + } + } + + nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no \'cpu\' line found")); + return -1; +} #endif int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) { @@ -360,6 +395,31 @@ int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) { #endif } +int nodeGetCpuTime(virConnectPtr conn ATTRIBUTE_UNUSED, + virNodeCpuTimePtr cpu_time) +{ + +#ifdef __linux__ + { + int ret; + FILE *procstat = fopen(PROCSTAT_PATH, "r"); + if (!procstat) { + virReportSystemError(errno, + _("cannot open %s"), PROCSTAT_PATH); + return -1; + } + ret = linuxNodeCpuTime(procstat, cpu_time); + VIR_FORCE_FCLOSE(procstat); + + return ret; + } +#else + nodeReportError(VIR_ERR_NO_SUPPORT, "%s", + _("node CPU time not implemented on this platform")); + return -1; +#endif +} + #if HAVE_NUMACTL # if LIBNUMA_API_VERSION <= 1 # define NUMA_MAX_N_CPUS 4096 diff --git a/src/nodeinfo.h b/src/nodeinfo.h index 88bac6c..106e9c1 100644 --- a/src/nodeinfo.h +++ b/src/nodeinfo.h @@ -30,7 +30,7 @@ int nodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo); int nodeCapsInitNUMA(virCapsPtr caps); - +int nodeGetCpuTime(virConnectPtr conn, virNodeCpuTimePtr cpu_time); int nodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems, int startCell, -- 1.7.1 -- Minoru Usui From wency at cn.fujitsu.com Fri Apr 1 03:17:57 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Fri, 01 Apr 2011 11:17:57 +0800 Subject: [libvirt] [PATCH] free tmp after unlinking it In-Reply-To: <20110331104907.GF24425@redhat.com> References: <4D943A05.3040508@cn.fujitsu.com> <20110331104907.GF24425@redhat.com> Message-ID: <4D9543E5.5030509@cn.fujitsu.com> At 03/31/2011 06:49 PM, Daniel P. Berrange Write: > On Thu, Mar 31, 2011 at 04:23:33PM +0800, Wen Congyang wrote: >> --- >> src/qemu/qemu_driver.c | 2 +- >> 1 files changed, 1 insertions(+), 1 deletions(-) >> >> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c >> index dd12dc8..5aa715e 100644 >> --- a/src/qemu/qemu_driver.c >> +++ b/src/qemu/qemu_driver.c >> @@ -5065,9 +5065,9 @@ endjob: >> vm = NULL; >> >> cleanup: >> - VIR_FREE(tmp); >> VIR_FORCE_CLOSE(fd); >> unlink (tmp); >> + VIR_FREE(tmp); >> if (vm) >> virDomainObjUnlock(vm); >> return ret; > > ACK, but can you write a bit of a longer commit message > saying what area of code / method this is fixing, because > the diff context is not showing the method name. I added a commit message and pushed it. Thanks. > > Daniel From wency at cn.fujitsu.com Fri Apr 1 03:20:04 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Fri, 01 Apr 2011 11:20:04 +0800 Subject: [libvirt] [PATCH] free tmp after unlinking it In-Reply-To: <20110331091159.GE24385@redhat.com> References: <4D943A05.3040508@cn.fujitsu.com> <20110331091159.GE24385@redhat.com> Message-ID: <4D954464.2070102@cn.fujitsu.com> At 03/31/2011 05:11 PM, Daniel Veillard Write: > On Thu, Mar 31, 2011 at 04:23:33PM +0800, Wen Congyang wrote: >> --- >> src/qemu/qemu_driver.c | 2 +- >> 1 files changed, 1 insertions(+), 1 deletions(-) >> >> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c >> index dd12dc8..5aa715e 100644 >> --- a/src/qemu/qemu_driver.c >> +++ b/src/qemu/qemu_driver.c >> @@ -5065,9 +5065,9 @@ endjob: >> vm = NULL; >> >> cleanup: >> - VIR_FREE(tmp); >> VIR_FORCE_CLOSE(fd); >> unlink (tmp); >> + VIR_FREE(tmp); >> if (vm) >> virDomainObjUnlock(vm); >> return ret; > > Houla ! ACK !!! > BTW, how did you find this, code review, valgrind or something else ? I found this when I was checking all the place that calls qemuDomainObjExitMonitor() /qemuDomainObjExitMonitorWithDriver(). > > thanks, > > Daniel > From jyang at redhat.com Fri Apr 1 03:42:35 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 01 Apr 2011 11:42:35 +0800 Subject: [libvirt] [PATCH] qemu: Fix improper logic of qemuCgroupSetup In-Reply-To: <4D95050F.4060405@redhat.com> References: <1301457277-5635-1-git-send-email-jyang@redhat.com> <4D95050F.4060405@redhat.com> Message-ID: <4D9549AB.2040408@redhat.com> ? 2011?04?01? 06:49, Eric Blake ??: > On 03/29/2011 09:54 PM, Osier Yang wrote: >> It throws errors as long as the cgroup controller is not available, >> regardless of whether we really want to use it to do setup or not, >> which is not what we want, fixing it with throwing error when need >> to use the controller. >> >> And change "VIR_WARN" to "qemuReportError" for memory controller >> incidentally. >> >> --- >> src/qemu/qemu_cgroup.c | 78 +++++++++++++++++++++++++---------------------- >> 1 files changed, 41 insertions(+), 37 deletions(-) > > ACK. > Thanks, applied Osier From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 1 04:14:43 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 1 Apr 2011 13:14:43 +0900 Subject: [libvirt] [PATCHv8 0/4] libvirt/qemu - persistent modification of inactive domans. Message-ID: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> Hi, this is v8. This one implements a new method for rollback in domain changes in patch 2/4. And I dropped "verify new device is.." patch which was 4/4 in v7. Then, totarl numbers of patches are not changed. I'll add NIC support when this patch goes. 1/4 ..... a base patch for all devices. (not changed much) 2/4 ..... copy-sync-undo for synchronized update of domain definition. 3/4 ..... allow persistent addtion of disks to invalid domain. 4/4 ..... address conflic check. Thanks, -Kame From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 1 04:17:24 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 1 Apr 2011 13:17:24 +0900 Subject: [libvirt] [PATCHv8 1/4] libvirt/qemu - persistent modification of inactive domans. In-Reply-To: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> References: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110401131724.248d20fc.kamezawa.hiroyu@jp.fujitsu.com> >From 1ffbe73b1663719414367abbdebc8f31b9592331 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Thu, 31 Mar 2011 16:20:05 +0900 Subject: [PATCHv8 1/4] libvirt/qemu - persistent modification of devices. Now, qemudDomainAttachDeviceFlags() and qemudDomainDetachDeviceFlags() doesn't support VIR_DOMAIN_DEVICE_MODIFY_CONFIG. By this, virsh's at(de)tatch-device --persistent cannot modify qemu config. (Xen allows it.) This patch is a base patch for adding support of devices in step by step manner. Following patches will add some device support. Signed-off-by: KAMEZAWA Hiroyuki --- src/qemu/qemu_driver.c | 150 +++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 136 insertions(+), 14 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index dd12dc8..b89bc8f 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3873,16 +3873,133 @@ cleanup: return ret; } -static int qemudDomainAttachDeviceFlags(virDomainPtr dom, - const char *xml, - unsigned int flags) { - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); +/* + * At(de)tach a device given by XML, the change will be persistent + * and domain XML definition file is updated when these function + * returns 0(success). IOW, at failure, XML definition is never updated. + * So, this function must guarantee consistency between vmdef and its XML + * definition in the file. + */ + +static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef, + virDomainDeviceDefPtr newdev) +{ + + switch(newdev->type) { + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("the device is not supported for now")); return -1; } - return qemudDomainAttachDevice(dom, xml); + return 0; +} + +static int qemuDomainDetachDevicePersistent(virDomainDefPtr vmdef, + virDomainDeviceDefPtr device) +{ + switch(device->type) { + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("the device is not supported for now")); + return -1; + } + return 0; +} + +static int qemuDomainModifyDevicePersistent(virDomainPtr dom, + const char *xml, + unsigned int attach, + unsigned int flags) +{ + struct qemud_driver *driver; + virDomainDeviceDefPtr device; + virDomainDefPtr vmdef; + virDomainObjPtr vm; + int ret = -1; + + /* + * When both of MODIFY_CONFIG and MODIFY_LIVE are passed at the same time, + * return error for now. We should support this later. + */ + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify active domain and its definition " + "at the same time.")); + return -1; + } + + driver = dom->conn->privateData; + qemuDriverLock(driver); + vm = virDomainFindByName(&driver->domains, dom->name); + if (!vm) { + qemuReportError(VIR_ERR_NO_DOMAIN, _("no domain with name : '%s'"), + dom->name); + goto unlock_out; + } + + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + goto unlock_out; + + if (virDomainObjIsActive(vm)) { + /* + * For now, just allow updating inactive domains. Further development + * will allow updating both active domain and its config file at + * the same time. + */ + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify active domain's definition")); + goto endjob; + } + + vmdef = virDomainObjGetPersistentDef(driver->caps, vm); + + if (!vmdef) + goto endjob; + + device = virDomainDeviceDefParse(driver->caps, + vmdef, xml, VIR_DOMAIN_XML_INACTIVE); + if (!device) + goto endjob; + + if (attach) + ret = qemuDomainAttachDevicePersistent(vmdef, device); + else + ret = qemuDomainDetachDevicePersistent(vmdef, device); + /* + * At(De)tachDevicePersistent() must guarantee that vmdef is consistent + * with XML definition when they returns a failure, ret != 0. + */ + if (!ret) + ret = virDomainSaveConfig(driver->configDir, vmdef); + + virDomainDeviceDefFree(device); + +endjob: + if (qemuDomainObjEndJob(vm) == 0) + vm = NULL; +unlock_out: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); + return ret; +} + +static int qemudDomainAttachDeviceFlags(virDomainPtr dom, + const char *xml, + unsigned int flags) +{ + int ret = -1; + + virCheckFlags((VIR_DOMAIN_DEVICE_MODIFY_CONFIG | + VIR_DOMAIN_DEVICE_MODIFY_LIVE), -1); + + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) + ret = qemuDomainModifyDevicePersistent(dom, xml, 1, flags); + else if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) + ret = qemudDomainAttachDevice(dom, xml); + + return ret; } @@ -4096,14 +4213,19 @@ cleanup: static int qemudDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) { - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } + unsigned int flags) +{ + int ret = -1; + + virCheckFlags((VIR_DOMAIN_DEVICE_MODIFY_CONFIG | + VIR_DOMAIN_DEVICE_MODIFY_LIVE), -1); - return qemudDomainDetachDevice(dom, xml); + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) + ret = qemuDomainModifyDevicePersistent(dom, xml, 0, flags); + else if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) + ret = qemudDomainDetachDevice(dom, xml); + + return ret; } static int qemudDomainGetAutostart(virDomainPtr dom, -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 1 04:19:46 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 1 Apr 2011 13:19:46 +0900 Subject: [libvirt] [PATCHv8 2/4] libvirt/qemu - synchronous update of device definition In-Reply-To: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> References: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110401131946.04fe8785.kamezawa.hiroyu@jp.fujitsu.com> >From 229cfc90781bfd7024f79db1aed8bea5963757e3 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Thu, 31 Mar 2011 18:52:24 +0900 Subject: [PATCHv8 2/4] libvirt/qemu - synchronous update of device definition. At persistent modification of inactive domains, we go several steps as - insert disk to vmdef - assign pci address if necessary - assign controller if necessary - save it to file If failure happens in above sequence, that implies there is inconsistency between XML definition in file and vmdef cached in memory. So, it's better to have some rollback method. Implementing undo in each stage doesn't seem very neat, this patch implements a generic one. This patch adds 3 calls. virDomainTemporalCopyAlloc(vmdef) virDomainTemporalCopySync(orig, copy) virDomainTemporalCopyUndo(orig, copy) CopyAlloc() will create a copy of vmdef, CopySync() is for synchronizing copy and orginal, updating origina., CopyUndo() is for discarding for discarding unnecessary things in copy at failure. With these, vmdef modification can be done in following manner. copy = virDomainTemporalCopyAlloc(orig) ....do update on copy ....save updated data to its file if (error) virDomainTemporalCopyUndo(orig, copy); else virDomainTemporalCopySync(orig, copy) # this never fails. At failure of attach or success of detach, all stale devices in copy or orig will be freed automatically. Signed-off-by: KAMEZAWA Hiroyuki --- src/conf/domain_conf.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 5 + src/libvirt_private.syms | 3 + src/qemu/qemu_driver.c | 18 +++- 4 files changed, 230 insertions(+), 4 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b6aaf33..098face 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9368,3 +9368,211 @@ cleanup: return ret; } + +/* + * This function creates a copy of vmdef. The copied vmdef and + * original vmdef share their pointers other than arrays. + * The caller can make any changes to Copy, and later + * sync copy and original one, later. + * + * The caller must guarantee + * - vmdef is under a lock and no other one touches it. + * - never free pointers pointed by vmdef or copy before calling + * virDomainTemporalCopySync() or virDomainTemporalCopyUndo(). + * + * This function just handles 'generic' structure of virDomainDef. + * So, if some driver specific handling is required, you need another + * calls. See qemuDomainModifyDevicePersistent() for example. + */ + +static void virDomainTemporalCopyFree(virDomainDefPtr copy) +{ + VIR_FREE(copy->graphics); + VIR_FREE(copy->inputs); + VIR_FREE(copy->disks); + VIR_FREE(copy->controllers); + VIR_FREE(copy->fss); + VIR_FREE(copy->nets); + VIR_FREE(copy->smartcards); + VIR_FREE(copy->serials); + VIR_FREE(copy->parallels); + VIR_FREE(copy->channels); + VIR_FREE(copy->sounds); + VIR_FREE(copy->videos); + VIR_FREE(copy->hostdevs); + VIR_FREE(copy); +} + +#define DupArray(ptr, count, orig) do {\ + if (VIR_ALLOC_N((ptr), (count)) < 0) {\ + virReportOOMError();\ + goto oom_out;\ + }\ + memcpy((ptr), (orig), sizeof(*ptr) * (count));\ +} while (0) + +virDomainDefPtr virDomainTemporalCopyAlloc(virDomainDefPtr vmdef) +{ + virDomainDefPtr copy; + + if (VIR_ALLOC(copy) < 0) { + virReportOOMError(); + return NULL; + } + + memcpy(copy, vmdef, sizeof(*copy)); + + /* + * For now, this is used for modify devices. Further updates + * may be necessary for handle other components. + * At handling copy, array of disks,networks....can be + * replaced by realloc(). We need to allocate another array + * to avoid confusions. + */ + copy->graphics = NULL; + copy->inputs = NULL; + copy->disks = NULL; + copy->controllers = NULL; + copy->fss = NULL; + copy->nets = NULL; + copy->smartcards = NULL; + copy->serials = NULL; + copy->parallels = NULL; + copy->channels = NULL; + copy->sounds = NULL; + copy->videos = NULL; + copy->hostdevs = NULL; + + DupArray(copy->graphics, vmdef->ngraphics, vmdef->graphics); + DupArray(copy->inputs, vmdef->ninputs, vmdef->inputs); + DupArray(copy->disks, vmdef->ndisks, vmdef->disks); + DupArray(copy->controllers, vmdef->ncontrollers, vmdef->controllers); + DupArray(copy->fss, vmdef->nfss, vmdef->fss); + DupArray(copy->nets, vmdef->nnets, vmdef->nets); + DupArray(copy->smartcards, vmdef->nsmartcards, vmdef->smartcards); + DupArray(copy->serials, vmdef->nserials, vmdef->serials); + DupArray(copy->parallels, vmdef->nparallels, vmdef->parallels); + DupArray(copy->channels, vmdef->nchannels, vmdef->channels); + DupArray(copy->sounds, vmdef->nsounds, vmdef->sounds); + DupArray(copy->videos, vmdef->nvideos, vmdef->videos); + DupArray(copy->hostdevs, vmdef->nhostdevs, vmdef->hostdevs); + + /* + * After this, we can modify copy with usual routines. + */ + return copy; +oom_out: + virDomainTemporalCopyFree(copy); + return NULL; +} +#undef DupArray + + +/* + * Original anc copy has different arrays, but objects potinted by + * arrays are shared. At syncing, if an object is in orig but not in copy, + * free it. If an object is not in orig but in copy, copy it. + * At rollback, if an object is in copy but not in orig, free it. + */ + +/* use macro for avoiding warnings */ +#define SyncArray(orig, copy, member, num, func) do {\ + int i, j;\ + for (i = 0; i < orig->num; i++) {\ + for (j = 0; j < copy->num; j++) \ + if (orig->member[i] == copy->member[j])\ + break;\ + if (j == copy->num)\ + func(orig->member[i]);\ + }\ +} while (0); + +#define ReplaceArray(orig, copy, member, num) do {\ + VIR_FREE(orig->member);\ + orig->member = copy->member;\ + copy->member = NULL;\ + orig->num = copy->num;\ +} while (0); + +void virDomainTemporalCopySync(virDomainDefPtr orig, + virDomainDefPtr copy) +{ + SyncArray(orig, copy, graphics, ngraphics, virDomainGraphicsDefFree); + ReplaceArray(orig, copy, graphics, ngraphics); + + SyncArray(orig, copy, inputs, ninputs, virDomainInputDefFree); + ReplaceArray(orig, copy, inputs, ninputs); + + SyncArray(orig, copy, disks, ndisks, virDomainDiskDefFree); + ReplaceArray(orig, copy, disks, ndisks); + + SyncArray(orig, copy, controllers, + ncontrollers, virDomainControllerDefFree); + ReplaceArray(orig, copy, controllers, ncontrollers); + + SyncArray(orig, copy, fss, nfss, virDomainFSDefFree); + ReplaceArray(orig, copy, fss, nfss); + + SyncArray(orig, copy, nets, nnets, virDomainNetDefFree); + ReplaceArray(orig, copy, nets, nnets); + + SyncArray(orig, copy, smartcards, nsmartcards, virDomainSmartcardDefFree); + ReplaceArray(orig, copy, smartcards, nsmartcards); + + SyncArray(orig, copy, serials, nserials, virDomainChrDefFree); + ReplaceArray(orig, copy, serials, nserials); + + SyncArray(orig, copy, parallels, nparallels, virDomainChrDefFree); + ReplaceArray(orig, copy, parallels, nparallels); + + SyncArray(orig, copy, channels, nchannels, virDomainChrDefFree); + ReplaceArray(orig, copy, channels, nchannels); + + SyncArray(orig, copy, sounds, nsounds, virDomainSoundDefFree); + ReplaceArray(orig, copy, sounds, nsounds); + + SyncArray(orig, copy, videos, nvideos, virDomainVideoDefFree); + ReplaceArray(orig, copy, videos, nvideos); + + SyncArray(orig, copy, hostdevs, nhostdevs, virDomainHostdevDefFree); + ReplaceArray(orig, copy, hostdevs, nhostdevs); + + VIR_FREE(copy); +} +/* + * Free all devices exists only in the copy. + */ +void virDomainTemporalCopyUndo(virDomainDefPtr orig, + virDomainDefPtr copy) +{ + /* Free redundunt objects in the copied array */ + SyncArray(copy, orig, graphics, ngraphics, virDomainGraphicsDefFree); + + SyncArray(copy, orig, inputs, ninputs, virDomainInputDefFree); + + SyncArray(copy, orig, disks, ndisks, virDomainDiskDefFree); + + SyncArray(copy, orig, + controllers, ncontrollers, virDomainControllerDefFree); + SyncArray(copy, orig, fss, nfss, virDomainFSDefFree); + + SyncArray(copy, orig, nets, nnets, virDomainNetDefFree); + + SyncArray(copy, orig, smartcards, nsmartcards, virDomainSmartcardDefFree); + + SyncArray(copy, orig, serials, nserials, virDomainChrDefFree); + + SyncArray(copy, orig, parallels, nparallels, virDomainChrDefFree); + + SyncArray(copy, orig, channels, nchannels, virDomainChrDefFree); + + SyncArray(copy, orig, sounds, nsounds, virDomainSoundDefFree); + + SyncArray(copy, orig, videos, nvideos, virDomainVideoDefFree); + + SyncArray(copy, orig, hostdevs, nhostdevs, virDomainHostdevDefFree); + + virDomainTemporalCopyFree(copy); +} +#undef SyncArray +#undef ReplaceArray diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 10e73cb..28b3c0e 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1377,6 +1377,11 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk, virDomainDiskDefPathIterator iter, void *opaque); +virDomainDefPtr virDomainTemporalCopyAlloc(virDomainDefPtr vmdef); +void virDomainTemporalCopySync(virDomainDefPtr orig, + virDomainDefPtr copy); +void virDomainTemporalCopyUndo(virDomainDefPtr orig, virDomainDefPtr copy); + typedef const char* (*virLifecycleToStringFunc)(int type); typedef int (*virLifecycleFromStringFunc)(const char *type); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 65a86d3..62643d4 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -312,6 +312,9 @@ virDomainSoundModelTypeFromString; virDomainSoundModelTypeToString; virDomainStateTypeFromString; virDomainStateTypeToString; +virDomainTemporalCopyAlloc; +virDomainTemporalCopySync; +virDomainTemporalCopyUndo; virDomainTimerModeTypeFromString; virDomainTimerModeTypeToString; virDomainTimerNameTypeFromString; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b89bc8f..08055ef 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3914,7 +3914,7 @@ static int qemuDomainModifyDevicePersistent(virDomainPtr dom, { struct qemud_driver *driver; virDomainDeviceDefPtr device; - virDomainDefPtr vmdef; + virDomainDefPtr vmdef, copied; virDomainObjPtr vm; int ret = -1; @@ -3962,16 +3962,26 @@ static int qemuDomainModifyDevicePersistent(virDomainPtr dom, if (!device) goto endjob; + copied = virDomainTemporalCopyAlloc(vmdef); + if (!copied) + goto endjob; + if (attach) - ret = qemuDomainAttachDevicePersistent(vmdef, device); + ret = qemuDomainAttachDevicePersistent(copied, device); else - ret = qemuDomainDetachDevicePersistent(vmdef, device); + ret = qemuDomainDetachDevicePersistent(copied, device); /* * At(De)tachDevicePersistent() must guarantee that vmdef is consistent * with XML definition when they returns a failure, ret != 0. */ if (!ret) - ret = virDomainSaveConfig(driver->configDir, vmdef); + ret = virDomainSaveConfig(driver->configDir, copied); + + /* If successfully saved the new vmdef, sync it. this never fails */ + if (!ret) + virDomainTemporalCopySync(vmdef, copied); + else /* discard */ + virDomainTemporalCopyUndo(vmdef, copied); virDomainDeviceDefFree(device); -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 1 04:20:39 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 1 Apr 2011 13:20:39 +0900 Subject: [libvirt] [PATCHv8 3/4] libvirt/qemu - support persistent disk modification In-Reply-To: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> References: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110401132039.4feb88dc.kamezawa.hiroyu@jp.fujitsu.com> >From 96e42331674c9de4640422dd6f9e044319d9f700 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 1 Apr 2011 11:38:49 +0900 Subject: [PATCH 3/4] libvirt/qemu - support persistent disk modification support changes of disks by VIR_DOMAIN_DEVICE_MODIFY_CONFIG for qemu. Signed-off-by: KAMEZAWA Hiroyuki Changelog: v7->v8 - adjusted to use Copy/Sync/Undo mechanism. --- src/conf/domain_conf.c | 22 ++++++++++++++++++++++ src/conf/domain_conf.h | 2 ++ src/libvirt_private.syms | 2 ++ src/qemu/qemu_driver.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 0 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 098face..8948ab0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4877,6 +4877,19 @@ virVirtualPortProfileFormat(virBufferPtr buf, virBufferVSprintf(buf, "%s\n", indent); } +int virDomainDiskIndexByName(virDomainDefPtr def, const char *name) +{ + virDomainDiskDefPtr vdisk; + int i; + + for (i = 0; i < def->ndisks; i++) { + vdisk = def->disks[i]; + if (STREQ(vdisk->dst, name)) + return i; + } + return -1; +} + int virDomainDiskInsert(virDomainDefPtr def, virDomainDiskDefPtr disk) { @@ -4948,6 +4961,15 @@ void virDomainDiskRemove(virDomainDefPtr def, size_t i) } } +int virDomainDiskRemoveByName(virDomainDefPtr def, const char *name) +{ + int i = virDomainDiskIndexByName(def, name); + if (i < 0) + return -1; + virDomainDiskRemove(def, i); + return 0; +} + int virDomainControllerInsert(virDomainDefPtr def, virDomainControllerDefPtr controller) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 28b3c0e..fc46700 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1282,6 +1282,7 @@ int virDomainVcpupinAdd(virDomainDefPtr def, int maplen, int vcpu); +int virDomainDiskIndexByName(virDomainDefPtr def, const char *name); int virDomainDiskInsert(virDomainDefPtr def, virDomainDiskDefPtr disk); void virDomainDiskInsertPreAlloced(virDomainDefPtr def, @@ -1289,6 +1290,7 @@ void virDomainDiskInsertPreAlloced(virDomainDefPtr def, int virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def); void virDomainDiskRemove(virDomainDefPtr def, size_t i); +int virDomainDiskRemoveByName(virDomainDefPtr def, const char *name); int virDomainControllerInsert(virDomainDefPtr def, virDomainControllerDefPtr controller); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 62643d4..e8c5dce 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -245,11 +245,13 @@ virDomainDiskDefFree; virDomainDiskDeviceTypeToString; virDomainDiskErrorPolicyTypeFromString; virDomainDiskErrorPolicyTypeToString; +virDomainDiskIndexByName; virDomainDiskInsert; virDomainDiskInsertPreAlloced; virDomainDiskIoTypeFromString; virDomainDiskIoTypeToString; virDomainDiskRemove; +virDomainDiskRemoveByName; virDomainDiskTypeFromString; virDomainDiskTypeToString; virDomainFSDefFree; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 08055ef..eeaea0c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3884,8 +3884,28 @@ cleanup: static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef, virDomainDeviceDefPtr newdev) { + virDomainDiskDefPtr disk; switch(newdev->type) { + case VIR_DOMAIN_DEVICE_DISK: + disk = newdev->data.disk; + if (virDomainDiskIndexByName(vmdef, disk->dst) >= 0) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("target %s already exists."), disk->dst); + return -1; + } + if (virDomainDiskInsert(vmdef, disk)) { + virReportOOMError(); + return -1; + } + /* It's inserted. CopySync() or CopyUndo() will do all jobs */ + newdev->data.disk = NULL; + if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO) + if (virDomainDefAddImplicitControllers(vmdef) < 0) + return -1; + if (qemuDomainAssignPCIAddresses(vmdef) < 0) + return -1; + break; default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the device is not supported for now")); @@ -3898,7 +3918,17 @@ static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef, static int qemuDomainDetachDevicePersistent(virDomainDefPtr vmdef, virDomainDeviceDefPtr device) { + virDomainDiskDefPtr disk; + switch(device->type) { + case VIR_DOMAIN_DEVICE_DISK: + disk = device->data.disk; + if (virDomainDiskRemoveByName(vmdef, disk->dst)) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("no target device %s"), disk->dst); + return -1; + } + break; default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the device is not supported for now")); -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 1 04:22:03 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 1 Apr 2011 13:22:03 +0900 Subject: [libvirt] [PATCHv8 4/4] libvirt/qemu - check address conflict at attach In-Reply-To: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> References: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110401132203.daf52bdb.kamezawa.hiroyu@jp.fujitsu.com> >From a87f4804dcea2ede3a20bb3d647e291c4bd9a579 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Fri, 1 Apr 2011 11:59:32 +0900 Subject: [PATCH 4/4] libvirt/qemu - check address conflict at attach. qemuDomainAttachDevicePersistent() calls qemuDomainAssignPCIAddresses() and virDomainDefAddImplicitControllers() at the end of its call. But PCI/Drive address confliction checks are PCI - confliction will be found but error report is not verbose. Drive - never done. For example, when adding a device which has already used address. [Before Patch] error: Failed to attach device from /home/kamezawa/testc.xml error: An error occurred, but the cause is unknown [After Patch] error: Failed to attach device from /home/kamezawa/testc.xml error: invalid argument in device address conflict This error report is better. And this aslo checks devices other and PCI devides, which wasn't done. Signed-off-by: KAMEZAWA Hiroyuki Changelog v7->v8 - fixed error messages. - use STREQ. --- src/conf/domain_conf.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 2 + src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 3 ++ 4 files changed, 71 insertions(+), 0 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 8948ab0..032ad1e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1305,6 +1305,71 @@ void virDomainDefClearDeviceAliases(virDomainDefPtr def) virDomainDeviceInfoIterate(def, virDomainDeviceInfoClearAlias, NULL); } +static int virDomainDeviceAddressMatch(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, + void *opaque) +{ + virDomainDeviceInfoPtr checked = opaque; + /* skip to check confliction of alias */ + if (info->type != checked->type) + return 0; + if (info->alias && checked->alias && STREQ(info->alias, checked->alias)) + return -1; + /* addr is zero cleared before filled */ + if (!memcmp(&info->addr, &checked->addr, sizeof(info->addr))) + return -1; + return 0; +} + +int virDomainDefFindDeviceAddressConflict(virDomainDefPtr def, + virDomainDeviceDefPtr dev) +{ + virDomainDeviceInfoPtr checked; + int ret; + + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + checked = &dev->data.disk->info; + break; + case VIR_DOMAIN_DEVICE_FS: + checked = &dev->data.fs->info; + break; + case VIR_DOMAIN_DEVICE_NET: + checked = &dev->data.net->info; + break; + case VIR_DOMAIN_DEVICE_INPUT: + checked = &dev->data.input->info; + break; + case VIR_DOMAIN_DEVICE_SOUND: + checked = &dev->data.sound->info; + break; + case VIR_DOMAIN_DEVICE_VIDEO: + checked = &dev->data.video->info; + break; + case VIR_DOMAIN_DEVICE_HOSTDEV: + checked = &dev->data.hostdev->info; + break; + case VIR_DOMAIN_DEVICE_WATCHDOG: + checked = &dev->data.watchdog->info; + break; + case VIR_DOMAIN_DEVICE_CONTROLLER: + checked = &dev->data.controller->info; + break; + case VIR_DOMAIN_DEVICE_GRAPHICS: /* has no address info */ + return 0; + default: /* internal error */ + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Unknown device type")); + return -1; + } + if (checked->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) + return 0; + ret = virDomainDeviceInfoIterate(def, virDomainDeviceAddressMatch, checked); + if (ret) + virDomainReportError(VIR_ERR_INVALID_ARG, + "%s", _("device address conflict")); + return ret; +} /* Generate a string representation of a device address * @param address Device address to stringify diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index fc46700..1124e73 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1215,6 +1215,8 @@ int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info); void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info); void virDomainDefClearPCIAddresses(virDomainDefPtr def); void virDomainDefClearDeviceAliases(virDomainDefPtr def); +int virDomainDefFindDeviceAddressConflict(virDomainDefPtr def, + virDomainDeviceDefPtr dev); typedef int (*virDomainDeviceInfoCallback)(virDomainDefPtr def, virDomainDeviceInfoPtr dev, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e8c5dce..d539011 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -222,6 +222,7 @@ virDomainCpuSetParse; virDomainDefAddImplicitControllers; virDomainDefClearDeviceAliases; virDomainDefClearPCIAddresses; +virDomainDefFindDeviceAddressConflict; virDomainDefFormat; virDomainDefFree; virDomainDefParseFile; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index eeaea0c..4d4b7e6 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3886,6 +3886,9 @@ static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef, { virDomainDiskDefPtr disk; + if (virDomainDefFindDeviceAddressConflict(vmdef, newdev)) + return -1; + switch(newdev->type) { case VIR_DOMAIN_DEVICE_DISK: disk = newdev->data.disk; -- 1.7.4.1 From izumi.taku at jp.fujitsu.com Fri Apr 1 05:03:56 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Fri, 01 Apr 2011 14:03:56 +0900 Subject: [libvirt] [PATCH 2/4] vcpupin: implement the code to address the new API in the qemu driver In-Reply-To: <4D942E36.3060708@redhat.com> References: <4D94124A.1090808@jp.fujitsu.com> <4D94136C.80504@jp.fujitsu.com> <4D942E36.3060708@redhat.com> Message-ID: <4D955CBC.4060709@jp.fujitsu.com> Thank you for reviewing! >> + if ((flags& (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_MEM_CONFIG)) == 0) { > > s/VIR_DOMAIN_MEM_CONFIG/VIR_DOMAIN_VCPU_CONFIG/ Oops!. orz > This allows both "LIVE" and "CONFIG" are set, and you use two > "if" clauses later for both of them, ( > if (flags& VIR_DOMAIN_VCPU_CONFIG), and > if (flags& VIR_DOMAIN_VCPU_LIVE) ) so there should be problem. > > IMHO it should be: Exactly one of "LIVE" or "CONFIG" is set. I think "LIVE" and "CONIFG" can coexist, so it is allowed to set at the same time. Best regards, Taku Izumi From liyong at skybility.com Fri Apr 1 05:25:16 2011 From: liyong at skybility.com (Lyre) Date: Fri, 1 Apr 2011 13:25:16 +0800 Subject: [libvirt] [libvirt-php] Remove strip from installation Message-ID: <1301635516-30885-1-git-send-email-liyong@skybility.com> Make it able to generate debuginfo package. --- configure.ac | 1 - src/Makefile.am | 2 +- 2 files changed, 1 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 8149349..5ebe416 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,6 @@ AC_LANG([C]) AC_PROG_INSTALL AC_PROG_SED AC_PROG_AWK -AC_CHECK_TOOL([STRIP], [strip]) AC_CHECK_TOOL([ECHO], [echo]) AC_CHECK_TOOL([RM], [rm]) diff --git a/src/Makefile.am b/src/Makefile.am index edb5df4..76ebee6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,7 +13,7 @@ build: $(ECHO) "Extension compiled as $(PACKAGE).so" install-exec-local: - $(INSTALL) -m 644 -D --strip $(PACKAGE).so $(DESTDIR)$(PHPEDIR)/$(PACKAGE).so + $(INSTALL) -m 644 -D $(PACKAGE).so $(DESTDIR)$(PHPEDIR)/$(PACKAGE).so $(INSTALL) -m 755 -d $(DESTDIR)$(PHPCDIR) $(ECHO) "extension=$(PACKAGE).so" > $(DESTDIR)$(PHPCDIR)/libvirt-php.ini -- 1.7.3.4 ? From st.yeyo at hotmail.com Fri Apr 1 06:10:52 2011 From: st.yeyo at hotmail.com (SanitYey o) Date: Fri, 1 Apr 2011 14:10:52 +0800 Subject: [libvirt] How many functions that can't be used within libvirt Message-ID: Hello, I've tested some functions of libvirt don't work. Could some people give me a reasonable explanation about these functions? Why do these function don't work? Or if there is anything wrong of my understanding. 1.virsh # migrate 1 xen+ssh://root at 172.16.201.183/Password: error: POST operation failed: xend_post: error from xen daemon: (xend.err "can't connect: (-2, 'Name or service not known')") 2.virsh # dommemstat 5error: Failed to get memory statistics for domain 5error: this function is not supported by the hypervisor: virDomainMemoryStats 3.virsh # dump 5 fileerror: Failed to core dump domain 5 to fileerror: POST operation failed: xend_post: error from xen daemon: (xend.err 'Too many values for live') 4.virsh # iface-list error: Failed to list active interfaceserror: this function is not supported by the hypervisor: virConnectNumOfInterfaces 5.virsh # vncdisplay 5:1 virsh # vncdisplay 41:0 6.virsh # snapshot-create 42 snapshot.xml error: Failed to create snapshot snapshot.xml for domain 42 7.NWFILTER functions Thank you very much! -------------- next part -------------- An HTML attachment was scrubbed... URL: From wency at cn.fujitsu.com Fri Apr 1 06:10:18 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Fri, 01 Apr 2011 14:10:18 +0800 Subject: [libvirt] [PATCHv8 2/4] libvirt/qemu - synchronous update of device definition In-Reply-To: <20110401131946.04fe8785.kamezawa.hiroyu@jp.fujitsu.com> References: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> <20110401131946.04fe8785.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4D956C4A.8040806@cn.fujitsu.com> At 04/01/2011 12:19 PM, KAMEZAWA Hiroyuki Write: >>From 229cfc90781bfd7024f79db1aed8bea5963757e3 Mon Sep 17 00:00:00 2001 > From: KAMEZAWA Hiroyuki > Date: Thu, 31 Mar 2011 18:52:24 +0900 > Subject: [PATCHv8 2/4] libvirt/qemu - synchronous update of device definition. > > At persistent modification of inactive domains, we go several steps as > - insert disk to vmdef > - assign pci address if necessary > - assign controller if necessary > - save it to file Step 2 should be after step 3. > > If failure happens in above sequence, that implies there is inconsistency > between XML definition in file and vmdef cached in memory. So, it's better > to have some rollback method. Implementing undo in each stage doesn't seem > very neat, this patch implements a generic one. > > This patch adds 3 calls. > virDomainTemporalCopyAlloc(vmdef) > virDomainTemporalCopySync(orig, copy) > virDomainTemporalCopyUndo(orig, copy) > > CopyAlloc() will create a copy of vmdef, CopySync() is for synchronizing > copy and orginal, updating origina., CopyUndo() is for discarding for > discarding unnecessary things in copy at failure. With these, vmdef > modification can be done in following manner. > > copy = virDomainTemporalCopyAlloc(orig) > ....do update on copy > ....save updated data to its file > if (error) > virDomainTemporalCopyUndo(orig, copy); > else > virDomainTemporalCopySync(orig, copy) # this never fails. You only copy arrays in orig. How about copy all from orig to copy? And we can introduce a new API virDomainObjAssignPersistentDef() that is like the API virDomainObjAssignDef(). So vmdef modification can be done like this: copy = virDomainTemporalCopyAlloc(orig) ....do update on copy if (error) { virDomainDefFree(copy); } else { virDomainObjAssignPersistentDef(vm, copy) # this never fails. ....save updated data to its file } We can copy vmdef easily: 1. xml = virDomainDefFormat(def, VIR_DOMAIN_XML_WRITE_FLAGS) 2. newdef = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS) > > At failure of attach or success of detach, all stale devices in > copy or orig will be freed automatically. > > Signed-off-by: KAMEZAWA Hiroyuki > --- > src/conf/domain_conf.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++ > src/conf/domain_conf.h | 5 + > src/libvirt_private.syms | 3 + > src/qemu/qemu_driver.c | 18 +++- > 4 files changed, 230 insertions(+), 4 deletions(-) > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index b6aaf33..098face 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -9368,3 +9368,211 @@ cleanup: > > return ret; > } > + > +/* > + * This function creates a copy of vmdef. The copied vmdef and > + * original vmdef share their pointers other than arrays. > + * The caller can make any changes to Copy, and later > + * sync copy and original one, later. > + * > + * The caller must guarantee > + * - vmdef is under a lock and no other one touches it. > + * - never free pointers pointed by vmdef or copy before calling > + * virDomainTemporalCopySync() or virDomainTemporalCopyUndo(). > + * > + * This function just handles 'generic' structure of virDomainDef. > + * So, if some driver specific handling is required, you need another > + * calls. See qemuDomainModifyDevicePersistent() for example. > + */ > + > +static void virDomainTemporalCopyFree(virDomainDefPtr copy) > +{ > + VIR_FREE(copy->graphics); > + VIR_FREE(copy->inputs); > + VIR_FREE(copy->disks); > + VIR_FREE(copy->controllers); > + VIR_FREE(copy->fss); > + VIR_FREE(copy->nets); > + VIR_FREE(copy->smartcards); > + VIR_FREE(copy->serials); > + VIR_FREE(copy->parallels); > + VIR_FREE(copy->channels); > + VIR_FREE(copy->sounds); > + VIR_FREE(copy->videos); > + VIR_FREE(copy->hostdevs); > + VIR_FREE(copy); > +} > + > +#define DupArray(ptr, count, orig) do {\ > + if (VIR_ALLOC_N((ptr), (count)) < 0) {\ > + virReportOOMError();\ > + goto oom_out;\ > + }\ > + memcpy((ptr), (orig), sizeof(*ptr) * (count));\ > +} while (0) > + > +virDomainDefPtr virDomainTemporalCopyAlloc(virDomainDefPtr vmdef) > +{ > + virDomainDefPtr copy; > + > + if (VIR_ALLOC(copy) < 0) { > + virReportOOMError(); > + return NULL; > + } > + > + memcpy(copy, vmdef, sizeof(*copy)); > + > + /* > + * For now, this is used for modify devices. Further updates > + * may be necessary for handle other components. > + * At handling copy, array of disks,networks....can be > + * replaced by realloc(). We need to allocate another array > + * to avoid confusions. > + */ > + copy->graphics = NULL; > + copy->inputs = NULL; > + copy->disks = NULL; > + copy->controllers = NULL; > + copy->fss = NULL; > + copy->nets = NULL; > + copy->smartcards = NULL; > + copy->serials = NULL; > + copy->parallels = NULL; > + copy->channels = NULL; > + copy->sounds = NULL; > + copy->videos = NULL; > + copy->hostdevs = NULL; > + > + DupArray(copy->graphics, vmdef->ngraphics, vmdef->graphics); > + DupArray(copy->inputs, vmdef->ninputs, vmdef->inputs); > + DupArray(copy->disks, vmdef->ndisks, vmdef->disks); > + DupArray(copy->controllers, vmdef->ncontrollers, vmdef->controllers); > + DupArray(copy->fss, vmdef->nfss, vmdef->fss); > + DupArray(copy->nets, vmdef->nnets, vmdef->nets); > + DupArray(copy->smartcards, vmdef->nsmartcards, vmdef->smartcards); > + DupArray(copy->serials, vmdef->nserials, vmdef->serials); > + DupArray(copy->parallels, vmdef->nparallels, vmdef->parallels); > + DupArray(copy->channels, vmdef->nchannels, vmdef->channels); > + DupArray(copy->sounds, vmdef->nsounds, vmdef->sounds); > + DupArray(copy->videos, vmdef->nvideos, vmdef->videos); > + DupArray(copy->hostdevs, vmdef->nhostdevs, vmdef->hostdevs); > + > + /* > + * After this, we can modify copy with usual routines. > + */ > + return copy; > +oom_out: > + virDomainTemporalCopyFree(copy); > + return NULL; > +} > +#undef DupArray > + > + > +/* > + * Original anc copy has different arrays, but objects potinted by > + * arrays are shared. At syncing, if an object is in orig but not in copy, > + * free it. If an object is not in orig but in copy, copy it. > + * At rollback, if an object is in copy but not in orig, free it. > + */ > + > +/* use macro for avoiding warnings */ > +#define SyncArray(orig, copy, member, num, func) do {\ > + int i, j;\ > + for (i = 0; i < orig->num; i++) {\ > + for (j = 0; j < copy->num; j++) \ > + if (orig->member[i] == copy->member[j])\ > + break;\ > + if (j == copy->num)\ > + func(orig->member[i]);\ > + }\ > +} while (0); > + > +#define ReplaceArray(orig, copy, member, num) do {\ > + VIR_FREE(orig->member);\ > + orig->member = copy->member;\ > + copy->member = NULL;\ > + orig->num = copy->num;\ > +} while (0); > + > +void virDomainTemporalCopySync(virDomainDefPtr orig, > + virDomainDefPtr copy) > +{ > + SyncArray(orig, copy, graphics, ngraphics, virDomainGraphicsDefFree); > + ReplaceArray(orig, copy, graphics, ngraphics); > + > + SyncArray(orig, copy, inputs, ninputs, virDomainInputDefFree); > + ReplaceArray(orig, copy, inputs, ninputs); > + > + SyncArray(orig, copy, disks, ndisks, virDomainDiskDefFree); > + ReplaceArray(orig, copy, disks, ndisks); > + > + SyncArray(orig, copy, controllers, > + ncontrollers, virDomainControllerDefFree); > + ReplaceArray(orig, copy, controllers, ncontrollers); > + > + SyncArray(orig, copy, fss, nfss, virDomainFSDefFree); > + ReplaceArray(orig, copy, fss, nfss); > + > + SyncArray(orig, copy, nets, nnets, virDomainNetDefFree); > + ReplaceArray(orig, copy, nets, nnets); > + > + SyncArray(orig, copy, smartcards, nsmartcards, virDomainSmartcardDefFree); > + ReplaceArray(orig, copy, smartcards, nsmartcards); > + > + SyncArray(orig, copy, serials, nserials, virDomainChrDefFree); > + ReplaceArray(orig, copy, serials, nserials); > + > + SyncArray(orig, copy, parallels, nparallels, virDomainChrDefFree); > + ReplaceArray(orig, copy, parallels, nparallels); > + > + SyncArray(orig, copy, channels, nchannels, virDomainChrDefFree); > + ReplaceArray(orig, copy, channels, nchannels); > + > + SyncArray(orig, copy, sounds, nsounds, virDomainSoundDefFree); > + ReplaceArray(orig, copy, sounds, nsounds); > + > + SyncArray(orig, copy, videos, nvideos, virDomainVideoDefFree); > + ReplaceArray(orig, copy, videos, nvideos); > + > + SyncArray(orig, copy, hostdevs, nhostdevs, virDomainHostdevDefFree); > + ReplaceArray(orig, copy, hostdevs, nhostdevs); > + > + VIR_FREE(copy); > +} > +/* > + * Free all devices exists only in the copy. > + */ > +void virDomainTemporalCopyUndo(virDomainDefPtr orig, > + virDomainDefPtr copy) > +{ > + /* Free redundunt objects in the copied array */ > + SyncArray(copy, orig, graphics, ngraphics, virDomainGraphicsDefFree); > + > + SyncArray(copy, orig, inputs, ninputs, virDomainInputDefFree); > + > + SyncArray(copy, orig, disks, ndisks, virDomainDiskDefFree); > + > + SyncArray(copy, orig, > + controllers, ncontrollers, virDomainControllerDefFree); > + SyncArray(copy, orig, fss, nfss, virDomainFSDefFree); > + > + SyncArray(copy, orig, nets, nnets, virDomainNetDefFree); > + > + SyncArray(copy, orig, smartcards, nsmartcards, virDomainSmartcardDefFree); > + > + SyncArray(copy, orig, serials, nserials, virDomainChrDefFree); > + > + SyncArray(copy, orig, parallels, nparallels, virDomainChrDefFree); > + > + SyncArray(copy, orig, channels, nchannels, virDomainChrDefFree); > + > + SyncArray(copy, orig, sounds, nsounds, virDomainSoundDefFree); > + > + SyncArray(copy, orig, videos, nvideos, virDomainVideoDefFree); > + > + SyncArray(copy, orig, hostdevs, nhostdevs, virDomainHostdevDefFree); > + > + virDomainTemporalCopyFree(copy); > +} > +#undef SyncArray > +#undef ReplaceArray > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > index 10e73cb..28b3c0e 100644 > --- a/src/conf/domain_conf.h > +++ b/src/conf/domain_conf.h > @@ -1377,6 +1377,11 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk, > virDomainDiskDefPathIterator iter, > void *opaque); > > +virDomainDefPtr virDomainTemporalCopyAlloc(virDomainDefPtr vmdef); > +void virDomainTemporalCopySync(virDomainDefPtr orig, > + virDomainDefPtr copy); > +void virDomainTemporalCopyUndo(virDomainDefPtr orig, virDomainDefPtr copy); > + > typedef const char* (*virLifecycleToStringFunc)(int type); > typedef int (*virLifecycleFromStringFunc)(const char *type); > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 65a86d3..62643d4 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -312,6 +312,9 @@ virDomainSoundModelTypeFromString; > virDomainSoundModelTypeToString; > virDomainStateTypeFromString; > virDomainStateTypeToString; > +virDomainTemporalCopyAlloc; > +virDomainTemporalCopySync; > +virDomainTemporalCopyUndo; > virDomainTimerModeTypeFromString; > virDomainTimerModeTypeToString; > virDomainTimerNameTypeFromString; > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index b89bc8f..08055ef 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -3914,7 +3914,7 @@ static int qemuDomainModifyDevicePersistent(virDomainPtr dom, > { > struct qemud_driver *driver; > virDomainDeviceDefPtr device; > - virDomainDefPtr vmdef; > + virDomainDefPtr vmdef, copied; > virDomainObjPtr vm; > int ret = -1; > > @@ -3962,16 +3962,26 @@ static int qemuDomainModifyDevicePersistent(virDomainPtr dom, > if (!device) > goto endjob; > > + copied = virDomainTemporalCopyAlloc(vmdef); > + if (!copied) > + goto endjob; > + > if (attach) > - ret = qemuDomainAttachDevicePersistent(vmdef, device); > + ret = qemuDomainAttachDevicePersistent(copied, device); > else > - ret = qemuDomainDetachDevicePersistent(vmdef, device); > + ret = qemuDomainDetachDevicePersistent(copied, device); > /* > * At(De)tachDevicePersistent() must guarantee that vmdef is consistent > * with XML definition when they returns a failure, ret != 0. > */ > if (!ret) > - ret = virDomainSaveConfig(driver->configDir, vmdef); > + ret = virDomainSaveConfig(driver->configDir, copied); > + > + /* If successfully saved the new vmdef, sync it. this never fails */ > + if (!ret) > + virDomainTemporalCopySync(vmdef, copied); > + else /* discard */ > + virDomainTemporalCopyUndo(vmdef, copied); > > virDomainDeviceDefFree(device); > From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 1 06:16:49 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 1 Apr 2011 15:16:49 +0900 Subject: [libvirt] [PATCHv8 2/4] libvirt/qemu - synchronous update of device definition In-Reply-To: <4D956C4A.8040806@cn.fujitsu.com> References: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> <20110401131946.04fe8785.kamezawa.hiroyu@jp.fujitsu.com> <4D956C4A.8040806@cn.fujitsu.com> Message-ID: <20110401151649.3c305372.kamezawa.hiroyu@jp.fujitsu.com> On Fri, 01 Apr 2011 14:10:18 +0800 Wen Congyang wrote: > At 04/01/2011 12:19 PM, KAMEZAWA Hiroyuki Write: > >>From 229cfc90781bfd7024f79db1aed8bea5963757e3 Mon Sep 17 00:00:00 2001 > > From: KAMEZAWA Hiroyuki > > Date: Thu, 31 Mar 2011 18:52:24 +0900 > > Subject: [PATCHv8 2/4] libvirt/qemu - synchronous update of device definition. > > > > At persistent modification of inactive domains, we go several steps as > > - insert disk to vmdef > > - assign pci address if necessary > > - assign controller if necessary > > - save it to file > > Step 2 should be after step 3. > yes ;) > > > > If failure happens in above sequence, that implies there is inconsistency > > between XML definition in file and vmdef cached in memory. So, it's better > > to have some rollback method. Implementing undo in each stage doesn't seem > > very neat, this patch implements a generic one. > > > > This patch adds 3 calls. > > virDomainTemporalCopyAlloc(vmdef) > > virDomainTemporalCopySync(orig, copy) > > virDomainTemporalCopyUndo(orig, copy) > > > > CopyAlloc() will create a copy of vmdef, CopySync() is for synchronizing > > copy and orginal, updating origina., CopyUndo() is for discarding for > > discarding unnecessary things in copy at failure. With these, vmdef > > modification can be done in following manner. > > > > copy = virDomainTemporalCopyAlloc(orig) > > ....do update on copy > > ....save updated data to its file > > if (error) > > virDomainTemporalCopyUndo(orig, copy); > > else > > virDomainTemporalCopySync(orig, copy) # this never fails. > > You only copy arrays in orig. How about copy all from orig to copy? > And we can introduce a new API virDomainObjAssignPersistentDef() that is > like the API virDomainObjAssignDef(). > > So vmdef modification can be done like this: > copy = virDomainTemporalCopyAlloc(orig) > ....do update on copy > if (error) { > virDomainDefFree(copy); > } else { > virDomainObjAssignPersistentDef(vm, copy) # this never fails. > ....save updated data to its file > } > > We can copy vmdef easily: > 1. xml = virDomainDefFormat(def, VIR_DOMAIN_XML_WRITE_FLAGS) > 2. newdef = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS) > Hmm, could you explain virDomainObjAssignPersistentDef() ? I think I should finally support moficication of active domains. Can I replace the whole vmdef of active domain ? Thanks, -Kame From wency at cn.fujitsu.com Fri Apr 1 06:33:23 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Fri, 01 Apr 2011 14:33:23 +0800 Subject: [libvirt] [PATCHv8 2/4] libvirt/qemu - synchronous update of device definition In-Reply-To: <20110401151649.3c305372.kamezawa.hiroyu@jp.fujitsu.com> References: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> <20110401131946.04fe8785.kamezawa.hiroyu@jp.fujitsu.com> <4D956C4A.8040806@cn.fujitsu.com> <20110401151649.3c305372.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4D9571B3.1000103@cn.fujitsu.com> At 04/01/2011 02:16 PM, KAMEZAWA Hiroyuki Write: > On Fri, 01 Apr 2011 14:10:18 +0800 > Wen Congyang wrote: > >> At 04/01/2011 12:19 PM, KAMEZAWA Hiroyuki Write: >>> >From 229cfc90781bfd7024f79db1aed8bea5963757e3 Mon Sep 17 00:00:00 2001 >>> From: KAMEZAWA Hiroyuki >>> Date: Thu, 31 Mar 2011 18:52:24 +0900 >>> Subject: [PATCHv8 2/4] libvirt/qemu - synchronous update of device definition. >>> >>> At persistent modification of inactive domains, we go several steps as >>> - insert disk to vmdef >>> - assign pci address if necessary >>> - assign controller if necessary >>> - save it to file >> >> Step 2 should be after step 3. >> > yes ;) > >>> >>> If failure happens in above sequence, that implies there is inconsistency >>> between XML definition in file and vmdef cached in memory. So, it's better >>> to have some rollback method. Implementing undo in each stage doesn't seem >>> very neat, this patch implements a generic one. >>> >>> This patch adds 3 calls. >>> virDomainTemporalCopyAlloc(vmdef) >>> virDomainTemporalCopySync(orig, copy) >>> virDomainTemporalCopyUndo(orig, copy) >>> >>> CopyAlloc() will create a copy of vmdef, CopySync() is for synchronizing >>> copy and orginal, updating origina., CopyUndo() is for discarding for >>> discarding unnecessary things in copy at failure. With these, vmdef >>> modification can be done in following manner. >>> >>> copy = virDomainTemporalCopyAlloc(orig) >>> ....do update on copy >>> ....save updated data to its file >>> if (error) >>> virDomainTemporalCopyUndo(orig, copy); >>> else >>> virDomainTemporalCopySync(orig, copy) # this never fails. >> >> You only copy arrays in orig. How about copy all from orig to copy? >> And we can introduce a new API virDomainObjAssignPersistentDef() that is >> like the API virDomainObjAssignDef(). >> >> So vmdef modification can be done like this: >> copy = virDomainTemporalCopyAlloc(orig) >> ....do update on copy >> if (error) { >> virDomainDefFree(copy); >> } else { >> virDomainObjAssignPersistentDef(vm, copy) # this never fails. >> ....save updated data to its file >> } >> >> We can copy vmdef easily: >> 1. xml = virDomainDefFormat(def, VIR_DOMAIN_XML_WRITE_FLAGS) >> 2. newdef = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS) >> > > Hmm, could you explain virDomainObjAssignPersistentDef() ? > > I think I should finally support moficication of active domains. > Can I replace the whole vmdef of active domain ? I found that virDomainObjAssignDef() can work. We can call it like this: virDomainObjAssignDef(vm, copy, false). We modify vm->newdef if domain is active, and modify vm->def if domain is inactive. > > Thanks, > -Kame > > > From jdenemar at redhat.com Fri Apr 1 06:53:42 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Fri, 1 Apr 2011 08:53:42 +0200 Subject: [libvirt] [PATCH v2] qemu: Ignore libvirt debug messages in qemu log In-Reply-To: <4D949883.6080805@redhat.com> References: <8e020f0c773ca0252fc65b4f3b4a4abf604335b3.1301560340.git.jdenemar@redhat.com> <4D949883.6080805@redhat.com> Message-ID: <20110401065342.GB389283@orkuz.home> On Thu, Mar 31, 2011 at 09:06:43 -0600, Eric Blake wrote: > On 03/31/2011 02:40 AM, Jiri Denemark wrote: > > qemu driver uses a 4K buffer for reading qemu log file. This is enough > > when only qemu's output is present in the log file. However, when > > debugging messages are turned on, intermediate libvirt process fills the > > log with a bunch of debugging messages before it executes qemu binary. > > In such a case the buffer may become too small. However, we are not > > really interested in libvirt messages so they can be filtered out from > > the buffer. > > --- > > Notes: > > Version 2: > > - add a comment to virLogFormatString() that this new code relies on the log > > message format > > - temporarily replace '\n' with '\0' to provide a bound for strstr() > > Looks nice, and your arguments about worrying about any further > optimizations being premature were valid. > > ACK. Thanks, I pushed the patch. Jirka From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 1 07:00:06 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 1 Apr 2011 16:00:06 +0900 Subject: [libvirt] [PATCHv8 2/4] libvirt/qemu - synchronous update of device definition In-Reply-To: <4D9571B3.1000103@cn.fujitsu.com> References: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> <20110401131946.04fe8785.kamezawa.hiroyu@jp.fujitsu.com> <4D956C4A.8040806@cn.fujitsu.com> <20110401151649.3c305372.kamezawa.hiroyu@jp.fujitsu.com> <4D9571B3.1000103@cn.fujitsu.com> Message-ID: <20110401160006.11fbd86d.kamezawa.hiroyu@jp.fujitsu.com> On Fri, 01 Apr 2011 14:33:23 +0800 Wen Congyang wrote: > I found that virDomainObjAssignDef() can work. We can call it like this: > virDomainObjAssignDef(vm, copy, false). > > We modify vm->newdef if domain is active, and modify vm->def if domain is inactive. > Okay, here is a replacement. it seems to work fine. Patch 3 and 4 can be applied without hunk. == >From b743fc6a0a449efa738638e165b139afab91439f Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Fri, 1 Apr 2011 16:02:31 +0900 Subject: [PATCH 2/2] libvirt/qemu - rollback for persistent modification. At persistent modification of inactive domains, we go several steps as - insert disk to vmdef - assign controller if necessary - assign pci address if necessary - save it to file If failure happens in above sequence, that implies there is inconsistency between XML definition in file and vmdef cached in memory. So, it's better to have some rollback method. Implementing undo in each stage doesn't seem very neat, this patch implements a generic one. This patch adds virDomainObjCopyPersistentDef(). This will create a copy of persistent def. The caller update this and later replace current one as: copy = virDomainObjCopyPersistentDef() .....update.... if (error) virDomainObjAssignDef(dom, copy); else virDomainDefFree(copy). Signed-off-by: KAMEZAWA Hiroyuki --- src/conf/domain_conf.c | 18 ++++++++++++++++++ src/conf/domain_conf.h | 3 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 8 +++++++- 4 files changed, 29 insertions(+), 1 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b6aaf33..31641f1 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9368,3 +9368,21 @@ cleanup: return ret; } + +virDomainDefPtr +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom) +{ + char *xml; + virDomainDefPtr cur, ret; + + cur = virDomainObjGetPersistentDef(caps, dom); + + xml = virDomainDefFormat(cur, VIR_DOMAIN_XML_WRITE_FLAGS); + if (!xml) + return NULL; + + ret = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS); + + VIR_FREE(xml); + return ret; +} diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 10e73cb..20bb4ed 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1377,6 +1377,9 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk, virDomainDiskDefPathIterator iter, void *opaque); +virDomainDefPtr +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom); + typedef const char* (*virLifecycleToStringFunc)(int type); typedef int (*virLifecycleFromStringFunc)(const char *type); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 65a86d3..ec69967 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -278,6 +278,7 @@ virDomainMemballoonModelTypeToString; virDomainNetDefFree; virDomainNetTypeToString; virDomainObjAssignDef; +virDomainObjCopyPersistentDef; virDomainObjSetDefTransient; virDomainObjGetPersistentDef; virDomainObjIsDuplicate; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b89bc8f..96c4df2 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3952,7 +3952,7 @@ static int qemuDomainModifyDevicePersistent(virDomainPtr dom, goto endjob; } - vmdef = virDomainObjGetPersistentDef(driver->caps, vm); + vmdef = virDomainObjCopyPersistentDef(driver->caps, vm); if (!vmdef) goto endjob; @@ -3973,6 +3973,12 @@ static int qemuDomainModifyDevicePersistent(virDomainPtr dom, if (!ret) ret = virDomainSaveConfig(driver->configDir, vmdef); + /* If successfully saved the new vmdef, update it. this never fails */ + if (!ret) + virDomainObjAssignDef(vm, vmdef, false); + else /* discard */ + virDomainDefFree(vmdef); + virDomainDeviceDefFree(device); endjob: -- 1.7.4.1 From jclift at redhat.com Fri Apr 1 07:14:00 2011 From: jclift at redhat.com (Justin Clift) Date: Fri, 1 Apr 2011 18:14:00 +1100 Subject: [libvirt] Libvirt potentially in GSoC 2011 through CERN Message-ID: Hi all, Just came across this interesting Google Summer of Code 2011 potential at CERN, where they specifically mention libvirt improvements in more than one project: http://cernvm.cern.ch/portal/gsoc11 Nifty eh? :) Regards and best wishes, Justin Clift From wency at cn.fujitsu.com Fri Apr 1 07:30:13 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Fri, 01 Apr 2011 15:30:13 +0800 Subject: [libvirt] [PATCHv8 1/4] libvirt/qemu - persistent modification of inactive domans. In-Reply-To: <20110401131724.248d20fc.kamezawa.hiroyu@jp.fujitsu.com> References: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> <20110401131724.248d20fc.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4D957F05.5070404@cn.fujitsu.com> At 04/01/2011 12:17 PM, KAMEZAWA Hiroyuki Write: >>From 1ffbe73b1663719414367abbdebc8f31b9592331 Mon Sep 17 00:00:00 2001 > From: KAMEZAWA Hiroyuki > Date: Thu, 31 Mar 2011 16:20:05 +0900 > Subject: [PATCHv8 1/4] libvirt/qemu - persistent modification of devices. > > Now, qemudDomainAttachDeviceFlags() and qemudDomainDetachDeviceFlags() > doesn't support VIR_DOMAIN_DEVICE_MODIFY_CONFIG. By this, virsh's > at(de)tatch-device --persistent cannot modify qemu config. > (Xen allows it.) > > This patch is a base patch for adding support of devices in > step by step manner. Following patches will add some device > support. > > Signed-off-by: KAMEZAWA Hiroyuki > > --- > src/qemu/qemu_driver.c | 150 +++++++++++++++++++++++++++++++++++++++++++----- > 1 files changed, 136 insertions(+), 14 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index dd12dc8..b89bc8f 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -3873,16 +3873,133 @@ cleanup: > return ret; > } > > -static int qemudDomainAttachDeviceFlags(virDomainPtr dom, > - const char *xml, > - unsigned int flags) { > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > - qemuReportError(VIR_ERR_OPERATION_INVALID, > - "%s", _("cannot modify the persistent configuration of a domain")); > +/* > + * At(de)tach a device given by XML, the change will be persistent > + * and domain XML definition file is updated when these function > + * returns 0(success). IOW, at failure, XML definition is never updated. > + * So, this function must guarantee consistency between vmdef and its XML > + * definition in the file. > + */ > + > +static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef, > + virDomainDeviceDefPtr newdev) > +{ > + > + switch(newdev->type) { > + default: > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("the device is not supported for now")); > return -1; > } > > - return qemudDomainAttachDevice(dom, xml); > + return 0; > +} > + > +static int qemuDomainDetachDevicePersistent(virDomainDefPtr vmdef, > + virDomainDeviceDefPtr device) > +{ > + switch(device->type) { > + default: > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("the device is not supported for now")); > + return -1; > + } > + return 0; > +} > + > +static int qemuDomainModifyDevicePersistent(virDomainPtr dom, > + const char *xml, > + unsigned int attach, > + unsigned int flags) > +{ > + struct qemud_driver *driver; > + virDomainDeviceDefPtr device; > + virDomainDefPtr vmdef; > + virDomainObjPtr vm; > + int ret = -1; > + > + /* > + * When both of MODIFY_CONFIG and MODIFY_LIVE are passed at the same time, > + * return error for now. We should support this later. > + */ > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { > + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", > + _("cannot modify active domain and its definition " > + "at the same time.")); > + return -1; > + } > + > + driver = dom->conn->privateData; > + qemuDriverLock(driver); > + vm = virDomainFindByName(&driver->domains, dom->name); > + if (!vm) { > + qemuReportError(VIR_ERR_NO_DOMAIN, _("no domain with name : '%s'"), > + dom->name); > + goto unlock_out; > + } > + > + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) > + goto unlock_out; > + > + if (virDomainObjIsActive(vm)) { > + /* > + * For now, just allow updating inactive domains. Further development > + * will allow updating both active domain and its config file at > + * the same time. > + */ > + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", > + _("cannot modify active domain's definition")); > + goto endjob; > + } > + > + vmdef = virDomainObjGetPersistentDef(driver->caps, vm); > + > + if (!vmdef) > + goto endjob; > + > + device = virDomainDeviceDefParse(driver->caps, > + vmdef, xml, VIR_DOMAIN_XML_INACTIVE); > + if (!device) > + goto endjob; > + > + if (attach) > + ret = qemuDomainAttachDevicePersistent(vmdef, device); > + else > + ret = qemuDomainDetachDevicePersistent(vmdef, device); > + /* > + * At(De)tachDevicePersistent() must guarantee that vmdef is consistent > + * with XML definition when they returns a failure, ret != 0. > + */ This comment can be removed in patch 2 as we use a copy of XML definition. > + if (!ret) > + ret = virDomainSaveConfig(driver->configDir, vmdef); > + > + virDomainDeviceDefFree(device); > + > +endjob: > + if (qemuDomainObjEndJob(vm) == 0) > + vm = NULL; > +unlock_out: > + if (vm) > + virDomainObjUnlock(vm); > + qemuDriverUnlock(driver); > + return ret; > +} > + > +static int qemudDomainAttachDeviceFlags(virDomainPtr dom, > + const char *xml, > + unsigned int flags) > +{ > + int ret = -1; > + > + virCheckFlags((VIR_DOMAIN_DEVICE_MODIFY_CONFIG | > + VIR_DOMAIN_DEVICE_MODIFY_LIVE), -1); > + > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) > + ret = qemuDomainModifyDevicePersistent(dom, xml, 1, flags); > + else if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) > + ret = qemudDomainAttachDevice(dom, xml); > + > + return ret; > } > > > @@ -4096,14 +4213,19 @@ cleanup: > > static int qemudDomainDetachDeviceFlags(virDomainPtr dom, > const char *xml, > - unsigned int flags) { > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > - qemuReportError(VIR_ERR_OPERATION_INVALID, > - "%s", _("cannot modify the persistent configuration of a domain")); > - return -1; > - } > + unsigned int flags) > +{ > + int ret = -1; > + > + virCheckFlags((VIR_DOMAIN_DEVICE_MODIFY_CONFIG | > + VIR_DOMAIN_DEVICE_MODIFY_LIVE), -1); > > - return qemudDomainDetachDevice(dom, xml); > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) > + ret = qemuDomainModifyDevicePersistent(dom, xml, 0, flags); > + else if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) > + ret = qemudDomainDetachDevice(dom, xml); > + > + return ret; > } > > static int qemudDomainGetAutostart(virDomainPtr dom, From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 1 07:29:32 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 1 Apr 2011 16:29:32 +0900 Subject: [libvirt] [PATCHv8 1/4] libvirt/qemu - persistent modification of inactive domans. In-Reply-To: <4D957F05.5070404@cn.fujitsu.com> References: <20110401131443.7e45c41f.kamezawa.hiroyu@jp.fujitsu.com> <20110401131724.248d20fc.kamezawa.hiroyu@jp.fujitsu.com> <4D957F05.5070404@cn.fujitsu.com> Message-ID: <20110401162932.d5ba03b3.kamezawa.hiroyu@jp.fujitsu.com> On Fri, 01 Apr 2011 15:30:13 +0800 Wen Congyang wrote: > At 04/01/2011 12:17 PM, KAMEZAWA Hiroyuki Write: > >>From 1ffbe73b1663719414367abbdebc8f31b9592331 Mon Sep 17 00:00:00 2001 > > From: KAMEZAWA Hiroyuki > > Date: Thu, 31 Mar 2011 16:20:05 +0900 > > Subject: [PATCHv8 1/4] libvirt/qemu - persistent modification of devices. > > > > Now, qemudDomainAttachDeviceFlags() and qemudDomainDetachDeviceFlags() > > doesn't support VIR_DOMAIN_DEVICE_MODIFY_CONFIG. By this, virsh's > > at(de)tatch-device --persistent cannot modify qemu config. > > (Xen allows it.) > > > > This patch is a base patch for adding support of devices in > > step by step manner. Following patches will add some device > > support. > > > > Signed-off-by: KAMEZAWA Hiroyuki > > > > --- > > src/qemu/qemu_driver.c | 150 +++++++++++++++++++++++++++++++++++++++++++----- > > 1 files changed, 136 insertions(+), 14 deletions(-) > > > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > > index dd12dc8..b89bc8f 100644 > > --- a/src/qemu/qemu_driver.c > > +++ b/src/qemu/qemu_driver.c > > @@ -3873,16 +3873,133 @@ cleanup: > > return ret; > > } > > > > -static int qemudDomainAttachDeviceFlags(virDomainPtr dom, > > - const char *xml, > > - unsigned int flags) { > > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > > - qemuReportError(VIR_ERR_OPERATION_INVALID, > > - "%s", _("cannot modify the persistent configuration of a domain")); > > +/* > > + * At(de)tach a device given by XML, the change will be persistent > > + * and domain XML definition file is updated when these function > > + * returns 0(success). IOW, at failure, XML definition is never updated. > > + * So, this function must guarantee consistency between vmdef and its XML > > + * definition in the file. > > + */ > > + > > +static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef, > > + virDomainDeviceDefPtr newdev) > > +{ > > + > > + switch(newdev->type) { > > + default: > > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > > + _("the device is not supported for now")); > > return -1; > > } > > > > - return qemudDomainAttachDevice(dom, xml); > > + return 0; > > +} > > + > > +static int qemuDomainDetachDevicePersistent(virDomainDefPtr vmdef, > > + virDomainDeviceDefPtr device) > > +{ > > + switch(device->type) { > > + default: > > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > > + _("the device is not supported for now")); > > + return -1; > > + } > > + return 0; > > +} > > + > > +static int qemuDomainModifyDevicePersistent(virDomainPtr dom, > > + const char *xml, > > + unsigned int attach, > > + unsigned int flags) > > +{ > > + struct qemud_driver *driver; > > + virDomainDeviceDefPtr device; > > + virDomainDefPtr vmdef; > > + virDomainObjPtr vm; > > + int ret = -1; > > + > > + /* > > + * When both of MODIFY_CONFIG and MODIFY_LIVE are passed at the same time, > > + * return error for now. We should support this later. > > + */ > > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { > > + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", > > + _("cannot modify active domain and its definition " > > + "at the same time.")); > > + return -1; > > + } > > + > > + driver = dom->conn->privateData; > > + qemuDriverLock(driver); > > + vm = virDomainFindByName(&driver->domains, dom->name); > > + if (!vm) { > > + qemuReportError(VIR_ERR_NO_DOMAIN, _("no domain with name : '%s'"), > > + dom->name); > > + goto unlock_out; > > + } > > + > > + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) > > + goto unlock_out; > > + > > + if (virDomainObjIsActive(vm)) { > > + /* > > + * For now, just allow updating inactive domains. Further development > > + * will allow updating both active domain and its config file at > > + * the same time. > > + */ > > + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", > > + _("cannot modify active domain's definition")); > > + goto endjob; > > + } > > + > > + vmdef = virDomainObjGetPersistentDef(driver->caps, vm); > > + > > + if (!vmdef) > > + goto endjob; > > + > > + device = virDomainDeviceDefParse(driver->caps, > > + vmdef, xml, VIR_DOMAIN_XML_INACTIVE); > > + if (!device) > > + goto endjob; > > + > > + if (attach) > > + ret = qemuDomainAttachDevicePersistent(vmdef, device); > > + else > > + ret = qemuDomainDetachDevicePersistent(vmdef, device); > > + /* > > + * At(De)tachDevicePersistent() must guarantee that vmdef is consistent > > + * with XML definition when they returns a failure, ret != 0. > > + */ > > This comment can be removed in patch 2 as we use a copy of XML definition. > Hmm, will do when I'll be back. I'll stop update for a week. Thanks, -Kame From minovotn at redhat.com Fri Apr 1 08:33:56 2011 From: minovotn at redhat.com (Michal Novotny) Date: Fri, 01 Apr 2011 10:33:56 +0200 Subject: [libvirt] [libvirt-php] Remove strip from installation In-Reply-To: <1301635516-30885-1-git-send-email-liyong@skybility.com> References: <1301635516-30885-1-git-send-email-liyong@skybility.com> Message-ID: <4D958DF4.4090206@redhat.com> On 04/01/2011 07:25 AM, Lyre wrote: > Make it able to generate debuginfo package. Thanks, pushed now! I don't know why this is not there but maybe I added this to f14 branch only since it's necessary to generate debuginfo packages for Fedora. However I applied your patch to master branch :) Thanks again, Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From hutao at cn.fujitsu.com Fri Apr 1 08:44:21 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Fri, 1 Apr 2011 16:44:21 +0800 Subject: [libvirt] [PATCH 3/4] vcpupin: implement the remote protocol to address the new API In-Reply-To: <4D9413A8.90401@jp.fujitsu.com> References: <4D94124A.1090808@jp.fujitsu.com> <4D9413A8.90401@jp.fujitsu.com> Message-ID: <20110401084421.GB5261@localhost.localdomain> On Thu, Mar 31, 2011 at 02:39:52PM +0900, Taku Izumi wrote: > > This patch implements the remote protocol to address the new API > (virDomainPinVcpuFlags). > > Signed-off-by: Taku Izumi > --- > daemon/remote.c | 37 +++++++++++++++++++++++++++++++++ > daemon/remote_dispatch_args.h | 1 > daemon/remote_dispatch_prototypes.h | 8 +++++++ > daemon/remote_dispatch_table.h | 5 ++++ > src/remote/remote_driver.c | 40 +++++++++++++++++++++++++++++++++++- > src/remote/remote_protocol.c | 16 ++++++++++++++ > src/remote/remote_protocol.h | 14 ++++++++++++ > src/remote/remote_protocol.x | 10 ++++++++- > src/remote_protocol-structs | 9 ++++++++ > 9 files changed, 138 insertions(+), 2 deletions(-) > > Index: libvirt/daemon/remote.c > =================================================================== > --- libvirt.orig/daemon/remote.c > +++ libvirt/daemon/remote.c > @@ -2188,6 +2188,43 @@ remoteDispatchDomainPinVcpu (struct qemu > } > > static int > +remoteDispatchDomainPinVcpuFlags (struct qemud_server *server ATTRIBUTE_UNUSED, > + struct qemud_client *client ATTRIBUTE_UNUSED, > + virConnectPtr conn, > + remote_message_header *hdr ATTRIBUTE_UNUSED, > + remote_error *rerr, > + remote_domain_pin_vcpu_flags_args *args, > + void *ret ATTRIBUTE_UNUSED) > +{ > + virDomainPtr dom; > + int rv; > + > + dom = get_nonnull_domain (conn, args->dom); > + if (dom == NULL) { > + remoteDispatchConnError(rerr, conn); > + return -1; > + } > + > + if (args->cpumap.cpumap_len > REMOTE_CPUMAP_MAX) { > + virDomainFree(dom); > + remoteDispatchFormatError (rerr, "%s", _("cpumap_len > REMOTE_CPUMAP_MAX")); > + return -1; > + } > + > + rv = virDomainPinVcpuFlags (dom, args->vcpu, > + (unsigned char *) args->cpumap.cpumap_val, > + args->cpumap.cpumap_len, > + args->flags); > + if (rv == -1) { > + remoteDispatchConnError(rerr, conn); > + virDomainFree(dom); > + return -1; > + } > + virDomainFree(dom); > + return 0; > +} > + > +static int > remoteDispatchDomainReboot (struct qemud_server *server ATTRIBUTE_UNUSED, > struct qemud_client *client ATTRIBUTE_UNUSED, > virConnectPtr conn, > Index: libvirt/daemon/remote_dispatch_args.h > =================================================================== > --- libvirt.orig/daemon/remote_dispatch_args.h > +++ libvirt/daemon/remote_dispatch_args.h > @@ -178,3 +178,4 @@ > remote_domain_migrate_set_max_speed_args > val_remote_domain_migrate_set_max_speed_args; Long line auto-wrapped by your mail client? > remote_storage_vol_upload_args val_remote_storage_vol_upload_args; > remote_storage_vol_download_args val_remote_storage_vol_download_args; > + remote_domain_pin_vcpu_flags_args val_remote_domain_pin_vcpu_flags_args; > Index: libvirt/daemon/remote_dispatch_prototypes.h > =================================================================== > --- libvirt.orig/daemon/remote_dispatch_prototypes.h > +++ libvirt/daemon/remote_dispatch_prototypes.h > @@ -506,6 +506,14 @@ static int remoteDispatchDomainPinVcpu( > remote_error *err, > remote_domain_pin_vcpu_args *args, > void *ret); > +static int remoteDispatchDomainPinVcpuFlags( > + struct qemud_server *server, > + struct qemud_client *client, > + virConnectPtr conn, > + remote_message_header *hdr, > + remote_error *err, > + remote_domain_pin_vcpu_flags_args *args, > + void *ret); > static int remoteDispatchDomainReboot( > struct qemud_server *server, > struct qemud_client *client, > Index: libvirt/daemon/remote_dispatch_table.h > =================================================================== > --- libvirt.orig/daemon/remote_dispatch_table.h > +++ libvirt/daemon/remote_dispatch_table.h > @@ -1052,3 +1052,8 @@ > .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, > .ret_filter = (xdrproc_t) xdr_void, > }, > +{ /* DomainPinVcpuFlags => 210 */ > + .fn = (dispatch_fn) remoteDispatchDomainPinVcpuFlags, > + .args_filter = (xdrproc_t) xdr_remote_domain_pin_vcpu_flags_args, > + .ret_filter = (xdrproc_t) xdr_void, > +}, > Index: libvirt/src/remote/remote_driver.c > =================================================================== > --- libvirt.orig/src/remote/remote_driver.c > +++ libvirt/src/remote/remote_driver.c > @@ -3042,6 +3042,44 @@ done: > } > > static int > +remoteDomainPinVcpuFlags (virDomainPtr domain, > + unsigned int vcpu, > + unsigned char *cpumap, > + int maplen, > + unsigned int flags) > +{ > + int rv = -1; > + remote_domain_pin_vcpu_flags_args args; > + struct private_data *priv = domain->conn->privateData; > + > + remoteDriverLock(priv); > + > + if (maplen > REMOTE_CPUMAP_MAX) { > + remoteError(VIR_ERR_RPC, > + _("map length greater than maximum: %d > %d"), > + maplen, REMOTE_CPUMAP_MAX); > + goto done; > + } > + > + make_nonnull_domain (&args.dom, domain); > + args.vcpu = vcpu; > + args.cpumap.cpumap_len = maplen; > + args.cpumap.cpumap_val = (char *) cpumap; > + args.flags = flags; > + > + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS, > + (xdrproc_t) xdr_remote_domain_pin_vcpu_flags_args, (char *) &args, > + (xdrproc_t) xdr_void, (char *) NULL) == -1) > + goto done; > + > + rv = 0; > + > +done: > + remoteDriverUnlock(priv); > + return rv; > +} > + > +static int > remoteDomainGetVcpus (virDomainPtr domain, > virVcpuInfoPtr info, > int maxinfo, > @@ -11227,7 +11265,7 @@ static virDriver remote_driver = { > remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ > remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ > remoteDomainPinVcpu, /* domainPinVcpu */ > - NULL, /* domainPinVcpuFlags */ > + remoteDomainPinVcpuFlags, /* domainPinVcpuFlags */ > remoteDomainGetVcpus, /* domainGetVcpus */ > remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */ > remoteDomainGetSecurityLabel, /* domainGetSecurityLabel */ > Index: libvirt/src/remote/remote_protocol.c > =================================================================== > --- libvirt.orig/src/remote/remote_protocol.c > +++ libvirt/src/remote/remote_protocol.c > @@ -1521,6 +1521,22 @@ xdr_remote_domain_pin_vcpu_args (XDR *xd > } > > bool_t > +xdr_remote_domain_pin_vcpu_flags_args (XDR *xdrs, remote_domain_pin_vcpu_flags_args > *objp) Long line auto-wrapped by your mail client? > +{ > + char **objp_cpp0 = (char **) (void *) &objp->cpumap.cpumap_val; > + > + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) > + return FALSE; > + if (!xdr_int (xdrs, &objp->vcpu)) > + return FALSE; > + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cpumap.cpumap_len, > REMOTE_CPUMAP_MAX)) Long line auto-wrapped by your mail client? > + return FALSE; > + if (!xdr_u_int (xdrs, &objp->flags)) > + return FALSE; > + return TRUE; > +} > + > +bool_t > xdr_remote_domain_get_vcpus_args (XDR *xdrs, remote_domain_get_vcpus_args *objp) > { > > Index: libvirt/src/remote/remote_protocol.h > =================================================================== > --- libvirt.orig/src/remote/remote_protocol.h > +++ libvirt/src/remote/remote_protocol.h > @@ -841,6 +841,17 @@ struct remote_domain_pin_vcpu_args { > }; > typedef struct remote_domain_pin_vcpu_args remote_domain_pin_vcpu_args; > > +struct remote_domain_pin_vcpu_flags_args { > + remote_nonnull_domain dom; > + int vcpu; > + struct { > + u_int cpumap_len; > + char *cpumap_val; > + } cpumap; > + u_int flags; > +}; > +typedef struct remote_domain_pin_vcpu_flags_args remote_domain_pin_vcpu_flags_args; > + > struct remote_domain_get_vcpus_args { > remote_nonnull_domain dom; > int maxinfo; > @@ -2413,6 +2424,7 @@ enum remote_procedure { > REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, > REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, > REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, > + REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS = 210, > }; > typedef enum remote_procedure remote_procedure; > > @@ -2566,6 +2578,7 @@ extern bool_t xdr_remote_domain_set_vcp > extern bool_t xdr_remote_domain_get_vcpus_flags_args (XDR *, > remote_domain_get_vcpus_flags_args*); Long line auto-wrapped by your mail client? > extern bool_t xdr_remote_domain_get_vcpus_flags_ret (XDR *, > remote_domain_get_vcpus_flags_ret*); Long line auto-wrapped by your mail client? > extern bool_t xdr_remote_domain_pin_vcpu_args (XDR *, remote_domain_pin_vcpu_args*); > +extern bool_t xdr_remote_domain_pin_vcpu_flags_args (XDR *, > remote_domain_pin_vcpu_flags_args*); Long line auto-wrapped by your mail client? > extern bool_t xdr_remote_domain_get_vcpus_args (XDR *, remote_domain_get_vcpus_args*); > extern bool_t xdr_remote_domain_get_vcpus_ret (XDR *, remote_domain_get_vcpus_ret*); > extern bool_t xdr_remote_domain_get_max_vcpus_args (XDR *, > remote_domain_get_max_vcpus_args*); Long line auto-wrapped by your mail client? > @@ -2923,6 +2936,7 @@ extern bool_t xdr_remote_domain_set_vcpu > extern bool_t xdr_remote_domain_get_vcpus_flags_args (); > extern bool_t xdr_remote_domain_get_vcpus_flags_ret (); > extern bool_t xdr_remote_domain_pin_vcpu_args (); > +extern bool_t xdr_remote_domain_pin_vcpu_flags_args (); > extern bool_t xdr_remote_domain_get_vcpus_args (); > extern bool_t xdr_remote_domain_get_vcpus_ret (); > extern bool_t xdr_remote_domain_get_max_vcpus_args (); > Index: libvirt/src/remote/remote_protocol.x > =================================================================== > --- libvirt.orig/src/remote/remote_protocol.x > +++ libvirt/src/remote/remote_protocol.x > @@ -843,6 +843,13 @@ struct remote_domain_pin_vcpu_args { > opaque cpumap; > }; > > +struct remote_domain_pin_vcpu_flags_args { > + remote_nonnull_domain dom; > + int vcpu; > + opaque cpumap; > + unsigned int flags; > +}; > + > struct remote_domain_get_vcpus_args { > remote_nonnull_domain dom; > int maxinfo; > @@ -2176,7 +2183,8 @@ enum remote_procedure { > REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, > REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, > REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, > - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 > + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, > + REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS = 210 > > /* > * Notice how the entries are grouped in sets of 10 ? > Index: libvirt/src/remote_protocol-structs > =================================================================== > --- libvirt.orig/src/remote_protocol-structs > +++ libvirt/src/remote_protocol-structs > @@ -528,6 +528,15 @@ struct remote_domain_pin_vcpu_args { > char * cpumap_val; > } cpumap; > }; > +struct remote_domain_pin_vcpu_flags_args { > + remote_nonnull_domain dom; > + int vcpu; > + struct { > + u_int cpumap_len; > + char * cpumap_val; > + } cpumap; > + u_int flags; > +}; > struct remote_domain_get_vcpus_args { > remote_nonnull_domain dom; > int maxinfo; > > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list From jdenemar at redhat.com Fri Apr 1 08:47:29 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Fri, 1 Apr 2011 10:47:29 +0200 Subject: [libvirt] [PATCH] virsh: Fix documentation for memtune command In-Reply-To: References: Message-ID: <44f0aebb40d95a22a5aee5717977da33824a54c0.1301647649.git.jdenemar@redhat.com> Commit 78ba748ef14c520ff1c4af2b5b0a44586ac49c8c claims to fix documentation for swap_hard_limit virsh memtune option but it only fixes documentation in formatdomain.html and libvirt.h. This patch completes the task by fixing "virsh help memtune" output and memtune section of virsh man page. --- docs/formatdomain.html.in | 6 +++++- tools/virsh.c | 2 +- tools/virsh.pod | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 438cbf0..5523fc7 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -314,7 +314,11 @@
memtune
The optional memtune element provides details regarding the memory tunable parameters for the domain. If this is - omitted, it defaults to the OS provided defaults.
+ omitted, it defaults to the OS provided defaults. For QEMU/KVMi, the + parameters are applied to the QEMU process as a whole. Thus, when + counting them, one needs to add up guest RAM, guest video RAM, and + some memory overhead of QEMU itself. The last piece is hard to + determine so one needs guess and try.
hard_limit
The optional hard_limit element is the maximum memory the guest can use. The units for this value are kilobytes (i.e. blocks diff --git a/tools/virsh.c b/tools/virsh.c index 3c759b9..19e3449 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -3202,7 +3202,7 @@ static const vshCmdOptDef opts_memtune[] = { {"soft-limit", VSH_OT_INT, VSH_OFLAG_NONE, N_("Memory during contention in kilobytes")}, {"swap-hard-limit", VSH_OT_INT, VSH_OFLAG_NONE, - N_("Max swap in kilobytes")}, + N_("Max memory plus swap in kilobytes")}, {"min-guarantee", VSH_OT_INT, VSH_OFLAG_NONE, N_("Min guaranteed memory in kilobytes")}, {NULL, 0, 0, NULL} diff --git a/tools/virsh.pod b/tools/virsh.pod index e882261..f4bd294 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -611,12 +611,42 @@ use the virsh B command instead to update its XML element. =item B I optional I<--hard-limit> B optional I<--soft-limit> B optional I<--swap-hard-limit> -B -I<--min-guarantee> B +B optional I<--min-guarantee> B Allows you to display or set the domain memory parameters. Without flags, the current settings are displayed; with a flag, the appropriate limit is adjusted if supported by the hypervisor. LXC and -QEMU/KVM supports I<--hard-limit>, I<--soft-limit>, and I<--swap-hard-limit>. +QEMU/KVM support I<--hard-limit>, I<--soft-limit>, and I<--swap-hard-limit>. + +For QEMU/KVM, the parameters are applied to the QEMU process as a whole. +Thus, when counting them, one needs to add up guest RAM, guest video RAM, and +some memory overhead of QEMU itself. The last piece is hard to determine so +one needs guess and try. + +=over 4 + +=item I<--hard-limit> + +The maximum memory the guest can use. The units for this value are kilobytes +(i.e. blocks of 1024 bytes). + +=item I<--soft-limit> + +The memory limit to enforce during memory contention. The units for this +value are kilobytes (i.e. blocks of 1024 bytes). + +=item I<--swap-hard-limit> + +The maximum memory plus swap the guest can use. The units for this value are +kilobytes (i.e. blocks of 1024 bytes). This has to be more than hard-limit +value provided. + +=item I<--min-guarantee> + +The guaranteed minimum memory allocation for the guest. The units for this +value are kilobytes (i.e. blocks of 1024 bytes). + +=back =item B I optional I<--weight> B -- 1.7.4.1 From berrange at redhat.com Fri Apr 1 09:24:46 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 1 Apr 2011 10:24:46 +0100 Subject: [libvirt] [PATCH] virsh: Fix documentation for memtune command In-Reply-To: <44f0aebb40d95a22a5aee5717977da33824a54c0.1301647649.git.jdenemar@redhat.com> References: <44f0aebb40d95a22a5aee5717977da33824a54c0.1301647649.git.jdenemar@redhat.com> Message-ID: <20110401092446.GA29510@redhat.com> On Fri, Apr 01, 2011 at 10:47:29AM +0200, Jiri Denemark wrote: > Commit 78ba748ef14c520ff1c4af2b5b0a44586ac49c8c claims to fix > documentation for swap_hard_limit virsh memtune option but it only fixes > documentation in formatdomain.html and libvirt.h. This patch completes > the task by fixing "virsh help memtune" output and memtune section of > virsh man page. > --- > docs/formatdomain.html.in | 6 +++++- > tools/virsh.c | 2 +- > tools/virsh.pod | 34 ++++++++++++++++++++++++++++++++-- > 3 files changed, 38 insertions(+), 4 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From liyong at skybility.com Fri Apr 1 09:23:51 2011 From: liyong at skybility.com (Lyre) Date: Fri, 01 Apr 2011 17:23:51 +0800 Subject: [libvirt] [libvirt-php] Remove strip from installation In-Reply-To: <4D958DF4.4090206@redhat.com> References: <1301635516-30885-1-git-send-email-liyong@skybility.com> <4D958DF4.4090206@redhat.com> Message-ID: <4D9599A7.4050805@skybility.com> ? 2011?04?01? 16:33, Michal Novotny ??: > On 04/01/2011 07:25 AM, Lyre wrote: >> Make it able to generate debuginfo package. > Thanks, pushed now! I don't know why this is not there but maybe I added > this to f14 branch only since it's necessary to generate debuginfo > packages for Fedora. However I applied your patch to master branch :) > > Thanks again, > Michal > Hi michal: I'm debugging a problem that maybe caused by libvirt-php. However if we strip the library during installation, we wouldn't be able to build the debuginfo package. The spec file wouldn't build this package, but this change make it possible. BTW, I've noticed that there's a bug in set_error(), I'll submit it after test.r From berrange at redhat.com Fri Apr 1 09:27:34 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 1 Apr 2011 10:27:34 +0100 Subject: [libvirt] [PATCH] Fix several formatting mistakes in doc In-Reply-To: <20110401012545.GG24385@redhat.com> References: <1301570043-30978-1-git-send-email-mprivozn@redhat.com> <20110331135837.GM24425@redhat.com> <4D94B6B6.7000806@redhat.com> <20110401012545.GG24385@redhat.com> Message-ID: <20110401092734.GB29510@redhat.com> On Fri, Apr 01, 2011 at 09:25:45AM +0800, Daniel Veillard wrote: > On Thu, Mar 31, 2011 at 11:15:34AM -0600, Eric Blake wrote: > > On 03/31/2011 07:58 AM, Daniel P. Berrange wrote: > > > > > > - We run xmllint, but failures in xmllint validation > > > are not causing a build failure > > > > We already have code in place to call 'exit 1' on xmllint failure (but > > not in all places). However, in my testing, it was xsltproc that is not > > throwing an error: > > > > $ /usr/bin/xsltproc --stringparam pagename $name --nonet --html > > ../docs/site.xsl formatdomain.html.in > formatdomain.html.tmp > > formatdomain.html.in:356: HTML parser error : Unexpected end tag : vcpu > > required attributes, the attribute vcpu specifies > > vcpu id, > > ^ > > $ echo $? > > 0 > > it's because we are using --html, instructing libxml2 underneath to > use teh HTML parser to load the .html.in . And the HTML parser is just > reporting errors, not failing on them (as 99% of the HTML around is > just buggy). > > > That looks like a bug in xsltproc (here from Fedora > > libxslt-1.1.26-3.fc14.x86_64), since the man page states that $? should > > be 6 when there is an error in the document. > > Well except for HTML input, remove the --html and see, maybe we could > do that in the Makefile and insist on the .html.in being well formed > in the first place. > > > I can work around it by sniffing for non-empty stderr; that will look > > yucky in the makefile, but is probably worth doing. > > Doesn't sound that great honnestly, try dropping --html instead and > see how it goes Yes, that sounds reasonable. Our site.xsl file is already setup to output XHTML, so we should treat our input as wellformed XHTML too, rather than loose HTML. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From veillard at redhat.com Fri Apr 1 09:34:27 2011 From: veillard at redhat.com (Daniel Veillard) Date: Fri, 1 Apr 2011 17:34:27 +0800 Subject: [libvirt] [PATCH] Fix libxl driver startup Message-ID: <20110401093426.GK24385@redhat.com> When you happen to have a libvirtd binary compiled with the libxenlight driver (say you have installed xen-4.1 libraries) but not running a xen enabled system, then libvirtd fails to start. The cause is that libxlStartup() returns -1 when failing to initialize the library, and this propagates to virStateInitialize() which consider this a failure. We should only exit libxlStartup with an error code if something like an allocation error occurs, not if the driver failed to initialize. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -------------- next part -------------- diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index e996ff6..3859405 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -548,7 +548,7 @@ libxlStartup(int privileged) { const libxl_version_info *ver_info; char *log_file = NULL; virCommandPtr cmd; - int status; + int status, ret = 0; /* Disable libxl driver if non-root */ if (!privileged) { @@ -659,19 +659,19 @@ libxlStartup(int privileged) { (xentoollog_logger *)xtl_createlogger_stdiostream(libxl_driver->logger_file, XTL_DEBUG, 0); if (!libxl_driver->logger) { VIR_ERROR0(_("cannot create logger for libxenlight")); - goto error; + goto fail; } if (libxl_ctx_init(&libxl_driver->ctx, LIBXL_VERSION, libxl_driver->logger)) { VIR_ERROR0(_("cannot initialize libxenlight context")); - goto error; + goto fail; } if ((ver_info = libxl_get_version_info(&libxl_driver->ctx)) == NULL) { VIR_ERROR0(_("cannot version information from libxenlight")); - goto error; + goto fail; } libxl_driver->version = (ver_info->xen_version_major * 1000000) + (ver_info->xen_version_minor * 1000); @@ -712,11 +712,13 @@ libxlStartup(int privileged) { out_of_memory: virReportOOMError(); error: + ret = -1; +fail: VIR_FREE(log_file); if (libxl_driver) libxlDriverUnlock(libxl_driver); libxlShutdown(); - return -1; + return ret; } static int From berrange at redhat.com Fri Apr 1 09:44:33 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 1 Apr 2011 10:44:33 +0100 Subject: [libvirt] [PATCH] virsh: fix mingw failure on creating nonblocking pipe In-Reply-To: <4D94FC39.10404@redhat.com> References: <1301609000-30523-1-git-send-email-eblake@redhat.com> <4D94FC39.10404@redhat.com> Message-ID: <20110401094433.GD29510@redhat.com> On Thu, Mar 31, 2011 at 04:12:09PM -0600, Eric Blake wrote: > On 03/31/2011 04:03 PM, Eric Blake wrote: > > * .gnulib: Update to latest, for nonblocking module. > > * bootstrap.conf (gnulib_modules): Add nonblocking. > > * src/util/util.c (virSetBlocking): Defer to gnulib. > > --- > > > > Matthias, does this work for you on your mingw build? So far, > > I have only tested that it cross-compiles, and that the new > > gnulib module passes its self-test when run in isolation on mingw. > > > > int virSetBlocking(int fd, bool blocking) { > > > - if (blocking) > > - flags &= ~O_NONBLOCK; > > > + return set_nonblocking_flag (fd, blocking); > > Oops - that _can't_ work. s/blocking/!blocking/ in that return statement. ACK with that fix :-) Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From laijs at cn.fujitsu.com Fri Apr 1 09:51:06 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Fri, 01 Apr 2011 17:51:06 +0800 Subject: [libvirt] [PATCH] add sendevent command and related APIs Message-ID: <4D95A00A.3040901@cn.fujitsu.com> Enable libvirt send some events to the guest. This command currently only supports NMI and key events. Signed-off-by: Lai Jiangshan --- daemon/remote.c | 52 +++++++++++++++++++++ daemon/remote_dispatch_args.h | 2 daemon/remote_dispatch_prototypes.h | 16 ++++++ daemon/remote_dispatch_table.h | 10 ++++ include/libvirt/libvirt.h.in | 3 + src/driver.h | 7 ++ src/esx/esx_driver.c | 2 src/libvirt.c | 88 ++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 2 src/libxl/libxl_driver.c | 2 src/lxc/lxc_driver.c | 2 src/openvz/openvz_driver.c | 2 src/phyp/phyp_driver.c | 4 + src/qemu/qemu_driver.c | 86 +++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 27 +++++++++++ src/qemu/qemu_monitor.h | 3 + src/qemu/qemu_monitor_json.c | 68 +++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 3 + src/qemu/qemu_monitor_text.c | 56 ++++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 2 src/remote/remote_driver.c | 50 ++++++++++++++++++++ src/remote/remote_protocol.c | 22 +++++++++ src/remote/remote_protocol.h | 19 +++++++ src/remote/remote_protocol.x | 14 +++++ src/test/test_driver.c | 2 src/uml/uml_driver.c | 2 src/vbox/vbox_tmpl.c | 2 src/vmware/vmware_driver.c | 2 src/xen/xen_driver.c | 2 src/xenapi/xenapi_driver.c | 2 tools/virsh.c | 56 ++++++++++++++++++++++ 31 files changed, 608 insertions(+), 2 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 1700c2d..5f9e78a 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -2836,6 +2836,58 @@ remoteDispatchDomainGetBlkioParameters(struct qemud_server *server } static int +remoteDispatchDomainSendEventNMI(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_send_event_nmi_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virDomainPtr dom; + + dom = get_nonnull_domain(conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + if (virDomainSendEventNMI(dom, args->vcpu) == -1) { + virDomainFree(dom); + remoteDispatchConnError(rerr, conn); + return -1; + } + virDomainFree(dom); + return 0; +} + +static int +remoteDispatchDomainSendEventKey(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_send_event_key_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virDomainPtr dom; + + dom = get_nonnull_domain(conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + if (virDomainSendEventKey(dom, args->key) == -1) { + virDomainFree(dom); + remoteDispatchConnError(rerr, conn); + return -1; + } + virDomainFree(dom); + return 0; +} + +static int remoteDispatchDomainSetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index f9537d7..289a42e 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -178,3 +178,5 @@ remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; remote_storage_vol_upload_args val_remote_storage_vol_upload_args; remote_storage_vol_download_args val_remote_storage_vol_download_args; + remote_domain_send_event_nmi_args val_remote_domain_send_event_nmi_args; + remote_domain_send_event_key_args val_remote_domain_send_event_key_args; diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 18bf41d..f920193 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -1618,3 +1618,19 @@ static int remoteDispatchSupportsFeature( remote_error *err, remote_supports_feature_args *args, remote_supports_feature_ret *ret); +static int remoteDispatchDomainSendEventNMI( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_send_event_nmi_args *args, + void *ret); +static int remoteDispatchDomainSendEventKey( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_send_event_key_args *args, + void *ret); diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index b39f7c2..a706b19 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1052,3 +1052,13 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* DomainSendEventNmi => 210 */ + .fn = (dispatch_fn) remoteDispatchDomainSendEventNMI, + .args_filter = (xdrproc_t) xdr_remote_domain_send_event_nmi_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainSendEventKey => 211 */ + .fn = (dispatch_fn) remoteDispatchDomainSendEventKey, + .args_filter = (xdrproc_t) xdr_remote_domain_send_event_key_args, + .ret_filter = (xdrproc_t) xdr_void, +}, diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index bd36015..adbe482 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2517,6 +2517,9 @@ int virDomainOpenConsole(virDomainPtr dom, virStreamPtr st, unsigned int flags); +int virDomainSendEventNMI(virDomainPtr domain, unsigned int vcpu); +int virDomainSendEventKey(virDomainPtr domain, const char *key); + #ifdef __cplusplus } #endif diff --git a/src/driver.h b/src/driver.h index e5f91ca..6caf13f 100644 --- a/src/driver.h +++ b/src/driver.h @@ -515,6 +515,11 @@ typedef int virStreamPtr st, unsigned int flags); +typedef int + (*virDrvDomainSendEventNMI)(virDomainPtr dom, unsigned int vcpu); + +typedef int + (*virDrvDomainSendEventKey)(virDomainPtr dom, const char *key); /** * _virDriver: @@ -639,6 +644,8 @@ struct _virDriver { virDrvDomainSnapshotDelete domainSnapshotDelete; virDrvQemuDomainMonitorCommand qemuDomainMonitorCommand; virDrvDomainOpenConsole domainOpenConsole; + virDrvDomainSendEventNMI domainSendEventNMI; + virDrvDomainSendEventKey domainSendEventKey; }; typedef int diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index deda372..7167712 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4675,6 +4675,8 @@ static virDriver esxDriver = { esxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainSendEventNMI */ + NULL, /* domainSendEventKey */ }; diff --git a/src/libvirt.c b/src/libvirt.c index 9bdb4c8..245247f 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -5245,6 +5245,94 @@ error: } /** + * virDomainSendEvnetNMI: + * @domain: pointer to domain object, or NULL for Domain0 + * @vcpu: the virtual CPU id to send NMI to + * + * Send NMI to a special vcpu of the guest + * + * Returns 0 in case of success, -1 in case of failure. + */ + +int virDomainSendEventNMI(virDomainPtr domain, unsigned int vcpu) +{ + virConnectPtr conn; + VIR_DOMAIN_DEBUG(domain, "vcpu=%u", vcpu); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainSendEventNMI) { + int ret; + ret = conn->driver->domainSendEventNMI(domain, vcpu); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} + +/** + * virDomainSendEventKey: + * @domain: pointer to domain object, or NULL for Domain0 + * @key: the string of key or key sequence + * + * Send a special key or key sequence to the guest + * + * Returns 0 in case of success, -1 in case of failure. + */ + +int virDomainSendEventKey(virDomainPtr domain, const char *key) +{ + virConnectPtr conn; + VIR_DOMAIN_DEBUG(domain, "key=%s", key); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainSendEventKey) { + int ret; + ret = conn->driver->domainSendEventKey(domain, key); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} + +/** * virDomainSetVcpus: * @domain: pointer to domain object, or NULL for Domain0 * @nvcpus: the new number of virtual CPUs for this domain diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b4aed41..cd0f474 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -434,6 +434,8 @@ LIBVIRT_0.9.0 { virEventRunDefaultImpl; virStorageVolDownload; virStorageVolUpload; + virDomainSendEventNMI; + virDomainSendEventKey; } LIBVIRT_0.8.8; # .... define new API here using predicted next version number .... diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index e996ff6..040fc16 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2353,6 +2353,8 @@ static virDriver libxlDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainSendEventNMI */ + NULL, /* domainSendEventKey */ }; static virStateDriver libxlStateDriver = { diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e905302..1284ab1 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2906,6 +2906,8 @@ static virDriver lxcDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ lxcDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainSendEventNMI */ + NULL, /* domainSendEventKey */ }; static virStateDriver lxcStateDriver = { diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index fb30c37..26ba0a5 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1654,6 +1654,8 @@ static virDriver openvzDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainSendEventNMI */ + NULL, /* domainSendEventKey */ }; int openvzRegister(void) { diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 51f9ff6..d5d0ea6 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -4054,7 +4054,9 @@ static virDriver phypDriver = { NULL, /* domainRevertToSnapshot */ NULL, /* domainSnapshotDelete */ NULL, /* qemuMonitorCommand */ - NULL, /* domainOpenConsole */ + NULL, /* domainOpenConsole */ + NULL, /* domainSendEventNMI */ + NULL, /* domainSendEventKey */ }; static virStorageDriver phypStorageDriver = { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index dd12dc8..02af591 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1659,6 +1659,90 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { return qemudDomainSetMemoryFlags(dom, newmem, VIR_DOMAIN_MEM_LIVE); } +static int qemuDomainSendEventNMI(virDomainPtr domain, unsigned int vcpu) +{ + struct qemud_driver *driver = domain->conn->privateData; + virDomainObjPtr vm = NULL; + int ret = -1; + qemuDomainObjPrivatePtr priv; + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, domain->uuid); + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(domain->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; + } + + priv = vm->privateData; + + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + goto cleanup; + qemuDomainObjEnterMonitorWithDriver(driver, vm); + ret = qemuMonitorSendEventNMI(priv->mon, vcpu); + qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjEndJob(vm) == 0) { + vm = NULL; + goto cleanup; + } + +cleanup: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); + return ret; +} + +static int qemuDomainSendEventKey(virDomainPtr domain, const char *key) +{ + struct qemud_driver *driver = domain->conn->privateData; + virDomainObjPtr vm = NULL; + int ret = -1; + qemuDomainObjPrivatePtr priv; + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, domain->uuid); + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(domain->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; + } + + priv = vm->privateData; + + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + goto cleanup; + qemuDomainObjEnterMonitorWithDriver(driver, vm); + ret = qemuMonitorSendEventKey(priv->mon, key); + qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjEndJob(vm) == 0) { + vm = NULL; + goto cleanup; + } + +cleanup: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); + return ret; +} + static int qemudDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { struct qemud_driver *driver = dom->conn->privateData; @@ -6923,6 +7007,8 @@ static virDriver qemuDriver = { qemuDomainSnapshotDelete, /* domainSnapshotDelete */ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ qemuDomainOpenConsole, /* domainOpenConsole */ + qemuDomainSendEventNMI, /* domainSendEventNMI */ + qemuDomainSendEventKey, /* domainSendEventKey */ }; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 2d28f8d..bc2e269 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2228,3 +2228,30 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, ret = qemuMonitorTextArbitraryCommand(mon, cmd, reply); return ret; } + + +int qemuMonitorSendEventNMI(qemuMonitorPtr mon, unsigned int vcpu) +{ + int ret; + + VIR_DEBUG("mon=%p, vcpu=%u", mon, vcpu); + + if (mon->json) + ret = qemuMonitorJSONSendEventNMI(mon, vcpu); + else + ret = qemuMonitorTextSendEventNMI(mon, vcpu); + return ret; +} + +int qemuMonitorSendEventKey(qemuMonitorPtr mon, const char *key) +{ + int ret; + + VIR_DEBUG("mon=%p, key sequence=%s", mon, key); + + if (mon->json) + ret = qemuMonitorJSONSendEventKey(mon, key); + else + ret = qemuMonitorTextSendEventKey(mon, key); + return ret; +} diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c90219b..fdc9859 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -423,6 +423,9 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, char **reply, bool hmp); +int qemuMonitorSendEventNMI(qemuMonitorPtr mon, unsigned int vcpu); +int qemuMonitorSendEventKey(qemuMonitorPtr mon, const char *key); + /** * When running two dd process and using <> redirection, we need a * shell that will not truncate files. These two strings serve that diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 20a78e1..5149d9e 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2513,3 +2513,71 @@ cleanup: return ret; } + +int qemuMonitorJSONSendEventNMI(qemuMonitorPtr mon, unsigned int vcpu) +{ + int ret = -1; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + char *hmp_cmd; + + /* + * FIXME: qmp nmi is not supported until qemu-0.16.0, + * use human-monitor-command instead temporary. + */ + if (virAsprintf(&hmp_cmd, "nmi %u", vcpu) < 0) { + virReportOOMError(); + return -1; + } + + cmd = qemuMonitorJSONMakeCommand("human-monitor-command", + "s:command-line", hmp_cmd, + NULL); + if (!cmd) + goto out_free_hmp_cmd; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + + virJSONValueFree(cmd); + virJSONValueFree(reply); +out_free_hmp_cmd: + VIR_FREE(hmp_cmd); + return ret; +} + +int qemuMonitorJSONSendEventKey(qemuMonitorPtr mon, const char *key_seq) +{ + int ret = -1; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + char *hmp_cmd; + + /* + * FIXME: qmp sendkey is not supported until qemu-0.16.0, + * use human-monitor-command instead temporary. + */ + if (virAsprintf(&hmp_cmd, "sendkey %s", key_seq) < 0) { + virReportOOMError(); + return -1; + } + + cmd = qemuMonitorJSONMakeCommand("human-monitor-command", + "s:command-line", hmp_cmd, + NULL); + if (!cmd) + goto out_free_hmp_cmd; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + + virJSONValueFree(cmd); + virJSONValueFree(reply); +out_free_hmp_cmd: + VIR_FREE(hmp_cmd); + return ret; +} diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 086f0e1..dc206df 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -204,4 +204,7 @@ int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon, char **reply_str, bool hmp); +int qemuMonitorJSONSendEventNMI(qemuMonitorPtr mon, unsigned int vcpu); +int qemuMonitorJSONSendEventKey(qemuMonitorPtr mon, const char *key); + #endif /* QEMU_MONITOR_JSON_H */ diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index e0e3292..d3416a8 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -2627,3 +2627,59 @@ int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, return ret; } + +int qemuMonitorTextSendEventNMI(qemuMonitorPtr mon, unsigned int vcpu) +{ + char *cmd; + char *reply = NULL; + int ret = -1; + + if (virAsprintf(&cmd, "nmi %u", vcpu) < 0) { + virReportOOMError(); + return -1; + } + if (qemuMonitorTextArbitraryCommand(mon, cmd, &reply)) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("failed to send NMI using command '%s'"), + cmd); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(cmd); + VIR_FREE(reply); + return ret; +} + +int qemuMonitorTextSendEventKey(qemuMonitorPtr mon, const char *key) +{ + char *cmd; + char *reply = NULL; + int ret = -1; + + if (virAsprintf(&cmd, "sendkey %s", key) < 0) { + virReportOOMError(); + return -1; + } + if (qemuMonitorTextArbitraryCommand(mon, cmd, &reply)) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("failed to send key using command '%s'"), + cmd); + goto cleanup; + } + + if (strstr(reply, "unknown key") != NULL) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("sent unknown key")); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(cmd); + VIR_FREE(reply); + return ret; +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 0838a2b..4a03c40 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -198,4 +198,6 @@ int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name); int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply); +int qemuMonitorTextSendEventNMI(qemuMonitorPtr mon, unsigned int vcpu); +int qemuMonitorTextSendEventKey(qemuMonitorPtr mon, const char *key); #endif /* QEMU_MONITOR_TEXT_H */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index bf94e70..676f473 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2929,6 +2929,54 @@ done: } static int +remoteDomainSendEventNMI(virDomainPtr domain, unsigned int vcpu) +{ + int rv = -1; + remote_domain_send_event_nmi_args args; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + make_nonnull_domain (&args.dom, domain); + args.vcpu = vcpu; + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SEND_EVENT_NMI, + (xdrproc_t) xdr_remote_domain_send_event_nmi_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainSendEventKey(virDomainPtr domain, const char *key) +{ + int rv = -1; + remote_domain_send_event_key_args args; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + make_nonnull_domain (&args.dom, domain); + args.key = (char *)key; + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SEND_EVENT_KEY, + (xdrproc_t) xdr_remote_domain_send_event_key_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int remoteDomainSetVcpus (virDomainPtr domain, unsigned int nvcpus) { int rv = -1; @@ -11296,6 +11344,8 @@ static virDriver remote_driver = { remoteDomainSnapshotDelete, /* domainSnapshotDelete */ remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ remoteDomainOpenConsole, /* domainOpenConsole */ + remoteDomainSendEventNMI, /* domainSendEventNMI */ + remoteDomainSendEventKey, /* domainSendEventKey */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 5604371..a829219 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -1463,6 +1463,28 @@ xdr_remote_domain_undefine_args (XDR *xdrs, remote_domain_undefine_args *objp) } bool_t +xdr_remote_domain_send_event_nmi_args (XDR *xdrs, remote_domain_send_event_nmi_args *objp) +{ + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->vcpu)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_send_event_key_args (XDR *xdrs, remote_domain_send_event_key_args *objp) +{ + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_remote_nonnull_string (xdrs, &objp->key)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_domain_set_vcpus_args (XDR *xdrs, remote_domain_set_vcpus_args *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index d9bf151..027ef88 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -2200,6 +2200,19 @@ struct remote_storage_vol_download_args { u_int flags; }; typedef struct remote_storage_vol_download_args remote_storage_vol_download_args; + +struct remote_domain_send_event_nmi_args { + remote_nonnull_domain dom; + u_int vcpu; +}; +typedef struct remote_domain_send_event_nmi_args remote_domain_send_event_nmi_args; + +struct remote_domain_send_event_key_args { + remote_nonnull_domain dom; + remote_nonnull_string key; +}; +typedef struct remote_domain_send_event_key_args remote_domain_send_event_key_args; + #define REMOTE_PROGRAM 0x20008086 #define REMOTE_PROTOCOL_VERSION 1 @@ -2413,6 +2426,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_SEND_EVENT_NMI = 210, + REMOTE_PROC_DOMAIN_SEND_EVENT_KEY = 211, }; typedef enum remote_procedure remote_procedure; @@ -2561,6 +2576,8 @@ extern bool_t xdr_remote_domain_create_with_flags_ret (XDR *, remote_domain_cre extern bool_t xdr_remote_domain_define_xml_args (XDR *, remote_domain_define_xml_args*); extern bool_t xdr_remote_domain_define_xml_ret (XDR *, remote_domain_define_xml_ret*); extern bool_t xdr_remote_domain_undefine_args (XDR *, remote_domain_undefine_args*); +extern bool_t xdr_remote_domain_send_event_nmi_args (XDR *, remote_domain_send_event_nmi_args*); +extern bool_t xdr_remote_domain_send_event_key_args (XDR *, remote_domain_send_event_key_args*); extern bool_t xdr_remote_domain_set_vcpus_args (XDR *, remote_domain_set_vcpus_args*); extern bool_t xdr_remote_domain_set_vcpus_flags_args (XDR *, remote_domain_set_vcpus_flags_args*); extern bool_t xdr_remote_domain_get_vcpus_flags_args (XDR *, remote_domain_get_vcpus_flags_args*); @@ -2918,6 +2935,8 @@ extern bool_t xdr_remote_domain_create_with_flags_ret (); extern bool_t xdr_remote_domain_define_xml_args (); extern bool_t xdr_remote_domain_define_xml_ret (); extern bool_t xdr_remote_domain_undefine_args (); +extern bool_t xdr_remote_domain_send_event_nmi_args (); +extern bool_t xdr_remote_domain_send_event_key_args (); extern bool_t xdr_remote_domain_set_vcpus_args (); extern bool_t xdr_remote_domain_set_vcpus_flags_args (); extern bool_t xdr_remote_domain_get_vcpus_flags_args (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 675eccd..34600d7 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -817,6 +817,16 @@ struct remote_domain_undefine_args { remote_nonnull_domain dom; }; +struct remote_domain_send_event_nmi_args { + remote_nonnull_domain dom; + unsigned int vcpu; +}; + +struct remote_domain_send_event_key_args { + remote_nonnull_domain dom; + remote_nonnull_string key; +}; + struct remote_domain_set_vcpus_args { remote_nonnull_domain dom; int nvcpus; @@ -2176,8 +2186,10 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_SEND_EVENT_NMI = 210, + REMOTE_PROC_DOMAIN_SEND_EVENT_KEY = 211, /* * Notice how the entries are grouped in sets of 10 ? * Nice isn't it. Please keep it this way when adding more. diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 17f5ad9..2163850 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5447,6 +5447,8 @@ static virDriver testDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainSendEventNMI */ + NULL, /* domainSendEventKey */ }; static virNetworkDriver testNetworkDriver = { diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index e2bd5f2..756877d 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2249,6 +2249,8 @@ static virDriver umlDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ umlDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainSendEventNMI */ + NULL, /* domainSendEventKey */ }; static int diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 8bd27dd..73c5c87 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8647,6 +8647,8 @@ virDriver NAME(Driver) = { vboxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainSendEventNMI */ + NULL, /* domainSendEventKey */ }; virNetworkDriver NAME(NetworkDriver) = { diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index b5e416b..eb64087 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -1007,6 +1007,8 @@ static virDriver vmwareDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainSendEventNMI */ + NULL, /* domainSendEventKey */ }; int diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 9f47722..bd82001 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2141,6 +2141,8 @@ static virDriver xenUnifiedDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ xenUnifiedDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainSendEventNMI */ + NULL, /* domainSendEventKey */ }; /** diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 27206a0..0f85ad8 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1885,6 +1885,8 @@ static virDriver xenapiDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainSendEventNMI */ + NULL, /* domainSendEventKey */ }; /** diff --git a/tools/virsh.c b/tools/virsh.c index faeaf47..0b78c6d 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2910,6 +2910,61 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) } /* + * "sendevent" command + */ +static const vshCmdInfo info_sendevent[] = { + {"help", N_("send events to the guest")}, + {"desc", N_("Send events (NMI or Keys) to the guest domain.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_sendevent[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"eventtype", VSH_OT_DATA, VSH_OFLAG_REQ, N_("the type of event (nmi or key)")}, + {"eventcontent", VSH_OT_DATA, VSH_OFLAG_REQ, N_("content for the event.")}, + {NULL, 0, 0, NULL} +}; + + +static int +cmdSendEvent(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + const char *type; + int ret = TRUE; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return FALSE; + + if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + return FALSE; + + if (vshCommandOptString(cmd, "eventtype", &type) < 0) + return FALSE; + + if (STREQ(type, "nmi")) { + int cpu; + + if ((vshCommandOptInt(cmd, "eventcontent", &cpu) < 0) + || (virDomainSendEventNMI(dom, cpu) < 0)) + ret = FALSE; + } else if (STREQ(type, "key")) { + const char *key; + + if ((vshCommandOptString(cmd, "eventcontent", &key) < 0) + || (virDomainSendEventKey(dom, key) < 0)) + ret = FALSE; + } else { + virDomainFree(dom); + vshError(ctl, _("Invalid event type: %s, only \"nmi\" or \"key\" supported currently."), type); + return FALSE; + } + + virDomainFree(dom); + return ret; +} + +/* * "setmemory" command */ static const vshCmdInfo info_setmem[] = { @@ -10693,6 +10748,7 @@ static const vshCmdDef domManagementCmds[] = { {"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem}, {"setmem", cmdSetmem, opts_setmem, info_setmem}, {"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus}, + {"sendevent", cmdSendEvent, opts_sendevent, info_sendevent}, {"shutdown", cmdShutdown, opts_shutdown, info_shutdown}, {"start", cmdStart, opts_start, info_start}, {"suspend", cmdSuspend, opts_suspend, info_suspend}, From minovotn at redhat.com Fri Apr 1 10:08:02 2011 From: minovotn at redhat.com (Michal Novotny) Date: Fri, 01 Apr 2011 12:08:02 +0200 Subject: [libvirt] [libvirt-php] Remove strip from installation In-Reply-To: <4D9599A7.4050805@skybility.com> References: <1301635516-30885-1-git-send-email-liyong@skybility.com> <4D958DF4.4090206@redhat.com> <4D9599A7.4050805@skybility.com> Message-ID: <4D95A402.1010305@redhat.com> On 04/01/2011 11:23 AM, Lyre wrote: > ? 2011?04?01? 16:33, Michal Novotny ??: >> On 04/01/2011 07:25 AM, Lyre wrote: >>> Make it able to generate debuginfo package. >> Thanks, pushed now! I don't know why this is not there but maybe I added >> this to f14 branch only since it's necessary to generate debuginfo >> packages for Fedora. However I applied your patch to master branch :) >> >> Thanks again, >> Michal >> > Hi michal: > > I'm debugging a problem that maybe caused by libvirt-php. However if we > strip the library during installation, we wouldn't be able to build the > debuginfo package. The spec file wouldn't build this package, but this > change make it possible. > > BTW, I've noticed that there's a bug in set_error(), I'll submit it > after test.r Hi, thanks. Now there's already set_error_if_unset() function so please make sure you're working against the latest tree, i.e. be sure to run `git pull` before you start working on that. Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From conor_murphy_virt at hotmail.com Fri Apr 1 09:11:55 2011 From: conor_murphy_virt at hotmail.com (Conor Murphy) Date: Fri, 1 Apr 2011 09:11:55 +0000 (UTC) Subject: [libvirt] [libvirt-php] API to add/remove disk to/from domain Message-ID: Hi, How do I add/remove a disk to a domain using the libvirt-php API? Thanks, Conor From minovotn at redhat.com Fri Apr 1 10:45:51 2011 From: minovotn at redhat.com (Michal Novotny) Date: Fri, 1 Apr 2011 12:45:51 +0200 Subject: [libvirt] [PATCH v2 0/5] Add TXT record and hosts support for DNS service and dnsmasq command-line regression testing Message-ID: <1301654756-3920-1-git-send-email-minovotn@redhat.com> Hi, this is the patch to introduce the TXT record and DNS hosts support for the DNS service on the virtual network. This can be defined using the txt-record subelement in the dns element of the network XML description. The definition of TXT record names containing spaces is rejected with the error message that TXT record names in DNS doesn't support spaces. Also, regression testing for the dnsmasq command line has been added to test whether the dnsmasq command-line is correct or not. The new XML definition syntax is: gateway host Where multiple host elements can be defined to put the aliases for specified IP addresses. The patch series has been tested for the configuration and it was working fine and also RelaxNG schema with the tests have been both altered to add test cases to test those patches. All of the patches passed the make, make check and make syntax-check commands and it has been tested for the definition described above and it was working fine (tested using dig for DNS TXT record and nslookup in the guest for the DNS hosts). Michal Signed-off-by: Michal Novotny Michal Novotny (5): Network: Add TXT record support for virtual DNS service Network: Add regression tests for the command line arguments Network: Move dnsmasqContext creation to networkSaveDnsmasqHostsfile() and pass to dnsmasq only if applicable Network: Add additional hosts internal infrastructure Network: Add support for DNS hosts definition in the network XML docs/formatnetwork.html.in | 31 +++- docs/schemas/network.rng | 20 ++ src/conf/network_conf.c | 183 ++++++++++++++ src/conf/network_conf.h | 25 ++ src/libvirt_private.syms | 1 + src/network/bridge_driver.c | 103 ++++++-- src/network/bridge_driver.h | 3 + src/util/dnsmasq.c | 266 +++++++++++++++++++- src/util/dnsmasq.h | 22 ++- tests/Makefile.am | 11 + tests/networkxml2argvdata/isolated-network.argv | 1 + tests/networkxml2argvdata/isolated-network.xml | 11 + .../networkxml2argvdata/nat-network-dns-hosts.argv | 1 + .../networkxml2argvdata/nat-network-dns-hosts.xml | 19 ++ .../nat-network-dns-txt-record.argv | 1 + .../nat-network-dns-txt-record.xml | 24 ++ tests/networkxml2argvdata/nat-network.argv | 1 + tests/networkxml2argvdata/nat-network.xml | 21 ++ tests/networkxml2argvdata/netboot-network.argv | 1 + tests/networkxml2argvdata/netboot-network.xml | 14 + .../networkxml2argvdata/netboot-proxy-network.argv | 1 + .../networkxml2argvdata/netboot-proxy-network.xml | 13 + tests/networkxml2argvdata/routed-network.argv | 1 + tests/networkxml2argvdata/routed-network.xml | 9 + tests/networkxml2argvtest.c | 120 +++++++++ tests/networkxml2xmlin/nat-network-dns-hosts.xml | 27 ++ .../nat-network-dns-txt-record.xml | 24 ++ tests/networkxml2xmlout/nat-network-dns-hosts.xml | 27 ++ .../nat-network-dns-txt-record.xml | 24 ++ tests/networkxml2xmltest.c | 2 + 30 files changed, 974 insertions(+), 33 deletions(-) create mode 100644 tests/networkxml2argvdata/isolated-network.argv create mode 100644 tests/networkxml2argvdata/isolated-network.xml create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.xml create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.xml create mode 100644 tests/networkxml2argvdata/nat-network.argv create mode 100644 tests/networkxml2argvdata/nat-network.xml create mode 100644 tests/networkxml2argvdata/netboot-network.argv create mode 100644 tests/networkxml2argvdata/netboot-network.xml create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.argv create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.xml create mode 100644 tests/networkxml2argvdata/routed-network.argv create mode 100644 tests/networkxml2argvdata/routed-network.xml create mode 100644 tests/networkxml2argvtest.c create mode 100644 tests/networkxml2xmlin/nat-network-dns-hosts.xml create mode 100644 tests/networkxml2xmlin/nat-network-dns-txt-record.xml create mode 100644 tests/networkxml2xmlout/nat-network-dns-hosts.xml create mode 100644 tests/networkxml2xmlout/nat-network-dns-txt-record.xml -- 1.7.3.2 From minovotn at redhat.com Fri Apr 1 10:45:52 2011 From: minovotn at redhat.com (Michal Novotny) Date: Fri, 1 Apr 2011 12:45:52 +0200 Subject: [libvirt] [PATCH v2 1/5] Network: Add TXT record support for virtual DNS service In-Reply-To: <1301654756-3920-1-git-send-email-minovotn@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> Message-ID: <1301654756-3920-2-git-send-email-minovotn@redhat.com> Make: passed Make check: passed Make syntax-check: passed Hi, this is the patch to add support for adding TXT records to the DNS service running on the virtual network. This has been tested on Fedora-14 i386 box and tests are also added to RelaxNG schema and test XML files. Since spaces are not allowed for the TXT records in DNS they are rejected and "TXT records in DNS doesn't support spaces" error message is being output to the user. It's been tested and checked/syntax-checked and everything was working fine. Also, the formatnetwork HTML document has been altered to include those information about new DNS tag. Michal Signed-off-by: Michal Novotny --- docs/formatnetwork.html.in | 24 ++++++- docs/schemas/network.rng | 12 +++ src/conf/network_conf.c | 71 ++++++++++++++++++++ src/conf/network_conf.h | 16 +++++ src/network/bridge_driver.c | 15 ++++- .../nat-network-dns-txt-record.xml | 24 +++++++ .../nat-network-dns-txt-record.xml | 24 +++++++ tests/networkxml2xmltest.c | 1 + 8 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 tests/networkxml2xmlin/nat-network-dns-txt-record.xml create mode 100644 tests/networkxml2xmlout/nat-network-dns-txt-record.xml diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in index c6969eb..5211ed2 100644 --- a/docs/formatnetwork.html.in +++ b/docs/formatnetwork.html.in @@ -108,7 +108,10 @@ The final set of elements define the addresses (IPv4 and/or IPv6, as well as MAC) to be assigned to the bridge device associated with the virtual network, and optionally enable DHCP - services. + services. The network creation also supports the TXT record in + the DNS to expose some information to the guest using this + record. This feature could be used in the similar way like DKIM + uses TXT records of DNS to expose public key.

@@ -120,6 +123,9 @@
             <host mac="00:16:3e:77:e2:ed" name="foo.example.com" ip="192.168.122.10" />
             <host mac="00:16:3e:3e:a9:1a" name="bar.example.com" ip="192.168.122.11" />
           </dhcp>
+          <dns>
+            <txt-record name="example" value="example value" />
+          </dns>
         </ip>
       </network>
@@ -199,6 +205,22 @@ element is used. The BOOTP options currently have to be the same for all address ranges and statically assigned addresses.Since 0.7.1 (server since 0.7.3). +
dns
Also within the ip element + there is an optional dns element. The presence of this element + enables configuration and exposal of records in the DNS service on the + virtual network. It will further contain one or more txt-record + elements. The dns element is supported for both IPv4 and IPv6 + networks. Since 0.9.1 +
+
txt-record
+
The txt-record element is the definition of TXT record for the + DNS service. There are two attributes that both have to be used for the TXT + record definition: name and value. The name + attribute doesn't support commas in it's value so the names with commas + will be rejected. This applies only to names of the TXT record and not values + since values (i.e. value contents) supports multiple values + separated by commas. + Since 0.9.1
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng index 6d01b06..e27dace 100644 --- a/docs/schemas/network.rng +++ b/docs/schemas/network.rng @@ -136,6 +136,18 @@ + + + + + + + + + + + diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index dcab9de..b7427d0 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -435,6 +435,60 @@ virNetworkDHCPRangeDefParseXML(const char *networkName, } static int +virNetworkDNSDefParseXML(virNetworkIpDefPtr def, + xmlNodePtr node) +{ + + xmlNodePtr cur; + int result = -1; + + if (VIR_ALLOC(def->dns)) + goto oom_error; + + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE && + xmlStrEqual(cur->name, BAD_CAST "txt-record")) { + char *name, *value; + + if (!(name = virXMLPropString(cur, "name"))) { + cur = cur->next; + continue; + } + if (!(value = virXMLPropString(cur, "value"))) { + VIR_FREE(name); + cur = cur->next; + continue; + } + + if (strchr(name, ' ') != NULL) { + virNetworkReportError(VIR_ERR_XML_DETAIL, + _("TXT record names in DNS doesn't support spaces")); + return -1; + } + + if (VIR_REALLOC_N(def->dns->txtrecords, def->dns->ntxtrecords + 1) < 0) + goto oom_error; + + def->dns->txtrecords[def->dns->ntxtrecords].name = strdup(name); + def->dns->txtrecords[def->dns->ntxtrecords].value = strdup(value); + def->dns->ntxtrecords++; + + VIR_FREE(name); + VIR_FREE(value); + } + + cur = cur->next; + } + + return 0; + +oom_error: + virReportOOMError(); + return result; +} + +static int virNetworkIPParseXML(const char *networkName, virNetworkIpDefPtr def, xmlNodePtr node, @@ -550,6 +604,12 @@ virNetworkIPParseXML(const char *networkName, goto error; } else if (cur->type == XML_ELEMENT_NODE && + xmlStrEqual(cur->name, BAD_CAST "dns")) { + result = virNetworkDNSDefParseXML(def, cur); + if (result) + goto error; + + } else if (cur->type == XML_ELEMENT_NODE && xmlStrEqual(cur->name, BAD_CAST "tftp")) { char *root; @@ -828,6 +888,17 @@ virNetworkIpDefFormat(virBufferPtr buf, virBufferAddLit(buf, " \n"); } + if ((def->dns != NULL) && (def->dns->ntxtrecords)) { + int ii; + + virBufferAddLit(buf, " \n"); + for (ii = 0 ; ii < def->dns->ntxtrecords ; ii++) { + virBufferVSprintf(buf, " \n", + def->dns->txtrecords[ii].name, + def->dns->txtrecords[ii].value); + } + virBufferAddLit(buf, " \n"); + } virBufferAddLit(buf, " \n"); diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 281124b..5f47595 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -57,6 +57,20 @@ struct _virNetworkDHCPHostDef { virSocketAddr ip; }; +typedef struct _virNetworkDNSTxtRecordsDef virNetworkDNSTxtRecordsDef; +typedef virNetworkDNSTxtRecordsDef *virNetworkDNSTxtRecordsDefPtr; +struct _virNetworkDNSTxtRecordsDef { + char *name; + char *value; +}; + +struct virNetworkDNSDef { + unsigned int ntxtrecords; + virNetworkDNSTxtRecordsDefPtr txtrecords; +} virNetworkDNSDef; + +typedef struct virNetworkDNSDef *virNetworkDNSDefPtr; + typedef struct _virNetworkIpDef virNetworkIpDef; typedef virNetworkIpDef *virNetworkIpDefPtr; struct _virNetworkIpDef { @@ -75,6 +89,8 @@ struct _virNetworkIpDef { unsigned int nranges; /* Zero or more dhcp ranges */ virNetworkDHCPRangeDefPtr ranges; + virNetworkDNSDefPtr dns; /* DNS related settings for DNSMasq */ + unsigned int nhosts; /* Zero or more dhcp hosts */ virNetworkDHCPHostDefPtr hosts; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index ea2bfd4..2e299f5 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -442,7 +442,6 @@ networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef, return 0; } - static int networkBuildDnsmasqArgv(virNetworkObjPtr network, virNetworkIpDefPtr ipdef, @@ -497,6 +496,20 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, if (network->def->forwardType == VIR_NETWORK_FORWARD_NONE) virCommandAddArg(cmd, "--dhcp-option=3"); + if (ipdef->dns != NULL) { + int i; + + for (i = 0; i < ipdef->dns->ntxtrecords; i++) { + virBuffer buf = VIR_BUFFER_INITIALIZER; + virBufferVSprintf(&buf, "%s,%s", + ipdef->dns->txtrecords[i].name, + ipdef->dns->txtrecords[i].value); + + virCommandAddArgPair(cmd, "--txt-record", virBufferContentAndReset(&buf)); + VIR_FREE(buf); + } + } + /* * --interface does not actually work with dnsmasq < 2.47, * due to DAD for ipv6 addresses on the interface. diff --git a/tests/networkxml2xmlin/nat-network-dns-txt-record.xml b/tests/networkxml2xmlin/nat-network-dns-txt-record.xml new file mode 100644 index 0000000..d3e795d --- /dev/null +++ b/tests/networkxml2xmlin/nat-network-dns-txt-record.xml @@ -0,0 +1,24 @@ + + default + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/networkxml2xmlout/nat-network-dns-txt-record.xml b/tests/networkxml2xmlout/nat-network-dns-txt-record.xml new file mode 100644 index 0000000..d3e795d --- /dev/null +++ b/tests/networkxml2xmlout/nat-network-dns-txt-record.xml @@ -0,0 +1,24 @@ + + default + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c index 7805548..beb00ef 100644 --- a/tests/networkxml2xmltest.c +++ b/tests/networkxml2xmltest.c @@ -90,6 +90,7 @@ mymain(int argc, char **argv) DO_TEST("nat-network"); DO_TEST("netboot-network"); DO_TEST("netboot-proxy-network"); + DO_TEST("nat-network-dns-txt-record"); return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } -- 1.7.3.2 From minovotn at redhat.com Fri Apr 1 10:45:53 2011 From: minovotn at redhat.com (Michal Novotny) Date: Fri, 1 Apr 2011 12:45:53 +0200 Subject: [libvirt] [PATCH v2 2/5] Network: Add regression tests for the command line arguments In-Reply-To: <1301654756-3920-1-git-send-email-minovotn@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> Message-ID: <1301654756-3920-3-git-send-email-minovotn@redhat.com> Make: passed Make check: passed Make syntax-check: passed Hi, this is the patch that is adding regression tests for the network bridge driver command-line arguments similar way it is done for QEMU driver. This is checking the built dnsmasq parameters (using networkBuildDhcpDaemonCommandLine() function) and comparing them to excepted arguments in the *.argv files. This has been tested and working fine. Michal Signed-off-by: Michal Novotny --- src/network/bridge_driver.c | 27 ++++- src/network/bridge_driver.h | 3 + tests/Makefile.am | 11 ++ tests/networkxml2argvdata/isolated-network.argv | 1 + tests/networkxml2argvdata/isolated-network.xml | 11 ++ .../nat-network-dns-txt-record.argv | 1 + .../nat-network-dns-txt-record.xml | 24 ++++ tests/networkxml2argvdata/nat-network.argv | 1 + tests/networkxml2argvdata/nat-network.xml | 21 ++++ tests/networkxml2argvdata/netboot-network.argv | 1 + tests/networkxml2argvdata/netboot-network.xml | 14 +++ .../networkxml2argvdata/netboot-proxy-network.argv | 1 + .../networkxml2argvdata/netboot-proxy-network.xml | 13 ++ tests/networkxml2argvdata/routed-network.argv | 1 + tests/networkxml2argvdata/routed-network.xml | 9 ++ tests/networkxml2argvtest.c | 119 ++++++++++++++++++++ 16 files changed, 255 insertions(+), 3 deletions(-) create mode 100644 tests/networkxml2argvdata/isolated-network.argv create mode 100644 tests/networkxml2argvdata/isolated-network.xml create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.xml create mode 100644 tests/networkxml2argvdata/nat-network.argv create mode 100644 tests/networkxml2argvdata/nat-network.xml create mode 100644 tests/networkxml2argvdata/netboot-network.argv create mode 100644 tests/networkxml2argvdata/netboot-network.xml create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.argv create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.xml create mode 100644 tests/networkxml2argvdata/routed-network.argv create mode 100644 tests/networkxml2argvdata/routed-network.xml create mode 100644 tests/networkxml2argvtest.c diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 2e299f5..b6ce39d 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -613,11 +613,11 @@ cleanup: return ret; } -static int -networkStartDhcpDaemon(virNetworkObjPtr network) +int +networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, virCommandPtr *cmdout, + char *pidfile) { virCommandPtr cmd = NULL; - char *pidfile = NULL; int ret = -1, err, ii; virNetworkIpDefPtr ipdef; @@ -666,6 +666,27 @@ networkStartDhcpDaemon(virNetworkObjPtr network) goto cleanup; } + if (cmdout) + *cmdout = cmd; + + ret = 0; +cleanup: + if (ret != 0) + virCommandFree(cmd); + return ret; +} + +static int +networkStartDhcpDaemon(virNetworkObjPtr network) +{ + virCommandPtr cmd = NULL; + char *pidfile = NULL; + int ret = -1; + + ret = networkBuildDhcpDaemonCommandLine(network, &cmd, pidfile); + if (ret != 0) + goto cleanup; + if (virCommandRun(cmd, NULL) < 0) goto cleanup; diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h index 32d2ae7..8d82b67 100644 --- a/src/network/bridge_driver.h +++ b/src/network/bridge_driver.h @@ -28,7 +28,10 @@ # include # include "internal.h" +# include "network_conf.h" +# include "command.h" int networkRegister(void); +int networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, virCommandPtr *cmdout, char *pidfile); #endif /* __VIR_NETWORK__DRIVER_H */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 5896442..a3f8d00 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -50,6 +50,7 @@ EXTRA_DIST = \ networkschematest \ networkxml2xmlin \ networkxml2xmlout \ + networkxml2argvdata \ nodedevschemadata \ nodedevschematest \ nodeinfodata \ @@ -104,6 +105,8 @@ endif check_PROGRAMS += networkxml2xmltest +check_PROGRAMS += networkxml2argvtest + check_PROGRAMS += nwfilterxml2xmltest check_PROGRAMS += storagevolxml2xmltest storagepoolxml2xmltest @@ -191,6 +194,8 @@ endif TESTS += networkxml2xmltest +TESTS += networkxml2argvtest + TESTS += storagevolxml2xmltest storagepoolxml2xmltest TESTS += nodedevxml2xmltest @@ -308,6 +313,12 @@ networkxml2xmltest_SOURCES = \ testutils.c testutils.h networkxml2xmltest_LDADD = $(LDADDS) +networkxml2argvtest_SOURCES = \ + networkxml2argvtest.c \ + ../src/network/bridge_driver.c network/bridge_driver.h \ + testutils.c testutils.h +networkxml2argvtest_LDADD = $(LDADDS) + nwfilterxml2xmltest_SOURCES = \ nwfilterxml2xmltest.c \ testutils.c testutils.h diff --git a/tests/networkxml2argvdata/isolated-network.argv b/tests/networkxml2argvdata/isolated-network.argv new file mode 100644 index 0000000..1c173db --- /dev/null +++ b/tests/networkxml2argvdata/isolated-network.argv @@ -0,0 +1 @@ +/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/private.pid --conf-file= --except-interface lo --dhcp-option=3 --listen-address 192.168.152.1 --dhcp-range 192.168.152.2,192.168.152.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/private.leases --dhcp-lease-max=253 --dhcp-no-override diff --git a/tests/networkxml2argvdata/isolated-network.xml b/tests/networkxml2argvdata/isolated-network.xml new file mode 100644 index 0000000..cc320a9 --- /dev/null +++ b/tests/networkxml2argvdata/isolated-network.xml @@ -0,0 +1,11 @@ + + private + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + + + diff --git a/tests/networkxml2argvdata/nat-network-dns-txt-record.argv b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv new file mode 100644 index 0000000..55dcf02 --- /dev/null +++ b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv @@ -0,0 +1 @@ +/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/default.pid --conf-file= --except-interface lo --txt-record=example,example value --listen-address 192.168.122.1 --listen-address 192.168.123.1 --listen-address 2001:db8:ac10:fe01::1 --listen-address 2001:db8:ac10:fd01::1 --listen-address 10.24.10.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases --dhcp-lease-max=253 --dhcp-no-override --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile diff --git a/tests/networkxml2argvdata/nat-network-dns-txt-record.xml b/tests/networkxml2argvdata/nat-network-dns-txt-record.xml new file mode 100644 index 0000000..d3e795d --- /dev/null +++ b/tests/networkxml2argvdata/nat-network-dns-txt-record.xml @@ -0,0 +1,24 @@ + + default + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/networkxml2argvdata/nat-network.argv b/tests/networkxml2argvdata/nat-network.argv new file mode 100644 index 0000000..95ee6d9 --- /dev/null +++ b/tests/networkxml2argvdata/nat-network.argv @@ -0,0 +1 @@ +/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/default.pid --conf-file= --except-interface lo --listen-address 192.168.122.1 --listen-address 192.168.123.1 --listen-address 2001:db8:ac10:fe01::1 --listen-address 2001:db8:ac10:fd01::1 --listen-address 10.24.10.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases --dhcp-lease-max=253 --dhcp-no-override --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile diff --git a/tests/networkxml2argvdata/nat-network.xml b/tests/networkxml2argvdata/nat-network.xml new file mode 100644 index 0000000..eb71d9e --- /dev/null +++ b/tests/networkxml2argvdata/nat-network.xml @@ -0,0 +1,21 @@ + + default + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + + + + + + + + + + + + + diff --git a/tests/networkxml2argvdata/netboot-network.argv b/tests/networkxml2argvdata/netboot-network.argv new file mode 100644 index 0000000..36c2360 --- /dev/null +++ b/tests/networkxml2argvdata/netboot-network.argv @@ -0,0 +1 @@ +/usr/sbin/dnsmasq --strict-order --bind-interfaces --domain example.com --pid-file=/var/run/libvirt/network/netboot.pid --conf-file= --except-interface lo --listen-address 192.168.122.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/netboot.leases --dhcp-lease-max=253 --dhcp-no-override --enable-tftp --tftp-root /var/lib/tftproot --dhcp-boot pxeboot.img diff --git a/tests/networkxml2argvdata/netboot-network.xml b/tests/networkxml2argvdata/netboot-network.xml new file mode 100644 index 0000000..b8a4d99 --- /dev/null +++ b/tests/networkxml2argvdata/netboot-network.xml @@ -0,0 +1,14 @@ + + netboot + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + + + + + + diff --git a/tests/networkxml2argvdata/netboot-proxy-network.argv b/tests/networkxml2argvdata/netboot-proxy-network.argv new file mode 100644 index 0000000..da97b72 --- /dev/null +++ b/tests/networkxml2argvdata/netboot-proxy-network.argv @@ -0,0 +1 @@ +/usr/sbin/dnsmasq --strict-order --bind-interfaces --domain example.com --pid-file=/var/run/libvirt/network/netboot.pid --conf-file= --except-interface lo --listen-address 192.168.122.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/netboot.leases --dhcp-lease-max=253 --dhcp-no-override --dhcp-boot pxeboot.img,,10.20.30.40 diff --git a/tests/networkxml2argvdata/netboot-proxy-network.xml b/tests/networkxml2argvdata/netboot-proxy-network.xml new file mode 100644 index 0000000..e11c50b --- /dev/null +++ b/tests/networkxml2argvdata/netboot-proxy-network.xml @@ -0,0 +1,13 @@ + + netboot + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + + + + + diff --git a/tests/networkxml2argvdata/routed-network.argv b/tests/networkxml2argvdata/routed-network.argv new file mode 100644 index 0000000..443087c --- /dev/null +++ b/tests/networkxml2argvdata/routed-network.argv @@ -0,0 +1 @@ +/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/local.pid --conf-file= --except-interface lo --listen-address 192.168.122.1 diff --git a/tests/networkxml2argvdata/routed-network.xml b/tests/networkxml2argvdata/routed-network.xml new file mode 100644 index 0000000..3aa8109 --- /dev/null +++ b/tests/networkxml2argvdata/routed-network.xml @@ -0,0 +1,9 @@ + + local + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + diff --git a/tests/networkxml2argvtest.c b/tests/networkxml2argvtest.c new file mode 100644 index 0000000..e3a8bb4 --- /dev/null +++ b/tests/networkxml2argvtest.c @@ -0,0 +1,119 @@ +#include + +#include +#include +#include +#include + +#include +#include + +#include "internal.h" +#include "testutils.h" +#include "network_conf.h" +#include "command.h" +#include "memory.h" +#include "network/bridge_driver.h" + +static char *progname; +static char *abs_srcdir; + +#define MAX_FILE 4096 + + +static int testCompareXMLToArgvFiles(const char *inxml, const char *outargv) { + char inXmlData[MAX_FILE]; + char *inXmlPtr = &(inXmlData[0]); + char outArgvData[MAX_FILE]; + char *outArgvPtr = &(outArgvData[0]); + char *actual = NULL; + int ret = -1; + virNetworkDefPtr dev = NULL; + virNetworkObjPtr obj = NULL; + virCommandPtr cmd = NULL; + char *pidfile = NULL; + + if (virtTestLoadFile(inxml, &inXmlPtr, MAX_FILE) < 0) + goto fail; + + if (virtTestLoadFile(outargv, &outArgvPtr, MAX_FILE) < 0) + goto fail; + + if (!(dev = virNetworkDefParseString(inXmlData))) + goto fail; + + if (VIR_ALLOC(obj) < 0) + goto fail; + + obj->def = dev; + + if (networkBuildDhcpDaemonCommandLine(obj, &cmd, pidfile) != 0) + goto fail; + + if (!(actual = virCommandToString(cmd))) + goto fail; + + /* There is a new line character but syntax-check would complain + * about this in argv files so just trim it now + */ + outArgvData[ strlen(outArgvData) - 1] = 0; + + if (STRNEQ(outArgvData, actual)) { + virtTestDifference(stderr, outArgvData, actual); + goto fail; + } + + ret = 0; + + fail: + free(actual); + VIR_FREE(pidfile); + virCommandFree(cmd); + virNetworkObjFree(obj); + return ret; +} + +static int testCompareXMLToArgvHelper(const void *data) { + char inxml[PATH_MAX]; + char outargv[PATH_MAX]; + snprintf(inxml, PATH_MAX, "%s/networkxml2argvdata/%s.xml", + abs_srcdir, (const char*)data); + snprintf(outargv, PATH_MAX, "%s/networkxml2argvdata/%s.argv", + abs_srcdir, (const char*)data); + return testCompareXMLToArgvFiles(inxml, outargv); +} + + +static int +mymain(int argc, char **argv) +{ + int ret = 0; + char cwd[PATH_MAX]; + + progname = argv[0]; + + if (argc > 1) { + fprintf(stderr, "Usage: %s\n", progname); + return (EXIT_FAILURE); + } + + abs_srcdir = getenv("abs_srcdir"); + if (!abs_srcdir) + abs_srcdir = getcwd(cwd, sizeof(cwd)); + +#define DO_TEST(name) \ + if (virtTestRun("Network XML-2-Argv " name, \ + 1, testCompareXMLToArgvHelper, (name)) < 0) \ + ret = -1 + + DO_TEST("isolated-network"); + DO_TEST("routed-network"); + DO_TEST("nat-network"); + DO_TEST("netboot-network"); + DO_TEST("netboot-proxy-network"); + DO_TEST("nat-network-dns-txt-record"); + + return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + +VIRT_TEST_MAIN(mymain) -- 1.7.3.2 From minovotn at redhat.com Fri Apr 1 10:45:54 2011 From: minovotn at redhat.com (Michal Novotny) Date: Fri, 1 Apr 2011 12:45:54 +0200 Subject: [libvirt] [PATCH v2 3/5] Network: Move dnsmasqContext creation to networkSaveDnsmasqHostsfile() and pass to dnsmasq only if applicable In-Reply-To: <1301654756-3920-1-git-send-email-minovotn@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> Message-ID: <1301654756-3920-4-git-send-email-minovotn@redhat.com> Make: passed Make check: passed Make syntax-check: passed Hi, this is the patch to move the dnsmasqContext creation to the networkSaveDnsmasqHostsfile() function and also it passes the hosts-file and addn-hosts to the file only if applicable, i.e. if it's already set. Originally I wanted to call the DhcpHostsfile and AddnHostsfile creation on the first call to dnsmasqAddDhcpHost/dnsmasqAddHost however that way I would have kept track of the path name to be generated which would require storing network name and config directory somewhere in the structure and that's why I changed it to simple approach used in this patch. Michal Signed-off-by: Michal Novotny --- src/network/bridge_driver.c | 38 +++++++++++++++++++++----------------- 1 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index b6ce39d..41b14f9 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -420,13 +420,20 @@ networkShutdown(void) { } -static int +static dnsmasqContext* networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef, - dnsmasqContext *dctx, + char *name, bool force) { unsigned int i; + dnsmasqContext *dctx = dnsmasqContextNew(name, + DNSMASQ_STATE_DIR); + if (dctx == NULL) { + virReportOOMError(); + goto cleanup; + } + if (! force && virFileExists(dctx->hostsfile->path)) return 0; @@ -437,9 +444,14 @@ networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef, } if (dnsmasqSave(dctx) < 0) - return -1; + goto cleanup; - return 0; + return dctx; + +cleanup: + dnsmasqContextFree(dctx); + + return NULL; } static int @@ -451,6 +463,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, int nbleases = 0; int ii; virNetworkIpDefPtr tmpipdef; + dnsmasqContext *dctx = NULL; /* * NB, be careful about syntax for dnsmasq options in long format. @@ -572,18 +585,11 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, if (ipdef->nranges || ipdef->nhosts) virCommandAddArg(cmd, "--dhcp-no-override"); - if (ipdef->nhosts > 0) { - dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, - DNSMASQ_STATE_DIR); - if (dctx == NULL) { - virReportOOMError(); - goto cleanup; - } - - if (networkSaveDnsmasqHostsfile(ipdef, dctx, false) == 0) { + if ((dctx = networkSaveDnsmasqHostsfile(ipdef, network->def->name, false))) { + if (dctx->hostsfile->nhosts) virCommandAddArgPair(cmd, "--dhcp-hostsfile", dctx->hostsfile->path); - } + dnsmasqContextFree(dctx); } @@ -2203,11 +2209,9 @@ static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) { } } if (ipv4def) { - dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR); + dnsmasqContext* dctx = networkSaveDnsmasqHostsfile(ipv4def, network->def->name, true); if (dctx == NULL) goto cleanup; - - networkSaveDnsmasqHostsfile(ipv4def, dctx, true); dnsmasqContextFree(dctx); } -- 1.7.3.2 From minovotn at redhat.com Fri Apr 1 10:45:56 2011 From: minovotn at redhat.com (Michal Novotny) Date: Fri, 1 Apr 2011 12:45:56 +0200 Subject: [libvirt] [PATCH v2 5/5] Network: Add support for DNS hosts definition to the network XML In-Reply-To: <1301654756-3920-1-git-send-email-minovotn@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> Message-ID: <1301654756-3920-6-git-send-email-minovotn@redhat.com> Make: passed Make check: passed Make syntax-check: passed Hi, this is the patch to add support for DNS hosts definition in the network XML description to generate the the hosts file. This patch uses the addnhosts* APIs implemented to the src/util/dnsmasq.c by part 2 of this patch series. Also, tests for the XML to XML definition and command-line regression tests has been added. Michal Signed-off-by: Michal Novotny --- docs/formatnetwork.html.in | 7 + docs/schemas/network.rng | 8 ++ src/conf/network_conf.c | 128 ++++++++++++++++++-- src/conf/network_conf.h | 9 ++ src/network/bridge_driver.c | 20 ++- .../networkxml2argvdata/nat-network-dns-hosts.argv | 1 + .../networkxml2argvdata/nat-network-dns-hosts.xml | 19 +++ tests/networkxml2argvtest.c | 1 + tests/networkxml2xmlin/nat-network-dns-hosts.xml | 27 ++++ tests/networkxml2xmlout/nat-network-dns-hosts.xml | 27 ++++ tests/networkxml2xmltest.c | 1 + 11 files changed, 234 insertions(+), 14 deletions(-) create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.xml create mode 100644 tests/networkxml2xmlin/nat-network-dns-hosts.xml create mode 100644 tests/networkxml2xmlout/nat-network-dns-hosts.xml diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in index 5211ed2..5d18ed9 100644 --- a/docs/formatnetwork.html.in +++ b/docs/formatnetwork.html.in @@ -222,6 +222,13 @@ separated by commas. Since 0.9.1 +
host
+
The host element is the definition of DNS hosts to be passed + to the DNS service. The IP address is identified by the ip attribute + and the names for the IP addresses are identified in the hostname + subelements of the host element. + Since 0.9.1 +

Example configuration

diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng index e27dace..05066a5 100644 --- a/docs/schemas/network.rng +++ b/docs/schemas/network.rng @@ -146,6 +146,14 @@ + + + + + + + + diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index b7427d0..1f88649 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -435,6 +435,53 @@ virNetworkDHCPRangeDefParseXML(const char *networkName, } static int +virNetworkDNSHostsDefParseXML(virNetworkIpDefPtr def, + xmlNodePtr node, + virSocketAddr ip) +{ + xmlNodePtr cur; + int result = -1; + + if (def->dns->hosts == NULL) { + if (VIR_ALLOC(def->dns->hosts) < 0) + goto oom_error; + def->dns->nhosts = 0; + } + + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE && + xmlStrEqual(cur->name, BAD_CAST "hostname")) { + if (cur->children != NULL) { + char *hostname; + + hostname = strdup((char *)cur->children->content); + + if (VIR_REALLOC_N(def->dns->hosts, def->dns->nhosts + 1) < 0) { + VIR_FREE(hostname); + result = -1; + goto oom_error; + } + + def->dns->hosts[def->dns->nhosts].name = strdup(hostname); + def->dns->hosts[def->dns->nhosts].ip = ip; + def->dns->nhosts++; + + VIR_FREE(hostname); + } + } + + cur = cur->next; + } + + return 0; + +oom_error: + virReportOOMError(); + return result; +} + +static int virNetworkDNSDefParseXML(virNetworkIpDefPtr def, xmlNodePtr node) { @@ -476,6 +523,27 @@ virNetworkDNSDefParseXML(virNetworkIpDefPtr def, VIR_FREE(name); VIR_FREE(value); + } else if (cur->type == XML_ELEMENT_NODE && + xmlStrEqual(cur->name, BAD_CAST "host")) { + char *ip; + virSocketAddr inaddr; + memset(&inaddr, 0, sizeof(inaddr)); + + if (!(ip = virXMLPropString(cur, "ip"))) { + cur = cur->next; + continue; + } + if ((ip == NULL) || + (virSocketParseAddr(ip, &inaddr, AF_UNSPEC) < 0)) { + virNetworkReportError(VIR_ERR_XML_DETAIL, + _("Missing IP address in DNS host definition")); + VIR_FREE(ip); + goto error; + } + VIR_FREE(ip); + result = virNetworkDNSHostsDefParseXML(def, cur, inaddr); + if (result) + goto error; } cur = cur->next; @@ -485,6 +553,7 @@ virNetworkDNSDefParseXML(virNetworkIpDefPtr def, oom_error: virReportOOMError(); +error: return result; } @@ -888,17 +957,60 @@ virNetworkIpDefFormat(virBufferPtr buf, virBufferAddLit(buf, " \n"); } - if ((def->dns != NULL) && (def->dns->ntxtrecords)) { - int ii; - + if (def->dns != NULL) { virBufferAddLit(buf, " \n"); - for (ii = 0 ; ii < def->dns->ntxtrecords ; ii++) { - virBufferVSprintf(buf, " \n", - def->dns->txtrecords[ii].name, - def->dns->txtrecords[ii].value); + + if (def->dns->ntxtrecords) { + int ii; + + for (ii = 0 ; ii < def->dns->ntxtrecords; ii++) { + virBufferVSprintf(buf, " \n", + def->dns->txtrecords[ii].name, + def->dns->txtrecords[ii].value); + } + } + if (def->dns->nhosts) { + int ii, j; + char **iplist = NULL; + int iplist_size = 0; + bool in_list; + + if (VIR_ALLOC(iplist) < 0) + goto error; + + for (ii = 0 ; ii < def->dns->nhosts; ii++) { + char *ip = virSocketFormatAddr(&def->dns->hosts[ii].ip); + in_list = false; + for (j = 0; j < iplist_size; j++) + if (STREQ(iplist[j], ip)) + in_list = true; + + if (!in_list) { + virBufferVSprintf(buf, " \n", ip); + + for (j = 0 ; j < def->dns->nhosts; j++) { + char *thisip = virSocketFormatAddr(&def->dns->hosts[j].ip); + if (STREQ(ip, thisip)) + virBufferVSprintf(buf, " %s\n", + def->dns->hosts[j].name); + } + virBufferVSprintf(buf, " \n"); + + if (VIR_REALLOC_N(iplist, iplist_size + 1) < 0) + goto error; + + iplist[iplist_size] = strdup(ip); + iplist_size++; + } + } + + for (j = 0; j < iplist_size; j++) + VIR_FREE(iplist[j]); + VIR_FREE(iplist); } + virBufferAddLit(buf, " \n"); - } + } virBufferAddLit(buf, " \n"); diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 5f47595..305ef0f 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -64,9 +64,18 @@ struct _virNetworkDNSTxtRecordsDef { char *value; }; +struct virNetworkDNSHostsDef { + virSocketAddr ip; + char *name; +} virNetworkDNSHostsDef; + +typedef struct virNetworkDNSHostsDef *virNetworkDNSHostsDefPtr; + struct virNetworkDNSDef { unsigned int ntxtrecords; + unsigned int nhosts; virNetworkDNSTxtRecordsDefPtr txtrecords; + virNetworkDNSHostsDefPtr hosts; } virNetworkDNSDef; typedef struct virNetworkDNSDef *virNetworkDNSDefPtr; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 4ad3143..99a61b0 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -434,13 +434,20 @@ networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef, goto cleanup; } - if (! force && virFileExists(dctx->hostsfile->path)) - return 0; + if (!(! force && virFileExists(dctx->hostsfile->path))) { + for (i = 0; i < ipdef->nhosts; i++) { + virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]); + if ((host->mac) && VIR_SOCKET_HAS_ADDR(&host->ip)) + dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name); + } + } - for (i = 0; i < ipdef->nhosts; i++) { - virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]); - if ((host->mac) && VIR_SOCKET_HAS_ADDR(&host->ip)) - dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name); + if (ipdef->dns) { + for (i = 0; i < ipdef->dns->nhosts; i++) { + virNetworkDNSHostsDefPtr host = &(ipdef->dns->hosts[i]); + if (VIR_SOCKET_HAS_ADDR(&host->ip)) + dnsmasqAddHost(dctx, &host->ip, host->name); + } } if (dnsmasqSave(dctx) < 0) @@ -589,6 +596,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, if (dctx->hostsfile->nhosts) virCommandAddArgPair(cmd, "--dhcp-hostsfile", dctx->hostsfile->path); + VIR_DEBUG("ADDN HOSTS: %d => %p", dctx->addnhostsfile->nhosts, ipdef->dns); if (dctx->addnhostsfile->nhosts) virCommandAddArgPair(cmd, "--addn-hosts", dctx->addnhostsfile->path); diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.argv b/tests/networkxml2argvdata/nat-network-dns-hosts.argv new file mode 100644 index 0000000..99dc724 --- /dev/null +++ b/tests/networkxml2argvdata/nat-network-dns-hosts.argv @@ -0,0 +1 @@ +/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/default.pid --conf-file= --except-interface lo --listen-address 192.168.122.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases --dhcp-lease-max=253 --dhcp-no-override --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile --addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.xml b/tests/networkxml2argvdata/nat-network-dns-hosts.xml new file mode 100644 index 0000000..35ee151 --- /dev/null +++ b/tests/networkxml2argvdata/nat-network-dns-hosts.xml @@ -0,0 +1,19 @@ + + default + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + + + + + + host + gateway + + + + diff --git a/tests/networkxml2argvtest.c b/tests/networkxml2argvtest.c index e3a8bb4..ce09206 100644 --- a/tests/networkxml2argvtest.c +++ b/tests/networkxml2argvtest.c @@ -112,6 +112,7 @@ mymain(int argc, char **argv) DO_TEST("netboot-network"); DO_TEST("netboot-proxy-network"); DO_TEST("nat-network-dns-txt-record"); + DO_TEST("nat-network-dns-hosts"); return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } diff --git a/tests/networkxml2xmlin/nat-network-dns-hosts.xml b/tests/networkxml2xmlin/nat-network-dns-hosts.xml new file mode 100644 index 0000000..fe545cf --- /dev/null +++ b/tests/networkxml2xmlin/nat-network-dns-hosts.xml @@ -0,0 +1,27 @@ + + default + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + + + + + + host + gateway + + + + + + + + + + + + diff --git a/tests/networkxml2xmlout/nat-network-dns-hosts.xml b/tests/networkxml2xmlout/nat-network-dns-hosts.xml new file mode 100644 index 0000000..fe545cf --- /dev/null +++ b/tests/networkxml2xmlout/nat-network-dns-hosts.xml @@ -0,0 +1,27 @@ + + default + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + + + + + + host + gateway + + + + + + + + + + + + diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c index beb00ef..f5c5715 100644 --- a/tests/networkxml2xmltest.c +++ b/tests/networkxml2xmltest.c @@ -91,6 +91,7 @@ mymain(int argc, char **argv) DO_TEST("netboot-network"); DO_TEST("netboot-proxy-network"); DO_TEST("nat-network-dns-txt-record"); + DO_TEST("nat-network-dns-hosts"); return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } -- 1.7.3.2 From minovotn at redhat.com Fri Apr 1 10:45:55 2011 From: minovotn at redhat.com (Michal Novotny) Date: Fri, 1 Apr 2011 12:45:55 +0200 Subject: [libvirt] [PATCH v2 4/5] Network: Add additional hosts internal infrastructure In-Reply-To: <1301654756-3920-1-git-send-email-minovotn@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> Message-ID: <1301654756-3920-5-git-send-email-minovotn@redhat.com> Hi, this is the patch to introduce the internal infrastructure for additional hosts for network bridge driver using the addnhosts* API functions. This is necessary for next part of the patch to support DNS hosts definition in the network XML description. Michal Signed-off-by: Michal Novotny --- src/libvirt_private.syms | 1 + src/network/bridge_driver.c | 3 + src/util/dnsmasq.c | 266 ++++++++++++++++++++++++++++++++++++++++++- src/util/dnsmasq.h | 22 ++++- 4 files changed, 287 insertions(+), 5 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 65a86d3..73c3f77 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -186,6 +186,7 @@ virUnrefStream; # dnsmasq.h dnsmasqAddDhcpHost; +dnsmasqAddHost; dnsmasqContextFree; dnsmasqContextNew; dnsmasqDelete; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 41b14f9..4ad3143 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -589,6 +589,9 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, if (dctx->hostsfile->nhosts) virCommandAddArgPair(cmd, "--dhcp-hostsfile", dctx->hostsfile->path); + if (dctx->addnhostsfile->nhosts) + virCommandAddArgPair(cmd, "--addn-hosts", + dctx->addnhostsfile->path); dnsmasqContextFree(dctx); } diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c index be230e1..fee3b90 100644 --- a/src/util/dnsmasq.c +++ b/src/util/dnsmasq.c @@ -48,6 +48,7 @@ #define VIR_FROM_THIS VIR_FROM_NETWORK #define DNSMASQ_HOSTSFILE_SUFFIX "hostsfile" +#define DNSMASQ_ADDNHOSTSFILE_SUFFIX "addnhosts" static void dhcphostFree(dnsmasqDhcpHost *host) @@ -56,6 +57,231 @@ dhcphostFree(dnsmasqDhcpHost *host) } static void +addnhostFree(dnsmasqAddnHost *host) +{ + VIR_FREE(host->hostnames); + VIR_FREE(host->ip); +} + +static void +addnhostsFree(dnsmasqAddnHostsfile *addnhostsfile) +{ + unsigned int i; + + if (addnhostsfile->hosts) { + for (i = 0; i < addnhostsfile->nhosts; i++) + addnhostFree(&addnhostsfile->hosts[i]); + + VIR_FREE(addnhostsfile->hosts); + + addnhostsfile->nhosts = 0; + } + + VIR_FREE(addnhostsfile->path); + + VIR_FREE(addnhostsfile); +} + +static int +addnhostsAdd(dnsmasqAddnHostsfile *addnhostsfile, + virSocketAddr *ip, + const char *name) +{ + char *ipstr = NULL; + int idx = -1; + int i; + + if (!(ipstr = virSocketFormatAddr(ip))) + return -1; + + for (i = 0; i < addnhostsfile->nhosts; i++) { + if (STREQ((const char *)addnhostsfile->hosts[i].ip, (const char *)ipstr)) { + idx = i; + break; + } + } + + if (idx < 0) { + if (VIR_REALLOC_N(addnhostsfile->hosts, addnhostsfile->nhosts + 1) < 0) + goto alloc_error; + + idx = addnhostsfile->nhosts; + if (VIR_ALLOC(addnhostsfile->hosts[idx].hostnames) < 0) + goto alloc_error; + + if (virAsprintf(&addnhostsfile->hosts[idx].ip, "%s", ipstr) < 0) + goto alloc_error; + + addnhostsfile->hosts[idx].nhostnames = 0; + addnhostsfile->nhosts++; + } + + if (VIR_REALLOC_N(addnhostsfile->hosts[idx].hostnames, addnhostsfile->hosts[idx].nhostnames + 1) < 0) + goto alloc_error; + + if (virAsprintf(&addnhostsfile->hosts[idx].hostnames[addnhostsfile->hosts[idx].nhostnames], "%s", name) < 0) + goto alloc_error; + + VIR_FREE(ipstr); + + addnhostsfile->hosts[idx].nhostnames++; + + return 0; + + alloc_error: + virReportOOMError(); + VIR_FREE(ipstr); + return -1; +} + +static dnsmasqAddnHostsfile * +addnhostsNew(const char *name, + const char *config_dir) +{ + int err; + dnsmasqAddnHostsfile *addnhostsfile; + + if (VIR_ALLOC(addnhostsfile) < 0) { + virReportOOMError(); + return NULL; + } + + addnhostsfile->hosts = NULL; + addnhostsfile->nhosts = 0; + + if (virAsprintf(&addnhostsfile->path, "%s/%s.%s", config_dir, name, + DNSMASQ_ADDNHOSTSFILE_SUFFIX) < 0) { + virReportOOMError(); + goto error; + } + + if ((err = virFileMakePath(config_dir))) { + virReportSystemError(err, _("cannot create config directory '%s'"), + config_dir); + goto error; + } + + return addnhostsfile; + + error: + addnhostsFree(addnhostsfile); + return NULL; +} + +static int +addnhostsWrite(const char *path, + dnsmasqAddnHost *hosts, + unsigned int nhosts) +{ + char *tmp; + FILE *f; + bool istmp = true; + unsigned int i, ii; + int rc = 0; + + if (nhosts == 0) + return rc; + + if (virAsprintf(&tmp, "%s.new", path) < 0) + return ENOMEM; + + if (!(f = fopen(tmp, "w"))) { + istmp = false; + if (!(f = fopen(path, "w"))) { + rc = errno; + goto cleanup; + } + } + + for (i = 0; i < nhosts; i++) { + if (fputs(hosts[i].ip, f) == EOF || fputc('\t', f) == EOF) { + rc = errno; + VIR_FORCE_FCLOSE(f); + + if (istmp) + unlink(tmp); + + goto cleanup; + } + + for (ii = 0; ii < hosts[i].nhostnames; ii++) { + if (fputs(hosts[i].hostnames[ii], f) == EOF || fputc('\t', f) == EOF) { + rc = errno; + VIR_FORCE_FCLOSE(f); + + if (istmp) + unlink(tmp); + + goto cleanup; + } + } + + if (fputc('\n', f) == EOF) { + rc = errno; + VIR_FORCE_FCLOSE(f); + + if (istmp) + unlink(tmp); + + goto cleanup; + } + } + + if (VIR_FCLOSE(f) == EOF) { + rc = errno; + goto cleanup; + } + + if (istmp) { + if (rename(tmp, path) < 0) { + rc = errno; + unlink(tmp); + goto cleanup; + } + + if (unlink(tmp) < 0) { + rc = errno; + goto cleanup; + } + } + + cleanup: + VIR_FREE(tmp); + + return rc; +} + +static int +addnhostsSave(dnsmasqAddnHostsfile *addnhostsfile) +{ + int err = addnhostsWrite(addnhostsfile->path, addnhostsfile->hosts, + addnhostsfile->nhosts); + + if (err < 0) { + virReportSystemError(err, _("cannot write config file '%s'"), + addnhostsfile->path); + return -1; + } + + return 0; +} + +static int +addnhostsDelete(dnsmasqAddnHostsfile *addnhostsfile) +{ + if (!virFileExists(addnhostsfile->path)) + return 0; + + if (unlink(addnhostsfile->path) < 0) { + virReportSystemError(errno, _("cannot remove config file '%s'"), + addnhostsfile->path); + return -1; + } + + return 0; +} + +static void hostsfileFree(dnsmasqHostsfile *hostsfile) { unsigned int i; @@ -255,6 +481,8 @@ dnsmasqContextNew(const char *network_name, if (!(ctx->hostsfile = hostsfileNew(network_name, config_dir))) goto error; + if (!(ctx->addnhostsfile = addnhostsNew(network_name, config_dir))) + goto error; return ctx; @@ -277,6 +505,8 @@ dnsmasqContextFree(dnsmasqContext *ctx) if (ctx->hostsfile) hostsfileFree(ctx->hostsfile); + if (ctx->addnhostsfile) + addnhostsFree(ctx->addnhostsfile); VIR_FREE(ctx); } @@ -300,6 +530,24 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx, hostsfileAdd(ctx->hostsfile, mac, ip, name); } +/* + * dnsmasqAddHost: + * @ctx: pointer to the dnsmasq context for each network + * @ip: pointer to the socket address contains ip of the host + * @name: pointer to the string contains hostname of the host + * + * Add additional host entry. + */ + +void +dnsmasqAddHost(dnsmasqContext *ctx, + virSocketAddr *ip, + const char *name) +{ + if (ctx->addnhostsfile) + addnhostsAdd(ctx->addnhostsfile, ip, name); +} + /** * dnsmasqSave: * @ctx: pointer to the dnsmasq context for each network @@ -309,10 +557,15 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx, int dnsmasqSave(const dnsmasqContext *ctx) { + int ret1 = 0; + int ret2 = 0; + if (ctx->hostsfile) - return hostsfileSave(ctx->hostsfile); + ret1 = hostsfileSave(ctx->hostsfile); + if (ctx->addnhostsfile) + ret2 = addnhostsSave(ctx->addnhostsfile); - return 0; + return ((ret1 == 0) && (ret2 == 0)) ? 0 : -1; } @@ -325,10 +578,15 @@ dnsmasqSave(const dnsmasqContext *ctx) int dnsmasqDelete(const dnsmasqContext *ctx) { + int ret1 = 0; + int ret2 = 0; + if (ctx->hostsfile) - return hostsfileDelete(ctx->hostsfile); + ret1 = hostsfileDelete(ctx->hostsfile); + if (ctx->addnhostsfile) + ret2 = addnhostsDelete(ctx->addnhostsfile); - return 0; + return ((ret1 == 0) && (ret2 == 0)) ? 0 : -1; } /** diff --git a/src/util/dnsmasq.h b/src/util/dnsmasq.h index 02a961f..3f6320a 100644 --- a/src/util/dnsmasq.h +++ b/src/util/dnsmasq.h @@ -44,7 +44,24 @@ typedef struct typedef struct { - dnsmasqHostsfile *hostsfile; + unsigned int nhostnames; + char *ip; + char **hostnames; + +} dnsmasqAddnHost; + +typedef struct +{ + unsigned int nhosts; + dnsmasqAddnHost *hosts; + + char *path; /* Absolute path of dnsmasq's hostsfile. */ +} dnsmasqAddnHostsfile; + +typedef struct +{ + dnsmasqHostsfile *hostsfile; + dnsmasqAddnHostsfile *addnhostsfile; } dnsmasqContext; dnsmasqContext * dnsmasqContextNew(const char *network_name, @@ -54,6 +71,9 @@ void dnsmasqAddDhcpHost(dnsmasqContext *ctx, const char *mac, virSocketAddr *ip, const char *name); +void dnsmasqAddHost(dnsmasqContext *ctx, + virSocketAddr *ip, + const char *name); int dnsmasqSave(const dnsmasqContext *ctx); int dnsmasqDelete(const dnsmasqContext *ctx); int dnsmasqReload(pid_t pid); -- 1.7.3.2 From berrange at redhat.com Fri Apr 1 11:17:07 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 1 Apr 2011 12:17:07 +0100 Subject: [libvirt] [libvirt-snmp][PATCH v4 4/4] Add SNMP trap/notification support. In-Reply-To: <1301484030-19174-5-git-send-email-mprivozn@redhat.com> References: <1301484030-19174-1-git-send-email-mprivozn@redhat.com> <1301484030-19174-5-git-send-email-mprivozn@redhat.com> Message-ID: <20110401111707.GH29510@redhat.com> On Wed, Mar 30, 2011 at 01:20:30PM +0200, Michal Privoznik wrote: > This patch adds support for domain lifecycle notification support > over SNMP traps. SNMP subagent monitors any domain events and when > something interesting happens, it sends a trap. > > Monitoring is done in a joinable thread using polling (used > domain-events example from libvirt) so we won't block the agent itself. > > Some debug info can be printed out by setting LIBVIRT_SNMP_VERBOSE > environment variable. > --- > src/event.c | 193 ++++++++++++ > src/event.h | 101 ++++++ You don't want to be copying those files. They are libvirt's internal event driver setup code. You just want to be providing an implementation fir that, which is what the next two files do: > src/event_poll.c | 724 ++++++++++++++++++++++++++++++++++++++++++++ > src/event_poll.h | 132 ++++++++ > diff --git a/src/libvirtSnmp.c b/src/libvirtSnmp.c > index dd1bd33..48eeb5c 100644 > --- a/src/libvirtSnmp.c > +++ b/src/libvirtSnmp.c > @@ -20,14 +20,63 @@ > * Author: Michal Privoznik > */ > > +#include > + > #include > #include > +#include > +#include > +#include > +#include > > #include "libvirtSnmp.h" > -/* include our MIB structures*/ > -#include "libvirtGuestTable.h" > - > +#include "libvirtGuestTable.h" /* include our MIB structures*/ > +#include "libvirtNotifications.h" > +#ifdef LIBVIRT_OLD > +# include "event.h" > +#endif > + > +#define DEBUG0(fmt) if (verbose) printf("%s:%d :: " fmt "\n", \ > + __func__, __LINE__) > +#define DEBUG(fmt, ...) if (verbose) printf("%s:%d: " fmt "\n", \ > + __func__, __LINE__, __VA_ARGS__) > +#define STREQ(a,b) (strcmp(a,b) == 0) > + > +#ifndef ATTRIBUTE_UNUSED > +#define ATTRIBUTE_UNUSED __attribute__((__unused__)) > +#endif > + > +int verbose = 0; > virConnectPtr conn; > +int callbackRet = -1; > +int run = 1; > +pthread_t poll_thread; > + > +static int > +domainEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED, > + virDomainPtr dom, int event, int detail, > + void *opaque ATTRIBUTE_UNUSED) > +{ > + DEBUG("%s EVENT: Domain %s(%d) %d %d\n", __func__, > + virDomainGetName(dom), virDomainGetID(dom), event, detail); > + > + send_libvirtGuestNotif_trap(dom); > + return 0; > +} > + > +static void > +myFreeFunc(void *opaque) > +{ > + if (opaque) > + free(opaque); > +} > + > +/* Signal trap function */ > +static void > +stop(int sig) > +{ > + run = 0; > +} > > static void > showError(virConnectPtr conn) > @@ -188,10 +237,77 @@ out: > return ret; > } > > +/* Polling thread function */ > +void * > +pollingThreadFunc(void *foo) { > + while (run) { > + if (virEventRunDefaultImpl() < 0) { This wants to be 'virEventPollRunOnce() < 0' > + showError(conn); > + pthread_exit(NULL); > + } > + } > + return NULL; > +} > + > int libvirtSnmpInit(void) > { > - /* virConnectOpenAuth is called here with all default parameters, > - * except, possibly, the URI of the hypervisor. */ > + char *verbose_env = getenv("LIBVIRT_SNMP_VERBOSE"); > + > + verbose = verbose_env != NULL; > + > + /* if we don't already have registered callback */ > + if (callbackRet == -1) > + virEventRegisterDefaultImpl(); > + And this would be if (virEventPollInit() < 0) return -1; virEventRegisterImpl( virEventPollAddHandle, virEventPollUpdateHandle, virEventPollRemoveHandle, virEventPollAddTimeout, virEventPollUpdateTimeout, virEventPollRemoveTimeout); Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Fri Apr 1 11:17:58 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 1 Apr 2011 12:17:58 +0100 Subject: [libvirt] [PATCH] Fix libxl driver startup In-Reply-To: <20110401093426.GK24385@redhat.com> References: <20110401093426.GK24385@redhat.com> Message-ID: <20110401111758.GI29510@redhat.com> On Fri, Apr 01, 2011 at 05:34:27PM +0800, Daniel Veillard wrote: > When you happen to have a libvirtd binary compiled with the > libxenlight driver (say you have installed xen-4.1 libraries) > but not running a xen enabled system, then libvirtd fails to start. > > The cause is that libxlStartup() returns -1 when failing to initialize > the library, and this propagates to virStateInitialize() which consider > this a failure. We should only exit libxlStartup with an error code > if something like an allocation error occurs, not if the driver failed > to initialize. > > Daniel > > -- > Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ > daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ > http://veillard.com/ | virtualization library http://libvirt.org/ > diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c > index e996ff6..3859405 100644 > --- a/src/libxl/libxl_driver.c > +++ b/src/libxl/libxl_driver.c > @@ -548,7 +548,7 @@ libxlStartup(int privileged) { > const libxl_version_info *ver_info; > char *log_file = NULL; > virCommandPtr cmd; > - int status; > + int status, ret = 0; > > /* Disable libxl driver if non-root */ > if (!privileged) { > @@ -659,19 +659,19 @@ libxlStartup(int privileged) { > (xentoollog_logger *)xtl_createlogger_stdiostream(libxl_driver->logger_file, XTL_DEBUG, 0); > if (!libxl_driver->logger) { > VIR_ERROR0(_("cannot create logger for libxenlight")); > - goto error; > + goto fail; > } > > if (libxl_ctx_init(&libxl_driver->ctx, > LIBXL_VERSION, > libxl_driver->logger)) { > VIR_ERROR0(_("cannot initialize libxenlight context")); > - goto error; > + goto fail; > } > > if ((ver_info = libxl_get_version_info(&libxl_driver->ctx)) == NULL) { > VIR_ERROR0(_("cannot version information from libxenlight")); > - goto error; > + goto fail; > } > libxl_driver->version = (ver_info->xen_version_major * 1000000) + > (ver_info->xen_version_minor * 1000); > @@ -712,11 +712,13 @@ libxlStartup(int privileged) { > out_of_memory: > virReportOOMError(); > error: > + ret = -1; > +fail: > VIR_FREE(log_file); > if (libxl_driver) > libxlDriverUnlock(libxl_driver); > libxlShutdown(); > - return -1; > + return ret; > } > > static int ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From minovotn at redhat.com Fri Apr 1 11:18:50 2011 From: minovotn at redhat.com (Michal Novotny) Date: Fri, 01 Apr 2011 13:18:50 +0200 Subject: [libvirt] [libvirt-php] API to add/remove disk to/from domain In-Reply-To: References: Message-ID: <4D95B49A.7010409@redhat.com> On 04/01/2011 11:11 AM, Conor Murphy wrote: > Hi, > > How do I add/remove a disk to a domain using the libvirt-php API? > > Thanks, > Conor > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list Hi Conor, you have to edit the domain XML file manually, there's no API yet. Please see the example scripts in the examples directory of the cloned repository. On the main page there is option to edit the domain XML description but you have to have the domain stopped (not running) to change the domain XML description. Adding the new disk is done using the: definition where /driver/@type is the type of the driver to be used for the image - raw is the standard image but you can also put qcow2 image there if supported by your hypervisor/emulator (e.g. QEMU). By target you can define the device presented to the guest and bus type (i.e. IDE or SCSI) and after this you can start up the guest with the configuration mentioned there. You can pass the address element there as well but you don't have to since it's generated automatically when omited. Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From jdenemar at redhat.com Fri Apr 1 11:21:07 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Fri, 1 Apr 2011 13:21:07 +0200 Subject: [libvirt] [PATCH] virsh: Fix documentation for memtune command In-Reply-To: <20110401092446.GA29510@redhat.com> References: <44f0aebb40d95a22a5aee5717977da33824a54c0.1301647649.git.jdenemar@redhat.com> <20110401092446.GA29510@redhat.com> Message-ID: <20110401112107.GE389283@orkuz.home> On Fri, Apr 01, 2011 at 10:24:46 +0100, Daniel P. Berrange wrote: > On Fri, Apr 01, 2011 at 10:47:29AM +0200, Jiri Denemark wrote: > > Commit 78ba748ef14c520ff1c4af2b5b0a44586ac49c8c claims to fix > > documentation for swap_hard_limit virsh memtune option but it only fixes > > documentation in formatdomain.html and libvirt.h. This patch completes > > the task by fixing "virsh help memtune" output and memtune section of > > virsh man page. > > --- > > docs/formatdomain.html.in | 6 +++++- > > tools/virsh.c | 2 +- > > tools/virsh.pod | 34 ++++++++++++++++++++++++++++++++-- > > 3 files changed, 38 insertions(+), 4 deletions(-) > > ACK Pushed, thanks. Jirka From veillard at redhat.com Fri Apr 1 11:32:49 2011 From: veillard at redhat.com (Daniel Veillard) Date: Fri, 1 Apr 2011 19:32:49 +0800 Subject: [libvirt] [PATCH] Fix libxl driver startup In-Reply-To: <20110401111758.GI29510@redhat.com> References: <20110401093426.GK24385@redhat.com> <20110401111758.GI29510@redhat.com> Message-ID: <20110401113249.GL24385@redhat.com> On Fri, Apr 01, 2011 at 12:17:58PM +0100, Daniel P. Berrange wrote: > On Fri, Apr 01, 2011 at 05:34:27PM +0800, Daniel Veillard wrote: > > When you happen to have a libvirtd binary compiled with the > > libxenlight driver (say you have installed xen-4.1 libraries) > > but not running a xen enabled system, then libvirtd fails to start. > > > > The cause is that libxlStartup() returns -1 when failing to initialize > > the library, and this propagates to virStateInitialize() which consider > > this a failure. We should only exit libxlStartup with an error code > > if something like an allocation error occurs, not if the driver failed > > to initialize. > > > > Daniel > > > > -- > > Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ > > daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ > > http://veillard.com/ | virtualization library http://libvirt.org/ > > > diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c > > index e996ff6..3859405 100644 > > --- a/src/libxl/libxl_driver.c > > +++ b/src/libxl/libxl_driver.c > > @@ -548,7 +548,7 @@ libxlStartup(int privileged) { > > const libxl_version_info *ver_info; > > char *log_file = NULL; > > virCommandPtr cmd; > > - int status; > > + int status, ret = 0; > > > > /* Disable libxl driver if non-root */ > > if (!privileged) { > > @@ -659,19 +659,19 @@ libxlStartup(int privileged) { > > (xentoollog_logger *)xtl_createlogger_stdiostream(libxl_driver->logger_file, XTL_DEBUG, 0); > > if (!libxl_driver->logger) { > > VIR_ERROR0(_("cannot create logger for libxenlight")); > > - goto error; > > + goto fail; > > } > > > > if (libxl_ctx_init(&libxl_driver->ctx, > > LIBXL_VERSION, > > libxl_driver->logger)) { > > VIR_ERROR0(_("cannot initialize libxenlight context")); > > - goto error; > > + goto fail; > > } > > > > if ((ver_info = libxl_get_version_info(&libxl_driver->ctx)) == NULL) { > > VIR_ERROR0(_("cannot version information from libxenlight")); > > - goto error; > > + goto fail; > > } > > libxl_driver->version = (ver_info->xen_version_major * 1000000) + > > (ver_info->xen_version_minor * 1000); > > @@ -712,11 +712,13 @@ libxlStartup(int privileged) { > > out_of_memory: > > virReportOOMError(); > > error: > > + ret = -1; > > +fail: > > VIR_FREE(log_file); > > if (libxl_driver) > > libxlDriverUnlock(libxl_driver); > > libxlShutdown(); > > - return -1; > > + return ret; > > } > > > > static int > > ACK Thanks, pushed ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From eblake at redhat.com Fri Apr 1 14:51:07 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 08:51:07 -0600 Subject: [libvirt] [libvirt-php] Remove strip from installation In-Reply-To: <1301635516-30885-1-git-send-email-liyong@skybility.com> References: <1301635516-30885-1-git-send-email-liyong@skybility.com> Message-ID: <4D95E65B.7060409@redhat.com> On 03/31/2011 11:25 PM, Lyre wrote: > Make it able to generate debuginfo package. > > install-exec-local: > - $(INSTALL) -m 644 -D --strip $(PACKAGE).so $(DESTDIR)$(PHPEDIR)/$(PACKAGE).so > + $(INSTALL) -m 644 -D $(PACKAGE).so $(DESTDIR)$(PHPEDIR)/$(PACKAGE).so > $(INSTALL) -m 755 -d $(DESTDIR)$(PHPCDIR) > $(ECHO) "extension=$(PACKAGE).so" > $(DESTDIR)$(PHPCDIR)/libvirt-php.ini Good change. GNU Coding Standards recommend, and Automake provides, 'make install' with debug vs. 'make install-strip' with stripped binaries; and 'make install-strip' works by reinvoking 'make install' with $(INSTALL) redefined to also do stripping. So it is still possible to install things stripped by specifically asking for it, but stripping should never be the default. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 1 14:54:55 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 08:54:55 -0600 Subject: [libvirt] [PATCH] virsh: fix mingw failure on creating nonblocking pipe In-Reply-To: <20110401094433.GD29510@redhat.com> References: <1301609000-30523-1-git-send-email-eblake@redhat.com> <4D94FC39.10404@redhat.com> <20110401094433.GD29510@redhat.com> Message-ID: <4D95E73F.6030508@redhat.com> On 04/01/2011 03:44 AM, Daniel P. Berrange wrote: > On Thu, Mar 31, 2011 at 04:12:09PM -0600, Eric Blake wrote: >> On 03/31/2011 04:03 PM, Eric Blake wrote: >>> * .gnulib: Update to latest, for nonblocking module. >>> * bootstrap.conf (gnulib_modules): Add nonblocking. >>> * src/util/util.c (virSetBlocking): Defer to gnulib. >>> --- >>> >>> Matthias, does this work for you on your mingw build? So far, >>> I have only tested that it cross-compiles, and that the new >>> gnulib module passes its self-test when run in isolation on mingw. >>> >>> int virSetBlocking(int fd, bool blocking) { >> >>> - if (blocking) >>> - flags &= ~O_NONBLOCK; >> >>> + return set_nonblocking_flag (fd, blocking); >> >> Oops - that _can't_ work. s/blocking/!blocking/ in that return statement. > > ACK with that fix :-) I ran a sanity check that the corrected version could still start and stop qemu guests on Linux, then pushed the corrected version. For the record, the gnulib patches include: * .gnulib 790645d...dec3475 (5): > nonblocking: fix mingw test failures > Fix bug with gl_WARN_ON_USE_PREPARE, introduced on 2011-01-23. > nonblocking: Tweak comment. > nonblocking: new module > Fix recent ChangeLog entries. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From mprivozn at redhat.com Fri Apr 1 15:29:14 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Fri, 1 Apr 2011 17:29:14 +0200 Subject: [libvirt] [PATCH 0/7] Add support for taking screenshots Message-ID: <1301671761-367-1-git-send-email-mprivozn@redhat.com> This patch series implements screenshots taking feature, which is accessible via new virDomainScreenshot API and 'screenshot' command in virsh. By now, 'flags' argument is not used, but can be later when specifying say image output format, etc. Talking of - output is hypervisor specific. QEMU output images in PPM, VirtualBox in PNG. Michal Privoznik (7): screenshot: Defining the public API screenshot: Defining the internal API screenshot: Implementing the public API screenshot: Implementing the remote protocol screenshot: Expose the new API in virsh qemu: Implement the driver methods vbox: Implement the driver methods daemon/remote.c | 26 +++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 +++ daemon/remote_dispatch_table.h | 5 ++ include/libvirt/libvirt.h.in | 7 ++ src/driver.h | 5 ++ src/esx/esx_driver.c | 1 + src/libvirt.c | 77 +++++++++++++++++++++++++ src/libvirt_public.syms | 1 + src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 106 +++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 20 +++++++ src/qemu/qemu_monitor.h | 3 + src/qemu/qemu_monitor_json.c | 23 ++++++++ src/qemu/qemu_monitor_json.h | 4 + src/qemu/qemu_monitor_text.c | 31 ++++++++++ src/qemu/qemu_monitor_text.h | 2 + src/remote/remote_driver.c | 26 +++++++++ src/remote/remote_protocol.c | 13 ++++ src/remote/remote_protocol.h | 10 +++ src/remote/remote_protocol.x | 9 +++- src/remote_protocol-structs | 5 ++ src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 97 ++++++++++++++++++++++++++++++++ src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xen/xen_driver.h | 1 + src/xen/xen_hypervisor.c | 1 + src/xen/xen_inotify.c | 1 + src/xen/xend_internal.c | 1 + src/xen/xm_internal.c | 1 + src/xen/xs_internal.c | 1 + src/xenapi/xenapi_driver.c | 1 + tools/virsh.c | 49 ++++++++++++++++ tools/virsh.pod | 4 + 39 files changed, 547 insertions(+), 1 deletions(-) -- 1.7.4 From mprivozn at redhat.com Fri Apr 1 15:29:15 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Fri, 1 Apr 2011 17:29:15 +0200 Subject: [libvirt] [PATCH 1/7] screenshot: Defining the public API In-Reply-To: <1301671761-367-1-git-send-email-mprivozn@redhat.com> References: <1301671761-367-1-git-send-email-mprivozn@redhat.com> Message-ID: <1301671761-367-2-git-send-email-mprivozn@redhat.com> --- include/libvirt/libvirt.h.in | 7 +++++++ src/libvirt_public.syms | 1 + 2 files changed, 8 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index bd36015..42711e6 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -670,6 +670,13 @@ int virDomainCoreDump (virDomainPtr domain, int flags); /* + * Screenshot of current domain console + */ +int virDomainScreenshot (virDomainPtr domain, + const char *to, + int flags); + +/* * Domain runtime information */ int virDomainGetInfo (virDomainPtr domain, diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b4aed41..a6ce1bb 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -428,6 +428,7 @@ LIBVIRT_0.9.0 { global: virDomainGetBlkioParameters; virDomainMigrateSetMaxSpeed; + virDomainScreenshot; virDomainSetBlkioParameters; virDomainSetMemoryFlags; virEventRegisterDefaultImpl; -- 1.7.4 From mprivozn at redhat.com Fri Apr 1 15:29:16 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Fri, 1 Apr 2011 17:29:16 +0200 Subject: [libvirt] [PATCH 2/7] screenshot: Defining the internal API In-Reply-To: <1301671761-367-1-git-send-email-mprivozn@redhat.com> References: <1301671761-367-1-git-send-email-mprivozn@redhat.com> Message-ID: <1301671761-367-3-git-send-email-mprivozn@redhat.com> --- src/driver.h | 5 +++++ src/esx/esx_driver.c | 1 + src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 1 + src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xen/xen_driver.h | 1 + src/xen/xen_hypervisor.c | 1 + src/xen/xen_inotify.c | 1 + src/xen/xend_internal.c | 1 + src/xen/xm_internal.c | 1 + src/xen/xs_internal.c | 1 + src/xenapi/xenapi_driver.c | 1 + 20 files changed, 24 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index e5f91ca..af463d0 100644 --- a/src/driver.h +++ b/src/driver.h @@ -175,6 +175,10 @@ typedef int (*virDrvDomainCoreDump) (virDomainPtr domain, const char *to, int flags); +typedef int + (*virDrvDomainScreenshot) (virDomainPtr domain, + const char *to, + int flags); typedef char * (*virDrvDomainDumpXML) (virDomainPtr dom, int flags); @@ -566,6 +570,7 @@ struct _virDriver { virDrvDomainSave domainSave; virDrvDomainRestore domainRestore; virDrvDomainCoreDump domainCoreDump; + virDrvDomainScreenshot domainScreenshot; virDrvDomainSetVcpus domainSetVcpus; virDrvDomainSetVcpusFlags domainSetVcpusFlags; virDrvDomainGetVcpusFlags domainGetVcpusFlags; diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index deda372..2d52314 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4602,6 +4602,7 @@ static virDriver esxDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ esxDomainSetVcpus, /* domainSetVcpus */ esxDomainSetVcpusFlags, /* domainSetVcpusFlags */ esxDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 3859405..7fa55bb 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2282,6 +2282,7 @@ static virDriver libxlDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ libxlDomainSetVcpus, /* domainSetVcpus */ libxlDomainSetVcpusFlags, /* domainSetVcpusFlags */ libxlDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e905302..ed40cb2 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2833,6 +2833,7 @@ static virDriver lxcDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ NULL, /* domainSetVcpus */ NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index fb30c37..b451276 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1581,6 +1581,7 @@ static virDriver openvzDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ openvzDomainSetVcpus, /* domainSetVcpus */ openvzDomainSetVcpusFlags, /* domainSetVcpusFlags */ openvzDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 51f9ff6..761ac34 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -3982,6 +3982,7 @@ static virDriver phypDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ phypDomainSetCPU, /* domainSetVcpus */ phypDomainSetVcpusFlags, /* domainSetVcpusFlags */ phypDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5aa715e..c9cc74a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6850,6 +6850,7 @@ static virDriver qemuDriver = { qemudDomainSave, /* domainSave */ qemuDomainRestore, /* domainRestore */ qemudDomainCoreDump, /* domainCoreDump */ + NULL, /* domainScreenshot */ qemudDomainSetVcpus, /* domainSetVcpus */ qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index bf94e70..d7772d0 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -11223,6 +11223,7 @@ static virDriver remote_driver = { remoteDomainSave, /* domainSave */ remoteDomainRestore, /* domainRestore */ remoteDomainCoreDump, /* domainCoreDump */ + NULL, /* domainScreenshot */ remoteDomainSetVcpus, /* domainSetVcpus */ remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 17f5ad9..5a33054 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5374,6 +5374,7 @@ static virDriver testDriver = { testDomainSave, /* domainSave */ testDomainRestore, /* domainRestore */ testDomainCoreDump, /* domainCoreDump */ + NULL, /* domainScreenshot */ testSetVcpus, /* domainSetVcpus */ testDomainSetVcpusFlags, /* domainSetVcpusFlags */ testDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index e2bd5f2..517b219 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2176,6 +2176,7 @@ static virDriver umlDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ NULL, /* domainSetVcpus */ NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 8bd27dd..390fc3b 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8564,6 +8564,7 @@ virDriver NAME(Driver) = { vboxDomainSave, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ vboxDomainSetVcpus, /* domainSetVcpus */ vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */ vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index b5e416b..926eca0 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -934,6 +934,7 @@ static virDriver vmwareDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ NULL, /* domainSetVcpus */ NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 9f47722..a883c15 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2068,6 +2068,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedDomainSave, /* domainSave */ xenUnifiedDomainRestore, /* domainRestore */ xenUnifiedDomainCoreDump, /* domainCoreDump */ + NULL, /* domainScreenshot */ xenUnifiedDomainSetVcpus, /* domainSetVcpus */ xenUnifiedDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenUnifiedDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/xen/xen_driver.h b/src/xen/xen_driver.h index 58b8561..8fb5832 100644 --- a/src/xen/xen_driver.h +++ b/src/xen/xen_driver.h @@ -93,6 +93,7 @@ struct xenUnifiedDriver { virDrvDomainSave domainSave; virDrvDomainRestore domainRestore; virDrvDomainCoreDump domainCoreDump; + virDrvDomainScreenshot domainScreenshot; virDrvDomainPinVcpu domainPinVcpu; virDrvDomainGetVcpus domainGetVcpus; virDrvListDefinedDomains listDefinedDomains; diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c index 47355ce..f624ed3 100644 --- a/src/xen/xen_hypervisor.c +++ b/src/xen/xen_hypervisor.c @@ -824,6 +824,7 @@ struct xenUnifiedDriver xenHypervisorDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ xenHypervisorPinVcpu, /* domainPinVcpu */ xenHypervisorGetVcpus, /* domainGetVcpus */ NULL, /* listDefinedDomains */ diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c index 7d4ba4c..46b7870 100644 --- a/src/xen/xen_inotify.c +++ b/src/xen/xen_inotify.c @@ -72,6 +72,7 @@ struct xenUnifiedDriver xenInotifyDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ NULL, /* domainPinVcpu */ NULL, /* domainGetVcpus */ NULL, /* listDefinedDomains */ diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 8859373..070ffc6 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -3847,6 +3847,7 @@ struct xenUnifiedDriver xenDaemonDriver = { xenDaemonDomainSave, /* domainSave */ xenDaemonDomainRestore, /* domainRestore */ xenDaemonDomainCoreDump, /* domainCoreDump */ + NULL, /* domainScreenshot */ xenDaemonDomainPinVcpu, /* domainPinVcpu */ xenDaemonDomainGetVcpus, /* domainGetVcpus */ xenDaemonListDefinedDomains, /* listDefinedDomains */ diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 7f73588..ae55e0f 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -103,6 +103,7 @@ struct xenUnifiedDriver xenXMDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ xenXMDomainPinVcpu, /* domainPinVcpu */ NULL, /* domainGetVcpus */ xenXMListDefinedDomains, /* listDefinedDomains */ diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c index d9aad1f..c17d5f9 100644 --- a/src/xen/xs_internal.c +++ b/src/xen/xs_internal.c @@ -65,6 +65,7 @@ struct xenUnifiedDriver xenStoreDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ NULL, /* domainPinVcpu */ NULL, /* domainGetVcpus */ NULL, /* listDefinedDomains */ diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 27206a0..d510697 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1812,6 +1812,7 @@ static virDriver xenapiDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ xenapiDomainSetVcpus, /* domainSetVcpus */ xenapiDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenapiDomainGetVcpusFlags, /* domainGetVcpusFlags */ -- 1.7.4 From mprivozn at redhat.com Fri Apr 1 15:29:17 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Fri, 1 Apr 2011 17:29:17 +0200 Subject: [libvirt] [PATCH 3/7] screenshot: Implementing the public API In-Reply-To: <1301671761-367-1-git-send-email-mprivozn@redhat.com> References: <1301671761-367-1-git-send-email-mprivozn@redhat.com> Message-ID: <1301671761-367-4-git-send-email-mprivozn@redhat.com> --- src/libvirt.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 77 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 8be18d4..9f8f2e6 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -2445,6 +2445,83 @@ error: } /** + * virDomainScreenshot: + * @domain: a domain object + * @to: path for the image + * @flags: extra flags, currently unused + * + * Take a screenshot of current domain console and store it + * as image under given path. The image format is hypervisor + * specific. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virDomainScreenshot(virDomainPtr domain, const char *to, int flags) +{ + char filepath[4096]; + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "to=%s, flags=%d", to, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + conn = domain->conn; + if (to == NULL) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + /* + * We must absolutize the file path as the save is done out of process + * TODO: check for URI when libxml2 is linked in. + */ + if(to[0] != '/') { + unsigned int len, t; + + t = strlen(to); + if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) { + virLibDomainError(VIR_ERR_SYSTEM_ERROR, + _("cannot get current directory")); + goto error; + } + len = strlen(filepath); + /* that should be covered by getcwd() semantic, but be 100% sure */ + if (len > sizeof(filepath) - (t + 3)) { + virLibDomainError(VIR_ERR_INTERNAL_ERROR, + _("path too long")); + goto error; + } + filepath[len] = '/'; + strcpy(&filepath[len + 1], to); + to = &filepath[0]; + } + + if (conn->driver->domainScreenshot) { + int ret; + ret = conn->driver->domainScreenshot (domain, to, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} + +/** * virDomainShutdown: * @domain: a domain object * -- 1.7.4 From mprivozn at redhat.com Fri Apr 1 15:29:18 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Fri, 1 Apr 2011 17:29:18 +0200 Subject: [libvirt] [PATCH 4/7] screenshot: Implementing the remote protocol In-Reply-To: <1301671761-367-1-git-send-email-mprivozn@redhat.com> References: <1301671761-367-1-git-send-email-mprivozn@redhat.com> Message-ID: <1301671761-367-5-git-send-email-mprivozn@redhat.com> --- daemon/remote.c | 26 ++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++++++ daemon/remote_dispatch_table.h | 5 +++++ src/remote/remote_driver.c | 27 ++++++++++++++++++++++++++- src/remote/remote_protocol.c | 13 +++++++++++++ src/remote/remote_protocol.h | 10 ++++++++++ src/remote/remote_protocol.x | 9 ++++++++- src/remote_protocol-structs | 5 +++++ 9 files changed, 102 insertions(+), 2 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 1700c2d..8797c38 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -2310,6 +2310,32 @@ remoteDispatchDomainCoreDump (struct qemud_server *server ATTRIBUTE_UNUSED, } static int +remoteDispatchDomainScreenshot (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_screenshot_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virDomainPtr dom; + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + if (virDomainScreenshot (dom, args->to, args->flags) == -1) { + remoteDispatchConnError(rerr, conn); + virDomainFree(dom); + return -1; + } + virDomainFree(dom); + return 0; +} + +static int remoteDispatchDomainSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index f9537d7..2be8003 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -178,3 +178,4 @@ remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; remote_storage_vol_upload_args val_remote_storage_vol_upload_args; remote_storage_vol_download_args val_remote_storage_vol_download_args; + remote_domain_screenshot_args val_remote_domain_screenshot_args; diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 18bf41d..d4844b4 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -546,6 +546,14 @@ static int remoteDispatchDomainSave( remote_error *err, remote_domain_save_args *args, void *ret); +static int remoteDispatchDomainScreenshot( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_screenshot_args *args, + void *ret); static int remoteDispatchDomainSetAutostart( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index b39f7c2..349006a 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1052,3 +1052,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* DomainScreenshot => 210 */ + .fn = (dispatch_fn) remoteDispatchDomainScreenshot, + .args_filter = (xdrproc_t) xdr_remote_domain_screenshot_args, + .ret_filter = (xdrproc_t) xdr_void, +}, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index d7772d0..3b6d141 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2929,6 +2929,31 @@ done: } static int +remoteDomainScreenshot (virDomainPtr domain, const char *to, int flags) +{ + int rv = -1; + remote_domain_screenshot_args args; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + make_nonnull_domain (&args.dom, domain); + args.to = (char *) to; + args.flags = flags; + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SCREENSHOT, + (xdrproc_t) xdr_remote_domain_screenshot_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int remoteDomainSetVcpus (virDomainPtr domain, unsigned int nvcpus) { int rv = -1; @@ -11223,7 +11248,7 @@ static virDriver remote_driver = { remoteDomainSave, /* domainSave */ remoteDomainRestore, /* domainRestore */ remoteDomainCoreDump, /* domainCoreDump */ - NULL, /* domainScreenshot */ + remoteDomainScreenshot, /* domainScreenshot */ remoteDomainSetVcpus, /* domainSetVcpus */ remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 5604371..00b51a0 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -1230,6 +1230,19 @@ xdr_remote_domain_core_dump_args (XDR *xdrs, remote_domain_core_dump_args *objp) } bool_t +xdr_remote_domain_screenshot_args (XDR *xdrs, remote_domain_screenshot_args *objp) +{ + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_remote_nonnull_string (xdrs, &objp->to)) + return FALSE; + if (!xdr_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_domain_dump_xml_args (XDR *xdrs, remote_domain_dump_xml_args *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index d9bf151..826853c 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -666,6 +666,13 @@ struct remote_domain_core_dump_args { }; typedef struct remote_domain_core_dump_args remote_domain_core_dump_args; +struct remote_domain_screenshot_args { + remote_nonnull_domain dom; + remote_nonnull_string to; + int flags; +}; +typedef struct remote_domain_screenshot_args remote_domain_screenshot_args; + struct remote_domain_dump_xml_args { remote_nonnull_domain dom; int flags; @@ -2413,6 +2420,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_SCREENSHOT = 210, }; typedef enum remote_procedure remote_procedure; @@ -2541,6 +2549,7 @@ extern bool_t xdr_remote_domain_get_info_ret (XDR *, remote_domain_get_info_ret extern bool_t xdr_remote_domain_save_args (XDR *, remote_domain_save_args*); extern bool_t xdr_remote_domain_restore_args (XDR *, remote_domain_restore_args*); extern bool_t xdr_remote_domain_core_dump_args (XDR *, remote_domain_core_dump_args*); +extern bool_t xdr_remote_domain_screenshot_args (XDR *, remote_domain_screenshot_args*); extern bool_t xdr_remote_domain_dump_xml_args (XDR *, remote_domain_dump_xml_args*); extern bool_t xdr_remote_domain_dump_xml_ret (XDR *, remote_domain_dump_xml_ret*); extern bool_t xdr_remote_domain_migrate_prepare_args (XDR *, remote_domain_migrate_prepare_args*); @@ -2898,6 +2907,7 @@ extern bool_t xdr_remote_domain_get_info_ret (); extern bool_t xdr_remote_domain_save_args (); extern bool_t xdr_remote_domain_restore_args (); extern bool_t xdr_remote_domain_core_dump_args (); +extern bool_t xdr_remote_domain_screenshot_args (); extern bool_t xdr_remote_domain_dump_xml_args (); extern bool_t xdr_remote_domain_dump_xml_ret (); extern bool_t xdr_remote_domain_migrate_prepare_args (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 675eccd..090e959 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -714,6 +714,12 @@ struct remote_domain_core_dump_args { int flags; }; +struct remote_domain_screenshot_args { + remote_nonnull_domain dom; + remote_nonnull_string to; + int flags; +}; + struct remote_domain_dump_xml_args { remote_nonnull_domain dom; int flags; @@ -2176,7 +2182,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_SCREENSHOT = 210 /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 944553c..9adc695 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -403,6 +403,11 @@ struct remote_domain_core_dump_args { remote_nonnull_string to; int flags; }; +struct remote_domain_screenshot_args { + remote_nonnull_domain dom; + remote_nonnull_string to; + int flags; +}; struct remote_domain_dump_xml_args { remote_nonnull_domain dom; int flags; -- 1.7.4 From mprivozn at redhat.com Fri Apr 1 15:29:19 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Fri, 1 Apr 2011 17:29:19 +0200 Subject: [libvirt] [PATCH 5/7] screenshot: Expose the new API in virsh In-Reply-To: <1301671761-367-1-git-send-email-mprivozn@redhat.com> References: <1301671761-367-1-git-send-email-mprivozn@redhat.com> Message-ID: <1301671761-367-6-git-send-email-mprivozn@redhat.com> --- tools/virsh.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 4 ++++ 2 files changed, 53 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 19e3449..6f6883d 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1881,6 +1881,54 @@ cmdDump(vshControl *ctl, const vshCmd *cmd) } /* + * "screenshot" command + */ +static const vshCmdInfo info_screenshot[] = { + {"help", N_("take a screenshot of a current domain console and store it " + "into a file")}, + {"desc", N_("screenshot of a current domain console")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_screenshot[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("where to store the screenshot")}, + {NULL, 0, 0, NULL} +}; + +static int +cmdScreenshot(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + const char *name = NULL; + const char *to = NULL; + int ret = FALSE; + int flags = 0; /* currently unused */ + + if (!vshConnectionUsability(ctl, ctl->conn)) + return FALSE; + + if (vshCommandOptString(cmd, "file", &to) <= 0) + return FALSE; + + if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + return FALSE; + + if (virDomainScreenshot(dom, to, flags) == 0) { + vshPrint(ctl, _("Screenshot saved to %s"), to); + } else { + vshError(ctl, _("Failed to take a screenshot of %s"), name); + goto error; + } + + ret = TRUE; + +error: + virDomainFree(dom); + return ret; +} + +/* * "resume" command */ static const vshCmdInfo info_resume[] = { @@ -10691,6 +10739,7 @@ static const vshCmdDef domManagementCmds[] = { {"resume", cmdResume, opts_resume, info_resume}, {"save", cmdSave, opts_save, info_save}, {"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo}, + {"screenshot", cmdScreenshot, opts_screenshot, info_screenshot}, {"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem}, {"setmem", cmdSetmem, opts_setmem, info_setmem}, {"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus}, diff --git a/tools/virsh.pod b/tools/virsh.pod index f4bd294..e61f501 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -578,6 +578,10 @@ Therefore, -1 is a useful shorthand for 262144. B: The weight and cap parameters are defined only for the XEN_CREDIT scheduler and are now I. +=item B I I + +Takes a screenshot of a current domain console and stores it into a file. + =item B I B optional I<--config> I<--live> Change the memory allocation for a guest domain. -- 1.7.4 From mprivozn at redhat.com Fri Apr 1 15:29:20 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Fri, 1 Apr 2011 17:29:20 +0200 Subject: [libvirt] [PATCH 6/7] qemu: Implement the driver methods In-Reply-To: <1301671761-367-1-git-send-email-mprivozn@redhat.com> References: <1301671761-367-1-git-send-email-mprivozn@redhat.com> Message-ID: <1301671761-367-7-git-send-email-mprivozn@redhat.com> --- src/qemu/qemu_driver.c | 107 +++++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_monitor.c | 20 ++++++++ src/qemu/qemu_monitor.h | 3 + src/qemu/qemu_monitor_json.c | 23 +++++++++ src/qemu/qemu_monitor_json.h | 4 ++ src/qemu/qemu_monitor_text.c | 31 ++++++++++++ src/qemu/qemu_monitor_text.h | 2 + 7 files changed, 189 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c9cc74a..e25c7a6 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2383,6 +2383,111 @@ cleanup: return ret; } +static int +qemuDomainScreenshot(virDomainPtr dom, const char *path, + int flags ATTRIBUTE_UNUSED) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + qemuDomainObjPrivatePtr priv; + char *tmp = NULL; + int path_fd = -1, tmp_fd = -1, ret = -1; + char buf[4096]; + ssize_t nread, nwrite; + + 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 matching uuid '%s'"), uuidstr); + goto cleanup; + } + + priv = vm->privateData; + + if (qemuDomainObjBeginJob(vm) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto endjob; + } + + if ((path_fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("failed to create '%s'"), path); + goto endjob; + } + + if (virAsprintf(&tmp, "%s/qemu.screendump.XXXXXX", driver->cacheDir) < 0) { + virReportOOMError(); + goto endjob; + } + + /* Create a temporary filename */ + if ((tmp_fd = mkstemp(tmp)) == -1) { + virReportSystemError(errno, _("mkstemp(\"%s\") failed"), tmp); + goto endjob; + } + + qemuDomainObjEnterMonitor(vm); + if (qemuMonitorScreendump(priv->mon, tmp) < 0) { + qemuDomainObjExitMonitor(vm); + goto endjob; + } + qemuDomainObjExitMonitor(vm); + + /* Copy to destination */ + while ((nread=saferead(tmp_fd, buf, sizeof(buf))) > 0) { + nwrite = safewrite(path_fd, buf, nread); + if (nread != nwrite) { + virReportSystemError(errno, _("failed to write data to '%s'"), + path); + goto endjob; + } + } + if (nread < 0) { + virReportSystemError(errno, _("failed to read data from '%s'"), + tmp); + } + + if (VIR_CLOSE(tmp_fd) < 0) { + virReportSystemError(errno, _("error closing '%s'"), tmp); + goto endjob; + } + tmp_fd = -1; + + if (VIR_CLOSE(path_fd) < 0) { + virReportSystemError(errno, _("error closing '%s'"), path); + goto endjob; + } + path_fd = -1; + + ret = 0; + +endjob: + VIR_FORCE_CLOSE(tmp_fd); + if (tmp != NULL) { + unlink(tmp); + VIR_FREE(tmp); + } + + VIR_FORCE_CLOSE(path_fd); + + if (qemuDomainObjEndJob(vm) == 0) + vm = NULL; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + static void processWatchdogEvent(void *data, void *opaque) { int ret; @@ -6850,7 +6955,7 @@ static virDriver qemuDriver = { qemudDomainSave, /* domainSave */ qemuDomainRestore, /* domainRestore */ qemudDomainCoreDump, /* domainCoreDump */ - NULL, /* domainScreenshot */ + qemuDomainScreenshot, /* domainScreenshot */ qemudDomainSetVcpus, /* domainSetVcpus */ qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 2d28f8d..6834d29 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2228,3 +2228,23 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, ret = qemuMonitorTextArbitraryCommand(mon, cmd, reply); return ret; } + +int qemuMonitorScreendump(qemuMonitorPtr mon, + const char *file) +{ + int ret; + + VIR_DEBUG("mon=%p, file=%s", mon, file); + + if (!mon) { + qemuReportError(VIR_ERR_INVALID_ARG,"%s", + _("monitor must not be NULL")); + return -1; + } + + if (mon->json) + ret = qemuMonitorJSONScreendump(mon, file); + else + ret = qemuMonitorTextScreendump(mon, file); + return ret; +} diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c90219b..5c96f12 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -423,6 +423,9 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, char **reply, bool hmp); +int qemuMonitorScreendump(qemuMonitorPtr mon, + const char *file); + /** * When running two dd process and using <> redirection, we need a * shell that will not truncate files. These two strings serve that diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 20a78e1..df45e4b 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2513,3 +2513,26 @@ cleanup: return ret; } + +int qemuMonitorJSONScreendump(qemuMonitorPtr mon, + const char *file) +{ + int ret; + virJSONValuePtr cmd, reply = NULL; + + cmd = qemuMonitorJSONMakeCommand("screendump", + "s:filename", file, + NULL); + + if (!cmd) + return -1; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 086f0e1..bcfdd24 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -204,4 +204,8 @@ int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon, char **reply_str, bool hmp); +int qemuMonitorJSONScreendump(qemuMonitorPtr mon, + const char *file); + + #endif /* QEMU_MONITOR_JSON_H */ diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 168c60f..52c82d0 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -2628,3 +2628,34 @@ int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, return ret; } + +/* Returns -1 on error, -2 if not supported */ +int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file) +{ + char *cmd = NULL; + char *reply = NULL; + int ret = -1; + + if (virAsprintf(&cmd, "screendump %s", file) < 0){ + virReportOOMError(); + goto cleanup; + } + + if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("taking screenshot failed")); + goto cleanup; + } + + if (strstr(reply, "unknown command:")) { + ret = -2; + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(reply); + VIR_FREE(cmd); + return ret; +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 0838a2b..773d33c 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -198,4 +198,6 @@ int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name); int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply); +int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file); + #endif /* QEMU_MONITOR_TEXT_H */ -- 1.7.4 From mprivozn at redhat.com Fri Apr 1 15:29:21 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Fri, 1 Apr 2011 17:29:21 +0200 Subject: [libvirt] [PATCH 7/7] vbox: Implement the driver methods In-Reply-To: <1301671761-367-1-git-send-email-mprivozn@redhat.com> References: <1301671761-367-1-git-send-email-mprivozn@redhat.com> Message-ID: <1301671761-367-8-git-send-email-mprivozn@redhat.com> --- src/vbox/vbox_tmpl.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 96 insertions(+), 0 deletions(-) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 390fc3b..5c9c271 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -36,6 +36,9 @@ #include #include +#include +#include +#include #include "internal.h" #include "datatypes.h" @@ -51,6 +54,7 @@ #include "nodeinfo.h" #include "logging.h" #include "vbox_driver.h" +#include "files.h" /* This one changes from version to version. */ #if VBOX_API_VERSION == 2002 @@ -8522,6 +8526,94 @@ static char *vboxStorageVolGetPath(virStorageVolPtr vol) { return ret; } +#if VBOX_API_VERSION == 4000 +static int +vboxDomainScreenshot(virDomainPtr dom, const char *path, + int flags ATTRIBUTE_UNUSED) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IConsole *console = NULL; + vboxIID iid = VBOX_IID_INITIALIZER; + IMachine *machine = NULL; + nsresult rc; + int fd = -1; + + vboxIIDFromUUID(&iid, dom->uuid); + rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); + if (NS_FAILED(rc)) { + vboxError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + return -1; + } + + rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); + if (NS_SUCCEEDED(rc)) { + rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console); + if (NS_SUCCEEDED(rc) && console) { + IDisplay *display = NULL; + + console->vtbl->GetDisplay(console, &display); + + if (display) { + PRUint32 width, height, bitsPerPixel; + PRUint32 screenDataSize; + PRUint8 *screenData; + + rc = display->vtbl->GetScreenResolution(display, 0, + &width, &height, + &bitsPerPixel); + + if (NS_FAILED(rc) || !width || !height) { + vboxError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to get screen resolution")); + goto endjob; + } + + rc = display->vtbl->TakeScreenShotPNGToArray(display, 0, + width, height, + &screenDataSize, + &screenData); + if (NS_FAILED(rc)) { + vboxError(VIR_ERR_OPERATION_FAILED, "%s", + _("failed to take screenshot")); + goto endjob; + } + + if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, + S_IRUSR|S_IWUSR)) < 0) { + vboxError(VIR_ERR_OPERATION_FAILED, _("failed to " + "create '%s'"), path); + goto endjob; + } + + if (safewrite(fd, (char *) screenData, screenDataSize) < 0) { + virReportSystemError(errno, _("unable to write data " + "to '%s'"), path); + goto endjob; + } + + if (VIR_CLOSE(fd) < 0) { + virReportSystemError(errno, _("error closing '%s'"), + path); + goto endjob; + } + + ret = 0; + +endjob: + VBOX_RELEASE(display); + } + VBOX_RELEASE(console); + } + VBOX_SESSION_CLOSE(); + } + + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} +#endif /* VBOX_API_VERSION == 4000 */ + /** * Function Tables */ @@ -8564,7 +8656,11 @@ virDriver NAME(Driver) = { vboxDomainSave, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ +#if VBOX_API_VERSION == 4000 + vboxDomainScreenshot, /* domainScreenshot */ +#else NULL, /* domainScreenshot */ +#endif vboxDomainSetVcpus, /* domainSetVcpus */ vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */ vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */ -- 1.7.4 From berrange at redhat.com Fri Apr 1 15:39:05 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 1 Apr 2011 16:39:05 +0100 Subject: [libvirt] [PATCH] Use gnulib's manywarnings & warnings modules Message-ID: <1301672345-31926-1-git-send-email-berrange@redhat.com> Remove custom code for checking compiler warnings, using gl_WARN_ADD instead. Don't list all flags ourselves, use gnulib's gl_MANYWARN_ALL_GCC to get all possible GCC flags, then turn off the ones we don't want yet. This patch alone doesn't buy us much. What we want is some more followup patches, which remove entries from the 'dontwarn' list, fixing up the corresponding code problems. We also need to fix our stack usage in many places so we can lower the ridiculous size of -Wframe-larger-than=20480 * acinclude.m4: Rewrite to use gl_WARN_ADD and gl_MANYWARN_ALL_GCC * bootstrap.conf: Add warnings & manywarnings * configure.ac: Switch to gl_WARN_ADD * m4/compiler-flags.m4: Obsoleted by gl_WARN_ADD --- acinclude.m4 | 153 ++++++++++++++++++++++++++------------------------ bootstrap.conf | 2 + configure.ac | 15 +++-- m4/compiler-flags.m4 | 48 ---------------- 4 files changed, 91 insertions(+), 127 deletions(-) delete mode 100644 m4/compiler-flags.m4 diff --git a/acinclude.m4 b/acinclude.m4 index 838ec46..63bfec7 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1,11 +1,6 @@ dnl -dnl Taken from gnome-common/macros2/gnome-compiler-flags.m4 -dnl -dnl We've added: -dnl -Wextra -Wshadow -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Winline -Wredundant-decls -dnl We've removed -dnl CFLAGS="$realsave_CFLAGS" -dnl to avoid clobbering user-specified CFLAGS +dnl Enable all known GCC compiler warnings, except for those +dnl we can't yet cope with dnl AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ dnl ****************************** @@ -13,90 +8,102 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ dnl ****************************** AC_ARG_ENABLE(compile-warnings, - [AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@], + [AC_HELP_STRING([--enable-compile-warnings=@<:@no/yes/error@:>@], [Turn on compiler warnings])],, - [enable_compile_warnings="m4_default([$1],[maximum])"]) - - warnCFLAGS= - - common_flags= - common_flags="$common_flags -Wp,-D_FORTIFY_SOURCE=2" - common_flags="$common_flags -fexceptions" - common_flags="$common_flags -fasynchronous-unwind-tables" - common_flags="$common_flags -fdiagnostics-show-option" + [enable_compile_warnings="m4_default([$1],[yes])"]) case "$enable_compile_warnings" in no) try_compiler_flags="" ;; - minimum) - try_compiler_flags="-Wall -Wformat -Wformat-security $common_flags" - ;; - yes) - try_compiler_flags="-Wall -Wformat -Wformat-security -Wmissing-prototypes $common_flags" - ;; - maximum|error) - try_compiler_flags="-Wall -Wformat -Wformat-security" - try_compiler_flags="$try_compiler_flags -Wmissing-prototypes" - try_compiler_flags="$try_compiler_flags -Wnested-externs " - try_compiler_flags="$try_compiler_flags -Wpointer-arith" - try_compiler_flags="$try_compiler_flags -Wextra -Wshadow" - try_compiler_flags="$try_compiler_flags -Wcast-align" - try_compiler_flags="$try_compiler_flags -Wwrite-strings" - try_compiler_flags="$try_compiler_flags -Waggregate-return" - try_compiler_flags="$try_compiler_flags -Wstrict-prototypes" - try_compiler_flags="$try_compiler_flags -Winline" - try_compiler_flags="$try_compiler_flags -Wredundant-decls" - try_compiler_flags="$try_compiler_flags -Wno-sign-compare" - try_compiler_flags="$try_compiler_flags -Wlogical-op" - try_compiler_flags="$try_compiler_flags $common_flags" - if test "$enable_compile_warnings" = "error" ; then - try_compiler_flags="$try_compiler_flags -Werror" - fi + yes|minimum|maximum|error) + + # List of warnings that are not relevant / wanted + dontwarn="$dontwarn -Wc++-compat" # Don't care about C++ compiler compat + dontwarn="$dontwarn -Wtraditional" # Don't care about ancient C standard compat + dontwarn="$dontwarn -Wtraditional-conversion" # Don't care about ancient C standard compat + dontwarn="$dontwarn -Wsystem-headers" # Ignore warnings in /usr/include + dontwarn="$dontwarn -Wpadded" # Happy for compiler to add struct padding + dontwarn="$dontwarn -Wunreachable-code" # GCC very confused with -O2 + dontwarn="$dontwarn -Wconversion" # Too many to deal with + dontwarn="$dontwarn -Wsign-conversion" # Too many to deal with + dontwarn="$dontwarn -Wvla" # GNULIB gettext.h violates + dontwarn="$dontwarn -Wundef" # Many GNULIB violations + dontwarn="$dontwarn -Wcast-qual" # Need to allow bad cast for execve() + dontwarn="$dontwarn -Wlong-long" # We need to use long long in many places + + # We might fundamentally need some of these disabled forever, but ideally + # we'd turn many of them on + dontwarn="$dontwarn -Wformat-nonliteral" + dontwarn="$dontwarn -Wswitch-default" + dontwarn="$dontwarn -Wswitch-enum" + dontwarn="$dontwarn -Wstrict-overflow" + dontwarn="$dontwarn -Wfloat-equal" + dontwarn="$dontwarn -Wdeclaration-after-statement" + dontwarn="$dontwarn -Wunsafe-loop-optimizations" + dontwarn="$dontwarn -Wcast-qual" + dontwarn="$dontwarn -Wconversion" + dontwarn="$dontwarn -Wsign-conversion" + dontwarn="$dontwarn -Wold-style-definition" + dontwarn="$dontwarn -Wmissing-noreturn" + dontwarn="$dontwarn -Wpacked" + dontwarn="$dontwarn -Wunused-macros" + dontwarn="$dontwarn -W" + dontwarn="$dontwarn -Woverlength-strings" + dontwarn="$dontwarn -Wmissing-format-attribute" + dontwarn="$dontwarn -Wstack-protector" + + # Get all possible GCC warnings + gl_MANYWARN_ALL_GCC([maybewarn]) + + # Remove the ones we don't want, blacklisted earlier + gl_MANYWARN_COMPLEMENT([wantwarn], [$maybewarn], [$dontwarn]) + + # Check for $CC support of each warning + for w in $wantwarn; do + gl_WARN_ADD([$w]) + done + + # This should be < 256 really, but with PATH_MAX everywhere + # we have doom, even with 4096. In fact we have some functions + # with several PATH_MAX sized variables :-( We should kill off + # all PATH_MAX usage and then lower this limit + gl_WARN_ADD([-Wframe-larger-than=20480]) + dnl gl_WARN_ADD([-Wframe-larger-than=4096]) + dnl gl_WARN_ADD([-Wframe-larger-than=256]) + + # Extra special flags + gl_WARN_ADD([-Wp,-D_FORTIFY_SOURCE=2]) + dnl Fedora only uses -fstack-protector, but doesn't seem to + dnl be great overhead in adding -fstack-protector-all instead + dnl gl_WARN_ADD([-fstack-protector]) + gl_WARN_ADD([-fstack-protector-all]) + gl_WARN_ADD([--param=ssp-buffer-size=4]) + gl_WARN_ADD([-fexceptions]) + gl_WARN_ADD([-fasynchronous-unwind-tables]) + gl_WARN_ADD([-fdiagnostics-show-option]) + + if test "$enable_compile_warnings" = "error" + then + gl_WARN_ADD([-Werror]) + fi ;; *) AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings) ;; esac - COMPILER_FLAGS= - for option in $try_compiler_flags; do - gl_COMPILER_FLAGS($option) - done - unset option - unset try_compiler_flags - - AC_ARG_ENABLE(iso-c, - AC_HELP_STRING([--enable-iso-c], - [Try to warn if code is not ISO C ]),, - [enable_iso_c=no]) - - AC_MSG_CHECKING(what language compliance flags to pass to the C compiler) - complCFLAGS= - if test "x$enable_iso_c" != "xno"; then - if test "x$GCC" = "xyes"; then - case " $CFLAGS " in - *[\ \ ]-ansi[\ \ ]*) ;; - *) complCFLAGS="$complCFLAGS -ansi" ;; - esac - case " $CFLAGS " in - *[\ \ ]-pedantic[\ \ ]*) ;; - *) complCFLAGS="$complCFLAGS -pedantic" ;; - esac - fi - fi - AC_MSG_RESULT($complCFLAGS) - - WARN_CFLAGS="$COMPILER_FLAGS $complCFLAGS" WARN_LDFLAGS=$WARN_CFLAGS AC_SUBST([WARN_CFLAGS]) AC_SUBST([WARN_LDFLAGS]) dnl Needed to keep compile quiet on python 2.4 - COMPILER_FLAGS= - gl_COMPILER_FLAGS(-Wno-redundant-decls) - WARN_PYTHON_CFLAGS=$COMPILER_FLAGS + save_WARN_CFLAGS=$WARN_CFLAGS + WARN_CFLAGS= + gl_WARN_ADD(-Wno-redundant-decls) + WARN_PYTHON_CFLAGS=$WARN_CFLAGS AC_SUBST(WARN_PYTHON_CFLAGS) + WARN_CFLAGS=$save_WARN_CFLAGS ]) diff --git a/bootstrap.conf b/bootstrap.conf index 733c354..e8cdf76 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -45,6 +45,7 @@ ignore-value inet_pton ioctl maintainer-makefile +manywarnings mkstemp mkstemps mktempd @@ -80,6 +81,7 @@ timegm uname useless-if-before-free usleep +warnings vasprintf verify vc-list-files diff --git a/configure.ac b/configure.ac index 2378d9a..0b9855b 100644 --- a/configure.ac +++ b/configure.ac @@ -1970,12 +1970,14 @@ AC_ARG_ENABLE([test-coverage], enable_coverage=$enableval if test "${enable_coverage}" = yes; then - COMPILER_FLAGS= - gl_COMPILER_FLAGS(-fprofile-arcs) - gl_COMPILER_FLAGS(-ftest-coverage) - AC_SUBST([COVERAGE_CFLAGS], [$COMPILER_FLAGS]) - AC_SUBST([COVERAGE_LDFLAGS], [$COMPILER_FLAGS]) - COMPILER_FLAGS= + save_WARN_CFLAGS=$WARN_CFLAGS + WARN_CFLAGS= + gl_WARN_ADD(-fprofile-arcs) + gl_WARN_ADD(-ftest-coverage) + COVERAGE_FLAGS=$WARN_CFLAGS + AC_SUBST([COVERAGE_CFLAGS], [$COVERAGE_FLAGS]) + AC_SUBST([COVERAGE_LDFLAGS], [$COVERAGE_FLAGS]) + WARN_CFLAGS=$save_WARN_CFLAGS fi AC_ARG_ENABLE([test-oom], @@ -2538,6 +2540,7 @@ AC_MSG_NOTICE([Miscellaneous]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([ Debug: $enable_debug]) AC_MSG_NOTICE([ Warnings: $enable_compile_warnings]) +AC_MSG_NOTICE([Warning Flags: $WARN_CFLAGS]) AC_MSG_NOTICE([ Readline: $lv_use_readline]) AC_MSG_NOTICE([ Python: $with_python]) AC_MSG_NOTICE([ DTrace: $with_dtrace]) diff --git a/m4/compiler-flags.m4 b/m4/compiler-flags.m4 deleted file mode 100644 index 6db4816..0000000 --- a/m4/compiler-flags.m4 +++ /dev/null @@ -1,48 +0,0 @@ -# serial 4 -# Find valid warning flags for the C Compiler. -*-Autoconf-*- -# -# Copyright (C) 2010 Red Hat, Inc. -# Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 USA - -# Written by Jesse Thilo. - -AC_DEFUN([gl_COMPILER_FLAGS], - [AC_MSG_CHECKING(whether compiler accepts $1) - ac_save_CFLAGS="$CFLAGS" - dnl Some flags are dependant, so we set all previously checked - dnl flags when testing. Except for -Werror which we have to - dnl check on its own, because some of our compiler flags cause - dnl warnings from the autoconf test program! - if test "$1" = "-Werror" ; then - CFLAGS="$CFLAGS $1" - else - CFLAGS="$CFLAGS $COMPILER_FLAGS $1" - fi - AC_TRY_LINK([], [], has_option=yes, has_option=no,) - echo 'int x;' >conftest.c - $CC $CFLAGS -c conftest.c 2>conftest.err - ret=$? - if test $ret != 0 || test -s conftest.err || test $has_option = "no"; then - AC_MSG_RESULT(no) - else - AC_MSG_RESULT(yes) - COMPILER_FLAGS="$COMPILER_FLAGS $1" - fi - CFLAGS="$ac_save_CFLAGS" - rm -f conftest* - ]) -- 1.7.4 From eblake at redhat.com Fri Apr 1 15:39:41 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 09:39:41 -0600 Subject: [libvirt] [PATCH 1/7] screenshot: Defining the public API In-Reply-To: <1301671761-367-2-git-send-email-mprivozn@redhat.com> References: <1301671761-367-1-git-send-email-mprivozn@redhat.com> <1301671761-367-2-git-send-email-mprivozn@redhat.com> Message-ID: <4D95F1BD.80600@redhat.com> On 04/01/2011 09:29 AM, Michal Privoznik wrote: > --- > include/libvirt/libvirt.h.in | 7 +++++++ > src/libvirt_public.syms | 1 + > 2 files changed, 8 insertions(+), 0 deletions(-) Hmm, we've already declared 0.9.0 feature freeze; > +++ b/src/libvirt_public.syms > @@ -428,6 +428,7 @@ LIBVIRT_0.9.0 { > global: > virDomainGetBlkioParameters; > virDomainMigrateSetMaxSpeed; > + virDomainScreenshot; > virDomainSetBlkioParameters; > virDomainSetMemoryFlags; > virEventRegisterDefaultImpl; So this needs to be reworked to start a new section for LIBVIRT_0.9.1, and defer this series until after the release. While it's probably a low-risk API addition, we're setting a bad precedent if we let this in this late after the release candidate and this close to the final release. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 1 15:50:22 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 1 Apr 2011 09:50:22 -0600 Subject: [libvirt] [PATCH] build: detect potentential uninitialized variables Message-ID: <1301673022-7410-1-git-send-email-eblake@redhat.com> Even with -Wuninitialized (which is part of autobuild.sh --enable-compile-warnings=error), gcc does NOT catch this use of an uninitialized variable: { if (cond) goto error; int a = 1; error: printf("%d", a); } which prints 0 (if the stack was previously wiped) if cond was true. Clang will catch it, but we dont' use clang as often. Using gcc -Wjump-misses-init gives false positives: { if (cond) goto error; int a = 1; return a; error: return 0; } Here, a was never used in the scope of the error block, so declaring it after goto is technically fine (and clang agrees); however, given that our HACKING already documents a preference to C89 decl-before-statement, the false positive warning is enough of a prod to comply with HACKING. [Personally, I'd _really_ rather use C99 decl-after-statement to minimize scope, but until gcc can efficiently and reliably catch scoping and uninitialized usage bugs, I'll settle with the compromise of enforcing a coding standard that rejects false positives.] * acinclude.m4 (LIBVIRT_COMPILE_WARNINGS): Add -Wjump-misses-init. * src/util/util.c (__virExec): Adjust offenders. * src/conf/domain_conf.c (virDomainTimerDefParseXML): Likewise. * src/remote/remote_driver.c (doRemoteOpen): Likewise. * src/phyp/phyp_driver.c (phypGetLparNAME, phypGetLparProfile) (phypGetVIOSFreeSCSIAdapter, phypVolumeGetKey) (phypGetStoragePoolDevice) (phypVolumeGetPhysicalVolumeByStoragePool) (phypVolumeGetPath): Likewise. * src/vbox/vbox_tmpl.c (vboxNetworkUndefineDestroy) (vboxNetworkCreate, vboxNetworkDumpXML) (vboxNetworkDefineCreateXML): Likewise. * src/xenapi/xenapi_driver.c (getCapsObject) (xenapiDomainDumpXML): Likewise. * src/xenapi/xenapi_utils.c (createVMRecordFromXml): Likewise. * src/security/security_selinux.c (SELinuxGenNewContext): Likewise. * src/qemu/qemu_command.c (qemuBuildCommandLine): Likewise. * src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia): Likewise. * src/qemu/qemu_process.c (qemuProcessWaitForMonitor): Likewise. * src/qemu/qemu_monitor_text.c (qemuMonitorTextGetPtyPaths): Likewise. * src/qemu/qemu_driver.c (qemudDomainShutdown) (qemudDomainBlockStats, qemudDomainMemoryPeek): Likewise. * src/storage/storage_backend_iscsi.c (virStorageBackendCreateIfaceIQN): Likewise. * src/node_device/node_device_udev.c (udevProcessPCI): Likewise. --- acinclude.m4 | 1 + src/conf/domain_conf.c | 6 ++++-- src/node_device/node_device_udev.c | 3 ++- src/phyp/phyp_driver.c | 24 ++++++++++++++++-------- src/qemu/qemu_command.c | 6 ++++-- src/qemu/qemu_driver.c | 9 ++++++--- src/qemu/qemu_hotplug.c | 4 ++-- src/qemu/qemu_monitor_text.c | 2 +- src/qemu/qemu_process.c | 3 ++- src/remote/remote_driver.c | 12 +++++++----- src/security/security_selinux.c | 3 ++- src/storage/storage_backend_iscsi.c | 25 ++++++++++++------------- src/util/util.c | 3 ++- src/vbox/vbox_tmpl.c | 28 ++++++++++++++-------------- src/xenapi/xenapi_driver.c | 24 ++++++++++++++---------- src/xenapi/xenapi_utils.c | 10 ++++++---- 16 files changed, 95 insertions(+), 68 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 838ec46..22eb7af 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -49,6 +49,7 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ try_compiler_flags="$try_compiler_flags -Wredundant-decls" try_compiler_flags="$try_compiler_flags -Wno-sign-compare" try_compiler_flags="$try_compiler_flags -Wlogical-op" + try_compiler_flags="$try_compiler_flags -Wjump-misses-init" try_compiler_flags="$try_compiler_flags $common_flags" if test "$enable_compile_warnings" = "error" ; then try_compiler_flags="$try_compiler_flags -Werror" diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b6aaf33..90a1317 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3557,6 +3557,8 @@ virDomainTimerDefParseXML(const xmlNodePtr node, virDomainTimerDefPtr def; xmlNodePtr oldnode = ctxt->node; + xmlNodePtr catchup; + int ret; if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -3610,7 +3612,7 @@ virDomainTimerDefParseXML(const xmlNodePtr node, } } - int ret = virXPathULong("string(./frequency)", ctxt, &def->frequency); + ret = virXPathULong("string(./frequency)", ctxt, &def->frequency); if (ret == -1) { def->frequency = 0; } else if (ret < 0) { @@ -3629,7 +3631,7 @@ virDomainTimerDefParseXML(const xmlNodePtr node, } } - xmlNodePtr catchup = virXPathNode("./catchup", ctxt); + catchup = virXPathNode("./catchup", ctxt); if (catchup != NULL) { ret = virXPathULong("string(./catchup/@threshold)", ctxt, &def->catchup.threshold); diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index 44df16e..372f1d1 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -415,6 +415,7 @@ static int udevProcessPCI(struct udev_device *device, const char *syspath = NULL; union _virNodeDevCapData *data = &def->caps->data; int ret = -1; + char *p; syspath = udev_device_get_syspath(device); @@ -425,7 +426,7 @@ static int udevProcessPCI(struct udev_device *device, goto out; } - char *p = strrchr(syspath, '/'); + p = strrchr(syspath, '/'); if ((p == NULL) || (udevStrToLong_ui(p+1, &p, diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 51f9ff6..b17d90b 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -1337,6 +1337,7 @@ phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system, char *ret = NULL; int exit_status = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; + char *char_ptr; virBufferAddLit(&buf, "lssyscfg -r lpar"); if (system_type == HMC) @@ -1354,7 +1355,7 @@ phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system, if (exit_status < 0 || ret == NULL) goto err; - char *char_ptr = strchr(ret, '\n'); + char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; @@ -1675,6 +1676,7 @@ phypGetLparProfile(virConnectPtr conn, int lpar_id) char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; + char *char_ptr; virBufferAddLit(&buf, "lssyscfg"); if (system_type == HMC) @@ -1694,7 +1696,7 @@ phypGetLparProfile(virConnectPtr conn, int lpar_id) if (exit_status < 0 || ret == NULL) goto err; - char *char_ptr = strchr(ret, '\n'); + char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; @@ -1892,6 +1894,7 @@ phypGetVIOSFreeSCSIAdapter(virConnectPtr conn) char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; + char *char_ptr; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -1916,7 +1919,7 @@ phypGetVIOSFreeSCSIAdapter(virConnectPtr conn) if (exit_status < 0 || ret == NULL) goto err; - char *char_ptr = strchr(ret, '\n'); + char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; @@ -2154,6 +2157,7 @@ phypVolumeGetKey(virConnectPtr conn, char *key, const char *name) char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; + char *char_ptr; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -2178,7 +2182,7 @@ phypVolumeGetKey(virConnectPtr conn, char *key, const char *name) if (exit_status < 0 || ret == NULL) goto err; - char *char_ptr = strchr(ret, '\n'); + char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; @@ -2209,6 +2213,7 @@ phypGetStoragePoolDevice(virConnectPtr conn, char *name) char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; + char *char_ptr; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -2233,7 +2238,7 @@ phypGetStoragePoolDevice(virConnectPtr conn, char *name) if (exit_status < 0 || ret == NULL) goto err; - char *char_ptr = strchr(ret, '\n'); + char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; @@ -2474,6 +2479,7 @@ phypVolumeGetPhysicalVolumeByStoragePool(virStorageVolPtr vol, char *sp) char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; + char *char_ptr; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -2498,7 +2504,7 @@ phypVolumeGetPhysicalVolumeByStoragePool(virStorageVolPtr vol, char *sp) if (exit_status < 0 || ret == NULL) goto err; - char *char_ptr = strchr(ret, '\n'); + char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; @@ -2723,6 +2729,8 @@ phypVolumeGetPath(virStorageVolPtr vol) char *sp = NULL; char *path = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; + char *char_ptr; + char *pv; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -2748,12 +2756,12 @@ phypVolumeGetPath(virStorageVolPtr vol) if (exit_status < 0 || sp == NULL) goto err; - char *char_ptr = strchr(sp, '\n'); + char_ptr = strchr(sp, '\n'); if (char_ptr) *char_ptr = '\0'; - char *pv = phypVolumeGetPhysicalVolumeByStoragePool(vol, sp); + pv = phypVolumeGetPhysicalVolumeByStoragePool(vol, sp); if (pv) { if (virAsprintf(&path, "/%s/%s/%s", pv, sp, vol->name) < 0) { diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 3138943..3d25ba4 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3727,6 +3727,8 @@ qemuBuildCommandLine(virConnectPtr conn, for (i = 0 ; i < def->nchannels ; i++) { virDomainChrDefPtr channel = def->channels[i]; char *devstr; + char *addr; + int port; switch(channel->targetType) { case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD: @@ -3745,10 +3747,10 @@ qemuBuildCommandLine(virConnectPtr conn, virCommandAddArg(cmd, devstr); VIR_FREE(devstr); - char *addr = virSocketFormatAddr(channel->target.addr); + addr = virSocketFormatAddr(channel->target.addr); if (!addr) goto error; - int port = virSocketGetPort(channel->target.addr); + port = virSocketGetPort(channel->target.addr); virCommandAddArg(cmd, "-netdev"); virCommandAddArgFormat(cmd, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5aa715e..48fe266 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1426,6 +1426,7 @@ static int qemudDomainShutdown(virDomainPtr dom) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; + qemuDomainObjPrivatePtr priv; qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -1448,7 +1449,7 @@ static int qemudDomainShutdown(virDomainPtr dom) { goto endjob; } - qemuDomainObjPrivatePtr priv = vm->privateData; + priv = vm->privateData; qemuDomainObjEnterMonitor(vm); ret = qemuMonitorSystemPowerdown(priv->mon); qemuDomainObjExitMonitor(vm); @@ -4748,6 +4749,7 @@ qemudDomainBlockStats (virDomainPtr dom, int i, ret = -1; virDomainObjPtr vm; virDomainDiskDefPtr disk = NULL; + qemuDomainObjPrivatePtr priv; qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -4788,7 +4790,7 @@ qemudDomainBlockStats (virDomainPtr dom, goto endjob; } - qemuDomainObjPrivatePtr priv = vm->privateData; + priv = vm->privateData; qemuDomainObjEnterMonitor(vm); ret = qemuMonitorGetBlockStatsInfo(priv->mon, disk->info.alias, @@ -4995,6 +4997,7 @@ qemudDomainMemoryPeek (virDomainPtr dom, virDomainObjPtr vm; char *tmp = NULL; int fd = -1, ret = -1; + qemuDomainObjPrivatePtr priv; qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -5035,7 +5038,7 @@ qemudDomainMemoryPeek (virDomainPtr dom, goto endjob; } - qemuDomainObjPrivatePtr priv = vm->privateData; + priv = vm->privateData; qemuDomainObjEnterMonitor(vm); if (flags == VIR_MEMORY_VIRTUAL) { if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) { diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 9082515..b03f774 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -51,8 +51,8 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver, int i; int ret; char *driveAlias = NULL; + qemuDomainObjPrivatePtr priv; - origdisk = NULL; for (i = 0 ; i < vm->def->ndisks ; i++) { if (vm->def->disks[i]->bus == disk->bus && STREQ(vm->def->disks[i]->dst, disk->dst)) { @@ -90,7 +90,7 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver, if (!(driveAlias = qemuDeviceDriveHostAlias(origdisk, qemuCaps))) goto error; - qemuDomainObjPrivatePtr priv = vm->privateData; + priv = vm->privateData; qemuDomainObjEnterMonitorWithDriver(driver, vm); if (disk->src) { const char *format = NULL; diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 168c60f..53781c8 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1873,7 +1873,7 @@ int qemuMonitorTextGetPtyPaths(qemuMonitorPtr mon, if (qemuMonitorHMPCommand(mon, "info chardev", &reply) < 0) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to retrieve chardev info in qemu with 'info chardev'")); - goto cleanup; + return -1; } char *pos; /* The current start of searching */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 2fc2b6c..870d942 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1017,6 +1017,7 @@ qemuProcessWaitForMonitor(struct qemud_driver* driver, int logfd; int ret = -1; virHashTablePtr paths = NULL; + qemuDomainObjPrivatePtr priv; if ((logfd = qemuProcessLogReadFD(driver->logDir, vm->def->name, pos)) < 0) return -1; @@ -1039,7 +1040,7 @@ qemuProcessWaitForMonitor(struct qemud_driver* driver, if (paths == NULL) goto cleanup; - qemuDomainObjPrivatePtr priv = vm->privateData; + priv = vm->privateData; qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorGetPtyPaths(priv->mon, paths); qemuDomainObjExitMonitorWithDriver(driver, vm); diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index bf94e70..166968a 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -869,12 +869,14 @@ doRemoteOpen (virConnectPtr conn, goto failed; /* Finally we can call the remote side's open function. */ - remote_open_args args = { &name, flags }; + { + remote_open_args args = { &name, flags }; - if (call (conn, priv, REMOTE_CALL_IN_OPEN, REMOTE_PROC_OPEN, - (xdrproc_t) xdr_remote_open_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto failed; + if (call (conn, priv, REMOTE_CALL_IN_OPEN, REMOTE_PROC_OPEN, + (xdrproc_t) xdr_remote_open_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto failed; + } /* Now try and find out what URI the daemon used */ if (conn->uri == NULL) { diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 587b3b5..d870616 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -95,8 +95,9 @@ SELinuxGenNewContext(const char *oldcontext, const char *mcs) { char *newcontext = NULL; char *scontext = strdup(oldcontext); + context_t con; if (!scontext) goto err; - context_t con = context_new(scontext); + con = context_new(scontext); if (!con) goto err; context_range_set(con, mcs); newcontext = strdup(context_str(con)); diff --git a/src/storage/storage_backend_iscsi.c b/src/storage/storage_backend_iscsi.c index 6eff5f5..f554537 100644 --- a/src/storage/storage_backend_iscsi.c +++ b/src/storage/storage_backend_iscsi.c @@ -1,7 +1,7 @@ /* * storage_backend_iscsi.c: storage backend for iSCSI handling * - * Copyright (C) 2007-2008, 2010 Red Hat, Inc. + * Copyright (C) 2007-2008, 2010-2011 Red Hat, Inc. * Copyright (C) 2007-2008 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -269,6 +269,15 @@ virStorageBackendCreateIfaceIQN(const char *initiatoriqn, { int ret = -1, exitstatus = -1; char temp_ifacename[32]; + const char *const cmdargv1[] = { + ISCSIADM, "--mode", "iface", "--interface", + temp_ifacename, "--op", "new", NULL + }; + const char *const cmdargv2[] = { + ISCSIADM, "--mode", "iface", "--interface", temp_ifacename, + "--op", "update", "--name", "iface.initiatorname", "--value", + initiatoriqn, NULL + }; if (virRandomInitialize(time(NULL) ^ getpid()) == -1) { virStorageReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -277,12 +286,8 @@ virStorageBackendCreateIfaceIQN(const char *initiatoriqn, goto out; } - snprintf(temp_ifacename, sizeof(temp_ifacename), "libvirt-iface-%08x", virRandom(1024 * 1024 * 1024)); - - const char *const cmdargv1[] = { - ISCSIADM, "--mode", "iface", "--interface", - &temp_ifacename[0], "--op", "new", NULL - }; + snprintf(temp_ifacename, sizeof(temp_ifacename), "libvirt-iface-%08x", + virRandom(1024 * 1024 * 1024)); VIR_DEBUG("Attempting to create interface '%s' with IQN '%s'", &temp_ifacename[0], initiatoriqn); @@ -298,12 +303,6 @@ virStorageBackendCreateIfaceIQN(const char *initiatoriqn, goto out; } - const char *const cmdargv2[] = { - ISCSIADM, "--mode", "iface", "--interface", &temp_ifacename[0], - "--op", "update", "--name", "iface.initiatorname", "--value", - initiatoriqn, NULL - }; - /* Note that we ignore the exitstatus. Older versions of iscsiadm tools * returned an exit status of > 0, even if they succeeded. We will just * rely on whether iface file got updated properly. */ diff --git a/src/util/util.c b/src/util/util.c index 43794b1..7384517 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -467,6 +467,7 @@ __virExec(const char *const*argv, int childerr = -1; int tmpfd; const char *binary = NULL; + int forkRet; if (argv[0][0] != '/') { if (!(binary = virFindFileInPath(argv[0]))) { @@ -544,7 +545,7 @@ __virExec(const char *const*argv, childerr = null; } - int forkRet = virFork(&pid); + forkRet = virFork(&pid); if (pid < 0) { goto cleanup; diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 8bd27dd..0fbfba5 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -7186,12 +7186,15 @@ static virNetworkPtr vboxNetworkDefineCreateXML(virConnectPtr conn, const char * } } #else /* VBOX_API_VERSION != 2002 */ - IProgress *progress = NULL; - host->vtbl->CreateHostOnlyNetworkInterface(host, &networkInterface, &progress); + { + IProgress *progress = NULL; + host->vtbl->CreateHostOnlyNetworkInterface(host, &networkInterface, + &progress); - if (progress) { - progress->vtbl->WaitForCompletion(progress, -1); - VBOX_RELEASE(progress); + if (progress) { + progress->vtbl->WaitForCompletion(progress, -1); + VBOX_RELEASE(progress); + } } #endif /* VBOX_API_VERSION != 2002 */ @@ -7342,6 +7345,8 @@ static virNetworkPtr vboxNetworkDefineXML(virConnectPtr conn, const char *xml) { static int vboxNetworkUndefineDestroy(virNetworkPtr network, bool removeinterface) { VBOX_OBJECT_HOST_CHECK(network->conn, int, -1); char *networkNameUtf8 = NULL; + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; /* Current limitation of the function for VirtualBox 2.2.* is * that you can't delete the default hostonly adaptor namely: @@ -7356,9 +7361,6 @@ static int vboxNetworkUndefineDestroy(virNetworkPtr network, bool removeinterfac goto cleanup; } - PRUnichar *networkInterfaceNameUtf16 = NULL; - IHostNetworkInterface *networkInterface = NULL; - VBOX_UTF8_TO_UTF16(network->name, &networkInterfaceNameUtf16); host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); @@ -7433,6 +7435,8 @@ static int vboxNetworkUndefine(virNetworkPtr network) { static int vboxNetworkCreate(virNetworkPtr network) { VBOX_OBJECT_HOST_CHECK(network->conn, int, -1); char *networkNameUtf8 = NULL; + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; /* Current limitation of the function for VirtualBox 2.2.* is * that the default hostonly network "vboxnet0" is always active @@ -7446,9 +7450,6 @@ static int vboxNetworkCreate(virNetworkPtr network) { goto cleanup; } - PRUnichar *networkInterfaceNameUtf16 = NULL; - IHostNetworkInterface *networkInterface = NULL; - VBOX_UTF8_TO_UTF16(network->name, &networkInterfaceNameUtf16); host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); @@ -7509,6 +7510,8 @@ static char *vboxNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSE virNetworkDefPtr def = NULL; virNetworkIpDefPtr ipdef = NULL; char *networkNameUtf8 = NULL; + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -7526,9 +7529,6 @@ static char *vboxNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSE goto cleanup; } - PRUnichar *networkInterfaceNameUtf16 = NULL; - IHostNetworkInterface *networkInterface = NULL; - VBOX_UTF8_TO_UTF16(network->name, &networkInterfaceNameUtf16); host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 27206a0..60b23c7 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -56,21 +56,24 @@ static virCapsPtr getCapsObject (void) { + virCapsGuestPtr guest1, guest2; + virCapsGuestDomainPtr domain1, domain2; virCapsPtr caps = virCapabilitiesNew("x86_64", 0, 0); + if (!caps) { virReportOOMError(); return NULL; } - virCapsGuestPtr guest1 = virCapabilitiesAddGuest(caps, "hvm", "x86_64", 0, "", "", 0, NULL); + guest1 = virCapabilitiesAddGuest(caps, "hvm", "x86_64", 0, "", "", 0, NULL); if (!guest1) goto error_cleanup; - virCapsGuestDomainPtr domain1 = virCapabilitiesAddGuestDomain(guest1, "xen", "", "", 0, NULL); + domain1 = virCapabilitiesAddGuestDomain(guest1, "xen", "", "", 0, NULL); if (!domain1) goto error_cleanup; - virCapsGuestPtr guest2 = virCapabilitiesAddGuest(caps, "xen", "x86_64", 0, "", "", 0, NULL); + guest2 = virCapabilitiesAddGuest(caps, "xen", "x86_64", 0, "", "", 0, NULL); if (!guest2) goto error_cleanup; - virCapsGuestDomainPtr domain2 = virCapabilitiesAddGuestDomain(guest2, "xen", "", "", 0, NULL); + domain2 = virCapabilitiesAddGuestDomain(guest2, "xen", "", "", 0, NULL); if (!domain2) goto error_cleanup; @@ -1234,6 +1237,12 @@ xenapiDomainDumpXML (virDomainPtr dom, int flags ATTRIBUTE_UNUSED) xen_string_string_map *result=NULL; xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; virDomainDefPtr defPtr = NULL; + char *boot_policy = NULL; + unsigned long memory=0; + int64_t dynamic_mem=0; + char *val = NULL; + struct xen_vif_set *vif_set = NULL; + char *xml; if (!xen_vm_get_by_name_label(session, &vms, dom->name)) return NULL; if (vms->size != 1) { @@ -1253,7 +1262,6 @@ xenapiDomainDumpXML (virDomainPtr dom, int flags ATTRIBUTE_UNUSED) memcpy(defPtr->uuid, dom->uuid, VIR_UUID_BUFLEN); if (!(defPtr->name = strdup(dom->name))) goto error_cleanup; - char *boot_policy = NULL; xen_vm_get_hvm_boot_policy(session, &boot_policy, vm); if (STREQ(boot_policy,"BIOS order")) { if (!(defPtr->os.type = strdup("hvm"))) { @@ -1318,7 +1326,6 @@ xenapiDomainDumpXML (virDomainPtr dom, int flags ATTRIBUTE_UNUSED) if (!(defPtr->os.bootloader = strdup("pygrub"))) goto error_cleanup; } - char *val = NULL; xen_vm_get_pv_bootloader_args(session, &val, vm); if (STRNEQ(val, "")) { if (!(defPtr->os.bootloaderArgs = strdup(val))) { @@ -1327,10 +1334,8 @@ xenapiDomainDumpXML (virDomainPtr dom, int flags ATTRIBUTE_UNUSED) } VIR_FREE(val); } - unsigned long memory=0; memory = xenapiDomainGetMaxMemory(dom); defPtr->mem.max_balloon = memory; - int64_t dynamic_mem=0; if (xen_vm_get_memory_dynamic_max(session, &dynamic_mem, vm)) { defPtr->mem.cur_balloon = (unsigned long) (dynamic_mem / 1024); } else { @@ -1365,7 +1370,6 @@ xenapiDomainDumpXML (virDomainPtr dom, int flags ATTRIBUTE_UNUSED) } xen_string_string_map_free(result); } - struct xen_vif_set *vif_set = NULL; xen_vm_get_vifs(session, &vif_set, vm); if (vif_set) { int i; @@ -1403,7 +1407,7 @@ xenapiDomainDumpXML (virDomainPtr dom, int flags ATTRIBUTE_UNUSED) xen_vif_set_free(vif_set); } if (vms) xen_vm_set_free(vms); - char *xml = virDomainDefFormat(defPtr, 0); + xml = virDomainDefFormat(defPtr, 0); virDomainDefFree(defPtr); return xml; diff --git a/src/xenapi/xenapi_utils.c b/src/xenapi/xenapi_utils.c index 2ec5f9e..f50610a 100644 --- a/src/xenapi/xenapi_utils.c +++ b/src/xenapi/xenapi_utils.c @@ -1,5 +1,6 @@ /* * xenapi_utils.c: Xen API driver -- utils parts. + * Copyright (C) 2011 Red Hat, Inc. * Copyright (C) 2009, 2010 Citrix Ltd. * * This library is free software; you can redistribute it and/or @@ -462,6 +463,11 @@ createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def, xen_vm_record **record, xen_vm *vm) { char uuidStr[VIR_UUID_STRING_BUFLEN]; + xen_string_string_map *strings = NULL; + int device_number = 0; + char *bridge = NULL, *mac = NULL; + int i; + *record = xen_vm_record_alloc(); if (!((*record)->name_label = strdup(def->name))) goto error_cleanup; @@ -521,7 +527,6 @@ createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def, if (def->onCrash) (*record)->actions_after_crash = actionCrashLibvirt2XenapiEnum(def->onCrash); - xen_string_string_map *strings = NULL; if (def->features) { if (def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)) allocStringMap(&strings, (char *)"acpi", (char *)"true"); @@ -546,9 +551,6 @@ createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def, return -1; } - int device_number = 0; - char *bridge = NULL, *mac = NULL; - int i; for (i = 0; i < def->nnets; i++) { if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { if (def->nets[i]->data.bridge.brname) -- 1.7.4 From eblake at redhat.com Fri Apr 1 16:02:18 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 10:02:18 -0600 Subject: [libvirt] [PATCH] Use gnulib's manywarnings & warnings modules In-Reply-To: <1301672345-31926-1-git-send-email-berrange@redhat.com> References: <1301672345-31926-1-git-send-email-berrange@redhat.com> Message-ID: <4D95F70A.80509@redhat.com> On 04/01/2011 09:39 AM, Daniel P. Berrange wrote: > Remove custom code for checking compiler warnings, using > gl_WARN_ADD instead. Don't list all flags ourselves, use > gnulib's gl_MANYWARN_ALL_GCC to get all possible GCC flags, > then turn off the ones we don't want yet. > > This patch alone doesn't buy us much. What we want is some > more followup patches, which remove entries from the > 'dontwarn' list, fixing up the corresponding code problems. Should we therefore defer this patch until post-0.9.0 when we can do more about the warnings cleanup? > > We also need to fix our stack usage in many places so we can > lower the ridiculous size of -Wframe-larger-than=20480 5 pages, ouch! Windows will (silently!) abort a process that has a page fault that jumps larger than the 1 page stack guard; a good goal is -Wframe-larger-than=4096. > > * acinclude.m4: Rewrite to use gl_WARN_ADD and gl_MANYWARN_ALL_GCC > * bootstrap.conf: Add warnings & manywarnings > * configure.ac: Switch to gl_WARN_ADD > * m4/compiler-flags.m4: Obsoleted by gl_WARN_ADD > --- > acinclude.m4 | 153 ++++++++++++++++++++++++++------------------------ I really don't like how we have crammed so much into acinclude.m4; it would be nicer if we could separate things into individual m4/foo.m4 files... > bootstrap.conf | 2 + > configure.ac | 15 +++-- > m4/compiler-flags.m4 | 48 ---------------- ...much like this used to be. But that's orthogonal to this patch. (It always takes me too long to figure out where the libvirt list of -W flags is to modify that list). > @@ -13,90 +8,102 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ > dnl ****************************** > > AC_ARG_ENABLE(compile-warnings, > - [AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@], > + [AC_HELP_STRING([--enable-compile-warnings=@<:@no/yes/error@:>@], > [Turn on compiler warnings])],, So we're getting rid of minimum and maximum (truthfully, I never used them). Sounds okay, especially since they weren't documented in HACKING (just in ./configure --help). > + yes|minimum|maximum|error) Hmm, so you still silently accept them, but they now are synonyms for yes. > + > + # List of warnings that are not relevant / wanted > + dontwarn="$dontwarn -Wc++-compat" # Don't care about C++ compiler compat > + dontwarn="$dontwarn -Wtraditional" # Don't care about ancient C standard compat > + dontwarn="$dontwarn -Wtraditional-conversion" # Don't care about ancient C standard compat > + dontwarn="$dontwarn -Wsystem-headers" # Ignore warnings in /usr/include > + dontwarn="$dontwarn -Wpadded" # Happy for compiler to add struct padding > + dontwarn="$dontwarn -Wunreachable-code" # GCC very confused with -O2 > + dontwarn="$dontwarn -Wconversion" # Too many to deal with > + dontwarn="$dontwarn -Wsign-conversion" # Too many to deal with > + dontwarn="$dontwarn -Wvla" # GNULIB gettext.h violates > + dontwarn="$dontwarn -Wundef" # Many GNULIB violations We really ought to follow coreutils' lead of generating two separate lists of -W flags - a larger set for libvirt and a smaller set for gnulib. Then exemptions such as -Wvla could be used just for gnulib. But that can be a followup patch. > + dontwarn="$dontwarn -Wcast-qual" # Need to allow bad cast for execve() > + dontwarn="$dontwarn -Wlong-long" # We need to use long long in many places > + > + # We might fundamentally need some of these disabled forever, but ideally > + # we'd turn many of them on > + dontwarn="$dontwarn -Wformat-nonliteral" > + dontwarn="$dontwarn -Wswitch-default" > + dontwarn="$dontwarn -Wswitch-enum" > + dontwarn="$dontwarn -Wstrict-overflow" > + dontwarn="$dontwarn -Wfloat-equal" > + dontwarn="$dontwarn -Wdeclaration-after-statement" > + dontwarn="$dontwarn -Wunsafe-loop-optimizations" > + dontwarn="$dontwarn -Wcast-qual" > + dontwarn="$dontwarn -Wconversion" > + dontwarn="$dontwarn -Wsign-conversion" > + dontwarn="$dontwarn -Wold-style-definition" > + dontwarn="$dontwarn -Wmissing-noreturn" > + dontwarn="$dontwarn -Wpacked" > + dontwarn="$dontwarn -Wunused-macros" > + dontwarn="$dontwarn -W" -W is the same as -Wextra - that turns on a lot of useful warnings. Can we fine-tune it to just disable the needed warnings? > + dontwarn="$dontwarn -Woverlength-strings" > + dontwarn="$dontwarn -Wmissing-format-attribute" > + dontwarn="$dontwarn -Wstack-protector" > + > + # Get all possible GCC warnings > + gl_MANYWARN_ALL_GCC([maybewarn]) > + > + # Remove the ones we don't want, blacklisted earlier > + gl_MANYWARN_COMPLEMENT([wantwarn], [$maybewarn], [$dontwarn]) > + > + # Check for $CC support of each warning > + for w in $wantwarn; do > + gl_WARN_ADD([$w]) > + done Yep, gnulib's macros are nice for this! > + > + # This should be < 256 really, but with PATH_MAX everywhere > + # we have doom, even with 4096. In fact we have some functions > + # with several PATH_MAX sized variables :-( We should kill off > + # all PATH_MAX usage and then lower this limit > + gl_WARN_ADD([-Wframe-larger-than=20480]) > + dnl gl_WARN_ADD([-Wframe-larger-than=4096]) > + dnl gl_WARN_ADD([-Wframe-larger-than=256]) 256 is a bit tight; I don't know of any platform where 4096 is an unreasonable bound for still reliably detecting stack overflow (then again, 4096 compared to 256 is 16 times more likely to stack overflow on a deeply nested call graph where every function in the graph uses a lot of stack). > + > + # Extra special flags > + gl_WARN_ADD([-Wp,-D_FORTIFY_SOURCE=2]) > + dnl Fedora only uses -fstack-protector, but doesn't seem to > + dnl be great overhead in adding -fstack-protector-all instead > + dnl gl_WARN_ADD([-fstack-protector]) > + gl_WARN_ADD([-fstack-protector-all]) > + gl_WARN_ADD([--param=ssp-buffer-size=4]) > + gl_WARN_ADD([-fexceptions]) > + gl_WARN_ADD([-fasynchronous-unwind-tables]) > + gl_WARN_ADD([-fdiagnostics-show-option]) > + > + if test "$enable_compile_warnings" = "error" > + then > + gl_WARN_ADD([-Werror]) > + fi > ;; > *) > AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings) > ;; > esac > > > AC_ARG_ENABLE([test-oom], > @@ -2538,6 +2540,7 @@ AC_MSG_NOTICE([Miscellaneous]) > AC_MSG_NOTICE([]) > AC_MSG_NOTICE([ Debug: $enable_debug]) > AC_MSG_NOTICE([ Warnings: $enable_compile_warnings]) > +AC_MSG_NOTICE([Warning Flags: $WARN_CFLAGS]) Nice configure summary addition. Overall, I like the direction of this patch. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From berrange at redhat.com Fri Apr 1 16:16:23 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 1 Apr 2011 17:16:23 +0100 Subject: [libvirt] [PATCH 1/7] screenshot: Defining the public API In-Reply-To: <1301671761-367-2-git-send-email-mprivozn@redhat.com> References: <1301671761-367-1-git-send-email-mprivozn@redhat.com> <1301671761-367-2-git-send-email-mprivozn@redhat.com> Message-ID: <20110401161623.GL29510@redhat.com> On Fri, Apr 01, 2011 at 05:29:15PM +0200, Michal Privoznik wrote: > --- > include/libvirt/libvirt.h.in | 7 +++++++ > src/libvirt_public.syms | 1 + > 2 files changed, 8 insertions(+), 0 deletions(-) > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > index bd36015..42711e6 100644 > --- a/include/libvirt/libvirt.h.in > +++ b/include/libvirt/libvirt.h.in > @@ -670,6 +670,13 @@ int virDomainCoreDump (virDomainPtr domain, > int flags); > > /* > + * Screenshot of current domain console > + */ > +int virDomainScreenshot (virDomainPtr domain, > + const char *to, > + int flags); I'm loathe to introduce any new APIs which accept a filename argument, because they're essentially useless for any app talking to libvirtd remotely, and often troublesome for non-privileged apps talking to privileged libvirtd. I think this API should instead use the virStreamPtr facility, making it follow the design of the virStorageVolDownload() API I recently added. A minor point is that 'flags' should be 'unsigned int' The question of file format is another interesting issue. We might want to actually return a string representing the mime-type of the output file. eg, char * virDomainScreenshot (virDomainPtr domain, virStreamPtr stream, unsigned int flags); char *mimetype = virDomainScreenshot(dom, st, 0); So then the client app can decide what file extension to use when saving the data, or when parsing it in memory. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From stefanb at linux.vnet.ibm.com Fri Apr 1 16:17:21 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Fri, 01 Apr 2011 12:17:21 -0400 Subject: [libvirt] [PATCH] nwfilters: support for TCP flags evaluation Message-ID: <4D95FA91.5080103@linux.vnet.ibm.com> This patch adds support for the evaluation of TCP flags in nwfilters. It adds documentation to the web page and extends the tests as well. Signed-off-by: Stefan Berger --- docs/formatnwfilter.html.in | 10 ++ docs/schemas/nwfilter.rng | 16 ++++ src/conf/nwfilter_conf.c | 115 +++++++++++++++++++++++++++--- src/conf/nwfilter_conf.h | 9 ++ src/libvirt_private.syms | 1 src/nwfilter/nwfilter_ebiptables_driver.c | 9 ++ tests/nwfilterxml2xmlin/tcp-test.xml | 12 +++ tests/nwfilterxml2xmlout/tcp-test.xml | 12 +++ 8 files changed, 174 insertions(+), 10 deletions(-) Index: libvirt-acl/src/conf/nwfilter_conf.c =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.c +++ libvirt-acl/src/conf/nwfilter_conf.c @@ -5,7 +5,8 @@ * Copyright (C) 2006-2011 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * - * Copyright (C) 2010 IBM Corporation + * Copyright (C) 2010-2011 IBM Corporation + * Copyright (C) 2010-2011 Stefan Berger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -726,17 +727,23 @@ printStringItems(virBufferPtr buf, const int32_t flags, const char *sep) { unsigned int i, c = 0; - int32_t last_attr = 0; + int32_t mask = 0x1; - for (i = 0; int_map[i].val; i++) { - if (last_attr != int_map[i].attr && - flags & int_map[i].attr) { - if (c >= 1) - virBufferVSprintf(buf, "%s", sep); - virBufferVSprintf(buf, "%s", int_map[i].val); - c++; + while (mask) { + if ((mask & flags)) { + for (i = 0; int_map[i].val; i++) { + if (mask == int_map[i].attr) { + if (c >= 1) + virBufferVSprintf(buf, "%s", sep); + virBufferVSprintf(buf, "%s", int_map[i].val); + c++; + } + } + flags ^= mask; + if (!flags) + break; } - last_attr = int_map[i].attr; + mask <<= 1; } return 0; @@ -799,6 +806,87 @@ stateFormatter(virBufferPtr buf, } + +static const struct int_map tcpFlags[] = { + INTMAP_ENTRY(0x1 , "FIN"), + INTMAP_ENTRY(0x2 , "SYN"), + INTMAP_ENTRY(0x4 , "RST"), + INTMAP_ENTRY(0x8 , "PSH"), + INTMAP_ENTRY(0x10, "ACK"), + INTMAP_ENTRY(0x20, "URG"), + INTMAP_ENTRY(0x3F, "ALL"), + INTMAP_ENTRY(0x0 , "NONE"), + INTMAP_ENTRY_LAST +}; + + +static bool +tcpFlagsValidator(enum attrDatatype datatype ATTRIBUTE_UNUSED, union data *val, + virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED, + nwItemDesc *item) +{ + bool rc = false; + char *s_mask = val->c; + char *sep = strchr(val->c, '/'); + char *s_flags; + int32_t mask = 0, flags = 0; + + if (!sep) + return false; + + s_flags = sep + 1; + + *sep = '\0'; + + if (!parseStringItems(tcpFlags, s_mask , &mask , ',') && + !parseStringItems(tcpFlags, s_flags, &flags, ',')) { + item->u.tcpFlags.mask = mask & 0x3f; + item->u.tcpFlags.flags = flags & 0x3f; + rc = true; + } + + *sep = '/'; + + return rc; +} + + +static void +printTCPFlags(virBufferPtr buf, uint8_t flags) +{ + if (flags == 0) + virBufferAddLit(buf, "NONE"); + else if (flags == 0x3f) + virBufferAddLit(buf, "ALL"); + else + printStringItems(buf, tcpFlags, flags, ","); +} + + +void +virNWFilterPrintTCPFlags(virBufferPtr buf, + uint8_t mask, char sep, uint8_t flags) +{ + printTCPFlags(buf, mask); + virBufferAddChar(buf, sep); + printTCPFlags(buf, flags); +} + + +static bool +tcpFlagsFormatter(virBufferPtr buf, + virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED, + nwItemDesc *item) +{ + virNWFilterPrintTCPFlags(buf, + item->u.tcpFlags.mask, + '/', + item->u.tcpFlags.flags); + + return true; +} + + #define COMMON_MAC_PROPS(STRUCT) \ {\ .name = SRCMACADDR,\ @@ -1104,6 +1192,13 @@ static const virXMLAttr2Struct tcpAttrib .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX, .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.dataTCPOption), }, + { + .name = "flags", + .datatype = DATATYPE_STRING, + .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.dataTCPFlags), + .validator = tcpFlagsValidator, + .formatter = tcpFlagsFormatter, + }, COMMENT_PROP_IPHDR(tcpHdrFilter), { .name = NULL, Index: libvirt-acl/src/conf/nwfilter_conf.h =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.h +++ libvirt-acl/src/conf/nwfilter_conf.h @@ -122,6 +122,10 @@ struct _nwItemDesc { uint16_t u16; char protocolID[10]; char *string; + struct { + uint8_t mask; + uint8_t flags; + } tcpFlags; } u; }; @@ -242,6 +246,7 @@ struct _tcpHdrFilterDef { ipHdrDataDef ipHdr; portDataDef portData; nwItemDesc dataTCPOption; + nwItemDesc dataTCPFlags; }; @@ -667,6 +672,10 @@ void virNWFilterCallbackDriversLock(void void virNWFilterCallbackDriversUnlock(void); +void virNWFilterPrintTCPFlags(virBufferPtr buf, uint8_t mask, + char sep, uint8_t flags); + + VIR_ENUM_DECL(virNWFilterRuleAction); VIR_ENUM_DECL(virNWFilterRuleDirection); VIR_ENUM_DECL(virNWFilterRuleProtocol); Index: libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_ebiptables_driver.c +++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c @@ -1204,6 +1204,15 @@ _iptablesCreateRuleInstance(int directio &prefix)) goto err_exit; + if (HAS_ENTRY_ITEM(&rule->p.tcpHdrFilter.dataTCPFlags)) { + virBufferVSprintf(&buf, " %s --tcp-flags ", + ENTRY_GET_NEG_SIGN(&rule->p.tcpHdrFilter.dataTCPFlags)); + virNWFilterPrintTCPFlags(&buf, + rule->p.tcpHdrFilter.dataTCPFlags.u.tcpFlags.mask, + ' ', + rule->p.tcpHdrFilter.dataTCPFlags.u.tcpFlags.flags); + } + if (iptablesHandlePortData(&buf, vars, &rule->p.tcpHdrFilter.portData, Index: libvirt-acl/docs/schemas/nwfilter.rng =================================================================== --- libvirt-acl.orig/docs/schemas/nwfilter.rng +++ libvirt-acl/docs/schemas/nwfilter.rng @@ -81,6 +81,7 @@ + @@ -184,6 +185,7 @@ + @@ -606,6 +608,14 @@ + + + + + + + + @@ -872,4 +882,10 @@ ((NEW|ESTABLISHED|RELATED|INVALID)(,(NEW|ESTABLISHED|RELATED|INVALID))*|NONE) + + + + ((SYN|ACK|URG|PSH|FIN|RST)(,(SYN|ACK|URG|PSH|FIN|RST))*|ALL|NONE)/((SYN|ACK|URG|PSH|FIN|RST)(,(SYN|ACK|URG|PSH|FIN|RST))*|ALL|NONE) + + Index: libvirt-acl/docs/formatnwfilter.html.in =================================================================== --- libvirt-acl.orig/docs/formatnwfilter.html.in +++ libvirt-acl/docs/formatnwfilter.html.in @@ -755,6 +755,11 @@ STRING comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE + + flags (Since 0.9.0) + STRING + TCP-only: format of mask/flags with mask and flags each being a comma separated list of SYN,ACK,URG,PSH,FIN,RST or NONE or ALL +



@@ -1040,6 +1045,11 @@ STRING comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE + + flags (Since 0.8.5) + STRING + format of mask/flags with mask and flags each being a comma separated list of SYN,ACK,URG,PSH,FIN,RST or NONE or ALL +



Index: libvirt-acl/src/libvirt_private.syms =================================================================== --- libvirt-acl.orig/src/libvirt_private.syms +++ libvirt-acl/src/libvirt_private.syms @@ -683,6 +683,7 @@ virNWFilterObjRemove; virNWFilterObjSaveDef; virNWFilterObjUnlock; virNWFilterPrintStateMatchFlags; +virNWFilterPrintTCPFlags; virNWFilterRegisterCallbackDriver; virNWFilterRuleActionTypeToString; virNWFilterRuleProtocolTypeToString; Index: libvirt-acl/tests/nwfilterxml2xmlin/tcp-test.xml =================================================================== --- libvirt-acl.orig/tests/nwfilterxml2xmlin/tcp-test.xml +++ libvirt-acl/tests/nwfilterxml2xmlin/tcp-test.xml @@ -19,4 +19,16 @@ srcportstart='255' srcportend='256' dstportstart='65535' dstportend='65536'/> + + + + + + + + + + + + Index: libvirt-acl/tests/nwfilterxml2xmlout/tcp-test.xml =================================================================== --- libvirt-acl.orig/tests/nwfilterxml2xmlout/tcp-test.xml +++ libvirt-acl/tests/nwfilterxml2xmlout/tcp-test.xml @@ -9,4 +9,16 @@ + + + + + + + + + + + + From stefanb at linux.vnet.ibm.com Fri Apr 1 16:17:32 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Fri, 01 Apr 2011 12:17:32 -0400 Subject: [libvirt] [TCK][PATCH] nwfilter: test support for TCP flags evaluation Message-ID: <4D95FA9C.4070706@linux.vnet.ibm.com> This patch extends an existing test with test cases for the TCP flags. Signed-off-by: Stefan Berger --- scripts/nwfilter/nwfilterxml2fwallout/tcp-test.fwall | 4 ++++ scripts/nwfilter/nwfilterxml2xmlin/tcp-test.xml | 12 ++++++++++++ 2 files changed, 16 insertions(+) Index: libvirt-tck/scripts/nwfilter/nwfilterxml2fwallout/tcp-test.fwall =================================================================== --- libvirt-tck.orig/scripts/nwfilter/nwfilterxml2fwallout/tcp-test.fwall +++ libvirt-tck/scripts/nwfilter/nwfilterxml2fwallout/tcp-test.fwall @@ -10,6 +10,10 @@ target prot opt source ACCEPT tcp -- 10.1.2.3 0.0.0.0/0 DSCP match 0x02state ESTABLISHED ctdir ORIGINAL ACCEPT tcp -- 10.1.2.3 0.0.0.0/0 MAC 01:02:03:04:05:06 DSCP match 0x21tcp spts:20:21 dpts:100:1111 ACCEPT tcp -- 10.1.2.3 0.0.0.0/0 MAC 01:02:03:04:05:06 DSCP match 0x3ftcp spts:255:256 dpt:65535 +ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp flags:0x02/0x3F +ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp flags:0x02/0x12 +ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp flags:0x04/0x00 +ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp flags:0x08/0x00 #iptables -L HI-vnet0 -n Chain HI-vnet0 (1 references) target prot opt source destination Index: libvirt-tck/scripts/nwfilter/nwfilterxml2xmlin/tcp-test.xml =================================================================== --- libvirt-tck.orig/scripts/nwfilter/nwfilterxml2xmlin/tcp-test.xml +++ libvirt-tck/scripts/nwfilter/nwfilterxml2xmlin/tcp-test.xml @@ -19,4 +19,16 @@ srcportstart='255' srcportend='256' dstportstart='65535' dstportend='65536'/> + + + + + + + + + + + + From eblake at redhat.com Fri Apr 1 16:19:20 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 10:19:20 -0600 Subject: [libvirt] [PATCH 1/6] virNodeGetCpuTime: Expose new API In-Reply-To: <20110401105548.a78607f7.usui@mxm.nes.nec.co.jp> References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> <20110401105548.a78607f7.usui@mxm.nes.nec.co.jp> Message-ID: <4D95FB08.20802@redhat.com> On 03/31/2011 07:55 PM, Minoru Usui wrote: > virNodeGetCpuTime: Expose new API > > include/libvirt/libvirt.h.in | 26 ++++++++++++++++++++++++++ > src/libvirt_public.syms | 1 + > 2 files changed, 27 insertions(+), 0 deletions(-) > > +/** > + * virNodeCpuTime: > + * > + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing > + * the information for the cpu time of Node. > + */ > + > +typedef struct _virNodeCpuTime virNodeCpuTime; > + > +struct _virNodeCpuTime { > + unsigned long long user; > + unsigned long long system; > + unsigned long long idle; > + unsigned long long iowait; > +}; Can we portably get all of this information on Windows? If not, how do you express which values we don't know how to obtain? > @@ -593,6 +616,9 @@ int virNodeGetInfo (virConnectPtr conn, > virNodeInfoPtr info); > char * virConnectGetCapabilities (virConnectPtr conn); > > +int virNodeGetCpuTime (virConnectPtr conn, > + virNodeCpuTimePtr cpu_time); > + Rather than locking ourselves into yet another inflexible API (no flags parameter and a hard-coded struct means no way to extend this if we ever come up with some new stat to query), should we instead be following the lead of getMemoryParameters which takes a typed-name/value array to pass an arbitrary number of parameters, which allows extension without a new API? > +++ b/src/libvirt_public.syms > @@ -434,6 +434,7 @@ LIBVIRT_0.9.0 { > virEventRunDefaultImpl; > virStorageVolDownload; > virStorageVolUpload; > + virNodeGetCpuTime; > } LIBVIRT_0.8.8; While I think that something along the lines of this API is appropriate for libvirt (indeed, knowing a host's CPU utilization can indeed be a factor for upper-level management software in deciding whether to migrate another domain on or off of the machine), it's too late to put it into 0.9.0. We'd be setting bad precedent by accepting this after the first release candidate did a feature freeze, so you'd need to adjust this to 0.9.1. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From berrange at redhat.com Fri Apr 1 16:24:18 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 1 Apr 2011 17:24:18 +0100 Subject: [libvirt] [TCK][PATCH] nwfilter: test support for TCP flags evaluation In-Reply-To: <4D95FA9C.4070706@linux.vnet.ibm.com> References: <4D95FA9C.4070706@linux.vnet.ibm.com> Message-ID: <20110401162418.GM29510@redhat.com> On Fri, Apr 01, 2011 at 12:17:32PM -0400, Stefan Berger wrote: > This patch extends an existing test with test cases for the TCP flags. > > Signed-off-by: Stefan Berger > > --- > scripts/nwfilter/nwfilterxml2fwallout/tcp-test.fwall | 4 ++++ > scripts/nwfilter/nwfilterxml2xmlin/tcp-test.xml | 12 ++++++++++++ > 2 files changed, 16 insertions(+) > > Index: libvirt-tck/scripts/nwfilter/nwfilterxml2fwallout/tcp-test.fwall > =================================================================== > --- libvirt-tck.orig/scripts/nwfilter/nwfilterxml2fwallout/tcp-test.fwall > +++ libvirt-tck/scripts/nwfilter/nwfilterxml2fwallout/tcp-test.fwall > @@ -10,6 +10,10 @@ target prot opt source > ACCEPT tcp -- 10.1.2.3 0.0.0.0/0 DSCP > match 0x02state ESTABLISHED ctdir ORIGINAL > ACCEPT tcp -- 10.1.2.3 0.0.0.0/0 MAC > 01:02:03:04:05:06 DSCP match 0x21tcp spts:20:21 dpts:100:1111 > ACCEPT tcp -- 10.1.2.3 0.0.0.0/0 MAC > 01:02:03:04:05:06 DSCP match 0x3ftcp spts:255:256 dpt:65535 > +ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp > flags:0x02/0x3F > +ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp > flags:0x02/0x12 > +ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp > flags:0x04/0x00 > +ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp > flags:0x08/0x00 > #iptables -L HI-vnet0 -n > Chain HI-vnet0 (1 references) > target prot opt source destination > Index: libvirt-tck/scripts/nwfilter/nwfilterxml2xmlin/tcp-test.xml > =================================================================== > --- libvirt-tck.orig/scripts/nwfilter/nwfilterxml2xmlin/tcp-test.xml > +++ libvirt-tck/scripts/nwfilter/nwfilterxml2xmlin/tcp-test.xml > @@ -19,4 +19,16 @@ > srcportstart='255' srcportend='256' > dstportstart='65535' dstportend='65536'/> > > + > + > + > + > + > + > + > + > + > + > + > + > ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From eblake at redhat.com Fri Apr 1 16:24:53 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 10:24:53 -0600 Subject: [libvirt] [PATCH] do not lock vm while allocating memory In-Reply-To: <4D92DFD9.6000700@cn.fujitsu.com> References: <4D92DFD9.6000700@cn.fujitsu.com> Message-ID: <4D95FC55.8080800@redhat.com> On 03/30/2011 01:46 AM, Wen Congyang wrote: > There is no need to lock vm while allocating memory. If allocating > memory failed, we forgot to unlock vm. > > --- > src/qemu/qemu_process.c | 3 +-- > 1 files changed, 1 insertions(+), 2 deletions(-) > > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > index e31e1b4..e74e0f1 100644 > --- a/src/qemu/qemu_process.c > +++ b/src/qemu/qemu_process.c > @@ -525,8 +525,6 @@ qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > virDomainEventGraphicsSubjectPtr subject = NULL; > int i; > > - virDomainObjLock(vm); > - > if (VIR_ALLOC(localAddr) < 0) > goto no_memory; > localAddr->family = localFamily; > @@ -560,6 +558,7 @@ qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > subject->nidentity++; > } > > + virDomainObjLock(vm); ACK. It only affects the OOM path, but is worth including in 0.9.0. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 1 16:26:15 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 10:26:15 -0600 Subject: [libvirt] [PATCH] fix memory leak in qemuProcessHandleGraphics() In-Reply-To: <4D92DFE1.4070602@cn.fujitsu.com> References: <4D92DFE1.4070602@cn.fujitsu.com> Message-ID: <4D95FCA7.3070801@redhat.com> On 03/30/2011 01:46 AM, Wen Congyang wrote: > If strdup("x509dname") or strdup("saslUsername") success, but > strdup(x509dname) or strdup(saslUsername) failed, subject->nidentity > is not the num elements of subject->identities, and we will leak some > memory. > > --- > src/qemu/qemu_process.c | 12 ++++++------ > 1 files changed, 6 insertions(+), 6 deletions(-) ACK - another OOM-only error appropriate for 0.9.0. I'm guessing you found it by inspection? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 1 16:28:59 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 10:28:59 -0600 Subject: [libvirt] [BUG] Managed save qemu state gets deleted after failed resume In-Reply-To: <201103301024.50356.hahn@univention.de> References: <201103301024.50356.hahn@univention.de> Message-ID: <4D95FD4B.9080008@redhat.com> On 03/30/2011 02:24 AM, Philipp Hahn wrote: > Hello, > > I haven't had time to provide a fix, but still want you to inform you about a > bug: If resuming a saved VM fails with Qemu-0.14, the managed save state > file /var/lib/libvirt/qemu/save/$VM.save is still deleted. I think it would > be better to only delete the state after an successful resume. Then we would get multiple failures on every resume attempt. However, I tend to agree with you that data loss in any form is bad, and this is a form of data loss. > -device usb-tablet,id=input0 -vnc 0.0.0.0:5 -k de -vga cirrus -device > virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 -option-rom > /usr/share/kvm/pxe-rtl8139.bin > Failed to allocate 2147483648 B: Cannot allocate memory Especially bad that it looks like a transient ENOMEM condition can cause the data loss (that is, if I'm interpreting your log correctly, then you can trigger this condition by temporarily consuming too much memory in the host, trying to resume a target, then reducing memory pressure, and try to resume again but now you've lost the state file to resume from). > > This issue is tracked in our (German) bug-tracker at > Thanks for the link. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 1 16:31:42 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 10:31:42 -0600 Subject: [libvirt] [PATCH v2 0/4] configure inactive domains' maximum memory size In-Reply-To: <4D940EEE.2090603@jp.fujitsu.com> References: <4D940EEE.2090603@jp.fujitsu.com> Message-ID: <4D95FDEE.8060609@redhat.com> On 03/30/2011 11:19 PM, Taku Izumi wrote: > Hi all, > > This patchset enables us to configure inactive domain's maximum memory > size. I redesigned according to Daniel-san's commnet. > The following patchset is the prerequisite of these. > => http://www.redhat.com/archives/libvir-list/2011-March/msg01057.html My sincere apologies at the delay on these series. I've been so focused on locking bugs and libvirtd crashers that I haven't had a chance to properly review any of the persistent settings patches in time for inclusion in 0.9.0. My justification is that you can always achieve persistent settings (albeit with undue pain) by raw XML editing, so this is just an enhancement request rather than a bug fix. However, now that we've missed the feature freeze deadline for 0.9.0, you have my promise that I will be reviewing this next week for inclusion in 0.9.1. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 1 16:40:07 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 10:40:07 -0600 Subject: [libvirt] How many functions that can't be used within libvirt In-Reply-To: References: Message-ID: <4D95FFE7.1000405@redhat.com> On 04/01/2011 12:10 AM, SanitYey o wrote: > > Hello, > I've tested some functions of libvirt don't work. Could some people give me a reasonable explanation about these functions? Why do these function don't work? Or if there is anything wrong of my understanding. > 1.virsh # migrate 1 xen+ssh://root at 172.16.201.183/Password: error: POST operation failed: xend_post: error from xen daemon: (xend.err "can't connect: (-2, 'Name or service not known')") Not sure why you got a failure here; xen migration should indeed work (although I haven't tried it myself, since I mostly use kvm). > > 2.virsh # dommemstat 5error: Failed to get memory statistics for domain 5error: this function is not supported by the hypervisor: virDomainMemoryStats Not all hypervisors can support all APIs. In some cases, it's merely because no one has contributed the glue code to query the information available from the hypervisor and convert it into the libvirt reply, in other cases it is truly because the hypervisor does not track that information in the first place. I'm assuming that this is still in regards to your xen:/// connection? > > 3.virsh # dump 5 fileerror: Failed to core dump domain 5 to fileerror: POST operation failed: xend_post: error from xen daemon: (xend.err 'Too many values for live') Not sure what failed there; does looking under /var/log/libvirt for a domain-specific log give any more clues? > > 4.virsh # iface-list error: Failed to list active interfaceserror: this function is not supported by the hypervisor: virConnectNumOfInterfaces Same category as 2. > > 5.virsh # vncdisplay 5:1 > virsh # vncdisplay 41:0 > > 6.virsh # snapshot-create 42 snapshot.xml error: Failed to create snapshot snapshot.xml for domain 42 I don't think snapshot-create has been ported to xen yet; and even for qemu-kvm, it pretty much only works with qcow2 images at the moment. > > 7.NWFILTER functions > Thank you very much! Again, I'm not sure if this has been ported to xen. You are welcome to help out by writing code for some of the missing functionality! Most of the current libvirt contributors tend to use qemu-kvm or the brand-new libxenlight interface to xen, so we could use more support from active xen users in developing code to improve the older xen:/// management interfaces. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 1 16:47:48 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 10:47:48 -0600 Subject: [libvirt] [PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) In-Reply-To: <4D94133A.30806@jp.fujitsu.com> References: <4D94124A.1090808@jp.fujitsu.com> <4D94133A.30806@jp.fujitsu.com> Message-ID: <4D9601B4.60206@redhat.com> On 03/30/2011 11:38 PM, Taku Izumi wrote: > > This patch introduces a new libvirt API (virDomainPinVcpuFlags) > > Signed-off-by: Taku Izumi > /** > + * virDomainPinVcpuFlags: > + * @domain: pointer to domain object, or NULL for Domain0 > + * @vcpu: virtual CPU number > + * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN) > + * Each bit set to 1 means that correspoinding CPU is usable. s/correspoinding/corresponding/ > + * Bytes are stored in little-endian order: CPU0-7, 8-15... > + * In each byte, lowest CPU number is least significant bit. > + * @maplen: number of bytes in cpumap, from 1 up to size of CPU map in > + * underlying virtualization system (Xen...). > + * If maplen < size, missing bytes are set to zero. > + * If maplen < size, failure code is returned. s// > + * @flags: an OR'ed set of virDomainVcpuFlags Is VIR_DOMAIN_VCPU_MAXIMUM really applicable here? The docs should probably mention that it is a subset of virDomainVcpuFlags. > + * > + * Dynamically change the real CPUs which can be allocated to a virtual CPU. > + * This function requires privileged access to the hypervisor. > + * > + * @flags must include VIR_DOMAIN_VCPU_LIVE to affect a running domain > + * (which may fail if domain is not active), or VIR_DOMAIN_MEM_CONFIG to s/VIR_DOMAIN_MEM_CONFIG/VIR_DOMAIN_VCPU_CONFIG/ > + * affect the next boot via the XML description of the domain. > + * Both flags may be set. > + * > + * Returns 0 in case of success, -1 in case of failure. > + * > + */ > +int > +virDomainPinVcpuFlags(virDomainPtr domain, unsigned int vcpu, > + unsigned char *cpumap, int maplen, unsigned int flags) > +{ > Index: libvirt/src/libvirt_public.syms > =================================================================== > --- libvirt.orig/src/libvirt_public.syms > +++ libvirt/src/libvirt_public.syms > @@ -434,6 +434,7 @@ LIBVIRT_0.9.0 { > virEventRunDefaultImpl; > virStorageVolDownload; > virStorageVolUpload; > + virDomainPinVcpuFlags; > } LIBVIRT_0.8.8; We've missed the 0.9.0 feature freeze, can you adjust this patch series to be for 0.9.1? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 1 16:52:22 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 10:52:22 -0600 Subject: [libvirt] [PATCH 2/4] vcpupin: implement the code to address the new API in the qemu driver In-Reply-To: <4D942E36.3060708@redhat.com> References: <4D94124A.1090808@jp.fujitsu.com> <4D94136C.80504@jp.fujitsu.com> <4D942E36.3060708@redhat.com> Message-ID: <4D9602C6.3000107@redhat.com> On 03/31/2011 01:33 AM, Osier Yang wrote: > > This allows both "LIVE" and "CONFIG" are set, and you use two > "if" clauses later for both of them, ( > if (flags& VIR_DOMAIN_VCPU_CONFIG), and > if (flags& VIR_DOMAIN_VCPU_LIVE) ) so there should be problem. > > IMHO it should be: Exactly one of "LIVE" or "CONFIG" is set. No, it should be perfectly acceptable to accept both at once (and some hypervisors may reject LIVE in isolation, as they can only affect LIVE and CONFIG simultaneously). We may _also_ want to document that if neither LIVE nor CONFIG is set, then we instead default to the current state of the domain (LIVE if it is active, CONFIG if it is just defined), as that has proved to be a handy shortcut. We're not very consistent on those semantics on existing APIs (so someone will have to read the docs for each API to learn which setting is which, due to backwards compatibility), but for future APIs it is best to shoot for: flags = 0 - default to LIVE or CONFIG as appropriate flags = LIVE - temporary change - affect running guest but not persistent (error if not running) flags = CONFIG - config change - affect next boot but not running guest (error if guest is transient and running, since there is no persistent state for transient guests) flags = LIVE|CONFIG - affect running guest and affect next boot (error if guest is not running, or if guest is transient) -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 1 17:45:17 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 11:45:17 -0600 Subject: [libvirt] [PATCH] add sendevent command and related APIs In-Reply-To: <4D95A00A.3040901@cn.fujitsu.com> References: <4D95A00A.3040901@cn.fujitsu.com> Message-ID: <4D960F2D.4040909@redhat.com> On 04/01/2011 03:51 AM, Lai Jiangshan wrote: > Enable libvirt send some events to the guest. > This command currently only supports NMI and key events. > > Signed-off-by: Lai Jiangshan Would you mind resending this split into several patches? For example, see how https://www.redhat.com/archives/libvir-list/2011-April/msg00052.html divided a new API into 7 patches: Michal Privoznik (7): screenshot: Defining the public API screenshot: Defining the internal API screenshot: Implementing the public API screenshot: Implementing the remote protocol screenshot: Expose the new API in virsh qemu: Implement the driver methods vbox: Implement the driver methods By separating definition, public access, virsh use, and driver implementation into separate patches, it becomes easier to review. Each division should still cleanly compile. See also http://libvirt.org/api_extension.html (although it predates some of the recent changes such as adding libxl and dropping OpenNebula, it is still a good reference). > +++ b/src/libvirt.c > @@ -5245,6 +5245,94 @@ error: > } > > /** > + * virDomainSendEvnetNMI: s/Evnet/Event/ > + * @domain: pointer to domain object, or NULL for Domain0 > + * @vcpu: the virtual CPU id to send NMI to > + * > + * Send NMI to a special vcpu of the guest s/special/specified/ > + * > + * Returns 0 in case of success, -1 in case of failure. > + */ > + > +int virDomainSendEventNMI(virDomainPtr domain, unsigned int vcpu) Absolutely must have a flags argument for future extension (even if the only supported flags value is 0 for now). > + > +/** > + * virDomainSendEventKey: > + * @domain: pointer to domain object, or NULL for Domain0 > + * @key: the string of key or key sequence > + * > + * Send a special key or key sequence to the guest > + * > + * Returns 0 in case of success, -1 in case of failure. > + */ > + > +int virDomainSendEventKey(virDomainPtr domain, const char *key) Needs a flags argument. Also, what is the format of a key sequence? There's several layers of key events, from what a keyboard sends, to what the OS driver encodes, to what X encodes, and so forth. If the format ever needs to include a NUL byte, then you need a length parameter. I'm worried that this is a bit underspecified. Do we know in advance which keys are acceptable (I'm assuming this is for SysRq sequences), in which case an enum value might be better than a raw char*. > +++ b/src/libvirt_public.syms > @@ -434,6 +434,8 @@ LIBVIRT_0.9.0 { > virEventRunDefaultImpl; > virStorageVolDownload; > virStorageVolUpload; > + virDomainSendEventNMI; > + virDomainSendEventKey; > } LIBVIRT_0.8.8; This is too late for the 0.9.0 feature freeze cutoff; when you split this into multiple patches, can you rebase it to be targetting 0.9.1? I haven't closely reviewed the rest of the patch yet, but think that the overall idea of being able to inject NMI and SysRq input to the virtual hardware of the guest is worth adding. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 1 17:53:18 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 11:53:18 -0600 Subject: [libvirt] [PATCH] nwfilters: support for TCP flags evaluation In-Reply-To: <4D95FA91.5080103@linux.vnet.ibm.com> References: <4D95FA91.5080103@linux.vnet.ibm.com> Message-ID: <4D96110E.4080907@redhat.com> On 04/01/2011 10:17 AM, Stefan Berger wrote: > This patch adds support for the evaluation of TCP flags in nwfilters. > > It adds documentation to the web page and extends the tests as well. > > Signed-off-by: Stefan Berger It would help to list a sample xml snippet in the commit message as well, so that 'git log' can more easily find when it was introduced. I haven't looked at this closely (it's post-0.9.0 material), but the idea sounds nice and in line with your overall efforts of making nwfilter more fine-grained :) > +++ libvirt-acl/docs/formatnwfilter.html.in > @@ -755,6 +755,11 @@ > STRING > comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE > > + > + flags (Since 0.9.0) So this would need to be 0.9.1. > + STRING > + TCP-only: format of mask/flags with mask and flags each being a > comma separated list of SYN,ACK,URG,PSH,FIN,RST or NONE or ALL > + > >

>

> @@ -1040,6 +1045,11 @@ > STRING > comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE > > + > + flags (Since 0.8.5) Is 0.8.5 right? > + STRING > + format of mask/flags with mask and flags each being a comma > separated list of SYN,ACK,URG,PSH,FIN,RST or NONE or ALL > + > >

>

-- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 1 18:04:04 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 01 Apr 2011 12:04:04 -0600 Subject: [libvirt] [PATCH] Fix several formatting mistakes in doc In-Reply-To: <20110401012752.GH24385@redhat.com> References: <1301570043-30978-1-git-send-email-mprivozn@redhat.com> <20110331135837.GM24425@redhat.com> <4D94B6B6.7000806@redhat.com> <20110331171843.GR24425@redhat.com> <4D94D495.4040503@redhat.com> <20110401012752.GH24385@redhat.com> Message-ID: <4D961394.4070204@redhat.com> On 03/31/2011 07:27 PM, Daniel Veillard wrote: >> $ SGML_CATALOG_FILES='/etc/xml/catalog' /usr/bin/xmllint --catalogs >> --nonet --format --valid formatcaps.html.in >/dev/null >> formatcaps.html.in:1: validity error : Validation failed: no DTD found ! >> >> ^ > > just drop --valid from the command line, xmllint usually doesn't > check validity. But IMHO it's simpler to just drop the --html flag from > xsltproc as suggestedon previous mail Almost, it definitely caught some more bugs. But it's not perfect; now I'm getting: Generating csharp.html.tmp csharp.html.in:21: parser error : Entity 'nbsp' not defined

 

^ ... csharp.html.in:125: parser error : Entity 'iacute' not defined based upon the previous work of Jaromír Červenka. ^ when make tries: name=`echo csharp.html.tmp | sed -e 's/.tmp//'`; \ /usr/bin/xsltproc --stringparam pagename $name --nonet \ ../docs/site.xsl csharp.html.in > csharp.html.tmp How do I make xsltproc recognize html entities without using --html? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Fri Apr 1 18:22:17 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 1 Apr 2011 20:22:17 +0200 Subject: [libvirt] [PATCH 1/6] virNodeGetCpuTime: Expose new API In-Reply-To: <4D95FB08.20802@redhat.com> References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> <20110401105548.a78607f7.usui@mxm.nes.nec.co.jp> <4D95FB08.20802@redhat.com> Message-ID: 2011/4/1 Eric Blake : > On 03/31/2011 07:55 PM, Minoru Usui wrote: >> virNodeGetCpuTime: Expose new API >> >> ?include/libvirt/libvirt.h.in | ? 26 ++++++++++++++++++++++++++ >> ?src/libvirt_public.syms ? ? ?| ? ?1 + >> ?2 files changed, 27 insertions(+), 0 deletions(-) > >> >> +/** >> + * virNodeCpuTime: >> + * >> + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing >> + * the information for the cpu time of Node. >> + */ >> + >> +typedef struct _virNodeCpuTime virNodeCpuTime; >> + >> +struct _virNodeCpuTime { >> + ? ?unsigned long long user; >> + ? ?unsigned long long system; >> + ? ?unsigned long long idle; >> + ? ?unsigned long long iowait; >> +}; > > Can we portably get all of this information on Windows? ?If not, how do > you express which values we don't know how to obtain? > In the context of ESX I vote against this absolute CPU time values. ESX provides this values relative to a 20 second timeslots with 1 hour of history. This makes it nearly impossible to obtain the absolute CPU time. The same problem already exists for the domain's virtual CPU time. When you look at virt-top's usage of the domain's virtual CPU time, you see that it actually doesn't really care about the absolute value, but deduces the CPU utilization from it. I suggest that we find a different representation for this information that is not by definition impossible to implement for ESX. Matthias From stefanb at linux.vnet.ibm.com Fri Apr 1 19:47:09 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Fri, 01 Apr 2011 15:47:09 -0400 Subject: [libvirt] [PATCH] nwfilters: support for TCP flags evaluation In-Reply-To: <4D96110E.4080907@redhat.com> References: <4D95FA91.5080103@linux.vnet.ibm.com> <4D96110E.4080907@redhat.com> Message-ID: <4D962BBD.8020904@linux.vnet.ibm.com> On 04/01/2011 01:53 PM, Eric Blake wrote: > On 04/01/2011 10:17 AM, Stefan Berger wrote: >> This patch adds support for the evaluation of TCP flags in nwfilters. >> >> It adds documentation to the web page and extends the tests as well. >> >> Signed-off-by: Stefan Berger > It would help to list a sample xml snippet in the commit message as > well, so that 'git log' can more easily find when it was introduced. > Ok, I will add it in V2. > I haven't looked at this closely (it's post-0.9.0 material), but the > idea sounds nice and in line with your overall efforts of making > nwfilter more fine-grained :) Thanks. >> +++ libvirt-acl/docs/formatnwfilter.html.in >> @@ -755,6 +755,11 @@ >> STRING >> comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE >> >> + >> +flags(Since 0.9.0) > So this would need to be 0.9.1. Will fix it. >> +STRING >> +TCP-only: format of mask/flags with mask and flags each being a >> comma separated list of SYN,ACK,URG,PSH,FIN,RST or NONE or ALL >> + >> >>

>>

>> @@ -1040,6 +1045,11 @@ >> STRING >> comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE >> >> + >> +flags(Since 0.8.5) > Is 0.8.5 right? Missed that one. That's how old this forgotten-about patch is... Stefan From eblake at redhat.com Fri Apr 1 22:04:52 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 1 Apr 2011 16:04:52 -0600 Subject: [libvirt] [PATCH] docs: correct invalid xml Message-ID: <1301695492-3876-1-git-send-email-eblake@redhat.com> * docs/internals.html.in: Fix xml errors. * docs/formatstorageencryption.html.in: Likewise. * docs/drvesx.html.in: Likewise. * docs/archnetwork.html.in: Likewise. * docs/logging.html.in: Likewise. * docs/drvvmware.html.in: Likewise. * docs/api.html.in: Likewise. * docs/formatnwfilter.html.in: Likewise. * docs/formatdomain.html.in: Likewise. * docs/windows.html.in: Likewise. --- Tightening up xsltproc found all of these. I'm pushing under the trivial rule. docs/api.html.in | 11 ++-- docs/archnetwork.html.in | 2 +- docs/drvesx.html.in | 10 ++-- docs/drvvmware.html.in | 4 +- docs/formatdomain.html.in | 18 +++--- docs/formatnwfilter.html.in | 96 +++++++++++++++++----------------- docs/formatstorageencryption.html.in | 2 +- docs/internals.html.in | 4 +- docs/logging.html.in | 4 +- docs/windows.html.in | 12 ++-- 10 files changed, 83 insertions(+), 80 deletions(-) diff --git a/docs/api.html.in b/docs/api.html.in index e8bbeed..384eb77 100644 --- a/docs/api.html.in +++ b/docs/api.html.in @@ -4,7 +4,7 @@

The libvirt API concepts

This page describes the main principles and architecture choices - behind the definition of the libvirt API: + behind the definition of the libvirt API:

    @@ -22,7 +22,7 @@ possible to use both KVM and LinuxContainers on the same node). A NULL name will default to a preselected hypervisor but it's probably not a wise thing to do in most cases. See the connection - URI page for a full descriptions of the values allowed.

    + URI page for a full descriptions of the values allowed.

    Once the application obtained a virConnectPtr connection to the hypervisor it can then use it to manage domains and related resources @@ -61,7 +61,7 @@ defined in which case they are inactive but there is a permanent definition available in the system for them. Based on this thay can be activated dynamically in order to be used.

    -

    Most kind of object can also be named in various ways:

    +

    Most kind of object can also be named in various ways:

    • by their name, an user friendly identifier but whose unicity cannot be garanteed between two nodes.
    • @@ -82,7 +82,7 @@

      For each first class object you will find apis for the following actions:

        -
      • Lookup:...LookupByName, +
      • Lookup:...LookupByName,
      • Enumeration:virConnectList... and virConnectNumOf...: those are used to enumerate a set of object available to an given hypervisor connection like: @@ -108,7 +108,8 @@
      • Destruction: ...

      For more in-depth details of the storage related APIs see - the storage management page, + the storage management page. +

      The libvirt drivers

      diff --git a/docs/archnetwork.html.in b/docs/archnetwork.html.in index 57b8f3d..c7ca4ca 100644 --- a/docs/archnetwork.html.in +++ b/docs/archnetwork.html.in @@ -32,7 +32,7 @@

    • Guest C. The only network interface is connected to a virtual network VLAN 2. It has no direct connectivity - to a physical LAN, relying on Guest B to route traffic + to a physical LAN, relying on Guest B to route traffic on its behalf.
    diff --git a/docs/drvesx.html.in b/docs/drvesx.html.in index a0f87c1..613cd07 100644 --- a/docs/drvesx.html.in +++ b/docs/drvesx.html.in @@ -74,7 +74,7 @@ vpx://example-vcenter.com/dc1/cluster1/example-esx.com -

    Extra parameters

    +

    Extra parameters

    Extra parameters can be added to a URI as part of the query string (the part following ?). A single parameter is formed by a @@ -308,7 +308,7 @@ error: invalid argument in libvirt was built without the 'esx' driver There are several specialties in the domain XML config for ESX domains.

    -

    Restrictions

    +

    Restrictions

    There are some restrictions for some values of the domain XML config. The driver will complain if this restrictions are violated. @@ -328,7 +328,7 @@ error: invalid argument in libvirt was built without the 'esx' driver -

    Datastore references

    +

    Datastore references

    Storage is managed in datastores. VMware uses a special path format to reference files in a datastore. Basically, the datastore name is put @@ -347,7 +347,7 @@ error: invalid argument in libvirt was built without the 'esx' driver

    -

    MAC addresses

    +

    MAC addresses

    VMware has registered two MAC address prefixes for domains: 00:0c:29 and 00:50:56. These prefixes are @@ -408,7 +408,7 @@ ethernet0.checkMACAddress = "false" -

    Available hardware

    +

    Available hardware

    VMware ESX supports different models of SCSI controllers and network cards. diff --git a/docs/drvvmware.html.in b/docs/drvvmware.html.in index 0ef6044..44814d3 100644 --- a/docs/drvvmware.html.in +++ b/docs/drvvmware.html.in @@ -8,7 +8,9 @@

    This driver uses the "vmrun" utility which is distributed with the VMware VIX API. - You can download the VIX API from here. + You can download the VIX API + from here. +

    Connections to VMware driver

    diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 5523fc7..6c624ab 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1277,7 +1277,7 @@

    Provides direct attachment of the virtual machine's NIC to the given physial interface of the host. - Since 0.7.7 (QEMU and KVM only)
    + Since 0.7.7 (QEMU and KVM only)
    This setup requires the Linux macvtap driver to be available. (Since Linux 2.6.34.) One of the modes 'vepa' @@ -1299,7 +1299,7 @@ originate from are directly delivered to the target macvtap device. Both origin and destination devices need to be in bridge mode for direct delivery. If either one of them is in vepa mode, - a VEPA capable bridge is required. + a VEPA capable bridge is required.

    private
    All packets are sent to the external bridge and will only be delivered to a target VM on the same host if they are sent through an @@ -1488,23 +1488,23 @@ qemu-kvm -net nic,model=? /dev/null The txmode attribute specifies how to handle transmission of packets when the transmit buffer is full. The value can be either 'iothread' or 'timer'. - Since 0.8.8 (QEMU and KVM only)

    + Since 0.8.8 (QEMU and KVM only)

    If set to 'iothread', packet tx is all done in an iothread in the bottom half of the driver (this option translates into adding "tx=bh" to the qemu commandline -device virtio-net-pci - option).

    + option).

    If set to 'timer', tx work is done in qemu, and if there is more tx data than can be sent at the present time, a timer is set before qemu moves on to do other things; when the timer - fires, another attempt is made to send more data.

    + fires, another attempt is made to send more data.

    The resulting difference, according to the qemu developer who added the option is: "bh makes tx more asynchronous and reduces latency, but potentially causes more processor bandwidth contention since the cpu doing the tx isn't necessarily the - cpu where the guest generated the packets."

    + cpu where the guest generated the packets."

    In general you should leave this option alone, unless you are very certain you know what you are doing. @@ -1628,8 +1628,8 @@ qemu-kvm -net nic,model=? /dev/null in clear text. The keymap attribute specifies the keymap to use. It is possible to set a limit on the validity of the password be giving an timestamp passwdValidTo='2010-04-09T15:51:00' - assumed to be in UTC. NB, this may not be supported by all hypervisors.
    -
    + assumed to be in UTC. NB, this may not be supported by all hypervisors.
    +
    Rather than using listen/port, QEMU supports a socket attribute for listening on a unix domain socket path. Since 0.8.8 @@ -2103,7 +2103,7 @@ qemu-kvm -net nic,model=? /dev/null Alternatively you can use telnet instead of raw TCP. Since 0.8.5 you can also use telnets (secure telnet) and tls. -

    +

       ...
    diff --git a/docs/formatnwfilter.html.in b/docs/formatnwfilter.html.in
    index 8840856..eb3c72b 100644
    --- a/docs/formatnwfilter.html.in
    +++ b/docs/formatnwfilter.html.in
    @@ -25,18 +25,18 @@
           cannot be circumvented from within
           the virtual machine, it makes them mandatory from the point of
           view of a virtual machine user.
    -      

    +

    The network filter subsystem allows each virtual machine's network traffic filtering rules to be configured individually on a per interface basis. The rules are applied on the host when the virtual machine is started and can be modified while the virtual machine is running. The latter can be achieved by modifying the XML description of a network filter. -

    +

    Multiple virtual machines can make use of the same generic network filter. When such a filter is modified, the network traffic filtering rules of all running virtual machines that reference this filter are updated. -

    +

    Network filtering support is available since 0.8.1 (Qemu, KVM)

    @@ -79,7 +79,7 @@ other filters can be used, a tree of filters can be built. The clean-traffic filter can be viewed using the command virsh nwfilter-dumpxml clean-traffic. -

    +

    As previously mentioned, a single network filter can be referenced by multiple virtual machines. Since interfaces will typically have individual parameters associated with their respective traffic @@ -108,7 +108,7 @@ 10.0.0.1 and enforce that the traffic from this interface will always be using 10.0.0.1 as the source IP address, which is one of the purposes of this particular filter. -

    +

    Usage of variables in filters

    @@ -117,7 +117,7 @@ Two variables names have so far been reserved for usage by the network traffic filtering subsystem: MAC and IP. -

    +

    MAC is the MAC address of the network interface. A filtering rule that references this variable will automatically be instantiated with the MAC address of the @@ -125,7 +125,7 @@ the MAC parameter. Even though it is possible to specify the MAC parameter similar to the IP parameter above, it is discouraged since libvirt knows what MAC address an interface will be using. -

    +

    The parameter IP represents the IP address that the operating system inside the virtual machine is expected to use on the given interface. The IP parameter @@ -136,7 +136,7 @@ For current limitations on IP address detection, consult the section on limitations on how to use this feature and what to expect when using it. -

    +

    The following is the XML description of the network filer no-arp-spoofing. It serves as an example for a network filter XML referencing the MAC and @@ -205,7 +205,7 @@ filters may be referenced multiple times in a filter tree but references between filters must not introduce loops (directed acyclic graph). -

    +

    The following shows the XML of the clean-traffic network filter referencing several other filters.

    @@ -226,7 +226,7 @@ needs to be provided inside a filter node. This node must have the attribute filter whose value contains the name of the filter to be referenced. -

    +

    New network filters can be defined at any time and may contain references to network filters that are not known to libvirt, yet. However, once a virtual machine @@ -282,7 +282,7 @@
  • statematch -- optional; possible values are '0' or 'false' to turn the underlying connection state matching off; default is 'true' -
    +
    Also read the section on advanced configuration topics.
  • @@ -294,7 +294,7 @@ traffic of type ip is also associated with the chain 'ipv4' then that filter's rules will be ordered relative to the priority 500 of the shown rule. -

    +

    A rule may contain a single rule for filtering of traffic. The above example shows that traffic of type ip is to be filtered. @@ -325,7 +325,7 @@
  • STRING: A string
  • -

    +

    Every attribute except for those of type IP_MASK or IPV6_MASK can be negated using the match attribute with value no. Multiple negated attributes @@ -349,14 +349,14 @@ the protocol property attribute1 does not match value1 AND the protocol property attribute2 does not match value2 AND the protocol property attribute3 matches value3. -

    +

    MAC (Ethernet)

    Protocol ID: mac -
    +
    Note: Rules of this type should go into the root chain.

    @@ -408,7 +408,7 @@
    ARP/RARP

    Protocol ID: arp or rarp -
    +
    Note: Rules of this type should either go into the root or arp/rarp chain.

    @@ -483,7 +483,7 @@ Valid strings for the Opcode field are: Request, Reply, Request_Reverse, Reply_Reverse, DRARP_Request, DRARP_Reply, DRARP_Error, InARP_Request, ARP_NAK -

    +

    IPv4
    @@ -572,7 +572,7 @@

    Valid strings for protocol are: tcp, udp, udplite, esp, ah, icmp, igmp, sctp -

    +

    @@ -662,13 +662,13 @@

    Valid strings for protocol are: tcp, udp, udplite, esp, ah, icmpv6, sctp -

    +

    TCP/UDP/SCTP

    Protocol ID: tcp, udp, sctp -
    +
    Note: The chain parameter is ignored for this type of traffic and should either be omitted or set to root.

    @@ -757,14 +757,14 @@

    -

    +

    ICMP

    Protocol ID: icmp -
    +
    Note: The chain parameter is ignored for this type of traffic and should either be omitted or set to root.

    @@ -857,13 +857,13 @@

    -

    +

    IGMP, ESP, AH, UDPLITE, 'ALL'

    Protocol ID: igmp, esp, ah, udplite, all -
    +
    Note: The chain parameter is ignored for this type of traffic and should either be omitted or set to root.

    @@ -946,14 +946,14 @@

    -

    +

    TCP/UDP/SCTP over IPV6

    Protocol ID: tcp-ipv6, udp-ipv6, sctp-ipv6 -
    +
    Note: The chain parameter is ignored for this type of traffic and should either be omitted or set to root.

    @@ -1042,14 +1042,14 @@

    -

    +

    ICMPv6

    Protocol ID: icmpv6 -
    +
    Note: The chain parameter is ignored for this type of traffic and should either be omitted or set to root.

    @@ -1128,13 +1128,13 @@

    -

    +

    IGMP, ESP, AH, UDPLITE, 'ALL' over IPv6

    Protocol ID: igmp-ipv6, esp-ipv6, ah-ipv6, udplite-ipv6, all-ipv6 -
    +
    Note: The chain parameter is ignored for this type of traffic and should either be omitted or set to root.

    @@ -1202,7 +1202,7 @@

    -

    +

    Advanced Filter Configuration Topics

    @@ -1227,7 +1227,7 @@ port 80 on an attacker site, then the attacker will not be able to initiate a connection from TCP port 80 back towards the VM. By default the connection state match that enables connection tracking - and then enforcement of directionality of traffic is turned on.
    + and then enforcement of directionality of traffic is turned on.
    The following shows an example XML fragement where this feature has been turned off for incoming connections to TCP port 12345.

    @@ -1277,14 +1277,14 @@

    Note that the rule for the limit has to logically appear - before the rule for accepting the traffic.
    + before the rule for accepting the traffic.
    An additional rule for letting DNS traffic to port 22 go out the VM has been added to avoid ssh sessions not getting established for reasons related to DNS lookup failures by the ssh daemon. Leaving this rule out may otherwise lead to fun-filled debugging joy (symptom: ssh client seems to hang while trying to connect). -

    +

    Lot of care must be taken with timeouts related to tracking of traffic. An ICMP ping that the user may have terminated inside the VM may have a long @@ -1299,7 +1299,7 @@

    sets the ICMP connection tracking timeout to 3 seconds. The effect of this is that once one ping is terminated, another - one can start after 3 seconds.
    + one can start after 3 seconds.
    Further, we want to point out that a client that for whatever reason has not properly closed a TCP connection may cause a connection to be held open for a longer period of time, @@ -1323,7 +1323,7 @@ with life-cycle support for network filters. All commands related to the network filtering subsystem start with the prefix nwfilter. The following commands are available: -

    +

    • nwfilter-list : list UUIDs and names of all network filters
    • nwfilter-define : define a new network filter or update an existing one
    • @@ -1398,7 +1398,7 @@ the protocols very well that you want to be filtering on so that no further traffic than what you want can pass and that in fact the traffic you want to allow does pass. -

      +

      The network filtering subsystem is currently only available on Linux hosts and only works for Qemu and KVM type of virtual machines. On Linux @@ -1412,19 +1412,19 @@
    • arp, rarp
    • ip
    • ipv6
    • -
    +

    All other protocols over IPv4 are supported using iptables, those over IPv6 are implemented using ip6tables. -

    +

    On a Linux host, all traffic filtering instantiated by libvirt's network filter subsystem first passes through the filtering support implemented by ebtables and only then through iptables or ip6tables filters. If a filter tree has rules with the protocols mac, arp, rarp, ip, or ipv6 ebtables rules will automatically be instantiated. -
    +
    The role of the chain attribute in the network filter XML is that internally a new user-defined ebtables table is created that then for example receives all arp traffic coming @@ -1435,7 +1435,7 @@ placed into filters specifying this chain. This type of branching into user-defined tables is only supported with filtering on the ebtables layer. -
    +
    As an example, it is possible to filter on UDP traffic by source and destination ports using the ip protocol filter and specifying attributes for the @@ -1467,7 +1467,7 @@ The requirement to prevent spoofing is fulfilled by the existing clean-traffic network filter, thus we will reference this filter from our custom filter. -
    +
    To enable traffic for TCP ports 22 and 80 we will add 2 rules to enable this type of traffic. To allow the VM to send ping traffic we will add a rule for ICMP traffic. For simplicity reasons @@ -1523,7 +1523,7 @@ per-interface basis and the rules are evaluated based on the knowledge about which (tap) interface has sent or will receive the packet rather than what their source or destination IP address may be. -

    +

    An XML fragment for a possible network interface description inside the domain XML of the test VM could then look like this:

    @@ -1568,7 +1568,7 @@
  • allows the VM to send ping traffic from an interface but not let the VM be pinged on the interface
  • allows the VM to do DNS lookups (UDP towards port 53)
  • -
  • enable an ftp server (in active mode) to be run inside the VM +
  • enable an ftp server (in active mode) to be run inside the VM
  • The additional requirement of allowing an ftp server to be run inside @@ -1577,7 +1577,7 @@ outgoing tcp connection originating from the VM's TCP port 20 back to the ftp client (ftp active mode). There are several ways of how this filter can be written and we present 2 solutions. -

    +

    The 1st solution makes use of the state attribute of the TCP protocol that gives us a hook into the connection tracking framework of the Linux host. For the VM-initiated ftp data connection @@ -1752,13 +1752,13 @@ to be using. Different IP addresses in use by multiple interfaces of a VM (one IP address each) will be independently detected. -

    +

    Once a VM's IP address has been detected, its IP network traffic may be locked to that address, if for example IP address spoofing is prevented by one of its filters. In that case the user of the VM will not be able to change the IP address on the interface inside the VM, which would be considered IP address spoofing. -

    +

    In case a VM is resumed after suspension or migrated, IP address detection will be restarted.

    @@ -1776,7 +1776,7 @@ outside the scope of libvirt to ensure that referenced filters on the source system are equivalent to those on the target system and vice versa. -

    +

    Migration must occur between libvirt insallations of version 0.8.1 or later in order not to lose the network traffic filters associated with an interface. diff --git a/docs/formatstorageencryption.html.in b/docs/formatstorageencryption.html.in index 0e5dcee..9557a22 100644 --- a/docs/formatstorageencryption.html.in +++ b/docs/formatstorageencryption.html.in @@ -30,7 +30,7 @@ by the particular volume format and driver, automatically generate a secret value at the time of volume creation, and store it using the specified uuid. -

    +

    "default" format

    <encryption type="default"/> can be specified only diff --git a/docs/internals.html.in b/docs/internals.html.in index 6fa2de3..5689998 100644 --- a/docs/internals.html.in +++ b/docs/internals.html.in @@ -9,9 +9,9 @@

    diff --git a/docs/logging.html.in b/docs/logging.html.in index 44171de..ebacdac 100644 --- a/docs/logging.html.in +++ b/docs/logging.html.in @@ -82,7 +82,7 @@ Logging in the daemon

    Similarly the daemon logging behaviour can be tuned using 3 config - variables, stored in the configuration file: + variables, stored in the configuration file:

    • log_level: accepts the following values:
        @@ -128,7 +128,7 @@

        Multiple filters can be defined in a single string, they just need to be separated by spaces, e.g: "3:remote 4:event" to only get warning or errors from the remote layer and only errors from the event - layer.

        + layer.

        If you specify a log priority in a filter that is below the default log priority level, messages that match that filter will still be logged, while others will not. In order to see those messages, you must also have diff --git a/docs/windows.html.in b/docs/windows.html.in index 4011cc3..8e0af7c 100644 --- a/docs/windows.html.in +++ b/docs/windows.html.in @@ -30,7 +30,7 @@ and untested Python bindings.

        -

        Caveats

        +

        Caveats

        • @@ -47,7 +47,7 @@
        -

        Existing problems with this installer we know about +

        Existing problems with this installer we know about

        These are problems we know about, and need to be fixed in subsequent @@ -72,7 +72,7 @@

      -

      Connection types

      +

      Connection types

      These connection types are known to work: @@ -114,7 +114,7 @@ be used in security sensitive environments.

      -

      Connecting to VMware ESX/vSphere

      +

      Connecting to VMware ESX/vSphere

      Details on the capabilities, certificates, and connection string @@ -124,7 +124,7 @@ http://libvirt.org/drvesx.html -

      TLS Certificates

      +

      TLS Certificates

      TLS certificates need to have been created and placed in the correct @@ -184,7 +184,7 @@

    • C:\Users\someuser\AppData\Roaming\libvirt\pki\libvirt\private\clientkey.pem
    -

    Feedback

    +

    Feedback

    Feedback and suggestions on changes to make and what else to include -- 1.7.4 From eblake at redhat.com Fri Apr 1 22:06:50 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 1 Apr 2011 16:06:50 -0600 Subject: [libvirt] [RFC PATCH] build: detect doc build errors Message-ID: <1301695610-4003-1-git-send-email-eblake@redhat.com> I'm still stumped by xsltproc complaining about   not being a valid XML entity, hence the (hackish) exemption in docs/Makefile.am that adds --html for a couple of .html.in files. But for the remaining files, this does make input validation stricter, and caught several bugs. Hence, this is an RFC (either we live with my hack that caught all the issues in the prior patch, or someone with more xsltproc knowledge than me will step in and teach it how to resolve html entities while processing the documents as xml instead of html). * docs/Makefile.am (maintainer-clean-local): Remove generated docs in VPATH build. (%.html.tmp): Don't use looser --html; our input should be strict xhtml. HACK - use --html when entities like   are involved. (html/index.html): Exit on formatting problems. (rebuild): Run full doc build on request. --- docs/Makefile.am | 24 ++++++++++++++---------- 1 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/Makefile.am b/docs/Makefile.am index db4bc59..2d1afe4 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -123,7 +123,7 @@ internals/%.html.tmp: internals/%.html.in subsite.xsl page.xsl sitemap.html.in echo "Generating $@"; \ $(MKDIR_P) "$(builddir)/internals"; \ name=`echo $@ | sed -e 's/.tmp//'`; \ - $(XSLTPROC) --stringparam pagename $$name --nonet --html \ + $(XSLTPROC) --stringparam pagename $$name --nonet \ $(top_srcdir)/docs/subsite.xsl $< > $@ \ || { rm $@ && exit 1; }; fi @@ -131,7 +131,8 @@ internals/%.html.tmp: internals/%.html.in subsite.xsl page.xsl sitemap.html.in @if [ -x $(XSLTPROC) ] ; then \ echo "Generating $@"; \ name=`echo $@ | sed -e 's/.tmp//'`; \ - $(XSLTPROC) --stringparam pagename $$name --nonet --html \ + $(XSLTPROC) --stringparam pagename $$name --nonet \ + $$(grep -qE '&(nbsp|uuml|mdash);' $< && printf %s --html) \ $(top_srcdir)/docs/site.xsl $< > $@ \ || { rm $@ && exit 1; }; fi @@ -147,21 +148,22 @@ internals/%.html.tmp: internals/%.html.in subsite.xsl page.xsl sitemap.html.in html/index.html: libvirt-api.xml newapi.xsl page.xsl sitemap.html.in - - at if [ -x $(XSLTPROC) ] ; then \ + @if [ -x $(XSLTPROC) ] ; then \ echo "Rebuilding the HTML pages from the XML API" ; \ $(XSLTPROC) --nonet -o $(srcdir)/ \ $(srcdir)/newapi.xsl $(srcdir)/libvirt-api.xml ; fi - - at if test -x $(XMLLINT) && test -x $(XMLCATALOG) ; then \ - if $(XMLCATALOG) '$(XML_CATALOG_FILE)' "-//W3C//DTD XHTML 1.0 Strict//EN" \ - > /dev/null ; then \ + @if test -x $(XMLLINT) && test -x $(XMLCATALOG) ; then \ + if $(XMLCATALOG) '$(XML_CATALOG_FILE)' \ + "-//W3C//DTD XHTML 1.0 Strict//EN" > /dev/null ; then \ echo "Validating the resulting XHTML pages" ; \ SGML_CATALOG_FILES='$(XML_CATALOG_FILE)' \ - $(XMLLINT) --catalogs --nonet --valid --noout $(srcdir)/html/*.html ; \ + $(XMLLINT) --catalogs --nonet --valid --noout $(srcdir)/html/*.html \ + || { rm $(srcdir)/$@ && exit 1; }; \ else echo "missing XHTML1 DTD" ; fi ; fi $(addprefix $(srcdir)/,$(devhelphtml)): $(srcdir)/libvirt-api.xml $(devhelpxsl) - at echo Rebuilding devhelp files - - at if [ -x $(XSLTPROC) ] ; then \ + @if [ -x $(XSLTPROC) ] ; then \ $(XSLTPROC) --nonet -o $(srcdir)/devhelp/ \ $(top_srcdir)/docs/devhelp/devhelp.xsl $(srcdir)/libvirt-api.xml ; fi @@ -183,9 +185,11 @@ clean-local: rm -f *~ *.bak *.hierarchy *.signals *-unused.txt *.html maintainer-clean-local: clean-local - rm -rf $(srcdir)/libvirt-api.xml $(srcdir)/libvirt-refs.xml todo.html.in + rm -rf $(srcdir)/libvirt-api.xml $(srcdir)/libvirt-refs.xml \ + todo.html.in $(srcdir)/*.html $(srcdir)/devhelp/*.html \ + $(srcdir)/html/*.html $(srcdir)/internals/*.html -rebuild: api all +rebuild: maintainer-clean-local api all install-data-local: $(mkinstalldirs) $(DESTDIR)$(HTML_DIR) -- 1.7.4 From eblake at redhat.com Fri Apr 1 22:18:53 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 1 Apr 2011 16:18:53 -0600 Subject: [libvirt] [PATCH] docs: fix typo Message-ID: <1301696333-1914-1-git-send-email-eblake@redhat.com> * docs/formatdomain.html.in: Fix KVM name. --- Pushing under the trivial rule. docs/formatdomain.html.in | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 6c624ab..574fee5 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -314,7 +314,7 @@

    memtune
    The optional memtune element provides details regarding the memory tunable parameters for the domain. If this is - omitted, it defaults to the OS provided defaults. For QEMU/KVMi, the + omitted, it defaults to the OS provided defaults. For QEMU/KVM, the parameters are applied to the QEMU process as a whole. Thus, when counting them, one needs to add up guest RAM, guest video RAM, and some memory overhead of QEMU itself. The last piece is hard to -- 1.7.4 From liyong at skybility.com Sat Apr 2 03:20:30 2011 From: liyong at skybility.com (Lyre) Date: Sat, 2 Apr 2011 11:20:30 +0800 Subject: [libvirt] [libvirt-php] Fixed set_error when argument is NULL Message-ID: <1301714430-9304-1-git-send-email-liyong@skybility.com> Avoid freeing a NULL pointer --- src/libvirt-php.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libvirt-php.c b/src/libvirt-php.c index 6a76f45..66b1de9 100644 --- a/src/libvirt-php.c +++ b/src/libvirt-php.c @@ -237,12 +237,16 @@ PHP_MINFO_FUNCTION(libvirt) */ void set_error(char *msg TSRMLS_DC) { - if (msg == NULL) { + if (LIBVIRT_G (last_error) != NULL) + { efree(LIBVIRT_G (last_error)); + } + + if (msg == NULL) { + LIBVIRT_G (last_error) = NULL; return; } php_error_docref(NULL TSRMLS_CC, E_WARNING,"%s",msg); - if (LIBVIRT_G (last_error)!=NULL) efree(LIBVIRT_G (last_error)); LIBVIRT_G (last_error)=estrndup(msg,strlen(msg)); } -- 1.7.3.4 ? From veillard at redhat.com Sat Apr 2 05:45:46 2011 From: veillard at redhat.com (Daniel Veillard) Date: Sat, 2 Apr 2011 13:45:46 +0800 Subject: [libvirt] [PATCH] Fix several formatting mistakes in doc In-Reply-To: <4D961394.4070204@redhat.com> References: <1301570043-30978-1-git-send-email-mprivozn@redhat.com> <20110331135837.GM24425@redhat.com> <4D94B6B6.7000806@redhat.com> <20110331171843.GR24425@redhat.com> <4D94D495.4040503@redhat.com> <20110401012752.GH24385@redhat.com> <4D961394.4070204@redhat.com> Message-ID: <20110402054546.GN24385@redhat.com> On Fri, Apr 01, 2011 at 12:04:04PM -0600, Eric Blake wrote: > On 03/31/2011 07:27 PM, Daniel Veillard wrote: > >> $ SGML_CATALOG_FILES='/etc/xml/catalog' /usr/bin/xmllint --catalogs > >> --nonet --format --valid formatcaps.html.in >/dev/null > >> formatcaps.html.in:1: validity error : Validation failed: no DTD found ! > >> > >> ^ > > > > just drop --valid from the command line, xmllint usually doesn't > > check validity. But IMHO it's simpler to just drop the --html flag from > > xsltproc as suggestedon previous mail > > Almost, it definitely caught some more bugs. But it's not perfect; now > I'm getting: > > Generating csharp.html.tmp > csharp.html.in:21: parser error : Entity 'nbsp' not defined >

     

    > ^ > ... > csharp.html.in:125: parser error : Entity 'iacute' not defined > based upon the previous work of Jaromír Červenka. > ^ Ah, that normal, it's an error but not a fatal error, the nbsp entity is available from the DTD but since we didn't asked for validation libxml2 didn't try to fetch it. Note it's an error, not a fatal error, i.e. processing continues, as the prser can't guess if the entity was in the (not loaded) DTD or not. You can add the --loaddtd to xmllint command line to ask it to load the DTd while just checking the well-formedness of the document > when make tries: > > name=`echo csharp.html.tmp | sed -e 's/.tmp//'`; \ > /usr/bin/xsltproc --stringparam pagename $name --nonet \ > ../docs/site.xsl csharp.html.in > csharp.html.tmp > > How do I make xsltproc recognize html entities without using --html? xsltproc will load the DTD, so there should be no problem there. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From matthias.bolte at googlemail.com Sat Apr 2 06:15:13 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 2 Apr 2011 08:15:13 +0200 Subject: [libvirt] [PATCH] build: detect potentential uninitialized variables In-Reply-To: <1301673022-7410-1-git-send-email-eblake@redhat.com> References: <1301673022-7410-1-git-send-email-eblake@redhat.com> Message-ID: 2011/4/1 Eric Blake : > Even with -Wuninitialized (which is part of autobuild.sh > --enable-compile-warnings=error), gcc does NOT catch this > use of an uninitialized variable: > > { > ?if (cond) > ? ?goto error; > ?int a = 1; > error: > ?printf("%d", a); > } > > which prints 0 (if the stack was previously wiped) if cond > was true. ?Clang will catch it, but we dont' use clang as > often. ?Using gcc -Wjump-misses-init gives false positives: > > { > ?if (cond) > ? ?goto error; > ?int a = 1; > ?return a; > error: > ?return 0; > } > > Here, a was never used in the scope of the error block, so > declaring it after goto is technically fine (and clang agrees); > however, given that our HACKING already documents a preference > to C89 decl-before-statement, the false positive warning is > enough of a prod to comply with HACKING. > > [Personally, I'd _really_ rather use C99 decl-after-statement > to minimize scope, but until gcc can efficiently and reliably > catch scoping and uninitialized usage bugs, I'll settle with > the compromise of enforcing a coding standard that rejects > false positives.] > diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c > index 9082515..b03f774 100644 > --- a/src/qemu/qemu_hotplug.c > +++ b/src/qemu/qemu_hotplug.c > @@ -51,8 +51,8 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver, > ? ? int i; > ? ? int ret; > ? ? char *driveAlias = NULL; > + ? ?qemuDomainObjPrivatePtr priv; > > - ? ?origdisk = NULL; > ? ? for (i = 0 ; i < vm->def->ndisks ; i++) { > ? ? ? ? if (vm->def->disks[i]->bus == disk->bus && > ? ? ? ? ? ? STREQ(vm->def->disks[i]->dst, disk->dst)) { I had to look it up in the source, as it is not visible in the context that it's okay to remove origdisk = NULL, but origdisk is already initialized to NULL, so this second assignment is not necessary. ACK. Matthias From matthias.bolte at googlemail.com Sat Apr 2 07:34:07 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 2 Apr 2011 09:34:07 +0200 Subject: [libvirt] [Libvirt-announce] 0.9.0 freeze week, RC2 version to test In-Reply-To: <305053C1-65ED-4BCA-99CF-15927F4B31E9@redhat.com> References: <20110328062538.GB7346@redhat.com> <20110329144659.GD25888@redhat.com> <20110331134423.GK24425@redhat.com> <305053C1-65ED-4BCA-99CF-15927F4B31E9@redhat.com> Message-ID: 2011/3/31 Justin Clift : > On 01/04/2011, at 12:44 AM, Daniel P. Berrange wrote: >> On Wed, Mar 30, 2011 at 02:16:28AM +1100, Justin Clift wrote: > >>> Same problem with virsh on OSX. ?Straight out hangs and never gets >>> to the prompt. >> >> Please run virsh with ?LIBVIRT_DEBUG=1 set and capture the logs. >> >> Also when it hangs please capture a full stack trace showing >> where it has got stuck > > Thanks. ?It's looking like some kind of problem interacting with > VirtualBox (v4.0.4): > This is the full gdb backtrace from the process: > > ?(gdb) thread apply all bt > > ?Thread 1 (process 85784): > ?#0 ?0x00007fff8549b3a6 in swtch_pri () > ?#1 ?0x00007fff854d5b51 in _pthread_find_thread () > ?#2 ?0x00007fff8551cb3e in pthread_getschedparam () > ?#3 ?0x00000001013c8752 in PR_SetThreadPriority () > ?#4 ?0x00000001013c88f1 in _PR_InitThreads () > ?#5 ?0x00000001013bbc26 in _PR_ImplicitInitialization () > ?#6 ?0x00000001013c8916 in PR_GetCurrentThread () > ?#7 ?0x00000001013a048f in nsIThread::GetCurrent () > ?#8 ?0x00000001013a04c1 in nsIThread::SetMainThread () > ?#9 ?0x00000001013524ee in NS_InitXPCOM2 () > ?#10 0x00000001004c022a in com::Initialize () > ?#11 0x00000001004bef8f in VBoxComInitialize () > ?#12 0x000000010015fa7f in vboxInitialize () > ?#13 0x0000000100160039 in vboxOpen () > ?#14 0x00000001000abbcb in do_open () > ?#15 0x00000001000ac712 in virConnectOpenAuth () > ?#16 0x000000010001a7ef in vshInit () > ?#17 0x000000010001bef1 in main () > ?(gdb) > > Any of that helpful? Strange point to get stuck. I assume VirtualBox for OSX comes with it's own GUI tool. Is it also affected or only virsh? Does this happen with VirtualBox 4.0.4 only, or is 4.x or even 3.x affected too? Matthias From matthias.bolte at googlemail.com Sat Apr 2 07:38:54 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 2 Apr 2011 09:38:54 +0200 Subject: [libvirt] mingw: virsh event loop failure in current git In-Reply-To: <4D950D60.6060104@redhat.com> References: <4D950D60.6060104@redhat.com> Message-ID: 2011/4/1 Eric Blake : > On 03/15/2011 02:29 AM, Matthias Bolte wrote: >> Commit 2ed6cc7bec41dd344d41ea1531f6760c93099128 "Expose event loop >> implementation as a public API" turned a failure to initialize the >> default event loop into a fatal error in virsh on Windows. Before that >> commit such a failure was ignored. > > Does this patch fix things? ?If so, we should definitely get it into 0.9.0: > https://www.redhat.com/archives/libvir-list/2011-March/msg01553.html > > (but be sure to pick up the logic correction before testing): > https://www.redhat.com/archives/libvir-list/2011-March/msg01554.html > Yes, at least virSetNonBlock doesn't fail anymore. But now virSetCloseExec is the next thing that fails, because it calls virSetInherit and virSetInherit always returns -1 on Windows. Matthias From wencongyang at gmail.com Sun Apr 3 01:16:43 2011 From: wencongyang at gmail.com (Wen Congyang) Date: Sun, 03 Apr 2011 09:16:43 +0800 Subject: [libvirt] [PATCH] do not lock vm while allocating memory In-Reply-To: <4D95FC55.8080800@redhat.com> References: <4D92DFD9.6000700@cn.fujitsu.com> <4D95FC55.8080800@redhat.com> Message-ID: <4D97CA7B.4040108@gmail.com> ? 2011-4-2 0:24, Eric Blake ??: > On 03/30/2011 01:46 AM, Wen Congyang wrote: >> There is no need to lock vm while allocating memory. If allocating >> memory failed, we forgot to unlock vm. >> >> --- >> src/qemu/qemu_process.c | 3 +-- >> 1 files changed, 1 insertions(+), 2 deletions(-) >> >> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c >> index e31e1b4..e74e0f1 100644 >> --- a/src/qemu/qemu_process.c >> +++ b/src/qemu/qemu_process.c >> @@ -525,8 +525,6 @@ qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED, >> virDomainEventGraphicsSubjectPtr subject = NULL; >> int i; >> >> - virDomainObjLock(vm); >> - >> if (VIR_ALLOC(localAddr)< 0) >> goto no_memory; >> localAddr->family = localFamily; >> @@ -560,6 +558,7 @@ qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED, >> subject->nidentity++; >> } >> >> + virDomainObjLock(vm); > > ACK. It only affects the OOM path, but is worth including in 0.9.0. Thanks, pushed. > > > > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list From wencongyang at gmail.com Sun Apr 3 01:18:23 2011 From: wencongyang at gmail.com (Wen Congyang) Date: Sun, 03 Apr 2011 09:18:23 +0800 Subject: [libvirt] [PATCH] fix memory leak in qemuProcessHandleGraphics() In-Reply-To: <4D95FCA7.3070801@redhat.com> References: <4D92DFE1.4070602@cn.fujitsu.com> <4D95FCA7.3070801@redhat.com> Message-ID: <4D97CADF.2080006@gmail.com> ? 2011-4-2 0:26, Eric Blake ??: > On 03/30/2011 01:46 AM, Wen Congyang wrote: >> If strdup("x509dname") or strdup("saslUsername") success, but >> strdup(x509dname) or strdup(saslUsername) failed, subject->nidentity >> is not the num elements of subject->identities, and we will leak some >> memory. >> >> --- >> src/qemu/qemu_process.c | 12 ++++++------ >> 1 files changed, 6 insertions(+), 6 deletions(-) > > ACK - another OOM-only error appropriate for 0.9.0. I'm guessing you > found it by inspection? Yes, I found it by inspection. I pushed this patch, thanks. > > > > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list From mcastrol at gmail.com Sun Apr 3 08:43:45 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Sun, 3 Apr 2011 10:43:45 +0200 Subject: [libvirt] Using Restore in another host. Message-ID: Hello: I need to know if I can use the restore operation (virsh o the equivalent in libvirt) to recover a previous state of a guest, but recovered previously in another host. I did a test, but I got an error: The exactly sequence using virsh I testes is: On [HOST SOURCE]: Using virsh 1) save [domain] [file] 2) restore file 3) destroy [domain] On [HOST SOURCE] using ubuntu sh 4) cp [guest.img] [guest.xml] [file] to HOST2 On [HOST TARGET] using virsh 5) define [guest.xml] (using image on destination in HOST2) 6) restore [file] The restore troughs the following message: *virsh # restore sv-chubut-2011-04-01-09:58 error: Failed to restore domain from sv-chubut-2011-04-01-09:58 error: monitor socket did not show up.: Connection refused* Thank you very much. Marcela. -------------- next part -------------- An HTML attachment was scrubbed... URL: From matthias.bolte at googlemail.com Sun Apr 3 09:21:14 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:14 +0200 Subject: [libvirt] [PATCH 01/20] Remove PATH_MAX sized stack allocations related to virFileBuildPath In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-2-git-send-email-matthias.bolte@googlemail.com> Make virFileBuildPath operate on the heap instead of the stack. It allocates a buffer instead of expecting a preexisting buffer. --- src/conf/nwfilter_conf.c | 21 +++++++-------------- src/conf/storage_conf.c | 44 +++++++++++++++----------------------------- src/util/util.c | 29 +++++++++++++++-------------- src/util/util.h | 8 +++----- src/xen/xen_inotify.c | 16 +++++++++------- src/xen/xm_internal.c | 33 +++++++++++++++++---------------- 6 files changed, 66 insertions(+), 85 deletions(-) diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 13b5b38..df8e20f 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -2484,7 +2484,7 @@ virNWFilterLoadAllConfigs(virConnectPtr conn, } while ((entry = readdir(dir))) { - char path[PATH_MAX]; + char *path; virNWFilterObjPtr nwfilter; if (entry->d_name[0] == '.') @@ -2493,17 +2493,16 @@ virNWFilterLoadAllConfigs(virConnectPtr conn, if (!virFileHasSuffix(entry->d_name, ".xml")) continue; - if (virFileBuildPath(configDir, entry->d_name, - NULL, path, PATH_MAX) < 0) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, - _("config filename '%s/%s' is too long"), - configDir, entry->d_name); + if (!(path = virFileBuildPath(configDir, entry->d_name, NULL))) { + virReportOOMError(); continue; } nwfilter = virNWFilterObjLoad(conn, nwfilters, entry->d_name, path); if (nwfilter) virNWFilterObjUnlock(nwfilter); + + VIR_FREE(path); } closedir(dir); @@ -2523,7 +2522,6 @@ virNWFilterObjSaveDef(virNWFilterDriverStatePtr driver, if (!nwfilter->configFile) { int err; - char path[PATH_MAX]; if ((err = virFileMakePath(driver->configDir))) { virReportSystemError(err, @@ -2532,13 +2530,8 @@ virNWFilterObjSaveDef(virNWFilterDriverStatePtr driver, return -1; } - if (virFileBuildPath(driver->configDir, def->name, ".xml", - path, sizeof(path)) < 0) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot construct config file path")); - return -1; - } - if (!(nwfilter->configFile = strdup(path))) { + if (!(nwfilter->configFile = virFileBuildPath(driver->configDir, + def->name, ".xml"))) { virReportOOMError(); return -1; } diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 13a3622..5a069f5 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -1473,8 +1473,8 @@ virStoragePoolLoadAllConfigs(virStoragePoolObjListPtr pools, } while ((entry = readdir(dir))) { - char path[PATH_MAX]; - char autostartLink[PATH_MAX]; + char *path; + char *autostartLink; virStoragePoolObjPtr pool; if (entry->d_name[0] == '.') @@ -1483,19 +1483,15 @@ virStoragePoolLoadAllConfigs(virStoragePoolObjListPtr pools, if (!virFileHasSuffix(entry->d_name, ".xml")) continue; - if (virFileBuildPath(configDir, entry->d_name, - NULL, path, PATH_MAX) < 0) { - virStorageReportError(VIR_ERR_INTERNAL_ERROR, - _("Config filename '%s/%s' is too long"), - configDir, entry->d_name); + if (!(path = virFileBuildPath(configDir, entry->d_name, NULL))) { + virReportOOMError(); continue; } - if (virFileBuildPath(autostartDir, entry->d_name, - NULL, autostartLink, PATH_MAX) < 0) { - virStorageReportError(VIR_ERR_INTERNAL_ERROR, - _("Autostart link path '%s/%s' is too long"), - autostartDir, entry->d_name); + if (!(autostartLink = virFileBuildPath(autostartDir, entry->d_name, + NULL))) { + virReportOOMError(); + VIR_FREE(path); continue; } @@ -1503,6 +1499,9 @@ virStoragePoolLoadAllConfigs(virStoragePoolObjListPtr pools, autostartLink); if (pool) virStoragePoolObjUnlock(pool); + + VIR_FREE(path); + VIR_FREE(autostartLink); } closedir(dir); @@ -1520,7 +1519,6 @@ virStoragePoolObjSaveDef(virStorageDriverStatePtr driver, if (!pool->configFile) { int err; - char path[PATH_MAX]; if ((err = virFileMakePath(driver->configDir))) { virReportSystemError(err, @@ -1529,26 +1527,14 @@ virStoragePoolObjSaveDef(virStorageDriverStatePtr driver, return -1; } - if (virFileBuildPath(driver->configDir, def->name, ".xml", - path, sizeof(path)) < 0) { - virStorageReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot construct config file path")); - return -1; - } - if (!(pool->configFile = strdup(path))) { + if (!(pool->configFile = virFileBuildPath(driver->configDir, + def->name, ".xml"))) { virReportOOMError(); return -1; } - if (virFileBuildPath(driver->autostartDir, def->name, ".xml", - path, sizeof(path)) < 0) { - virStorageReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot construct " - "autostart link path")); - VIR_FREE(pool->configFile); - return -1; - } - if (!(pool->autostartLink = strdup(path))) { + if (!(pool->autostartLink = virFileBuildPath(driver->autostartDir, + def->name, ".xml"))) { virReportOOMError(); VIR_FREE(pool->configFile); return -1; diff --git a/src/util/util.c b/src/util/util.c index 43794b1..31feecc 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -1841,23 +1841,24 @@ cleanup: return err; } -/* Build up a fully qualfiied path for a config file to be +/* Build up a fully qualified path for a config file to be * associated with a persistent guest or network */ -int virFileBuildPath(const char *dir, - const char *name, - const char *ext, - char *buf, - unsigned int buflen) +char * +virFileBuildPath(const char *dir, const char *name, const char *ext) { - if ((strlen(dir) + 1 + strlen(name) + (ext ? strlen(ext) : 0) + 1) >= (buflen-1)) - return -1; + char *path; - strcpy(buf, dir); - strcat(buf, "/"); - strcat(buf, name); - if (ext) - strcat(buf, ext); - return 0; + if (ext == NULL) { + if (virAsprintf(&path, "%s/%s", dir, name) < 0) { + return NULL; + } + } else { + if (virAsprintf(&path, "%s/%s%s", dir, name, ext) < 0) { + return NULL; + } + } + + return path; } diff --git a/src/util/util.h b/src/util/util.h index 7b7722a..d320c40 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -146,11 +146,9 @@ int virDirCreate(const char *path, mode_t mode, uid_t uid, gid_t gid, unsigned int flags) ATTRIBUTE_RETURN_CHECK; int virFileMakePath(const char *path) ATTRIBUTE_RETURN_CHECK; -int virFileBuildPath(const char *dir, - const char *name, - const char *ext, - char *buf, - unsigned int buflen) ATTRIBUTE_RETURN_CHECK; +char *virFileBuildPath(const char *dir, + const char *name, + const char *ext) ATTRIBUTE_RETURN_CHECK; int virFileAbsPath(const char *path, char **abspath) ATTRIBUTE_RETURN_CHECK; diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c index 7d4ba4c..5a997e6 100644 --- a/src/xen/xen_inotify.c +++ b/src/xen/xen_inotify.c @@ -387,7 +387,7 @@ xenInotifyOpen(virConnectPtr conn, { DIR *dh; struct dirent *ent; - char path[PATH_MAX]; + char *path; xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData; if (priv->configDir) { @@ -414,19 +414,21 @@ xenInotifyOpen(virConnectPtr conn, continue; /* Build the full file path */ - if ((strlen(priv->configDir) + 1 + - strlen(ent->d_name) + 1) > PATH_MAX) - continue; - strcpy(path, priv->configDir); - strcat(path, "/"); - strcat(path, ent->d_name); + if (!(path = virFileBuildPath(priv->configDir, ent->d_name, NULL))) { + virReportOOMError(); + closedir(dh); + return -1; + } if (xenInotifyAddDomainConfigInfo(conn, path) < 0 ) { virXenInotifyError(VIR_ERR_INTERNAL_ERROR, "%s", _("Error adding file to config list")); closedir(dh); + VIR_FREE(path); return -1; } + + VIR_FREE(path); } closedir(dh); } diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 7f73588..9225808 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -358,7 +358,7 @@ int xenXMConfigCacheRefresh (virConnectPtr conn) { while ((ent = readdir(dh))) { struct stat st; - char path[PATH_MAX]; + char *path; /* * Skip a bunch of crufty files that clearly aren't config files @@ -387,15 +387,16 @@ int xenXMConfigCacheRefresh (virConnectPtr conn) { continue; /* Build the full file path */ - if ((strlen(priv->configDir) + 1 + strlen(ent->d_name) + 1) > PATH_MAX) - continue; - strcpy(path, priv->configDir); - strcat(path, "/"); - strcat(path, ent->d_name); + if (!(path = virFileBuildPath(priv->configDir, ent->d_name, NULL))) { + virReportOOMError(); + closedir(dh); + return -1; + } /* Skip anything which isn't a file (takes care of scripts/ subdir */ if ((stat(path, &st) < 0) || (!S_ISREG(st.st_mode))) { + VIR_FREE(path); continue; } @@ -404,6 +405,8 @@ int xenXMConfigCacheRefresh (virConnectPtr conn) { if (xenXMConfigCacheAddFile(conn, path) < 0) { /* Ignoring errors, since alot of stuff goes wrong in /etc/xen */ } + + VIR_FREE(path); } /* Reap all entries which were not changed, by comparing @@ -1046,10 +1049,11 @@ int xenXMDomainCreate(virDomainPtr domain) { * Create a config file for a domain, based on an XML * document describing its config */ -virDomainPtr xenXMDomainDefineXML(virConnectPtr conn, const char *xml) { +virDomainPtr xenXMDomainDefineXML(virConnectPtr conn, const char *xml) +{ virDomainPtr ret; - char filename[PATH_MAX]; - const char * oldfilename; + char *filename; + const char *oldfilename; virDomainDefPtr def = NULL; xenXMConfCachePtr entry = NULL; xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData; @@ -1130,16 +1134,11 @@ virDomainPtr xenXMDomainDefineXML(virConnectPtr conn, const char *xml) { entry = NULL; } - if ((strlen(priv->configDir) + 1 + strlen(def->name) + 1) > PATH_MAX) { - xenXMError(VIR_ERR_INTERNAL_ERROR, - "%s", _("config file name is too long")); + if (!(filename = virFileBuildPath(priv->configDir, def->name, NULL))) { + virReportOOMError(); goto error; } - strcpy(filename, priv->configDir); - strcat(filename, "/"); - strcat(filename, def->name); - if (xenXMConfigSaveFile(conn, filename, def) < 0) goto error; @@ -1172,9 +1171,11 @@ virDomainPtr xenXMDomainDefineXML(virConnectPtr conn, const char *xml) { ret = virGetDomain(conn, def->name, def->uuid); xenUnifiedUnlock(priv); + VIR_FREE(filename); return (ret); error: + VIR_FREE(filename); VIR_FREE(entry); virDomainDefFree(def); xenUnifiedUnlock(priv); -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:15 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:15 +0200 Subject: [libvirt] [PATCH 02/20] pci: Remove PATH_MAX sized stack allocations In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-3-git-send-email-matthias.bolte@googlemail.com> Use virAsprintf instead of snprintf. --- src/util/pci.c | 172 +++++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 127 insertions(+), 45 deletions(-) diff --git a/src/util/pci.c b/src/util/pci.c index 8d2dbb0..6ed96f4 100644 --- a/src/util/pci.c +++ b/src/util/pci.c @@ -775,38 +775,72 @@ pciResetDevice(pciDevice *dev, } -static void -pciDriverDir(char *buf, size_t buflen, const char *driver) +static int +pciDriverDir(char **buffer, const char *driver) { - snprintf(buf, buflen, PCI_SYSFS "drivers/%s", driver); + VIR_FREE(*buffer); + + if (virAsprintf(buffer, PCI_SYSFS "drivers/%s", driver) < 0) { + virReportOOMError(); + return -1; + } + + return 0; } -static void -pciDriverFile(char *buf, size_t buflen, const char *driver, const char *file) +static int +pciDriverFile(char **buffer, const char *driver, const char *file) { - snprintf(buf, buflen, PCI_SYSFS "drivers/%s/%s", driver, file); + VIR_FREE(*buffer); + + if (virAsprintf(buffer, PCI_SYSFS "drivers/%s/%s", driver, file) < 0) { + virReportOOMError(); + return -1; + } + + return 0; } -static void -pciDeviceFile(char *buf, size_t buflen, const char *device, const char *file) +static int +pciDeviceFile(char **buffer, const char *device, const char *file) { - snprintf(buf, buflen, PCI_SYSFS "devices/%s/%s", device, file); + VIR_FREE(*buffer); + + if (virAsprintf(buffer, PCI_SYSFS "devices/%s/%s", device, file) < 0) { + virReportOOMError(); + return -1; + } + + return 0; } static const char * pciFindStubDriver(void) { - char drvpath[PATH_MAX]; + char *drvpath = NULL; int probed = 0; recheck: - pciDriverDir(drvpath, sizeof(drvpath), "pci-stub"); - if (virFileExists(drvpath)) + if (pciDriverDir(&drvpath, "pci-stub") < 0) { + return NULL; + } + + if (virFileExists(drvpath)) { + VIR_FREE(drvpath); return "pci-stub"; - pciDriverDir(drvpath, sizeof(drvpath), "pciback"); - if (virFileExists(drvpath)) + } + + if (pciDriverDir(&drvpath, "pciback") < 0) { + return NULL; + } + + if (virFileExists(drvpath)) { + VIR_FREE(drvpath); return "pciback"; + } + + VIR_FREE(drvpath); if (!probed) { const char *const stubprobe[] = { MODPROBE, "pci-stub", NULL }; @@ -837,8 +871,9 @@ recheck: static int pciBindDeviceToStub(pciDevice *dev, const char *driver) { - char drvdir[PATH_MAX]; - char path[PATH_MAX]; + int result = -1; + char *drvdir = NULL; + char *path = NULL; /* Add the PCI device ID to the stub's dynamic ID table; * this is needed to allow us to bind the device to the stub. @@ -848,12 +883,15 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) * is triggered for such a device, it will also be immediately * bound by the stub. */ - pciDriverFile(path, sizeof(path), driver, "new_id"); + if (pciDriverFile(&path, driver, "new_id") < 0) { + return -1; + } + if (virFileWriteStr(path, dev->id, 0) < 0) { virReportSystemError(errno, _("Failed to add PCI device ID '%s' to %s"), dev->id, driver); - return -1; + goto cleanup; } /* If the device is already bound to a driver, unbind it. @@ -861,48 +899,69 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) * PCI device happens to be IDE controller for the disk hosting * your root filesystem. */ - pciDeviceFile(path, sizeof(path), dev->name, "driver/unbind"); + if (pciDeviceFile(&path, dev->name, "driver/unbind") < 0) { + goto cleanup; + } + if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to unbind PCI device '%s'"), dev->name); - return -1; + goto cleanup; } /* If the device isn't already bound to pci-stub, try binding it now. */ - pciDriverDir(drvdir, sizeof(drvdir), driver); - pciDeviceFile(path, sizeof(path), dev->name, "driver"); + if (pciDriverDir(&drvdir, driver) < 0 || + pciDeviceFile(&path, dev->name, "driver") < 0) { + goto cleanup; + } + if (!virFileLinkPointsTo(path, drvdir)) { /* Xen's pciback.ko wants you to use new_slot first */ - pciDriverFile(path, sizeof(path), driver, "new_slot"); + if (pciDriverFile(&path, driver, "new_slot") < 0) { + goto cleanup; + } + if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to add slot for PCI device '%s' to %s"), dev->name, driver); - return -1; + goto cleanup; + } + + if (pciDriverFile(&path, driver, "bind") < 0) { + goto cleanup; } - pciDriverFile(path, sizeof(path), driver, "bind"); if (virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to bind PCI device '%s' to %s"), dev->name, driver); - return -1; + goto cleanup; } } /* If 'remove_id' exists, remove the device id from pci-stub's dynamic * ID table so that 'drivers_probe' works below. */ - pciDriverFile(path, sizeof(path), driver, "remove_id"); + if (pciDriverFile(&path, driver, "remove_id") < 0) { + goto cleanup; + } + if (virFileExists(path) && virFileWriteStr(path, dev->id, 0) < 0) { virReportSystemError(errno, _("Failed to remove PCI ID '%s' from %s"), dev->id, driver); - return -1; + goto cleanup; } - return 0; + result = 0; + +cleanup: + VIR_FREE(drvdir); + VIR_FREE(path); + + return result; } int @@ -927,49 +986,67 @@ pciDettachDevice(pciDevice *dev, pciDeviceList *activeDevs) static int pciUnBindDeviceFromStub(pciDevice *dev, const char *driver) { - char drvdir[PATH_MAX]; - char path[PATH_MAX]; + int result = -1; + char *drvdir = NULL; + char *path = NULL; /* If the device is bound to stub, unbind it. */ - pciDriverDir(drvdir, sizeof(drvdir), driver); - pciDeviceFile(path, sizeof(path), dev->name, "driver"); + if (pciDriverDir(&drvdir, driver) < 0 || + pciDeviceFile(&path, dev->name, "driver") < 0) { + goto cleanup; + } + if (virFileExists(drvdir) && virFileLinkPointsTo(path, drvdir)) { - pciDriverFile(path, sizeof(path), driver, "unbind"); + if (pciDriverFile(&path, driver, "unbind") < 0) { + goto cleanup; + } + if (virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to bind PCI device '%s' to %s"), dev->name, driver); - return -1; + goto cleanup; } } /* Xen's pciback.ko wants you to use remove_slot on the specific device */ - pciDriverFile(path, sizeof(path), driver, "remove_slot"); + if (pciDriverFile(&path, driver, "remove_slot") < 0) { + goto cleanup; + } + if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to remove slot for PCI device '%s' to %s"), dev->name, driver); - return -1; + goto cleanup; } - /* Trigger a re-probe of the device is not in the stub's dynamic * ID table. If the stub is available, but 'remove_id' isn't * available, then re-probing would just cause the device to be * re-bound to the stub. */ - pciDriverFile(path, sizeof(path), driver, "remove_id"); + if (pciDriverFile(&path, driver, "remove_id") < 0) { + goto cleanup; + } + if (!virFileExists(drvdir) || virFileExists(path)) { if (virFileWriteStr(PCI_SYSFS "drivers_probe", dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to trigger a re-probe for PCI device '%s'"), dev->name); - return -1; + goto cleanup; } } - return 0; + result = 0; + +cleanup: + VIR_FREE(drvdir); + VIR_FREE(path); + + return result; } int @@ -1103,15 +1180,20 @@ pciWaitForDeviceCleanup(pciDevice *dev, const char *matcher) static char * pciReadDeviceID(pciDevice *dev, const char *id_name) { - char path[PATH_MAX]; + char *path; char *id_str; - snprintf(path, sizeof(path), PCI_SYSFS "devices/%s/%s", - dev->name, id_name); + if (pciDeviceFile(&path, dev->name, id_name) < 0) { + return NULL; + } /* ID string is '0xNNNN\n' ... i.e. 7 bytes */ - if (virFileReadAll(path, 7, &id_str) < 0) + if (virFileReadAll(path, 7, &id_str) < 0) { + VIR_FREE(path); return NULL; + } + + VIR_FREE(path); /* Check for 0x suffix */ if (id_str[0] != '0' || id_str[1] != 'x') { -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:16 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:16 +0200 Subject: [libvirt] [PATCH 03/20] ebtables: Remove PATH_MAX sized stack allocation In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-4-git-send-email-matthias.bolte@googlemail.com> --- src/util/ebtables.c | 44 +++++++++++++++++++++++++++++--------------- 1 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/util/ebtables.c b/src/util/ebtables.c index e3b8da4..27dce5d 100644 --- a/src/util/ebtables.c +++ b/src/util/ebtables.c @@ -266,29 +266,43 @@ ebtablesAddRemoveRule(ebtRules *rules, int action, const char *arg, ...) ebtablesContext * ebtablesContextNew(const char *driver) { - ebtablesContext *ctx; - char chain[PATH_MAX]; + bool success = false; + ebtablesContext *ctx = NULL; + char *input_chain = NULL; + char *forward_chain = NULL; + char *nat_chain = NULL; if (VIR_ALLOC(ctx) < 0) return NULL; - snprintf(chain, sizeof(chain), "libvirt_%s_INPUT", driver); - if (!(ctx->input_filter = ebtRulesNew("filter", chain))) - goto error; + if (virAsprintf(&input_chain, "libvirt_%s_INPUT", driver) < 0 || + virAsprintf(&forward_chain, "libvirt_%s_FORWARD", driver) < 0 || + virAsprintf(&nat_chain, "libvirt_%s_POSTROUTING", driver) < 0) { + goto cleanup; + } - snprintf(chain, sizeof(chain), "libvirt_%s_FORWARD", driver); - if (!(ctx->forward_filter = ebtRulesNew("filter", chain))) - goto error; + if (!(ctx->input_filter = ebtRulesNew("filter", input_chain))) + goto cleanup; - snprintf(chain, sizeof(chain), "libvirt_%s_POSTROUTING", driver); - if (!(ctx->nat_postrouting = ebtRulesNew("nat", chain))) - goto error; + if (!(ctx->forward_filter = ebtRulesNew("filter", forward_chain))) + goto cleanup; - return ctx; + if (!(ctx->nat_postrouting = ebtRulesNew("nat", nat_chain))) + goto cleanup; - error: - ebtablesContextFree(ctx); - return NULL; + success = true; + +cleanup: + VIR_FREE(input_chain); + VIR_FREE(forward_chain); + VIR_FREE(nat_chain); + + if (!success) { + ebtablesContextFree(ctx); + ctx = NULL; + } + + return ctx; } /** -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:13 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:13 +0200 Subject: [libvirt] [PATCH 00/20] Remove large stack allocations Message-ID: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> This is meant for post-0.9.0. The series removes many large stack allocations from the code base and makes it compile with -Wframe-larger-than=2500. This was inspired by Dan's patch for using gnulib's manywarnings & warnings modules [1]. Where he mentioned that currently -Wframe-larger-than=20480 is required. This series doesn't address stack usage in the test suite. [1] https://www.redhat.com/archives/libvir-list/2011-April/msg00060.html Matthias From matthias.bolte at googlemail.com Sun Apr 3 09:21:17 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:17 +0200 Subject: [libvirt] [PATCH 04/20] virt-aa-helper: Remove PATH_MAX sized stack allocations In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-5-git-send-email-matthias.bolte@googlemail.com> --- src/security/virt-aa-helper.c | 46 +++++++++++++++++++++++++---------------- 1 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 77df514..bb716e6 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -188,8 +188,9 @@ replace_string(char *orig, const size_t len, const char *oldstr, static int parserCommand(const char *profile_name, const char cmd) { + int result = -1; char flag[3]; - char profile[PATH_MAX]; + char *profile; int status; int ret; @@ -200,15 +201,15 @@ parserCommand(const char *profile_name, const char cmd) snprintf(flag, 3, "-%c", cmd); - if (snprintf(profile, PATH_MAX, "%s/%s", - APPARMOR_DIR "/libvirt", profile_name) > PATH_MAX - 1) { + if (virAsprintf(&profile, "%s/%s", + APPARMOR_DIR "/libvirt", profile_name) < 0) { vah_error(NULL, 0, _("profile name exceeds maximum length")); return -1; } if (!virFileExists(profile)) { vah_error(NULL, 0, _("profile does not exist")); - return -1; + goto cleanup; } else { const char * const argv[] = { "/sbin/apparmor_parser", flag, profile, NULL @@ -217,18 +218,23 @@ parserCommand(const char *profile_name, const char cmd) (WIFEXITED(status) && WEXITSTATUS(status) != 0)) { if (ret != 0) { vah_error(NULL, 0, _("failed to run apparmor_parser")); - return -1; + goto cleanup; } else if (cmd == 'R' && WIFEXITED(status) && WEXITSTATUS(status) == 234) { vah_warning(_("unable to unload already unloaded profile")); } else { vah_error(NULL, 0, _("apparmor_parser exited with error")); - return -1; + goto cleanup; } } } - return 0; + result = 0; + +cleanup: + VIR_FREE(profile); + + return result; } /* @@ -308,7 +314,7 @@ static int create_profile(const char *profile, const char *profile_name, const char *profile_files) { - char template[PATH_MAX]; + char *template; char *tcontent = NULL; char *pcontent = NULL; char *replace_name = NULL; @@ -324,8 +330,7 @@ create_profile(const char *profile, const char *profile_name, goto end; } - if (snprintf(template, PATH_MAX, "%s/TEMPLATE", - APPARMOR_DIR "/libvirt") > PATH_MAX - 1) { + if (virAsprintf(&template, "%s/TEMPLATE", APPARMOR_DIR "/libvirt") < 0) { vah_error(NULL, 0, _("template name exceeds maximum length")); goto end; } @@ -409,6 +414,7 @@ create_profile(const char *profile, const char *profile_name, clean_tcontent: VIR_FREE(tcontent); end: + VIR_FREE(template); return rc; } @@ -1134,8 +1140,8 @@ main(int argc, char **argv) vahControl _ctl, *ctl = &_ctl; virBuffer buf = VIR_BUFFER_INITIALIZER; int rc = -1; - char profile[PATH_MAX]; - char include_file[PATH_MAX]; + char *profile = NULL; + char *include_file = NULL; if (setlocale(LC_ALL, "") == NULL || bindtextdomain(PACKAGE, LOCALEDIR) == NULL || @@ -1164,13 +1170,13 @@ main(int argc, char **argv) if (vahParseArgv(ctl, argc, argv) != 0) vah_error(ctl, 1, _("could not parse arguments")); - if (snprintf(profile, PATH_MAX, "%s/%s", - APPARMOR_DIR "/libvirt", ctl->uuid) > PATH_MAX - 1) - vah_error(ctl, 1, _("profile name exceeds maximum length")); + if (virAsprintf(&profile, "%s/%s", + APPARMOR_DIR "/libvirt", ctl->uuid) < 0) + vah_error(ctl, 0, _("could not allocate memory")); - if (snprintf(include_file, PATH_MAX, "%s/%s.files", - APPARMOR_DIR "/libvirt", ctl->uuid) > PATH_MAX - 1) - vah_error(ctl, 1, _("disk profile name exceeds maximum length")); + if (virAsprintf(&include_file, "%s/%s.files", + APPARMOR_DIR "/libvirt", ctl->uuid) < 0) + vah_error(ctl, 0, _("could not allocate memory")); if (ctl->cmd == 'a') rc = parserLoad(ctl->uuid); @@ -1258,5 +1264,9 @@ main(int argc, char **argv) } vahDeinit(ctl); + + VIR_FREE(profile); + VIR_FREE(include_file); + exit(rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE); } -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:18 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:18 +0200 Subject: [libvirt] [PATCH 05/20] phyp: Remove 16kb stack allocation In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-6-git-send-email-matthias.bolte@googlemail.com> Allocate on the heap instead. --- src/phyp/phyp_driver.c | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 51f9ff6..fe2e99d 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -115,12 +115,18 @@ phypExec(LIBSSH2_SESSION * session, char *cmd, int *exit_status, LIBSSH2_CHANNEL *channel; ConnectionData *connection_data = conn->networkPrivateData; virBuffer tex_ret = VIR_BUFFER_INITIALIZER; - char buffer[0x4000] = { 0 }; + char *buffer = NULL; + size_t buffer_size = 16384; int exitcode; int bytecount = 0; int sock = connection_data->sock; int rc = 0; + if (VIR_ALLOC_N(buffer, buffer_size) < 0) { + virReportOOMError(); + return NULL; + } + /* Exec non-blocking on the remove host */ while ((channel = libssh2_channel_open_session(session)) == NULL && libssh2_session_last_error(session, NULL, NULL, 0) == @@ -144,7 +150,7 @@ phypExec(LIBSSH2_SESSION * session, char *cmd, int *exit_status, for (;;) { /* loop until we block */ do { - rc = libssh2_channel_read(channel, buffer, sizeof(buffer)); + rc = libssh2_channel_read(channel, buffer, buffer_size); if (rc > 0) { bytecount += rc; virBufferVSprintf(&tex_ret, "%s", buffer); @@ -179,9 +185,12 @@ phypExec(LIBSSH2_SESSION * session, char *cmd, int *exit_status, err: (*exit_status) = SSH_CMD_ERR; virBufferFreeAndReset(&tex_ret); + VIR_FREE(buffer); return NULL; exit: + VIR_FREE(buffer); + if (virBufferError(&tex_ret)) { virBufferFreeAndReset(&tex_ret); virReportOOMError(); -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:19 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:19 +0200 Subject: [libvirt] [PATCH 06/20] qemu: Use heap allocated memory to read the monitor greeting In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-7-git-send-email-matthias.bolte@googlemail.com> Removing a 4kb stack allocation. Reduce stack buffer for virStrerror to the common 1kb instead of 4kb. --- src/qemu/qemu_process.c | 16 ++++++++++++---- 1 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 90fcea0..fc9fdae 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1012,7 +1012,8 @@ static int qemuProcessWaitForMonitor(struct qemud_driver* driver, virDomainObjPtr vm, off_t pos) { - char buf[4096] = ""; /* Plenty of space to get startup greeting */ + char *buf; + size_t buf_size = 4096; /* Plenty of space to get startup greeting */ int logfd; int ret = -1; virHashTablePtr paths = NULL; @@ -1020,7 +1021,12 @@ qemuProcessWaitForMonitor(struct qemud_driver* driver, if ((logfd = qemuProcessLogReadFD(driver->logDir, vm->def->name, pos)) < 0) return -1; - if (qemuProcessReadLogOutput(vm, logfd, buf, sizeof(buf), + if (VIR_ALLOC_N(buf, buf_size) < 0) { + virReportOOMError(); + return -1; + } + + if (qemuProcessReadLogOutput(vm, logfd, buf, buf_size, qemuProcessFindCharDevicePTYs, "console", 30) < 0) goto closelog; @@ -1053,16 +1059,18 @@ cleanup: if (kill(vm->pid, 0) == -1 && errno == ESRCH) { /* VM is dead, any other error raised in the interim is probably * not as important as the qemu cmdline output */ - qemuProcessReadLogFD(logfd, buf, sizeof(buf), strlen(buf)); + qemuProcessReadLogFD(logfd, buf, buf_size, strlen(buf)); qemuReportError(VIR_ERR_INTERNAL_ERROR, _("process exited while connecting to monitor: %s"), buf); ret = -1; } + VIR_FREE(buf); + closelog: if (VIR_CLOSE(logfd) < 0) { - char ebuf[4096]; + char ebuf[1024]; VIR_WARN("Unable to close logfile: %s", virStrerror(errno, ebuf, sizeof ebuf)); } -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:20 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:20 +0200 Subject: [libvirt] [PATCH 07/20] sasl: Remove stack allocated 8kb temporary buffers In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-8-git-send-email-matthias.bolte@googlemail.com> Move the buffers to the heap allocated client/private data structs. --- daemon/libvirtd.c | 10 ++++++---- daemon/libvirtd.h | 1 + src/remote/remote_driver.c | 8 +++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 024f56f..42cbe5d 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -1766,15 +1766,17 @@ static ssize_t qemudClientReadSASL(struct qemud_client *client) { /* Need to read some more data off the wire */ if (client->saslDecoded == NULL) { int ret; - char encoded[8192]; - ssize_t encodedLen = sizeof(encoded); - encodedLen = qemudClientReadBuf(client, encoded, encodedLen); + ssize_t encodedLen; + + encodedLen = qemudClientReadBuf(client, client->saslTemporary, + sizeof(client->saslTemporary)); if (encodedLen <= 0) return encodedLen; - ret = sasl_decode(client->saslconn, encoded, encodedLen, + ret = sasl_decode(client->saslconn, client->saslTemporary, encodedLen, &client->saslDecoded, &client->saslDecodedLength); + if (ret != SASL_OK) { VIR_ERROR(_("failed to decode SASL data %s"), sasl_errstring(ret, NULL, NULL)); diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h index 7da3cfd..d37c3fd 100644 --- a/daemon/libvirtd.h +++ b/daemon/libvirtd.h @@ -213,6 +213,7 @@ struct qemud_client { unsigned int saslEncodedLength; unsigned int saslEncodedOffset; char *saslUsername; + char saslTemporary[8192]; /* temorary holds data to be decoded */ # endif /* Count of meages in 'dx' or 'tx' queue diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index bf94e70..942ff4b 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -174,6 +174,8 @@ struct private_data { const char *saslEncoded; unsigned int saslEncodedLength; unsigned int saslEncodedOffset; + + char saslTemporary[8192]; /* temorary holds data to be decoded */ #endif /* Buffer for incoming data packets @@ -10063,15 +10065,15 @@ remoteIOReadMessage(struct private_data *priv) { #if HAVE_SASL if (priv->saslconn) { if (priv->saslDecoded == NULL) { - char encoded[8192]; int ret, err; - ret = remoteIOReadBuffer(priv, encoded, sizeof(encoded)); + ret = remoteIOReadBuffer(priv, priv->saslTemporary, + sizeof(priv->saslTemporary)); if (ret < 0) return -1; if (ret == 0) return 0; - err = sasl_decode(priv->saslconn, encoded, ret, + err = sasl_decode(priv->saslconn, priv->saslTemporary, ret, &priv->saslDecoded, &priv->saslDecodedLength); if (err != SASL_OK) { remoteError(VIR_ERR_INTERNAL_ERROR, -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:21 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:21 +0200 Subject: [libvirt] [PATCH 08/20] xenxs: Remove PATH_MAX sized stack alocation in XM script parsing In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-9-git-send-email-matthias.bolte@googlemail.com> --- src/xenxs/xen_xm.c | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/xenxs/xen_xm.c b/src/xenxs/xen_xm.c index 0acd120..22ad788 100644 --- a/src/xenxs/xen_xm.c +++ b/src/xenxs/xen_xm.c @@ -211,6 +211,7 @@ xenParseXM(virConfPtr conf, int xendConfigVersion, const char *defaultArch, *defaultMachine; int vmlocaltime = 0; unsigned long count; + char *script = NULL; if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -556,7 +557,6 @@ xenParseXM(virConfPtr conf, int xendConfigVersion, if (list && list->type == VIR_CONF_LIST) { list = list->list; while (list) { - char script[PATH_MAX]; char model[10]; char type[10]; char ip[16]; @@ -567,7 +567,6 @@ xenParseXM(virConfPtr conf, int xendConfigVersion, bridge[0] = '\0'; mac[0] = '\0'; - script[0] = '\0'; ip[0] = '\0'; model[0] = '\0'; type[0] = '\0'; @@ -602,12 +601,10 @@ xenParseXM(virConfPtr conf, int xendConfigVersion, goto skipnic; } } else if (STRPREFIX(key, "script=")) { - int len = nextkey ? (nextkey - data) : sizeof(script) - 1; - if (virStrncpy(script, data, len, sizeof(script)) == NULL) { - XENXS_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Script %s too big for destination"), - data); - goto skipnic; + int len = nextkey ? (nextkey - data) : strlen(data); + VIR_FREE(script); + if (!(script = strndup(data, len))) { + goto no_memory; } } else if (STRPREFIX(key, "model=")) { int len = nextkey ? (nextkey - data) : sizeof(model) - 1; @@ -1043,6 +1040,7 @@ cleanup: virDomainNetDefFree(net); virDomainDiskDefFree(disk); virDomainDefFree(def); + VIR_FREE(script); return NULL; } -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:23 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:23 +0200 Subject: [libvirt] [PATCH 10/20] virsh: Remove two 4kb stack allocations In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-11-git-send-email-matthias.bolte@googlemail.com> --- tools/virsh.c | 23 +++++++++++++++++------ 1 files changed, 17 insertions(+), 6 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 19e3449..99da054 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2052,7 +2052,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) virDomainInfo info; virDomainPtr dom; virSecurityModel secmodel; - virSecurityLabel seclabel; + virSecurityLabelPtr seclabel; int persistent = 0; int ret = TRUE, autostart; unsigned int id; @@ -2138,15 +2138,22 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, "%-15s %s\n", _("Security DOI:"), secmodel.doi); /* Security labels are only valid for active domains */ - memset(&seclabel, 0, sizeof seclabel); - if (virDomainGetSecurityLabel(dom, &seclabel) == -1) { + if (VIR_ALLOC(seclabel) < 0) { virDomainFree(dom); return FALSE; + } + + if (virDomainGetSecurityLabel(dom, seclabel) == -1) { + virDomainFree(dom); + VIR_FREE(seclabel); + return FALSE; } else { - if (seclabel.label[0] != '\0') + if (seclabel->label[0] != '\0') vshPrint(ctl, "%-15s %s (%s)\n", _("Security label:"), - seclabel.label, seclabel.enforcing ? "enforcing" : "permissive"); + seclabel->label, seclabel->enforcing ? "enforcing" : "permissive"); } + + VIR_FREE(seclabel); } } virDomainFree(dom); @@ -12141,7 +12148,7 @@ vshOpenLogFile(vshControl *ctl) static void vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, va_list ap) { - char msg_buf[MSG_BUFFER]; + char *msg_buf; const char *lvl = ""; struct timeval stTimeval; struct tm *stTm; @@ -12149,6 +12156,8 @@ vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, va_list if (ctl->log_fd == -1) return; + msg_buf = vshMalloc(ctl, MSG_BUFFER); + /** * create log format * @@ -12199,6 +12208,8 @@ vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, va_list vshCloseLogFile(ctl); vshError(ctl, "%s", _("failed to write the log file")); } + + VIR_FREE(msg_buf); } /** -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:22 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:22 +0200 Subject: [libvirt] [PATCH 09/20] Use virFileAbsPath instead of manually creating the absolute path In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-10-git-send-email-matthias.bolte@googlemail.com> Removes multiple 4kb stack allocations. --- src/libvirt.c | 113 +++++++++++++++++++++------------------------------------ 1 files changed, 42 insertions(+), 71 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 8be18d4..25f8d41 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -2238,7 +2238,6 @@ error: int virDomainSave(virDomainPtr domain, const char *to) { - char filepath[4096]; virConnectPtr conn; VIR_DOMAIN_DEBUG(domain, "to=%s", to); @@ -2260,29 +2259,24 @@ virDomainSave(virDomainPtr domain, const char *to) goto error; } - /* - * We must absolutize the file path as the save is done out of process - * TODO: check for URI when libxml2 is linked in. - */ - if (to[0] != '/') { - unsigned int len, t; + if (conn->driver->domainSave) { + int ret; + char *absolute_to; - t = strlen(to); - if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) - return -1; - len = strlen(filepath); - /* that should be covered by getcwd() semantic, but be 100% sure */ - if (len > sizeof(filepath) - (t + 3)) - return -1; - filepath[len] = '/'; - strcpy(&filepath[len + 1], to); - to = &filepath[0]; + /* + * We must absolutize the file path as the save is done out of process + * TODO: check for URI when libxml2 is linked in. + */ + if (virFileAbsPath(to, &absolute_to) < 0) { + virLibConnError(VIR_ERR_INTERNAL_ERROR, + _("could not build absolute output file path")); + goto error; + } - } + ret = conn->driver->domainSave(domain, absolute_to); + + VIR_FREE(absolute_to); - if (conn->driver->domainSave) { - int ret; - ret = conn->driver->domainSave (domain, to); if (ret < 0) goto error; return ret; @@ -2298,7 +2292,7 @@ error: /** * virDomainRestore: * @conn: pointer to the hypervisor connection - * @from: path to the + * @from: path to the input file * * This method will restore a domain saved to disk by virDomainSave(). * @@ -2307,7 +2301,6 @@ error: int virDomainRestore(virConnectPtr conn, const char *from) { - char filepath[4096]; VIR_DEBUG("conn=%p, from=%s", conn, from); virResetLastError(); @@ -2326,34 +2319,24 @@ virDomainRestore(virConnectPtr conn, const char *from) goto error; } - /* - * We must absolutize the file path as the restore is done out of process - * TODO: check for URI when libxml2 is linked in. - */ - if (from[0] != '/') { - unsigned int len, t; + if (conn->driver->domainRestore) { + int ret; + char *absolute_from; - t = strlen(from); - if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) { - virLibConnError(VIR_ERR_SYSTEM_ERROR, - _("cannot get working directory")); - goto error; - } - len = strlen(filepath); - /* that should be covered by getcwd() semantic, but be 100% sure */ - if (len > sizeof(filepath) - (t + 3)) { + /* + * We must absolutize the file path as the restore is done out of process + * TODO: check for URI when libxml2 is linked in. + */ + if (virFileAbsPath(from, &absolute_from) < 0) { virLibConnError(VIR_ERR_INTERNAL_ERROR, - _("path too long")); + _("could not build absolute input file path")); goto error; } - filepath[len] = '/'; - strcpy(&filepath[len + 1], from); - from = &filepath[0]; - } - if (conn->driver->domainRestore) { - int ret; - ret = conn->driver->domainRestore (conn, from); + ret = conn->driver->domainRestore(conn, absolute_from); + + VIR_FREE(absolute_from); + if (ret < 0) goto error; return ret; @@ -2381,7 +2364,6 @@ error: int virDomainCoreDump(virDomainPtr domain, const char *to, int flags) { - char filepath[4096]; virConnectPtr conn; VIR_DOMAIN_DEBUG(domain, "to=%s, flags=%d", to, flags); @@ -2403,35 +2385,24 @@ virDomainCoreDump(virDomainPtr domain, const char *to, int flags) goto error; } - /* - * We must absolutize the file path as the save is done out of process - * TODO: check for URI when libxml2 is linked in. - */ - if (to[0] != '/') { - unsigned int len, t; + if (conn->driver->domainCoreDump) { + int ret; + char *absolute_to; - t = strlen(to); - if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) { - virLibDomainError(VIR_ERR_SYSTEM_ERROR, - _("cannot get current directory")); - goto error; - } - len = strlen(filepath); - /* that should be covered by getcwd() semantic, but be 100% sure */ - if (len > sizeof(filepath) - (t + 3)) { - virLibDomainError(VIR_ERR_INTERNAL_ERROR, - _("path too long")); + /* + * We must absolutize the file path as the save is done out of process + * TODO: check for URI when libxml2 is linked in. + */ + if (virFileAbsPath(to, &absolute_to) < 0) { + virLibConnError(VIR_ERR_INTERNAL_ERROR, + _("could not build absolute core file path")); goto error; } - filepath[len] = '/'; - strcpy(&filepath[len + 1], to); - to = &filepath[0]; - } + ret = conn->driver->domainCoreDump(domain, absolute_to, flags); + + VIR_FREE(absolute_to); - if (conn->driver->domainCoreDump) { - int ret; - ret = conn->driver->domainCoreDump (domain, to, flags); if (ret < 0) goto error; return ret; -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:24 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:24 +0200 Subject: [libvirt] [PATCH 11/20] phyp: Remove the last instance of stack allocating a 4kb volume key In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-12-git-send-email-matthias.bolte@googlemail.com> --- src/phyp/phyp_driver.c | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index fe2e99d..76207c2 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -2362,13 +2362,22 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, static virStorageVolPtr phypVolumeLookupByName(virStoragePoolPtr pool, const char *volname) { + char *key; + virStorageVolPtr vol; - char key[MAX_KEY_SIZE]; + if (VIR_ALLOC_N(key, MAX_KEY_SIZE) < 0) { + virReportOOMError(); + return NULL; + } if (phypVolumeGetKey(pool->conn, key, volname) == -1) return NULL; - return virGetStorageVol(pool->conn, pool->name, volname, key); + vol = virGetStorageVol(pool->conn, pool->name, volname, key); + + VIR_FREE(key); + + return vol; } static virStorageVolPtr -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:25 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:25 +0200 Subject: [libvirt] [PATCH 12/20] daemon: Remove 4kb stack allocation of security label In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-13-git-send-email-matthias.bolte@googlemail.com> --- daemon/remote.c | 20 ++++++++++++++------ 1 files changed, 14 insertions(+), 6 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 1700c2d..dd85ef1 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1607,7 +1607,7 @@ remoteDispatchDomainGetSecurityLabel(struct qemud_server *server ATTRIBUTE_UNUSE remote_domain_get_security_label_ret *ret) { virDomainPtr dom; - virSecurityLabel seclabel; + virSecurityLabelPtr seclabel; dom = get_nonnull_domain(conn, args->dom); if (dom == NULL) { @@ -1615,22 +1615,30 @@ remoteDispatchDomainGetSecurityLabel(struct qemud_server *server ATTRIBUTE_UNUSE return -1; } - memset(&seclabel, 0, sizeof seclabel); - if (virDomainGetSecurityLabel(dom, &seclabel) == -1) { + if (VIR_ALLOC(seclabel) < 0) { + virDomainFree(dom); + remoteDispatchOOMError(rerr); + return -1; + } + + if (virDomainGetSecurityLabel(dom, seclabel) == -1) { remoteDispatchConnError(rerr, conn); virDomainFree(dom); + VIR_FREE(seclabel); return -1; } - ret->label.label_len = strlen(seclabel.label) + 1; + ret->label.label_len = strlen(seclabel->label) + 1; if (VIR_ALLOC_N(ret->label.label_val, ret->label.label_len) < 0) { virDomainFree(dom); + VIR_FREE(seclabel); remoteDispatchOOMError(rerr); return -1; } - strcpy(ret->label.label_val, seclabel.label); - ret->enforcing = seclabel.enforcing; + strcpy(ret->label.label_val, seclabel->label); + ret->enforcing = seclabel->enforcing; virDomainFree(dom); + VIR_FREE(seclabel); return 0; } -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:27 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:27 +0200 Subject: [libvirt] [PATCH 14/20] Remove PATH_MAX sized stack allocation from virFileOpenTtyAt In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-15-git-send-email-matthias.bolte@googlemail.com> --- src/util/util.c | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/util/util.c b/src/util/util.c index 31feecc..c0391ad 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -1901,14 +1901,13 @@ int virFileOpenTtyAt(const char *ptmx, } if (ttyName) { - char tempTtyName[PATH_MAX]; - if (ptsname_r(*ttymaster, tempTtyName, sizeof(tempTtyName)) < 0) - goto cleanup; - - if ((*ttyName = strdup(tempTtyName)) == NULL) { + if (VIR_ALLOC_N(*ttyName, PATH_MAX) < 0) { errno = ENOMEM; goto cleanup; } + + if (ptsname_r(*ttymaster, *ttyName, PATH_MAX) < 0) + goto cleanup; } rc = 0; -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:26 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:26 +0200 Subject: [libvirt] [PATCH 13/20] openvz: Remove several larger stack allocations In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-14-git-send-email-matthias.bolte@googlemail.com> Replace openvz_readline with getline in several places to get rid of stack allocated buffers to hold lines. openvzReadConfigParam allocates memory for return values instead of expecting a preexisting buffer. --- src/openvz/openvz_conf.c | 141 +++++++++++++++++++++++++++----------------- src/openvz/openvz_conf.h | 2 +- src/openvz/openvz_driver.c | 45 +++++++++----- 3 files changed, 117 insertions(+), 71 deletions(-) diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c index 2fcca68..88cd4c8 100644 --- a/src/openvz/openvz_conf.c +++ b/src/openvz/openvz_conf.c @@ -187,7 +187,7 @@ openvzReadNetworkConf(virDomainDefPtr def, int veid) { int ret; virDomainNetDefPtr net = NULL; - char temp[4096]; + char *temp = NULL; char *token, *saveptr = NULL; /*parse routing network configuration* @@ -195,7 +195,7 @@ openvzReadNetworkConf(virDomainDefPtr def, * IP_ADDRESS="1.1.1.1 1.1.1.2" * splited IPs by space */ - ret = openvzReadVPSConfigParam(veid, "IP_ADDRESS", temp, sizeof(temp)); + ret = openvzReadVPSConfigParam(veid, "IP_ADDRESS", &temp); if (ret < 0) { openvzError(VIR_ERR_INTERNAL_ERROR, _("Could not read 'IP_ADDRESS' from config for container %d"), @@ -227,7 +227,7 @@ openvzReadNetworkConf(virDomainDefPtr def, *NETIF="ifname=eth10,mac=00:18:51:C1:05:EE,host_ifname=veth105.10,host_mac=00:18:51:8F:D9:F3" *devices splited by ';' */ - ret = openvzReadVPSConfigParam(veid, "NETIF", temp, sizeof(temp)); + ret = openvzReadVPSConfigParam(veid, "NETIF", &temp); if (ret < 0) { openvzError(VIR_ERR_INTERNAL_ERROR, _("Could not read 'NETIF' from config for container %d"), @@ -316,10 +316,13 @@ openvzReadNetworkConf(virDomainDefPtr def, } } + VIR_FREE(temp); + return 0; no_memory: virReportOOMError(); error: + VIR_FREE(temp); virDomainNetDefFree(net); return -1; } @@ -364,10 +367,10 @@ openvzReadFSConf(virDomainDefPtr def, int veid) { int ret; virDomainFSDefPtr fs = NULL; - char* veid_str = NULL; - char temp[100]; + char *veid_str = NULL; + char *temp = NULL; - ret = openvzReadVPSConfigParam(veid, "OSTEMPLATE", temp, sizeof(temp)); + ret = openvzReadVPSConfigParam(veid, "OSTEMPLATE", &temp); if (ret < 0) { openvzError(VIR_ERR_INTERNAL_ERROR, _("Could not read 'OSTEMPLATE' from config for container %d"), @@ -381,7 +384,7 @@ openvzReadFSConf(virDomainDefPtr def, fs->src = strdup(temp); } else { /* OSTEMPLATE was not found, VE was booted from a private dir directly */ - ret = openvzReadVPSConfigParam(veid, "VE_PRIVATE", temp, sizeof(temp)); + ret = openvzReadVPSConfigParam(veid, "VE_PRIVATE", &temp); if (ret <= 0) { openvzError(VIR_ERR_INTERNAL_ERROR, _("Could not read 'VE_PRIVATE' from config for container %d"), @@ -411,10 +414,13 @@ openvzReadFSConf(virDomainDefPtr def, def->fss[def->nfss++] = fs; fs = NULL; + VIR_FREE(temp); + return 0; no_memory: virReportOOMError(); error: + VIR_FREE(temp); virDomainFSDefFree(fs); return -1; } @@ -439,7 +445,7 @@ int openvzLoadDomains(struct openvz_driver *driver) { char *status; char uuidstr[VIR_UUID_STRING_BUFLEN]; virDomainObjPtr dom = NULL; - char temp[50]; + char *temp = NULL; char *outbuf = NULL; char *line; virCommandPtr cmd = NULL; @@ -506,7 +512,7 @@ int openvzLoadDomains(struct openvz_driver *driver) { if (!(dom->def->os.init = strdup("/sbin/init"))) goto no_memory; - ret = openvzReadVPSConfigParam(veid, "CPUS", temp, sizeof(temp)); + ret = openvzReadVPSConfigParam(veid, "CPUS", &temp); if (ret < 0) { openvzError(VIR_ERR_INTERNAL_ERROR, _("Could not read config for container %d"), @@ -534,6 +540,7 @@ int openvzLoadDomains(struct openvz_driver *driver) { } virCommandFree(cmd); + VIR_FREE(temp); VIR_FREE(outbuf); return 0; @@ -543,6 +550,7 @@ int openvzLoadDomains(struct openvz_driver *driver) { cleanup: virCommandFree(cmd); + VIR_FREE(temp); VIR_FREE(outbuf); /* dom hasn't been shared yet, so unref should return 0 */ if (dom) @@ -565,25 +573,26 @@ static int openvzWriteConfigParam(const char * conf_file, const char *param, const char *value) { char * temp_file = NULL; - int fd = -1, temp_fd = -1; - char line[PATH_MAX]; + int temp_fd = -1; + FILE *fp; + char *line = NULL; + size_t line_size = 0; if (virAsprintf(&temp_file, "%s.tmp", conf_file)<0) { virReportOOMError(); return -1; } - fd = open(conf_file, O_RDONLY); - if (fd == -1) + fp = fopen(conf_file, "r"); + if (fp == NULL) goto error; temp_fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (temp_fd == -1) { - VIR_FORCE_CLOSE(fd); goto error; } while (1) { - if (openvz_readline(fd, line, sizeof(line)) <= 0) + if (getline(&line, &line_size, fp) <= 0) break; if (!(STRPREFIX(line, param) && line[strlen(param)] == '=')) { @@ -599,7 +608,7 @@ openvzWriteConfigParam(const char * conf_file, const char *param, const char *va safewrite(temp_fd, "\"\n", 2) < 0) goto error; - if (VIR_CLOSE(fd) < 0) + if (VIR_FCLOSE(fp) < 0) goto error; if (VIR_CLOSE(temp_fd) < 0) goto error; @@ -607,10 +616,13 @@ openvzWriteConfigParam(const char * conf_file, const char *param, const char *va if (rename(temp_file, conf_file) < 0) goto error; + VIR_FREE(line); + return 0; error: - VIR_FORCE_CLOSE(fd); + VIR_FREE(line); + VIR_FORCE_FCLOSE(fp); VIR_FORCE_CLOSE(temp_fd); if (temp_file) unlink(temp_file); @@ -632,23 +644,29 @@ openvzWriteVPSConfigParam(int vpsid, const char *param, const char *value) return ret; } +/* + * value will be freed before a new value is assigned to it, the caller is + * responsible for freeing it afterwards. + */ static int -openvzReadConfigParam(const char * conf_file ,const char * param, char *value, int maxlen) +openvzReadConfigParam(const char *conf_file, const char *param, char **value) { - char line[PATH_MAX]; - int ret, found = 0; - int fd; - char * sf, * token; + char *line = NULL; + size_t line_size = 0; + ssize_t ret; + FILE *fp; + int found = 0; + char *sf, *token; char *saveptr = NULL; value[0] = 0; - fd = open(conf_file, O_RDONLY); - if (fd == -1) + fp = fopen(conf_file, "r"); + if (fp == NULL) return -1; while (1) { - ret = openvz_readline(fd, line, sizeof(line)); + ret = getline(&line, &line_size, fp); if (ret <= 0) break; saveptr = NULL; @@ -658,7 +676,9 @@ openvzReadConfigParam(const char * conf_file ,const char * param, char *value, i if (sf[0] == '=' && sf[1] != '\0' ) { sf++; if ((token = strtok_r(sf,"\"\t\n", &saveptr)) != NULL) { - if (virStrcpy(value, token, maxlen) == NULL) { + VIR_FREE(*value); + *value = strdup(token); + if (value == NULL) { ret = -1; break; } @@ -667,7 +687,8 @@ openvzReadConfigParam(const char * conf_file ,const char * param, char *value, i } } } - VIR_FORCE_CLOSE(fd); + VIR_FREE(line); + VIR_FORCE_FCLOSE(fp); if (ret == 0 && found) ret = 1; @@ -676,14 +697,18 @@ openvzReadConfigParam(const char * conf_file ,const char * param, char *value, i } /* -* Read parameter from container config -* sample: 133, "OSTEMPLATE", value, 1024 -* return: -1 - error -* 0 - don't found -* 1 - OK -*/ + * Read parameter from container config + * + * value will be freed before a new value is assined to it, the caller is + * responsible for freeing it afterwards. + * + * sample: 133, "OSTEMPLATE", &value + * return: -1 - error + * 0 - don't found + * 1 - OK + */ int -openvzReadVPSConfigParam(int vpsid ,const char * param, char *value, int maxlen) +openvzReadVPSConfigParam(int vpsid, const char *param, char **value) { char *conf_file; int ret; @@ -691,7 +716,7 @@ openvzReadVPSConfigParam(int vpsid ,const char * param, char *value, int maxlen) if (openvzLocateConfFile(vpsid, &conf_file, "conf") < 0) return -1; - ret = openvzReadConfigParam(conf_file, param, value, maxlen); + ret = openvzReadConfigParam(conf_file, param, value); VIR_FREE(conf_file); return ret; } @@ -699,21 +724,23 @@ openvzReadVPSConfigParam(int vpsid ,const char * param, char *value, int maxlen) static int openvz_copyfile(char* from_path, char* to_path) { - char line[PATH_MAX]; - int fd, copy_fd; + char *line = NULL; + size_t line_size = 0; + FILE *fp; + int copy_fd; int bytes_read; - fd = open(from_path, O_RDONLY); - if (fd == -1) + fp = fopen(from_path, "r"); + if (fp == NULL) return -1; copy_fd = open(to_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (copy_fd == -1) { - VIR_FORCE_CLOSE(fd); + VIR_FORCE_FCLOSE(fp); return -1; } while (1) { - if (openvz_readline(fd, line, sizeof(line)) <= 0) + if (getline(&line, &line_size, fp) <= 0) break; bytes_read = strlen(line); @@ -721,15 +748,18 @@ openvz_copyfile(char* from_path, char* to_path) goto error; } - if (VIR_CLOSE(fd) < 0) + if (VIR_FCLOSE(fp) < 0) goto error; if (VIR_CLOSE(copy_fd) < 0) goto error; + VIR_FREE(line); + return 0; error: - VIR_FORCE_CLOSE(fd); + VIR_FREE(line); + VIR_FORCE_FCLOSE(fp); VIR_FORCE_CLOSE(copy_fd); return -1; } @@ -742,14 +772,13 @@ error: int openvzCopyDefaultConfig(int vpsid) { - char * confdir = NULL; - char * default_conf_file = NULL; - char configfile_value[PATH_MAX]; + char *confdir = NULL; + char *default_conf_file = NULL; + char *configfile_value = NULL; char *conf_file = NULL; int ret = -1; - if (openvzReadConfigParam(VZ_CONF_FILE, "CONFIGFILE", configfile_value, - PATH_MAX) < 0) + if (openvzReadConfigParam(VZ_CONF_FILE, "CONFIGFILE", &configfile_value) < 0) goto cleanup; confdir = openvzLocateConfDir(); @@ -772,6 +801,7 @@ openvzCopyDefaultConfig(int vpsid) cleanup: VIR_FREE(confdir); VIR_FREE(default_conf_file); + VIR_FREE(configfile_value); VIR_FREE(conf_file); return ret; } @@ -844,22 +874,24 @@ static int openvzGetVPSUUID(int vpsid, char *uuidstr, size_t len) { char *conf_file; - char line[1024]; + char *line = NULL; + size_t line_size = 0; + ssize_t ret; char *saveptr = NULL; char *uuidbuf; char *iden; - int fd, ret; + FILE *fp; int retval = -1; if (openvzLocateConfFile(vpsid, &conf_file, "conf") < 0) return -1; - fd = open(conf_file, O_RDONLY); - if (fd == -1) + fp = fopen(conf_file, "r"); + if (fp == NULL) goto cleanup; while (1) { - ret = openvz_readline(fd, line, sizeof(line)); + ret = getline(&line, &line_size, fp); if (ret == -1) goto cleanup; @@ -882,7 +914,8 @@ openvzGetVPSUUID(int vpsid, char *uuidstr, size_t len) } retval = 0; cleanup: - VIR_FORCE_CLOSE(fd); + VIR_FREE(line); + VIR_FORCE_FCLOSE(fp); VIR_FREE(conf_file); return retval; diff --git a/src/openvz/openvz_conf.h b/src/openvz/openvz_conf.h index 50bcb5e..4673fa6 100644 --- a/src/openvz/openvz_conf.h +++ b/src/openvz/openvz_conf.h @@ -55,7 +55,7 @@ struct openvz_driver { int openvz_readline(int fd, char *ptr, int maxlen); int openvzExtractVersion(struct openvz_driver *driver); -int openvzReadVPSConfigParam(int vpsid ,const char * param, char *value, int maxlen); +int openvzReadVPSConfigParam(int vpsid, const char *param, char **value); int openvzWriteVPSConfigParam(int vpsid, const char *param, const char *value); int openvzCopyDefaultConfig(int vpsid); virCapsPtr openvzCapsInit(void); diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index fb30c37..c6fee3b 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -631,15 +631,16 @@ openvzGenerateVethName(int veid, char *dev_name_ve) static char * openvzGenerateContainerVethName(int veid) { - char temp[1024]; + char *temp = NULL; + char *name = NULL; /* try to get line "^NETIF=..." from config */ - if (openvzReadVPSConfigParam(veid, "NETIF", temp, sizeof(temp)) <= 0) { - snprintf(temp, sizeof(temp), "eth0"); + if (openvzReadVPSConfigParam(veid, "NETIF", &temp) <= 0) { + name = strdup("eth0"); } else { char *saveptr; - char *s; - int max = 0; + char *s; + int max = 0; /* get maximum interface number (actually, it is the last one) */ for (s=strtok_r(temp, ";", &saveptr); s; s=strtok_r(NULL, ";", &saveptr)) { @@ -650,9 +651,16 @@ openvzGenerateContainerVethName(int veid) } /* set new name */ - snprintf(temp, sizeof(temp), "eth%d", max+1); + virAsprintf(&name, "eth%d", max + 1); } - return strdup(temp); + + VIR_FREE(temp); + + if (name == NULL) { + virReportOOMError(); + } + + return name; } static int @@ -1125,7 +1133,7 @@ openvzDomainGetAutostart(virDomainPtr dom, int *autostart) { struct openvz_driver *driver = dom->conn->privateData; virDomainObjPtr vm; - char value[1024]; + char *value = NULL; int ret = -1; openvzDriverLock(driver); @@ -1138,7 +1146,7 @@ openvzDomainGetAutostart(virDomainPtr dom, int *autostart) goto cleanup; } - if (openvzReadVPSConfigParam(strtoI(vm->def->name), "ONBOOT", value, sizeof(value)) < 0) { + if (openvzReadVPSConfigParam(strtoI(vm->def->name), "ONBOOT", &value) < 0) { openvzError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not read container config")); goto cleanup; @@ -1150,6 +1158,8 @@ openvzDomainGetAutostart(virDomainPtr dom, int *autostart) ret = 0; cleanup: + VIR_FREE(value); + if (vm) virDomainObjUnlock(vm); return ret; @@ -1464,12 +1474,14 @@ out: return -1; } -static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid) { - int fd; - char line[1024] ; +static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid) +{ + FILE *fp; + char *line = NULL; + size_t line_size = 0; unsigned long long usertime, systime, nicetime; int readvps = vpsid + 1; /* ensure readvps is initially different */ - int ret; + ssize_t ret; /* read statistic from /proc/vz/vestat. sample: @@ -1479,12 +1491,12 @@ Version: 2.2 55 178 0 5340 59424597 542650441835148 other.. */ - if ((fd = open("/proc/vz/vestat", O_RDONLY)) == -1) + if ((fp = fopen("/proc/vz/vestat", "r")) == NULL) return -1; /*search line with VEID=vpsid*/ while (1) { - ret = openvz_readline(fd, line, sizeof(line)); + ret = getline(&line, &line_size, fp); if (ret <= 0) break; @@ -1499,7 +1511,8 @@ Version: 2.2 } } - VIR_FORCE_CLOSE(fd); + VIR_FREE(line); + VIR_FORCE_FCLOSE(fp); if (ret < 0) return -1; -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:28 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:28 +0200 Subject: [libvirt] [PATCH 15/20] qemu: Remove PATH_MAX sized stack allocation used in commandline building In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-16-git-send-email-matthias.bolte@googlemail.com> --- src/qemu/qemu_command.c | 43 ++++++++++++++++++++++++++++++------------- 1 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 3138943..326a6b3 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3318,7 +3318,8 @@ qemuBuildCommandLine(virConnectPtr conn, } else { for (i = 0 ; i < def->ndisks ; i++) { char dev[NAME_MAX]; - char file[PATH_MAX]; + char *file; + const char *fmt; virDomainDiskDefPtr disk = def->disks[i]; int j; @@ -3368,9 +3369,13 @@ qemuBuildCommandLine(virConnectPtr conn, goto error; } if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) - snprintf(file, PATH_MAX, "fat:floppy:%s", disk->src); + fmt = "fat:floppy:%s"; else - snprintf(file, PATH_MAX, "fat:%s", disk->src); + fmt = "fat:%s"; + + if (virAsprintf(&file, fmt, disk->src) < 0) { + goto no_memory; + } } else if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK) { switch (disk->protocol) { case VIR_DOMAIN_DISK_PROTOCOL_NBD: @@ -3379,11 +3384,15 @@ qemuBuildCommandLine(virConnectPtr conn, _("NBD accepts only one host")); goto error; } - snprintf(file, PATH_MAX, "nbd:%s:%s,", - disk->hosts->name, disk->hosts->port); + if (virAsprintf(&file, "nbd:%s:%s,", disk->hosts->name, + disk->hosts->port) < 0) { + goto no_memory; + } break; case VIR_DOMAIN_DISK_PROTOCOL_RBD: - snprintf(file, PATH_MAX, "rbd:%s,", disk->src); + if (virAsprintf(&file, "rbd:%s,", disk->src) < 0) { + goto no_memory; + } for (j = 0 ; j < disk->nhosts ; j++) { if (!has_rbd_hosts) { virBufferAddLit(&rbd_hosts, "CEPH_ARGS=-m "); @@ -3403,20 +3412,28 @@ qemuBuildCommandLine(virConnectPtr conn, } break; case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG: - if (disk->nhosts == 0) - snprintf(file, PATH_MAX, "sheepdog:%s,", disk->src); - else + if (disk->nhosts == 0) { + if (virAsprintf(&file, "sheepdog:%s,", disk->src) < 0) { + goto no_memory; + } + } else { /* only one host is supported now */ - snprintf(file, PATH_MAX, "sheepdog:%s:%s:%s,", - disk->hosts->name, disk->hosts->port, - disk->src); + if (virAsprintf(&file, "sheepdog:%s:%s:%s,", + disk->hosts->name, disk->hosts->port, + disk->src) < 0) { + goto no_memory; + } + } break; } } else { - snprintf(file, PATH_MAX, "%s", disk->src); + if (!(file = strdup(disk->src))) { + goto no_memory; + } } virCommandAddArgList(cmd, dev, file, NULL); + VIR_FREE(file); } } -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:29 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:29 +0200 Subject: [libvirt] [PATCH 16/20] xen: Remove PATH_MAX sized stack allocation from block stats code In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-17-git-send-email-matthias.bolte@googlemail.com> --- src/xen/block_stats.c | 52 +++++++++++++++++++++++++----------------------- 1 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/xen/block_stats.c b/src/xen/block_stats.c index e7c80c9..6b4171d 100644 --- a/src/xen/block_stats.c +++ b/src/xen/block_stats.c @@ -113,34 +113,36 @@ read_stat (const char *path) } static int64_t -read_bd_stat (int device, int domid, const char *str) +read_bd_stat(int device, int domid, const char *str) { - char path[PATH_MAX]; + static const char *paths[] = { + "/sys/bus/xen-backend/devices/vbd-%d-%d/statistics/%s", + "/sys/bus/xen-backend/devices/tap-%d-%d/statistics/%s", + "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s", + "/sys/devices/xen-backend/tap-%d-%d/statistics/%s", + NULL + }; + + int i; + char *path; int64_t r; - snprintf (path, sizeof path, - "/sys/bus/xen-backend/devices/vbd-%d-%d/statistics/%s", - domid, device, str); - r = read_stat (path); - if (r >= 0) return r; - - snprintf (path, sizeof path, - "/sys/bus/xen-backend/devices/tap-%d-%d/statistics/%s", - domid, device, str); - r = read_stat (path); - if (r >= 0) return r; - - snprintf (path, sizeof path, - "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s", - domid, device, str); - r = read_stat (path); - if (r >= 0) return r; - - snprintf (path, sizeof path, - "/sys/devices/xen-backend/tap-%d-%d/statistics/%s", - domid, device, str); - r = read_stat (path); - return r; + for (i = 0; paths[i] != NULL; ++i) { + if (virAsprintf(&path, paths[i], domid, device, str) < 0) { + virReportOOMError(); + return -1; + } + + r = read_stat(path); + + VIR_FREE(path); + + if (r >= 0) { + return r; + } + } + + return -1; } /* In Xenstore, /local/domain/0/backend/vbd///state, -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:30 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:30 +0200 Subject: [libvirt] [PATCH 17/20] storage: Remove PATH_MAX sized stack allocation from iSCSI backend In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-18-git-send-email-matthias.bolte@googlemail.com> --- src/storage/storage_backend_iscsi.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/storage/storage_backend_iscsi.c b/src/storage/storage_backend_iscsi.c index 6eff5f5..2e2e99e 100644 --- a/src/storage/storage_backend_iscsi.c +++ b/src/storage/storage_backend_iscsi.c @@ -409,12 +409,15 @@ static int virStorageBackendISCSIFindLUs(virStoragePoolObjPtr pool, const char *session) { - char sysfs_path[PATH_MAX]; + char *sysfs_path; int retval = 0; uint32_t host; - snprintf(sysfs_path, PATH_MAX, - "/sys/class/iscsi_session/session%s/device", session); + if (virAsprintf(&sysfs_path, + "/sys/class/iscsi_session/session%s/device", session) < 0) { + virReportOOMError(); + return -1; + } if (virStorageBackendSCSIGetHostNumber(sysfs_path, &host) < 0) { virReportSystemError(errno, @@ -430,6 +433,8 @@ virStorageBackendISCSIFindLUs(virStoragePoolObjPtr pool, retval = -1; } + VIR_FREE(sysfs_path); + return retval; } -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:31 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:31 +0200 Subject: [libvirt] [PATCH 18/20] uml: Remove PATH_MAX sized stack allocation from /proc parsing code In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-19-git-send-email-matthias.bolte@googlemail.com> --- src/uml/uml_driver.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index e2bd5f2..33849a0 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -1036,21 +1036,25 @@ static char *umlGetCapabilities(virConnectPtr conn) { -static int umlGetProcessInfo(unsigned long long *cpuTime, int pid) { - char proc[PATH_MAX]; +static int umlGetProcessInfo(unsigned long long *cpuTime, int pid) +{ + char *proc; FILE *pidinfo; unsigned long long usertime, systime; - if (snprintf(proc, sizeof(proc), "/proc/%d/stat", pid) >= (int)sizeof(proc)) { + if (virAsprintf(&proc, "/proc/%d/stat", pid) < 0) { return -1; } if (!(pidinfo = fopen(proc, "r"))) { /* VM probably shut down, so fake 0 */ *cpuTime = 0; + VIR_FREE(proc); return 0; } + VIR_FREE(proc); + if (fscanf(pidinfo, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu", &usertime, &systime) != 2) { umlDebug("not enough arg"); VIR_FORCE_FCLOSE(pidinfo); -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:32 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:32 +0200 Subject: [libvirt] [PATCH 19/20] xend: Remove 4kb stack allocation In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-20-git-send-email-matthias.bolte@googlemail.com> --- src/xen/xend_internal.c | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 8859373..8b07a8a 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -279,11 +279,17 @@ istartswith(const char *haystack, const char *needle) static int ATTRIBUTE_NONNULL (2) xend_req(int fd, char **content) { - char buffer[4096]; + char *buffer; + size_t buffer_size = 4096; int content_length = 0; int retcode = 0; - while (sreads(fd, buffer, sizeof(buffer)) > 0) { + if (VIR_ALLOC_N(buffer, buffer_size) < 0) { + virReportOOMError(); + return -1; + } + + while (sreads(fd, buffer, buffer_size) > 0) { if (STREQ(buffer, "\r\n")) break; @@ -293,6 +299,8 @@ xend_req(int fd, char **content) retcode = atoi(buffer + 9); } + VIR_FREE(buffer); + if (content_length > 0) { ssize_t ret; -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 09:21:33 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 11:21:33 +0200 Subject: [libvirt] [PATCH 20/20] Use virBufferPtr for sexpr2string instead of manual buffer handling In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1301822493-23013-21-git-send-email-matthias.bolte@googlemail.com> Removes 4kb stack allocation in the XenD subdriver. --- src/util/sexpr.c | 142 +++++++++++++++++++++++------------------------ src/util/sexpr.h | 3 +- src/xen/xend_internal.c | 17 +++++- 3 files changed, 86 insertions(+), 76 deletions(-) diff --git a/src/util/sexpr.c b/src/util/sexpr.c index 7f14206..ae1692a 100644 --- a/src/util/sexpr.c +++ b/src/util/sexpr.c @@ -199,78 +199,56 @@ sexpr_append(struct sexpr *lst, const struct sexpr *value) * sexpr2string: * @sexpr: an S-Expression pointer * @buffer: the output buffer - * @n_buffer: the size of the buffer in bytes * * Serialize the S-Expression in the buffer. - * Note that the output may be truncated if @n_buffer is too small - * resulting in an unparseable value. * - * Returns the number of bytes used by the serialization in the buffer or - * 0 in case of error. + * Returns 0 on success, -1 on error. */ -size_t -sexpr2string(const struct sexpr * sexpr, char *buffer, size_t n_buffer) +int +sexpr2string(const struct sexpr *sexpr, virBufferPtr buffer) { - size_t ret = 0, tmp; - - if ((sexpr == NULL) || (buffer == NULL) || (n_buffer <= 0)) - return (0); + if ((sexpr == NULL) || (buffer == NULL)) + return -1; switch (sexpr->kind) { - case SEXPR_CONS: - tmp = snprintf(buffer + ret, n_buffer - ret, "("); - if (tmp == 0) - goto error; - ret += tmp; - tmp = sexpr2string(sexpr->u.s.car, buffer + ret, n_buffer - ret); - if (tmp == 0) - goto error; - ret += tmp; - while (sexpr->u.s.cdr->kind != SEXPR_NIL) { - sexpr = sexpr->u.s.cdr; - tmp = snprintf(buffer + ret, n_buffer - ret, " "); - if (tmp == 0) - goto error; - ret += tmp; - tmp = - sexpr2string(sexpr->u.s.car, buffer + ret, n_buffer - ret); - if (tmp == 0) - goto error; - ret += tmp; - } - tmp = snprintf(buffer + ret, n_buffer - ret, ")"); - if (tmp == 0) - goto error; - ret += tmp; - break; - case SEXPR_VALUE: - if (strchr(sexpr->u.value, ' ') || - strchr(sexpr->u.value, ')') || - strchr(sexpr->u.value, '(')) - tmp = snprintf(buffer + ret, n_buffer - ret, "'%s'", - sexpr->u.value); - else - tmp = snprintf(buffer + ret, n_buffer - ret, "%s", - sexpr->u.value); - if (tmp == 0) - goto error; - ret += tmp; - break; - case SEXPR_NIL: - tmp = snprintf(buffer + ret, n_buffer - ret, "()"); - if (tmp == 0) - goto error; - ret += tmp; - break; - default: + case SEXPR_CONS: + virBufferAddChar(buffer, '('); + + if (sexpr2string(sexpr->u.s.car, buffer) < 0) goto error; + + while (sexpr->u.s.cdr->kind != SEXPR_NIL) { + sexpr = sexpr->u.s.cdr; + + virBufferAddChar(buffer, ' '); + + if (sexpr2string(sexpr->u.s.car, buffer) < 0) + goto error; + } + + virBufferAddChar(buffer, ')'); + break; + case SEXPR_VALUE: + if (strchr(sexpr->u.value, ' ') || + strchr(sexpr->u.value, ')') || + strchr(sexpr->u.value, '(')) + virBufferVSprintf(buffer, "'%s'", sexpr->u.value); + else + virBufferVSprintf(buffer, "%s", sexpr->u.value); + + break; + case SEXPR_NIL: + virBufferAddLit(buffer, "()"); + break; + default: + goto error; } - return (ret); + return 0; + error: - buffer[n_buffer - 1] = 0; - virSexprError(VIR_ERR_SEXPR_SERIAL, "%s", buffer); - return (0); + virSexprError(VIR_ERR_SEXPR_SERIAL, NULL); + return -1; } #define IS_SPACE(c) ((c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA)) @@ -413,22 +391,28 @@ string2sexpr(const char *buffer) static struct sexpr * sexpr_lookup_key(const struct sexpr *sexpr, const char *node) { - char buffer[4096], *ptr, *token; + struct sexpr *result = NULL; + char *buffer, *ptr, *token; if ((node == NULL) || (sexpr == NULL)) - return (NULL); + return NULL; - snprintf(buffer, sizeof(buffer), "%s", node); + buffer = strdup(node); + + if (buffer == NULL) { + virReportOOMError(); + return NULL; + } ptr = buffer; token = strsep(&ptr, "/"); if (sexpr->kind != SEXPR_CONS || sexpr->u.s.car->kind != SEXPR_VALUE) { - return NULL; + goto cleanup; } if (STRNEQ(sexpr->u.s.car->u.value, token)) { - return NULL; + goto cleanup; } for (token = strsep(&ptr, "/"); token; token = strsep(&ptr, "/")) { @@ -454,10 +438,15 @@ sexpr_lookup_key(const struct sexpr *sexpr, const char *node) } if (token != NULL) { - return NULL; + goto cleanup; } - return (struct sexpr *) sexpr; + result = (struct sexpr *) sexpr; + +cleanup: + VIR_FREE(buffer); + + return result; } /** @@ -550,21 +539,30 @@ int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst) * @... extra data to build the path * * Search a node value in the S-Expression based on its path - * NOTE: path are limited to 4096 bytes. * * Returns the value of the node or NULL if not found. */ const char * sexpr_fmt_node(const struct sexpr *sexpr, const char *fmt, ...) { + int result; va_list ap; - char node[4096]; + char *node; + const char *value; va_start(ap, fmt); - vsnprintf(node, sizeof(node), fmt, ap); + result = virVasprintf(&node, fmt, ap); va_end(ap); - return sexpr_node(sexpr, node); + if (result < 0) { + return NULL; + } + + value = sexpr_node(sexpr, node); + + VIR_FREE(node); + + return value; } /** diff --git a/src/util/sexpr.h b/src/util/sexpr.h index dc6687d..8dfd89a 100644 --- a/src/util/sexpr.h +++ b/src/util/sexpr.h @@ -14,6 +14,7 @@ # define _LIBVIR_SEXPR_H_ # include "internal.h" +# include "buf.h" # include # include @@ -36,7 +37,7 @@ struct sexpr { }; /* conversion to/from strings */ -size_t sexpr2string(const struct sexpr *sexpr, char *buffer, size_t n_buffer); +int sexpr2string(const struct sexpr *sexpr, virBufferPtr buffer); struct sexpr *string2sexpr(const char *buffer); /* constructors and destructors */ diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 8b07a8a..04122ba 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -3023,7 +3023,8 @@ xenDaemonDomainSetAutostart(virDomainPtr domain, int autostart) { struct sexpr *root, *autonode; - char buf[4096]; + virBuffer buffer = VIR_BUFFER_INITIALIZER; + char *content = NULL; int ret = -1; xenUnifiedPrivatePtr priv; @@ -3065,12 +3066,20 @@ xenDaemonDomainSetAutostart(virDomainPtr domain, goto error; } - if (sexpr2string(root, buf, sizeof(buf)) == 0) { + if (sexpr2string(root, &buffer) < 0) { virXendError(VIR_ERR_INTERNAL_ERROR, "%s", _("sexpr2string failed")); goto error; } - if (xend_op(domain->conn, "", "op", "new", "config", buf, NULL) != 0) { + + if (virBufferError(&buffer)) { + virReportOOMError(); + goto error; + } + + content = virBufferContentAndReset(&buffer); + + if (xend_op(domain->conn, "", "op", "new", "config", content, NULL) != 0) { virXendError(VIR_ERR_XEN_CALL, "%s", _("Failed to redefine sexpr")); goto error; @@ -3083,6 +3092,8 @@ xenDaemonDomainSetAutostart(virDomainPtr domain, ret = 0; error: + virBufferFreeAndReset(&buffer); + VIR_FREE(content); sexpr_free(root); return ret; } -- 1.7.0.4 From stefanha at gmail.com Sun Apr 3 11:57:02 2011 From: stefanha at gmail.com (Stefan Hajnoczi) Date: Sun, 3 Apr 2011 12:57:02 +0100 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> Message-ID: On Tue, Mar 29, 2011 at 8:04 PM, Stefan Hajnoczi wrote: > Piggy-back on the guest CD-ROM polling to poll on the host. ?Open and > close the host CD-ROM file descriptor to ensure we read the new size and > not a stale size. > > Two things are going on here: > > 1. If hald/udisks is not already polling CD-ROMs on the host then > ? re-opening the CD-ROM causes the host to read the new medium's size. > > 2. There is a bug in Linux which means the CD-ROM file descriptor must > ? be re-opened in order for lseek(2) to see the new size. ?The > ? inode size gets out of sync with the underlying device (which you can > ? confirm by checking that /sys/block/sr0/size and lseek(2) do not > ? match after media change). ?I have raised this with the > ? maintainers but we need a workaround for the foreseeable future. > > Note that these changes are all in a #ifdef __linux__ section. > > Signed-off-by: Stefan Hajnoczi > --- > ?block/raw-posix.c | ? 26 ++++++++++++++++++++++---- > ?1 files changed, 22 insertions(+), 4 deletions(-) > > diff --git a/block/raw-posix.c b/block/raw-posix.c > index 6b72470..8b5205c 100644 > --- a/block/raw-posix.c > +++ b/block/raw-posix.c > @@ -1238,10 +1238,28 @@ static int cdrom_is_inserted(BlockDriverState *bs) > ? ? BDRVRawState *s = bs->opaque; > ? ? int ret; > > - ? ?ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); > - ? ?if (ret == CDS_DISC_OK) > - ? ? ? ?return 1; > - ? ?return 0; > + ? ?/* > + ? ? * Close the file descriptor if no medium is present and open it to poll > + ? ? * again. ?This ensures the medium size is refreshed. ?If the file > + ? ? * descriptor is kept open the size can become stale. ?This is essentially > + ? ? * replicating CD-ROM polling but is driven by the guest. ?As the guest > + ? ? * polls, we poll the host. > + ? ? */ > + > + ? ?if (s->fd == -1) { > + ? ? ? ?s->fd = qemu_open(bs->filename, s->open_flags, 0644); > + ? ? ? ?if (s->fd < 0) { > + ? ? ? ? ? ?return 0; > + ? ? ? ?} > + ? ?} > + > + ? ?ret = (ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK); > + > + ? ?if (!ret) { > + ? ? ? ?close(s->fd); > + ? ? ? ?s->fd = -1; > + ? ?} > + ? ?return ret; > ?} > > ?static int cdrom_eject(BlockDriverState *bs, int eject_flag) > -- > 1.7.4.1 > > > There is an issue with reopening host devices in QEMU when running under libvirt. It appears that libvirt chowns image files (including device nodes) so that the launched QEMU process can access them. Unfortunately after media change on host devices udev will reset the ownership of the device node. This causes open(2) to fail with EACCES since the QEMU process does not have the right uid/gid/groups and libvirt is unaware that the file's ownership has changed. In order for media change to work with Linux host CD-ROM it is necessary to reopen the file (otherwise the inode size will not refresh, this is an issue with existing kernels). How can libvirt's security model be made to support this case? In theory udev could be temporarily configured with libvirt permissions for the CD-ROM device while passed through to the guest, but is that feasible? Stefan From matthias.bolte at googlemail.com Sun Apr 3 12:19:14 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 14:19:14 +0200 Subject: [libvirt] [PATCH] vmx: Use case-insensitive compare functions for all content Message-ID: <20110403121914.GA22826@sbox> --- src/vmx/vmx.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c index 9f4d5fb..9a482ef 100644 --- a/src/vmx/vmx.c +++ b/src/vmx/vmx.c @@ -730,7 +730,7 @@ virVMXGetConfigLong(virConfPtr conf, const char *name, long long *number, } } - if (STREQ(value->str, "unlimited")) { + if (STRCASEEQ(value->str, "unlimited")) { *number = -1; } else if (virStrToLong_ll(value->str, NULL, 10, number) < 0) { VMX_ERROR(VIR_ERR_INTERNAL_ERROR, @@ -1385,7 +1385,7 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx) goto cleanup; } - if (sched_cpu_affinity != NULL && STRNEQ(sched_cpu_affinity, "all")) { + if (sched_cpu_affinity != NULL && STRCASENEQ(sched_cpu_affinity, "all")) { const char *current = sched_cpu_affinity; int number, count = 0; @@ -2107,7 +2107,7 @@ virVMXParseDisk(virVMXContext *ctx, virCapsPtr caps, virConfPtr conf, goto cleanup; } } else if (virFileHasSuffix(fileName, ".iso") || - STREQ(deviceType, "atapi-cdrom")) { + STRCASEEQ(deviceType, "atapi-cdrom")) { /* * This function was called in order to parse a harddisk device, * but .iso files and 'atapi-cdrom' devices are for CDROM devices @@ -2146,7 +2146,7 @@ virVMXParseDisk(virVMXContext *ctx, virCapsPtr caps, virConfPtr conf, * handle it. */ goto ignore; - } else if (STREQ(deviceType, "atapi-cdrom")) { + } else if (STRCASEEQ(deviceType, "atapi-cdrom")) { (*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK; (*def)->src = fileName; @@ -2174,7 +2174,7 @@ virVMXParseDisk(virVMXContext *ctx, virCapsPtr caps, virConfPtr conf, if ((*def)->src == NULL) { goto cleanup; } - } else if (fileType != NULL && STREQ(fileType, "device")) { + } else if (fileType != NULL && STRCASEEQ(fileType, "device")) { (*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK; (*def)->src = fileName; -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 3 12:43:55 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 3 Apr 2011 14:43:55 +0200 Subject: [libvirt] [PATCH] vmx: Support persistent CPU shares Message-ID: <20110403124355.GA22943@sbox> --- src/vmx/vmx.c | 43 ++++++++++++++++++++++ tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx | 2 +- tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml | 3 ++ tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml | 3 ++ tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx | 2 +- tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml | 3 ++ tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml | 3 ++ tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml | 3 ++ tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx | 1 + tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml | 3 ++ tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx | 1 + tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml | 3 ++ tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx | 1 + tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml | 3 ++ 14 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c index 9a482ef..b0d3218 100644 --- a/src/vmx/vmx.c +++ b/src/vmx/vmx.c @@ -55,6 +55,8 @@ def->mem.cur_balloon = <=> sched.mem.max = "mem.min_guarantee = <=> sched.mem.minsize = "" # defaults to 0 def->maxvcpus = <=> numvcpus = "" # must be 1 or a multiple of 2, defaults to 1 def->cpumask = <=> sched.cpu.affinity = "" +def->cputune.shares = <=> sched.cpu.shares = "" # with handling for special values + # "high", "normal", "low" @@ -1200,6 +1202,7 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx) long long sched_mem_minsize = 0; long long numvcpus = 0; char *sched_cpu_affinity = NULL; + char *sched_cpu_shares = NULL; char *guestOS = NULL; bool smbios_reflecthost = false; int controller; @@ -1449,6 +1452,30 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx) } } + /* vmx:sched.cpu.shares -> def:cputune.shares */ + if (virVMXGetConfigString(conf, "sched.cpu.shares", &sched_cpu_shares, + true) < 0) { + goto cleanup; + } + + if (sched_cpu_shares != NULL) { + /* See http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.SharesInfo.Level.html */ + if (STRCASEEQ(sched_cpu_shares, "low")) { + def->cputune.shares = def->vcpus * 500; + } else if (STRCASEEQ(sched_cpu_shares, "normal")) { + def->cputune.shares = def->vcpus * 1000; + } else if (STRCASEEQ(sched_cpu_shares, "high")) { + def->cputune.shares = def->vcpus * 2000; + } else if (virStrToLong_ul(sched_cpu_shares, NULL, 10, + &def->cputune.shares) < 0) { + VMX_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Expecting VMX entry 'sched.cpu.shares' to be an " + "unsigned integer or 'low', 'normal' or 'high' but " + "found '%s'"), sched_cpu_shares); + goto cleanup; + } + } + /* def:lifecycle */ def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART; def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY; @@ -1715,6 +1742,7 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx) virConfFree(conf); VIR_FREE(encoding); VIR_FREE(sched_cpu_affinity); + VIR_FREE(sched_cpu_shares); VIR_FREE(guestOS); return def; @@ -2998,6 +3026,21 @@ virVMXFormatConfig(virVMXContext *ctx, virCapsPtr caps, virDomainDefPtr def, virBufferAddLit(&buffer, "\"\n"); } + /* def:cputune.shares -> vmx:sched.cpu.shares */ + if (def->cputune.shares > 0) { + /* See http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.SharesInfo.Level.html */ + if (def->cputune.shares == def->vcpus * 500) { + virBufferAddLit(&buffer, "sched.cpu.shares = \"low\"\n"); + } else if (def->cputune.shares == def->vcpus * 1000) { + virBufferAddLit(&buffer, "sched.cpu.shares = \"normal\"\n"); + } else if (def->cputune.shares == def->vcpus * 2000) { + virBufferAddLit(&buffer, "sched.cpu.shares = \"high\"\n"); + } else { + virBufferVSprintf(&buffer, "sched.cpu.shares = \"%lu\"\n", + def->cputune.shares); + } + } + /* def:graphics */ for (i = 0; i < def->ngraphics; ++i) { switch (def->graphics[i]->type) { diff --git a/tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx b/tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx index bd36cf8..8641c5c 100644 --- a/tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx +++ b/tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx @@ -35,7 +35,7 @@ UUID.BIOS = "50 11 5E 16 9B DC 49 D7-F1 71 53 C4 D7 F9 17 10" SNAPSHOT.ACTION = "KEEP" SCHED.CPU.MIN = "0" SCHED.CPU.UNITS = "MHZ" -SCHED.CPU.SHARES = "NORMAL" +SCHED.CPU.SHARES = "4223" SCHED.MEM.MINSIZE = "0" SCHED.MEM.SHARES = "NORMAL" TOOLSCRIPTS.AFTERPOWERON = "TRUE" diff --git a/tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml b/tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml index 7a5ff5b..ef6edd8 100644 --- a/tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml +++ b/tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml @@ -4,6 +4,9 @@ 1048576 1048576 1 + + 4223 + hvm diff --git a/tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml b/tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml index 18d6461..02771b9 100644 --- a/tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml +++ b/tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml @@ -4,6 +4,9 @@ 1048576 1048576 1 + + 1000 + hvm diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx index 4392062..78741ae 100644 --- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx +++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx @@ -36,7 +36,7 @@ uuid.bios = "50 11 5e 16 9b dc 49 d7-f1 71 53 c4 d7 f9 17 10" snapshot.action = "keep" sched.cpu.min = "0" sched.cpu.units = "mhz" -sched.cpu.shares = "normal" +sched.cpu.shares = "low" sched.mem.minsize = "0" sched.mem.shares = "normal" toolScripts.afterPowerOn = "true" diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml index 5e67e74..e8f9307 100644 --- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml +++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml @@ -4,6 +4,9 @@ 1048576 1048576 1 + + 500 + hvm diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml index 419df51..2824d66 100644 --- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml +++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml @@ -4,6 +4,9 @@ 524288 524288 1 + + 1000 + hvm diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml index 0040163..6f0a9d1 100644 --- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml +++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml @@ -8,6 +8,9 @@ 262144 2 + + 2000 + hvm diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx index e72ca80..9059197 100644 --- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx +++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx @@ -6,6 +6,7 @@ uuid.bios = "50 11 5e 16 9b dc 49 d7-f1 71 53 c4 d7 f9 17 10" displayName = "Fedora11" memsize = "1024" numvcpus = "1" +sched.cpu.shares = "low" scsi0.present = "true" scsi0.virtualDev = "lsilogic" scsi0:0.present = "true" diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml index 3f4ff88..ea59778 100644 --- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml +++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml @@ -4,6 +4,9 @@ 1048576 1048576 1 + + 500 + hvm diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx index 627fcfb..504997f 100644 --- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx +++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx @@ -6,6 +6,7 @@ uuid.bios = "56 4d 9b ef ac d9 b4 e0-c8 f0 ae a8 b9 10 35 15" displayName = "virtMonServ1" memsize = "512" numvcpus = "1" +sched.cpu.shares = "normal" scsi0.present = "true" scsi0.virtualDev = "lsilogic" scsi0:0.present = "true" diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml index 078753a..443aacd 100644 --- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml +++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml @@ -4,6 +4,9 @@ 524288 524288 1 + + 1000 + hvm diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx index cc2485f..2e3b856 100644 --- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx +++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx @@ -8,6 +8,7 @@ annotation = "Centos 5.5 64bit Server" memsize = "2048" sched.mem.minsize = "256" numvcpus = "2" +sched.cpu.shares = "normal" scsi0.present = "true" scsi0.virtualDev = "lsilogic" scsi0:0.present = "true" diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml index d55bf6b..f28c15e 100644 --- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml +++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml @@ -8,6 +8,9 @@ 262144 2 + + 2000 + hvm -- 1.7.0.4 From blauwirbel at gmail.com Sun Apr 3 13:12:08 2011 From: blauwirbel at gmail.com (Blue Swirl) Date: Sun, 3 Apr 2011 16:12:08 +0300 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> Message-ID: On Sun, Apr 3, 2011 at 2:57 PM, Stefan Hajnoczi wrote: > On Tue, Mar 29, 2011 at 8:04 PM, Stefan Hajnoczi > wrote: >> Piggy-back on the guest CD-ROM polling to poll on the host. ?Open and >> close the host CD-ROM file descriptor to ensure we read the new size and >> not a stale size. >> >> Two things are going on here: >> >> 1. If hald/udisks is not already polling CD-ROMs on the host then >> ? re-opening the CD-ROM causes the host to read the new medium's size. >> >> 2. There is a bug in Linux which means the CD-ROM file descriptor must >> ? be re-opened in order for lseek(2) to see the new size. ?The >> ? inode size gets out of sync with the underlying device (which you can >> ? confirm by checking that /sys/block/sr0/size and lseek(2) do not >> ? match after media change). ?I have raised this with the >> ? maintainers but we need a workaround for the foreseeable future. >> >> Note that these changes are all in a #ifdef __linux__ section. >> >> Signed-off-by: Stefan Hajnoczi >> --- >> ?block/raw-posix.c | ? 26 ++++++++++++++++++++++---- >> ?1 files changed, 22 insertions(+), 4 deletions(-) >> >> diff --git a/block/raw-posix.c b/block/raw-posix.c >> index 6b72470..8b5205c 100644 >> --- a/block/raw-posix.c >> +++ b/block/raw-posix.c >> @@ -1238,10 +1238,28 @@ static int cdrom_is_inserted(BlockDriverState *bs) >> ? ? BDRVRawState *s = bs->opaque; >> ? ? int ret; >> >> - ? ?ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); >> - ? ?if (ret == CDS_DISC_OK) >> - ? ? ? ?return 1; >> - ? ?return 0; >> + ? ?/* >> + ? ? * Close the file descriptor if no medium is present and open it to poll >> + ? ? * again. ?This ensures the medium size is refreshed. ?If the file >> + ? ? * descriptor is kept open the size can become stale. ?This is essentially >> + ? ? * replicating CD-ROM polling but is driven by the guest. ?As the guest >> + ? ? * polls, we poll the host. >> + ? ? */ >> + >> + ? ?if (s->fd == -1) { >> + ? ? ? ?s->fd = qemu_open(bs->filename, s->open_flags, 0644); >> + ? ? ? ?if (s->fd < 0) { >> + ? ? ? ? ? ?return 0; >> + ? ? ? ?} >> + ? ?} >> + >> + ? ?ret = (ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK); >> + >> + ? ?if (!ret) { >> + ? ? ? ?close(s->fd); >> + ? ? ? ?s->fd = -1; >> + ? ?} >> + ? ?return ret; >> ?} >> >> ?static int cdrom_eject(BlockDriverState *bs, int eject_flag) >> -- >> 1.7.4.1 >> >> >> > > There is an issue with reopening host devices in QEMU when running > under libvirt. ?It appears that libvirt chowns image files (including > device nodes) so that the launched QEMU process can access them. > > Unfortunately after media change on host devices udev will reset the > ownership of the device node. ?This causes open(2) to fail with EACCES > since the QEMU process does not have the right uid/gid/groups and > libvirt is unaware that the file's ownership has changed. > > In order for media change to work with Linux host CD-ROM it is > necessary to reopen the file (otherwise the inode size will not > refresh, this is an issue with existing kernels). > > How can libvirt's security model be made to support this case? ?In > theory udev could be temporarily configured with libvirt permissions > for the CD-ROM device while passed through to the guest, but is that > feasible? How about something like this: Add an explicit reopen method to BlockDriver. Make a special block device for passed file descriptors. Pass descriptors in libvirt for CD-ROMs instead of the device paths. The reopen method for file descriptors should notify libvirt about need to pass a reopened descriptor and then block all accesses until a new descriptor is available. This should also solve your earlier problem. From stefanha at gmail.com Sun Apr 3 18:06:17 2011 From: stefanha at gmail.com (Stefan Hajnoczi) Date: Sun, 3 Apr 2011 19:06:17 +0100 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> Message-ID: On Sun, Apr 3, 2011 at 2:12 PM, Blue Swirl wrote: > On Sun, Apr 3, 2011 at 2:57 PM, Stefan Hajnoczi wrote: >> On Tue, Mar 29, 2011 at 8:04 PM, Stefan Hajnoczi >> wrote: >>> Piggy-back on the guest CD-ROM polling to poll on the host. ?Open and >>> close the host CD-ROM file descriptor to ensure we read the new size and >>> not a stale size. >>> >>> Two things are going on here: >>> >>> 1. If hald/udisks is not already polling CD-ROMs on the host then >>> ? re-opening the CD-ROM causes the host to read the new medium's size. >>> >>> 2. There is a bug in Linux which means the CD-ROM file descriptor must >>> ? be re-opened in order for lseek(2) to see the new size. ?The >>> ? inode size gets out of sync with the underlying device (which you can >>> ? confirm by checking that /sys/block/sr0/size and lseek(2) do not >>> ? match after media change). ?I have raised this with the >>> ? maintainers but we need a workaround for the foreseeable future. >>> >>> Note that these changes are all in a #ifdef __linux__ section. >>> >>> Signed-off-by: Stefan Hajnoczi >>> --- >>> ?block/raw-posix.c | ? 26 ++++++++++++++++++++++---- >>> ?1 files changed, 22 insertions(+), 4 deletions(-) >>> >>> diff --git a/block/raw-posix.c b/block/raw-posix.c >>> index 6b72470..8b5205c 100644 >>> --- a/block/raw-posix.c >>> +++ b/block/raw-posix.c >>> @@ -1238,10 +1238,28 @@ static int cdrom_is_inserted(BlockDriverState *bs) >>> ? ? BDRVRawState *s = bs->opaque; >>> ? ? int ret; >>> >>> - ? ?ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); >>> - ? ?if (ret == CDS_DISC_OK) >>> - ? ? ? ?return 1; >>> - ? ?return 0; >>> + ? ?/* >>> + ? ? * Close the file descriptor if no medium is present and open it to poll >>> + ? ? * again. ?This ensures the medium size is refreshed. ?If the file >>> + ? ? * descriptor is kept open the size can become stale. ?This is essentially >>> + ? ? * replicating CD-ROM polling but is driven by the guest. ?As the guest >>> + ? ? * polls, we poll the host. >>> + ? ? */ >>> + >>> + ? ?if (s->fd == -1) { >>> + ? ? ? ?s->fd = qemu_open(bs->filename, s->open_flags, 0644); >>> + ? ? ? ?if (s->fd < 0) { >>> + ? ? ? ? ? ?return 0; >>> + ? ? ? ?} >>> + ? ?} >>> + >>> + ? ?ret = (ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK); >>> + >>> + ? ?if (!ret) { >>> + ? ? ? ?close(s->fd); >>> + ? ? ? ?s->fd = -1; >>> + ? ?} >>> + ? ?return ret; >>> ?} >>> >>> ?static int cdrom_eject(BlockDriverState *bs, int eject_flag) >>> -- >>> 1.7.4.1 >>> >>> >>> >> >> There is an issue with reopening host devices in QEMU when running >> under libvirt. ?It appears that libvirt chowns image files (including >> device nodes) so that the launched QEMU process can access them. >> >> Unfortunately after media change on host devices udev will reset the >> ownership of the device node. ?This causes open(2) to fail with EACCES >> since the QEMU process does not have the right uid/gid/groups and >> libvirt is unaware that the file's ownership has changed. >> >> In order for media change to work with Linux host CD-ROM it is >> necessary to reopen the file (otherwise the inode size will not >> refresh, this is an issue with existing kernels). >> >> How can libvirt's security model be made to support this case? ?In >> theory udev could be temporarily configured with libvirt permissions >> for the CD-ROM device while passed through to the guest, but is that >> feasible? > > How about something like this: Add an explicit reopen method to > BlockDriver. Make a special block device for passed file descriptors. > Pass descriptors in libvirt for CD-ROMs instead of the device paths. > The reopen method for file descriptors should notify libvirt about > need to pass a reopened descriptor and then block all accesses until a > new descriptor is available. This should also solve your earlier > problem. I'm hoping libvirt's behavior can be made to just work rather than adding new features to QEMU. But perhaps passing file descriptors is useful for more than just reopening host devices. This would basically be a privilege separation model where the QEMU process isn't able to open files itself but can request libvirt to open them on its behalf. Stefan From wency at cn.fujitsu.com Mon Apr 4 01:42:17 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Mon, 04 Apr 2011 09:42:17 +0800 Subject: [libvirt] [BUG] qemu quited unexpectedly will cause libvirtd crashed In-Reply-To: <4D94CDCA.50801@redhat.com> References: <4D91B1BF.6050106@cn.fujitsu.com> <4D938B96.8090503@redhat.com> <4D94224D.70905@cn.fujitsu.com> <4D94CDCA.50801@redhat.com> Message-ID: <4D9921F9.6070506@cn.fujitsu.com> At 04/01/2011 02:54 AM, Eric Blake Write: > On 03/31/2011 12:42 AM, Wen Congyang wrote: >>>> So I try to use gdb and add sleep() to trigger this bug. I have posted two patches >>>> to fix 2 bugs. But there is still another bug, and I have no good way to fix it. >>> >>>> Steps to reproduce this bug: >>>> 1. use gdb to attach libvirtd, and set a breakpoint in the function >>>> qemuConnectMonitor() >>>> 2. start a vm >>>> 3. let the libvirtd to run until qemuMonitorSetCapabilities() returns. >>>> 4. kill the qemu process >>>> 5. step into qemuDomainObjExitMonitorWithDriver(), and set debug to 1 >>>> >>>> Now, qemuDomainObjExitMonitorWithDriver() will sleep 100s to make sure >>>> qemuProcessHandleMonitorEOF() is done before qemuProcessHandleMonitorEOF() >>>> returns. >>>> >>>> priv->mon will be null after qemuDomainObjExitMonitorWithDriver() returns. >>>> So we must not use it. Unfortunately we still use it, and it will cause >>>> libvirtd crashed. >>> >>> Sounds like qemuConnectMonitor needs an extra reference around priv->mon >>> for the duration of the connect attempt, so that >>> qemuProcessHandleMonitorEOF will not free the monitor. >> >> No, qemuConnectMonitor() calls qemuDomainObjEnterMonitorWithDriver() to hold >> an extra reference around priv->mon, and release it in qemuDomainObjExitMonitorWithDriver(). >> But qemuDomainObjExitMonitorWithDriver() does not tell the caller whether >> priv->mon can be used. >> >> If we will call qemuDomainObjEnterMonitorWithDriver()/qemuDomainObjEnterMonitor(), >> I think we must check whether the domain is active. If we call them more than once, >> we must check it every time. And we should not do other things between checking whether >> the domain is active and calling them(If we do as this, the code can be maintained easily) > > I think I hit on the same problem earlier, of a guest modifying vm state > on assumption that a successful monitor command even if the vm went down > in the window after the monitor command completed but before lock was > regained: > > https://www.redhat.com/archives/libvir-list/2011-March/msg00636.html > >> >> But some codes does not respect this rule. >> >> Here is the list of the functions that may have the similar problem: >> 1. qemu_migration.c >> doNativeMigrate() >> qemuMigrationToFile() > > My current thoughts are that maybe qemuDomainObjExitMonitor should be > made to return the value of vm active after regaining lock, and marked > ATTRIBUTE_RETURN_CHECK, to force all other callers to detect the case of > a monitor command completing successfully but then the VM disappearing > in the window between command completion and regaining the vm lock. We can make qemuDomainObjExitMonitor() to return a value of vm active after regaining lock, and mark it ATTRIBUTE_RETURN_CHECK. The compiler can check the problem. But if we do something like this: { ... qemuDomainObjBeginJob(); qemuDomainObjEnterMonitor(); ... } Libvirtd still may crash as vm is inactive when qemuDomainObjBeginJob() returns and vm->priv->mon is NULL. function a() { ... qemuDomainObjEnterMonitor(); /* invoke monitor command */ qemuDomainObjExitMonitor(); ... } function b() { ... ignore_value(a()); ... qemuDomainObjEnterMonitor(); ... } If invoking monitor command failed is not a fatal problem, and we ignore the return value of function a(). libvirtd may crash if a() failed. The complier can not detect the above problems. If we always check whether vm is active before calling qemuDomainObjEnterMonitor(), we can avoid this problem. From usui at mxm.nes.nec.co.jp Mon Apr 4 01:05:29 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Mon, 4 Apr 2011 10:05:29 +0900 Subject: [libvirt] [PATCH 1/6] virNodeGetCpuTime: Expose new API In-Reply-To: <4D95FB08.20802@redhat.com> References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> <20110401105548.a78607f7.usui@mxm.nes.nec.co.jp> <4D95FB08.20802@redhat.com> Message-ID: <20110404100529.510af367.usui@mxm.nes.nec.co.jp> Hi, Eric On Fri, 01 Apr 2011 10:19:20 -0600 Eric Blake wrote: > On 03/31/2011 07:55 PM, Minoru Usui wrote: > > virNodeGetCpuTime: Expose new API > > > > include/libvirt/libvirt.h.in | 26 ++++++++++++++++++++++++++ > > src/libvirt_public.syms | 1 + > > 2 files changed, 27 insertions(+), 0 deletions(-) > > > > > +/** > > + * virNodeCpuTime: > > + * > > + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing > > + * the information for the cpu time of Node. > > + */ > > + > > +typedef struct _virNodeCpuTime virNodeCpuTime; > > + > > +struct _virNodeCpuTime { > > + unsigned long long user; > > + unsigned long long system; > > + unsigned long long idle; > > + unsigned long long iowait; > > +}; > > Can we portably get all of this information on Windows? If not, how do > you express which values we don't know how to obtain? > > > @@ -593,6 +616,9 @@ int virNodeGetInfo (virConnectPtr conn, > > virNodeInfoPtr info); > > char * virConnectGetCapabilities (virConnectPtr conn); > > > > +int virNodeGetCpuTime (virConnectPtr conn, > > + virNodeCpuTimePtr cpu_time); > > + > > Rather than locking ourselves into yet another inflexible API (no flags > parameter and a hard-coded struct means no way to extend this if we ever > come up with some new stat to query), should we instead be following the > lead of getMemoryParameters which takes a typed-name/value array to pass > an arbitrary number of parameters, which allows extension without a new API? OK. I'll change its user I/F like virDomainGetMemoryParameters(), if it doesn't return absolute CPU time values. > > +++ b/src/libvirt_public.syms > > @@ -434,6 +434,7 @@ LIBVIRT_0.9.0 { > > virEventRunDefaultImpl; > > virStorageVolDownload; > > virStorageVolUpload; > > + virNodeGetCpuTime; > > } LIBVIRT_0.8.8; > > While I think that something along the lines of this API is appropriate > for libvirt (indeed, knowing a host's CPU utilization can indeed be a > factor for upper-level management software in deciding whether to > migrate another domain on or off of the machine), it's too late to put > it into 0.9.0. We'd be setting bad precedent by accepting this after > the first release candidate did a feature freeze, so you'd need to > adjust this to 0.9.1. OK. I'll change it. > > -- > Eric Blake eblake at redhat.com +1-801-349-2682 > Libvirt virtualization library http://libvirt.org > -- Minoru Usui From usui at mxm.nes.nec.co.jp Mon Apr 4 02:03:10 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Mon, 4 Apr 2011 11:03:10 +0900 Subject: [libvirt] [PATCH 1/6] virNodeGetCpuTime: Expose new API In-Reply-To: References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> <20110401105548.a78607f7.usui@mxm.nes.nec.co.jp> <4D95FB08.20802@redhat.com> Message-ID: <20110404110310.e85d09ba.usui@mxm.nes.nec.co.jp> Hi, Matthias. On Fri, 1 Apr 2011 20:22:17 +0200 Matthias Bolte wrote: > 2011/4/1 Eric Blake : > > On 03/31/2011 07:55 PM, Minoru Usui wrote: > >> virNodeGetCpuTime: Expose new API > >> > >> ?include/libvirt/libvirt.h.in | ? 26 ++++++++++++++++++++++++++ > >> ?src/libvirt_public.syms ? ? ?| ? ?1 + > >> ?2 files changed, 27 insertions(+), 0 deletions(-) > > > >> > >> +/** > >> + * virNodeCpuTime: > >> + * > >> + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing > >> + * the information for the cpu time of Node. > >> + */ > >> + > >> +typedef struct _virNodeCpuTime virNodeCpuTime; > >> + > >> +struct _virNodeCpuTime { > >> + ? ?unsigned long long user; > >> + ? ?unsigned long long system; > >> + ? ?unsigned long long idle; > >> + ? ?unsigned long long iowait; > >> +}; > > > > Can we portably get all of this information on Windows? ?If not, how do > > you express which values we don't know how to obtain? > > > > In the context of ESX I vote against this absolute CPU time values. > ESX provides this values relative to a 20 second timeslots with 1 hour > of history. This makes it nearly impossible to obtain the absolute CPU > time. The same problem already exists for the domain's virtual CPU > time. > > When you look at virt-top's usage of the domain's virtual CPU time, > you see that it actually doesn't really care about the absolute value, > but deduces the CPU utilization from it. I suggest that we find a > different representation for this information that is not by > definition impossible to implement for ESX. > > Matthias I didn't know ESX couldn't return absolute CPU time value. Thank you for your comment. We really want to get CPU utilization information of the node, not absolute CPU time values. But linux doesn't provide CPU utilization directly, so my patch returns absolute CPU time values, and CPU utilization is calculated by client which uses new API. To return CPU utilization by new API, I think there are two issues of implementing on linux. a) How much interval does calculate CPU utilization? To calculate CPU utilization on linux, we need to get absolute CPU time value of the node from /proc/stat two times. How much interval properly? 1sec? 1min? or others? b) Can new API wait its interval? If we select simply implementation, new API waits its interval. But API user don't want to wait every API calls, if its interval is long. So I think libvirtd will be calculating CPU utilization in background every interval. Is this approach OK? -- Minoru Usui From veillard at redhat.com Mon Apr 4 03:02:37 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 4 Apr 2011 11:02:37 +0800 Subject: [libvirt] [PATCH] vmx: Use case-insensitive compare functions for all content In-Reply-To: <20110403121914.GA22826@sbox> References: <20110403121914.GA22826@sbox> Message-ID: <20110404030237.GP24385@redhat.com> On Sun, Apr 03, 2011 at 02:19:14PM +0200, Matthias Bolte wrote: > --- > src/vmx/vmx.c | 10 +++++----- > 1 files changed, 5 insertions(+), 5 deletions(-) > > diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c > index 9f4d5fb..9a482ef 100644 > --- a/src/vmx/vmx.c > +++ b/src/vmx/vmx.c > @@ -730,7 +730,7 @@ virVMXGetConfigLong(virConfPtr conf, const char *name, long long *number, > } > } > > - if (STREQ(value->str, "unlimited")) { > + if (STRCASEEQ(value->str, "unlimited")) { > *number = -1; > } else if (virStrToLong_ll(value->str, NULL, 10, number) < 0) { > VMX_ERROR(VIR_ERR_INTERNAL_ERROR, > @@ -1385,7 +1385,7 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx) > goto cleanup; > } > > - if (sched_cpu_affinity != NULL && STRNEQ(sched_cpu_affinity, "all")) { > + if (sched_cpu_affinity != NULL && STRCASENEQ(sched_cpu_affinity, "all")) { > const char *current = sched_cpu_affinity; > int number, count = 0; > > @@ -2107,7 +2107,7 @@ virVMXParseDisk(virVMXContext *ctx, virCapsPtr caps, virConfPtr conf, > goto cleanup; > } > } else if (virFileHasSuffix(fileName, ".iso") || > - STREQ(deviceType, "atapi-cdrom")) { > + STRCASEEQ(deviceType, "atapi-cdrom")) { > /* > * This function was called in order to parse a harddisk device, > * but .iso files and 'atapi-cdrom' devices are for CDROM devices > @@ -2146,7 +2146,7 @@ virVMXParseDisk(virVMXContext *ctx, virCapsPtr caps, virConfPtr conf, > * handle it. > */ > goto ignore; > - } else if (STREQ(deviceType, "atapi-cdrom")) { > + } else if (STRCASEEQ(deviceType, "atapi-cdrom")) { > (*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK; > (*def)->src = fileName; > > @@ -2174,7 +2174,7 @@ virVMXParseDisk(virVMXContext *ctx, virCapsPtr caps, virConfPtr conf, > if ((*def)->src == NULL) { > goto cleanup; > } > - } else if (fileType != NULL && STREQ(fileType, "device")) { > + } else if (fileType != NULL && STRCASEEQ(fileType, "device")) { > (*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK; > (*def)->src = fileName; Sounds fine to me but would you categorize this as bug fix (for 0.9.0) or rather an improvement and wait. I guess it depends how you ended up crossing this, and I can't guess it :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Mon Apr 4 03:05:41 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 4 Apr 2011 11:05:41 +0800 Subject: [libvirt] [PATCH] vmx: Support persistent CPU shares In-Reply-To: <20110403124355.GA22943@sbox> References: <20110403124355.GA22943@sbox> Message-ID: <20110404030541.GQ24385@redhat.com> On Sun, Apr 03, 2011 at 02:43:55PM +0200, Matthias Bolte wrote: > --- > src/vmx/vmx.c | 43 ++++++++++++++++++++++ > tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx | 2 +- > tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml | 3 ++ > tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml | 3 ++ > tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx | 2 +- > tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml | 3 ++ > tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml | 3 ++ > tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml | 3 ++ > tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx | 1 + > tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml | 3 ++ > tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx | 1 + > tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml | 3 ++ > tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx | 1 + > tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml | 3 ++ > 14 files changed, 72 insertions(+), 2 deletions(-) > > diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c > index 9a482ef..b0d3218 100644 > --- a/src/vmx/vmx.c > +++ b/src/vmx/vmx.c > @@ -55,6 +55,8 @@ def->mem.cur_balloon = <=> sched.mem.max = " def->mem.min_guarantee = <=> sched.mem.minsize = "" # defaults to 0 > def->maxvcpus = <=> numvcpus = "" # must be 1 or a multiple of 2, defaults to 1 > def->cpumask = <=> sched.cpu.affinity = "" > +def->cputune.shares = <=> sched.cpu.shares = "" # with handling for special values > + # "high", "normal", "low" > > > > @@ -1200,6 +1202,7 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx) > long long sched_mem_minsize = 0; > long long numvcpus = 0; > char *sched_cpu_affinity = NULL; > + char *sched_cpu_shares = NULL; > char *guestOS = NULL; > bool smbios_reflecthost = false; > int controller; > @@ -1449,6 +1452,30 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx) > } > } > > + /* vmx:sched.cpu.shares -> def:cputune.shares */ > + if (virVMXGetConfigString(conf, "sched.cpu.shares", &sched_cpu_shares, > + true) < 0) { > + goto cleanup; > + } > + > + if (sched_cpu_shares != NULL) { > + /* See http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.SharesInfo.Level.html */ > + if (STRCASEEQ(sched_cpu_shares, "low")) { > + def->cputune.shares = def->vcpus * 500; > + } else if (STRCASEEQ(sched_cpu_shares, "normal")) { > + def->cputune.shares = def->vcpus * 1000; > + } else if (STRCASEEQ(sched_cpu_shares, "high")) { > + def->cputune.shares = def->vcpus * 2000; > + } else if (virStrToLong_ul(sched_cpu_shares, NULL, 10, > + &def->cputune.shares) < 0) { > + VMX_ERROR(VIR_ERR_INTERNAL_ERROR, > + _("Expecting VMX entry 'sched.cpu.shares' to be an " > + "unsigned integer or 'low', 'normal' or 'high' but " > + "found '%s'"), sched_cpu_shares); > + goto cleanup; > + } > + } > + > /* def:lifecycle */ > def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART; > def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY; > @@ -1715,6 +1742,7 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx) > virConfFree(conf); > VIR_FREE(encoding); > VIR_FREE(sched_cpu_affinity); > + VIR_FREE(sched_cpu_shares); > VIR_FREE(guestOS); > > return def; > @@ -2998,6 +3026,21 @@ virVMXFormatConfig(virVMXContext *ctx, virCapsPtr caps, virDomainDefPtr def, > virBufferAddLit(&buffer, "\"\n"); > } > > + /* def:cputune.shares -> vmx:sched.cpu.shares */ > + if (def->cputune.shares > 0) { > + /* See http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.SharesInfo.Level.html */ > + if (def->cputune.shares == def->vcpus * 500) { > + virBufferAddLit(&buffer, "sched.cpu.shares = \"low\"\n"); > + } else if (def->cputune.shares == def->vcpus * 1000) { > + virBufferAddLit(&buffer, "sched.cpu.shares = \"normal\"\n"); > + } else if (def->cputune.shares == def->vcpus * 2000) { > + virBufferAddLit(&buffer, "sched.cpu.shares = \"high\"\n"); > + } else { > + virBufferVSprintf(&buffer, "sched.cpu.shares = \"%lu\"\n", > + def->cputune.shares); > + } > + } > + > /* def:graphics */ > for (i = 0; i < def->ngraphics; ++i) { > switch (def->graphics[i]->type) { > diff --git a/tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx b/tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx > index bd36cf8..8641c5c 100644 > --- a/tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx > +++ b/tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx > @@ -35,7 +35,7 @@ UUID.BIOS = "50 11 5E 16 9B DC 49 D7-F1 71 53 C4 D7 F9 17 10" > SNAPSHOT.ACTION = "KEEP" > SCHED.CPU.MIN = "0" > SCHED.CPU.UNITS = "MHZ" > -SCHED.CPU.SHARES = "NORMAL" > +SCHED.CPU.SHARES = "4223" > SCHED.MEM.MINSIZE = "0" > SCHED.MEM.SHARES = "NORMAL" > TOOLSCRIPTS.AFTERPOWERON = "TRUE" > diff --git a/tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml b/tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml > index 7a5ff5b..ef6edd8 100644 > --- a/tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml > +++ b/tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml > @@ -4,6 +4,9 @@ > 1048576 > 1048576 > 1 > + > + 4223 > + > > hvm > > diff --git a/tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml b/tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml > index 18d6461..02771b9 100644 > --- a/tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml > +++ b/tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml > @@ -4,6 +4,9 @@ > 1048576 > 1048576 > 1 > + > + 1000 > + > > hvm > > diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx > index 4392062..78741ae 100644 > --- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx > +++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx > @@ -36,7 +36,7 @@ uuid.bios = "50 11 5e 16 9b dc 49 d7-f1 71 53 c4 d7 f9 17 10" > snapshot.action = "keep" > sched.cpu.min = "0" > sched.cpu.units = "mhz" > -sched.cpu.shares = "normal" > +sched.cpu.shares = "low" > sched.mem.minsize = "0" > sched.mem.shares = "normal" > toolScripts.afterPowerOn = "true" > diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml > index 5e67e74..e8f9307 100644 > --- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml > +++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml > @@ -4,6 +4,9 @@ > 1048576 > 1048576 > 1 > + > + 500 > + > > hvm > > diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml > index 419df51..2824d66 100644 > --- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml > +++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml > @@ -4,6 +4,9 @@ > 524288 > 524288 > 1 > + > + 1000 > + > > hvm > > diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml > index 0040163..6f0a9d1 100644 > --- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml > +++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml > @@ -8,6 +8,9 @@ > 262144 > > 2 > + > + 2000 > + > > hvm > > diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx > index e72ca80..9059197 100644 > --- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx > +++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx > @@ -6,6 +6,7 @@ uuid.bios = "50 11 5e 16 9b dc 49 d7-f1 71 53 c4 d7 f9 17 10" > displayName = "Fedora11" > memsize = "1024" > numvcpus = "1" > +sched.cpu.shares = "low" > scsi0.present = "true" > scsi0.virtualDev = "lsilogic" > scsi0:0.present = "true" > diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml > index 3f4ff88..ea59778 100644 > --- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml > +++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml > @@ -4,6 +4,9 @@ > 1048576 > 1048576 > 1 > + > + 500 > + > > hvm > > diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx > index 627fcfb..504997f 100644 > --- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx > +++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx > @@ -6,6 +6,7 @@ uuid.bios = "56 4d 9b ef ac d9 b4 e0-c8 f0 ae a8 b9 10 35 15" > displayName = "virtMonServ1" > memsize = "512" > numvcpus = "1" > +sched.cpu.shares = "normal" > scsi0.present = "true" > scsi0.virtualDev = "lsilogic" > scsi0:0.present = "true" > diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml > index 078753a..443aacd 100644 > --- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml > +++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml > @@ -4,6 +4,9 @@ > 524288 > 524288 > 1 > + > + 1000 > + > > hvm > > diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx > index cc2485f..2e3b856 100644 > --- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx > +++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx > @@ -8,6 +8,7 @@ annotation = "Centos 5.5 64bit Server" > memsize = "2048" > sched.mem.minsize = "256" > numvcpus = "2" > +sched.cpu.shares = "normal" > scsi0.present = "true" > scsi0.virtualDev = "lsilogic" > scsi0:0.present = "true" > diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml > index d55bf6b..f28c15e 100644 > --- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml > +++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml > @@ -8,6 +8,9 @@ > 262144 > > 2 > + > + 2000 > + > > hvm > ACK, while nice, it may be a bit late for 0.9.0, okay to wait for the next cycle ? We already have this for xen and qemu, seeing it for ESX confirms the design is fine, which is the most important from my point of vue :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Mon Apr 4 03:11:23 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 4 Apr 2011 11:11:23 +0800 Subject: [libvirt] [RFC PATCH] build: detect doc build errors In-Reply-To: <1301695610-4003-1-git-send-email-eblake@redhat.com> References: <1301695610-4003-1-git-send-email-eblake@redhat.com> Message-ID: <20110404031123.GR24385@redhat.com> On Fri, Apr 01, 2011 at 04:06:50PM -0600, Eric Blake wrote: > I'm still stumped by xsltproc complaining about   not being a > valid XML entity, hence the (hackish) exemption in docs/Makefile.am > that adds --html for a couple of .html.in files. But for the > remaining files, this does make input validation stricter, and caught > several bugs. The only solution would be to add a DTD to the html.in which use any entity beyond the 5 ones hardcoded in the parser (lt, gt, amp, quot and apos. > Hence, this is an RFC (either we live with my hack that caught > all the issues in the prior patch, or someone with more xsltproc > knowledge than me will step in and teach it how to resolve html > entities while processing the documents as xml instead of html). We would need to add to all the .html.in for consistency, since we now expect them to be well formed XML and possibly using html entities. > * docs/Makefile.am (maintainer-clean-local): Remove generated docs > in VPATH build. > (%.html.tmp): Don't use looser --html; our input should be strict > xhtml. HACK - use --html when entities like   are involved. > (html/index.html): Exit on formatting problems. > (rebuild): Run full doc build on request. > --- > docs/Makefile.am | 24 ++++++++++++++---------- > 1 files changed, 14 insertions(+), 10 deletions(-) > > diff --git a/docs/Makefile.am b/docs/Makefile.am > index db4bc59..2d1afe4 100644 > --- a/docs/Makefile.am > +++ b/docs/Makefile.am > @@ -123,7 +123,7 @@ internals/%.html.tmp: internals/%.html.in subsite.xsl page.xsl sitemap.html.in > echo "Generating $@"; \ > $(MKDIR_P) "$(builddir)/internals"; \ > name=`echo $@ | sed -e 's/.tmp//'`; \ > - $(XSLTPROC) --stringparam pagename $$name --nonet --html \ > + $(XSLTPROC) --stringparam pagename $$name --nonet \ > $(top_srcdir)/docs/subsite.xsl $< > $@ \ > || { rm $@ && exit 1; }; fi > > @@ -131,7 +131,8 @@ internals/%.html.tmp: internals/%.html.in subsite.xsl page.xsl sitemap.html.in > @if [ -x $(XSLTPROC) ] ; then \ > echo "Generating $@"; \ > name=`echo $@ | sed -e 's/.tmp//'`; \ > - $(XSLTPROC) --stringparam pagename $$name --nonet --html \ > + $(XSLTPROC) --stringparam pagename $$name --nonet \ > + $$(grep -qE '&(nbsp|uuml|mdash);' $< && printf %s --html) \ > $(top_srcdir)/docs/site.xsl $< > $@ \ > || { rm $@ && exit 1; }; fi > > @@ -147,21 +148,22 @@ internals/%.html.tmp: internals/%.html.in subsite.xsl page.xsl sitemap.html.in > > > html/index.html: libvirt-api.xml newapi.xsl page.xsl sitemap.html.in > - - at if [ -x $(XSLTPROC) ] ; then \ > + @if [ -x $(XSLTPROC) ] ; then \ > echo "Rebuilding the HTML pages from the XML API" ; \ > $(XSLTPROC) --nonet -o $(srcdir)/ \ > $(srcdir)/newapi.xsl $(srcdir)/libvirt-api.xml ; fi > - - at if test -x $(XMLLINT) && test -x $(XMLCATALOG) ; then \ > - if $(XMLCATALOG) '$(XML_CATALOG_FILE)' "-//W3C//DTD XHTML 1.0 Strict//EN" \ > - > /dev/null ; then \ > + @if test -x $(XMLLINT) && test -x $(XMLCATALOG) ; then \ > + if $(XMLCATALOG) '$(XML_CATALOG_FILE)' \ > + "-//W3C//DTD XHTML 1.0 Strict//EN" > /dev/null ; then \ > echo "Validating the resulting XHTML pages" ; \ > SGML_CATALOG_FILES='$(XML_CATALOG_FILE)' \ > - $(XMLLINT) --catalogs --nonet --valid --noout $(srcdir)/html/*.html ; \ > + $(XMLLINT) --catalogs --nonet --valid --noout $(srcdir)/html/*.html \ > + || { rm $(srcdir)/$@ && exit 1; }; \ > else echo "missing XHTML1 DTD" ; fi ; fi > > $(addprefix $(srcdir)/,$(devhelphtml)): $(srcdir)/libvirt-api.xml $(devhelpxsl) > - at echo Rebuilding devhelp files > - - at if [ -x $(XSLTPROC) ] ; then \ > + @if [ -x $(XSLTPROC) ] ; then \ > $(XSLTPROC) --nonet -o $(srcdir)/devhelp/ \ > $(top_srcdir)/docs/devhelp/devhelp.xsl $(srcdir)/libvirt-api.xml ; fi > > @@ -183,9 +185,11 @@ clean-local: > rm -f *~ *.bak *.hierarchy *.signals *-unused.txt *.html > > maintainer-clean-local: clean-local > - rm -rf $(srcdir)/libvirt-api.xml $(srcdir)/libvirt-refs.xml todo.html.in > + rm -rf $(srcdir)/libvirt-api.xml $(srcdir)/libvirt-refs.xml \ > + todo.html.in $(srcdir)/*.html $(srcdir)/devhelp/*.html \ > + $(srcdir)/html/*.html $(srcdir)/internals/*.html > > -rebuild: api all > +rebuild: maintainer-clean-local api all > > install-data-local: > $(mkinstalldirs) $(DESTDIR)$(HTML_DIR) > -- > 1.7.4 I think I will check this in a few hours while preparing the release, depending on the size of the resulting diff, I may put this in, as is, add the DTD and go full XML or keep as-is ... Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From hahn at univention.de Mon Apr 4 06:08:27 2011 From: hahn at univention.de (Philipp Hahn) Date: Mon, 4 Apr 2011 08:08:27 +0200 Subject: [libvirt] [BUG] qemu: snapshots no longer shown after migration^2 Message-ID: <201104040808.32278.hahn@univention.de> Hello, when a domain is migrated to another host and than back again, snapshots of this domain are no longer shown. I think that is because qemuDomainSnapshotLoad() is only called once from qemudStartup() during startup, but not after migration (or re-definition of a previously deleted domain, e.g. offline-migration) No patch yet, but this is tracked at our German bugzilla at Sincerely Philipp Hahn -- Philipp Hahn Open Source Software Engineer hahn at univention.de Univention GmbH Linux for Your Business fon: +49 421 22 232- 0 Mary-Somerville-Str.1 D-28359 Bremen fax: +49 421 22 232-99 http://www.univention.de/ -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 197 bytes Desc: This is a digitally signed message part. URL: From matthias.bolte at googlemail.com Mon Apr 4 06:28:24 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 4 Apr 2011 08:28:24 +0200 Subject: [libvirt] [PATCH] vmx: Support persistent CPU shares In-Reply-To: <20110404030541.GQ24385@redhat.com> References: <20110403124355.GA22943@sbox> <20110404030541.GQ24385@redhat.com> Message-ID: 2011/4/4 Daniel Veillard : > On Sun, Apr 03, 2011 at 02:43:55PM +0200, Matthias Bolte wrote: >> --- >> ?src/vmx/vmx.c ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| ? 43 ++++++++++++++++++++++ >> ?tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx | ? ?2 +- >> ?tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml | ? ?3 ++ >> ?tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml | ? ?3 ++ >> ?tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx ?| ? ?2 +- >> ?tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml ?| ? ?3 ++ >> ?tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml ?| ? ?3 ++ >> ?tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml ?| ? ?3 ++ >> ?tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx ?| ? ?1 + >> ?tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml ?| ? ?3 ++ >> ?tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx ?| ? ?1 + >> ?tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml ?| ? ?3 ++ >> ?tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx ?| ? ?1 + >> ?tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml ?| ? ?3 ++ >> ?14 files changed, 72 insertions(+), 2 deletions(-) >> > > ?ACK, while nice, it may be a bit late for 0.9.0, okay to wait for the > next cycle ? We already have this for xen and qemu, seeing it for ESX > confirms the design is fine, which is the most important from my point > of vue :-) > > Daniel > Sure, this can wait until 0.9.1. On the ESX side the shares value is persistent anyway. This patch just exposes it as persistent in libvirt too. Matthias From izumi.taku at jp.fujitsu.com Mon Apr 4 07:24:34 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Mon, 04 Apr 2011 16:24:34 +0900 Subject: [libvirt] [PATCH v2 0/4] configure inactive domains' maximum memory size In-Reply-To: <4D95FDEE.8060609@redhat.com> References: <4D940EEE.2090603@jp.fujitsu.com> <4D95FDEE.8060609@redhat.com> Message-ID: <4D997232.2070009@jp.fujitsu.com> Hi Eric, (2011/04/02 1:31), Eric Blake wrote: > On 03/30/2011 11:19 PM, Taku Izumi wrote: >> Hi all, >> >> This patchset enables us to configure inactive domain's maximum memory >> size. I redesigned according to Daniel-san's commnet. > >> The following patchset is the prerequisite of these. >> => http://www.redhat.com/archives/libvir-list/2011-March/msg01057.html > > My sincere apologies at the delay on these series. I've been so focused > on locking bugs and libvirtd crashers that I haven't had a chance to > properly review any of the persistent settings patches in time for > inclusion in 0.9.0. My justification is that you can always achieve > persistent settings (albeit with undue pain) by raw XML editing, so this > is just an enhancement request rather than a bug fix. However, now that > we've missed the feature freeze deadline for 0.9.0, you have my promise > that I will be reviewing this next week for inclusion in 0.9.1. > That's OK, I don't mind. Please review this after releasing 0.9.0. Best regards, Taku Izumi From izumi.taku at jp.fujitsu.com Mon Apr 4 07:26:08 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Mon, 04 Apr 2011 16:26:08 +0900 Subject: [libvirt] [PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) In-Reply-To: <4D9601B4.60206@redhat.com> References: <4D94124A.1090808@jp.fujitsu.com> <4D94133A.30806@jp.fujitsu.com> <4D9601B4.60206@redhat.com> Message-ID: <4D997290.8070708@jp.fujitsu.com> (2011/04/02 1:47), Eric Blake wrote: > On 03/30/2011 11:38 PM, Taku Izumi wrote: >> >> This patch introduces a new libvirt API (virDomainPinVcpuFlags) >> >> Signed-off-by: Taku Izumi > >> /** >> + * virDomainPinVcpuFlags: >> + * @domain: pointer to domain object, or NULL for Domain0 >> + * @vcpu: virtual CPU number >> + * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN) >> + * Each bit set to 1 means that correspoinding CPU is usable. > > s/correspoinding/corresponding/ > >> + * Bytes are stored in little-endian order: CPU0-7, 8-15... >> + * In each byte, lowest CPU number is least significant bit. >> + * @maplen: number of bytes in cpumap, from 1 up to size of CPU map in >> + * underlying virtualization system (Xen...). >> + * If maplen< size, missing bytes are set to zero. >> + * If maplen< size, failure code is returned. > > s// > >> + * @flags: an OR'ed set of virDomainVcpuFlags > > Is VIR_DOMAIN_VCPU_MAXIMUM really applicable here? The docs should > probably mention that it is a subset of virDomainVcpuFlags. > >> + * >> + * Dynamically change the real CPUs which can be allocated to a virtual CPU. >> + * This function requires privileged access to the hypervisor. >> + * >> + * @flags must include VIR_DOMAIN_VCPU_LIVE to affect a running domain >> + * (which may fail if domain is not active), or VIR_DOMAIN_MEM_CONFIG to > > s/VIR_DOMAIN_MEM_CONFIG/VIR_DOMAIN_VCPU_CONFIG/ > >> + * affect the next boot via the XML description of the domain. >> + * Both flags may be set. >> + * >> + * Returns 0 in case of success, -1 in case of failure. >> + * >> + */ >> +int >> +virDomainPinVcpuFlags(virDomainPtr domain, unsigned int vcpu, >> + unsigned char *cpumap, int maplen, unsigned int flags) >> +{ >> Index: libvirt/src/libvirt_public.syms >> =================================================================== >> --- libvirt.orig/src/libvirt_public.syms >> +++ libvirt/src/libvirt_public.syms >> @@ -434,6 +434,7 @@ LIBVIRT_0.9.0 { >> virEventRunDefaultImpl; >> virStorageVolDownload; >> virStorageVolUpload; >> + virDomainPinVcpuFlags; >> } LIBVIRT_0.8.8; > > We've missed the 0.9.0 feature freeze, can you adjust this patch series > to be for 0.9.1? > Thank you for reviewing. I'll rebase this patch set after releasing libvirt 0.9.0. Best regards, Taku Izumi From minovotn at redhat.com Mon Apr 4 08:32:16 2011 From: minovotn at redhat.com (Michal Novotny) Date: Mon, 04 Apr 2011 10:32:16 +0200 Subject: [libvirt] [libvirt-php] Fixed set_error when argument is NULL In-Reply-To: <1301714430-9304-1-git-send-email-liyong@skybility.com> References: <1301714430-9304-1-git-send-email-liyong@skybility.com> Message-ID: <4D998210.6070900@redhat.com> On 04/02/2011 05:20 AM, Lyre wrote: > Avoid freeing a NULL pointer > --- > src/libvirt-php.c | 8 ++++++-- > 1 files changed, 6 insertions(+), 2 deletions(-) > > diff --git a/src/libvirt-php.c b/src/libvirt-php.c > index 6a76f45..66b1de9 100644 > --- a/src/libvirt-php.c > +++ b/src/libvirt-php.c > @@ -237,12 +237,16 @@ PHP_MINFO_FUNCTION(libvirt) > */ > void set_error(char *msg TSRMLS_DC) > { > - if (msg == NULL) { > + if (LIBVIRT_G (last_error) != NULL) > + { > efree(LIBVIRT_G (last_error)); > + } > + > + if (msg == NULL) { > + LIBVIRT_G (last_error) = NULL; > return; > } > php_error_docref(NULL TSRMLS_CC, E_WARNING,"%s",msg); > - if (LIBVIRT_G (last_error)!=NULL) efree(LIBVIRT_G (last_error)); > LIBVIRT_G (last_error)=estrndup(msg,strlen(msg)); > } > Good pick. Thanks! Pushed now. Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From mcastrol at gmail.com Mon Apr 4 09:58:25 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Mon, 4 Apr 2011 11:58:25 +0200 Subject: [libvirt] LIBVIRT migration In-Reply-To: References: <20110401142611.GK29510@redhat.com> Message-ID: Hello I'm having problem using migration. I'm working on ubuntu 10.4 and this versions of libvirt and virsh: virsh # version Compiled against library: libvir 0.7.5 Using library: libvir 0.7.5 Using API: QEMU 0.7.5 Running hypervisor: QEMU 0.12.3 This is the error. *virsh # migrate scompi1 qemu+ssh://rionegro/system error: Unknown failure * This is the log on the destination, that show that there is no communication problem, but it has a problem starting the guest on destination. radic at rionegro:~$ sudo cat /var/log/libvirt/qemu/scompi1.log [sudo] password for radic: LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 -S -M pc-0.12 -enable-kvm -m 4096 -smp 4 -name scompi1 -uuid 355123af-b683-9fa6-ca31-10506c9ab9da -chardev socket,id=monitor,path=/var/lib/libvirt/qemu/scompi1.monitor,server,nowait -monitor chardev:monitor -boot c -drive file=/home/radic/mvdata/imagenes/scompi1.img,if=ide,index=0,boot=on,format=raw -drive if=ide,media=cdrom,index=2,format=raw -net nic,macaddr=52:54:00:05:d1:2a,vlan=0,model=virtio,name=virtio.0 -net tap,fd=33,vlan=0,name=tap.0 -chardev pty,id=serial0 -serial chardev:serial0 -parallel none -usb -vnc 127.0.0.1:0 -vga cirrus -incoming tcp:0.0.0.0:49153 char device redirected to /dev/pts/1 LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 -S -M pc-0.12 -enable-kvm -m 4096 -smp 4 -name scompi1 -uuid 355123af-b683-9fa6-ca31-10506c9ab9da -chardev socket,id=monitor,path=/var/lib/libvirt/qemu/scompi1.monitor,server,nowait -monitor chardev:monitor -boot c -drive file=/home/radic/mvdata/imagenes/scompi1.img,if=ide,index=0,boot=on,format=raw -drive if=ide,media=cdrom,index=2,format=raw -net nic,macaddr=52:54:00:05:d1:2a,vlan=0,model=virtio,name=virtio.0 -net tap,fd=33,vlan=0,name=tap.0 -chardev pty,id=serial0 -serial chardev:serial0 -parallel none -usb -vnc 127.0.0.1:0 -vga cirrus -incoming tcp:0.0.0.0:49154 char device redirected to /dev/pts/2 LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 -S -M pc-0.12 -enable-kvm -m 4096 -smp 4 -name scompi1 -uuid 355123af-b683-9fa6-ca31-10506c9ab9da -chardev socket,id=monitor,path=/var/lib/libvirt/qemu/scompi1.monitor,server,nowait -monitor chardev:monitor -boot c -drive file=/home/radic/mvdata/imagenes/scompi1.img,if=ide,index=0,boot=on,format=raw -drive if=ide,media=cdrom,index=2,format=raw -net nic,macaddr=52:54:00:05:d1:2a,vlan=0,model=virtio,name=virtio.0 -net tap,fd=33,vlan=0,name=tap.0 -chardev pty,id=serial0 -serial chardev:serial0 -parallel none -usb -vnc 127.0.0.1:0 -vga cirrus -incoming tcp:0.0.0.0:49155 char device redirected to /dev/pts/2 I'm attaching the xml of the scompi1 that i'm trying to migrate. I'd apprciate a lot any help. Marcela -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: scompi1.xml Type: text/xml Size: 1292 bytes Desc: not available URL: From berrange at redhat.com Mon Apr 4 10:20:13 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:20:13 +0100 Subject: [libvirt] Using Restore in another host. In-Reply-To: References: Message-ID: <20110404102013.GB13616@redhat.com> On Sun, Apr 03, 2011 at 10:43:45AM +0200, Marcela Castro Le?n wrote: > Hello: > I need to know if I can use the restore operation (virsh o the equivalent in > libvirt) to recover a previous state of a guest, but recovered previously in > another host. > I did a test, but I got an error: > > The exactly sequence using virsh I testes is: > On [HOST SOURCE]: Using virsh > 1) save [domain] [file] > 2) restore file > 3) destroy [domain] > > On [HOST SOURCE] using ubuntu sh > 4) cp [guest.img] [guest.xml] [file] to HOST2 > > On [HOST TARGET] using virsh > 5) define [guest.xml] (using image on destination in HOST2) > 6) restore [file] As a general rule you should only ever 'restore' from a file *once*. This is because after the first restore operation, the guest may have made writes to its disk. Restoring a second time the guest OS will likely have an inconsistent view of the disk & will cause filesystem corruption. If you want to be able to restore from a saved image multiple times, you need to also take a snapshot of the disk image at the same time, and restore that snapshot when restoring the memory image. That aside, saving on one host & restoring on a different host is fine. So if you leave out steps 2+3 in your example above, then your data would still be safe. > The restore troughs the following message: > *virsh # restore sv-chubut-2011-04-01-09:58 > error: Failed to restore domain from sv-chubut-2011-04-01-09:58 > error: monitor socket did not show up.: Connection refused* There is probably some configuration difference on your 2nd host that prevented the VM from starting up. If you're lucky the file /var/log/libvirt/qemu/$NAME.log will tell you more Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:22:13 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:22:13 +0100 Subject: [libvirt] [PATCH 01/20] Remove PATH_MAX sized stack allocations related to virFileBuildPath In-Reply-To: <1301822493-23013-2-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-2-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404102213.GC13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:14AM +0200, Matthias Bolte wrote: > Make virFileBuildPath operate on the heap instead of the stack. It > allocates a buffer instead of expecting a preexisting buffer. > --- > src/conf/nwfilter_conf.c | 21 +++++++-------------- > src/conf/storage_conf.c | 44 +++++++++++++++----------------------------- > src/util/util.c | 29 +++++++++++++++-------------- > src/util/util.h | 8 +++----- > src/xen/xen_inotify.c | 16 +++++++++------- > src/xen/xm_internal.c | 33 +++++++++++++++++---------------- > 6 files changed, 66 insertions(+), 85 deletions(-) > - if (!(pool->autostartLink = strdup(path))) { > + if (!(pool->autostartLink = virFileBuildPath(driver->autostartDir, > + def->name, ".xml"))) { > virReportOOMError(); > VIR_FREE(pool->configFile); > return -1; > diff --git a/src/util/util.c b/src/util/util.c > index 43794b1..31feecc 100644 > --- a/src/util/util.c > +++ b/src/util/util.c > @@ -1841,23 +1841,24 @@ cleanup: > return err; > } > > -/* Build up a fully qualfiied path for a config file to be > +/* Build up a fully qualified path for a config file to be > * associated with a persistent guest or network */ > -int virFileBuildPath(const char *dir, > - const char *name, > - const char *ext, > - char *buf, > - unsigned int buflen) > +char * > +virFileBuildPath(const char *dir, const char *name, const char *ext) > { > - if ((strlen(dir) + 1 + strlen(name) + (ext ? strlen(ext) : 0) + 1) >= (buflen-1)) > - return -1; > + char *path; > > - strcpy(buf, dir); > - strcat(buf, "/"); > - strcat(buf, name); > - if (ext) > - strcat(buf, ext); > - return 0; > + if (ext == NULL) { > + if (virAsprintf(&path, "%s/%s", dir, name) < 0) { > + return NULL; > + } > + } else { > + if (virAsprintf(&path, "%s/%s%s", dir, name, ext) < 0) { > + return NULL; > + } > + } > + > + return path; > } ACK to the patch, but we might like to make virFileBuildPath invoke virReportOOMError() itself as a followup, so callers don't have to worry about it Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:23:21 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:23:21 +0100 Subject: [libvirt] [PATCH 02/20] pci: Remove PATH_MAX sized stack allocations In-Reply-To: <1301822493-23013-3-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-3-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404102321.GD13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:15AM +0200, Matthias Bolte wrote: > Use virAsprintf instead of snprintf. > --- > src/util/pci.c | 172 +++++++++++++++++++++++++++++++++++++++++--------------- > 1 files changed, 127 insertions(+), 45 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:24:02 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:24:02 +0100 Subject: [libvirt] [PATCH 03/20] ebtables: Remove PATH_MAX sized stack allocation In-Reply-To: <1301822493-23013-4-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-4-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404102402.GE13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:16AM +0200, Matthias Bolte wrote: > --- > src/util/ebtables.c | 44 +++++++++++++++++++++++++++++--------------- > 1 files changed, 29 insertions(+), 15 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:24:56 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:24:56 +0100 Subject: [libvirt] [PATCH 04/20] virt-aa-helper: Remove PATH_MAX sized stack allocations In-Reply-To: <1301822493-23013-5-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-5-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404102456.GF13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:17AM +0200, Matthias Bolte wrote: > --- > src/security/virt-aa-helper.c | 46 +++++++++++++++++++++++++---------------- > 1 files changed, 28 insertions(+), 18 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:25:27 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:25:27 +0100 Subject: [libvirt] [PATCH 05/20] phyp: Remove 16kb stack allocation In-Reply-To: <1301822493-23013-6-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-6-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404102527.GG13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:18AM +0200, Matthias Bolte wrote: > Allocate on the heap instead. > --- > src/phyp/phyp_driver.c | 13 +++++++++++-- > 1 files changed, 11 insertions(+), 2 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:26:15 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:26:15 +0100 Subject: [libvirt] [PATCH 06/20] qemu: Use heap allocated memory to read the monitor greeting In-Reply-To: <1301822493-23013-7-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-7-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404102615.GH13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:19AM +0200, Matthias Bolte wrote: > Removing a 4kb stack allocation. > > Reduce stack buffer for virStrerror to the common 1kb instead of 4kb. > --- > src/qemu/qemu_process.c | 16 ++++++++++++---- > 1 files changed, 12 insertions(+), 4 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:27:17 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:27:17 +0100 Subject: [libvirt] [PATCH 07/20] sasl: Remove stack allocated 8kb temporary buffers In-Reply-To: <1301822493-23013-8-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-8-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404102717.GI13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:20AM +0200, Matthias Bolte wrote: > Move the buffers to the heap allocated client/private data structs. > --- > daemon/libvirtd.c | 10 ++++++---- > daemon/libvirtd.h | 1 + > src/remote/remote_driver.c | 8 +++++--- > 3 files changed, 12 insertions(+), 7 deletions(-) ACK, I wouldn't have done it this way, but it doesn't matter because this code will die very soon. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:27:56 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:27:56 +0100 Subject: [libvirt] [PATCH 08/20] xenxs: Remove PATH_MAX sized stack alocation in XM script parsing In-Reply-To: <1301822493-23013-9-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-9-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404102755.GJ13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:21AM +0200, Matthias Bolte wrote: > --- > src/xenxs/xen_xm.c | 14 ++++++-------- > 1 files changed, 6 insertions(+), 8 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:30:14 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:30:14 +0100 Subject: [libvirt] [PATCH 09/20] Use virFileAbsPath instead of manually creating the absolute path In-Reply-To: <1301822493-23013-10-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-10-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404103014.GK13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:22AM +0200, Matthias Bolte wrote: > Removes multiple 4kb stack allocations. > --- > src/libvirt.c | 113 +++++++++++++++++++++------------------------------------ > 1 files changed, 42 insertions(+), 71 deletions(-) > > diff --git a/src/libvirt.c b/src/libvirt.c > index 8be18d4..25f8d41 100644 > --- a/src/libvirt.c > +++ b/src/libvirt.c > @@ -2238,7 +2238,6 @@ error: > int > virDomainSave(virDomainPtr domain, const char *to) > { > - char filepath[4096]; > virConnectPtr conn; > > VIR_DOMAIN_DEBUG(domain, "to=%s", to); > @@ -2260,29 +2259,24 @@ virDomainSave(virDomainPtr domain, const char *to) > goto error; > } > > - /* > - * We must absolutize the file path as the save is done out of process > - * TODO: check for URI when libxml2 is linked in. > - */ > - if (to[0] != '/') { > - unsigned int len, t; > + if (conn->driver->domainSave) { > + int ret; > + char *absolute_to; > > - t = strlen(to); > - if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) > - return -1; > - len = strlen(filepath); > - /* that should be covered by getcwd() semantic, but be 100% sure */ > - if (len > sizeof(filepath) - (t + 3)) > - return -1; > - filepath[len] = '/'; > - strcpy(&filepath[len + 1], to); > - to = &filepath[0]; > + /* > + * We must absolutize the file path as the save is done out of process > + * TODO: check for URI when libxml2 is linked in. > + */ > + if (virFileAbsPath(to, &absolute_to) < 0) { > + virLibConnError(VIR_ERR_INTERNAL_ERROR, > + _("could not build absolute output file path")); > + goto error; > + } > > - } > + ret = conn->driver->domainSave(domain, absolute_to); > + > + VIR_FREE(absolute_to); > > - if (conn->driver->domainSave) { > - int ret; > - ret = conn->driver->domainSave (domain, to); > if (ret < 0) > goto error; > return ret; > @@ -2298,7 +2292,7 @@ error: > /** > * virDomainRestore: > * @conn: pointer to the hypervisor connection > - * @from: path to the > + * @from: path to the input file > * > * This method will restore a domain saved to disk by virDomainSave(). > * > @@ -2307,7 +2301,6 @@ error: > int > virDomainRestore(virConnectPtr conn, const char *from) > { > - char filepath[4096]; > VIR_DEBUG("conn=%p, from=%s", conn, from); > > virResetLastError(); > @@ -2326,34 +2319,24 @@ virDomainRestore(virConnectPtr conn, const char *from) > goto error; > } > > - /* > - * We must absolutize the file path as the restore is done out of process > - * TODO: check for URI when libxml2 is linked in. > - */ > - if (from[0] != '/') { > - unsigned int len, t; > + if (conn->driver->domainRestore) { > + int ret; > + char *absolute_from; > > - t = strlen(from); > - if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) { > - virLibConnError(VIR_ERR_SYSTEM_ERROR, > - _("cannot get working directory")); > - goto error; > - } > - len = strlen(filepath); > - /* that should be covered by getcwd() semantic, but be 100% sure */ > - if (len > sizeof(filepath) - (t + 3)) { > + /* > + * We must absolutize the file path as the restore is done out of process > + * TODO: check for URI when libxml2 is linked in. > + */ > + if (virFileAbsPath(from, &absolute_from) < 0) { > virLibConnError(VIR_ERR_INTERNAL_ERROR, > - _("path too long")); > + _("could not build absolute input file path")); > goto error; > } > - filepath[len] = '/'; > - strcpy(&filepath[len + 1], from); > - from = &filepath[0]; > - } > > - if (conn->driver->domainRestore) { > - int ret; > - ret = conn->driver->domainRestore (conn, from); > + ret = conn->driver->domainRestore(conn, absolute_from); > + > + VIR_FREE(absolute_from); > + > if (ret < 0) > goto error; > return ret; > @@ -2381,7 +2364,6 @@ error: > int > virDomainCoreDump(virDomainPtr domain, const char *to, int flags) > { > - char filepath[4096]; > virConnectPtr conn; > > VIR_DOMAIN_DEBUG(domain, "to=%s, flags=%d", to, flags); > @@ -2403,35 +2385,24 @@ virDomainCoreDump(virDomainPtr domain, const char *to, int flags) > goto error; > } > > - /* > - * We must absolutize the file path as the save is done out of process > - * TODO: check for URI when libxml2 is linked in. > - */ > - if (to[0] != '/') { > - unsigned int len, t; > + if (conn->driver->domainCoreDump) { > + int ret; > + char *absolute_to; > > - t = strlen(to); > - if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) { > - virLibDomainError(VIR_ERR_SYSTEM_ERROR, > - _("cannot get current directory")); > - goto error; > - } > - len = strlen(filepath); > - /* that should be covered by getcwd() semantic, but be 100% sure */ > - if (len > sizeof(filepath) - (t + 3)) { > - virLibDomainError(VIR_ERR_INTERNAL_ERROR, > - _("path too long")); > + /* > + * We must absolutize the file path as the save is done out of process > + * TODO: check for URI when libxml2 is linked in. > + */ > + if (virFileAbsPath(to, &absolute_to) < 0) { > + virLibConnError(VIR_ERR_INTERNAL_ERROR, > + _("could not build absolute core file path")); > goto error; > } > - filepath[len] = '/'; > - strcpy(&filepath[len + 1], to); > - to = &filepath[0]; > > - } > + ret = conn->driver->domainCoreDump(domain, absolute_to, flags); > + > + VIR_FREE(absolute_to); > > - if (conn->driver->domainCoreDump) { > - int ret; > - ret = conn->driver->domainCoreDump (domain, to, flags); > if (ret < 0) > goto error; > return ret; ACK, but you could kill those TODO: comments, since I don't think we will ever let libvirt save to arbitrary URIs. If anything we would introduce a different API using the virStreamPtr facility, so the client app would deal with URIs as needed Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:31:27 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:31:27 +0100 Subject: [libvirt] [PATCH 10/20] virsh: Remove two 4kb stack allocations In-Reply-To: <1301822493-23013-11-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-11-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404103127.GL13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:23AM +0200, Matthias Bolte wrote: > --- > tools/virsh.c | 23 +++++++++++++++++------ > 1 files changed, 17 insertions(+), 6 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:35:18 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:35:18 +0100 Subject: [libvirt] [PATCH 11/20] phyp: Remove the last instance of stack allocating a 4kb volume key In-Reply-To: <1301822493-23013-12-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-12-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404103518.GM13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:24AM +0200, Matthias Bolte wrote: > --- > src/phyp/phyp_driver.c | 13 +++++++++++-- > 1 files changed, 11 insertions(+), 2 deletions(-) > > diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c > index fe2e99d..76207c2 100644 > --- a/src/phyp/phyp_driver.c > +++ b/src/phyp/phyp_driver.c > @@ -2362,13 +2362,22 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, > static virStorageVolPtr > phypVolumeLookupByName(virStoragePoolPtr pool, const char *volname) > { > + char *key; > + virStorageVolPtr vol; > > - char key[MAX_KEY_SIZE]; > + if (VIR_ALLOC_N(key, MAX_KEY_SIZE) < 0) { > + virReportOOMError(); > + return NULL; > + } > > if (phypVolumeGetKey(pool->conn, key, volname) == -1) > return NULL; > > - return virGetStorageVol(pool->conn, pool->name, volname, key); > + vol = virGetStorageVol(pool->conn, pool->name, volname, key); > + > + VIR_FREE(key); > + > + return vol; > } I think the signature of phypVolumeGetKey() is rather dangerous - it is blindly assuming the caller allocates MAX_KEY_SIZE for 'key'. The phypVolumeGetKey knows exactly how long the key it has is, so it'd be better for it to allocate the buffer itself & return it to the callers I realize this isn't a new problem from your patch, but I reckon we should fix it here. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:35:53 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:35:53 +0100 Subject: [libvirt] [PATCH 12/20] daemon: Remove 4kb stack allocation of security label In-Reply-To: <1301822493-23013-13-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-13-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404103553.GN13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:25AM +0200, Matthias Bolte wrote: > --- > daemon/remote.c | 20 ++++++++++++++------ > 1 files changed, 14 insertions(+), 6 deletions(-) > > diff --git a/daemon/remote.c b/daemon/remote.c > index 1700c2d..dd85ef1 100644 > --- a/daemon/remote.c > +++ b/daemon/remote.c > @@ -1607,7 +1607,7 @@ remoteDispatchDomainGetSecurityLabel(struct qemud_server *server ATTRIBUTE_UNUSE > remote_domain_get_security_label_ret *ret) > { > virDomainPtr dom; > - virSecurityLabel seclabel; > + virSecurityLabelPtr seclabel; > > dom = get_nonnull_domain(conn, args->dom); > if (dom == NULL) { > @@ -1615,22 +1615,30 @@ remoteDispatchDomainGetSecurityLabel(struct qemud_server *server ATTRIBUTE_UNUSE > return -1; > } > > - memset(&seclabel, 0, sizeof seclabel); > - if (virDomainGetSecurityLabel(dom, &seclabel) == -1) { > + if (VIR_ALLOC(seclabel) < 0) { > + virDomainFree(dom); > + remoteDispatchOOMError(rerr); > + return -1; > + } > + > + if (virDomainGetSecurityLabel(dom, seclabel) == -1) { > remoteDispatchConnError(rerr, conn); > virDomainFree(dom); > + VIR_FREE(seclabel); > return -1; > } > > - ret->label.label_len = strlen(seclabel.label) + 1; > + ret->label.label_len = strlen(seclabel->label) + 1; > if (VIR_ALLOC_N(ret->label.label_val, ret->label.label_len) < 0) { > virDomainFree(dom); > + VIR_FREE(seclabel); > remoteDispatchOOMError(rerr); > return -1; > } > - strcpy(ret->label.label_val, seclabel.label); > - ret->enforcing = seclabel.enforcing; > + strcpy(ret->label.label_val, seclabel->label); > + ret->enforcing = seclabel->enforcing; > virDomainFree(dom); > + VIR_FREE(seclabel); > > return 0; > } ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:37:20 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:37:20 +0100 Subject: [libvirt] [PATCH 13/20] openvz: Remove several larger stack allocations In-Reply-To: <1301822493-23013-14-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-14-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404103720.GO13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:26AM +0200, Matthias Bolte wrote: > Replace openvz_readline with getline in several places to get rid of stack > allocated buffers to hold lines. > > openvzReadConfigParam allocates memory for return values instead of > expecting a preexisting buffer. > --- > src/openvz/openvz_conf.c | 141 +++++++++++++++++++++++++++----------------- > src/openvz/openvz_conf.h | 2 +- > src/openvz/openvz_driver.c | 45 +++++++++----- > 3 files changed, 117 insertions(+), 71 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:38:05 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:38:05 +0100 Subject: [libvirt] [PATCH 14/20] Remove PATH_MAX sized stack allocation from virFileOpenTtyAt In-Reply-To: <1301822493-23013-15-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-15-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404103805.GP13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:27AM +0200, Matthias Bolte wrote: > --- > src/util/util.c | 9 ++++----- > 1 files changed, 4 insertions(+), 5 deletions(-) > > diff --git a/src/util/util.c b/src/util/util.c > index 31feecc..c0391ad 100644 > --- a/src/util/util.c > +++ b/src/util/util.c > @@ -1901,14 +1901,13 @@ int virFileOpenTtyAt(const char *ptmx, > } > > if (ttyName) { > - char tempTtyName[PATH_MAX]; > - if (ptsname_r(*ttymaster, tempTtyName, sizeof(tempTtyName)) < 0) > - goto cleanup; > - > - if ((*ttyName = strdup(tempTtyName)) == NULL) { > + if (VIR_ALLOC_N(*ttyName, PATH_MAX) < 0) { > errno = ENOMEM; > goto cleanup; > } > + > + if (ptsname_r(*ttymaster, *ttyName, PATH_MAX) < 0) > + goto cleanup; > } ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:38:49 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:38:49 +0100 Subject: [libvirt] [PATCH 15/20] qemu: Remove PATH_MAX sized stack allocation used in commandline building In-Reply-To: <1301822493-23013-16-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-16-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404103849.GQ13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:28AM +0200, Matthias Bolte wrote: > --- > src/qemu/qemu_command.c | 43 ++++++++++++++++++++++++++++++------------- > 1 files changed, 30 insertions(+), 13 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:40:23 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:40:23 +0100 Subject: [libvirt] [PATCH 16/20] xen: Remove PATH_MAX sized stack allocation from block stats code In-Reply-To: <1301822493-23013-17-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-17-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404104023.GR13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:29AM +0200, Matthias Bolte wrote: > --- > src/xen/block_stats.c | 52 +++++++++++++++++++++++++----------------------- > 1 files changed, 27 insertions(+), 25 deletions(-) > > diff --git a/src/xen/block_stats.c b/src/xen/block_stats.c > index e7c80c9..6b4171d 100644 > --- a/src/xen/block_stats.c > +++ b/src/xen/block_stats.c > @@ -113,34 +113,36 @@ read_stat (const char *path) > } > > static int64_t > -read_bd_stat (int device, int domid, const char *str) > +read_bd_stat(int device, int domid, const char *str) > { > - char path[PATH_MAX]; > + static const char *paths[] = { > + "/sys/bus/xen-backend/devices/vbd-%d-%d/statistics/%s", > + "/sys/bus/xen-backend/devices/tap-%d-%d/statistics/%s", > + "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s", > + "/sys/devices/xen-backend/tap-%d-%d/statistics/%s", > + NULL > + }; If you leave out the trailing NULL > + > + int i; > + char *path; > int64_t r; > > - snprintf (path, sizeof path, > - "/sys/bus/xen-backend/devices/vbd-%d-%d/statistics/%s", > - domid, device, str); > - r = read_stat (path); > - if (r >= 0) return r; > - > - snprintf (path, sizeof path, > - "/sys/bus/xen-backend/devices/tap-%d-%d/statistics/%s", > - domid, device, str); > - r = read_stat (path); > - if (r >= 0) return r; > - > - snprintf (path, sizeof path, > - "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s", > - domid, device, str); > - r = read_stat (path); > - if (r >= 0) return r; > - > - snprintf (path, sizeof path, > - "/sys/devices/xen-backend/tap-%d-%d/statistics/%s", > - domid, device, str); > - r = read_stat (path); > - return r; > + for (i = 0; paths[i] != NULL; ++i) { you can just use for (i = 0 ; i < ARRAY_CARDINALITY(paths) ; i++) which I find slightly clearer. > + if (virAsprintf(&path, paths[i], domid, device, str) < 0) { > + virReportOOMError(); > + return -1; > + } > + > + r = read_stat(path); > + > + VIR_FREE(path); > + > + if (r >= 0) { > + return r; > + } > + } > + > + return -1; > } Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:41:12 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:41:12 +0100 Subject: [libvirt] [PATCH 17/20] storage: Remove PATH_MAX sized stack allocation from iSCSI backend In-Reply-To: <1301822493-23013-18-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-18-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404104112.GS13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:30AM +0200, Matthias Bolte wrote: > --- > src/storage/storage_backend_iscsi.c | 11 ++++++++--- > 1 files changed, 8 insertions(+), 3 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:41:37 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:41:37 +0100 Subject: [libvirt] [PATCH 18/20] uml: Remove PATH_MAX sized stack allocation from /proc parsing code In-Reply-To: <1301822493-23013-19-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-19-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404104137.GT13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:31AM +0200, Matthias Bolte wrote: > --- > src/uml/uml_driver.c | 10 +++++++--- > 1 files changed, 7 insertions(+), 3 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:42:11 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:42:11 +0100 Subject: [libvirt] [PATCH 19/20] xend: Remove 4kb stack allocation In-Reply-To: <1301822493-23013-20-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-20-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404104211.GU13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:32AM +0200, Matthias Bolte wrote: > --- > src/xen/xend_internal.c | 12 ++++++++++-- > 1 files changed, 10 insertions(+), 2 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:43:05 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:43:05 +0100 Subject: [libvirt] [PATCH 20/20] Use virBufferPtr for sexpr2string instead of manual buffer handling In-Reply-To: <1301822493-23013-21-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <1301822493-23013-21-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404104305.GV13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:33AM +0200, Matthias Bolte wrote: > Removes 4kb stack allocation in the XenD subdriver. > --- > src/util/sexpr.c | 142 +++++++++++++++++++++++------------------------ > src/util/sexpr.h | 3 +- > src/xen/xend_internal.c | 17 +++++- > 3 files changed, 86 insertions(+), 76 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:44:23 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:44:23 +0100 Subject: [libvirt] [PATCH 00/20] Remove large stack allocations In-Reply-To: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110404104423.GW13616@redhat.com> On Sun, Apr 03, 2011 at 11:21:13AM +0200, Matthias Bolte wrote: > This is meant for post-0.9.0. > > The series removes many large stack allocations from the code base and makes > it compile with -Wframe-larger-than=2500. This was inspired by Dan's patch for > using gnulib's manywarnings & warnings modules [1]. Where he mentioned that > currently -Wframe-larger-than=20480 is required. > > This series doesn't address stack usage in the test suite. I've ACKd most of the patches - feel free to push those after the release & just repost the couple which had comments, rather than the whole series. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:47:53 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:47:53 +0100 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> Message-ID: <20110404104753.GX13616@redhat.com> On Sun, Apr 03, 2011 at 07:06:17PM +0100, Stefan Hajnoczi wrote: > On Sun, Apr 3, 2011 at 2:12 PM, Blue Swirl wrote: > > On Sun, Apr 3, 2011 at 2:57 PM, Stefan Hajnoczi wrote: > >> On Tue, Mar 29, 2011 at 8:04 PM, Stefan Hajnoczi > >> wrote: > >>> Piggy-back on the guest CD-ROM polling to poll on the host. ?Open and > >>> close the host CD-ROM file descriptor to ensure we read the new size and > >>> not a stale size. > >>> > >>> Two things are going on here: > >>> > >>> 1. If hald/udisks is not already polling CD-ROMs on the host then > >>> ? re-opening the CD-ROM causes the host to read the new medium's size. > >>> > >>> 2. There is a bug in Linux which means the CD-ROM file descriptor must > >>> ? be re-opened in order for lseek(2) to see the new size. ?The > >>> ? inode size gets out of sync with the underlying device (which you can > >>> ? confirm by checking that /sys/block/sr0/size and lseek(2) do not > >>> ? match after media change). ?I have raised this with the > >>> ? maintainers but we need a workaround for the foreseeable future. > >>> > >>> Note that these changes are all in a #ifdef __linux__ section. > >>> > >>> Signed-off-by: Stefan Hajnoczi > >>> --- > >>> ?block/raw-posix.c | ? 26 ++++++++++++++++++++++---- > >>> ?1 files changed, 22 insertions(+), 4 deletions(-) > >>> > >>> diff --git a/block/raw-posix.c b/block/raw-posix.c > >>> index 6b72470..8b5205c 100644 > >>> --- a/block/raw-posix.c > >>> +++ b/block/raw-posix.c > >>> @@ -1238,10 +1238,28 @@ static int cdrom_is_inserted(BlockDriverState *bs) > >>> ? ? BDRVRawState *s = bs->opaque; > >>> ? ? int ret; > >>> > >>> - ? ?ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); > >>> - ? ?if (ret == CDS_DISC_OK) > >>> - ? ? ? ?return 1; > >>> - ? ?return 0; > >>> + ? ?/* > >>> + ? ? * Close the file descriptor if no medium is present and open it to poll > >>> + ? ? * again. ?This ensures the medium size is refreshed. ?If the file > >>> + ? ? * descriptor is kept open the size can become stale. ?This is essentially > >>> + ? ? * replicating CD-ROM polling but is driven by the guest. ?As the guest > >>> + ? ? * polls, we poll the host. > >>> + ? ? */ > >>> + > >>> + ? ?if (s->fd == -1) { > >>> + ? ? ? ?s->fd = qemu_open(bs->filename, s->open_flags, 0644); > >>> + ? ? ? ?if (s->fd < 0) { > >>> + ? ? ? ? ? ?return 0; > >>> + ? ? ? ?} > >>> + ? ?} > >>> + > >>> + ? ?ret = (ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK); > >>> + > >>> + ? ?if (!ret) { > >>> + ? ? ? ?close(s->fd); > >>> + ? ? ? ?s->fd = -1; > >>> + ? ?} > >>> + ? ?return ret; > >>> ?} > >>> > >>> ?static int cdrom_eject(BlockDriverState *bs, int eject_flag) > >>> -- > >>> 1.7.4.1 > >>> > >>> > >>> > >> > >> There is an issue with reopening host devices in QEMU when running > >> under libvirt. ?It appears that libvirt chowns image files (including > >> device nodes) so that the launched QEMU process can access them. > >> > >> Unfortunately after media change on host devices udev will reset the > >> ownership of the device node. ?This causes open(2) to fail with EACCES > >> since the QEMU process does not have the right uid/gid/groups and > >> libvirt is unaware that the file's ownership has changed. > >> > >> In order for media change to work with Linux host CD-ROM it is > >> necessary to reopen the file (otherwise the inode size will not > >> refresh, this is an issue with existing kernels). > >> > >> How can libvirt's security model be made to support this case? ?In > >> theory udev could be temporarily configured with libvirt permissions > >> for the CD-ROM device while passed through to the guest, but is that > >> feasible? > > > > How about something like this: Add an explicit reopen method to > > BlockDriver. Make a special block device for passed file descriptors. > > Pass descriptors in libvirt for CD-ROMs instead of the device paths. > > The reopen method for file descriptors should notify libvirt about > > need to pass a reopened descriptor and then block all accesses until a > > new descriptor is available. This should also solve your earlier > > problem. > > I'm hoping libvirt's behavior can be made to just work rather than > adding new features to QEMU. But perhaps passing file descriptors is > useful for more than just reopening host devices. This would > basically be a privilege separation model where the QEMU process isn't > able to open files itself but can request libvirt to open them on its > behalf. It is rather frickin' annoying the way udev resets the ownership when the media merely changes. If it isn't possible to stop udev doing this, then i think the only practical thing is to use ACLs instead of user/group ownership. We wanted to switch to ACLs in libvirt for other reasons already, but it isn't quite as simple as it sounds[1] so we've not done it just yet. Daniel [1] Mostly due to handling upgrades from existing libvirtd while VMs are running, and coping with filesystems which don't support ACLs (or have them turned of by mount options) -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 10:50:13 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 11:50:13 +0100 Subject: [libvirt] FYI, "Unable to create cgroup for ..." In-Reply-To: <87k4fixf0f.fsf@rho.meyering.net> References: <87k4fixf0f.fsf@rho.meyering.net> Message-ID: <20110404105013.GY13616@redhat.com> On Tue, Mar 29, 2011 at 02:55:28PM +0200, Jim Meyering wrote: > In case someone else encounters this... > > Today none of my VMs would start on F15: > > # virsh create rawhide.xml > error: Failed to create domain from rawhide.xml > error: Unable to create cgroup for rawhide: No such file or directory > > Luckily, I noticed that Rich Jones had the same problem > a week ago and he found that restarting libvirtd was enough > to solve the problem: > > # service libvirtd restart > > That did it for me, too. This is a bug in systemd. It periodically scans all mounted cgroups and deletes any directories which don't contain any attached processes. Needless to say this breaks libvirt, and possibly other apps, which don't expect 3rd parties to be deleting their directories. https://bugzilla.redhat.com/show_bug.cgi?id=678555 Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From jclift at redhat.com Mon Apr 4 10:59:58 2011 From: jclift at redhat.com (Justin Clift) Date: Mon, 4 Apr 2011 20:59:58 +1000 Subject: [libvirt] [Libvirt-announce] 0.9.0 freeze week, RC2 version to test In-Reply-To: <883C8F48-51DF-4514-AC21-AA7397EE741A@redhat.com> References: <20110328062538.GB7346@redhat.com> <20110329144659.GD25888@redhat.com> <20110331134423.GK24425@redhat.com> <305053C1-65ED-4BCA-99CF-15927F4B31E9@redhat.com> <883C8F48-51DF-4514-AC21-AA7397EE741A@redhat.com> Message-ID: <788B08A8-35E5-4B62-A3C9-4984DE63D5AD@redhat.com> On 04/04/2011, at 8:51 PM, Justin Clift wrote: > On 02/04/2011, at 6:34 PM, Matthias Bolte wrote: > >>> Thanks. It's looking like some kind of problem interacting with >>> VirtualBox (v4.0.4): >> >>> This is the full gdb backtrace from the process: >>> >>> (gdb) thread apply all bt >>> >>> Thread 1 (process 85784): >>> #0 0x00007fff8549b3a6 in swtch_pri () >>> #1 0x00007fff854d5b51 in _pthread_find_thread () > >> Strange point to get stuck. >> >> I assume VirtualBox for OSX comes with it's own GUI tool. Is it also >> affected or only virsh? >> >> Does this happen with VirtualBox 4.0.4 only, or is 4.x or even 3.x affected too? > > Just tried with the earlier versions of 4.0.2 and 3.2.12, with full libvirt > autogen.sh and recompile after each installation. Exact same behaviour, hang > point, everything. :( > > The VirtualBox GUI seems completely unaffected. While virsh is stuck, the > GUI can be started, VM's started/stopped, GUI shut down, all as per normal. > > I guess this is going to take a bunch more debugging, which I personally don't > have the time for atm. (ugh) :( > > Are there any other OSX users around that could take a look? As additional info, connecting to a remote RHEL 6.0 libvirtd using ssh works: $ tools/virsh -c qemu+ssh://root at servername/system?socket=/var/run/libvirt/libvirt-sock root at servername's password: Welcome to virsh, the virtualization interactive terminal. Type: 'help' for help with commands 'quit' to quit virsh # ^D $ Which is nice, as from memory it didn't used to (for ssh specifically). + Justin From jim at meyering.net Mon Apr 4 11:24:09 2011 From: jim at meyering.net (Jim Meyering) Date: Mon, 04 Apr 2011 13:24:09 +0200 Subject: [libvirt] FYI, "Unable to create cgroup for ..." In-Reply-To: <20110404105013.GY13616@redhat.com> (Daniel P. Berrange's message of "Mon, 4 Apr 2011 11:50:13 +0100") References: <87k4fixf0f.fsf@rho.meyering.net> <20110404105013.GY13616@redhat.com> Message-ID: <87bp0m9s4m.fsf@rho.meyering.net> Daniel P. Berrange wrote: > On Tue, Mar 29, 2011 at 02:55:28PM +0200, Jim Meyering wrote: >> In case someone else encounters this... >> >> Today none of my VMs would start on F15: >> >> # virsh create rawhide.xml >> error: Failed to create domain from rawhide.xml >> error: Unable to create cgroup for rawhide: No such file or directory >> >> Luckily, I noticed that Rich Jones had the same problem >> a week ago and he found that restarting libvirtd was enough >> to solve the problem: >> >> # service libvirtd restart >> >> That did it for me, too. > > This is a bug in systemd. It periodically scans all mounted cgroups > and deletes any directories which don't contain any attached processes. > Needless to say this breaks libvirt, and possibly other apps, which > don't expect 3rd parties to be deleting their directories. > > https://bugzilla.redhat.com/show_bug.cgi?id=678555 Thanks. With that, it's sure to be fixed soon. From berrange at redhat.com Mon Apr 4 11:34:53 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 12:34:53 +0100 Subject: [libvirt] [PATCH] add sendevent command and related APIs In-Reply-To: <4D95A00A.3040901@cn.fujitsu.com> References: <4D95A00A.3040901@cn.fujitsu.com> Message-ID: <20110404113453.GZ13616@redhat.com> On Fri, Apr 01, 2011 at 05:51:06PM +0800, Lai Jiangshan wrote: > Enable libvirt send some events to the guest. > This command currently only supports NMI and key events. > > Signed-off-by: Lai Jiangshan > --- > daemon/remote.c | 52 +++++++++++++++++++++ > daemon/remote_dispatch_args.h | 2 > daemon/remote_dispatch_prototypes.h | 16 ++++++ > daemon/remote_dispatch_table.h | 10 ++++ > include/libvirt/libvirt.h.in | 3 + > src/driver.h | 7 ++ > src/esx/esx_driver.c | 2 > src/libvirt.c | 88 ++++++++++++++++++++++++++++++++++++ > src/libvirt_public.syms | 2 > src/libxl/libxl_driver.c | 2 > src/lxc/lxc_driver.c | 2 > src/openvz/openvz_driver.c | 2 > src/phyp/phyp_driver.c | 4 + > src/qemu/qemu_driver.c | 86 +++++++++++++++++++++++++++++++++++ > src/qemu/qemu_monitor.c | 27 +++++++++++ > src/qemu/qemu_monitor.h | 3 + > src/qemu/qemu_monitor_json.c | 68 +++++++++++++++++++++++++++ > src/qemu/qemu_monitor_json.h | 3 + > src/qemu/qemu_monitor_text.c | 56 ++++++++++++++++++++++ > src/qemu/qemu_monitor_text.h | 2 > src/remote/remote_driver.c | 50 ++++++++++++++++++++ > src/remote/remote_protocol.c | 22 +++++++++ > src/remote/remote_protocol.h | 19 +++++++ > src/remote/remote_protocol.x | 14 +++++ > src/test/test_driver.c | 2 > src/uml/uml_driver.c | 2 > src/vbox/vbox_tmpl.c | 2 > src/vmware/vmware_driver.c | 2 > src/xen/xen_driver.c | 2 > src/xenapi/xenapi_driver.c | 2 > tools/virsh.c | 56 ++++++++++++++++++++++ > 31 files changed, 608 insertions(+), 2 deletions(-) > diff --git a/src/libvirt.c b/src/libvirt.c > index 9bdb4c8..245247f 100644 > --- a/src/libvirt.c > +++ b/src/libvirt.c > @@ -5245,6 +5245,94 @@ error: > } > > /** > + * virDomainSendEvnetNMI: > + * @domain: pointer to domain object, or NULL for Domain0 > + * @vcpu: the virtual CPU id to send NMI to > + * > + * Send NMI to a special vcpu of the guest > + * > + * Returns 0 in case of success, -1 in case of failure. > + */ > + > +int virDomainSendEventNMI(virDomainPtr domain, unsigned int vcpu) Your proposal to qemu-devel to add inject-nmi for QMP does not include any CPU index parameter anymore. Instead it will automatically inject the NMI to all present CPUs. This libvirt API would appear to be incompatible with that QMP design. For Xen, it appears the API also does not allow a CPU index to be given - it just injects to the first CPU AFAICT. So do we really need to have a 'unsigned int vcpu' parameter in the libvirt API, or can we just leave it out and always inject to CPU==0 for HMP ? eg simplify to int virDomainSendNMI(virDomainPtr domain) > +{ > + virConnectPtr conn; > + VIR_DOMAIN_DEBUG(domain, "vcpu=%u", vcpu); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { > + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); > + virDispatchError(NULL); > + return (-1); > + } > + if (domain->conn->flags & VIR_CONNECT_RO) { > + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); > + goto error; > + } > + > + conn = domain->conn; > + > + if (conn->driver->domainSendEventNMI) { > + int ret; > + ret = conn->driver->domainSendEventNMI(domain, vcpu); > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virLibConnError (VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + virDispatchError(domain->conn); > + return -1; > +} > + > +/** > + * virDomainSendEventKey: > + * @domain: pointer to domain object, or NULL for Domain0 > + * @key: the string of key or key sequence > + * > + * Send a special key or key sequence to the guest > + * > + * Returns 0 in case of success, -1 in case of failure. > + */ > + > +int virDomainSendEventKey(virDomainPtr domain, const char *key) I don't entirely like that the 'const char *key' is just directly exposing QEMU key names and combining syntax eg "ctrl-alt-delete". The names are symbolic names for XT scancodes, which QEMU uses internally as its master scancode set (regardless of arch or whether the keyboard is actually XT based). The VirtualBox API, requires that the application send an array of integer scancodes. The QEMU 'sendkey' command also has another 'holdtime' parameter which controls how long QEMU waits between the 'press' and 'release' of the keys, which our API does not have. The core requirement is that our API be able to send any possible key, to any hypervisor. The problem with XT scancodes, is that while it can be made to represent any possible scancode, it gets somewhat confusing for apps because there are many different ways to represent extended scancodes in use across apps. One alternative would be to duplicate Linux's virtual scancode constants, which are a superset of all known possible scancode lists. Then we would do a conversion inside libvirt from Linux to hypervisor specific scancode format (probably XT values, or XT strings). The interesting thing about using Linux virtual scancode constants is that this includes mouse buttons. So the same API could be used to inject mouse clicks. We'd still need an explicit API for doing mouse events though, because we'd need to be able to press buttons, then generate motion events, then release buttons. So, my preference would be for an API virDomainSendKey(virDomainPtr dom, unsigned int nkeycodes, unsigned int keycodes, unsigned int holdtime); If "holdtime" is zero, then the hypervisor default behaviour would be used. This allows us to support VirtualBox where we'd have to reject any non-zero "holdtime" value Then I think I'd create a new header file include/libvirt/virtkeys.h which contained a copy of only the KEY_* constants from: /usr/include/linux/input.h We'd just have a static array with a mapping from keys to the QEMU keycode names. > diff --git a/tools/virsh.c b/tools/virsh.c > index faeaf47..0b78c6d 100644 > --- a/tools/virsh.c > +++ b/tools/virsh.c > @@ -2910,6 +2910,61 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) > } > > /* > + * "sendevent" command > + */ > +static const vshCmdInfo info_sendevent[] = { > + {"help", N_("send events to the guest")}, > + {"desc", N_("Send events (NMI or Keys) to the guest domain.")}, > + {NULL, NULL} > +}; > + > +static const vshCmdOptDef opts_sendevent[] = { > + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, > + {"eventtype", VSH_OT_DATA, VSH_OFLAG_REQ, N_("the type of event (nmi or key)")}, > + {"eventcontent", VSH_OT_DATA, VSH_OFLAG_REQ, N_("content for the event.")}, > + {NULL, 0, 0, NULL} > +}; > + > + > +static int > +cmdSendEvent(vshControl *ctl, const vshCmd *cmd) > +{ > + virDomainPtr dom; > + const char *type; > + int ret = TRUE; > + > + if (!vshConnectionUsability(ctl, ctl->conn)) > + return FALSE; > + > + if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) > + return FALSE; > + > + if (vshCommandOptString(cmd, "eventtype", &type) < 0) > + return FALSE; > + > + if (STREQ(type, "nmi")) { > + int cpu; > + > + if ((vshCommandOptInt(cmd, "eventcontent", &cpu) < 0) > + || (virDomainSendEventNMI(dom, cpu) < 0)) > + ret = FALSE; > + } else if (STREQ(type, "key")) { > + const char *key; > + > + if ((vshCommandOptString(cmd, "eventcontent", &key) < 0) > + || (virDomainSendEventKey(dom, key) < 0)) > + ret = FALSE; > + } else { > + virDomainFree(dom); > + vshError(ctl, _("Invalid event type: %s, only \"nmi\" or \"key\" supported currently."), type); > + return FALSE; > + } > + > + virDomainFree(dom); > + return ret; > +} I don't like the way two APIs are combined into one virsh command. Particularly since I think we'll likely add another API 'virDomainSendPointer' which will take as many as 4/5 parameters, instead of just one. Thus I think it would be better to have virsh send-nmi virsh send-key [--holdtime millsec] [ ...] virsh send-pointer ... virsh send-..... etc... Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 4 11:50:43 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 12:50:43 +0100 Subject: [libvirt] [PATCH 1/6] virNodeGetCpuTime: Expose new API In-Reply-To: <20110404110310.e85d09ba.usui@mxm.nes.nec.co.jp> References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> <20110401105548.a78607f7.usui@mxm.nes.nec.co.jp> <4D95FB08.20802@redhat.com> <20110404110310.e85d09ba.usui@mxm.nes.nec.co.jp> Message-ID: <20110404115043.GA13616@redhat.com> On Mon, Apr 04, 2011 at 11:03:10AM +0900, Minoru Usui wrote: > Hi, Matthias. > > On Fri, 1 Apr 2011 20:22:17 +0200 > Matthias Bolte wrote: > > > 2011/4/1 Eric Blake : > > > On 03/31/2011 07:55 PM, Minoru Usui wrote: > > >> virNodeGetCpuTime: Expose new API > > >> > > >> ?include/libvirt/libvirt.h.in | ? 26 ++++++++++++++++++++++++++ > > >> ?src/libvirt_public.syms ? ? ?| ? ?1 + > > >> ?2 files changed, 27 insertions(+), 0 deletions(-) > > > > > >> > > >> +/** > > >> + * virNodeCpuTime: > > >> + * > > >> + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing > > >> + * the information for the cpu time of Node. > > >> + */ > > >> + > > >> +typedef struct _virNodeCpuTime virNodeCpuTime; > > >> + > > >> +struct _virNodeCpuTime { > > >> + ? ?unsigned long long user; > > >> + ? ?unsigned long long system; > > >> + ? ?unsigned long long idle; > > >> + ? ?unsigned long long iowait; > > >> +}; > > > > > > Can we portably get all of this information on Windows? ?If not, how do > > > you express which values we don't know how to obtain? > > > > > > > In the context of ESX I vote against this absolute CPU time values. > > ESX provides this values relative to a 20 second timeslots with 1 hour > > of history. This makes it nearly impossible to obtain the absolute CPU > > time. The same problem already exists for the domain's virtual CPU > > time. > > > > When you look at virt-top's usage of the domain's virtual CPU time, > > you see that it actually doesn't really care about the absolute value, > > but deduces the CPU utilization from it. I suggest that we find a > > different representation for this information that is not by > > definition impossible to implement for ESX. > > > > Matthias > > I didn't know ESX couldn't return absolute CPU time value. > Thank you for your comment. > > We really want to get CPU utilization information of the node, not > absolute CPU time values. > But linux doesn't provide CPU utilization directly, > so my patch returns absolute CPU time values, > and CPU utilization is calculated by client which uses new API. > > To return CPU utilization by new API, I think there are two issues of implementing on linux. > > a) How much interval does calculate CPU utilization? > To calculate CPU utilization on linux, we need to get absolute CPU time value of the node > from /proc/stat two times. > How much interval properly? 1sec? 1min? or others? The fact that there is the question of what is the right interval demonstrates the inherant flaw in such an API design. Providing the raw absolute time allows an app much more flexiblity in how they work with the data, avoiding the need for such policies in libvirt. > b) Can new API wait its interval? > If we select simply implementation, new API waits its interval. > But API user don't want to wait every API calls, if its interval is long. > So I think libvirtd will be calculating CPU utilization in background every interval. > Is this approach OK? IMHO we don't really want libvirtd to be constantly polling & calculating this data, at least not unless an application is currently asking for it. I think we want this API to have the style that is like the current virDomainMemoryStats API. Then, we can define a set of parameters that can be fetched, allowing each parameter to be optional eg enum { VIR_NODE_CPU_TIME_KERNEL, VIR_NODE_CPU_TIME_USER, VIR_NODE_CPU_TIME_IDLE, VIR_NODE_CPU_TIME_IOWAIT, VIR_NODE_CPU_TIME_UTILIZATION, }; For QEMU we'd provide the first 4 values, allowing apps maximum flexibility in how they calculate utilization over different time periods. For VMWare we'd provide only the last value. An app like virt-manager, can display UTILIZATION value directly if that is present, otherwise it will be able to calculate data from the other times as it does now for domains. So it would work with both QEMU and VMWare, to the best of its abilities. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From matthias.bolte at googlemail.com Mon Apr 4 12:30:32 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 4 Apr 2011 14:30:32 +0200 Subject: [libvirt] [PATCH 1/6] virNodeGetCpuTime: Expose new API In-Reply-To: <20110404115043.GA13616@redhat.com> References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> <20110401105548.a78607f7.usui@mxm.nes.nec.co.jp> <4D95FB08.20802@redhat.com> <20110404110310.e85d09ba.usui@mxm.nes.nec.co.jp> <20110404115043.GA13616@redhat.com> Message-ID: 2011/4/4 Daniel P. Berrange : > On Mon, Apr 04, 2011 at 11:03:10AM +0900, Minoru Usui wrote: >> Hi, Matthias. >> >> On Fri, 1 Apr 2011 20:22:17 +0200 >> Matthias Bolte wrote: >> >> > 2011/4/1 Eric Blake : >> > > On 03/31/2011 07:55 PM, Minoru Usui wrote: >> > >> virNodeGetCpuTime: Expose new API >> > >> >> > >> ?include/libvirt/libvirt.h.in | ? 26 ++++++++++++++++++++++++++ >> > >> ?src/libvirt_public.syms ? ? ?| ? ?1 + >> > >> ?2 files changed, 27 insertions(+), 0 deletions(-) >> > > >> > >> >> > >> +/** >> > >> + * virNodeCpuTime: >> > >> + * >> > >> + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing >> > >> + * the information for the cpu time of Node. >> > >> + */ >> > >> + >> > >> +typedef struct _virNodeCpuTime virNodeCpuTime; >> > >> + >> > >> +struct _virNodeCpuTime { >> > >> + ? ?unsigned long long user; >> > >> + ? ?unsigned long long system; >> > >> + ? ?unsigned long long idle; >> > >> + ? ?unsigned long long iowait; >> > >> +}; >> > > >> > > Can we portably get all of this information on Windows? ?If not, how do >> > > you express which values we don't know how to obtain? >> > > >> > >> > In the context of ESX I vote against this absolute CPU time values. >> > ESX provides this values relative to a 20 second timeslots with 1 hour >> > of history. This makes it nearly impossible to obtain the absolute CPU >> > time. The same problem already exists for the domain's virtual CPU >> > time. >> > >> > When you look at virt-top's usage of the domain's virtual CPU time, >> > you see that it actually doesn't really care about the absolute value, >> > but deduces the CPU utilization from it. I suggest that we find a >> > different representation for this information that is not by >> > definition impossible to implement for ESX. >> > >> > Matthias >> >> I didn't know ESX couldn't return absolute CPU time value. >> Thank you for your comment. >> >> We really want to get CPU utilization information of the node, not >> absolute CPU time values. >> But linux doesn't provide CPU utilization directly, >> so my patch returns absolute CPU time values, >> and CPU utilization is calculated by client which uses new API. >> >> To return CPU utilization by new API, I think there are two issues of implementing on linux. >> >> ? a) How much interval does calculate CPU utilization? >> ? ? ?To calculate CPU utilization on linux, we need to get absolute CPU time value of the node >> ? ? ?from /proc/stat two times. >> ? ? ?How much interval properly? 1sec? 1min? or others? > > The fact that there is the question of what is the right interval > demonstrates the inherant flaw in such an API design. Providing > the raw absolute time allows an app much more flexiblity in how > they work with the data, avoiding the need for such policies in > libvirt. > >> ? b) Can new API wait its interval? >> ? ? ?If we select simply implementation, new API waits its interval. >> ? ? ?But API user don't want to wait every API calls, if its interval is long. >> ? ? ?So I think libvirtd will be calculating CPU utilization in background every interval. >> ? ? ?Is this approach OK? > > IMHO we don't really want libvirtd to be constantly polling & calculating > this data, at least not unless an application is currently asking for it. > I think we want this API to have the style that is like the current > virDomainMemoryStats ?API. Then, we can define a set of parameters that > can be fetched, allowing each parameter to be optional > > eg > > ?enum { > ? ? VIR_NODE_CPU_TIME_KERNEL, > ? ? VIR_NODE_CPU_TIME_USER, > ? ? VIR_NODE_CPU_TIME_IDLE, > ? ? VIR_NODE_CPU_TIME_IOWAIT, > ? ? VIR_NODE_CPU_TIME_UTILIZATION, > ?}; > > For QEMU we'd provide the first 4 values, allowing apps maximum > flexibility in how they calculate utilization over different time > periods. For VMWare we'd provide only the last value. > > An app like virt-manager, can display UTILIZATION value directly if > that is present, otherwise it will be able to calculate data from > the other times as it does now for domains. So it would work with > both QEMU and VMWare, to the best of its abilities. > > Regards, > Daniel > For ESX the driver doesn't even need to calculate a usage/utilization value, because the ESX server already does this on it's own and the driver can just ask for it. The usage value is in percent and 100% represents all CPUs on the server. I like that approach. Matthias From jclift at redhat.com Mon Apr 4 10:51:58 2011 From: jclift at redhat.com (Justin Clift) Date: Mon, 4 Apr 2011 20:51:58 +1000 Subject: [libvirt] [Libvirt-announce] 0.9.0 freeze week, RC2 version to test In-Reply-To: References: <20110328062538.GB7346@redhat.com> <20110329144659.GD25888@redhat.com> <20110331134423.GK24425@redhat.com> <305053C1-65ED-4BCA-99CF-15927F4B31E9@redhat.com> Message-ID: <883C8F48-51DF-4514-AC21-AA7397EE741A@redhat.com> On 02/04/2011, at 6:34 PM, Matthias Bolte wrote: >> Thanks. It's looking like some kind of problem interacting with >> VirtualBox (v4.0.4): > >> This is the full gdb backtrace from the process: >> >> (gdb) thread apply all bt >> >> Thread 1 (process 85784): >> #0 0x00007fff8549b3a6 in swtch_pri () >> #1 0x00007fff854d5b51 in _pthread_find_thread () > Strange point to get stuck. > > I assume VirtualBox for OSX comes with it's own GUI tool. Is it also > affected or only virsh? > > Does this happen with VirtualBox 4.0.4 only, or is 4.x or even 3.x affected too? Just tried with the earlier versions of 4.0.2 and 3.2.12, with full libvirt autogen.sh and recompile after each installation. Exact same behaviour, hang point, everything. :( The VirtualBox GUI seems completely unaffected. While virsh is stuck, the GUI can be started, VM's started/stopped, GUI shut down, all as per normal. I guess this is going to take a bunch more debugging, which I personally don't have the time for atm. (ugh) :( Are there any other OSX users around that could take a look? Regards and best wishes, Justin Clift From berrange at redhat.com Mon Apr 4 12:55:31 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 13:55:31 +0100 Subject: [libvirt] [PATCH] Allow handshake with child process during startup Message-ID: <1301921731-32248-1-git-send-email-berrange@redhat.com> Allow the parent process to perform a bi-directional handshake with the child process during fork/exec. The child process will fork and do its initial setup. Immediately prior to the exec(), it will stop & wait for a handshake from the parent process. The parent process will spawn the child and wait until the child reaches the handshake point. It will do whatever extra setup work is required, before signalling the child to continue. The implementation of this is done using two pairs of blocking pipes. The first pair is used to block the parent, until the child writes a single byte. Then the second pair pair is used to block the child, until the parent confirms with another single byte. * src/util/command.c, src/util/command.h, src/libvirt_private.syms: Add APIs to perform a handshake --- src/libvirt_private.syms | 3 + src/util/command.c | 142 +++++++++++++++++++++++++++++++++++++++++++++- src/util/command.h | 5 ++ 3 files changed, 148 insertions(+), 2 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 114bc2e..87f0432 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -106,11 +106,14 @@ virCommandAddEnvString; virCommandClearCaps; virCommandDaemonize; virCommandFree; +virCommandHandshakeNotify; +virCommandHandshakeWait; virCommandNew; virCommandNewArgList; virCommandNewArgs; virCommandNonblockingFDs; virCommandPreserveFD; +virCommandRequireHandshake; virCommandRun; virCommandRunAsync; virCommandSetErrorBuffer; diff --git a/src/util/command.c b/src/util/command.c index 2e475a0..d8440ca 100644 --- a/src/util/command.c +++ b/src/util/command.c @@ -35,6 +35,11 @@ #include "files.h" #include "buf.h" +#include +#include +#include +#include + #define VIR_FROM_THIS VIR_FROM_NONE #define virCommandError(code, ...) \ @@ -76,6 +81,10 @@ struct _virCommand { int *outfdptr; int *errfdptr; + bool handshake; + int handshakeWait[2]; + int handshakeNotify[2]; + virExecHook hook; void *opaque; @@ -107,6 +116,11 @@ virCommandNewArgs(const char *const*args) if (VIR_ALLOC(cmd) < 0) return NULL; + cmd->handshakeWait[0] = -1; + cmd->handshakeWait[1] = -1; + cmd->handshakeNotify[0] = -1; + cmd->handshakeNotify[1] = -1; + FD_ZERO(&cmd->preserve); FD_ZERO(&cmd->transfer); cmd->infd = cmd->outfd = cmd->errfd = -1; @@ -1115,7 +1129,6 @@ virCommandRun(virCommandPtr cmd, int *exitstatus) return ret; } - /* * Perform all virCommand-specific actions, along with the user hook. */ @@ -1125,12 +1138,61 @@ virCommandHook(void *data) virCommandPtr cmd = data; int res = 0; - if (cmd->hook) + if (cmd->hook) { + VIR_DEBUG("Run hook %p %p", cmd->hook, cmd->opaque); res = cmd->hook(cmd->opaque); + VIR_DEBUG("Done hook %d", res); + } if (res == 0 && cmd->pwd) { VIR_DEBUG("Running child in %s", cmd->pwd); res = chdir(cmd->pwd); + if (res < 0) { + virReportSystemError(errno, + _("Unable to change to %s"), cmd->pwd); + } + } + if (cmd->handshake) { + char c = res < 0 ? '0' : '1'; + int rv; + VIR_DEBUG("Notifying parent for handshake start on %d", cmd->handshakeWait[1]); + if (safewrite(cmd->handshakeWait[1], &c, sizeof(c)) != sizeof(c)) { + virReportSystemError(errno, "%s", _("Unable to notify parent process")); + return -1; + } + + /* On failure we pass the error message back to parent, + * so they don't have to dig through stderr logs + */ + if (res < 0) { + virErrorPtr err = virGetLastError(); + const char *msg = err ? err->message : + _("Unknown failure during hook execution"); + size_t len = strlen(msg) + 1; + if (safewrite(cmd->handshakeWait[1], msg, len) != len) { + virReportSystemError(errno, "%s", _("Unable to send error to parent process")); + return -1; + } + return -1; + } + + VIR_DEBUG("Waiting on parent for handshake complete on %d", cmd->handshakeNotify[0]); + if ((rv = saferead(cmd->handshakeNotify[0], &c, sizeof(c))) != sizeof(c)) { + if (rv < 0) + virReportSystemError(errno, "%s", _("Unable to wait on parent process")); + else + virReportSystemError(EIO, "%s", _("libvirtd quit during handshake")); + return -1; + } + if (c != '1') { + virReportSystemError(EINVAL, _("Unexpected confirm code '%c' from parent process"), c); + return -1; + } + VIR_FORCE_CLOSE(cmd->handshakeWait[1]); + VIR_FORCE_CLOSE(cmd->handshakeNotify[0]); } + + VIR_DEBUG("Hook is done %d", res); + return res; } @@ -1220,6 +1282,10 @@ virCommandRunAsync(virCommandPtr cmd, pid_t *pid) FD_CLR(i, &cmd->transfer); } } + if (cmd->handshake) { + VIR_FORCE_CLOSE(cmd->handshakeWait[1]); + VIR_FORCE_CLOSE(cmd->handshakeNotify[0]); + } if (ret == 0 && pid) *pid = cmd->pid; @@ -1360,6 +1426,71 @@ virCommandAbort(virCommandPtr cmd ATTRIBUTE_UNUSED) } #endif + +void virCommandRequireHandshake(virCommandPtr cmd) +{ + if (pipe(cmd->handshakeWait) < 0) { + cmd->has_error = errno; + return; + } + if (pipe(cmd->handshakeNotify) < 0) { + VIR_FORCE_CLOSE(cmd->handshakeWait[0]); + VIR_FORCE_CLOSE(cmd->handshakeWait[1]); + cmd->has_error = errno; + return; + } + + VIR_DEBUG("Transfer handshake wait=%d notify=%d", + cmd->handshakeWait[1], cmd->handshakeNotify[0]); + virCommandPreserveFD(cmd, cmd->handshakeWait[1]); + virCommandPreserveFD(cmd, cmd->handshakeNotify[0]); + cmd->handshake = true; +} + +int virCommandHandshakeWait(virCommandPtr cmd) +{ + char c; + int rv; + VIR_DEBUG("Wait for handshake on %d", cmd->handshakeWait[0]); + if ((rv = saferead(cmd->handshakeWait[0], &c, sizeof(c))) != sizeof(c)) { + if (rv < 0) + virReportSystemError(errno, "%s", _("Unable to wait for child process")); + else + virReportSystemError(EIO, "%s", _("Child process quit during startup handshake")); + return -1; + } + if (c != '1') { + char *msg; + ssize_t len; + if (VIR_ALLOC_N(msg, 1024) < 0) { + virReportOOMError(); + return -1; + } + if ((len = saferead(cmd->handshakeWait[0], msg, 1024)) < 0) { + VIR_FREE(msg); + virReportSystemError(errno, "%s", _("No error message from child failure")); + return -1; + } + msg[len-1] = '\0'; + virCommandError(VIR_ERR_INTERNAL_ERROR, "%s", msg); + VIR_FREE(msg); + return -1; + } + return 0; +} + +int virCommandHandshakeNotify(virCommandPtr cmd) +{ + char c = '1'; + VIR_DEBUG("Notify handshake on %d", cmd->handshakeWait[0]); + if (safewrite(cmd->handshakeNotify[1], &c, sizeof(c)) != sizeof(c)) { + virReportSystemError(errno, "%s", _("Unable to notify child process")); + return -1; + } + return 0; +} + + /* * Release all resources */ @@ -1391,6 +1522,13 @@ virCommandFree(virCommandPtr cmd) VIR_FREE(cmd->pwd); + if (cmd->handshake) { + VIR_FORCE_CLOSE(cmd->handshakeWait[0]); + VIR_FORCE_CLOSE(cmd->handshakeWait[1]); + VIR_FORCE_CLOSE(cmd->handshakeNotify[0]); + VIR_FORCE_CLOSE(cmd->handshakeNotify[1]); + } + VIR_FREE(cmd->pidfile); if (cmd->reap) diff --git a/src/util/command.h b/src/util/command.h index ff8ccf5..4712301 100644 --- a/src/util/command.h +++ b/src/util/command.h @@ -274,6 +274,11 @@ int virCommandRunAsync(virCommandPtr cmd, int virCommandWait(virCommandPtr cmd, int *exitstatus) ATTRIBUTE_RETURN_CHECK; +void virCommandRequireHandshake(virCommandPtr cmd); + +int virCommandHandshakeWait(virCommandPtr cmd); +int virCommandHandshakeNotify(virCommandPtr cmd); + /* * Abort an async command if it is running, without issuing * any errors or affecting errno. Designed for error paths -- 1.7.4 From stefanha at gmail.com Mon Apr 4 12:58:35 2011 From: stefanha at gmail.com (Stefan Hajnoczi) Date: Mon, 4 Apr 2011 13:58:35 +0100 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <20110404104753.GX13616@redhat.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <20110404104753.GX13616@redhat.com> Message-ID: On Mon, Apr 4, 2011 at 11:47 AM, Daniel P. Berrange wrote: > On Sun, Apr 03, 2011 at 07:06:17PM +0100, Stefan Hajnoczi wrote: >> On Sun, Apr 3, 2011 at 2:12 PM, Blue Swirl wrote: >> > On Sun, Apr 3, 2011 at 2:57 PM, Stefan Hajnoczi wrote: >> >> On Tue, Mar 29, 2011 at 8:04 PM, Stefan Hajnoczi >> >> wrote: >> >>> Piggy-back on the guest CD-ROM polling to poll on the host. ?Open and >> >>> close the host CD-ROM file descriptor to ensure we read the new size and >> >>> not a stale size. >> >>> >> >>> Two things are going on here: >> >>> >> >>> 1. If hald/udisks is not already polling CD-ROMs on the host then >> >>> ? re-opening the CD-ROM causes the host to read the new medium's size. >> >>> >> >>> 2. There is a bug in Linux which means the CD-ROM file descriptor must >> >>> ? be re-opened in order for lseek(2) to see the new size. ?The >> >>> ? inode size gets out of sync with the underlying device (which you can >> >>> ? confirm by checking that /sys/block/sr0/size and lseek(2) do not >> >>> ? match after media change). ?I have raised this with the >> >>> ? maintainers but we need a workaround for the foreseeable future. >> >>> >> >>> Note that these changes are all in a #ifdef __linux__ section. >> >>> >> >>> Signed-off-by: Stefan Hajnoczi >> >>> --- >> >>> ?block/raw-posix.c | ? 26 ++++++++++++++++++++++---- >> >>> ?1 files changed, 22 insertions(+), 4 deletions(-) >> >>> >> >>> diff --git a/block/raw-posix.c b/block/raw-posix.c >> >>> index 6b72470..8b5205c 100644 >> >>> --- a/block/raw-posix.c >> >>> +++ b/block/raw-posix.c >> >>> @@ -1238,10 +1238,28 @@ static int cdrom_is_inserted(BlockDriverState *bs) >> >>> ? ? BDRVRawState *s = bs->opaque; >> >>> ? ? int ret; >> >>> >> >>> - ? ?ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); >> >>> - ? ?if (ret == CDS_DISC_OK) >> >>> - ? ? ? ?return 1; >> >>> - ? ?return 0; >> >>> + ? ?/* >> >>> + ? ? * Close the file descriptor if no medium is present and open it to poll >> >>> + ? ? * again. ?This ensures the medium size is refreshed. ?If the file >> >>> + ? ? * descriptor is kept open the size can become stale. ?This is essentially >> >>> + ? ? * replicating CD-ROM polling but is driven by the guest. ?As the guest >> >>> + ? ? * polls, we poll the host. >> >>> + ? ? */ >> >>> + >> >>> + ? ?if (s->fd == -1) { >> >>> + ? ? ? ?s->fd = qemu_open(bs->filename, s->open_flags, 0644); >> >>> + ? ? ? ?if (s->fd < 0) { >> >>> + ? ? ? ? ? ?return 0; >> >>> + ? ? ? ?} >> >>> + ? ?} >> >>> + >> >>> + ? ?ret = (ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK); >> >>> + >> >>> + ? ?if (!ret) { >> >>> + ? ? ? ?close(s->fd); >> >>> + ? ? ? ?s->fd = -1; >> >>> + ? ?} >> >>> + ? ?return ret; >> >>> ?} >> >>> >> >>> ?static int cdrom_eject(BlockDriverState *bs, int eject_flag) >> >>> -- >> >>> 1.7.4.1 >> >>> >> >>> >> >>> >> >> >> >> There is an issue with reopening host devices in QEMU when running >> >> under libvirt. ?It appears that libvirt chowns image files (including >> >> device nodes) so that the launched QEMU process can access them. >> >> >> >> Unfortunately after media change on host devices udev will reset the >> >> ownership of the device node. ?This causes open(2) to fail with EACCES >> >> since the QEMU process does not have the right uid/gid/groups and >> >> libvirt is unaware that the file's ownership has changed. >> >> >> >> In order for media change to work with Linux host CD-ROM it is >> >> necessary to reopen the file (otherwise the inode size will not >> >> refresh, this is an issue with existing kernels). >> >> >> >> How can libvirt's security model be made to support this case? ?In >> >> theory udev could be temporarily configured with libvirt permissions >> >> for the CD-ROM device while passed through to the guest, but is that >> >> feasible? >> > >> > How about something like this: Add an explicit reopen method to >> > BlockDriver. Make a special block device for passed file descriptors. >> > Pass descriptors in libvirt for CD-ROMs instead of the device paths. >> > The reopen method for file descriptors should notify libvirt about >> > need to pass a reopened descriptor and then block all accesses until a >> > new descriptor is available. This should also solve your earlier >> > problem. >> >> I'm hoping libvirt's behavior can be made to just work rather than >> adding new features to QEMU. ?But perhaps passing file descriptors is >> useful for more than just reopening host devices. ?This would >> basically be a privilege separation model where the QEMU process isn't >> able to open files itself but can request libvirt to open them on its >> behalf. > > It is rather frickin' annoying the way udev resets the ownership > when the media merely changes. If it isn't possible to stop udev > doing this, then i think the only practical thing is to use ACLs > instead of user/group ownership. We wanted to switch to ACLs in > libvirt for other reasons already, but it isn't quite as simple > as it sounds[1] so we've not done it just yet. > > Daniel > > [1] Mostly due to handling upgrades from existing libvirtd while > ? ?VMs are running, and coping with filesystems which don't > ? ?support ACLs (or have them turned of by mount options) I haven't peeked at how udev does it but perhaps the ACLs will be lost or reset across media change too? Daniel, do you know someone from the udev side who we should include in this discussion? Stefan From aliguori at us.ibm.com Mon Apr 4 13:02:26 2011 From: aliguori at us.ibm.com (Anthony Liguori) Date: Mon, 04 Apr 2011 08:02:26 -0500 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <20110404104753.GX13616@redhat.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <20110404104753.GX13616@redhat.com> Message-ID: <4D99C162.7060706@us.ibm.com> On 04/04/2011 05:47 AM, Daniel P. Berrange wrote: >> I'm hoping libvirt's behavior can be made to just work rather than >> adding new features to QEMU. But perhaps passing file descriptors is >> useful for more than just reopening host devices. This would >> basically be a privilege separation model where the QEMU process isn't >> able to open files itself but can request libvirt to open them on its >> behalf. > It is rather frickin' annoying the way udev resets the ownership > when the media merely changes. If it isn't possible to stop udev > doing this, then i think the only practical thing is to use ACLs > instead of user/group ownership. We wanted to switch to ACLs in > libvirt for other reasons already, but it isn't quite as simple > as it sounds[1] so we've not done it just yet. Isn't the root of the problem that you're not running a guest in the expected security context? How much of a leap would it be to spawn a guest with the credentials of the user that created/defined it? Or better yet, to let the user be specified in the XML. Regards, Anthony Liguori > Daniel > > [1] Mostly due to handling upgrades from existing libvirtd while > VMs are running, and coping with filesystems which don't > support ACLs (or have them turned of by mount options) From berrange at redhat.com Mon Apr 4 13:16:39 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 14:16:39 +0100 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D99C162.7060706@us.ibm.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <20110404104753.GX13616@redhat.com> <4D99C162.7060706@us.ibm.com> Message-ID: <20110404131639.GB13616@redhat.com> On Mon, Apr 04, 2011 at 08:02:26AM -0500, Anthony Liguori wrote: > On 04/04/2011 05:47 AM, Daniel P. Berrange wrote: > >>I'm hoping libvirt's behavior can be made to just work rather than > >>adding new features to QEMU. But perhaps passing file descriptors is > >>useful for more than just reopening host devices. This would > >>basically be a privilege separation model where the QEMU process isn't > >>able to open files itself but can request libvirt to open them on its > >>behalf. > >It is rather frickin' annoying the way udev resets the ownership > >when the media merely changes. If it isn't possible to stop udev > >doing this, then i think the only practical thing is to use ACLs > >instead of user/group ownership. We wanted to switch to ACLs in > >libvirt for other reasons already, but it isn't quite as simple > >as it sounds[1] so we've not done it just yet. > > Isn't the root of the problem that you're not running a guest in the > expected security context? That doesn't really have any impact. If a desktop user is logged in, udev may change the ownership to match that user, but if they aren't, then udev may reset it to root:disk. Either way, QEMU may loose permissions to the disk. > How much of a leap would it be to spawn a guest with the credentials > of the user that created/defined it? Or better yet, to let the user > be specified in the XML. That's a completely independent RFE which won't fix this issue in the general case. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From jdenemar at redhat.com Mon Apr 4 13:18:59 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Mon, 4 Apr 2011 15:18:59 +0200 Subject: [libvirt] [PATCH] qemu: Don't fail driver startup with ancient qemu Message-ID: <2e1f2e4705bb467bcf237647706555bf4e97ec1e.1301923139.git.jdenemar@redhat.com> Failure to extract version info (e.g., because qemu binary is so ancient that it doesn't even support -help) shouldn't be considered fatal since we only need it to detect whether qemu supports bootindex option. --- src/qemu/qemu_capabilities.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index f86e7f5..6d2a3f6 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -554,9 +554,10 @@ qemuCapsInitGuest(virCapsPtr caps, !virCapabilitiesAddGuestFeature(guest, "cpuselection", 1, 0)) goto error; - if (qemuCapsExtractVersionInfo(binary, info->arch, NULL, &qemuCaps) < 0 || - (qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX) && - !virCapabilitiesAddGuestFeature(guest, "deviceboot", 1, 0))) + if (qemuCapsExtractVersionInfo(binary, info->arch, + NULL, &qemuCaps) == 0 && + qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX) && + !virCapabilitiesAddGuestFeature(guest, "deviceboot", 1, 0)) goto error; if (hvm) { -- 1.7.4.1 From avi at redhat.com Mon Apr 4 13:22:38 2011 From: avi at redhat.com (Avi Kivity) Date: Mon, 04 Apr 2011 16:22:38 +0300 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> Message-ID: <4D99C61E.3080600@redhat.com> On 04/03/2011 02:57 PM, Stefan Hajnoczi wrote: > In order for media change to work with Linux host CD-ROM it is > necessary to reopen the file (otherwise the inode size will not > refresh, this is an issue with existing kernels). > Maybe we should fix the bug in Linux (and backport as necessary)? I think cd-rom assignment is sufficiently obscure that we can require a fixed kernel instead of providing a workaround. -- error compiling committee.c: too many arguments to function From berrange at redhat.com Mon Apr 4 13:23:59 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 14:23:59 +0100 Subject: [libvirt] [PATCH] qemu: Don't fail driver startup with ancient qemu In-Reply-To: <2e1f2e4705bb467bcf237647706555bf4e97ec1e.1301923139.git.jdenemar@redhat.com> References: <2e1f2e4705bb467bcf237647706555bf4e97ec1e.1301923139.git.jdenemar@redhat.com> Message-ID: <20110404132359.GC13616@redhat.com> On Mon, Apr 04, 2011 at 03:18:59PM +0200, Jiri Denemark wrote: > Failure to extract version info (e.g., because qemu binary is so ancient > that it doesn't even support -help) shouldn't be considered fatal since > we only need it to detect whether qemu supports bootindex option. > --- > src/qemu/qemu_capabilities.c | 7 ++++--- > 1 files changed, 4 insertions(+), 3 deletions(-) What version QEMU doesn't support -help ? We only aim to work with QEMU >= 0.9.0 and I'm fairly sure that has -help support. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From veillard at redhat.com Mon Apr 4 13:30:58 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 4 Apr 2011 21:30:58 +0800 Subject: [libvirt] Release of libvirt-0.9.0 Message-ID: <20110404133058.GT24385@redhat.com> As scheduled, libvirt 0.9.0 was tagged and pushed today, it's available from FTP at: ftp://libvirt.org/libvirt/ This is a large release w.r.t. the amount of features and changes, and well worth bumping the middle version number. We are also getting closer to a 1.0.0 release ! Features: - Support cputune cpu usage tuning (Osier Yang and Nikunj A. Dadhania) - Add public APIs for storage volume upload/download (Daniel P. Berrange) - Add public API for setting migration speed on the fly (Daniel P. Berrange) - Add libxenlight driver (Jim Fehlig and Markus Gro?) - qemu: support migration to fd (Eric Blake) - libvirt: add virDomain{Get,Set}BlkioParameters (Gui Jianfeng) - setmem: introduce a new libvirt API (virDomainSetMemoryFlags) (Taku Izumi) - Expose event loop implementation as a public API (Daniel P. Berrange) - Dump the debug buffer to libvirtd.log on fatal signal (Daniel Veillard) - Audit support (Eric Blake) Documentation: - fix typo (Eric Blake) - correct invalid xml (Eric Blake) - virsh: Fix documentation for memtune command (Jiri Denemark) - Fix several formatting mistakes in doc (Michal Privoznik) - mention C89 syntax preferences (Eric Blake) - document recent hook additions (Eric Blake) - Update on the goal page (Daniel Veillard) - Document first release with spice and qxl (Cole Robinson) - Add schema definition for imagelabel (Osier Yang) - update virGetVersion description (Tiziano Mueller) - Improve logging documentation including the debug buffer (Daniel Veillard) - update windows page for initial libvirt 0.8.8 installer (Justin Clift) - formatdomain.html.in: Fix spelling PIC->PCI (Philipp Hahn) - fix missing

    (Eric Blake) - documenting the 802.1Qbg parameters of a 'direct' interface (Gerhard Stenzel) - silence warnings about generated API docs (Eric Blake) - document for interfaces (Eric Blake) - correct range of default NAT subnet (Eric Blake) - formatdomain: Add release info for disk attributes (Cole Robinson) - Fix spelling mistake: seek (Philipp Hahn) - maint: fix grammar in error message (Eric Blake) Portability: - virsh: fix mingw failure on creating nonblocking pipe (Eric Blake) - Remove iohelper on Win32 since it is not required (Daniel P. Berrange) - Fix domain events C example on Win32 (Daniel P. Berrange) - build: fix compilation on mingw (Eric Blake) - util: use SCM_RIGHTS in virFileOperation when needed (Eric Blake) - Don't use INT64_MAX in libvirt.h because it requires stdint.h (Matthias Bolte) - libvirtd: Remove indirect linking (Guido G?nther) - build: avoid compiler warning on cygwin (Eric Blake) - build: fix build on cygwin (Eric Blake) - build: fix building error when building without libvirtd (Wen Congyang) - virsh: Remove indirect link against libxml2 (Guido G?nther) - Fix build on cygwin (Daniel Veillard) - Add check for kill() to fix build of cgroups on win32 (Daniel P. Berrange) - build: fix broken mingw cross-compilation (Eric Blake) Bug fixes: - fix memory leak in qemuProcessHandleGraphics() (Wen Congyang) - do not lock vm while allocating memory (Wen Congyang) - Fix libxl driver startup (Daniel Veillard) - qemu: Ignore libvirt debug messages in qemu log (Jiri Denemark) - qemu: Fix improper logic of qemuCgroupSetup (Osier Yang) - free tmp after unlinking it (Wen Congyang) - qemu: Fix media eject with qemu-0.12.* (Jiri Denemark) - check whether qemuMonitorJSONHMP() failed (Wen Congyang) - do not send monitor command after monitor meet error (Wen Congyang) - qemu: unlock qemu driver before return from domain save (Hu Tao) - qemu: fix regression with fd labeling on migration (Eric Blake) - Ignore return value of virDomainObjUnref (Markus Gro?) - Fix infinite loop in daemon if client quits with multiple streams open (Daniel P. Berrange) - qemu: fix regression that hangs on save failure (Eric Blake) - qemu: fix restoring a compressed save image (Eric Blake) - util: allow clearing cloexec bit (Eric Blake) - logging: always NUL-terminate circular buffer (Eric Blake) - tests: don't alter state in $HOME (Eric Blake) - qemu: don't restore state label twice (Eric Blake) - Fix syntax error in configure.ac (Osier Yang) - remote: Don't leak gnutls session on negotiation error (Matthias Bolte) - hooks: fix regression in previous patch (Eric Blake) - Add missing { for qemudDomainInterfaceStats (Philipp Hahn) - daemon: Avoid resetting errors before they are reported (Jiri Denemark) - fix the check of the output of monitor command 'device_add' (Wen Congyang) - Make error reporting in libvirtd thread safe (Jiri Denemark) - update domain status forcibly even if attach a device failed (Wen Congyang) - util: Fix return value for virJSONValueFromString if it fails (Osier Yang) - Initialization error of qemuCgroupData in Qemu host usb hotplug (Wen Congyang) - build: fix missing initializer (Eric Blake) - Fix uninitialized variable & error reporting in LXC veth setup (Daniel P. Berrange) - udev: fix regression with qemu:///session (Eric Blake) - logging: fix off-by-one bug (Eric Blake) - do not report OOM error when prepareCall() failed (Wen Congyang) - Don't return an error on failure to create blkio controller (Hu Tao) - qemu: respect locking rules (Eric Blake) - openvz: fix a simple bug in openvzListDefinedDomains() (Jean-Baptiste Rouault) - Fix delayed event delivery when SASL is active (Daniel P. Berrange) - qemu: Fix copy&paste error messages in text monitor (Jiri Denemark) - do not unref obj in qemuDomainObjExitMonitor* (Wen Congyang) - qemu: check driver name while attaching disk (Wen Congyang) - remote: Add missing virCondDestroy calls (Matthias Bolte) - build: improve rpm generation for distro backports (Eric Blake) - storage: Fix a problem which will cause libvirtd crashed (Osier Yang) - Fix misc bugs in virCommandPtr (Daniel P. Berrange) - libvirt: fix a simple bug in virDomainSetMemoryFlags() (Taku Izumi) - qemu: Check the unsigned integer overflow (Osier Yang) - audit: eliminate potential null pointer deref when auditing macvtap devices (Laine Stump) - network driver: don't send default route to clients on isolated networks (Laine Stump) - virsh: Free stream when shutdown console (Osier Yang) - Add missing checks for read only connections (Guido G?nther) - qemu: fix -global argument usage (Eric Blake) - Make sure we reset the umask on the error path (Guido G?nther) - qemu: Stop guest CPUs before creating a snapshot (Jiri Denemark) - qemu: Escape snapshot name passed to {save,load,del}vm (Jiri Denemark) - qemu: Fix warnings in event handlers (Jiri Denemark) - storage: Update qemu-img flag checking (Osier Yang) - Make sure the rundir is accessible by the user (Guido G?nther) - Fix a wrong error message thrown to user (Hu Tao) - unlock eventLoop before calling callback function (Wen Congyang) - fixes for several memory leaks (Phil Petty) - Fix a counter bug in the log buffer (Daniel Veillard) - qemu: avoid corruption of domain hashtable and misuse of freed domains (Laine Stump) - qemu: Add missing lock of virDomainObj before calling virDomainUnref (Laine Stump) - esx: Escape password for XML (Matthias Bolte) - util: correct retry path in virFileOperation (Eric Blake) - util: Allow removing hash entries in virHashForEach (Jiri Denemark) - qemu: avoid double close on domain restore (Eric Blake) - Fix port value parsing for serial and parallel ports (Michal Novotny) - Fix off-by-1 in virFileAbsPath. (Daniel P. Berrange) - security: avoid memory leak (Eric Blake) - protect the scsi controller to be deleted when it is in use (Wen Congyang) - virsh: freecell --all getting wrong NUMA nodes count (Michal Privoznik) - remove duplicated call to reportOOMError (Christophe Fergeau) Improvements: - Make check_fc_host() and check_vport_capable() usable as rvalues (Guido G?nther) - maint: avoid locale-sensitivity in string case comparisons (Eric Blake) - extend logging to record configuration-related changes (Naoya Horiguchi) - Add libvirt_iohelper to spec file (Daniel Veillard) - cputune: New tests for cputune XML (Osier Yang) - cputune: Support cputune for xend driver (Osier Yang) - cputune: Support cputune for lxc driver (Osier Yang) - cputune: Support cputune for qemu driver (Osier Yang) - cputune: Implementations of parsing and formating cputune xml (Osier Yang) - cputune: Add data structures presenting cputune XML (Osier Yang) - cputune: Add document for cputune XML (Osier Yang) - cputune: Add XML schema for cputune xml (Osier Yang) - qemu: improve error message on failed fd transfer (Eric Blake) - maint: ignore new built file (Eric Blake) - Add domainSuspend/Resume to libxl driver (Markus Gro?) - Add domainGetOSType to libxl driver (Markus Gro?) - Add domainGetSchedulerType to libxl driver (Markus Gro?) - Implements domainXMLTo/FromNative in libxl driver (Markus Gro?) - Add vcpu functions to libxl driver (Markus Gro?) - List authors in copyright headers (Markus Gro?) - Add event callbacks to libxl driver (Markus Gro?) - Remote protocol support for storage vol upload/download APIs (Daniel P. Berrange) - Support volume data upload/download APIs in storage driver (Daniel P. Berrange) - Add vol-upload and vol-download commands to virsh (Daniel P. Berrange) - Enhance the streams helper to support plain file I/O (Daniel P. Berrange) - Update event loop example programs to demonstrate best practice (Daniel P. Berrange) - qemu: support fd: migration with compression (Eric Blake) - qemu: skip granting access during fd migration (Eric Blake) - qemu: consolidate migration to file code (Eric Blake) - qemu: use common API for reading difficult files (Eric Blake) - qemu, storage: improve type safety (Eric Blake) - util: adjust indentation in previous patch (Eric Blake) - util: rename virFileOperation to virFileOpenAs (Eric Blake) - storage: simplify fd handling (Eric Blake) - qemu: simplify domain save fd handling (Eric Blake) - qemu: allow simple domain save to use fd: protocol (Eric Blake) - Update of localisations, switch to transifex (Daniel Veillard) - build: shorten libxenlight summary for consistent alignment (Eric Blake) - command: add virCommandAbort for cleanup paths (Eric Blake) - command: don't mix RunAsync and daemons (Eric Blake) - command: properly diagnose process exit via signal (Eric Blake) - Add memory functions to libxl driver (Markus Gro?) - build: enforce reference count checking (Eric Blake) - maint: prohibit access(,X_OK) (Eric Blake) - Get cpu time and current memory balloon from libxl (Markus Gro?) - build: nuke all .x-sc* files, and fix VPATH syntax-check (Eric Blake) - command: reject pidfile on non-daemon (Eric Blake) - rpm: add missing dependencies (Eric Blake) - rpm: separate runtime and build requirements (Eric Blake) - qemu: simplify monitor callbacks (Eric Blake) - 8021Qbh: use preassociate-rr during the migration prepare stage (Roopa Prabhu) - Wire up virDomainMigrateSetSpeed into QEMU driver (Daniel P. Berrange) - Wire up virDomainMigrateSetSpeed for the remote RPC driver (Daniel P. Berrange) - maint: update authors (Eric Blake) - Disable libxl build in RPM on Fedora < 16 (Daniel P. Berrange) - qemu: fallback to HMP drive_add/drive_del (Hu Tao) - qemu: Only use HMP passthrough if it is supported (Jiri Denemark) - qemu: Detect support for HMP passthrough (Jiri Denemark) - qemu: add two hook script events "prepare" and "release" (Thibault Vincent) - qemu: simplify interface fd handling in monitor (Eric Blake) - qemu: simplify PCI configfd handling in monitor (Eric Blake) - qemu: simplify monitor fd error handling (Eric Blake) - util: guarantee sane errno in virFileIsExecutable (Eric Blake) - Don't build libxenlight driver for Xen 4.0 (Jim Fehlig) - network driver: log error and abort network startup when radvd isn't found (Laine Stump) - build: translate changes in previous patch (Eric Blake) - Ensure binary is resolved wrt $PATH in virExec (Daniel P. Berrange) - util: Forbid calling hash APIs from iterator callback (Jiri Denemark) - Avoid taking lock in libvirt debug dump (Daniel Veillard) - unlock the monitor when unwatching the monitor (Wen Congyang) - Add vim configuration that makes vim auto-indent code (Hu Tao) - virsh: fix memtune's help message for swap_hard_limit (Nikunj A. Dadhania) - Add PCI sysfs reset access (Alex Williamson) - Support Xen sysctl v8, domctl v7 (Jim Fehlig) - macvtap: log an error if on failure to connect to netlink socket (Laine Stump) - qemu: improve efficiency of dd during snapshots (Eric Blake) - virsh: allow empty string arguments (Eric Blake) - qemu: Fallback to HMP when cpu_set QMP command is not found (Wen Congyang) - Change message for VIR_FROM_RPC error domain (Daniel P. Berrange) - Add compat function for geteuid() (Daniel P. Berrange) - Add virSetBlocking() to allow O_NONBLOCK to be toggle on or off (Daniel P. Berrange) - qemu: use more appropriate error (Eric Blake) - Make LXC container startup/shutdown/I/O more robust (Daniel P. Berrange) - Allow to dynamically set the size of the debug buffer (Daniel Veillard) - qemu: consolidate duplicated monitor migration code (Eric Blake) - qemu: use lighter-weight fd:n on incoming tunneled migration (Eric Blake) - Fix performance problem of virStorageVolCreateXMLFrom() (Minoru Usui) - libvirt-guests: avoid globbing when splitting $URIS (Eric Blake) - libvirt-guest.init: quoting variables (Philipp Hahn) - virsh: Insert error messages to avoid a quiet abortion of commands (Michal Privoznik) - python: Use hardcoded python path in libvirt.py (Jiri Denemark) - virsh: Allow starting domains by UUID (Jiri Denemark) - network driver: Use a separate dhcp leases file for each network (Laine Stump) - network driver: Start dnsmasq even if no dhcp ranges/hosts are specified. (Laine Stump) - libvirt-guest.init: handle domain name with spaces (Philipp Hahn) - domain.rng vs. formatdomain.html#elementsUSB (Philipp Hahn) - Ignore backing file errors in FS storage pool (Philipp Hahn) - remote-protocol: implement new BlkioParameters API (Gui Jianfeng) - virsh: Adding blkiotune command to virsh tool (Gui Jianfeng) - qemu: implement new BlkioParameters API (Gui Jianfeng) - libvirt: implements virDomain{Get,Set}BlkioParameters (Gui Jianfeng) - setmem: add the new options to "virsh setmem" command (Taku Izumi) - setmem: implement the remote protocol to address the new API (Taku Izumi) - setmem: implement the code to address the new API in the qemu driver (Taku Izumi) - audit: audit use of /dev/net/tun, /dev/tapN, /dev/vhost-net (Eric Blake) - qemu: don't request cgroup ACL access for /dev/net/tun (Eric Blake) - qemu: support vhost in attach-interface (Eric Blake) - qemu: Refactor qemuDomainSnapshotCreateXML (Jiri Denemark) - qemu: Fallback to HMP for snapshot commands (Jiri Denemark) - qemu: Setup infrastructure for HMP passthrough (Jiri Denemark) - qemu: Replace deprecated option of qemu-img (Osier Yang) - audit: also audit cgroup ACL permissions (Eric Blake) - cgroup: allow fine-tuning of device ACL permissions (Eric Blake) - audit: rename remaining qemu audit functions (Eric Blake) - audit: also audit cgroup controller path (Eric Blake) - audit: split cgroup audit types to allow more information (Eric Blake) - audit: tweak audit messages to match conventions (Eric Blake) - Don't overwrite virRun error messages (Cole Robinson) - virsh: Change option parsing functions to return tri-state information (Michal Privoznik) - virsh: change vshCommandOptString return type and fix const-correctness (Michal Privoznik) - support to detach USB disk (Wen Congyang) - rename qemuDomainDetachSCSIDiskDevice to qemuDomainDetachDiskDevice (Wen Congyang) - qemu_hotplug: Reword error if spice password change not available (Cole Robinson) - Move event code out of the daemon/ into src/util/ (Daniel P. Berrange) - Convert daemon/virsh over to use primary event APIs, rather than impl (Daniel P. Berrange) - Cleaning up some of the logging code (Daniel Veillard) - qemu: Support vram for video of qxl type (Osier Yang) - Add an an internal API for emergency dump of debug buffer (Daniel Veillard) - Add logrotate support for libvirtd.log (Daniel Veillard) - Change default log policy to libvirtd.log instead of syslog (Daniel Veillard) - Force all logs to go to the round robbin memory buffer (Daniel Veillard) - AUTHORS: adjust to preferred spelling (KAMEZAWA Hiroyuki) - Pass virSecurityManagerPtr to virSecurityDAC{Set, Restore}ChardevCallback (Soren Hansen) - maint: update to latest gnulib (Eric Blake) - Attempt to improve an error message (Daniel P. Berrange) - add additional event debug points (Daniel P. Berrange) - qemu: only request sound cgroup ACL when required (Eric Blake) - Add support for multiple serial ports into the Xen driver (Michal Novotny) - Add APIs for killing off processes inside a cgroup (Daniel P. Berrange) - Allow hash tables to use generic pointers as keys (Daniel P. Berrange) - Remove deallocator parameter from hash functions (Daniel P. Berrange) - Make commandtest more robust wrt its execution environment (Daniel P. Berrange) - audit: audit qemu pci and usb device passthrough (Eric Blake) - audit: audit qemu memory and vcpu adjusments (Eric Blake) - audit: add qemu hooks for auditing cgroup events (Eric Blake) - audit: prepare qemu for listing vm in cgroup audits (Eric Blake) - cgroup: determine when skipping non-devices (Eric Blake) - virExec: avoid uninitialized memory usage (Eric Blake) - Allow 32-on-64 execution for LXC guests (Daniel P. Berrange) - Put into internal.h so it is available everywhere (Daniel P. Berrange) - qemu: Switch over command line capabilities to virBitmap (Jiri Denemark) - qemu: Rename qemud\?CmdFlags to qemuCaps (Jiri Denemark) - qemu: Use helper functions for handling cmd line capabilities (Jiri Denemark) - qemu: Rename QEMUD_CMD_FLAG_* to QEMU_CAPS_* (Jiri Denemark) - util: Add API for converting virBitmap into printable string (Jiri Denemark) - util: Use unsigned long as a base type for virBitmap (Jiri Denemark) - Expose name + UUID to LXC containers via env variables (Daniel P. Berrange) - Fix discard of expected errors (Daniel P. Berrange) - Fix group/mode for /dev/pts inside LXC container (Daniel P. Berrange) - 802.1Qbh: Delay IFF_UP'ing interface until migration final stage (Roopa Prabhu) - storage: make debug log more useful (Osier Yang) - virsh: replace vshPrint with vshPrintExtra for snapshot list Otherwise extra information will be printed even if "--quiet" is specified. (Osier Yang) - check device-mapper when building with mpath or disk storage driver (Wen Congyang) - build: add dependency on gnutls-utils (Eric Blake) - Renamed functions in xenxs (Markus Gro?) - Moved XM formatting functions to xenxs (Markus Gro?) - Moved XM parsing functions to xenxs (Markus Gro?) - Moved SEXPR formatting functions to xenxs (Markus Gro?) - Moved SEXPR parsing functions to xenxs (Markus Gro?) - Moved some SEXPR functions from xen-unified (Markus Gro?) - Moved SEXPR unit to utils (Markus Gro?) - virt-*-validate.in: quote all variable references (Dan Kenigsberg) - virt-pki-validate: behave when CERTTOOL is missing (Dan Kenigsberg) - autobuild.sh: use VPATH build (Eric Blake) - maint: fix 'make dist' in VPATH build (Eric Blake) - build: don't require pod2man for tarball builds (Eric Blake) - hash: make virHashFree more free-like (Eric Blake) - build: Fix API docs generation in VPATH build (Jiri Denemark) - Remove all object hashtable caches from virConnectPtr (Daniel P. Berrange) - nwfilter: enable rejection of packets (Stefan Berger) - Drop empty argument from dnsmasq call (Guido G?nther) - esx: Ignore malformed host UUID from BIOS (Matthias Bolte) - build: speed up non-maintainer builds (Eric Blake) - build: recompute symbols after changing configure options (Eric Blake) - Requires gettext for client package (Osier Yang) - Do not add drive 'boot=on' param when a kernel is specified (Jim Fehlig) - factor common code in virHashAddEntry and virHashUpdateEntry (Christophe Fergeau) - add hash table rebalancing in virHashUpdateEntry (Christophe Fergeau) - hash: modernize debug code (Eric Blake) - build: improve 'make install' for VPATH builds (Eric Blake) - check more error info about whether drive_add failed (Wen Congyang) - logging: make VIR_ERROR and friends preserve errno (Eric Blake) - maint: avoid 'make syntax-check' from tarball (Eric Blake) - Give each virtual network bridge its own fixed MAC address (Laine Stump) - Allow brAddTap to create a tap device that is down (Laine Stump) - Add txmode attribute to interface XML for virtio backend (Laine Stump) - Restructure domain struct interface "driver" data for easier expansion (Laine Stump) - build: Fix VPATH build (Jiri Denemark) - storage: Allow to delete device mapper disk partition (Osier Yang) Cleanups: - The next release is 0.9.0 not 0.8.9 (Daniel Veillard) - maint: use space, not tab, in remote_protocol-structs (Eric Blake) - Remove the Open Nebula driver (Daniel P. Berrange) - domain_conf: drop unused ref-count in snapshot object (Eric Blake) - Update the set of maintainers for the project (Daniel Veillard) - Make virDomainObjParseNode() static (Hu Tao) - maint: make spacing in .sh files easier (Eric Blake) - network driver: Fix indentation from previous commit (Laine Stump) - qemu: Rename qemuMonitorCommandWithHandler as qemuMonitorText* (Jiri Denemark) - qemu: Rename qemuMonitorCommand{,WithFd} as qemuMonitorHMP* (Jiri Denemark) - maint: avoid long lines in more tests (Eric Blake) - maint: kill all remaining uses of old DEBUG macro (Eric Blake) - maint: Expand tabs in python code (Jiri Denemark) - remove space between function name and ( (Christophe Fergeau) - don't check for NULL before calling virHashFree (Christophe Fergeau) - remove no longer needed calls to virReportOOMError (Christophe Fergeau) - Move all the QEMU migration code to a new file (Daniel P. Berrange) - Split all QEMU process mangement code into separate file (Daniel P. Berrange) Thanks to everybody who helped one way or another for this release ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From jdenemar at redhat.com Mon Apr 4 13:37:32 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Mon, 4 Apr 2011 15:37:32 +0200 Subject: [libvirt] [PATCH] qemu: Don't fail driver startup with ancient qemu In-Reply-To: <20110404132359.GC13616@redhat.com> References: <2e1f2e4705bb467bcf237647706555bf4e97ec1e.1301923139.git.jdenemar@redhat.com> <20110404132359.GC13616@redhat.com> Message-ID: <20110404133732.GH389283@orkuz.home> On Mon, Apr 04, 2011 at 14:23:59 +0100, Daniel P. Berrange wrote: > On Mon, Apr 04, 2011 at 03:18:59PM +0200, Jiri Denemark wrote: > > Failure to extract version info (e.g., because qemu binary is so ancient > > that it doesn't even support -help) shouldn't be considered fatal since > > we only need it to detect whether qemu supports bootindex option. > > --- > > src/qemu/qemu_capabilities.c | 7 ++++--- > > 1 files changed, 4 insertions(+), 3 deletions(-) > > What version QEMU doesn't support -help ? > > We only aim to work with QEMU >= 0.9.0 and I'm fairly sure > that has -help support. An ancient one, 0.6.0. But that was just an example. Extracting version info may fail for a bunch of reasons. The main thing is that it shouldn't fail qemu driver startup since that results in libvirtd startup failure. Jirka From anthony at codemonkey.ws Mon Apr 4 13:38:53 2011 From: anthony at codemonkey.ws (Anthony Liguori) Date: Mon, 04 Apr 2011 08:38:53 -0500 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D99C61E.3080600@redhat.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> Message-ID: <4D99C9ED.3020602@codemonkey.ws> On 04/04/2011 08:22 AM, Avi Kivity wrote: > On 04/03/2011 02:57 PM, Stefan Hajnoczi wrote: >> In order for media change to work with Linux host CD-ROM it is >> necessary to reopen the file (otherwise the inode size will not >> refresh, this is an issue with existing kernels). >> > > Maybe we should fix the bug in Linux (and backport as necessary)? > > I think cd-rom assignment is sufficiently obscure that we can require > a fixed kernel instead of providing a workaround. Do reads fail after CD change? Or do they succeed and the size is just reported incorrectly? If it's the later, I'd agree that it needs fixing in the kernel. If it's the former, I'd say it's clearly a feature. Regards, Anthony Liguori From jdenemar at redhat.com Mon Apr 4 13:46:31 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Mon, 4 Apr 2011 15:46:31 +0200 Subject: [libvirt] [PATCH] qemu: Rewrite LOOKUP_PTYS macro into a function Message-ID: <6583e184fb3f616c15ec4bc42f1af58fff320a8b.1301924390.git.jdenemar@redhat.com> The macro is huge and gives us nothing but headache when maintaining it. --- The reason for this patch is not that I'm going to modify anything in the code. It's that I was working in the area and noticed this huge macro. src/qemu/qemu_process.c | 102 ++++++++++++++++++++++++++++------------------- 1 files changed, 61 insertions(+), 41 deletions(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 90fcea0..53a42a5 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -895,51 +895,71 @@ qemuProcessExtractTTYPath(const char *haystack, } static int +qemuProcessLookupPTYs(virDomainChrDefPtr *devices, + int count, + const char *prefix, + virHashTablePtr paths) +{ + int i; + + for (i = 0 ; i < count ; i++) { + virDomainChrDefPtr chr = devices[i]; + if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) { + char id[16]; + const char *path; + + if (snprintf(id, sizeof(id), "%s%d", prefix, i) >= sizeof(id)) + return -1; + + path = (const char *) virHashLookup(paths, id); + if (path == NULL) { + if (chr->source.data.file.path == NULL) { + /* neither the log output nor 'info chardev' had a + * pty path for this chardev, report an error + */ + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("no assigned pty for device %s"), id); + return -1; + } else { + /* 'info chardev' had no pty path for this chardev, + * but the log output had, so we're fine + */ + continue; + } + } + + VIR_FREE(chr->source.data.file.path); + chr->source.data.file.path = strdup(path); + + if (chr->source.data.file.path == NULL) { + virReportOOMError(); + return -1; + } + } + } + + return 0; +} + +static int qemuProcessFindCharDevicePTYsMonitor(virDomainObjPtr vm, virHashTablePtr paths) { - int i; + if (qemuProcessLookupPTYs(vm->def->serials, vm->def->nserials, + "serial", paths) < 0) + return -1; + + if (qemuProcessLookupPTYs(vm->def->parallels, vm->def->nparallels, + "parallel", paths) < 0) + return -1; -#define LOOKUP_PTYS(array, arraylen, idprefix) \ - for (i = 0 ; i < (arraylen) ; i++) { \ - virDomainChrDefPtr chr = (array)[i]; \ - if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) { \ - char id[16]; \ - \ - if (snprintf(id, sizeof(id), idprefix "%i", i) >= sizeof(id)) \ - return -1; \ - \ - const char *path = (const char *) virHashLookup(paths, id); \ - if (path == NULL) { \ - if (chr->source.data.file.path == NULL) { \ - /* neither the log output nor 'info chardev' had a */ \ - /* pty path for this chardev, report an error */ \ - qemuReportError(VIR_ERR_INTERNAL_ERROR, \ - _("no assigned pty for device %s"), id); \ - return -1; \ - } else { \ - /* 'info chardev' had no pty path for this chardev, */\ - /* but the log output had, so we're fine */ \ - continue; \ - } \ - } \ - \ - VIR_FREE(chr->source.data.file.path); \ - chr->source.data.file.path = strdup(path); \ - \ - if (chr->source.data.file.path == NULL) { \ - virReportOOMError(); \ - return -1; \ - } \ - } \ - } - - LOOKUP_PTYS(vm->def->serials, vm->def->nserials, "serial"); - LOOKUP_PTYS(vm->def->parallels, vm->def->nparallels, "parallel"); - LOOKUP_PTYS(vm->def->channels, vm->def->nchannels, "channel"); - if (vm->def->console) - LOOKUP_PTYS(&vm->def->console, 1, "console"); -#undef LOOKUP_PTYS + if (qemuProcessLookupPTYs(vm->def->channels, vm->def->nchannels, + "channel", paths) < 0) + return -1; + + if (vm->def->console && + qemuProcessLookupPTYs(&vm->def->console, 1, "console", paths) < 0) + return -1; return 0; } -- 1.7.4.1 From avi at redhat.com Mon Apr 4 13:49:40 2011 From: avi at redhat.com (Avi Kivity) Date: Mon, 04 Apr 2011 16:49:40 +0300 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D99C9ED.3020602@codemonkey.ws> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> Message-ID: <4D99CC74.9070703@redhat.com> On 04/04/2011 04:38 PM, Anthony Liguori wrote: > On 04/04/2011 08:22 AM, Avi Kivity wrote: >> On 04/03/2011 02:57 PM, Stefan Hajnoczi wrote: >>> In order for media change to work with Linux host CD-ROM it is >>> necessary to reopen the file (otherwise the inode size will not >>> refresh, this is an issue with existing kernels). >>> >> >> Maybe we should fix the bug in Linux (and backport as necessary)? >> >> I think cd-rom assignment is sufficiently obscure that we can require >> a fixed kernel instead of providing a workaround. > > Do reads fail after CD change? Or do they succeed and the size is > just reported incorrectly? > > If it's the later, I'd agree that it needs fixing in the kernel. If > it's the former, I'd say it's clearly a feature. > Even if it's a documented or intentional feature, we can add an ioctl to "refresh" the device with up-to-date data. -- error compiling committee.c: too many arguments to function From aliguori at us.ibm.com Mon Apr 4 14:19:36 2011 From: aliguori at us.ibm.com (Anthony Liguori) Date: Mon, 04 Apr 2011 09:19:36 -0500 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <20110404131639.GB13616@redhat.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <20110404104753.GX13616@redhat.com> <4D99C162.7060706@us.ibm.com> <20110404131639.GB13616@redhat.com> Message-ID: <4D99D378.8030206@us.ibm.com> On 04/04/2011 08:16 AM, Daniel P. Berrange wrote: > That doesn't really have any impact. If a desktop user is logged > in, udev may change the ownership to match that user, but if they > aren't, then udev may reset it to root:disk. Either way, QEMU > may loose permissions to the disk. Then if you create a guest without being in the 'disk' group, it'll fail. That's pretty expected AFAICT. But with libvirt today, when you launch a guest, your security context doesn't matter and there's no way you can control what context the guest gets. libvirt is essentially creating it's own authorization mechanism. Supporting ACLs goes much further down that path. >> How much of a leap would it be to spawn a guest with the credentials >> of the user that created/defined it? Or better yet, to let the user >> be specified in the XML. > That's a completely independent RFE which won't fix this issue in > the general case. I think it really does. Regards, Anthony Liguori > Regards, > Daniel From berrange at redhat.com Mon Apr 4 14:26:12 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 15:26:12 +0100 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D99D378.8030206@us.ibm.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <20110404104753.GX13616@redhat.com> <4D99C162.7060706@us.ibm.com> <20110404131639.GB13616@redhat.com> <4D99D378.8030206@us.ibm.com> Message-ID: <20110404142612.GD13616@redhat.com> On Mon, Apr 04, 2011 at 09:19:36AM -0500, Anthony Liguori wrote: > On 04/04/2011 08:16 AM, Daniel P. Berrange wrote: > >That doesn't really have any impact. If a desktop user is logged > >in, udev may change the ownership to match that user, but if they > >aren't, then udev may reset it to root:disk. Either way, QEMU > >may loose permissions to the disk. > > Then if you create a guest without being in the 'disk' group, it'll > fail. That's pretty expected AFAICT. We don't *ever* want to put QEMU in the 'disk' group because that gives it access to any disk on the system in general. > But with libvirt today, when you launch a guest, your security > context doesn't matter and there's no way you can control what > context the guest gets. libvirt is essentially creating it's own > authorization mechanism. Supporting ACLs goes much further down > that path. > > >>How much of a leap would it be to spawn a guest with the credentials > >>of the user that created/defined it? Or better yet, to let the user > >>be specified in the XML. > >That's a completely independent RFE which won't fix this issue in > >the general case. > > I think it really does. Nope it doesn't. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From veillard at redhat.com Mon Apr 4 14:42:21 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 4 Apr 2011 22:42:21 +0800 Subject: [libvirt] [PATCH 1/2] extend logging to record configuration-related events on host machine In-Reply-To: <1301300027-5858-2-git-send-email-n-horiguchi@ah.jp.nec.com> References: <1301300027-5858-1-git-send-email-n-horiguchi@ah.jp.nec.com> <1301300027-5858-2-git-send-email-n-horiguchi@ah.jp.nec.com> Message-ID: <20110404144221.GU24385@redhat.com> [ OOPs actually I wrote this reply wednesday last week but forgot to send it, sorry , Daniel ] On Mon, Mar 28, 2011 at 05:13:46PM +0900, Naoya Horiguchi wrote: > Currently libvirt's logging is so poor that it's difficult to determine > what was happening when a proglem occurred (especially on someone's Actually libvirt logging is fairly complete, but the default logging at the INFO level is not complete, which can be a problem for a prosteriori analysis. http://libvirt.org/logging.html I tried to fix this for serious problems like crashes https://www.redhat.com/archives/libvir-list/2011-March/msg00072.html but for continuous default logging, yeah we could be a bit more verbose > machines you don't know the detail.) This patch helps us to do that > by making additional logging available for the following events: > > creating/defining/undefining domains > creating/defining/undefining/starting/stopping networks > creating/defining/undefining/starting/stopping storage pools > creating/defining/undefining/starting/stopping storage volumes. Okay, makes sense to me. ACK, > Signed-off-by: Naoya Horiguchi > --- > src/network/bridge_driver.c | 4 ++++ > src/qemu/qemu_driver.c | 5 ++++- > src/storage/storage_driver.c | 12 ++++++++++++ > 3 files changed, 20 insertions(+), 1 deletions(-) > > diff --git v0.8.8/src/network/bridge_driver.c v0.8.8/src/network/bridge_driver.c Note: your patch didn't applied cleanly because you developped it against a released versions, it's better to do this against libvirt git head. I rebased it solving the couple of conflict, it was easy, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From anthony at codemonkey.ws Mon Apr 4 14:43:44 2011 From: anthony at codemonkey.ws (Anthony Liguori) Date: Mon, 04 Apr 2011 09:43:44 -0500 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <20110404142612.GD13616@redhat.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <20110404104753.GX13616@redhat.com> <4D99C162.7060706@us.ibm.com> <20110404131639.GB13616@redhat.com> <4D99D378.8030206@us.ibm.com> <20110404142612.GD13616@redhat.com> Message-ID: <4D99D920.1040800@codemonkey.ws> On 04/04/2011 09:26 AM, Daniel P. Berrange wrote: > On Mon, Apr 04, 2011 at 09:19:36AM -0500, Anthony Liguori wrote: >> On 04/04/2011 08:16 AM, Daniel P. Berrange wrote: >>> That doesn't really have any impact. If a desktop user is logged >>> in, udev may change the ownership to match that user, but if they >>> aren't, then udev may reset it to root:disk. Either way, QEMU >>> may loose permissions to the disk. >> Then if you create a guest without being in the 'disk' group, it'll >> fail. That's pretty expected AFAICT. > We don't *ever* want to put QEMU in the 'disk' group because > that gives it access to any disk on the system in general. If that's what the user wants to do, what's the problem with doing it? Setting the global user/group is not enough because just because you have one VM that you want in disk doesn't mean you want all of them in disk. And to be clear, if you could do this today, there wouldn't be a problem here in terms of QEMU just reopening the file. Regards, Anthony Liguori Regards, Anthony Liguori From berrange at redhat.com Mon Apr 4 14:55:26 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 15:55:26 +0100 Subject: [libvirt] [PATCH 2/2] qemu: extend logging to record guest configuration events In-Reply-To: <1301300027-5858-3-git-send-email-n-horiguchi@ah.jp.nec.com> References: <1301300027-5858-1-git-send-email-n-horiguchi@ah.jp.nec.com> <1301300027-5858-3-git-send-email-n-horiguchi@ah.jp.nec.com> Message-ID: <20110404145526.GE13616@redhat.com> On Mon, Mar 28, 2011 at 05:13:47PM +0900, Naoya Horiguchi wrote: > The following events can be logged onto /var/log/libvirt/qemu/.log: > > starting/shutting down/suspending/resuming/migrating domains > changing the amount of memory > changing the number of VCPUs > inserting/ejecting a media into/from CDROM/Floppy devices > attaching/detaching PCI/SCSI/USB devices (including NICs and disks.) > > This patch generalizes qemudLog*() introduced in commit 93bc093ac > to handle the whole range of qemu driver's events. > > This is useful for the same reason as explainged in the previous patch. I think we need to think about the question of logging in a more thorough way. - libvirt.c: Logs invocation of every API call - qemu/driver.c/qemu_audit.c: Logs major lifecycle changes & any config change that is related host resources - virterror.c: Logs any API call that results in an error - qemu_driver.c: Logs a set of lifecycle/config changes (your previous patch 1/2) at VIR_INFO - qemu_driver.c: Logs a different set of lifecycle/config changes in /var/log/libvirt/qemu/.loog I don't think the latter two are particularly great because they are only cover a fraction of the API calls in the QEMU driver. libvirt.c has full logging cover, but it only covers API calls, it doesn't indicate whether it was successful or failed. For SystemTAP, we likely want to add probes to libvirt.c which will log initial parameters, and the return values. Our SystemTAP probe macros also generate log statements. A further complication is that /var/log/libvirt/qemu/$NAME.log is intended for QEMU's stderr output. The only time that libvirtd currently writes to it, is before QEMU starts and after it has shutdown. This new patch means that libvirtd writes to it while QEMU is running, which is not really safe because you can now end up with 2 proceses writing to the same file at once. The log messages may well get interleaved/corrupted by each other. I don't think that is good for something that wants to be used as a formal record of operations on a VM. I think that in each driver we only really want to have to insert one set of formal "operation logging" calls. Since we already have the audit APIs present, I think we could try to make use of that to generate a record of operations against a VM in some way. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From stefanha at gmail.com Mon Apr 4 15:09:05 2011 From: stefanha at gmail.com (Stefan Hajnoczi) Date: Mon, 4 Apr 2011 16:09:05 +0100 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D99CC74.9070703@redhat.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D99CC74.9070703@redhat.com> Message-ID: On Mon, Apr 4, 2011 at 2:49 PM, Avi Kivity wrote: > On 04/04/2011 04:38 PM, Anthony Liguori wrote: >> >> On 04/04/2011 08:22 AM, Avi Kivity wrote: >>> >>> On 04/03/2011 02:57 PM, Stefan Hajnoczi wrote: >>>> >>>> In order for media change to work with Linux host CD-ROM it is >>>> necessary to reopen the file (otherwise the inode size will not >>>> refresh, this is an issue with existing kernels). >>>> >>> >>> Maybe we should fix the bug in Linux (and backport as necessary)? >>> >>> I think cd-rom assignment is sufficiently obscure that we can require a >>> fixed kernel instead of providing a workaround. >> >> Do reads fail after CD change? ?Or do they succeed and the size is just >> reported incorrectly? >> >> If it's the later, I'd agree that it needs fixing in the kernel. ?If it's >> the former, I'd say it's clearly a feature. >> > > Even if it's a documented or intentional feature, we can add an ioctl to > "refresh" the device with up-to-date data. It's possible to fix this in the kernel. I just haven't written the patch yet. The inode size needs to be updated when the new medium is detected. I haven't tested but I suspect reads within the size of the previous medium will succeed. But if the new medium is larger then reads beyond the old medium size will fail. The size reported by lseek(fd, 0, SEEK_END) is outdated. Stefan From avi at redhat.com Mon Apr 4 15:11:20 2011 From: avi at redhat.com (Avi Kivity) Date: Mon, 04 Apr 2011 18:11:20 +0300 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D99CC74.9070703@redhat.com> Message-ID: <4D99DF98.2030708@redhat.com> On 04/04/2011 06:09 PM, Stefan Hajnoczi wrote: > On Mon, Apr 4, 2011 at 2:49 PM, Avi Kivity wrote: > > On 04/04/2011 04:38 PM, Anthony Liguori wrote: > >> > >> On 04/04/2011 08:22 AM, Avi Kivity wrote: > >>> > >>> On 04/03/2011 02:57 PM, Stefan Hajnoczi wrote: > >>>> > >>>> In order for media change to work with Linux host CD-ROM it is > >>>> necessary to reopen the file (otherwise the inode size will not > >>>> refresh, this is an issue with existing kernels). > >>>> > >>> > >>> Maybe we should fix the bug in Linux (and backport as necessary)? > >>> > >>> I think cd-rom assignment is sufficiently obscure that we can require a > >>> fixed kernel instead of providing a workaround. > >> > >> Do reads fail after CD change? Or do they succeed and the size is just > >> reported incorrectly? > >> > >> If it's the later, I'd agree that it needs fixing in the kernel. If it's > >> the former, I'd say it's clearly a feature. > >> > > > > Even if it's a documented or intentional feature, we can add an ioctl to > > "refresh" the device with up-to-date data. > > It's possible to fix this in the kernel. I just haven't written the > patch yet. The inode size needs to be updated when the new medium is > detected. > > I haven't tested but I suspect reads within the size of the previous > medium will succeed. But if the new medium is larger then reads > beyond the old medium size will fail. > > The size reported by lseek(fd, 0, SEEK_END) is outdated. I believe a kernel fix is best in that case, leaving qemu alone. -- error compiling committee.c: too many arguments to function From berrange at redhat.com Mon Apr 4 16:19:58 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 17:19:58 +0100 Subject: [libvirt] [PATCH 0/6] Switch to use gnulib's manywarnings Message-ID: <1301934004-6204-1-git-send-email-berrange@redhat.com> A second version of http://www.redhat.com/archives/libvir-list/2011-April/msg00060.html In this version: - Move acinclude.m4 into m4/ - Don't blacklist -W, only use -Wno-sign-compare - Fix some issues allowing further warnings to be turned on - Increase max stack size to 65700 bytes to make test suite compile. Test suite to be fixed later :-) From berrange at redhat.com Mon Apr 4 16:19:59 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 17:19:59 +0100 Subject: [libvirt] [PATCH 1/6] Use gnulib's manywarnings & warnings modules In-Reply-To: <1301934004-6204-1-git-send-email-berrange@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> Message-ID: <1301934004-6204-2-git-send-email-berrange@redhat.com> Remove custom code for checking compiler warnings, using gl_WARN_ADD instead. Don't list all flags ourselves, use gnulib's gl_MANYWARN_ALL_GCC to get all possible GCC flags, then turn off the ones we don't want yet. * acinclude.m4: Rewrite to use gl_WARN_ADD and gl_MANYWARN_ALL_GCC * bootstrap.conf: Add warnings & manywarnings * configure.ac: Switch to gl_WARN_ADD * m4/compiler-flags.m4: Obsoleted by gl_WARN_ADD --- acinclude.m4 | 158 +++++++++++++++++++++++++++----------------------- bootstrap.conf | 2 + configure.ac | 15 +++-- m4/compiler-flags.m4 | 48 --------------- 4 files changed, 96 insertions(+), 127 deletions(-) delete mode 100644 m4/compiler-flags.m4 diff --git a/acinclude.m4 b/acinclude.m4 index 838ec46..8eb0ec5 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1,11 +1,6 @@ dnl -dnl Taken from gnome-common/macros2/gnome-compiler-flags.m4 -dnl -dnl We've added: -dnl -Wextra -Wshadow -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Winline -Wredundant-decls -dnl We've removed -dnl CFLAGS="$realsave_CFLAGS" -dnl to avoid clobbering user-specified CFLAGS +dnl Enable all known GCC compiler warnings, except for those +dnl we can't yet cope with dnl AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ dnl ****************************** @@ -13,90 +8,107 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ dnl ****************************** AC_ARG_ENABLE(compile-warnings, - [AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@], + [AC_HELP_STRING([--enable-compile-warnings=@<:@no/yes/error@:>@], [Turn on compiler warnings])],, - [enable_compile_warnings="m4_default([$1],[maximum])"]) - - warnCFLAGS= - - common_flags= - common_flags="$common_flags -Wp,-D_FORTIFY_SOURCE=2" - common_flags="$common_flags -fexceptions" - common_flags="$common_flags -fasynchronous-unwind-tables" - common_flags="$common_flags -fdiagnostics-show-option" + [enable_compile_warnings="m4_default([$1],[yes])"]) case "$enable_compile_warnings" in no) try_compiler_flags="" ;; - minimum) - try_compiler_flags="-Wall -Wformat -Wformat-security $common_flags" - ;; - yes) - try_compiler_flags="-Wall -Wformat -Wformat-security -Wmissing-prototypes $common_flags" - ;; - maximum|error) - try_compiler_flags="-Wall -Wformat -Wformat-security" - try_compiler_flags="$try_compiler_flags -Wmissing-prototypes" - try_compiler_flags="$try_compiler_flags -Wnested-externs " - try_compiler_flags="$try_compiler_flags -Wpointer-arith" - try_compiler_flags="$try_compiler_flags -Wextra -Wshadow" - try_compiler_flags="$try_compiler_flags -Wcast-align" - try_compiler_flags="$try_compiler_flags -Wwrite-strings" - try_compiler_flags="$try_compiler_flags -Waggregate-return" - try_compiler_flags="$try_compiler_flags -Wstrict-prototypes" - try_compiler_flags="$try_compiler_flags -Winline" - try_compiler_flags="$try_compiler_flags -Wredundant-decls" - try_compiler_flags="$try_compiler_flags -Wno-sign-compare" - try_compiler_flags="$try_compiler_flags -Wlogical-op" - try_compiler_flags="$try_compiler_flags $common_flags" - if test "$enable_compile_warnings" = "error" ; then - try_compiler_flags="$try_compiler_flags -Werror" - fi + yes|minimum|maximum|error) + + # List of warnings that are not relevant / wanted + dontwarn="$dontwarn -Wc++-compat" # Don't care about C++ compiler compat + dontwarn="$dontwarn -Wtraditional" # Don't care about ancient C standard compat + dontwarn="$dontwarn -Wtraditional-conversion" # Don't care about ancient C standard compat + dontwarn="$dontwarn -Wsystem-headers" # Ignore warnings in /usr/include + dontwarn="$dontwarn -Wpadded" # Happy for compiler to add struct padding + dontwarn="$dontwarn -Wunreachable-code" # GCC very confused with -O2 + dontwarn="$dontwarn -Wconversion" # Too many to deal with + dontwarn="$dontwarn -Wsign-conversion" # Too many to deal with + dontwarn="$dontwarn -Wvla" # GNULIB gettext.h violates + dontwarn="$dontwarn -Wundef" # Many GNULIB violations + dontwarn="$dontwarn -Wcast-qual" # Need to allow bad cast for execve() + dontwarn="$dontwarn -Wlong-long" # We need to use long long in many places + dontwarn="$dontwarn -Wswitch-default" # We allow manual list of all enum cases without default: + dontwarn="$dontwarn -Wswitch-enum" # We allow optional default: instead of listing all enum values + dontwarn="$dontwarn -Wstrict-overflow" # Not a problem since we don't use -fstrict-overflow + dontwarn="$dontwarn -Wunsafe-loop-optimizations" # Not a problem since we don't use -funsafe-loop-optimizations + + # We might fundamentally need some of these disabled forever, but ideally + # we'd turn many of them on + dontwarn="$dontwarn -Wformat-nonliteral" + dontwarn="$dontwarn -Wfloat-equal" + dontwarn="$dontwarn -Wdeclaration-after-statement" + dontwarn="$dontwarn -Wcast-qual" + dontwarn="$dontwarn -Wconversion" + dontwarn="$dontwarn -Wsign-conversion" + dontwarn="$dontwarn -Wold-style-definition" + dontwarn="$dontwarn -Wmissing-noreturn" + dontwarn="$dontwarn -Wpacked" + dontwarn="$dontwarn -Wunused-macros" + dontwarn="$dontwarn -Woverlength-strings" + dontwarn="$dontwarn -Wmissing-format-attribute" + dontwarn="$dontwarn -Wstack-protector" + + # Get all possible GCC warnings + gl_MANYWARN_ALL_GCC([maybewarn]) + + # Remove the ones we don't want, blacklisted earlier + gl_MANYWARN_COMPLEMENT([wantwarn], [$maybewarn], [$dontwarn]) + + # Check for $CC support of each warning + for w in $wantwarn; do + gl_WARN_ADD([$w]) + done + + # GNULIB uses '-W' which includes a bunch of stuff, + # kinda like -Wextra. Unfortunately, it means you + # can't simply use '-Wsign-compare' with gl_MANYWARN_COMPLEMENT + # So we have -W enabled, and then have to explicitly turn off + gl_WARN_ADD(-Wno-sign-compare) + + # This should be < 256 really, but with PATH_MAX everywhere + # we have doom, even with 4096. In fact we have some functions + # with several PATH_MAX sized variables :-( We should kill off + # all PATH_MAX usage and then lower this limit + gl_WARN_ADD([-Wframe-larger-than=65700]) + dnl gl_WARN_ADD([-Wframe-larger-than=4096]) + dnl gl_WARN_ADD([-Wframe-larger-than=256]) + + # Extra special flags + gl_WARN_ADD([-Wp,-D_FORTIFY_SOURCE=2]) + dnl Fedora only uses -fstack-protector, but doesn't seem to + dnl be great overhead in adding -fstack-protector-all instead + dnl gl_WARN_ADD([-fstack-protector]) + gl_WARN_ADD([-fstack-protector-all]) + gl_WARN_ADD([--param=ssp-buffer-size=4]) + gl_WARN_ADD([-fexceptions]) + gl_WARN_ADD([-fasynchronous-unwind-tables]) + gl_WARN_ADD([-fdiagnostics-show-option]) + + if test "$enable_compile_warnings" = "error" + then + gl_WARN_ADD([-Werror]) + fi ;; *) AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings) ;; esac - COMPILER_FLAGS= - for option in $try_compiler_flags; do - gl_COMPILER_FLAGS($option) - done - unset option - unset try_compiler_flags - - AC_ARG_ENABLE(iso-c, - AC_HELP_STRING([--enable-iso-c], - [Try to warn if code is not ISO C ]),, - [enable_iso_c=no]) - - AC_MSG_CHECKING(what language compliance flags to pass to the C compiler) - complCFLAGS= - if test "x$enable_iso_c" != "xno"; then - if test "x$GCC" = "xyes"; then - case " $CFLAGS " in - *[\ \ ]-ansi[\ \ ]*) ;; - *) complCFLAGS="$complCFLAGS -ansi" ;; - esac - case " $CFLAGS " in - *[\ \ ]-pedantic[\ \ ]*) ;; - *) complCFLAGS="$complCFLAGS -pedantic" ;; - esac - fi - fi - AC_MSG_RESULT($complCFLAGS) - - WARN_CFLAGS="$COMPILER_FLAGS $complCFLAGS" WARN_LDFLAGS=$WARN_CFLAGS AC_SUBST([WARN_CFLAGS]) AC_SUBST([WARN_LDFLAGS]) dnl Needed to keep compile quiet on python 2.4 - COMPILER_FLAGS= - gl_COMPILER_FLAGS(-Wno-redundant-decls) - WARN_PYTHON_CFLAGS=$COMPILER_FLAGS + save_WARN_CFLAGS=$WARN_CFLAGS + WARN_CFLAGS= + gl_WARN_ADD(-Wno-redundant-decls) + WARN_PYTHON_CFLAGS=$WARN_CFLAGS AC_SUBST(WARN_PYTHON_CFLAGS) + WARN_CFLAGS=$save_WARN_CFLAGS ]) diff --git a/bootstrap.conf b/bootstrap.conf index ca0c3de..86aad14 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -45,6 +45,7 @@ ignore-value inet_pton ioctl maintainer-makefile +manywarnings mkstemp mkstemps mktempd @@ -81,6 +82,7 @@ timegm uname useless-if-before-free usleep +warnings vasprintf verify vc-list-files diff --git a/configure.ac b/configure.ac index a8d223a..7874c30 100644 --- a/configure.ac +++ b/configure.ac @@ -1970,12 +1970,14 @@ AC_ARG_ENABLE([test-coverage], enable_coverage=$enableval if test "${enable_coverage}" = yes; then - COMPILER_FLAGS= - gl_COMPILER_FLAGS(-fprofile-arcs) - gl_COMPILER_FLAGS(-ftest-coverage) - AC_SUBST([COVERAGE_CFLAGS], [$COMPILER_FLAGS]) - AC_SUBST([COVERAGE_LDFLAGS], [$COMPILER_FLAGS]) - COMPILER_FLAGS= + save_WARN_CFLAGS=$WARN_CFLAGS + WARN_CFLAGS= + gl_WARN_ADD(-fprofile-arcs) + gl_WARN_ADD(-ftest-coverage) + COVERAGE_FLAGS=$WARN_CFLAGS + AC_SUBST([COVERAGE_CFLAGS], [$COVERAGE_FLAGS]) + AC_SUBST([COVERAGE_LDFLAGS], [$COVERAGE_FLAGS]) + WARN_CFLAGS=$save_WARN_CFLAGS fi AC_ARG_ENABLE([test-oom], @@ -2538,6 +2540,7 @@ AC_MSG_NOTICE([Miscellaneous]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([ Debug: $enable_debug]) AC_MSG_NOTICE([ Warnings: $enable_compile_warnings]) +AC_MSG_NOTICE([Warning Flags: $WARN_CFLAGS]) AC_MSG_NOTICE([ Readline: $lv_use_readline]) AC_MSG_NOTICE([ Python: $with_python]) AC_MSG_NOTICE([ DTrace: $with_dtrace]) diff --git a/m4/compiler-flags.m4 b/m4/compiler-flags.m4 deleted file mode 100644 index 6db4816..0000000 --- a/m4/compiler-flags.m4 +++ /dev/null @@ -1,48 +0,0 @@ -# serial 4 -# Find valid warning flags for the C Compiler. -*-Autoconf-*- -# -# Copyright (C) 2010 Red Hat, Inc. -# Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 USA - -# Written by Jesse Thilo. - -AC_DEFUN([gl_COMPILER_FLAGS], - [AC_MSG_CHECKING(whether compiler accepts $1) - ac_save_CFLAGS="$CFLAGS" - dnl Some flags are dependant, so we set all previously checked - dnl flags when testing. Except for -Werror which we have to - dnl check on its own, because some of our compiler flags cause - dnl warnings from the autoconf test program! - if test "$1" = "-Werror" ; then - CFLAGS="$CFLAGS $1" - else - CFLAGS="$CFLAGS $COMPILER_FLAGS $1" - fi - AC_TRY_LINK([], [], has_option=yes, has_option=no,) - echo 'int x;' >conftest.c - $CC $CFLAGS -c conftest.c 2>conftest.err - ret=$? - if test $ret != 0 || test -s conftest.err || test $has_option = "no"; then - AC_MSG_RESULT(no) - else - AC_MSG_RESULT(yes) - COMPILER_FLAGS="$COMPILER_FLAGS $1" - fi - CFLAGS="$ac_save_CFLAGS" - rm -f conftest* - ]) -- 1.7.4 From berrange at redhat.com Mon Apr 4 16:20:00 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 17:20:00 +0100 Subject: [libvirt] [PATCH 2/6] Remove acinclude.m4 file In-Reply-To: <1301934004-6204-1-git-send-email-berrange@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> Message-ID: <1301934004-6204-3-git-send-email-berrange@redhat.com> Split the bit acinclude.m4 file into smaller pieces named as m4/virt-XXXXX.m4 * .gitignore: Ignore gettext related files * acinclude.m4: Delete * m4/virt-compile-warnings.m4: Checks for GCC compiler flags * m4/virt-pkgconfig-back-compat.m4: Backcompat check for pkgconfig program --- .gitignore | 36 +++++++++- acinclude.m4 | 137 -------------------------------------- m4/virt-compile-warnings.m4 | 112 +++++++++++++++++++++++++++++++ m4/virt-pkgconfig-back-compat.m4 | 23 ++++++ 4 files changed, 169 insertions(+), 139 deletions(-) delete mode 100644 acinclude.m4 create mode 100644 m4/virt-compile-warnings.m4 create mode 100644 m4/virt-pkgconfig-back-compat.m4 diff --git a/.gitignore b/.gitignore index ba4d351..278bc4f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -!/m4/compiler-flags.m4 !/po/*.po !/po/POTFILES.in !/po/libvirt.pot @@ -46,7 +45,6 @@ /libvirt.spec /ltconfig /ltmain.sh -/m4/ /maint.mk /mingw32-libvirt.spec /mkinstalldirs @@ -67,3 +65,37 @@ results.log stamp-h stamp-h.in stamp-h1 +m4/codeset.m4 +m4/gettext.m4 +m4/glibc21.m4 +m4/iconv.m4 +m4/intdiv0.m4 +m4/intmax.m4 +m4/inttypes_h.m4 +m4/inttypes.m4 +m4/inttypes-pri.m4 +m4/isc-posix.m4 +m4/lcmessage.m4 +m4/lib-ld.m4 +m4/lib-link.m4 +m4/lib-prefix.m4 +m4/libtool.m4 +m4/longdouble.m4 +m4/longlong.m4 +m4/lt~obsolete.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/nls.m4 +m4/po.m4 +m4/printf-posix.m4 +m4/progtest.m4 +m4/signed.m4 +m4/size_max.m4 +m4/stdint_h.m4 +m4/uintmax_t.m4 +m4/ulonglong.m4 +m4/wchar_t.m4 +m4/wint_t.m4 +m4/xsize.m4 +m4/.gitignore diff --git a/acinclude.m4 b/acinclude.m4 deleted file mode 100644 index 8eb0ec5..0000000 --- a/acinclude.m4 +++ /dev/null @@ -1,137 +0,0 @@ -dnl -dnl Enable all known GCC compiler warnings, except for those -dnl we can't yet cope with -dnl -AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ - dnl ****************************** - dnl More compiler warnings - dnl ****************************** - - AC_ARG_ENABLE(compile-warnings, - [AC_HELP_STRING([--enable-compile-warnings=@<:@no/yes/error@:>@], - [Turn on compiler warnings])],, - [enable_compile_warnings="m4_default([$1],[yes])"]) - - case "$enable_compile_warnings" in - no) - try_compiler_flags="" - ;; - yes|minimum|maximum|error) - - # List of warnings that are not relevant / wanted - dontwarn="$dontwarn -Wc++-compat" # Don't care about C++ compiler compat - dontwarn="$dontwarn -Wtraditional" # Don't care about ancient C standard compat - dontwarn="$dontwarn -Wtraditional-conversion" # Don't care about ancient C standard compat - dontwarn="$dontwarn -Wsystem-headers" # Ignore warnings in /usr/include - dontwarn="$dontwarn -Wpadded" # Happy for compiler to add struct padding - dontwarn="$dontwarn -Wunreachable-code" # GCC very confused with -O2 - dontwarn="$dontwarn -Wconversion" # Too many to deal with - dontwarn="$dontwarn -Wsign-conversion" # Too many to deal with - dontwarn="$dontwarn -Wvla" # GNULIB gettext.h violates - dontwarn="$dontwarn -Wundef" # Many GNULIB violations - dontwarn="$dontwarn -Wcast-qual" # Need to allow bad cast for execve() - dontwarn="$dontwarn -Wlong-long" # We need to use long long in many places - dontwarn="$dontwarn -Wswitch-default" # We allow manual list of all enum cases without default: - dontwarn="$dontwarn -Wswitch-enum" # We allow optional default: instead of listing all enum values - dontwarn="$dontwarn -Wstrict-overflow" # Not a problem since we don't use -fstrict-overflow - dontwarn="$dontwarn -Wunsafe-loop-optimizations" # Not a problem since we don't use -funsafe-loop-optimizations - - # We might fundamentally need some of these disabled forever, but ideally - # we'd turn many of them on - dontwarn="$dontwarn -Wformat-nonliteral" - dontwarn="$dontwarn -Wfloat-equal" - dontwarn="$dontwarn -Wdeclaration-after-statement" - dontwarn="$dontwarn -Wcast-qual" - dontwarn="$dontwarn -Wconversion" - dontwarn="$dontwarn -Wsign-conversion" - dontwarn="$dontwarn -Wold-style-definition" - dontwarn="$dontwarn -Wmissing-noreturn" - dontwarn="$dontwarn -Wpacked" - dontwarn="$dontwarn -Wunused-macros" - dontwarn="$dontwarn -Woverlength-strings" - dontwarn="$dontwarn -Wmissing-format-attribute" - dontwarn="$dontwarn -Wstack-protector" - - # Get all possible GCC warnings - gl_MANYWARN_ALL_GCC([maybewarn]) - - # Remove the ones we don't want, blacklisted earlier - gl_MANYWARN_COMPLEMENT([wantwarn], [$maybewarn], [$dontwarn]) - - # Check for $CC support of each warning - for w in $wantwarn; do - gl_WARN_ADD([$w]) - done - - # GNULIB uses '-W' which includes a bunch of stuff, - # kinda like -Wextra. Unfortunately, it means you - # can't simply use '-Wsign-compare' with gl_MANYWARN_COMPLEMENT - # So we have -W enabled, and then have to explicitly turn off - gl_WARN_ADD(-Wno-sign-compare) - - # This should be < 256 really, but with PATH_MAX everywhere - # we have doom, even with 4096. In fact we have some functions - # with several PATH_MAX sized variables :-( We should kill off - # all PATH_MAX usage and then lower this limit - gl_WARN_ADD([-Wframe-larger-than=65700]) - dnl gl_WARN_ADD([-Wframe-larger-than=4096]) - dnl gl_WARN_ADD([-Wframe-larger-than=256]) - - # Extra special flags - gl_WARN_ADD([-Wp,-D_FORTIFY_SOURCE=2]) - dnl Fedora only uses -fstack-protector, but doesn't seem to - dnl be great overhead in adding -fstack-protector-all instead - dnl gl_WARN_ADD([-fstack-protector]) - gl_WARN_ADD([-fstack-protector-all]) - gl_WARN_ADD([--param=ssp-buffer-size=4]) - gl_WARN_ADD([-fexceptions]) - gl_WARN_ADD([-fasynchronous-unwind-tables]) - gl_WARN_ADD([-fdiagnostics-show-option]) - - if test "$enable_compile_warnings" = "error" - then - gl_WARN_ADD([-Werror]) - fi - ;; - *) - AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings) - ;; - esac - - WARN_LDFLAGS=$WARN_CFLAGS - AC_SUBST([WARN_CFLAGS]) - AC_SUBST([WARN_LDFLAGS]) - - dnl Needed to keep compile quiet on python 2.4 - save_WARN_CFLAGS=$WARN_CFLAGS - WARN_CFLAGS= - gl_WARN_ADD(-Wno-redundant-decls) - WARN_PYTHON_CFLAGS=$WARN_CFLAGS - AC_SUBST(WARN_PYTHON_CFLAGS) - WARN_CFLAGS=$save_WARN_CFLAGS -]) - - -dnl -dnl To support the old pkg-config from RHEL4 vintage, we need -dnl to define the PKG_PROG_PKG_CONFIG macro if its not already -dnl present -m4_ifndef([PKG_PROG_PKG_CONFIG], - [AC_DEFUN([PKG_PROG_PKG_CONFIG], -[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) -m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) -AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then - AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) -fi -if test -n "$PKG_CONFIG"; then - _pkg_min_version=m4_default([$1], [0.9.0]) - AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) - if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - PKG_CONFIG="" - fi -fi[]dnl -])]) diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4 new file mode 100644 index 0000000..f8ee474 --- /dev/null +++ b/m4/virt-compile-warnings.m4 @@ -0,0 +1,112 @@ +dnl +dnl Enable all known GCC compiler warnings, except for those +dnl we can't yet cope with +dnl +AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ + dnl ****************************** + dnl More compiler warnings + dnl ****************************** + + AC_ARG_ENABLE(compile-warnings, + [AC_HELP_STRING([--enable-compile-warnings=@<:@no/yes/error@:>@], + [Turn on compiler warnings])],, + [enable_compile_warnings="m4_default([$1],[yes])"]) + + case "$enable_compile_warnings" in + no) + try_compiler_flags="" + ;; + yes|minimum|maximum|error) + + # List of warnings that are not relevant / wanted + dontwarn="$dontwarn -Wc++-compat" # Don't care about C++ compiler compat + dontwarn="$dontwarn -Wtraditional" # Don't care about ancient C standard compat + dontwarn="$dontwarn -Wtraditional-conversion" # Don't care about ancient C standard compat + dontwarn="$dontwarn -Wsystem-headers" # Ignore warnings in /usr/include + dontwarn="$dontwarn -Wpadded" # Happy for compiler to add struct padding + dontwarn="$dontwarn -Wunreachable-code" # GCC very confused with -O2 + dontwarn="$dontwarn -Wconversion" # Too many to deal with + dontwarn="$dontwarn -Wsign-conversion" # Too many to deal with + dontwarn="$dontwarn -Wvla" # GNULIB gettext.h violates + dontwarn="$dontwarn -Wundef" # Many GNULIB violations + dontwarn="$dontwarn -Wcast-qual" # Need to allow bad cast for execve() + dontwarn="$dontwarn -Wlong-long" # We need to use long long in many places + dontwarn="$dontwarn -Wswitch-default" # We allow manual list of all enum cases without default: + dontwarn="$dontwarn -Wswitch-enum" # We allow optional default: instead of listing all enum values + dontwarn="$dontwarn -Wstrict-overflow" # Not a problem since we don't use -fstrict-overflow + dontwarn="$dontwarn -Wunsafe-loop-optimizations" # Not a problem since we don't use -funsafe-loop-optimizations + + # We might fundamentally need some of these disabled forever, but ideally + # we'd turn many of them on + dontwarn="$dontwarn -Wformat-nonliteral" + dontwarn="$dontwarn -Wfloat-equal" + dontwarn="$dontwarn -Wdeclaration-after-statement" + dontwarn="$dontwarn -Wcast-qual" + dontwarn="$dontwarn -Wconversion" + dontwarn="$dontwarn -Wsign-conversion" + dontwarn="$dontwarn -Wold-style-definition" + dontwarn="$dontwarn -Wmissing-noreturn" + dontwarn="$dontwarn -Wpacked" + dontwarn="$dontwarn -Wunused-macros" + dontwarn="$dontwarn -Woverlength-strings" + dontwarn="$dontwarn -Wmissing-format-attribute" + dontwarn="$dontwarn -Wstack-protector" + + # Get all possible GCC warnings + gl_MANYWARN_ALL_GCC([maybewarn]) + + # Remove the ones we don't want, blacklisted earlier + gl_MANYWARN_COMPLEMENT([wantwarn], [$maybewarn], [$dontwarn]) + + # Check for $CC support of each warning + for w in $wantwarn; do + gl_WARN_ADD([$w]) + done + + # GNULIB uses '-W' which includes a bunch of stuff, + # kinda like -Wextra. Unfortunately, it means you + # can't simply use '-Wsign-compare' with gl_MANYWARN_COMPLEMENT + # So we have -W enabled, and then have to explicitly turn off + gl_WARN_ADD(-Wno-sign-compare) + + # This should be < 256 really, but with PATH_MAX everywhere + # we have doom, even with 4096. In fact we have some functions + # with several PATH_MAX sized variables :-( We should kill off + # all PATH_MAX usage and then lower this limit + gl_WARN_ADD([-Wframe-larger-than=65700]) + dnl gl_WARN_ADD([-Wframe-larger-than=4096]) + dnl gl_WARN_ADD([-Wframe-larger-than=256]) + + # Extra special flags + gl_WARN_ADD([-Wp,-D_FORTIFY_SOURCE=2]) + dnl Fedora only uses -fstack-protector, but doesn't seem to + dnl be great overhead in adding -fstack-protector-all instead + dnl gl_WARN_ADD([-fstack-protector]) + gl_WARN_ADD([-fstack-protector-all]) + gl_WARN_ADD([--param=ssp-buffer-size=4]) + gl_WARN_ADD([-fexceptions]) + gl_WARN_ADD([-fasynchronous-unwind-tables]) + gl_WARN_ADD([-fdiagnostics-show-option]) + + if test "$enable_compile_warnings" = "error" + then + gl_WARN_ADD([-Werror]) + fi + ;; + *) + AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings) + ;; + esac + + WARN_LDFLAGS=$WARN_CFLAGS + AC_SUBST([WARN_CFLAGS]) + AC_SUBST([WARN_LDFLAGS]) + + dnl Needed to keep compile quiet on python 2.4 + save_WARN_CFLAGS=$WARN_CFLAGS + WARN_CFLAGS= + gl_WARN_ADD(-Wno-redundant-decls) + WARN_PYTHON_CFLAGS=$WARN_CFLAGS + AC_SUBST(WARN_PYTHON_CFLAGS) + WARN_CFLAGS=$save_WARN_CFLAGS +]) diff --git a/m4/virt-pkgconfig-back-compat.m4 b/m4/virt-pkgconfig-back-compat.m4 new file mode 100644 index 0000000..7eab84b --- /dev/null +++ b/m4/virt-pkgconfig-back-compat.m4 @@ -0,0 +1,23 @@ +dnl +dnl To support the old pkg-config from RHEL4 vintage, we need +dnl to define the PKG_PROG_PKG_CONFIG macro if its not already +dnl present +m4_ifndef([PKG_PROG_PKG_CONFIG], + [AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])]) -- 1.7.4 From berrange at redhat.com Mon Apr 4 16:20:01 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 17:20:01 +0100 Subject: [libvirt] [PATCH 3/6] Enable -Wmissing-format-attribute warning In-Reply-To: <1301934004-6204-1-git-send-email-berrange@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> Message-ID: <1301934004-6204-4-git-send-email-berrange@redhat.com> Add a couple of missing ATTRIBUTE_FMT_PRINTF annotations * tools/virsh.c, tests/testutils.c: Add printf format attribute * m4/virt-compile-warnings.m4: Enable -Wmissing-format-attribute --- m4/virt-compile-warnings.m4 | 1 - tests/testutils.c | 2 +- tools/virsh.c | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4 index f8ee474..51e21a9 100644 --- a/m4/virt-compile-warnings.m4 +++ b/m4/virt-compile-warnings.m4 @@ -49,7 +49,6 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ dontwarn="$dontwarn -Wpacked" dontwarn="$dontwarn -Wunused-macros" dontwarn="$dontwarn -Woverlength-strings" - dontwarn="$dontwarn -Wmissing-format-attribute" dontwarn="$dontwarn -Wstack-protector" # Get all possible GCC warnings diff --git a/tests/testutils.c b/tests/testutils.c index 3110457..0ce3c7b 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -67,7 +67,7 @@ virtTestCountAverage(double *items, int nitems) return (double) (sum / nitems); } - +ATTRIBUTE_FMT_PRINTF(3,4) void virtTestResult(const char *name, int ret, const char *msg, ...) { va_list vargs; diff --git a/tools/virsh.c b/tools/virsh.c index 19e3449..4765f5c 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -243,7 +243,8 @@ static int vshInit(vshControl *ctl); static int vshDeinit(vshControl *ctl); static void vshUsage(void); static void vshOpenLogFile(vshControl *ctl); -static void vshOutputLogFile(vshControl *ctl, int log_level, const char *format, va_list ap); +static void vshOutputLogFile(vshControl *ctl, int log_level, const char *format, va_list ap) + ATTRIBUTE_FMT_PRINTF(3, 0); static void vshCloseLogFile(vshControl *ctl); static int vshParseArgv(vshControl *ctl, int argc, char **argv); -- 1.7.4 From berrange at redhat.com Mon Apr 4 16:20:02 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 17:20:02 +0100 Subject: [libvirt] [PATCH 4/6] Enable use of -Wmissing-noreturn In-Reply-To: <1301934004-6204-1-git-send-email-berrange@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> Message-ID: <1301934004-6204-5-git-send-email-berrange@redhat.com> * src/internal.h: Define a ATTRIBUTE_NO_RETURN annotation * src/lxc/lxc_container.c: Annotate lxcContainerDummyChild with ATTRIBUTE_NO_RETURN * tests/eventtest.c: Mark async thread as ATTRIBUTE_NO_RETURN * m4/virt-compile-warnings.m4: Enable -Wmissing-noreturn --- m4/virt-compile-warnings.m4 | 1 - src/internal.h | 9 +++++++++ src/lxc/lxc_container.c | 3 ++- tests/eventtest.c | 3 +-- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4 index 51e21a9..9643419 100644 --- a/m4/virt-compile-warnings.m4 +++ b/m4/virt-compile-warnings.m4 @@ -45,7 +45,6 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ dontwarn="$dontwarn -Wconversion" dontwarn="$dontwarn -Wsign-conversion" dontwarn="$dontwarn -Wold-style-definition" - dontwarn="$dontwarn -Wmissing-noreturn" dontwarn="$dontwarn -Wpacked" dontwarn="$dontwarn -Wunused-macros" dontwarn="$dontwarn -Woverlength-strings" diff --git a/src/internal.h b/src/internal.h index 2afbd8d..4641fc1 100644 --- a/src/internal.h +++ b/src/internal.h @@ -117,6 +117,15 @@ # endif /** + * ATTRIBUTE_NORETURN: + * + * Macro to indicate that a function won't return to the caller + */ +# ifndef ATTRIBUTE_NORETURN +# define ATTRIBUTE_NORETURN __attribute__((__noreturn__)) +# endif + +/** * ATTRIBUTE_SENTINEL: * * Macro to check for NULL-terminated varargs lists diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 9830b71..af453f3 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -914,7 +914,8 @@ int lxcContainerStart(virDomainDefPtr def, return pid; } -static int lxcContainerDummyChild(void *argv ATTRIBUTE_UNUSED) +ATTRIBUTE_NORETURN static int +lxcContainerDummyChild(void *argv ATTRIBUTE_UNUSED) { _exit(0); } diff --git a/tests/eventtest.c b/tests/eventtest.c index 4d22070..eb4b755 100644 --- a/tests/eventtest.c +++ b/tests/eventtest.c @@ -119,7 +119,7 @@ static pthread_cond_t eventThreadJobCond = PTHREAD_COND_INITIALIZER; static int eventThreadJobDone = 0; -static void *eventThreadLoop(void *data ATTRIBUTE_UNUSED) { +ATTRIBUTE_NORETURN static void *eventThreadLoop(void *data ATTRIBUTE_UNUSED) { while (1) { pthread_mutex_lock(&eventThreadMutex); while (!eventThreadRunOnce) { @@ -135,7 +135,6 @@ static void *eventThreadLoop(void *data ATTRIBUTE_UNUSED) { pthread_cond_signal(&eventThreadJobCond); pthread_mutex_unlock(&eventThreadMutex); } - return NULL; } -- 1.7.4 From berrange at redhat.com Mon Apr 4 16:20:03 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 17:20:03 +0100 Subject: [libvirt] [PATCH 5/6] Enable use of -Wold-style-definition compiler flag In-Reply-To: <1301934004-6204-1-git-send-email-berrange@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> Message-ID: <1301934004-6204-6-git-send-email-berrange@redhat.com> A couple of functions were declared using the old style foo() for no-parameters, instead of foo(void) * src/xen/xen_hypervisor.c, tests/testutils.c: Replace () with (void) in some function declarations * m4/virt-compile-warnings.m4: Enable -Wold-style-definition --- m4/virt-compile-warnings.m4 | 1 - src/xen/xen_hypervisor.c | 2 +- tests/testutils.c | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4 index 9643419..24710e6 100644 --- a/m4/virt-compile-warnings.m4 +++ b/m4/virt-compile-warnings.m4 @@ -44,7 +44,6 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ dontwarn="$dontwarn -Wcast-qual" dontwarn="$dontwarn -Wconversion" dontwarn="$dontwarn -Wsign-conversion" - dontwarn="$dontwarn -Wold-style-definition" dontwarn="$dontwarn -Wpacked" dontwarn="$dontwarn -Wunused-macros" dontwarn="$dontwarn -Woverlength-strings" diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c index 47355ce..8a9dae5 100644 --- a/src/xen/xen_hypervisor.c +++ b/src/xen/xen_hypervisor.c @@ -3621,7 +3621,7 @@ xenHypervisorGetVcpuMax(virDomainPtr domain) * Return true if the current process should be able to connect to Xen. */ int -xenHavePrivilege() +xenHavePrivilege(void) { #ifdef __sun return priv_ineffect (PRIV_XVM_CONTROL); diff --git a/tests/testutils.c b/tests/testutils.c index 0ce3c7b..1f3b569 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -457,14 +457,14 @@ virTestGetFlag(const char *name) { } unsigned int -virTestGetDebug() { +virTestGetDebug(void) { if (testDebug == -1) testDebug = virTestGetFlag("VIR_TEST_DEBUG"); return testDebug; } unsigned int -virTestGetVerbose() { +virTestGetVerbose(void) { if (testVerbose == -1) testVerbose = virTestGetFlag("VIR_TEST_VERBOSE"); return testVerbose || virTestGetDebug(); -- 1.7.4 From berrange at redhat.com Mon Apr 4 16:20:04 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 17:20:04 +0100 Subject: [libvirt] [PATCH 6/6] Remove unused macros and enable -Wunused-macros In-Reply-To: <1301934004-6204-1-git-send-email-berrange@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> Message-ID: <1301934004-6204-7-git-send-email-berrange@redhat.com> * m4/virt-compile-warnings.m4: Enable -Wunused-macros * daemon/libvirtd.c: Remove MAX_LISTEN * daemon/remote.c: Remote VIR_FROM_THIS * examples/domain-events/events-c/event-test.c: Remove VIR_DEBUG * python/libvirt-override.c: Put NAME() inside DEBUG_ERROR * src/esx/esx*.c: Comment out unused VIR_FROM_THIS * src/node_device/node_device_hal.c: Remove pointless macros for accessing privateData * src/openvz/openvz_driver.c: Remove CMDBUF_LEN/CMDOP_LEN * src/qemu/qemu_monitor_text.c: Remove QEMU_CMD_PROMPT and QEMU_PASSWD_PROMPT * src/remote/remote_driver.c: Remove UNIX_PATH_MAX * src/security/security_stack.c: Remove VIR_FROM_THIS * src/uml/uml_conf.c: Remove umlLog() * src/uml/uml_driver.c: Remove TEMPDIR * src/util/bridge.c: Remove JIFFIES_TO_MS/MS_TO_JIFFIES * src/util/hooks.c: Ensure VIR_FROM_THIS is used * src/util/logging.c: Remove VIR_FROM_THIS * src/util/macvtap.c: Disable unused constants * src/util/storage_file.c: Disable QCOW1_HDR_TOTAL_SIZE * src/vbox/vbox_driver.c: Remove duplicated VIR_FROM_THIS and make sure it is used * src/util/pci.c: Disable some unused constants * src/xen/xen_hypervisor.c: Remove XEN_V0_IOCTL_HYPERCALL_CMD and unused DOMFLAGS_CPUMASK/DOMFLAGS_CPUSHIFT * src/xen/xm_internal.c: Remove XM_XML_ERROR, XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU and XEND_CONFIG_MIN_VERS_PVFB_NEWCONF * tools/virsh.c: Remove DIR_MODE/LOCK_MODE, LVL_NOTICE constants * tests/sockettest.c: Remove DO_TEST_PARSE --- daemon/libvirtd.c | 2 +- daemon/remote.c | 1 - examples/domain-events/events-c/event-test.c | 2 -- m4/virt-compile-warnings.m4 | 1 - python/libvirt-override.c | 2 ++ src/driver.c | 3 +-- src/esx/esx_device_monitor.c | 2 +- src/esx/esx_interface_driver.c | 2 +- src/esx/esx_network_driver.c | 2 +- src/esx/esx_nwfilter_driver.c | 2 +- src/esx/esx_secret_driver.c | 2 +- src/esx/esx_vi.c | 7 ------- src/esx/esx_vi_methods.c | 9 +++++---- src/esx/esx_vi_types.c | 3 ++- src/libvirt.c | 3 --- src/node_device/node_device_hal.c | 17 ++++------------- src/openvz/openvz_driver.c | 2 -- src/qemu/qemu_monitor_text.c | 3 --- src/remote/remote_driver.c | 3 --- src/security/security_stack.c | 2 -- src/uml/uml_conf.c | 2 -- src/uml/uml_driver.c | 3 --- src/util/bridge.c | 3 --- src/util/hooks.c | 2 +- src/util/logging.c | 2 -- src/util/macvtap.c | 6 ++++-- src/util/pci.c | 4 ++-- src/util/storage_file.c | 4 +++- src/vbox/vbox_driver.c | 4 +--- src/xen/xen_hypervisor.c | 14 +++++--------- src/xen/xm_internal.c | 9 --------- tests/sockettest.c | 10 ---------- tools/virsh.c | 13 ++----------- 33 files changed, 38 insertions(+), 108 deletions(-) diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 024f56f..991aaeb 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -3154,7 +3154,7 @@ enum { OPT_VERSION = 129 }; -#define MAX_LISTEN 5 + int main(int argc, char **argv) { struct qemud_server *server = NULL; const char *pid_file = NULL; diff --git a/daemon/remote.c b/daemon/remote.c index 1700c2d..98279e1 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -62,7 +62,6 @@ #include "libvirt/libvirt-qemu.h" #include "command.h" -#define VIR_FROM_THIS VIR_FROM_REMOTE #define REMOTE_DEBUG(fmt, ...) VIR_DEBUG(fmt, __VA_ARGS__) static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain); diff --git a/examples/domain-events/events-c/event-test.c b/examples/domain-events/events-c/event-test.c index 1f46d42..3de2aa8 100644 --- a/examples/domain-events/events-c/event-test.c +++ b/examples/domain-events/events-c/event-test.c @@ -10,8 +10,6 @@ #define VIR_DEBUG0(fmt) printf("%s:%d :: " fmt "\n", \ __func__, __LINE__) -#define VIR_DEBUG(fmt, ...) printf("%s:%d: " fmt "\n", \ - __func__, __LINE__, __VA_ARGS__) #define STREQ(a,b) (strcmp(a,b) == 0) #ifndef ATTRIBUTE_UNUSED diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4 index 24710e6..5022676 100644 --- a/m4/virt-compile-warnings.m4 +++ b/m4/virt-compile-warnings.m4 @@ -45,7 +45,6 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ dontwarn="$dontwarn -Wconversion" dontwarn="$dontwarn -Wsign-conversion" dontwarn="$dontwarn -Wpacked" - dontwarn="$dontwarn -Wunused-macros" dontwarn="$dontwarn -Woverlength-strings" dontwarn="$dontwarn -Wstack-protector" diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 4a9b432..8568ff2 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -2595,7 +2595,9 @@ static char *updateTimeoutName = NULL; static PyObject *removeTimeoutObj = NULL; static char *removeTimeoutName = NULL; +#if DEBUG_ERROR #define NAME(fn) ( fn ## Name ? fn ## Name : # fn ) +#endif static int libvirt_virEventAddHandleFunc (int fd, diff --git a/src/driver.c b/src/driver.c index f882ea1..25623cd 100644 --- a/src/driver.c +++ b/src/driver.c @@ -30,13 +30,12 @@ #include "util.h" #include "configmake.h" -#define DEFAULT_DRIVER_DIR LIBDIR "/libvirt/connection-driver" - /* Make sure ... INTERNAL_CALL can not be set by the caller */ verify((VIR_SECRET_GET_VALUE_INTERNAL_CALL & VIR_SECRET_GET_VALUE_FLAGS_MASK) == 0); #ifdef WITH_DRIVER_MODULES +# define DEFAULT_DRIVER_DIR LIBDIR "/libvirt/connection-driver" /* XXX re-implment this for other OS, or use libtools helper lib ? */ diff --git a/src/esx/esx_device_monitor.c b/src/esx/esx_device_monitor.c index d559f96..6d765ac 100644 --- a/src/esx/esx_device_monitor.c +++ b/src/esx/esx_device_monitor.c @@ -35,7 +35,7 @@ #include "esx_vi_methods.h" #include "esx_util.h" -#define VIR_FROM_THIS VIR_FROM_ESX +/* #define VIR_FROM_THIS VIR_FROM_ESX */ diff --git a/src/esx/esx_interface_driver.c b/src/esx/esx_interface_driver.c index 4bac3d5..8d0b9a2 100644 --- a/src/esx/esx_interface_driver.c +++ b/src/esx/esx_interface_driver.c @@ -35,7 +35,7 @@ #include "esx_vi_methods.h" #include "esx_util.h" -#define VIR_FROM_THIS VIR_FROM_ESX +/* #define VIR_FROM_THIS VIR_FROM_ESX */ diff --git a/src/esx/esx_network_driver.c b/src/esx/esx_network_driver.c index a64bb8e..7117a60 100644 --- a/src/esx/esx_network_driver.c +++ b/src/esx/esx_network_driver.c @@ -35,7 +35,7 @@ #include "esx_vi_methods.h" #include "esx_util.h" -#define VIR_FROM_THIS VIR_FROM_ESX +/* #define VIR_FROM_THIS VIR_FROM_ESX */ diff --git a/src/esx/esx_nwfilter_driver.c b/src/esx/esx_nwfilter_driver.c index a9d046d..4ba9f46 100644 --- a/src/esx/esx_nwfilter_driver.c +++ b/src/esx/esx_nwfilter_driver.c @@ -34,7 +34,7 @@ #include "esx_vi_methods.h" #include "esx_util.h" -#define VIR_FROM_THIS VIR_FROM_ESX +/* #define VIR_FROM_THIS VIR_FROM_ESX */ diff --git a/src/esx/esx_secret_driver.c b/src/esx/esx_secret_driver.c index 1ae7ddc..350d8e0 100644 --- a/src/esx/esx_secret_driver.c +++ b/src/esx/esx_secret_driver.c @@ -34,7 +34,7 @@ #include "esx_vi_methods.h" #include "esx_util.h" -#define VIR_FROM_THIS VIR_FROM_ESX +/* #define VIR_FROM_THIS VIR_FROM_ESX */ diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index 7446ec5..3b38937 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -40,13 +40,6 @@ #define VIR_FROM_THIS VIR_FROM_ESX - -#define ESX_VI__SOAP__RESPONSE_XPATH(_type) \ - ((char *)"/soapenv:Envelope/soapenv:Body/" \ - "vim:"_type"Response/vim:returnval") - - - #define ESX_VI__TEMPLATE__ALLOC(_type) \ int \ esxVI_##_type##_Alloc(esxVI_##_type **ptrptr) \ diff --git a/src/esx/esx_vi_methods.c b/src/esx/esx_vi_methods.c index 5967088..440a62a 100644 --- a/src/esx/esx_vi_methods.c +++ b/src/esx/esx_vi_methods.c @@ -1,4 +1,3 @@ - /* * esx_vi_methods.c: client for the VMware VI API 2.5 to manage ESX hosts * @@ -52,8 +51,10 @@ +#if 0 #define ESX_VI__METHOD__CHECK_OUTPUT__RequiredList \ ESX_VI__METHOD__CHECK_OUTPUT__NotNone +#endif @@ -78,12 +79,12 @@ } - -#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__RequiredList(_type, _suffix) \ +#if 0 +#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__RequiredList(_type) \ if (esxVI_##_type##_DeserializeList(response->node, output) < 0) { \ goto cleanup; \ } - +#endif #define ESX_VI__METHOD__DESERIALIZE_OUTPUT__OptionalItem(_type, _suffix) \ diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c index f3df2b5..56121ef 100644 --- a/src/esx/esx_vi_types.c +++ b/src/esx/esx_vi_types.c @@ -531,11 +531,12 @@ +#if 0 #define ESX_VI__TEMPLATE__DISPATCH__DEEP_COPY(_type) \ case esxVI_Type_##_type: \ return esxVI_##_type##_DeepCopy((esxVI_##_type **)dst, \ (esxVI_##_type *)src); - +#endif #define ESX_VI__TEMPLATE__DISPATCH__CAST_FROM_ANY_TYPE(_type) \ diff --git a/src/libvirt.c b/src/libvirt.c index 8be18d4..564988b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -492,9 +492,6 @@ DllMain (HINSTANCE instance ATTRIBUTE_UNUSED, #define virLibSecretError(code, ...) \ virReportErrorHelper(NULL, VIR_FROM_SECRET, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) -#define virLibStreamError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_STREAMS, code, __FILE__, \ - __FUNCTION__, __LINE__, __VA_ARGS__) #define virLibNWFilterError(code, ...) \ virReportErrorHelper(NULL, VIR_FROM_NWFILTER, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) diff --git a/src/node_device/node_device_hal.c b/src/node_device/node_device_hal.c index 3af2bcf..b4a4c73 100644 --- a/src/node_device/node_device_hal.c +++ b/src/node_device/node_device_hal.c @@ -38,21 +38,12 @@ #include "logging.h" #include "node_device_driver.h" -#define VIR_FROM_THIS VIR_FROM_NODEDEV - /* * Host device enumeration (HAL implementation) */ static virDeviceMonitorStatePtr driverState; -#define CONN_DRV_STATE(conn) \ - ((virDeviceMonitorStatePtr)((conn)->devMonPrivateData)) -#define DRV_STATE_HAL_CTX(ds) ((LibHalContext *)((ds)->privateData)) -#define CONN_HAL_CTX(conn) DRV_STATE_HAL_CTX(CONN_DRV_STATE(conn)) - -#define NODE_DEV_UDI(obj) ((const char *)((obj)->privateData) - static const char *hal_name(const char *udi) { @@ -441,7 +432,7 @@ static void dev_create(const char *udi) return; nodeDeviceLock(driverState); - ctx = DRV_STATE_HAL_CTX(driverState); + ctx = driverState->privateData; if (VIR_ALLOC(def) < 0) goto failure; @@ -600,7 +591,7 @@ static void dbus_watch_callback(int fdatch ATTRIBUTE_UNUSED, (void)dbus_watch_handle(watch, dbus_flags); nodeDeviceLock(driverState); - hal_ctx = DRV_STATE_HAL_CTX(driverState); + hal_ctx = driverState->privateData; dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx); nodeDeviceUnlock(driverState); while (dbus_connection_dispatch(dbus_conn) == DBUS_DISPATCH_DATA_REMAINS) @@ -808,7 +799,7 @@ static int halDeviceMonitorShutdown(void) { if (driverState) { nodeDeviceLock(driverState); - LibHalContext *hal_ctx = DRV_STATE_HAL_CTX(driverState); + LibHalContext *hal_ctx = driverState->privateData; virNodeDeviceObjListFree(&driverState->devs); (void)libhal_ctx_shutdown(hal_ctx, NULL); (void)libhal_ctx_free(hal_ctx); @@ -834,7 +825,7 @@ static int halDeviceMonitorReload(void) virNodeDeviceObjListFree(&driverState->devs); nodeDeviceUnlock(driverState); - hal_ctx = DRV_STATE_HAL_CTX(driverState); + hal_ctx = driverState->privateData; VIR_INFO0("Creating new objects"); dbus_error_init(&err); udi = libhal_get_all_devices(hal_ctx, &num_devs, &err); diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index fb30c37..c492341 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -63,8 +63,6 @@ #define VIR_FROM_THIS VIR_FROM_OPENVZ #define OPENVZ_MAX_ARG 28 -#define CMDBUF_LEN 1488 -#define CMDOP_LEN 288 static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid); static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type); diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 168c60f..2208573 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -43,9 +43,6 @@ #define VIR_FROM_THIS VIR_FROM_QEMU -#define QEMU_CMD_PROMPT "\n(qemu) " -#define QEMU_PASSWD_PROMPT "Password: " - #define DEBUG_IO 0 /* Return -1 for error, 0 for success */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index bf94e70..7f7687a 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -691,9 +691,6 @@ doRemoteOpen (virConnectPtr conn, } } -# ifndef UNIX_PATH_MAX -# define UNIX_PATH_MAX(addr) (sizeof (addr).sun_path) -# endif struct sockaddr_un addr; int trials = 0; diff --git a/src/security/security_stack.c b/src/security/security_stack.c index 64f745a..5cdcc6a 100644 --- a/src/security/security_stack.c +++ b/src/security/security_stack.c @@ -24,8 +24,6 @@ #include "virterror_internal.h" -#define VIR_FROM_THIS VIR_FROM_SECURITY - typedef struct _virSecurityStackData virSecurityStackData; typedef virSecurityStackData *virSecurityStackDataPtr; diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c index 7c8fb16..909515f 100644 --- a/src/uml/uml_conf.c +++ b/src/uml/uml_conf.c @@ -52,8 +52,6 @@ #define VIR_FROM_THIS VIR_FROM_UML -#define umlLog(level, msg, ...) \ - virLogMessage(__FILE__, level, 0, msg, __VA_ARGS__) virCapsPtr umlCapsInit(void) { struct utsname utsname; diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index e2bd5f2..a26087c 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -65,9 +65,6 @@ #define VIR_FROM_THIS VIR_FROM_UML -/* For storing short-lived temporary files. */ -#define TEMPDIR LOCALSTATEDIR "/cache/libvirt" - typedef struct _umlDomainObjPrivate umlDomainObjPrivate; typedef umlDomainObjPrivate *umlDomainObjPrivatePtr; struct _umlDomainObjPrivate { diff --git a/src/util/bridge.c b/src/util/bridge.c index 3ed71be..00234df 100644 --- a/src/util/bridge.c +++ b/src/util/bridge.c @@ -52,9 +52,6 @@ # include "logging.h" # include "network.h" -# define JIFFIES_TO_MS(j) (((j)*1000)/HZ) -# define MS_TO_JIFFIES(ms) (((ms)*HZ)/1000) - struct _brControl { int fd; }; diff --git a/src/util/hooks.c b/src/util/hooks.c index 819c95c..3eeb698 100644 --- a/src/util/hooks.c +++ b/src/util/hooks.c @@ -42,7 +42,7 @@ #define VIR_FROM_THIS VIR_FROM_HOOK #define virHookReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_HOOK, code, __FILE__, \ + virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define LIBVIRT_HOOK_DIR SYSCONFDIR "/libvirt/hooks" diff --git a/src/util/logging.c b/src/util/logging.c index 9d18752..0330fec 100644 --- a/src/util/logging.c +++ b/src/util/logging.c @@ -44,8 +44,6 @@ #include "threads.h" #include "files.h" -#define VIR_FROM_THIS VIR_FROM_NONE - /* * Macro used to format the message as a string in virLogMessage * and borrowed from libxml2 (also used in virRaiseError) diff --git a/src/util/macvtap.c b/src/util/macvtap.c index 346eaf6..f563c23 100644 --- a/src/util/macvtap.c +++ b/src/util/macvtap.c @@ -71,8 +71,10 @@ # define MICROSEC_PER_SEC (1000 * 1000) -# define NLMSGBUF_SIZE 256 -# define RATTBUF_SIZE 64 +# if 0 +# define NLMSGBUF_SIZE 256 +# define RATTBUF_SIZE 64 +# endif # define NETLINK_ACK_TIMEOUT_S 2 diff --git a/src/util/pci.c b/src/util/pci.c index 8d2dbb0..0e8cdee 100644 --- a/src/util/pci.c +++ b/src/util/pci.c @@ -96,7 +96,7 @@ struct _pciDeviceList { #define PCI_HEADER_TYPE 0x0e /* Header type */ #define PCI_HEADER_TYPE_BRIDGE 0x1 #define PCI_HEADER_TYPE_MASK 0x7f -#define PCI_HEADER_TYPE_MULTI 0x80 +/*#define PCI_HEADER_TYPE_MULTI 0x80*/ /* PCI30 6.2.1 Device Identification */ #define PCI_CLASS_DEVICE 0x0a /* Device class */ @@ -123,7 +123,7 @@ struct _pciDeviceList { #define PCI_EXP_DEVCAP_FLR (1<<28) /* Function Level Reset */ /* Header type 1 BR12 3.2 PCI-to-PCI Bridge Configuration Space Header Format */ -#define PCI_PRIMARY_BUS 0x18 /* BR12 3.2.5.2 Primary bus number */ +/*#define PCI_PRIMARY_BUS 0x18*/ /* BR12 3.2.5.2 Primary bus number */ #define PCI_SECONDARY_BUS 0x19 /* BR12 3.2.5.3 Secondary bus number */ #define PCI_SUBORDINATE_BUS 0x1a /* BR12 3.2.5.4 Highest bus number behind the bridge */ #define PCI_BRIDGE_CONTROL 0x3e diff --git a/src/util/storage_file.c b/src/util/storage_file.c index ede79fa..c427054 100644 --- a/src/util/storage_file.c +++ b/src/util/storage_file.c @@ -101,7 +101,9 @@ qedGetBackingStore(char **, int *, const unsigned char *, size_t); #define QCOW1_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8+1+1) #define QCOW2_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8) -#define QCOW1_HDR_TOTAL_SIZE (QCOW1_HDR_CRYPT+4+8) +#if 0 +# define QCOW1_HDR_TOTAL_SIZE (QCOW1_HDR_CRYPT+4+8) +#endif #define QCOW2_HDR_TOTAL_SIZE (QCOW2_HDR_CRYPT+4+4+8+8+4+4+8) #define QCOW2_HDR_EXTENSION_END 0 diff --git a/src/vbox/vbox_driver.c b/src/vbox/vbox_driver.c index 9526ee4..6e680ba 100644 --- a/src/vbox/vbox_driver.c +++ b/src/vbox/vbox_driver.c @@ -42,8 +42,6 @@ #include "virterror_internal.h" #include "util.h" -#define VIR_FROM_THIS VIR_FROM_VBOX - extern virDriver vbox22Driver; extern virNetworkDriver vbox22NetworkDriver; @@ -66,7 +64,7 @@ static virDriver vboxDriverDummy; #define VIR_FROM_THIS VIR_FROM_VBOX #define vboxError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_VBOX, code, __FILE__, \ + virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) int vboxRegister(void) { diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c index 8a9dae5..d7d74a4 100644 --- a/src/xen/xen_hypervisor.c +++ b/src/xen/xen_hypervisor.c @@ -80,16 +80,12 @@ typedef struct v0_hypercall_struct { } v0_hypercall_t; #ifdef __linux__ -# define XEN_V0_IOCTL_HYPERCALL_CMD \ - _IOC(_IOC_NONE, 'P', 0, sizeof(v0_hypercall_t)) /* the new one */ typedef struct v1_hypercall_struct { uint64_t op; uint64_t arg[5]; } v1_hypercall_t; -# define XEN_V1_IOCTL_HYPERCALL_CMD \ - _IOC(_IOC_NONE, 'P', 0, sizeof(v1_hypercall_t)) typedef v1_hypercall_t hypercall_t; #elif defined(__sun) typedef privcmd_hypercall_t hypercall_t; @@ -140,8 +136,6 @@ static regex_t xen_cap_rec; # define DOMFLAGS_PAUSED (1<<3) /* Currently paused by control software. */ # define DOMFLAGS_BLOCKED (1<<4) /* Currently blocked pending an event. */ # define DOMFLAGS_RUNNING (1<<5) /* Domain is currently running. */ -# define DOMFLAGS_CPUMASK 255 /* CPU to which this domain is bound. */ -# define DOMFLAGS_CPUSHIFT 8 # define DOMFLAGS_SHUTDOWNMASK 255 /* DOMFLAGS_SHUTDOWN guest-supplied code. */ # define DOMFLAGS_SHUTDOWNSHIFT 16 #endif @@ -2709,13 +2703,13 @@ xenHypervisorMakeCapabilities(virConnectPtr conn) } } - capabilities = fopen ("/sys/hypervisor/properties/capabilities", "r"); + capabilities = fopen(HYPERVISOR_CAPABILITIES, "r"); if (capabilities == NULL) { if (errno != ENOENT) { VIR_FORCE_FCLOSE(cpuinfo); virReportSystemError(errno, _("cannot read file %s"), - "/sys/hypervisor/properties/capabilities"); + HYPERVISOR_CAPABILITIES); return NULL; } } @@ -3175,7 +3169,9 @@ xenHypervisorGetDomInfo(virConnectPtr conn, int id, virDomainInfoPtr info) break; case DOMFLAGS_SHUTDOWN: /* The domain is shutdown. Determine the cause. */ - domain_shutdown_cause = domain_flags >> DOMFLAGS_SHUTDOWNSHIFT; + domain_shutdown_cause = + (domain_flags >> DOMFLAGS_SHUTDOWNSHIFT) & + DOMFLAGS_SHUTDOWNMASK; switch (domain_shutdown_cause) { case SHUTDOWN_crash: info->state = VIR_DOMAIN_CRASHED; diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 7f73588..6c43811 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -52,14 +52,6 @@ #define VIR_FROM_THIS VIR_FROM_XENXM -#ifdef WITH_RHEL5_API -# define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 0 -# define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 2 -#else -# define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 3 -# define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3 -#endif - /* The true Xen limit varies but so far is always way less than 1024, which is the Linux kernel limit according to sched.h, so we'll match that for now */ @@ -78,7 +70,6 @@ static int xenXMDomainDetachDeviceFlags(virDomainPtr domain, const char *xml, #define XEND_CONFIG_FILE "xend-config.sxp" #define XEND_PCI_CONFIG_PREFIX "xend-pci-" #define QEMU_IF_SCRIPT "qemu-ifup" -#define XM_XML_ERROR "Invalid xml" struct xenUnifiedDriver xenXMDriver = { xenXMOpen, /* open */ diff --git a/tests/sockettest.c b/tests/sockettest.c index 2c9ff03..bb44496 100644 --- a/tests/sockettest.c +++ b/tests/sockettest.c @@ -170,16 +170,6 @@ mymain(int argc ATTRIBUTE_UNUSED, if (!virTestGetDebug()) virSetErrorFunc(NULL, testQuietError); -#define DO_TEST_PARSE(addrstr, family, pass) \ - do { \ - virSocketAddr addr; \ - struct testParseData data = { &addr, addrstr, family, pass }; \ - memset(&addr, 0, sizeof(addr)); \ - if (virtTestRun("Test parse " addrstr, \ - 1, testParseHelper, &data) < 0) \ - ret = -1; \ - } while (0) - #define DO_TEST_PARSE_AND_FORMAT(addrstr, family, pass) \ do { \ virSocketAddr addr; \ diff --git a/tools/virsh.c b/tools/virsh.c index 4765f5c..d1c3fe3 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -80,12 +80,12 @@ static char *progname; */ #define MSG_BUFFER 4096 #define SIGN_NAME "virsh" -#define DIR_MODE (S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) /* 0755 */ #define FILE_MODE (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) /* 0644 */ -#define LOCK_MODE (S_IWUSR | S_IRUSR) /* 0600 */ #define LVL_DEBUG "DEBUG" #define LVL_INFO "INFO" +#if 0 #define LVL_NOTICE "NOTICE" +#endif #define LVL_WARNING "WARNING" #define LVL_ERROR "ERROR" @@ -409,15 +409,6 @@ _vshStrdup(vshControl *ctl, const char *s, const char *filename, int line) exit(EXIT_FAILURE); } -/* Poison the raw allocating identifiers in favor of our vsh variants. */ -#undef malloc -#undef calloc -#undef realloc -#undef strdup -#define malloc use_vshMalloc_instead_of_malloc -#define calloc use_vshCalloc_instead_of_calloc -#define realloc use_vshRealloc_instead_of_realloc -#define strdup use_vshStrdup_instead_of_strdup static int idsorter(const void *a, const void *b) { const int *ia = (const int *)a; -- 1.7.4 From berrange at redhat.com Mon Apr 4 16:28:52 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 17:28:52 +0100 Subject: [libvirt] [PATCH] Use gnulib's manywarnings & warnings modules In-Reply-To: <4D95F70A.80509@redhat.com> References: <1301672345-31926-1-git-send-email-berrange@redhat.com> <4D95F70A.80509@redhat.com> Message-ID: <20110404162852.GF13616@redhat.com> On Fri, Apr 01, 2011 at 10:02:18AM -0600, Eric Blake wrote: > On 04/01/2011 09:39 AM, Daniel P. Berrange wrote: > > > > * acinclude.m4: Rewrite to use gl_WARN_ADD and gl_MANYWARN_ALL_GCC > > * bootstrap.conf: Add warnings & manywarnings > > * configure.ac: Switch to gl_WARN_ADD > > * m4/compiler-flags.m4: Obsoleted by gl_WARN_ADD > > --- > > acinclude.m4 | 153 ++++++++++++++++++++++++++------------------------ > > I really don't like how we have crammed so much into acinclude.m4; it > would be nicer if we could separate things into individual m4/foo.m4 > files... The new series moves this file > > + # List of warnings that are not relevant / wanted > > + dontwarn="$dontwarn -Wc++-compat" # Don't care about C++ compiler compat > > + dontwarn="$dontwarn -Wtraditional" # Don't care about ancient C standard compat > > + dontwarn="$dontwarn -Wtraditional-conversion" # Don't care about ancient C standard compat > > + dontwarn="$dontwarn -Wsystem-headers" # Ignore warnings in /usr/include > > + dontwarn="$dontwarn -Wpadded" # Happy for compiler to add struct padding > > + dontwarn="$dontwarn -Wunreachable-code" # GCC very confused with -O2 > > + dontwarn="$dontwarn -Wconversion" # Too many to deal with > > + dontwarn="$dontwarn -Wsign-conversion" # Too many to deal with > > + dontwarn="$dontwarn -Wvla" # GNULIB gettext.h violates > > + dontwarn="$dontwarn -Wundef" # Many GNULIB violations > > We really ought to follow coreutils' lead of generating two separate > lists of -W flags - a larger set for libvirt and a smaller set for > gnulib. Then exemptions such as -Wvla could be used just for gnulib. > But that can be a followup patch. The problem isn't with the compilation of gnulib - that doesn't use any of these flags. The issue is with various things in the gnulib header files, which impact compilation of the main libvirt code. eg ../gnulib/lib/gettext.h:218:3: error: variable length array 'msg_ctxt_id' is used [-Wvla] > > > + dontwarn="$dontwarn -Wcast-qual" # Need to allow bad cast for execve() > > + dontwarn="$dontwarn -Wlong-long" # We need to use long long in many places > > + > > + # We might fundamentally need some of these disabled forever, but ideally > > + # we'd turn many of them on > > + dontwarn="$dontwarn -Wformat-nonliteral" > > + dontwarn="$dontwarn -Wswitch-default" > > + dontwarn="$dontwarn -Wswitch-enum" > > + dontwarn="$dontwarn -Wstrict-overflow" > > + dontwarn="$dontwarn -Wfloat-equal" > > + dontwarn="$dontwarn -Wdeclaration-after-statement" > > + dontwarn="$dontwarn -Wunsafe-loop-optimizations" > > + dontwarn="$dontwarn -Wcast-qual" > > + dontwarn="$dontwarn -Wconversion" > > + dontwarn="$dontwarn -Wsign-conversion" > > + dontwarn="$dontwarn -Wold-style-definition" > > + dontwarn="$dontwarn -Wmissing-noreturn" > > + dontwarn="$dontwarn -Wpacked" > > + dontwarn="$dontwarn -Wunused-macros" > > + dontwarn="$dontwarn -W" > > -W is the same as -Wextra - that turns on a lot of useful warnings. Can > we fine-tune it to just disable the needed warnings? Removing that means I need a manual check for -Wno-sign-compare since gl_MANYWAY_COMPLEMENT can't see that -W include -Wsign-compare > > > + dontwarn="$dontwarn -Woverlength-strings" > > + dontwarn="$dontwarn -Wmissing-format-attribute" > > + dontwarn="$dontwarn -Wstack-protector" > > + > > + # Get all possible GCC warnings > > + gl_MANYWARN_ALL_GCC([maybewarn]) > > + > > + # Remove the ones we don't want, blacklisted earlier > > + gl_MANYWARN_COMPLEMENT([wantwarn], [$maybewarn], [$dontwarn]) > > + > > + # Check for $CC support of each warning > > + for w in $wantwarn; do > > + gl_WARN_ADD([$w]) > > + done > > Yep, gnulib's macros are nice for this! Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From blauwirbel at gmail.com Mon Apr 4 16:38:51 2011 From: blauwirbel at gmail.com (Blue Swirl) Date: Mon, 4 Apr 2011 19:38:51 +0300 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D99D920.1040800@codemonkey.ws> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <20110404104753.GX13616@redhat.com> <4D99C162.7060706@us.ibm.com> <20110404131639.GB13616@redhat.com> <4D99D378.8030206@us.ibm.com> <20110404142612.GD13616@redhat.com> <4D99D920.1040800@codemonkey.ws> Message-ID: On Mon, Apr 4, 2011 at 5:43 PM, Anthony Liguori wrote: > On 04/04/2011 09:26 AM, Daniel P. Berrange wrote: >> >> On Mon, Apr 04, 2011 at 09:19:36AM -0500, Anthony Liguori wrote: >>> >>> On 04/04/2011 08:16 AM, Daniel P. Berrange wrote: >>>> >>>> That doesn't really have any impact. If a desktop user is logged >>>> in, udev may change the ownership to match that user, but if they >>>> aren't, then udev may reset it to root:disk. Either way, QEMU >>>> may loose permissions to the disk. >>> >>> Then if you create a guest without being in the 'disk' group, it'll >>> fail. ?That's pretty expected AFAICT. >> >> We don't *ever* want to put QEMU in the 'disk' group because >> that gives it access to any disk on the system in general. > > If that's what the user wants to do, what's the problem with doing it? > > Setting the global user/group is not enough because just because you have > one VM that you want in disk doesn't mean you want all of them in disk. Privilege separated QEMU sounds so interesting that I'd go for that direction. There could be helper processes which retain privileges and communicate with the main unprivileged QEMU with only file descriptors. The helpers could even execute setgid disk group re-opener for the CD-ROM case, or ask libvirt to do the reopen. For unprivileged QEMU part it wouldn't matter, all it sees are the descriptors. From berrange at redhat.com Mon Apr 4 16:59:50 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 4 Apr 2011 17:59:50 +0100 Subject: [libvirt] [PATCH v2] Improve SCSI volume key generation Message-ID: <1301936390-14887-1-git-send-email-berrange@redhat.com> An update of patch 10 from: http://www.redhat.com/archives/libvir-list/2010-November/msg00555.html The SCSI volumes get a better 'key' field based on the fully qualified volume path. All SCSI volumes have a unique serial available in hardware which can be obtained by sending a suitable SCSI command. Call out to udev's 'scsi_id' command to fetch this value In v2: - Only use scsi_id if HAVE_UDEV is defined. This ensures use only on udev >= 145 and thus avoids problem of different semantics on RHEL-5 vintage udev - Use virCommandPtr instead of virExec - Use VIR_FDOPEN instead of fdopen * src/storage/storage_backend_scsi.c: Improve volume key field value stability and uniqueness --- src/storage/storage_backend_scsi.c | 65 +++++++++++++++++++++++++++++++++-- 1 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c index d880d65..ed91703 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -33,6 +33,7 @@ #include "memory.h" #include "logging.h" #include "files.h" +#include "command.h" #define VIR_FROM_THIS VIR_FROM_STORAGE @@ -160,6 +161,65 @@ cleanup: return ret; } + +static char * +virStorageBackendSCSISerial(const char *dev) +{ + char *serial = NULL; +#ifdef HAVE_UDEV + int fd = -1; + FILE *list = NULL; + char line[1024]; + virCommandPtr cmd = virCommandNewArgList( + "/lib/udev/scsi_id", + "--replace-whitespace", + "--whitelisted", + "--device", dev, + NULL + ); + + /* Run the program and capture its output */ + virCommandSetOutputFD(cmd, &fd); + if (virCommandRunAsync(cmd, NULL) < 0) + goto cleanup; + + if ((list = VIR_FDOPEN(fd, "r")) == NULL) { + virStorageReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot read fd")); + goto cleanup; + } + + if (fgets(line, sizeof(line), list)) { + char *nl = strchr(line, '\n'); + if (nl) + *nl = '\0'; + VIR_ERROR("GOT ID %s\n", line); + serial = strdup(line); + } else { + VIR_ERROR("NO ID %s\n", dev); + serial = strdup(dev); + } + + if (!serial) { + virReportOOMError(); + goto cleanup; + } + +cleanup: + if (list) + fclose(list); + else + VIR_FORCE_CLOSE(fd); + + virCommandFree(cmd); +#else + if (!(serial = strdup(dev))) + virReportOOMError(); +#endif + return serial; +} + + static int virStorageBackendSCSINewLun(virStoragePoolObjPtr pool, uint32_t host ATTRIBUTE_UNUSED, @@ -233,10 +293,7 @@ virStorageBackendSCSINewLun(virStoragePoolObjPtr pool, goto free_vol; } - /* XXX should use logical unit's UUID instead */ - vol->key = strdup(vol->target.path); - if (vol->key == NULL) { - virReportOOMError(); + if (!(vol->key = virStorageBackendSCSISerial(vol->target.path))) { retval = -1; goto free_vol; } -- 1.7.4 From eblake at redhat.com Mon Apr 4 17:12:17 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 11:12:17 -0600 Subject: [libvirt] [PATCH v2] Improve SCSI volume key generation In-Reply-To: <1301936390-14887-1-git-send-email-berrange@redhat.com> References: <1301936390-14887-1-git-send-email-berrange@redhat.com> Message-ID: <4D99FBF1.5000003@redhat.com> On 04/04/2011 10:59 AM, Daniel P. Berrange wrote: > An update of patch 10 from: > > http://www.redhat.com/archives/libvir-list/2010-November/msg00555.html > > The SCSI volumes get a better 'key' field based on the fully > qualified volume path. All SCSI volumes have a unique serial > available in hardware which can be obtained by sending a > suitable SCSI command. Call out to udev's 'scsi_id' command > to fetch this value > > +static char * > +virStorageBackendSCSISerial(const char *dev) > +{ > + char *serial = NULL; > +#ifdef HAVE_UDEV > + int fd = -1; > + FILE *list = NULL; > + char line[1024]; > + virCommandPtr cmd = virCommandNewArgList( > + "/lib/udev/scsi_id", > + "--replace-whitespace", > + "--whitelisted", > + "--device", dev, > + NULL > + ); > + > + /* Run the program and capture its output */ > + virCommandSetOutputFD(cmd, &fd); Why not just run virCommandSetOutputBuffer, to capture the entire output into a single string... > + if (virCommandRunAsync(cmd, NULL) < 0) > + goto cleanup; ...then you just use virCommandRun, > + > + if ((list = VIR_FDOPEN(fd, "r")) == NULL) { ...you don't have to mess with fdopen, > + virStorageReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", _("cannot read fd")); > + goto cleanup; > + } > + > + if (fgets(line, sizeof(line), list)) { ...and you don't have to mess with fgets, > +cleanup: > + if (list) > + fclose(list); and your cleanup gets a lot easier (not to mention that 'make syntax-check' should have been telling you to use VIR_FORCE_FCLOSE if you don't make those simplifications). -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 17:28:23 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 11:28:23 -0600 Subject: [libvirt] [PATCH] build: detect potentential uninitialized variables In-Reply-To: References: <1301673022-7410-1-git-send-email-eblake@redhat.com> Message-ID: <4D99FFB7.7010005@redhat.com> On 04/02/2011 12:15 AM, Matthias Bolte wrote: >> which prints 0 (if the stack was previously wiped) if cond >> was true. Clang will catch it, but we dont' use clang as >> often. Using gcc -Wjump-misses-init gives false positives: >> > > ACK. Thanks; pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 17:30:42 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 11:30:42 -0600 Subject: [libvirt] [PATCH] vmx: Support persistent CPU shares In-Reply-To: References: <20110403124355.GA22943@sbox> <20110404030541.GQ24385@redhat.com> Message-ID: <4D9A0042.8030805@redhat.com> On 04/04/2011 12:28 AM, Matthias Bolte wrote: > 2011/4/4 Daniel Veillard : >> On Sun, Apr 03, 2011 at 02:43:55PM +0200, Matthias Bolte wrote: > >> >> ACK, while nice, it may be a bit late for 0.9.0, okay to wait for the >> next cycle ? We already have this for xen and qemu, seeing it for ESX >> confirms the design is fine, which is the most important from my point >> of vue :-) >> >> Daniel >> > > Sure, this can wait until 0.9.1. On the ESX side the shares value is > persistent anyway. This patch just exposes it as persistent in libvirt > too. 0.9.1 is now started, so feel free to push now :) -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From dallan at redhat.com Mon Apr 4 18:24:37 2011 From: dallan at redhat.com (Dave Allan) Date: Mon, 4 Apr 2011 14:24:37 -0400 Subject: [libvirt] [PATCH] qemu: Don't fail driver startup with ancient qemu In-Reply-To: <20110404133732.GH389283@orkuz.home> References: <2e1f2e4705bb467bcf237647706555bf4e97ec1e.1301923139.git.jdenemar@redhat.com> <20110404132359.GC13616@redhat.com> <20110404133732.GH389283@orkuz.home> Message-ID: <20110404182437.GD4156@redhat.com> On Mon, Apr 04, 2011 at 03:37:32PM +0200, Jiri Denemark wrote: > On Mon, Apr 04, 2011 at 14:23:59 +0100, Daniel P. Berrange wrote: > > On Mon, Apr 04, 2011 at 03:18:59PM +0200, Jiri Denemark wrote: > > > Failure to extract version info (e.g., because qemu binary is so ancient > > > that it doesn't even support -help) shouldn't be considered fatal since > > > we only need it to detect whether qemu supports bootindex option. > > > --- > > > src/qemu/qemu_capabilities.c | 7 ++++--- > > > 1 files changed, 4 insertions(+), 3 deletions(-) > > > > What version QEMU doesn't support -help ? > > > > We only aim to work with QEMU >= 0.9.0 and I'm fairly sure > > that has -help support. > > An ancient one, 0.6.0. But that was just an example. Extracting version info > may fail for a bunch of reasons. The main thing is that it shouldn't fail qemu > driver startup since that results in libvirtd startup failure. Why does driver startup failure result in libvirtd startup failure? Shouldn't it only result in the lack of availability of the driver? Dave From dsahern at gmail.com Mon Apr 4 17:54:25 2011 From: dsahern at gmail.com (David Ahern) Date: Mon, 04 Apr 2011 11:54:25 -0600 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D99C9ED.3020602@codemonkey.ws> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> Message-ID: <4D9A05D1.1000501@gmail.com> On 04/04/11 07:38, Anthony Liguori wrote: > On 04/04/2011 08:22 AM, Avi Kivity wrote: >> On 04/03/2011 02:57 PM, Stefan Hajnoczi wrote: >>> In order for media change to work with Linux host CD-ROM it is >>> necessary to reopen the file (otherwise the inode size will not >>> refresh, this is an issue with existing kernels). >>> >> >> Maybe we should fix the bug in Linux (and backport as necessary)? >> >> I think cd-rom assignment is sufficiently obscure that we can require >> a fixed kernel instead of providing a workaround. > > Do reads fail after CD change? Or do they succeed and the size is just > reported incorrectly? > > If it's the later, I'd agree that it needs fixing in the kernel. If > it's the former, I'd say it's clearly a feature. In January 2010 I was seeing old data -- data from the prior CD -- in the guest after the media change. David From eblake at redhat.com Mon Apr 4 19:31:40 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 13:31:40 -0600 Subject: [libvirt] [PATCH] Allow handshake with child process during startup In-Reply-To: <1301921731-32248-1-git-send-email-berrange@redhat.com> References: <1301921731-32248-1-git-send-email-berrange@redhat.com> Message-ID: <4D9A1C9C.3020501@redhat.com> On 04/04/2011 06:55 AM, Daniel P. Berrange wrote: > Allow the parent process to perform a bi-directional handshake > with the child process during fork/exec. The child process > will fork and do its initial setup. Immediately prior to the > exec(), it will stop & wait for a handshake from the parent > process. The parent process will spawn the child and wait > until the child reaches the handshake point. It will do > whatever extra setup work is required, before signalling the > child to continue. > > The implementation of this is done using two pairs of blocking > pipes. The first pair is used to block the parent, until the > child writes a single byte. Then the second pair pair is used > to block the child, until the parent confirms with another > single byte. How worried are we about the child not doing any async-unsafe actions if it wishes to avoid deadlock? We've already previously identified this as a bug (such as in our handling of malloc in the child), but it's somewhat of a corner-case, and I'm not sure how invasive it will be to fix properly; so I am okay if a fixed version of this patch goes in while we still leave that larger issue open for thought. > +++ b/src/util/command.c > @@ -35,6 +35,11 @@ > #include "files.h" > #include "buf.h" > > +#include > +#include "internal.h" guaranteed this one for us. > +#include > +#include Why do we need this one? We're already using WIFEXITED and friends without explicitly needing this header. > @@ -1115,7 +1129,6 @@ virCommandRun(virCommandPtr cmd, int *exitstatus) > return ret; > } > > - > /* > * Perform all virCommand-specific actions, along with the user hook. > */ Spurious whitespace change? > @@ -1125,12 +1138,61 @@ virCommandHook(void *data) > virCommandPtr cmd = data; > int res = 0; > > - if (cmd->hook) > + if (cmd->hook) { > + VIR_DEBUG("Run hook %p %p", cmd->hook, cmd->opaque); > res = cmd->hook(cmd->opaque); > + VIR_DEBUG("Done hook %d", res); This adds yet more calls to malloc() inside the child, > + } > if (res == 0 && cmd->pwd) { > VIR_DEBUG("Running child in %s", cmd->pwd); ...but no worse than what we've already been doing. If VIR_DEBUG were the only use of malloc() in the child, then it could just boil down to conditionally compiling VIR_DEBUG statements where they can be turned on for debugging the implementation, but compiled out later to avoid deadlock (at least, I'm assuming that VIR_DEBUG uses malloc() to format a timestamp prior to the message when posting to the circular buffer). > res = chdir(cmd->pwd); > + if (res < 0) { > + virReportSystemError(errno, > + _("Unable to change to %s"), cmd->pwd); > + } > + } > + if (cmd->handshake) { > + char c = res < 0 ? '0' : '1'; > + int rv; > + VIR_DEBUG("Notifying parent for handshake start on %d", cmd->handshakeWait[1]); > + if (safewrite(cmd->handshakeWait[1], &c, sizeof(c)) != sizeof(c)) { Since c is char, sizeof(c) == 1 by definition. But I'm okay with you spelling out the longer form. > + virReportSystemError(errno, "%s", _("Unable to notify parent process")); > + return -1; > + } > + > + /* On failure we pass the error message back to parent, > + * so they don't have to dig through stderr logs > + */ > + if (res < 0) { > + virErrorPtr err = virGetLastError(); > + const char *msg = err ? err->message : > + _("Unknown failure during hook execution"); Hmm, now that's a lot more use of malloc(), and not just in VIR_DEBUG() calls. > + > +void virCommandRequireHandshake(virCommandPtr cmd) > +{ > + if (pipe(cmd->handshakeWait) < 0) { NULL dereference if cmd had a previous failure. You need to guard with: if (!cmd || cmd->has_error) return; > + > +int virCommandHandshakeWait(virCommandPtr cmd) > +{ > + char c; > + int rv; > + VIR_DEBUG("Wait for handshake on %d", cmd->handshakeWait[0]); Likewise. > + > +int virCommandHandshakeNotify(virCommandPtr cmd) > +{ > + char c = '1'; > + VIR_DEBUG("Notify handshake on %d", cmd->handshakeWait[0]); Likewise. > +++ b/src/util/command.h > @@ -274,6 +274,11 @@ int virCommandRunAsync(virCommandPtr cmd, > int virCommandWait(virCommandPtr cmd, > int *exitstatus) ATTRIBUTE_RETURN_CHECK; > > +void virCommandRequireHandshake(virCommandPtr cmd); > + > +int virCommandHandshakeWait(virCommandPtr cmd); > +int virCommandHandshakeNotify(virCommandPtr cmd); These last two could use ATTRIBUTE_RETURN_CHECK. All three could use documentation. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 19:49:04 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 13:49:04 -0600 Subject: [libvirt] [PATCH] qemu: Rewrite LOOKUP_PTYS macro into a function In-Reply-To: <6583e184fb3f616c15ec4bc42f1af58fff320a8b.1301924390.git.jdenemar@redhat.com> References: <6583e184fb3f616c15ec4bc42f1af58fff320a8b.1301924390.git.jdenemar@redhat.com> Message-ID: <4D9A20B0.6070405@redhat.com> On 04/04/2011 07:46 AM, Jiri Denemark wrote: > The macro is huge and gives us nothing but headache when maintaining it. > --- > The reason for this patch is not that I'm going to modify anything in > the code. It's that I was working in the area and noticed this huge > macro. > > src/qemu/qemu_process.c | 102 ++++++++++++++++++++++++++++------------------- > 1 files changed, 61 insertions(+), 41 deletions(-) The diffstat hides the fact that this really is a code cleanup. ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 20:29:06 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 14:29:06 -0600 Subject: [libvirt] [PATCH 1/6] Use gnulib's manywarnings & warnings modules In-Reply-To: <1301934004-6204-2-git-send-email-berrange@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> <1301934004-6204-2-git-send-email-berrange@redhat.com> Message-ID: <4D9A2A12.3010401@redhat.com> On 04/04/2011 10:19 AM, Daniel P. Berrange wrote: > Remove custom code for checking compiler warnings, using > gl_WARN_ADD instead. Don't list all flags ourselves, use > gnulib's gl_MANYWARN_ALL_GCC to get all possible GCC flags, > then turn off the ones we don't want yet. > > * acinclude.m4: Rewrite to use gl_WARN_ADD and gl_MANYWARN_ALL_GCC > * bootstrap.conf: Add warnings & manywarnings > * configure.ac: Switch to gl_WARN_ADD > * m4/compiler-flags.m4: Obsoleted by gl_WARN_ADD > --- > acinclude.m4 | 158 +++++++++++++++++++++++++++----------------------- > bootstrap.conf | 2 + > configure.ac | 15 +++-- > m4/compiler-flags.m4 | 48 --------------- > 4 files changed, 96 insertions(+), 127 deletions(-) > delete mode 100644 m4/compiler-flags.m4 > + > + # List of warnings that are not relevant / wanted > + dontwarn="$dontwarn -Wc++-compat" # Don't care about C++ compiler compat > + dontwarn="$dontwarn -Wtraditional" # Don't care about ancient C standard compat > + dontwarn="$dontwarn -Wtraditional-conversion" # Don't care about ancient C standard compat > + dontwarn="$dontwarn -Wsystem-headers" # Ignore warnings in /usr/include > + dontwarn="$dontwarn -Wpadded" # Happy for compiler to add struct padding > + dontwarn="$dontwarn -Wunreachable-code" # GCC very confused with -O2 > + dontwarn="$dontwarn -Wconversion" # Too many to deal with > + dontwarn="$dontwarn -Wsign-conversion" # Too many to deal with > + dontwarn="$dontwarn -Wvla" # GNULIB gettext.h violates > + dontwarn="$dontwarn -Wundef" # Many GNULIB violations > + dontwarn="$dontwarn -Wcast-qual" # Need to allow bad cast for execve() > + dontwarn="$dontwarn -Wlong-long" # We need to use long long in many places > + dontwarn="$dontwarn -Wswitch-default" # We allow manual list of all enum cases without default: > + dontwarn="$dontwarn -Wswitch-enum" # We allow optional default: instead of listing all enum values > + dontwarn="$dontwarn -Wstrict-overflow" # Not a problem since we don't use -fstrict-overflow > + dontwarn="$dontwarn -Wunsafe-loop-optimizations" # Not a problem since we don't use -funsafe-loop-optimizations Seems okay (but long lines - any way to break that into 80 columns?) > + > + # We might fundamentally need some of these disabled forever, but ideally > + # we'd turn many of them on > + dontwarn="$dontwarn -Wformat-nonliteral" This one may need to always be disabled, thanks to virAsprintf (it would be nicer if we could disable for just one or two files, rather than globally). > + dontwarn="$dontwarn -Wfloat-equal" > + dontwarn="$dontwarn -Wdeclaration-after-statement" If gcc would do better, I'd love to guarantee C99 and take advantage of this (smaller scopes have maintenance benefits) - thus, I envision this one being permanent (float it up to the earlier set). > + dontwarn="$dontwarn -Wcast-qual" > + dontwarn="$dontwarn -Wconversion" > + dontwarn="$dontwarn -Wsign-conversion" > + dontwarn="$dontwarn -Wold-style-definition" > + dontwarn="$dontwarn -Wmissing-noreturn" > + dontwarn="$dontwarn -Wpacked" > + dontwarn="$dontwarn -Wunused-macros" > + dontwarn="$dontwarn -Woverlength-strings" > + dontwarn="$dontwarn -Wmissing-format-attribute" > + dontwarn="$dontwarn -Wstack-protector" Yes, I agree that the rest of these should be temporary, and are probably worth fixing. > + > + # Get all possible GCC warnings > + gl_MANYWARN_ALL_GCC([maybewarn]) > + > + # Remove the ones we don't want, blacklisted earlier > + gl_MANYWARN_COMPLEMENT([wantwarn], [$maybewarn], [$dontwarn]) > + > + # Check for $CC support of each warning > + for w in $wantwarn; do > + gl_WARN_ADD([$w]) > + done > + > + # GNULIB uses '-W' which includes a bunch of stuff, > + # kinda like -Wextra. Unfortunately, it means you "kinda like"? Exactly like! -W was the old spelling, -Wextra was the new one (added quite some time ago; something like gcc 3.4, off the top of my head). > + # can't simply use '-Wsign-compare' with gl_MANYWARN_COMPLEMENT > + # So we have -W enabled, and then have to explicitly turn off > + gl_WARN_ADD(-Wno-sign-compare) > + > + # This should be < 256 really, but with PATH_MAX everywhere > + # we have doom, even with 4096. In fact we have some functions > + # with several PATH_MAX sized variables :-( We should kill off > + # all PATH_MAX usage and then lower this limit > + gl_WARN_ADD([-Wframe-larger-than=65700]) > + dnl gl_WARN_ADD([-Wframe-larger-than=4096]) > + dnl gl_WARN_ADD([-Wframe-larger-than=256]) > + > + # Extra special flags > + gl_WARN_ADD([-Wp,-D_FORTIFY_SOURCE=2]) > + dnl Fedora only uses -fstack-protector, but doesn't seem to > + dnl be great overhead in adding -fstack-protector-all instead > + dnl gl_WARN_ADD([-fstack-protector]) > + gl_WARN_ADD([-fstack-protector-all]) > + gl_WARN_ADD([--param=ssp-buffer-size=4]) > + gl_WARN_ADD([-fexceptions]) > + gl_WARN_ADD([-fasynchronous-unwind-tables]) > + gl_WARN_ADD([-fdiagnostics-show-option]) > + > + if test "$enable_compile_warnings" = "error" > + then > + gl_WARN_ADD([-Werror]) > + fi Looks like a good conversion. > @@ -81,6 +82,7 @@ timegm > uname > useless-if-before-free > usleep > +warnings > vasprintf > verify > vc-list-files Where did you learn to sort? :) > diff --git a/configure.ac b/configure.ac > index a8d223a..7874c30 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -1970,12 +1970,14 @@ AC_ARG_ENABLE([test-coverage], > enable_coverage=$enableval > > if test "${enable_coverage}" = yes; then > - COMPILER_FLAGS= > - gl_COMPILER_FLAGS(-fprofile-arcs) > - gl_COMPILER_FLAGS(-ftest-coverage) > - AC_SUBST([COVERAGE_CFLAGS], [$COMPILER_FLAGS]) > - AC_SUBST([COVERAGE_LDFLAGS], [$COMPILER_FLAGS]) > - COMPILER_FLAGS= > + save_WARN_CFLAGS=$WARN_CFLAGS > + WARN_CFLAGS= > + gl_WARN_ADD(-fprofile-arcs) > + gl_WARN_ADD(-ftest-coverage) Nit: use consistent m4 quoting: gl_WARN_ADD([-fprofile-arcs]) ACK with nits addressed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 20:37:00 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 14:37:00 -0600 Subject: [libvirt] [PATCH 2/6] Remove acinclude.m4 file In-Reply-To: <1301934004-6204-3-git-send-email-berrange@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> <1301934004-6204-3-git-send-email-berrange@redhat.com> Message-ID: <4D9A2BEC.1080809@redhat.com> On 04/04/2011 10:20 AM, Daniel P. Berrange wrote: > Split the bit acinclude.m4 file into smaller pieces named > as m4/virt-XXXXX.m4 > > * .gitignore: Ignore gettext related files > * acinclude.m4: Delete > * m4/virt-compile-warnings.m4: Checks for GCC compiler flags > * m4/virt-pkgconfig-back-compat.m4: Backcompat check for > pkgconfig program > --- > .gitignore | 36 +++++++++- > acinclude.m4 | 137 -------------------------------------- > m4/virt-compile-warnings.m4 | 112 +++++++++++++++++++++++++++++++ > m4/virt-pkgconfig-back-compat.m4 | 23 ++++++ > 4 files changed, 169 insertions(+), 139 deletions(-) > delete mode 100644 acinclude.m4 > create mode 100644 m4/virt-compile-warnings.m4 > create mode 100644 m4/virt-pkgconfig-back-compat.m4 > > diff --git a/.gitignore b/.gitignore > index ba4d351..278bc4f 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -1,4 +1,3 @@ > -!/m4/compiler-flags.m4 > !/po/*.po > !/po/POTFILES.in > !/po/libvirt.pot > @@ -46,7 +45,6 @@ > /libvirt.spec Yuck - gnulib's bootstrap script sorts .gitignore, but this is broken (lines starting with ! should come last, not first, according to 'man gitignore'; it's a shame I'm just noticing it now, since it's been broken since November 2010). > @@ -67,3 +65,37 @@ results.log > stamp-h > stamp-h.in > stamp-h1 > +m4/codeset.m4 > +m4/gettext.m4 Rerunning bootstrap will re-sort this list, leading to spurious diffs unless we get it sorted first. But why should we blacklist all of the m4 files individually, when it is much easier to whitelist just the files we want? /m4/ !/m4/virt-*.m4 I've posted an upstream bug to gnulib about bootstrap botching sort order; let's get that fixed first and then respin this patch on top of that one. However, even though it's not ready for prime-time yet, I'm pleased with the concept of splitting things into easier-to-find per-file macros. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 20:40:28 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 14:40:28 -0600 Subject: [libvirt] [PATCH 3/6] Enable -Wmissing-format-attribute warning In-Reply-To: <1301934004-6204-4-git-send-email-berrange@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> <1301934004-6204-4-git-send-email-berrange@redhat.com> Message-ID: <4D9A2CBC.8060401@redhat.com> On 04/04/2011 10:20 AM, Daniel P. Berrange wrote: > Add a couple of missing ATTRIBUTE_FMT_PRINTF annotations > > * tools/virsh.c, tests/testutils.c: Add printf format attribute > * m4/virt-compile-warnings.m4: Enable -Wmissing-format-attribute > > - > +ATTRIBUTE_FMT_PRINTF(3,4) > void virtTestResult(const char *name, int ret, const char *msg, ...) gcc attribute syntax is screwy. I'm somewhat used to: void ATTRIBUTE_FMT_PRINTF(3,4) virtTestResult(...) but if doing the attribute before the return type works, great. > { > va_list vargs; > diff --git a/tools/virsh.c b/tools/virsh.c > index 19e3449..4765f5c 100644 > --- a/tools/virsh.c > +++ b/tools/virsh.c > @@ -243,7 +243,8 @@ static int vshInit(vshControl *ctl); > static int vshDeinit(vshControl *ctl); > static void vshUsage(void); > static void vshOpenLogFile(vshControl *ctl); > -static void vshOutputLogFile(vshControl *ctl, int log_level, const char *format, va_list ap); > +static void vshOutputLogFile(vshControl *ctl, int log_level, const char *format, va_list ap) > + ATTRIBUTE_FMT_PRINTF(3, 0); > static void vshCloseLogFile(vshControl *ctl); ACK (although rebasing this to apply before we fix patch 2/6 vs. gnulib bootstrap may not be worth your time). -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 20:42:18 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 14:42:18 -0600 Subject: [libvirt] [PATCH 4/6] Enable use of -Wmissing-noreturn In-Reply-To: <1301934004-6204-5-git-send-email-berrange@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> <1301934004-6204-5-git-send-email-berrange@redhat.com> Message-ID: <4D9A2D2A.3060108@redhat.com> On 04/04/2011 10:20 AM, Daniel P. Berrange wrote: > * src/internal.h: Define a ATTRIBUTE_NO_RETURN annotation > * src/lxc/lxc_container.c: Annotate lxcContainerDummyChild > with ATTRIBUTE_NO_RETURN > * tests/eventtest.c: Mark async thread as ATTRIBUTE_NO_RETURN > * m4/virt-compile-warnings.m4: Enable -Wmissing-noreturn > --- > m4/virt-compile-warnings.m4 | 1 - > src/internal.h | 9 +++++++++ > src/lxc/lxc_container.c | 3 ++- > tests/eventtest.c | 3 +-- > 4 files changed, 12 insertions(+), 4 deletions(-) > > +++ b/src/internal.h > @@ -117,6 +117,15 @@ > # endif > > /** > + * ATTRIBUTE_NORETURN: > + * > + * Macro to indicate that a function won't return to the caller > + */ > +# ifndef ATTRIBUTE_NORETURN > +# define ATTRIBUTE_NORETURN __attribute__((__noreturn__)) > +# endif Do we need a minimum gcc version detection, so this cause grief on older setups? At any rate, ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 20:44:21 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 14:44:21 -0600 Subject: [libvirt] [PATCH 5/6] Enable use of -Wold-style-definition compiler flag In-Reply-To: <1301934004-6204-6-git-send-email-berrange@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> <1301934004-6204-6-git-send-email-berrange@redhat.com> Message-ID: <4D9A2DA5.8040900@redhat.com> On 04/04/2011 10:20 AM, Daniel P. Berrange wrote: > A couple of functions were declared using the old style foo() > for no-parameters, instead of foo(void) > > * src/xen/xen_hypervisor.c, tests/testutils.c: Replace () with (void) > in some function declarations > * m4/virt-compile-warnings.m4: Enable -Wold-style-definition > --- > m4/virt-compile-warnings.m4 | 1 - > src/xen/xen_hypervisor.c | 2 +- > tests/testutils.c | 4 ++-- > 3 files changed, 3 insertions(+), 4 deletions(-) ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 20:54:28 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 14:54:28 -0600 Subject: [libvirt] [PATCH 6/6] Remove unused macros and enable -Wunused-macros In-Reply-To: <1301934004-6204-7-git-send-email-berrange@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> <1301934004-6204-7-git-send-email-berrange@redhat.com> Message-ID: <4D9A3004.50305@redhat.com> On 04/04/2011 10:20 AM, Daniel P. Berrange wrote: > * m4/virt-compile-warnings.m4: Enable -Wunused-macros > * daemon/libvirtd.c: Remove MAX_LISTEN > * daemon/remote.c: Remote VIR_FROM_THIS s/Remote/Remove/ > 33 files changed, 38 insertions(+), 108 deletions(-) Nice ratio! > +++ b/src/esx/esx_vi_methods.c > @@ -1,4 +1,3 @@ > - > /* > * esx_vi_methods.c: client for the VMware VI API 2.5 to manage ESX hosts > * > @@ -52,8 +51,10 @@ > > > > +#if 0 > #define ESX_VI__METHOD__CHECK_OUTPUT__RequiredList \ Won't this cause 'make syntax-check' grief during cppi checks? (Multiple instances) > +++ b/tools/virsh.c > @@ -409,15 +409,6 @@ _vshStrdup(vshControl *ctl, const char *s, const char *filename, int line) > exit(EXIT_FAILURE); > } > > -/* Poison the raw allocating identifiers in favor of our vsh variants. */ > -#undef malloc > -#undef calloc > -#undef realloc > -#undef strdup > -#define malloc use_vshMalloc_instead_of_malloc > -#define calloc use_vshCalloc_instead_of_calloc > -#define realloc use_vshRealloc_instead_of_realloc > -#define strdup use_vshStrdup_instead_of_strdup Hmm, I don't want to completely lose this. Can we instead include "warn-on-use.h" (already provided by gnulib) and do: _GL_WARN_ON_USE(malloc, "use vshMalloc instead of malloc"); to get the same poisoning effects but via magic attributes rather than unused macros? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jdenemar at redhat.com Mon Apr 4 22:08:17 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 5 Apr 2011 00:08:17 +0200 Subject: [libvirt] [PATCH] qemu: Ignore unusable binaries Message-ID: When initializing qemu guest capabilities, we should ignore qemu binaries that we are not able to extract version/help info from since they will be unusable for creating domains anyway. Ignoring them is also much better than letting initialization of qemu driver fail. --- src/qemu/qemu_capabilities.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index f86e7f5..63486cc 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -490,6 +490,12 @@ qemuCapsInitGuest(virCapsPtr caps, if (!binary) return 0; + /* Ignore binary if extracting version info fails */ + if (qemuCapsExtractVersionInfo(binary, info->arch, NULL, &qemuCaps) < 0) { + ret = 0; + goto cleanup; + } + if (stat(binary, &st) == 0) { binary_mtime = st.st_mtime; } else { @@ -554,9 +560,8 @@ qemuCapsInitGuest(virCapsPtr caps, !virCapabilitiesAddGuestFeature(guest, "cpuselection", 1, 0)) goto error; - if (qemuCapsExtractVersionInfo(binary, info->arch, NULL, &qemuCaps) < 0 || - (qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX) && - !virCapabilitiesAddGuestFeature(guest, "deviceboot", 1, 0))) + if (qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX) && + !virCapabilitiesAddGuestFeature(guest, "deviceboot", 1, 0)) goto error; if (hvm) { -- 1.7.4.1 From eblake at redhat.com Mon Apr 4 22:09:12 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 16:09:12 -0600 Subject: [libvirt] [PATCH 07/12] Introduce generic RPC server objects In-Reply-To: <1300474467-23485-8-git-send-email-berrange@redhat.com> References: <1300474467-23485-1-git-send-email-berrange@redhat.com> <1300474467-23485-8-git-send-email-berrange@redhat.com> Message-ID: <4D9A4188.2050301@redhat.com> On 03/18/2011 12:54 PM, Daniel P. Berrange wrote: > To facilitate creation of new daemons providing XDR RPC services, > pull alot of the libvirtd daemon code into a set of reusable > objects. Part 3. Hopefully I finish before sending this time. > +int virNetServerAddService(virNetServerPtr srv, > + virNetServerServicePtr svc) > + > +int virNetServerSetTLSContext(virNetServerPtr srv, > + virNetTLSContextPtr tls) > +{ > + srv->tls = tls; > + virNetTLSContextRef(tls); > + return 0; No virNetServerLock(srv)? > +static void virNetServerAutoShutdownTimer(int timerid ATTRIBUTE_UNUSED, > + void *opaque) { > + virNetServerPtr srv = opaque; > + > + virNetServerLock(srv); > + > + if (srv->autoShutdownFunc(srv, srv->autoShutdownOpaque)) { > + VIR_DEBUG0("Automatic shutdown triggered"); > + srv->quit = 1; Should srv->quit be bool instead of int? > +void virNetServerRun(virNetServerPtr srv) > +{ > + int timerid = -1; > + int timerActive = 0; > + int i; > + > + virNetServerLock(srv); > + > + if (srv->autoShutdownTimeout && > + (timerid = virEventAddTimeout(-1, > + virNetServerAutoShutdownTimer, > + srv, NULL)) < 0) { > + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Failed to register shutdown timeout")); > + goto cleanup; > + } > + > + while (!srv->quit) { > + /* A shutdown timeout is specified, so check > + * if any drivers have active state, if not > + * shutdown after timeout seconds > + */ > + if (srv->autoShutdownTimeout) { > + if (timerActive) { > + if (srv->clients) { > + VIR_DEBUG("Deactivating shutdown timer %d", timerid); > + virEventUpdateTimeout(timerid, -1); > + timerActive = 0; > + } > + } else { > + if (!srv->clients) { > + VIR_DEBUG("Activating shutdown timer %d", timerid); > + virEventUpdateTimeout(timerid, > + srv->autoShutdownTimeout * 1000); Do we need to worry about overflow here (that is, should srv->autoShutdownTimeout be validated to be less than INT_MAX/1000 earlier on)? > + timerActive = 1; > + } > + } > + } > + > + virNetServerUnlock(srv); > + if (virEventRunDefaultImpl() < 0) { > + virNetServerLock(srv); > + VIR_DEBUG0("Loop iteration error, exiting"); > + break; > + } > + virNetServerLock(srv); > + > + reprocess: > + for (i = 0 ; i < srv->nclients ; i++) { > + if (virNetServerClientWantClose(srv->clients[i])) > + virNetServerClientClose(srv->clients[i]); > + if (virNetServerClientIsClosed(srv->clients[i])) { > + virNetServerClientFree(srv->clients[i]); Do we really want to hold the server lock while calling these two client-related functions? Or is this a recipe for deadlock? > +++ b/src/rpc/virnetserver.h > @@ -0,0 +1,80 @@ > + > +# include "internal.h" should guarantee this > + > +void virNetServerRef(virNetServerPtr srv); ATTRIBUTE_NONNULL(1) > + > +bool virNetServerIsPrivileged(virNetServerPtr srv); ATTRIBUTE_NONNULL(1) > + > +void virNetServerAutoShutdown(virNetServerPtr srv, > + unsigned int timeout, > + virNetServerAutoShutdownFunc func, > + void *opaque); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) > + > +typedef void (*virNetServerSignalFunc)(virNetServerPtr srv, siginfo_t *info, void *opaque); > + > +int virNetServerAddSignalHandler(virNetServerPtr srv, > + int signum, > + virNetServerSignalFunc func, > + void *opaque); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) > + > +int virNetServerAddService(virNetServerPtr srv, > + virNetServerServicePtr svc); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) > + > +int virNetServerAddProgram(virNetServerPtr srv, > + virNetServerProgramPtr prog); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) > + > +int virNetServerSetTLSContext(virNetServerPtr srv, > + virNetTLSContextPtr tls); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) > + > +void virNetServerUpdateServices(virNetServerPtr srv, > + bool enabled); ATTRIBUTE_NONNULL(1) > + > +void virNetServerRun(virNetServerPtr srv); ATTRIBUTE_NONNULL(1) > + > +void virNetServerQuit(virNetServerPtr srv); ATTRIBUTE_NONNULL(1) > +++ b/src/rpc/virnetserverclient.c > @@ -0,0 +1,938 @@ > + > +#include > + > +#if HAVE_SASL > +# include > +#endif Do we really need this, or did it get taken care of by hiding all SASL details behind virNetSASL* > +struct _virNetServerClient > +{ > + int refs; > + bool wantClose; > + virMutex lock; > + virNetSocketPtr sock; > + int auth; > + bool readonly; > + char *identity; > + virNetTLSContextPtr tlsCtxt; > + virNetTLSSessionPtr tls; > +#if HAVE_SASL > + virNetSASLSessionPtr sasl; > +#endif > + > + /* Count of messages in the 'tx' queue, > + * and the server worker pool queue > + * ie RPC calls in progress. Does not count s/ie/i.e./ > + * async events which are not used for > + * throttling calculations */ > + size_t nrequests; > + size_t nrequests_max; > + /* Zero or one messages being received. Zero if > + * nrequests >= max_clients and throttling */ > + virNetMessagePtr rx; > + /* Zero or many messages waiting for transmit > + * back to client, including async events */ > + virNetMessagePtr tx; > + > + /* Filters to capture messages that would otherwise > + * end up on the 'dx' queue */ dx? Did you mean tx? > + > +/* > + * @server: a locked or unlocked server object > + * @client: a locked client object > + */ > +static int virNetServerClientRegisterEvent(virNetServerClientPtr client) No @server argument; too much copy-n-paste? > + > +int virNetServerClientAddFilter(virNetServerClientPtr client, > + virNetServerClientFilterFunc func, > + void *opaque) No docs? > + > + > +void virNetServerClientRemoveFilter(virNetServerClientPtr client, > + int filterID) > +{ > + virNetServerClientFilterPtr tmp, prev; > + virNetServerClientLock(client); > + > + prev = NULL; > + tmp = client->filters; > + while (tmp) { > + if (tmp->id == filterID) { > + if (prev) > + prev->next = tmp->next; > + else > + client->filters = tmp->next; > + > + VIR_FREE(tmp); > + break; > + } > + tmp = tmp->next; > + } Where does prev get set in that loop? > + > + > +virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock, > + int auth, > + bool readonly, > + virNetTLSContextPtr tls) > +{ > + virNetServerClientPtr client; > + > + VIR_DEBUG("sock=%p auth=%d tls=%p", sock, auth, tls); > + > + if (VIR_ALLOC(client) < 0) { > + virReportOOMError(); > + return NULL; > + } > + > + if (virMutexInit(&client->lock) < 0) > + goto error; > + > + client->refs = 1; > + client->sock = sock; > + client->auth = auth; > + client->readonly = readonly; > + client->tlsCtxt = tls; > + client->nrequests_max = 10; /* XXX */ Any plans to change this, such as making it a caller-settable parameter (which the caller can then load from a conf file)? Does it really matter? > + > + if (tls) > + virNetTLSContextRef(tls); > + > + /* Prepare one for packet receive */ > + if (!(client->rx = virNetMessageNew())) > + goto error; > + client->rx->bufferLength = VIR_NET_MESSAGE_LEN_MAX; > + client->nrequests = 1; > + > + VIR_DEBUG("client=%p refs=%d", client, client->refs); > + > + return client; > + > +error: > + /* XXX ref counting is better than this */ > + client->sock = NULL; /* Caller owns 'sock' upon failure */ > + virNetServerClientFree(client); Should we clean this up first? > + > +void virNetServerClientRef(virNetServerClientPtr client) > +{ > + virNetServerClientLock(client); > + client->refs++; > + VIR_DEBUG("client=%p refs=%d", client, client->refs); > + virNetServerClientUnlock(client); virObject and atomic ref-counting seems like it might be nice to get in first. > +bool virNetServerClientGetReadonly(virNetServerClientPtr client) > +{ > + bool readonly; > + virNetServerClientLock(client); > + readonly = client->readonly; > + virNetServerClientUnlock(client); > + return readonly; Do we need to lock in order to read data that should never be changed after the client is first created? > +int virNetServerClientGetFD(virNetServerClientPtr client) > +{ > + int fd = 0; Why do you init this to 0, > + virNetServerClientLock(client); > + fd = virNetSocketGetFD(client->sock); > + virNetServerClientUnlock(client); > + return fd; if it will always get overwritten, and since -1 is a safer init value for an fd? > +bool virNetServerClientIsSecure(virNetServerClientPtr client) > +{ > + bool secure = false; > + virNetServerClientLock(client); > + if (client->tls) > + secure = true; > +#if HAVE_SASL > + if (client->sasl) else if > + secure = true; > +#endif > + if (virNetSocketIsLocal(client->sock)) else if (no need to spend time on calling virNetSocketIsLocal if we already had our answer from client->tls or client->sasl) > +void virNetServerClientSetPrivateData(virNetServerClientPtr client, > + void *opaque, > + virNetServerClientFreeFunc ff) > +{ > + virNetServerClientLock(client); > + > + if (client->privateData && > + client->privateDataFreeFunc) > + client->privateDataFreeFunc(client->privateData); Should this be deferred, and the old function and data cached for calling after locks are dropped, so that the callback can't deadlock with other client-locked functions? > +void virNetServerClientFree(virNetServerClientPtr client) > +{ > + if (!client) > + return; > + > + virNetServerClientLock(client); > + VIR_DEBUG("client=%p refs=%d", client, client->refs); > + > + client->refs--; > + if (client->refs > 0) { > + virNetServerClientUnlock(client); > + return; > + } > + > + if (client->privateData && > + client->privateDataFreeFunc) > + client->privateDataFreeFunc(client->privateData); Likewise to calling this outside lock? > +/* > + * > + * We don't free stuff here, merely disconnect the client's > + * network socket & resources. > + * > + * Full free of the client is done later in a safe point > + * where it can be guaranteed it is no longer in use > + */ > +void virNetServerClientClose(virNetServerClientPtr client) > +{ > + virNetServerClientLock(client); > + VIR_DEBUG("client=%p refs=%d", client, client->refs); > + if (!client->sock) { > + virNetServerClientUnlock(client); > + return; > + } > + > + /* Do now, even though we don't close the socket > + * until end, to ensure we don't get invoked > + * again due to tls shutdown */ > + if (client->sock) > + virNetSocketRemoveIOCallback(client->sock); > + > + if (client->tls) { > + virNetTLSSessionFree(client->tls); > + client->tls = NULL; > + } > + if (client->sock) { > + virNetSocketFree(client->sock); > + client->sock = NULL; > + } > + > + while (client->rx) { > + virNetMessagePtr msg > + = virNetMessageQueueServe(&client->rx); > + virNetMessageFree(msg); > + } > + while (client->tx) { > + virNetMessagePtr msg > + = virNetMessageQueueServe(&client->tx); > + virNetMessageFree(msg); > + } Should we flush tx before rx, in case the act of flushing tx results in a couple more responses received? > +bool virNetServerClientIsClosed(virNetServerClientPtr client) > +{ > + bool closed; > + virNetServerClientLock(client); > + closed = client->sock == NULL ? true : false; I would have written closed = (client->sock == NULL) or even closed = !!client->sock > + > +/* > + * Read data until we get a complete message to process > + */ > +static void virNetServerClientDispatchRead(virNetServerClientPtr client) > +{ > +readmore: > + if (virNetServerClientRead(client) < 0) { > + client->wantClose = true; > + return; /* Error */ > + } > + > + if (client->rx->bufferOffset < client->rx->bufferLength) > + return; /* Still not read enough */ > + > + /* Either done with length word header */ > + if (client->rx->bufferLength == VIR_NET_MESSAGE_LEN_MAX) { > + if (virNetMessageDecodeLength(client->rx) < 0) > + return; > + > + virNetServerClientUpdateEvent(client); > + > + /* Try and read payload immediately instead of going back > + into poll() because chances are the data is already > + waiting for us */ > + goto readmore; > + } else { > + /* Grab the completed message */ > + virNetMessagePtr msg = virNetMessageQueueServe(&client->rx); > + virNetServerClientFilterPtr filter; > + > + /* Decode the header so we can use it for routing decisions */ > + if (virNetMessageDecodeHeader(msg) < 0) { > + virNetMessageFree(msg); > + client->wantClose = true; > + return; > + } > + > + /* Maybe send off for queue against a filter */ > + filter = client->filters; > + while (filter) { > + int ret = filter->func(client, msg, filter->opaque); > + if (ret < 0 || ret > 0) { ret != 0 When do the filters return > 0? > + virNetMessageFree(msg); > + msg = NULL; > + if (ret < 0) > + client->wantClose = true; > + break; > + } > + > + filter = filter->next; > + } > + > + /* Send off to for normal dispatch to workers */ > + if (msg) { > + if (!client->dispatchFunc || > + client->dispatchFunc(client, msg, client->dispatchOpaque) < 0) { Should we log the case of client->dispatchFunc being NULL? > + > +static void > +virNetServerClientDispatchHandshake(virNetServerClientPtr client) > +{ > + int ret; > + /* Continue the handshake. */ > + ret = virNetTLSSessionHandshake(client->tls); > + if (ret == 0) { > + /* Finished. Next step is to check the certificate. */ > + if (virNetServerClientCheckAccess(client) < 0) > + client->wantClose = true; > + else > + virNetServerClientUpdateEvent(client); > + } else if (ret > 0) { > + /* Carry on waiting for more handshake. Update > + the events just in case handshake data flow > + direction has changed */ > + virNetServerClientUpdateEvent (client); s/ (/(/ > +++ b/src/rpc/virnetserverclient.h > @@ -0,0 +1,106 @@ > + > +virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock, > + int auth, > + bool readonly, > + virNetTLSContextPtr tls); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4) > + > +int virNetServerClientAddFilter(virNetServerClientPtr client, > + virNetServerClientFilterFunc func, > + void *opaque); ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK > + > +void virNetServerClientRemoveFilter(virNetServerClientPtr client, > + int filterID); ATTRIBUTE_NONNULL(1) > + > +int virNetServerClientGetAuth(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > +bool virNetServerClientGetReadonly(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > + > +bool virNetServerClientHasTLSSession(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > +int virNetServerClientGetTLSKeySize(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > + > +#ifdef HAVE_SASL > +void virNetServerClientSetSASLSession(virNetServerClientPtr client, > + virNetSASLSessionPtr sasl); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) > +#endif > + > +int virNetServerClientGetFD(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > + > +bool virNetServerClientIsSecure(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > + > +int virNetServerClientSetIdentity(virNetServerClientPtr client, > + const char *identity); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) > +const char *virNetServerClientGetIdentity(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > + > +int virNetServerClientGetLocalIdentity(virNetServerClientPtr client, > + uid_t *uid, pid_t *pid); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) > + > +void virNetServerClientRef(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > + > +typedef void (*virNetServerClientFreeFunc)(void *data); > + > +void virNetServerClientSetPrivateData(virNetServerClientPtr client, > + void *opaque, > + virNetServerClientFreeFunc ff); ATTRIBUTE_NONNULL(1) > +void *virNetServerClientGetPrivateData(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > + > +void virNetServerClientSetDispatcher(virNetServerClientPtr client, > + virNetServerClientDispatchFunc func, > + void *opaque); ATTRIBUTE_NONNULL(1) > +void virNetServerClientClose(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > + > +bool virNetServerClientIsClosed(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > +void virNetServerClientMarkClose(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > +bool virNetServerClientWantClose(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > + > +int virNetServerClientInit(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK > + > +const char *virNetServerClientLocalAddrString(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK > +const char *virNetServerClientRemoteAddrString(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK > + > +int virNetServerClientSendMessage(virNetServerClientPtr client, > + virNetMessagePtr msg); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) > + > +bool virNetServerClientNeedAuth(virNetServerClientPtr client); ATTRIBUTE_NONNULL(1) > +++ b/src/rpc/virnetserverprogram.c > +static int > +virNetServerProgramDispatchCall(virNetServerProgramPtr prog, > + virNetServerPtr server, > + virNetServerClientPtr client, > + virNetMessagePtr msg) > +{ > + /* > + * When the RPC handler is called: > + * > + * - Server object is unlocked > + * - Client object is unlocked > + * > + * Without locking, it is safe to use: > + * > + * 'args and 'ret' s/'args/'args'/ > +++ b/src/rpc/virnetserverprogram.h > @@ -0,0 +1,107 @@ > +# define __VIR_NET_PROGRAM_H__ > + > +# include Provided by "internal.h" > + > +struct _virNetServerProgramProc { > + virNetServerProgramDispatchFunc func; > + size_t arg_len; > + xdrproc_t arg_filter; > + size_t ret_len; > + xdrproc_t ret_filter; > + bool needAuth; > +}; > + > +virNetServerProgramPtr virNetServerProgramNew(unsigned program, > + unsigned version, > + virNetServerProgramProcPtr procs, > + size_t nprocs); ATTRIBUTE_NONNULL(3) > + > +int virNetServerProgramGetID(virNetServerProgramPtr prog); ATTRIBUTE_NONNULL(1) > +int virNetServerProgramGetVersion(virNetServerProgramPtr prog); ATTRIBUTE_NONNULL(1) > + > +void virNetServerProgramRef(virNetServerProgramPtr prog); ATTRIBUTE_NONNULL(1) > + > +int virNetServerProgramMatches(virNetServerProgramPtr prog, > + virNetMessagePtr msg); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) > + > +int virNetServerProgramDispatch(virNetServerProgramPtr prog, > + virNetServerPtr server, > + virNetServerClientPtr client, > + virNetMessagePtr msg); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) > + > +int virNetServerProgramSendReplyError(virNetServerProgramPtr prog, > + virNetServerClientPtr client, > + virNetMessagePtr msg, > + virNetMessageErrorPtr rerr, > + virNetMessageHeaderPtr req); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) > + > +int virNetServerProgramSendStreamError(virNetServerProgramPtr prog, > + virNetServerClientPtr client, > + virNetMessagePtr msg, > + virNetMessageErrorPtr rerr, > + int procedure, > + int serial); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) > + > +int virNetServerProgramSendStreamData(virNetServerProgramPtr prog, > + virNetServerClientPtr client, > + virNetMessagePtr msg, > + int procedure, > + int serial, > + const char *data, > + size_t len); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(6) > + > +++ b/src/rpc/virnetserverservice.c > + > +static void virNetServerServiceAccept(virNetSocketPtr sock, > + int events ATTRIBUTE_UNUSED, > + void *opaque) > +{ > + virNetServerServicePtr svc = opaque; > + virNetServerClientPtr client = NULL; > + virNetSocketPtr clientsock = NULL; > + > + if (virNetSocketAccept(sock, &clientsock) < 0) > + goto error; > + > + if (!clientsock) /* Connection already went away */ > + goto cleanup; Why not just return;? > + > + if (!(client = virNetServerClientNew(clientsock, > + svc->auth, > + svc->readonly, > + svc->tls))) > + goto error; > + > + if (!svc->dispatchFunc) > + goto error; > + > + if (svc->dispatchFunc(svc, client, svc->dispatchOpaque) < 0) > + virNetServerClientClose(client); > + > + virNetServerClientFree(client); > + > +cleanup: > + return; and avoid an extra label? > +++ b/src/rpc/virnetserverservice.h > @@ -0,0 +1,65 @@ > + > +virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename, > + const char *service, > + int auth, > + bool readonly, > + virNetTLSContextPtr tls); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5) > +virNetServerServicePtr virNetServerServiceNewUNIX(const char *path, > + mode_t mask, > + gid_t grp, > + int auth, > + bool readonly, > + virNetTLSContextPtr tls); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(6) > + > +int virNetServerServiceGetAuth(virNetServerServicePtr svc); ATTRIBUTE_NONNULL(1) > +bool virNetServerServiceIsReadonly(virNetServerServicePtr svc); ATTRIBUTE_NONNULL(1) > + > +void virNetServerServiceRef(virNetServerServicePtr svc); ATTRIBUTE_NONNULL(1) > + > +void virNetServerServiceSetDispatcher(virNetServerServicePtr svc, > + virNetServerServiceDispatchFunc func, > + void *opaque); ATTRIBUTE_NONNULL(1) > + > +void virNetServerServiceFree(virNetServerServicePtr svc); > + > +void virNetServerServiceToggle(virNetServerServicePtr svc, > + bool enabled); ATTRIBUTE_NONNULL(1) Phew. I finished reviewing this. I think I found several points worth fixing (both here and in the first two messages reviewing the same mail), and you'll probably have other changes when rebasing to latest. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 22:14:00 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 16:14:00 -0600 Subject: [libvirt] [PATCH] virsh: Increase device-detach intelligence In-Reply-To: <1301065746-12468-1-git-send-email-mprivozn@redhat.com> References: <1301065746-12468-1-git-send-email-mprivozn@redhat.com> Message-ID: <4D9A42A8.1040206@redhat.com> On 03/25/2011 09:09 AM, Michal Privoznik wrote: > Up to now users have to give a full XML description on input when > device-detaching. If they omited something it lead to unclear > error messages (like generated MAC wasn't found, etc.). > With this patch users can specify only those information which > specify one device sufficiently precise. Remaining information is > completed from domain. > --- > tools/virsh.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- > 1 files changed, 245 insertions(+), 15 deletions(-) Not forgotten, but not quite yet to the top of my queue, either :( I guess having too many patches to review is a good sign that there is a lot of contribution going on. > > diff --git a/tools/virsh.c b/tools/virsh.c > index 50ca50f..95d27f7 100644 > --- a/tools/virsh.c > +++ b/tools/virsh.c > @@ -8702,6 +8702,224 @@ cmdAttachDevice(vshControl *ctl, const vshCmd *cmd) > return TRUE; > } > > +/** > + * Check if n1 is superset of n2, meaning n1 contains all elements and > + * attributes as n2 at lest. Including children. > + * @n1 first node > + * @n2 second node > + * return 1 in case n1 covers n2, 0 otherwise. > + */ > +static int > +vshNodeIsSuperset(xmlNodePtr n1, xmlNodePtr n2) { Are there any xml library functions that can already do this without you rewriting it from scratch? > +/** > + * To given domain and (probably incomplete) device XML specification try to > + * find such device in domain and complete missing parts. This is however > + * possible when given device XML is sufficiently precise so it addresses only > + * one device. > + * @ctl vshControl for error messages printing > + * @dom domain > + * @oldXML device XML before > + * @newXML and after completion > + * Returns -2 when no such device exists in domain, -3 when given XML selects many > + * (is too ambiguous), 0 in case of success. Otherwise returns -1. @newXML > + * is touched only in case of success. > + */ > +static int > +vshCompleteXMLFromDomain(vshControl *ctl, virDomainPtr dom, char *oldXML, > + char **newXML) { My quick glance of just the documentation says that this looks like a nice helper, but I haven't reviewed it in depth. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jdenemar at redhat.com Mon Apr 4 22:16:10 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 5 Apr 2011 00:16:10 +0200 Subject: [libvirt] [PATCH] qemu: Don't fail driver startup with ancient qemu In-Reply-To: <20110404182437.GD4156@redhat.com> References: <2e1f2e4705bb467bcf237647706555bf4e97ec1e.1301923139.git.jdenemar@redhat.com> <20110404132359.GC13616@redhat.com> <20110404133732.GH389283@orkuz.home> <20110404182437.GD4156@redhat.com> Message-ID: <20110404221610.GI389283@orkuz.home> On Mon, Apr 04, 2011 at 14:24:37 -0400, Dave Allan wrote: > On Mon, Apr 04, 2011 at 03:37:32PM +0200, Jiri Denemark wrote: > > On Mon, Apr 04, 2011 at 14:23:59 +0100, Daniel P. Berrange wrote: > > > On Mon, Apr 04, 2011 at 03:18:59PM +0200, Jiri Denemark wrote: > > > > Failure to extract version info (e.g., because qemu binary is so ancient > > > > that it doesn't even support -help) shouldn't be considered fatal since > > > > we only need it to detect whether qemu supports bootindex option. > > > > --- > > > > src/qemu/qemu_capabilities.c | 7 ++++--- > > > > 1 files changed, 4 insertions(+), 3 deletions(-) > > > > > > What version QEMU doesn't support -help ? > > > > > > We only aim to work with QEMU >= 0.9.0 and I'm fairly sure > > > that has -help support. > > > > An ancient one, 0.6.0. But that was just an example. Extracting version info > > may fail for a bunch of reasons. The main thing is that it shouldn't fail qemu > > driver startup since that results in libvirtd startup failure. > > Why does driver startup failure result in libvirtd startup failure? > Shouldn't it only result in the lack of availability of the driver? IIUC, driver startup is supposed to fail only on serious errors, such as ENOMEM. But it doesn't really matter anymore since I realized there's a better fix for this issue. Instead of not adding deviceboot flag to guest capabilities, we should rather ignore qemu binary for which we are not able to extract version info and don't put it into guest capabilities at all. I've sent a patch for that, which obsoletes this patch. Jirka From eblake at redhat.com Mon Apr 4 22:23:23 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 16:23:23 -0600 Subject: [libvirt] [PATCH] qemu: Ignore unusable binaries In-Reply-To: References: Message-ID: <4D9A44DB.1080802@redhat.com> On 04/04/2011 04:08 PM, Jiri Denemark wrote: > When initializing qemu guest capabilities, we should ignore qemu > binaries that we are not able to extract version/help info from since > they will be unusable for creating domains anyway. Ignoring them is also > much better than letting initialization of qemu driver fail. > --- > src/qemu/qemu_capabilities.c | 11 ++++++++--- > 1 files changed, 8 insertions(+), 3 deletions(-) ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 22:39:39 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 16:39:39 -0600 Subject: [libvirt] [PATCH] Allow relative path for qemu backing file In-Reply-To: <1301275814-25480-1-git-send-email-jesse.cook@eads-na-security.com> References: <1301275814-25480-1-git-send-email-jesse.cook@eads-na-security.com> Message-ID: <4D9A48AB.2090504@redhat.com> On 03/27/2011 07:30 PM, Jesse Cook wrote: > This patch enables the relative backing file path support provided by > qemu-img create. > > If a relative path is specified for the backing file, it is converted > to an absolute path using the storage pool path. The absolute path is > used to verify that the backing file exists. If the backing file exists, > the relative path is allowed and will be provided to qemu-img create. > > This patch takes the place of a previous patch: > http://www.redhat.com/archives/libvir-list/2011-March/msg00179.html > --- > src/storage/storage_backend.c | 18 +++++++++++++++++- > 1 files changed, 17 insertions(+), 1 deletions(-) Sorry for not reviewing this in time for 0.9.0. > @@ -686,7 +689,20 @@ virStorageBackendCreateQemuImg(virConnectPtr conn, > vol->backingStore.format); > return -1; > } > - if (access(vol->backingStore.path, R_OK) != 0) { > + > + /* Convert relative backing store paths to absolute paths for access > + * validation. > + */ > + if ('/' != *(vol->backingStore.path)) { > + virAsprintf(&absolutePath, "%s/%s", pool->def->target.path, > + vol->backingStore.path); > + > + } else { > + virAsprintf(&absolutePath, "%s", vol->backingStore.path); strdup is more efficient here, and avoiding malloc in the first place even more so. > + } > + accessRetCode = access(absolutePath, R_OK); This could segfault on OOM. > + VIR_FREE(absolutePath); > + if (accessRetCode != 0) { > virReportSystemError(errno, > _("inaccessible backing store volume %s"), > vol->backingStore.path); ACK with nits fixed; so here's what I squashed in before pushing. I also updated AUTHORS to pass 'make syntax-check'; feel free to let me know off-list if you prefer any alternate spelling there (especially since you sent v1 and v2 under different email aliases). diff --git i/src/storage/storage_backend.c w/src/storage/storage_backend.c index 5f5565b..8af2878 100644 --- i/src/storage/storage_backend.c +++ w/src/storage/storage_backend.c @@ -693,7 +693,6 @@ virStorageBackendCreateQemuImg(virConnectPtr conn, if (vol->backingStore.path) { int accessRetCode = -1; - char *absolutePath = NULL; /* XXX: Not strictly required: qemu-img has an option a different @@ -719,14 +718,14 @@ virStorageBackendCreateQemuImg(virConnectPtr conn, /* Convert relative backing store paths to absolute paths for access * validation. */ - if ('/' != *(vol->backingStore.path)) { + if ('/' != *(vol->backingStore.path) && virAsprintf(&absolutePath, "%s/%s", pool->def->target.path, - vol->backingStore.path); - - } else { - virAsprintf(&absolutePath, "%s", vol->backingStore.path); + vol->backingStore.path) < 0) { + virReportOOMError(); + return -1; } - accessRetCode = access(absolutePath, R_OK); + accessRetCode = access(absolutePath ? absolutePath + : vol->backingStore.path, R_OK); VIR_FREE(absolutePath); if (accessRetCode != 0) { virReportSystemError(errno, -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 22:43:01 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 16:43:01 -0600 Subject: [libvirt] [PATCH 1/3] remove devices from driver->activePciHostdevs when qemuPrepareHostdevPCIDevices() failed In-Reply-To: <4D90323A.2040508@cn.fujitsu.com> References: <4D90306A.6060805@cn.fujitsu.com> <4D90323A.2040508@cn.fujitsu.com> Message-ID: <4D9A4975.20202@redhat.com> On 03/28/2011 01:01 AM, Wen Congyang wrote: > We should not mark pci devices as active when qemuPrepareHostdevPCIDevices() > failed. > > --- > src/qemu/qemu_hostdev.c | 21 ++++++++++++++++++--- > 1 files changed, 18 insertions(+), 3 deletions(-) > > diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c > index f4b2108..30db0e2 100644 > --- a/src/qemu/qemu_hostdev.c > +++ b/src/qemu/qemu_hostdev.c > @@ -112,7 +112,7 @@ int qemuPrepareHostdevPCIDevices(struct qemud_driver *driver, > if (!(pcidevs = qemuGetPciHostDeviceList(hostdevs, nhostdevs))) > return -1; > > - /* We have to use 3 loops here. *All* devices must > + /* We have to use 4 loops here. *All* devices must ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 22:53:49 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 16:53:49 -0600 Subject: [libvirt] [PATCH 2/3] reattach pci device when pciBindDeviceToStub() failed In-Reply-To: <4D90323D.4000008@cn.fujitsu.com> References: <4D90306A.6060805@cn.fujitsu.com> <4D90323D.4000008@cn.fujitsu.com> Message-ID: <4D9A4BFD.8090405@redhat.com> On 03/28/2011 01:01 AM, Wen Congyang wrote: > We should bind pci device to original driver when pciBindDeviceToStub() failed. > If the pci device is not bound to any driver before calling pciBindDeviceToStub(), > we should only unbind it from pci-stub. If it is bound to pci-stub, we should not > unbid it from pci-stub. > > --- > src/util/pci.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++------ > 1 files changed, 80 insertions(+), 10 deletions(-) > > diff --git a/src/util/pci.c b/src/util/pci.c > index 8d2dbb0..e30f5cf 100644 > --- a/src/util/pci.c > +++ b/src/util/pci.c > @@ -65,6 +65,11 @@ struct _pciDevice { > unsigned has_flr : 1; > unsigned has_pm_reset : 1; > unsigned managed : 1; > + > + /* used by reattach function */ > + unsigned unbind_from_stub : 1; > + unsigned remove_slot : 1; > + unsigned reprobe : 1; > }; > > struct _pciDeviceList { > @@ -834,11 +839,25 @@ recheck: > } > > > +static int pciUnBindDeviceFromStub(pciDevice *dev, const char *driver); I would have used Unbind rather than UnBind, but that's cosmetic. Is it possible to float that function up, instead of having to have a forward declaration? I tend to topologically sort my static functions when possible (again, cosmetic). > static int > pciBindDeviceToStub(pciDevice *dev, const char *driver) > { > char drvdir[PATH_MAX]; > char path[PATH_MAX]; > + int reprobe = 0; > + int ret = 0; > + > + /* check whether the device is already bound to a driver */ > + pciDriverDir(drvdir, sizeof(drvdir), driver); > + pciDeviceFile(path, sizeof(path), dev->name, "driver"); Ouch - conflict with Matthias's patches to avoid PATH_MAX. If that goes in first, your rebase might not be trivial, so it would be worth a v2. But overall, I think the idea of this patch is sane, and nothing obvious jumped out at me as needing fixing other than rebase issues. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 22:54:54 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 16:54:54 -0600 Subject: [libvirt] [PATCH 3/3] reattach pci devices when qemuPrepareHostdevPCIDevices() failed In-Reply-To: <4D90323F.1020105@cn.fujitsu.com> References: <4D90306A.6060805@cn.fujitsu.com> <4D90323F.1020105@cn.fujitsu.com> Message-ID: <4D9A4C3E.2030003@redhat.com> On 03/28/2011 01:01 AM, Wen Congyang wrote: > Reattach all pci devices that we detached when qemuPrepareHostdevPCIDevices() > failed. > > --- > src/qemu/qemu_hostdev.c | 12 +++++++++--- > 1 files changed, 9 insertions(+), 3 deletions(-) > > diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c > index 30db0e2..7f5ad51 100644 > --- a/src/qemu/qemu_hostdev.c > +++ b/src/qemu/qemu_hostdev.c > @@ -127,11 +127,11 @@ int qemuPrepareHostdevPCIDevices(struct qemud_driver *driver, > for (i = 0; i < pciDeviceListCount(pcidevs); i++) { > pciDevice *dev = pciDeviceListGet(pcidevs, i); > if (!pciDeviceIsAssignable(dev, !driver->relaxedACS)) > - goto cleanup; > + goto reattachdevs; > > if (pciDeviceGetManaged(dev) && > pciDettachDevice(dev, driver->activePciHostdevs) < 0) > - goto cleanup; > + goto reattachdevs; Makes sense; ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 4 23:28:50 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 04 Apr 2011 17:28:50 -0600 Subject: [libvirt] [PATCH] Add autostart support to libxl driver In-Reply-To: <201103281249.22632.gross@univention.de> References: <201103281249.22632.gross@univention.de> Message-ID: <4D9A5432.7030905@redhat.com> On 03/28/2011 04:49 AM, Markus Gro? wrote: > This patch is rebased against the patchset from here: > https://www.redhat.com/archives/libvir-list/2011-March/msg01260.html > The domainSetAutostart function is nearly identical to the one from qemu. > > --- > src/libxl/libxl_driver.c | 137 ++++++++++++++++++++++++++++++++++++++++++++-- > 1 files changed, 131 insertions(+), 6 deletions(-) ACK and pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From usui at mxm.nes.nec.co.jp Tue Apr 5 01:11:07 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Tue, 5 Apr 2011 10:11:07 +0900 Subject: [libvirt] [PATCH 1/6] virNodeGetCpuTime: Expose new API In-Reply-To: References: <20110401103833.8b66b57e.usui@mxm.nes.nec.co.jp> <20110401105548.a78607f7.usui@mxm.nes.nec.co.jp> <4D95FB08.20802@redhat.com> <20110404110310.e85d09ba.usui@mxm.nes.nec.co.jp> <20110404115043.GA13616@redhat.com> Message-ID: <20110405101107.ec0a1246.usui@mxm.nes.nec.co.jp> Hi, Daniel, Matthias Thank you for your comments. On Mon, 4 Apr 2011 14:30:32 +0200 Matthias Bolte wrote: > 2011/4/4 Daniel P. Berrange : > > On Mon, Apr 04, 2011 at 11:03:10AM +0900, Minoru Usui wrote: > >> Hi, Matthias. > >> > >> On Fri, 1 Apr 2011 20:22:17 +0200 > >> Matthias Bolte wrote: > >> > >> > 2011/4/1 Eric Blake : > >> > > On 03/31/2011 07:55 PM, Minoru Usui wrote: > >> > >> virNodeGetCpuTime: Expose new API > >> > >> > >> > >> ?include/libvirt/libvirt.h.in | ? 26 ++++++++++++++++++++++++++ > >> > >> ?src/libvirt_public.syms ? ? ?| ? ?1 + > >> > >> ?2 files changed, 27 insertions(+), 0 deletions(-) > >> > > > >> > >> > >> > >> +/** > >> > >> + * virNodeCpuTime: > >> > >> + * > >> > >> + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing > >> > >> + * the information for the cpu time of Node. > >> > >> + */ > >> > >> + > >> > >> +typedef struct _virNodeCpuTime virNodeCpuTime; > >> > >> + > >> > >> +struct _virNodeCpuTime { > >> > >> + ? ?unsigned long long user; > >> > >> + ? ?unsigned long long system; > >> > >> + ? ?unsigned long long idle; > >> > >> + ? ?unsigned long long iowait; > >> > >> +}; > >> > > > >> > > Can we portably get all of this information on Windows? ?If not, how do > >> > > you express which values we don't know how to obtain? > >> > > > >> > > >> > In the context of ESX I vote against this absolute CPU time values. > >> > ESX provides this values relative to a 20 second timeslots with 1 hour > >> > of history. This makes it nearly impossible to obtain the absolute CPU > >> > time. The same problem already exists for the domain's virtual CPU > >> > time. > >> > > >> > When you look at virt-top's usage of the domain's virtual CPU time, > >> > you see that it actually doesn't really care about the absolute value, > >> > but deduces the CPU utilization from it. I suggest that we find a > >> > different representation for this information that is not by > >> > definition impossible to implement for ESX. > >> > > >> > Matthias > >> > >> I didn't know ESX couldn't return absolute CPU time value. > >> Thank you for your comment. > >> > >> We really want to get CPU utilization information of the node, not > >> absolute CPU time values. > >> But linux doesn't provide CPU utilization directly, > >> so my patch returns absolute CPU time values, > >> and CPU utilization is calculated by client which uses new API. > >> > >> To return CPU utilization by new API, I think there are two issues of implementing on linux. > >> > >> ? a) How much interval does calculate CPU utilization? > >> ? ? ?To calculate CPU utilization on linux, we need to get absolute CPU time value of the node > >> ? ? ?from /proc/stat two times. > >> ? ? ?How much interval properly? 1sec? 1min? or others? > > > > The fact that there is the question of what is the right interval > > demonstrates the inherant flaw in such an API design. Providing > > the raw absolute time allows an app much more flexiblity in how > > they work with the data, avoiding the need for such policies in > > libvirt. > > > >> ? b) Can new API wait its interval? > >> ? ? ?If we select simply implementation, new API waits its interval. > >> ? ? ?But API user don't want to wait every API calls, if its interval is long. > >> ? ? ?So I think libvirtd will be calculating CPU utilization in background every interval. > >> ? ? ?Is this approach OK? > > > > IMHO we don't really want libvirtd to be constantly polling & calculating > > this data, at least not unless an application is currently asking for it. > > I think we want this API to have the style that is like the current > > virDomainMemoryStats ?API. Then, we can define a set of parameters that > > can be fetched, allowing each parameter to be optional > > > > eg > > > > ?enum { > > ? ? VIR_NODE_CPU_TIME_KERNEL, > > ? ? VIR_NODE_CPU_TIME_USER, > > ? ? VIR_NODE_CPU_TIME_IDLE, > > ? ? VIR_NODE_CPU_TIME_IOWAIT, > > ? ? VIR_NODE_CPU_TIME_UTILIZATION, > > ?}; > > > > For QEMU we'd provide the first 4 values, allowing apps maximum > > flexibility in how they calculate utilization over different time > > periods. For VMWare we'd provide only the last value. > > > > An app like virt-manager, can display UTILIZATION value directly if > > that is present, otherwise it will be able to calculate data from > > the other times as it does now for domains. So it would work with > > both QEMU and VMWare, to the best of its abilities. > > > > Regards, > > Daniel > > > > For ESX the driver doesn't even need to calculate a usage/utilization > value, because the ESX server already does this on it's own and the > driver can just ask for it. The usage value is in percent and 100% > represents all CPUs on the server. > > I like that approach. > > Matthias OK. I'll change the user I/F to above one. -- Minoru Usui From jfehlig at novell.com Tue Apr 5 04:05:40 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Mon, 04 Apr 2011 22:05:40 -0600 Subject: [libvirt] [PATCH] Add autostart support to libxl driver In-Reply-To: <4D9A5432.7030905@redhat.com> References: <201103281249.22632.gross@univention.de> <4D9A5432.7030905@redhat.com> Message-ID: <4D9A9514.9090705@novell.com> Eric Blake wrote: > On 03/28/2011 04:49 AM, Markus Gro? wrote: > >> This patch is rebased against the patchset from here: >> https://www.redhat.com/archives/libvir-list/2011-March/msg01260.html >> The domainSetAutostart function is nearly identical to the one from qemu. >> >> --- >> src/libxl/libxl_driver.c | 137 ++++++++++++++++++++++++++++++++++++++++++++-- >> 1 files changed, 131 insertions(+), 6 deletions(-) >> > > ACK and pushed. Eric, thanks for the review. Markus, sorry for the silence on your patch. I've been traveling and just now catching up on mail. Regards, Jim From amit.shah at redhat.com Tue Apr 5 06:41:20 2011 From: amit.shah at redhat.com (Amit Shah) Date: Tue, 5 Apr 2011 12:11:20 +0530 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D99CC74.9070703@redhat.com> Message-ID: <20110405064120.GB2872@amit-x200.redhat.com> On (Mon) 04 Apr 2011 [16:09:05], Stefan Hajnoczi wrote: > On Mon, Apr 4, 2011 at 2:49 PM, Avi Kivity wrote: > > On 04/04/2011 04:38 PM, Anthony Liguori wrote: > >> > >> On 04/04/2011 08:22 AM, Avi Kivity wrote: > >>> > >>> On 04/03/2011 02:57 PM, Stefan Hajnoczi wrote: > >>>> > >>>> In order for media change to work with Linux host CD-ROM it is > >>>> necessary to reopen the file (otherwise the inode size will not > >>>> refresh, this is an issue with existing kernels). > >>>> > >>> > >>> Maybe we should fix the bug in Linux (and backport as necessary)? > >>> > >>> I think cd-rom assignment is sufficiently obscure that we can require a > >>> fixed kernel instead of providing a workaround. > >> > >> Do reads fail after CD change? ?Or do they succeed and the size is just > >> reported incorrectly? > >> > >> If it's the later, I'd agree that it needs fixing in the kernel. ?If it's > >> the former, I'd say it's clearly a feature. > >> > > > > Even if it's a documented or intentional feature, we can add an ioctl to > > "refresh" the device with up-to-date data. > > It's possible to fix this in the kernel. I just haven't written the > patch yet. The inode size needs to be updated when the new medium is > detected. > > I haven't tested but I suspect reads within the size of the previous > medium will succeed. But if the new medium is larger then reads > beyond the old medium size will fail. See http://www.spinics.net/lists/linux-scsi/msg51504.html Amit From jyang at redhat.com Tue Apr 5 06:47:22 2011 From: jyang at redhat.com (Osier Yang) Date: Tue, 5 Apr 2011 14:47:22 +0800 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. Message-ID: <1301986042-13725-1-git-send-email-jyang@redhat.com> Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to restore the domain from managedsave'ed image if it exists (by invoking "qemuDomainObjRestore"), but it unlinks the image even if restoring fails, which causes data loss. However, I'm not sure if it's the very correct way to fix it, if restoring fails, and we didn't remove the image, it will trys to restore from the image again next time, if that's not the user expected (e.g. the user made quite many changes on the guest), then it's a new problem. --- src/qemu/qemu_driver.c | 12 +++++++----- 1 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 48fe266..22c29e4 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3423,18 +3423,20 @@ static int qemudDomainObjStart(virConnectPtr conn, /* * If there is a managed saved state restore it instead of starting - * from scratch. In any case the old state is removed. + * from scratch. */ managed_save = qemuDomainManagedSavePath(driver, vm); if ((managed_save) && (virFileExists(managed_save))) { ret = qemuDomainObjRestore(conn, driver, vm, managed_save); - if (unlink(managed_save) < 0) { - VIR_WARN("Failed to remove the managed state %s", managed_save); - } + if (ret == 0) { + if (unlink(managed_save) < 0) + VIR_WARN("Failed to remove the managed state %s", managed_save); - if (ret == 0) goto cleanup; + } else { + VIR_WARN("Failed to restore from the managed state %s", managed_save); + } } ret = qemuProcessStart(conn, driver, vm, NULL, start_paused, -1, NULL, -- 1.7.4 From matthias.bolte at googlemail.com Tue Apr 5 06:49:28 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Tue, 5 Apr 2011 08:49:28 +0200 Subject: [libvirt] [PATCH] vmx: Support persistent CPU shares In-Reply-To: <4D9A0042.8030805@redhat.com> References: <20110403124355.GA22943@sbox> <20110404030541.GQ24385@redhat.com> <4D9A0042.8030805@redhat.com> Message-ID: 2011/4/4 Eric Blake : > On 04/04/2011 12:28 AM, Matthias Bolte wrote: >> 2011/4/4 Daniel Veillard : >>> On Sun, Apr 03, 2011 at 02:43:55PM +0200, Matthias Bolte wrote: >> >>> >>> ?ACK, while nice, it may be a bit late for 0.9.0, okay to wait for the >>> next cycle ? We already have this for xen and qemu, seeing it for ESX >>> confirms the design is fine, which is the most important from my point >>> of vue :-) >>> >>> Daniel >>> >> >> Sure, this can wait until 0.9.1. On the ESX side the shares value is >> persistent anyway. This patch just exposes it as persistent in libvirt >> too. > > 0.9.1 is now started, so feel free to push now :) > Pushed, thanks. Matthias From matthias.bolte at googlemail.com Tue Apr 5 06:50:06 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Tue, 5 Apr 2011 08:50:06 +0200 Subject: [libvirt] [PATCH] vmx: Use case-insensitive compare functions for all content In-Reply-To: <20110404030237.GP24385@redhat.com> References: <20110403121914.GA22826@sbox> <20110404030237.GP24385@redhat.com> Message-ID: 2011/4/4 Daniel Veillard : > On Sun, Apr 03, 2011 at 02:19:14PM +0200, Matthias Bolte wrote: >> --- >> ?src/vmx/vmx.c | ? 10 +++++----- >> ?1 files changed, 5 insertions(+), 5 deletions(-) >> >> diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c >> index 9f4d5fb..9a482ef 100644 >> --- a/src/vmx/vmx.c >> +++ b/src/vmx/vmx.c >> @@ -730,7 +730,7 @@ virVMXGetConfigLong(virConfPtr conf, const char *name, long long *number, >> ? ? ? ? ? ? ?} >> ? ? ? ? ?} >> >> - ? ? ? ?if (STREQ(value->str, "unlimited")) { >> + ? ? ? ?if (STRCASEEQ(value->str, "unlimited")) { >> ? ? ? ? ? ? ?*number = -1; >> ? ? ? ? ?} else if (virStrToLong_ll(value->str, NULL, 10, number) < 0) { >> ? ? ? ? ? ? ?VMX_ERROR(VIR_ERR_INTERNAL_ERROR, >> @@ -1385,7 +1385,7 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx) >> ? ? ? ? ?goto cleanup; >> ? ? ?} >> >> - ? ?if (sched_cpu_affinity != NULL && STRNEQ(sched_cpu_affinity, "all")) { >> + ? ?if (sched_cpu_affinity != NULL && STRCASENEQ(sched_cpu_affinity, "all")) { >> ? ? ? ? ?const char *current = sched_cpu_affinity; >> ? ? ? ? ?int number, count = 0; >> >> @@ -2107,7 +2107,7 @@ virVMXParseDisk(virVMXContext *ctx, virCapsPtr caps, virConfPtr conf, >> ? ? ? ? ? ? ? ? ?goto cleanup; >> ? ? ? ? ? ? ?} >> ? ? ? ? ?} else if (virFileHasSuffix(fileName, ".iso") || >> - ? ? ? ? ? ? ? ? ? STREQ(deviceType, "atapi-cdrom")) { >> + ? ? ? ? ? ? ? ? ? STRCASEEQ(deviceType, "atapi-cdrom")) { >> ? ? ? ? ? ? ?/* >> ? ? ? ? ? ? ? * This function was called in order to parse a harddisk device, >> ? ? ? ? ? ? ? * but .iso files and 'atapi-cdrom' devices are for CDROM devices >> @@ -2146,7 +2146,7 @@ virVMXParseDisk(virVMXContext *ctx, virCapsPtr caps, virConfPtr conf, >> ? ? ? ? ? ? ? * handle it. >> ? ? ? ? ? ? ? */ >> ? ? ? ? ? ? ?goto ignore; >> - ? ? ? ?} else if (STREQ(deviceType, "atapi-cdrom")) { >> + ? ? ? ?} else if (STRCASEEQ(deviceType, "atapi-cdrom")) { >> ? ? ? ? ? ? ?(*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK; >> ? ? ? ? ? ? ?(*def)->src = fileName; >> >> @@ -2174,7 +2174,7 @@ virVMXParseDisk(virVMXContext *ctx, virCapsPtr caps, virConfPtr conf, >> ? ? ? ? ? ? ?if ((*def)->src == NULL) { >> ? ? ? ? ? ? ? ? ?goto cleanup; >> ? ? ? ? ? ? ?} >> - ? ? ? ?} else if (fileType != NULL && STREQ(fileType, "device")) { >> + ? ? ? ?} else if (fileType != NULL && STRCASEEQ(fileType, "device")) { >> ? ? ? ? ? ? ?(*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK; >> ? ? ? ? ? ? ?(*def)->src = fileName; > > ?Sounds fine to me but would you categorize this as bug fix (for 0.9.0) > or rather an improvement and wait. I guess it depends how you ended up > crossing this, and I can't guess it :-) > > Daniel > There was a bug report a while ago about the VMX parser being case-sensitive, but the .vmx files actually being case-insensitive. The initial fix was incomplete and I just came across this remaining case-sensitive compares while adding persistent CPU shares. As 0.9.0 is out of the door now, I pushed it. Matthias From mprivozn at redhat.com Tue Apr 5 07:27:41 2011 From: mprivozn at redhat.com (=?ISO-8859-1?Q?Michal_Pr=EDvozn=EDk?=) Date: Tue, 05 Apr 2011 09:27:41 +0200 Subject: [libvirt] [PATCH] virsh: Increase device-detach intelligence In-Reply-To: <4D9A42A8.1040206@redhat.com> References: <1301065746-12468-1-git-send-email-mprivozn@redhat.com> <4D9A42A8.1040206@redhat.com> Message-ID: <4D9AC46D.9070604@redhat.com> On 04/05/2011 12:14 AM, Eric Blake wrote: > On 03/25/2011 09:09 AM, Michal Privoznik wrote: >> Up to now users have to give a full XML description on input when >> device-detaching. If they omited something it lead to unclear >> error messages (like generated MAC wasn't found, etc.). >> With this patch users can specify only those information which >> specify one device sufficiently precise. Remaining information is >> completed from domain. >> --- >> tools/virsh.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- >> 1 files changed, 245 insertions(+), 15 deletions(-) > > Not forgotten, but not quite yet to the top of my queue, either :( I > guess having too many patches to review is a good sign that there is a > lot of contribution going on. > >> >> diff --git a/tools/virsh.c b/tools/virsh.c >> index 50ca50f..95d27f7 100644 >> --- a/tools/virsh.c >> +++ b/tools/virsh.c >> @@ -8702,6 +8702,224 @@ cmdAttachDevice(vshControl *ctl, const vshCmd *cmd) >> return TRUE; >> } >> >> +/** >> + * Check if n1 is superset of n2, meaning n1 contains all elements and >> + * attributes as n2 at lest. Including children. >> + * @n1 first node >> + * @n2 second node >> + * return 1 in case n1 covers n2, 0 otherwise. >> + */ >> +static int >> +vshNodeIsSuperset(xmlNodePtr n1, xmlNodePtr n2) { > > Are there any xml library functions that can already do this without you > rewriting it from scratch? No, there are not. I consulted this issue with Daniel Veillard. > >> +/** >> + * To given domain and (probably incomplete) device XML specification try to >> + * find such device in domain and complete missing parts. This is however >> + * possible when given device XML is sufficiently precise so it addresses only >> + * one device. >> + * @ctl vshControl for error messages printing >> + * @dom domain >> + * @oldXML device XML before >> + * @newXML and after completion >> + * Returns -2 when no such device exists in domain, -3 when given XML selects many >> + * (is too ambiguous), 0 in case of success. Otherwise returns -1. @newXML >> + * is touched only in case of success. >> + */ >> +static int >> +vshCompleteXMLFromDomain(vshControl *ctl, virDomainPtr dom, char *oldXML, >> + char **newXML) { > > My quick glance of just the documentation says that this looks like a > nice helper, but I haven't reviewed it in depth. > From matthias.bolte at googlemail.com Tue Apr 5 07:36:36 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Tue, 5 Apr 2011 09:36:36 +0200 Subject: [libvirt] [PATCH 00/20] Remove large stack allocations In-Reply-To: <20110404104423.GW13616@redhat.com> References: <1301822493-23013-1-git-send-email-matthias.bolte@googlemail.com> <20110404104423.GW13616@redhat.com> Message-ID: 2011/4/4 Daniel P. Berrange : > On Sun, Apr 03, 2011 at 11:21:13AM +0200, Matthias Bolte wrote: >> This is meant for post-0.9.0. >> >> The series removes many large stack allocations from the code base and makes >> it compile with -Wframe-larger-than=2500. This was inspired by Dan's patch for >> using gnulib's manywarnings & warnings modules [1]. Where he mentioned that >> currently -Wframe-larger-than=20480 is required. >> >> This series doesn't address stack usage in the test suite. > > I've ACKd most of the patches - feel free to push those after the release > & just repost the couple which had comments, rather than the whole series. > > Daniel > Okay, I removed the TODO comments from 09/20 and pushed the series expect 11/20 and 16/20. Matthias From avi at redhat.com Tue Apr 5 07:48:16 2011 From: avi at redhat.com (Avi Kivity) Date: Tue, 05 Apr 2011 10:48:16 +0300 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <20110405064120.GB2872@amit-x200.redhat.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D99CC74.9070703@redhat.com> <20110405064120.GB2872@amit-x200.redhat.com> Message-ID: <4D9AC940.5000502@redhat.com> On 04/05/2011 09:41 AM, Amit Shah wrote: > See http://www.spinics.net/lists/linux-scsi/msg51504.html I see this is quite fresh. What are the plans here? -- error compiling committee.c: too many arguments to function From amit.shah at redhat.com Tue Apr 5 08:09:00 2011 From: amit.shah at redhat.com (Amit Shah) Date: Tue, 5 Apr 2011 13:39:00 +0530 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D9AC940.5000502@redhat.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D99CC74.9070703@redhat.com> <20110405064120.GB2872@amit-x200.redhat.com> <4D9AC940.5000502@redhat.com> Message-ID: <20110405080900.GE2872@amit-x200.redhat.com> On (Tue) 05 Apr 2011 [10:48:16], Avi Kivity wrote: > On 04/05/2011 09:41 AM, Amit Shah wrote: > >See http://www.spinics.net/lists/linux-scsi/msg51504.html > > I see this is quite fresh. What are the plans here? We're still discussing where the fix should be, but it certainly is a kernel bug and should be fixed there, and then applied to stable. However, there are other bugs in qemu which will prevent the right size changes to be visible in the guest (the RFC series I sent out earlier in this thread need to be applied to QEMU at the least, the series has grown in my development tree since the time I sent that one out). So essentially we need to update both, the hypervisor and the guest to get proper CDROM media change support. It also looks like we can't have a workaround in QEMU to get older guests to work. However, a hack in the kernel can be used without any QEMU changes (revalidate disk on each sr_open() call, irrespective of detecting any media change). I'm against doing that for upstream, but downstreams could do that for new guest - old hypervisor compat. Amit From stefanha at gmail.com Tue Apr 5 08:40:05 2011 From: stefanha at gmail.com (Stefan Hajnoczi) Date: Tue, 5 Apr 2011 09:40:05 +0100 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <20110405064120.GB2872@amit-x200.redhat.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D99CC74.9070703@redhat.com> <20110405064120.GB2872@amit-x200.redhat.com> Message-ID: On Tue, Apr 5, 2011 at 7:41 AM, Amit Shah wrote: > On (Mon) 04 Apr 2011 [16:09:05], Stefan Hajnoczi wrote: >> On Mon, Apr 4, 2011 at 2:49 PM, Avi Kivity wrote: >> > On 04/04/2011 04:38 PM, Anthony Liguori wrote: >> >> >> >> On 04/04/2011 08:22 AM, Avi Kivity wrote: >> >>> >> >>> On 04/03/2011 02:57 PM, Stefan Hajnoczi wrote: >> >>>> >> >>>> In order for media change to work with Linux host CD-ROM it is >> >>>> necessary to reopen the file (otherwise the inode size will not >> >>>> refresh, this is an issue with existing kernels). >> >>>> >> >>> >> >>> Maybe we should fix the bug in Linux (and backport as necessary)? >> >>> >> >>> I think cd-rom assignment is sufficiently obscure that we can require a >> >>> fixed kernel instead of providing a workaround. >> >> >> >> Do reads fail after CD change? ?Or do they succeed and the size is just >> >> reported incorrectly? >> >> >> >> If it's the later, I'd agree that it needs fixing in the kernel. ?If it's >> >> the former, I'd say it's clearly a feature. >> >> >> > >> > Even if it's a documented or intentional feature, we can add an ioctl to >> > "refresh" the device with up-to-date data. >> >> It's possible to fix this in the kernel. ?I just haven't written the >> patch yet. ?The inode size needs to be updated when the new medium is >> detected. >> >> I haven't tested but I suspect reads within the size of the previous >> medium will succeed. ?But if the new medium is larger then reads >> beyond the old medium size will fail. > > See http://www.spinics.net/lists/linux-scsi/msg51504.html I don't think that patch updates the block inode size. We'd need to call fs/block_dev.c:revalidate_disk() instead of directly calling cdi->disk->fops->revalidate_disk(cdi->disk). fs/block_dev.c:revalidate_disk() calls check_disk_size_change(), which will update the inode size. Here are the steps to reproduce the issue: https://lkml.org/lkml/2011/3/23/156 Stefan From amit.shah at redhat.com Tue Apr 5 08:58:32 2011 From: amit.shah at redhat.com (Amit Shah) Date: Tue, 5 Apr 2011 14:28:32 +0530 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D99CC74.9070703@redhat.com> <20110405064120.GB2872@amit-x200.redhat.com> Message-ID: <20110405085832.GA27661@amit-x200.redhat.com> On (Tue) 05 Apr 2011 [09:40:05], Stefan Hajnoczi wrote: > > See http://www.spinics.net/lists/linux-scsi/msg51504.html > > I don't think that patch updates the block inode size. We'd need to > call fs/block_dev.c:revalidate_disk() instead of directly calling > cdi->disk->fops->revalidate_disk(cdi->disk). > fs/block_dev.c:revalidate_disk() calls check_disk_size_change(), which > will update the inode size. Then the patch is buggy :-) As Tejun also says in the thread, the patch should be in the block layer, not sr.c. (btw that patch does update /sys/block/sr0/size, so that part of revalidation is done.) Amit From avi at redhat.com Tue Apr 5 09:00:38 2011 From: avi at redhat.com (Avi Kivity) Date: Tue, 05 Apr 2011 12:00:38 +0300 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <20110405080900.GE2872@amit-x200.redhat.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D99CC74.9070703@redhat.com> <20110405064120.GB2872@amit-x200.redhat.com> <4D9AC940.5000502@redhat.com> <20110405080900.GE2872@amit-x200.redhat.com> Message-ID: <4D9ADA36.8040306@redhat.com> On 04/05/2011 11:09 AM, Amit Shah wrote: > On (Tue) 05 Apr 2011 [10:48:16], Avi Kivity wrote: > > On 04/05/2011 09:41 AM, Amit Shah wrote: > > >See http://www.spinics.net/lists/linux-scsi/msg51504.html > > > > I see this is quite fresh. What are the plans here? > > We're still discussing where the fix should be, but it certainly is a > kernel bug and should be fixed there, and then applied to stable. > > However, there are other bugs in qemu which will prevent the right > size changes to be visible in the guest (the RFC series I sent out > earlier in this thread need to be applied to QEMU at the least, the > series has grown in my development tree since the time I sent that one > out). So essentially we need to update both, the hypervisor and the > guest to get proper CDROM media change support. Why do we need to update the guest for a qemu bug? What is the qemu bug? > It also looks like we can't have a workaround in QEMU to get older > guests to work. Older guests? or older hosts? > However, a hack in the kernel can be used without any QEMU changes > (revalidate disk on each sr_open() call, irrespective of detecting any > media change). I'm against doing that for upstream, but downstreams > could do that for new guest - old hypervisor compat. Seriously confused. Please use the kernels "host kernel" and "qemu" instead of "hypervisor" which is ambiguous. -- error compiling committee.c: too many arguments to function From amit.shah at redhat.com Tue Apr 5 09:12:03 2011 From: amit.shah at redhat.com (Amit Shah) Date: Tue, 5 Apr 2011 14:42:03 +0530 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D9ADA36.8040306@redhat.com> References: <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D99CC74.9070703@redhat.com> <20110405064120.GB2872@amit-x200.redhat.com> <4D9AC940.5000502@redhat.com> <20110405080900.GE2872@amit-x200.redhat.com> <4D9ADA36.8040306@redhat.com> Message-ID: <20110405091203.GC27661@amit-x200.redhat.com> On (Tue) 05 Apr 2011 [12:00:38], Avi Kivity wrote: > On 04/05/2011 11:09 AM, Amit Shah wrote: > >On (Tue) 05 Apr 2011 [10:48:16], Avi Kivity wrote: > >> On 04/05/2011 09:41 AM, Amit Shah wrote: > >> >See http://www.spinics.net/lists/linux-scsi/msg51504.html > >> > >> I see this is quite fresh. What are the plans here? > > > >We're still discussing where the fix should be, but it certainly is a > >kernel bug and should be fixed there, and then applied to stable. > > > >However, there are other bugs in qemu which will prevent the right > >size changes to be visible in the guest (the RFC series I sent out > >earlier in this thread need to be applied to QEMU at the least, the > >series has grown in my development tree since the time I sent that one > >out). So essentially we need to update both, the hypervisor and the > >guest to get proper CDROM media change support. > > Why do we need to update the guest for a qemu bug? What is the qemu bug? Guest kernel bug: CDROM change event missed, so the the revalidate call isn't made, which causes stale data (like disc size) to be used on newer media. qemu bug: We don't handle the GET_EVENT_STATUS_NOTIFICATION command from guests (which is a mandatory command acc. to scsi spec) which the guest uses to detect CDROM changes. Once this command is implemented, QEMU sends the required info the guest needs to detect CDROM changes. I have this implemented locally (also sent as RFC PATCH 2/3 in the 'cdrom bug roundup' thread. So: even if qemu is updated to handle this command, the guest won't work correctly since it misses the event. > >It also looks like we can't have a workaround in QEMU to get older > >guests to work. > > Older guests? or older hosts? Older guests (not patched with fix for the bug described above). Since the guest kernel completely misses the disc change event in the path that does the revalidation, there's nothing qemu can do that will make such older guests notice disc change. Also: if only the guest kernel is updated by qemu is not, things still won't work since qemu will never send valid information for the GET_EVENT_STATUS_NOTIFICATION command. > >However, a hack in the kernel can be used without any QEMU changes > >(revalidate disk on each sr_open() call, irrespective of detecting any > >media change). I'm against doing that for upstream, but downstreams > >could do that for new guest - old hypervisor compat. > > Seriously confused. Please use the kernels "host kernel" and "qemu" > instead of "hypervisor" which is ambiguous. OK: this last bit says that forcefully revalidating discs in the guest kernel when a guest userspace opens the disc will ensure size changes are reflected properly for guest userspace. So in this case, even if we're using an older qemu which doesn't implement GET_EVENT_STATUS_NOTIFICATION, guest userspace apps will work fine. This is obviously a hack. Amit From avi at redhat.com Tue Apr 5 09:17:30 2011 From: avi at redhat.com (Avi Kivity) Date: Tue, 05 Apr 2011 12:17:30 +0300 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <20110405091203.GC27661@amit-x200.redhat.com> References: <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D99CC74.9070703@redhat.com> <20110405064120.GB2872@amit-x200.redhat.com> <4D9AC940.5000502@redhat.com> <20110405080900.GE2872@amit-x200.redhat.com> <4D9ADA36.8040306@redhat.com> <20110405091203.GC27661@amit-x200.redhat.com> Message-ID: <4D9ADE2A.2020201@redhat.com> On 04/05/2011 12:12 PM, Amit Shah wrote: > On (Tue) 05 Apr 2011 [12:00:38], Avi Kivity wrote: > > On 04/05/2011 11:09 AM, Amit Shah wrote: > > >On (Tue) 05 Apr 2011 [10:48:16], Avi Kivity wrote: > > >> On 04/05/2011 09:41 AM, Amit Shah wrote: > > >> >See http://www.spinics.net/lists/linux-scsi/msg51504.html > > >> > > >> I see this is quite fresh. What are the plans here? > > > > > >We're still discussing where the fix should be, but it certainly is a > > >kernel bug and should be fixed there, and then applied to stable. > > > > > >However, there are other bugs in qemu which will prevent the right > > >size changes to be visible in the guest (the RFC series I sent out > > >earlier in this thread need to be applied to QEMU at the least, the > > >series has grown in my development tree since the time I sent that one > > >out). So essentially we need to update both, the hypervisor and the > > >guest to get proper CDROM media change support. > > > > Why do we need to update the guest for a qemu bug? What is the qemu bug? > > Guest kernel bug: CDROM change event missed, so the the revalidate > call isn't made, which causes stale data (like disc size) to be used > on newer media. > > qemu bug: We don't handle the GET_EVENT_STATUS_NOTIFICATION command > from guests (which is a mandatory command acc. to scsi spec) which the > guest uses to detect CDROM changes. Once this command is implemented, > QEMU sends the required info the guest needs to detect CDROM changes. > I have this implemented locally (also sent as RFC PATCH 2/3 in the > 'cdrom bug roundup' thread. > > So: even if qemu is updated to handle this command, the guest won't > work correctly since it misses the event. Okay. We aren't responsible for guest kernel bugs, especially those which apply to real hardware (we should make more effort for virtio bugs). It's enough that we fix qemu here. > > >It also looks like we can't have a workaround in QEMU to get older > > >guests to work. > > > > Older guests? or older hosts? > > Older guests (not patched with fix for the bug described above). > > Since the guest kernel completely misses the disc change event in the > path that does the revalidation, there's nothing qemu can do that will > make such older guests notice disc change. > > Also: if only the guest kernel is updated by qemu is not, things still > won't work since qemu will never send valid information for the > GET_EVENT_STATUS_NOTIFICATION command. > > > >However, a hack in the kernel can be used without any QEMU changes > > >(revalidate disk on each sr_open() call, irrespective of detecting any > > >media change). I'm against doing that for upstream, but downstreams > > >could do that for new guest - old hypervisor compat. > > > > Seriously confused. Please use the kernels "host kernel" and "qemu" > > instead of "hypervisor" which is ambiguous. > > OK: this last bit says that forcefully revalidating discs in the guest > kernel when a guest userspace opens the disc will ensure size changes > are reflected properly for guest userspace. So in this case, even if > we're using an older qemu which doesn't implement > GET_EVENT_STATUS_NOTIFICATION, guest userspace apps will work fine. > > This is obviously a hack. Yes. Thanks for the clarification. (let's see if I really got it - we have a kernel bug that hit both the guest and the host, plus a qemu bug?) -- error compiling committee.c: too many arguments to function From amit.shah at redhat.com Tue Apr 5 09:26:48 2011 From: amit.shah at redhat.com (Amit Shah) Date: Tue, 5 Apr 2011 14:56:48 +0530 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D9ADE2A.2020201@redhat.com> References: <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D99CC74.9070703@redhat.com> <20110405064120.GB2872@amit-x200.redhat.com> <4D9AC940.5000502@redhat.com> <20110405080900.GE2872@amit-x200.redhat.com> <4D9ADA36.8040306@redhat.com> <20110405091203.GC27661@amit-x200.redhat.com> <4D9ADE2A.2020201@redhat.com> Message-ID: <20110405092648.GA28577@amit-x200.redhat.com> On (Tue) 05 Apr 2011 [12:17:30], Avi Kivity wrote: > On 04/05/2011 12:12 PM, Amit Shah wrote: > >On (Tue) 05 Apr 2011 [12:00:38], Avi Kivity wrote: > >> On 04/05/2011 11:09 AM, Amit Shah wrote: > >> >On (Tue) 05 Apr 2011 [10:48:16], Avi Kivity wrote: > >> >> On 04/05/2011 09:41 AM, Amit Shah wrote: > >> >> >See http://www.spinics.net/lists/linux-scsi/msg51504.html > >> >> > >> >> I see this is quite fresh. What are the plans here? > >> > > >> >We're still discussing where the fix should be, but it certainly is a > >> >kernel bug and should be fixed there, and then applied to stable. > >> > > >> >However, there are other bugs in qemu which will prevent the right > >> >size changes to be visible in the guest (the RFC series I sent out > >> >earlier in this thread need to be applied to QEMU at the least, the > >> >series has grown in my development tree since the time I sent that one > >> >out). So essentially we need to update both, the hypervisor and the > >> >guest to get proper CDROM media change support. > >> > >> Why do we need to update the guest for a qemu bug? What is the qemu bug? > > > >Guest kernel bug: CDROM change event missed, so the the revalidate > >call isn't made, which causes stale data (like disc size) to be used > >on newer media. > > > >qemu bug: We don't handle the GET_EVENT_STATUS_NOTIFICATION command > >from guests (which is a mandatory command acc. to scsi spec) which the > >guest uses to detect CDROM changes. Once this command is implemented, > >QEMU sends the required info the guest needs to detect CDROM changes. > >I have this implemented locally (also sent as RFC PATCH 2/3 in the > >'cdrom bug roundup' thread. > > > >So: even if qemu is updated to handle this command, the guest won't > >work correctly since it misses the event. > > Okay. We aren't responsible for guest kernel bugs, especially those > which apply to real hardware (we should make more effort for virtio > bugs). It's enough that we fix qemu here. > > >> >It also looks like we can't have a workaround in QEMU to get older > >> >guests to work. > >> > >> Older guests? or older hosts? > > > >Older guests (not patched with fix for the bug described above). > > > >Since the guest kernel completely misses the disc change event in the > >path that does the revalidation, there's nothing qemu can do that will > >make such older guests notice disc change. > > > >Also: if only the guest kernel is updated by qemu is not, things still > >won't work since qemu will never send valid information for the > >GET_EVENT_STATUS_NOTIFICATION command. > > > >> >However, a hack in the kernel can be used without any QEMU changes > >> >(revalidate disk on each sr_open() call, irrespective of detecting any > >> >media change). I'm against doing that for upstream, but downstreams > >> >could do that for new guest - old hypervisor compat. > >> > >> Seriously confused. Please use the kernels "host kernel" and "qemu" > >> instead of "hypervisor" which is ambiguous. > > > >OK: this last bit says that forcefully revalidating discs in the guest > >kernel when a guest userspace opens the disc will ensure size changes > >are reflected properly for guest userspace. So in this case, even if > >we're using an older qemu which doesn't implement > >GET_EVENT_STATUS_NOTIFICATION, guest userspace apps will work fine. > > > >This is obviously a hack. > > Yes. Thanks for the clarification. > > (let's see if I really got it - we have a kernel bug that hit both > the guest and the host, plus a qemu bug?) Yes -- but just that we have many more qemu bugs. Our cdrom emulation has a lot of holes when it comes to being spec-compliant. I have a few fixes, Markus is working on some as well. Amit From mcastrol at gmail.com Tue Apr 5 09:57:02 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Tue, 5 Apr 2011 11:57:02 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: <20110404102013.GB13616@redhat.com> References: <20110404102013.GB13616@redhat.com> Message-ID: Hello Daniel Thank you for all your information, but I still didn't solve the problem. I tried the option you mention, with two differents guest into two differents host, but all the cases I've got: *virsh # restore sv-chubut-2011-04-04-17:38* *error: Failed to restore domain from sv-chubut-2011-04-04-17:38* *error: monitor socket did not show up.: Connection refused*** I cannot get any useful information (at least form me) on the log you mention. I'd appreciate a lot a new suggestion. Thanks Marcela 2011/4/4 Daniel P. Berrange > On Sun, Apr 03, 2011 at 10:43:45AM +0200, Marcela Castro Le?n wrote: > > Hello: > > I need to know if I can use the restore operation (virsh o the equivalent > in > > libvirt) to recover a previous state of a guest, but recovered previously > in > > another host. > > I did a test, but I got an error: > > > > The exactly sequence using virsh I testes is: > > On [HOST SOURCE]: Using virsh > > 1) save [domain] [file] > > 2) restore file > > 3) destroy [domain] > > > > On [HOST SOURCE] using ubuntu sh > > 4) cp [guest.img] [guest.xml] [file] to HOST2 > > > > On [HOST TARGET] using virsh > > 5) define [guest.xml] (using image on destination in HOST2) > > 6) restore [file] > > As a general rule you should only ever 'restore' from a > file *once*. This is because after the first restore > operation, the guest may have made writes to its disk. > Restoring a second time the guest OS will likely have > an inconsistent view of the disk & will cause filesystem > corruption. > > If you want to be able to restore from a saved image > multiple times, you need to also take a snapshot of > the disk image at the same time, and restore that > snapshot when restoring the memory image. > > > That aside, saving on one host & restoring on a > different host is fine. So if you leave out steps > 2+3 in your example above, then your data would > still be safe. > > > The restore troughs the following message: > > *virsh # restore sv-chubut-2011-04-01-09:58 > > error: Failed to restore domain from sv-chubut-2011-04-01-09:58 > > error: monitor socket did not show up.: Connection refused* > > There is probably some configuration difference on your 2nd host > that prevented the VM from starting up. If you're lucky the file > /var/log/libvirt/qemu/$NAME.log will tell you more > > Daniel > -- > |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/:| > |: http://libvirt.org -o- http://virt-manager.org:| > |: http://autobuild.org -o- http://search.cpan.org/~danberr/:| > |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc:| > -------------- next part -------------- An HTML attachment was scrubbed... URL: From berrange at redhat.com Tue Apr 5 10:36:36 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 5 Apr 2011 11:36:36 +0100 Subject: [libvirt] [PATCH 6/6] Remove unused macros and enable -Wunused-macros In-Reply-To: <4D9A3004.50305@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> <1301934004-6204-7-git-send-email-berrange@redhat.com> <4D9A3004.50305@redhat.com> Message-ID: <20110405103636.GB32225@redhat.com> On Mon, Apr 04, 2011 at 02:54:28PM -0600, Eric Blake wrote: > On 04/04/2011 10:20 AM, Daniel P. Berrange wrote: > > * m4/virt-compile-warnings.m4: Enable -Wunused-macros > > * daemon/libvirtd.c: Remove MAX_LISTEN > > * daemon/remote.c: Remote VIR_FROM_THIS > > s/Remote/Remove/ > > > 33 files changed, 38 insertions(+), 108 deletions(-) > > Nice ratio! > > > +++ b/src/esx/esx_vi_methods.c > > @@ -1,4 +1,3 @@ > > - > > /* > > * esx_vi_methods.c: client for the VMware VI API 2.5 to manage ESX hosts > > * > > @@ -52,8 +51,10 @@ > > > > > > > > +#if 0 > > #define ESX_VI__METHOD__CHECK_OUTPUT__RequiredList \ > > Won't this cause 'make syntax-check' grief during cppi checks? (Multiple > instances) > > > +++ b/tools/virsh.c > > @@ -409,15 +409,6 @@ _vshStrdup(vshControl *ctl, const char *s, const char *filename, int line) > > exit(EXIT_FAILURE); > > } > > > > -/* Poison the raw allocating identifiers in favor of our vsh variants. */ > > -#undef malloc > > -#undef calloc > > -#undef realloc > > -#undef strdup > > -#define malloc use_vshMalloc_instead_of_malloc > > -#define calloc use_vshCalloc_instead_of_calloc > > -#define realloc use_vshRealloc_instead_of_realloc > > -#define strdup use_vshStrdup_instead_of_strdup > > Hmm, I don't want to completely lose this. Can we instead include > "warn-on-use.h" (already provided by gnulib) and do: > > _GL_WARN_ON_USE(malloc, "use vshMalloc instead of malloc"); > > to get the same poisoning effects but via magic attributes rather than > unused macros? That doesn't work either: cc1: warnings being treated as errors virsh.c:366:1: error: redundant redeclaration of 'malloc' [-Wredundant-decls] virsh.c:367:1: error: redundant redeclaration of 'calloc' [-Wredundant-decls] virsh.c:368:1: error: redundant redeclaration of 'realloc' [-Wredundant-decls] virsh.c:369:1: error: redundant redeclaration of 'strdup' [-Wredundant-decls] What we really want is a syntax-check rule for these i reckon Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Tue Apr 5 10:41:36 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 5 Apr 2011 11:41:36 +0100 Subject: [libvirt] [PATCH 1/6] Use gnulib's manywarnings & warnings modules In-Reply-To: <4D9A2A12.3010401@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> <1301934004-6204-2-git-send-email-berrange@redhat.com> <4D9A2A12.3010401@redhat.com> Message-ID: <20110405104136.GC32225@redhat.com> On Mon, Apr 04, 2011 at 02:29:06PM -0600, Eric Blake wrote: > On 04/04/2011 10:19 AM, Daniel P. Berrange wrote: > > Remove custom code for checking compiler warnings, using > > gl_WARN_ADD instead. Don't list all flags ourselves, use > > gnulib's gl_MANYWARN_ALL_GCC to get all possible GCC flags, > > then turn off the ones we don't want yet. > > > > * acinclude.m4: Rewrite to use gl_WARN_ADD and gl_MANYWARN_ALL_GCC > > * bootstrap.conf: Add warnings & manywarnings > > * configure.ac: Switch to gl_WARN_ADD > > * m4/compiler-flags.m4: Obsoleted by gl_WARN_ADD > > --- > > acinclude.m4 | 158 +++++++++++++++++++++++++++----------------------- > > bootstrap.conf | 2 + > > configure.ac | 15 +++-- > > m4/compiler-flags.m4 | 48 --------------- > > 4 files changed, 96 insertions(+), 127 deletions(-) > > delete mode 100644 m4/compiler-flags.m4 > > > + > > + # List of warnings that are not relevant / wanted > > + dontwarn="$dontwarn -Wc++-compat" # Don't care about C++ compiler compat > > + dontwarn="$dontwarn -Wtraditional" # Don't care about ancient C standard compat > > + dontwarn="$dontwarn -Wtraditional-conversion" # Don't care about ancient C standard compat > > + dontwarn="$dontwarn -Wsystem-headers" # Ignore warnings in /usr/include > > + dontwarn="$dontwarn -Wpadded" # Happy for compiler to add struct padding > > + dontwarn="$dontwarn -Wunreachable-code" # GCC very confused with -O2 > > + dontwarn="$dontwarn -Wconversion" # Too many to deal with > > + dontwarn="$dontwarn -Wsign-conversion" # Too many to deal with > > + dontwarn="$dontwarn -Wvla" # GNULIB gettext.h violates > > + dontwarn="$dontwarn -Wundef" # Many GNULIB violations > > + dontwarn="$dontwarn -Wcast-qual" # Need to allow bad cast for execve() > > + dontwarn="$dontwarn -Wlong-long" # We need to use long long in many places > > + dontwarn="$dontwarn -Wswitch-default" # We allow manual list of all enum cases without default: > > + dontwarn="$dontwarn -Wswitch-enum" # We allow optional default: instead of listing all enum values > > + dontwarn="$dontwarn -Wstrict-overflow" # Not a problem since we don't use -fstrict-overflow > > + dontwarn="$dontwarn -Wunsafe-loop-optimizations" # Not a problem since we don't use -funsafe-loop-optimizations > > Seems okay (but long lines - any way to break that into 80 columns?) > > > + > > + # We might fundamentally need some of these disabled forever, but ideally > > + # we'd turn many of them on > > + dontwarn="$dontwarn -Wformat-nonliteral" > > This one may need to always be disabled, thanks to virAsprintf (it would > be nicer if we could disable for just one or two files, rather than > globally). > > > + dontwarn="$dontwarn -Wfloat-equal" > > + dontwarn="$dontwarn -Wdeclaration-after-statement" > > If gcc would do better, I'd love to guarantee C99 and take advantage of > this (smaller scopes have maintenance benefits) - thus, I envision this > one being permanent (float it up to the earlier set). > > > + dontwarn="$dontwarn -Wcast-qual" > > + dontwarn="$dontwarn -Wconversion" > > + dontwarn="$dontwarn -Wsign-conversion" > > + dontwarn="$dontwarn -Wold-style-definition" > > + dontwarn="$dontwarn -Wmissing-noreturn" > > + dontwarn="$dontwarn -Wpacked" > > + dontwarn="$dontwarn -Wunused-macros" > > + dontwarn="$dontwarn -Woverlength-strings" > > + dontwarn="$dontwarn -Wmissing-format-attribute" > > + dontwarn="$dontwarn -Wstack-protector" > > Yes, I agree that the rest of these should be temporary, and are > probably worth fixing. > > > + > > + # Get all possible GCC warnings > > + gl_MANYWARN_ALL_GCC([maybewarn]) > > + > > + # Remove the ones we don't want, blacklisted earlier > > + gl_MANYWARN_COMPLEMENT([wantwarn], [$maybewarn], [$dontwarn]) > > + > > + # Check for $CC support of each warning > > + for w in $wantwarn; do > > + gl_WARN_ADD([$w]) > > + done > > + > > + # GNULIB uses '-W' which includes a bunch of stuff, > > + # kinda like -Wextra. Unfortunately, it means you > > "kinda like"? Exactly like! -W was the old spelling, -Wextra was the > new one (added quite some time ago; something like gcc 3.4, off the top > of my head). Ah, I didn't realize it was the same. > > > + # can't simply use '-Wsign-compare' with gl_MANYWARN_COMPLEMENT > > + # So we have -W enabled, and then have to explicitly turn off > > + gl_WARN_ADD(-Wno-sign-compare) > > + > > + # This should be < 256 really, but with PATH_MAX everywhere > > + # we have doom, even with 4096. In fact we have some functions > > + # with several PATH_MAX sized variables :-( We should kill off > > + # all PATH_MAX usage and then lower this limit > > + gl_WARN_ADD([-Wframe-larger-than=65700]) > > + dnl gl_WARN_ADD([-Wframe-larger-than=4096]) > > + dnl gl_WARN_ADD([-Wframe-larger-than=256]) > > + > > + # Extra special flags > > + gl_WARN_ADD([-Wp,-D_FORTIFY_SOURCE=2]) > > + dnl Fedora only uses -fstack-protector, but doesn't seem to > > + dnl be great overhead in adding -fstack-protector-all instead > > + dnl gl_WARN_ADD([-fstack-protector]) > > + gl_WARN_ADD([-fstack-protector-all]) > > + gl_WARN_ADD([--param=ssp-buffer-size=4]) > > + gl_WARN_ADD([-fexceptions]) > > + gl_WARN_ADD([-fasynchronous-unwind-tables]) > > + gl_WARN_ADD([-fdiagnostics-show-option]) > > + > > + if test "$enable_compile_warnings" = "error" > > + then > > + gl_WARN_ADD([-Werror]) > > + fi > > Looks like a good conversion. I also added gl_WARN_ADD([-Wjump-misses-init]) because we loose that due to turning off -Wc++-compat Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Tue Apr 5 10:42:46 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 5 Apr 2011 11:42:46 +0100 Subject: [libvirt] [PATCH 2/6] Remove acinclude.m4 file In-Reply-To: <4D9A2BEC.1080809@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> <1301934004-6204-3-git-send-email-berrange@redhat.com> <4D9A2BEC.1080809@redhat.com> Message-ID: <20110405104246.GD32225@redhat.com> On Mon, Apr 04, 2011 at 02:37:00PM -0600, Eric Blake wrote: > On 04/04/2011 10:20 AM, Daniel P. Berrange wrote: > > Split the bit acinclude.m4 file into smaller pieces named > > as m4/virt-XXXXX.m4 > > > > * .gitignore: Ignore gettext related files > > * acinclude.m4: Delete > > * m4/virt-compile-warnings.m4: Checks for GCC compiler flags > > * m4/virt-pkgconfig-back-compat.m4: Backcompat check for > > pkgconfig program > > --- > > .gitignore | 36 +++++++++- > > acinclude.m4 | 137 -------------------------------------- > > m4/virt-compile-warnings.m4 | 112 +++++++++++++++++++++++++++++++ > > m4/virt-pkgconfig-back-compat.m4 | 23 ++++++ > > 4 files changed, 169 insertions(+), 139 deletions(-) > > delete mode 100644 acinclude.m4 > > create mode 100644 m4/virt-compile-warnings.m4 > > create mode 100644 m4/virt-pkgconfig-back-compat.m4 > > > > diff --git a/.gitignore b/.gitignore > > index ba4d351..278bc4f 100644 > > --- a/.gitignore > > +++ b/.gitignore > > @@ -1,4 +1,3 @@ > > -!/m4/compiler-flags.m4 > > !/po/*.po > > !/po/POTFILES.in > > !/po/libvirt.pot > > @@ -46,7 +45,6 @@ > > /libvirt.spec > > Yuck - gnulib's bootstrap script sorts .gitignore, but this is broken > (lines starting with ! should come last, not first, according to 'man > gitignore'; it's a shame I'm just noticing it now, since it's been > broken since November 2010). > > > @@ -67,3 +65,37 @@ results.log > > stamp-h > > stamp-h.in > > stamp-h1 > > +m4/codeset.m4 > > +m4/gettext.m4 > > Rerunning bootstrap will re-sort this list, leading to spurious diffs > unless we get it sorted first. But why should we blacklist all of the > m4 files individually, when it is much easier to whitelist just the > files we want? > > /m4/ > !/m4/virt-*.m4 Ok, I've pushed with that, but with the bogus sort order, since it is no worse than what we already have. We can fix sort order once gnulib is fixed. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Tue Apr 5 10:43:48 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 5 Apr 2011 11:43:48 +0100 Subject: [libvirt] [PATCH 4/6] Enable use of -Wmissing-noreturn In-Reply-To: <4D9A2D2A.3060108@redhat.com> References: <1301934004-6204-1-git-send-email-berrange@redhat.com> <1301934004-6204-5-git-send-email-berrange@redhat.com> <4D9A2D2A.3060108@redhat.com> Message-ID: <20110405104348.GE32225@redhat.com> On Mon, Apr 04, 2011 at 02:42:18PM -0600, Eric Blake wrote: > On 04/04/2011 10:20 AM, Daniel P. Berrange wrote: > > * src/internal.h: Define a ATTRIBUTE_NO_RETURN annotation > > * src/lxc/lxc_container.c: Annotate lxcContainerDummyChild > > with ATTRIBUTE_NO_RETURN > > * tests/eventtest.c: Mark async thread as ATTRIBUTE_NO_RETURN > > * m4/virt-compile-warnings.m4: Enable -Wmissing-noreturn > > --- > > m4/virt-compile-warnings.m4 | 1 - > > src/internal.h | 9 +++++++++ > > src/lxc/lxc_container.c | 3 ++- > > tests/eventtest.c | 3 +-- > > 4 files changed, 12 insertions(+), 4 deletions(-) > > > > > +++ b/src/internal.h > > @@ -117,6 +117,15 @@ > > # endif > > > > /** > > + * ATTRIBUTE_NORETURN: > > + * > > + * Macro to indicate that a function won't return to the caller > > + */ > > +# ifndef ATTRIBUTE_NORETURN > > +# define ATTRIBUTE_NORETURN __attribute__((__noreturn__)) > > +# endif > > Do we need a minimum gcc version detection, so this cause grief on older > setups? It has existed since gcc 2.4, so IMHO that is so old we don't need the check Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Tue Apr 5 11:10:54 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 5 Apr 2011 12:10:54 +0100 Subject: [libvirt] [PATCH v3] Improve SCSI volume key generation Message-ID: <1302001854-2218-1-git-send-email-berrange@redhat.com> The SCSI volumes get a better 'key' field based on the fully qualified volume path. All SCSI volumes have a unique serial available in hardware which can be obtained by sending a suitable SCSI command. Call out to udev's 'scsi_id' command to fetch this value In v3: - Use virCommandSetOutputBuffer/virCommandRun instead of VIR_FDOPEN - Skip serial if it matches empty string * src/storage/storage_backend_scsi.c: Improve volume key field value stability and uniqueness --- src/storage/storage_backend_scsi.c | 45 ++++++++++++++++++++++++++++++++--- 1 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c index d880d65..da34547 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -33,6 +33,7 @@ #include "memory.h" #include "logging.h" #include "files.h" +#include "command.h" #define VIR_FROM_THIS VIR_FROM_STORAGE @@ -160,6 +161,45 @@ cleanup: return ret; } + +static char * +virStorageBackendSCSISerial(const char *dev) +{ + char *serial = NULL; +#ifdef HAVE_UDEV + virCommandPtr cmd = virCommandNewArgList( + "/lib/udev/scsi_id", + "--replace-whitespace", + "--whitelisted", + "--device", dev, + NULL + ); + + /* Run the program and capture its output */ + virCommandSetOutputBuffer(cmd, &serial); + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; +#endif + + if (serial && STRNEQ(serial, "")) { + char *nl = strchr(serial, '\n'); + if (nl) + *nl = '\0'; + } else { + VIR_FREE(serial); + if (!(serial = strdup(dev))) + virReportOOMError(); + } + +#ifdef HAVE_UDEV +cleanup: + virCommandFree(cmd); +#endif + + return serial; +} + + static int virStorageBackendSCSINewLun(virStoragePoolObjPtr pool, uint32_t host ATTRIBUTE_UNUSED, @@ -233,10 +273,7 @@ virStorageBackendSCSINewLun(virStoragePoolObjPtr pool, goto free_vol; } - /* XXX should use logical unit's UUID instead */ - vol->key = strdup(vol->target.path); - if (vol->key == NULL) { - virReportOOMError(); + if (!(vol->key = virStorageBackendSCSISerial(vol->target.path))) { retval = -1; goto free_vol; } -- 1.7.4 From minovotn at redhat.com Tue Apr 5 11:38:12 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 05 Apr 2011 13:38:12 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: References: <20110404102013.GB13616@redhat.com> Message-ID: <4D9AFF24.6060109@redhat.com> Hi Marcela, is any other guest on the host that cannot restore this VM working fine ? You could also try running the: */# LIBVIRT_DEBUG=1 virsh restore sv-chubut-2011-04-04-17:38 2> virsh-restore.log /*command which would enable the libvirt logging and output the debug log into the virsh-restore.log file. This file could be sent to the list for analysis what's wrong. Thanks, Michal On 04/05/2011 11:57 AM, Marcela Castro Le?n wrote: > Hello Daniel > Thank you for all your information, but I still didn't solve the > problem. I tried the option you mention, with two differents guest > into two differents host, but all the cases I've got: > > */virsh # restore sv-chubut-2011-04-04-17:38/* > */error: Failed to restore domain from sv-chubut-2011-04-04-17:38/* > */error: monitor socket did not show up.: Connection refused/* > > I cannot get any useful information (at least form me) on the log you > mention. > I'd appreciate a lot a new suggestion. > Thanks > Marcela > > > > > 2011/4/4 Daniel P. Berrange > > > On Sun, Apr 03, 2011 at 10:43:45AM +0200, Marcela Castro Le?n wrote: > > Hello: > > I need to know if I can use the restore operation (virsh o the > equivalent in > > libvirt) to recover a previous state of a guest, but recovered > previously in > > another host. > > I did a test, but I got an error: > > > > The exactly sequence using virsh I testes is: > > On [HOST SOURCE]: Using virsh > > 1) save [domain] [file] > > 2) restore file > > 3) destroy [domain] > > > > On [HOST SOURCE] using ubuntu sh > > 4) cp [guest.img] [guest.xml] [file] to HOST2 > > > > On [HOST TARGET] using virsh > > 5) define [guest.xml] (using image on destination in HOST2) > > 6) restore [file] > > As a general rule you should only ever 'restore' from a > file *once*. This is because after the first restore > operation, the guest may have made writes to its disk. > Restoring a second time the guest OS will likely have > an inconsistent view of the disk & will cause filesystem > corruption. > > If you want to be able to restore from a saved image > multiple times, you need to also take a snapshot of > the disk image at the same time, and restore that > snapshot when restoring the memory image. > > > That aside, saving on one host & restoring on a > different host is fine. So if you leave out steps > 2+3 in your example above, then your data would > still be safe. > > > The restore troughs the following message: > > *virsh # restore sv-chubut-2011-04-01-09:58 > > error: Failed to restore domain from sv-chubut-2011-04-01-09:58 > > error: monitor socket did not show up.: Connection refused* > > There is probably some configuration difference on your 2nd host > that prevented the VM from starting up. If you're lucky the file > /var/log/libvirt/qemu/$NAME.log will tell you more > > Daniel > -- > |: http://berrange.com -o- > http://www.flickr.com/photos/dberrange/ :| > |: http://libvirt.org -o- > http://virt-manager.org :| > |: http://autobuild.org -o- > http://search.cpan.org/~danberr/ > :| > |: http://entangle-photo.org -o- > http://live.gnome.org/gtk-vnc :| > > > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From jyang at redhat.com Tue Apr 5 12:38:47 2011 From: jyang at redhat.com (Osier Yang) Date: Tue, 5 Apr 2011 20:38:47 +0800 Subject: [libvirt] [PATCH] virsh: Fix a problem of argv parsing Message-ID: <1302007127-16185-1-git-send-email-jyang@redhat.com> Problem example: # virsh -d 5 vol-create --pool default col.xml vol-create: pool(optdata): default vol-create: pool(optdata): col.xml error: command 'vol-create' requires option It gets same "vshCmdOptDef" for both "--pool default" and "col.xml". This patch fixes it by increase "data_ct" when things like "--pool default" is successfully parsed, so that could get right "vshCmdOptDef" for the other arguments which are not with option name together. --- tools/virsh.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 19e3449..4d52bfb 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -11750,6 +11750,8 @@ vshCommandParse(vshControl *ctl, vshCommandParser *parser) VSH_OT_INT ? _("number") : _("string")); goto syntaxError; } + + data_ct++; } else { tkdata = NULL; if (optstr) { -- 1.7.4 From stefanha at gmail.com Tue Apr 5 05:33:36 2011 From: stefanha at gmail.com (Stefan Hajnoczi) Date: Tue, 5 Apr 2011 06:33:36 +0100 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D9A05D1.1000501@gmail.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D9A05D1.1000501@gmail.com> Message-ID: On Mon, Apr 4, 2011 at 6:54 PM, David Ahern wrote: > > > On 04/04/11 07:38, Anthony Liguori wrote: >> On 04/04/2011 08:22 AM, Avi Kivity wrote: >>> On 04/03/2011 02:57 PM, Stefan Hajnoczi wrote: >>>> In order for media change to work with Linux host CD-ROM it is >>>> necessary to reopen the file (otherwise the inode size will not >>>> refresh, this is an issue with existing kernels). >>>> >>> >>> Maybe we should fix the bug in Linux (and backport as necessary)? >>> >>> I think cd-rom assignment is sufficiently obscure that we can require >>> a fixed kernel instead of providing a workaround. >> >> Do reads fail after CD change? ?Or do they succeed and the size is just >> reported incorrectly? >> >> If it's the later, I'd agree that it needs fixing in the kernel. ?If >> it's the former, I'd say it's clearly a feature. > > In January 2010 I was seeing old data -- data from the prior CD -- in > the guest after the media change. Yikes. Is there a bug report for this? What are the steps to reproduce it? Stefan From dsahern at gmail.com Tue Apr 5 05:42:57 2011 From: dsahern at gmail.com (David Ahern) Date: Mon, 04 Apr 2011 23:42:57 -0600 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D9A05D1.1000501@gmail.com> Message-ID: <4D9AABE1.9030609@gmail.com> On 04/04/11 23:33, Stefan Hajnoczi wrote: > On Mon, Apr 4, 2011 at 6:54 PM, David Ahern wrote: >> On 04/04/11 07:38, Anthony Liguori wrote: >>> On 04/04/2011 08:22 AM, Avi Kivity wrote: >>>> On 04/03/2011 02:57 PM, Stefan Hajnoczi wrote: >>>>> In order for media change to work with Linux host CD-ROM it is >>>>> necessary to reopen the file (otherwise the inode size will not >>>>> refresh, this is an issue with existing kernels). >>>>> >>>> >>>> Maybe we should fix the bug in Linux (and backport as necessary)? >>>> >>>> I think cd-rom assignment is sufficiently obscure that we can require >>>> a fixed kernel instead of providing a workaround. >>> >>> Do reads fail after CD change? Or do they succeed and the size is just >>> reported incorrectly? >>> >>> If it's the later, I'd agree that it needs fixing in the kernel. If >>> it's the former, I'd say it's clearly a feature. >> >> In January 2010 I was seeing old data -- data from the prior CD -- in >> the guest after the media change. > > Yikes. Is there a bug report for this? What are the steps to reproduce it? Not that I know of. It is reported by someone else last year as well: http://www.mail-archive.com/kvm at vger.kernel.org/msg32999.html > > Stefan From jdenemar at redhat.com Tue Apr 5 13:00:06 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 5 Apr 2011 15:00:06 +0200 Subject: [libvirt] [PATCH] qemu: Rewrite LOOKUP_PTYS macro into a function In-Reply-To: <4D9A20B0.6070405@redhat.com> References: <6583e184fb3f616c15ec4bc42f1af58fff320a8b.1301924390.git.jdenemar@redhat.com> <4D9A20B0.6070405@redhat.com> Message-ID: <20110405130006.GA7195@orkuz.home> On Mon, Apr 04, 2011 at 13:49:04 -0600, Eric Blake wrote: > On 04/04/2011 07:46 AM, Jiri Denemark wrote: > > The macro is huge and gives us nothing but headache when maintaining it. > > --- > > The reason for this patch is not that I'm going to modify anything in > > the code. It's that I was working in the area and noticed this huge > > macro. > > > > src/qemu/qemu_process.c | 102 ++++++++++++++++++++++++++++------------------- > > 1 files changed, 61 insertions(+), 41 deletions(-) > > The diffstat hides the fact that this really is a code cleanup. > > ACK. Thanks, pushed. Jirka From jdenemar at redhat.com Tue Apr 5 13:00:24 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 5 Apr 2011 15:00:24 +0200 Subject: [libvirt] [PATCH] qemu: Ignore unusable binaries In-Reply-To: <4D9A44DB.1080802@redhat.com> References: <4D9A44DB.1080802@redhat.com> Message-ID: <20110405130024.GB7195@orkuz.home> On Mon, Apr 04, 2011 at 16:23:23 -0600, Eric Blake wrote: > On 04/04/2011 04:08 PM, Jiri Denemark wrote: > > When initializing qemu guest capabilities, we should ignore qemu > > binaries that we are not able to extract version/help info from since > > they will be unusable for creating domains anyway. Ignoring them is also > > much better than letting initialization of qemu driver fail. > > --- > > src/qemu/qemu_capabilities.c | 11 ++++++++--- > > 1 files changed, 8 insertions(+), 3 deletions(-) > > ACK. Thanks, pushed. Jirka From jdenemar at redhat.com Tue Apr 5 13:20:38 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 5 Apr 2011 15:20:38 +0200 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <1301986042-13725-1-git-send-email-jyang@redhat.com> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> Message-ID: <20110405132037.GC7195@orkuz.home> On Tue, Apr 05, 2011 at 14:47:22 +0800, Osier Yang wrote: > Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to > restore the domain from managedsave'ed image if it exists (by > invoking "qemuDomainObjRestore"), but it unlinks the image even > if restoring fails, which causes data loss. > > However, I'm not sure if it's the very correct way to fix it, > if restoring fails, and we didn't remove the image, it will > trys to restore from the image again next time, if that's > not the user expected (e.g. the user made quite many changes > on the guest), then it's a new problem. I think this patch is risky. You should either remove the state on error (which is the current state) or fail domain start if managed state is present but resuming from it fails. If you do something in the middle (your patch) you will certainly end up corrupting domain's disks. Jirka From jyang at redhat.com Tue Apr 5 13:24:39 2011 From: jyang at redhat.com (Osier Yang) Date: Tue, 05 Apr 2011 21:24:39 +0800 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <20110405132037.GC7195@orkuz.home> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> Message-ID: <4D9B1817.50705@redhat.com> ? 2011?04?05? 21:20, Jiri Denemark ??: > On Tue, Apr 05, 2011 at 14:47:22 +0800, Osier Yang wrote: >> Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to >> restore the domain from managedsave'ed image if it exists (by >> invoking "qemuDomainObjRestore"), but it unlinks the image even >> if restoring fails, which causes data loss. >> >> However, I'm not sure if it's the very correct way to fix it, >> if restoring fails, and we didn't remove the image, it will >> trys to restore from the image again next time, if that's >> not the user expected (e.g. the user made quite many changes >> on the guest), then it's a new problem. > > I think this patch is risky. You should either remove the state on error > (which is the current state) or fail domain start if managed state is present > but resuming from it fails. If you do something in the middle (your patch) you > will certainly end up corrupting domain's disks. > > Jirka Hum, it makes sense, that's what I was worried about, I think failing domain start will be better than data loss anyway, so will update with that. Thanks for the reviewing Regards Osier From jyang at redhat.com Tue Apr 5 13:35:30 2011 From: jyang at redhat.com (Osier Yang) Date: Tue, 5 Apr 2011 21:35:30 +0800 Subject: [libvirt] [PATCH v2] qemu: Do not unlink managedsave image if restoring fails In-Reply-To: <20110405132037.GC7195@orkuz.home> References: <20110405132037.GC7195@orkuz.home> Message-ID: <1302010530-23152-1-git-send-email-jyang@redhat.com> Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to restore the domain from managedsave'ed image if it exists (by invoking "qemuDomainObjRestore"), but it unlinks the image even if restoring fails, which causes data loss. The fix is to fail the domain startup if the restoring fails, but doesn't unlink()s the save state. v1 - v2: * Fails the domain startup and throws error instead of throwing a warning. --- src/qemu/qemu_driver.c | 15 +++++++++------ 1 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 48fe266..ef4d277 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3423,18 +3423,21 @@ static int qemudDomainObjStart(virConnectPtr conn, /* * If there is a managed saved state restore it instead of starting - * from scratch. In any case the old state is removed. + * from scratch. */ managed_save = qemuDomainManagedSavePath(driver, vm); if ((managed_save) && (virFileExists(managed_save))) { ret = qemuDomainObjRestore(conn, driver, vm, managed_save); - if (unlink(managed_save) < 0) { - VIR_WARN("Failed to remove the managed state %s", managed_save); + if (ret == 0) { + if (unlink(managed_save) < 0) + VIR_WARN("Failed to remove the managed state %s", managed_save); + } else { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to restore from the managed state %s"), + managed_save); } - - if (ret == 0) - goto cleanup; + goto cleanup; } ret = qemuProcessStart(conn, driver, vm, NULL, start_paused, -1, NULL, -- 1.7.4 From jyang at redhat.com Tue Apr 5 13:49:58 2011 From: jyang at redhat.com (Osier Yang) Date: Tue, 5 Apr 2011 21:49:58 +0800 Subject: [libvirt] [PATCH] qemu: Always reserves slot 0x02 for primary VGA. Message-ID: <1302011398-25541-1-git-send-email-jyang@redhat.com> To address https://bugzilla.redhat.com/show_bug.cgi?id=692355 This fix is to reserve slot 0x02 for primary VGA even if there is no "video" specified in domain XML to avoid the problem. --- src/qemu/qemu_command.c | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 3d25ba4..9b93d5e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -947,6 +947,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) { int i; bool reservedIDE = false; + bool reservedVGA = false; /* Host bridge */ if (qemuDomainPCIAddressReserveSlot(addrs, 0) < 0) @@ -966,7 +967,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) _("Primary IDE controller must have PCI address 0:0:1.1")); goto error; } - /* If TYPE==PCI, then then qemuCollectPCIAddress() function + /* If TYPE==PCI, then qemuCollectPCIAddress() function * has already reserved the address, so we must skip */ reservedIDE = true; } else { @@ -997,16 +998,22 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) _("Primary video card must have PCI address 0:0:2.0")); goto error; } + /* If TYPE==PCI, then qemuCollectPCIAddress() function + * has already reserved the address, so we must skip */ + reservedVGA = true; } else { def->videos[0]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; def->videos[0]->info.addr.pci.domain = 0; def->videos[0]->info.addr.pci.bus = 0; def->videos[0]->info.addr.pci.slot = 2; def->videos[0]->info.addr.pci.function = 0; - if (qemuDomainPCIAddressReserveSlot(addrs, 2) < 0) - goto error; } } + + if (!reservedVGA + && qemuDomainPCIAddressReserveSlot(addrs, 2) < 0) + goto error; + for (i = 0; i < def->nfss ; i++) { if (def->fss[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) continue; -- 1.7.4 From stefanha at gmail.com Tue Apr 5 12:41:37 2011 From: stefanha at gmail.com (Stefan Hajnoczi) Date: Tue, 5 Apr 2011 13:41:37 +0100 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D9AABE1.9030609@gmail.com> References: <1301425482-8722-1-git-send-email-stefanha@linux.vnet.ibm.com> <1301425482-8722-4-git-send-email-stefanha@linux.vnet.ibm.com> <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D9A05D1.1000501@gmail.com> <4D9AABE1.9030609@gmail.com> Message-ID: On Tue, Apr 5, 2011 at 6:42 AM, David Ahern wrote: > On 04/04/11 23:33, Stefan Hajnoczi wrote: >> On Mon, Apr 4, 2011 at 6:54 PM, David Ahern wrote: >>> On 04/04/11 07:38, Anthony Liguori wrote: >>>> On 04/04/2011 08:22 AM, Avi Kivity wrote: >>>>> On 04/03/2011 02:57 PM, Stefan Hajnoczi wrote: >>>>>> In order for media change to work with Linux host CD-ROM it is >>>>>> necessary to reopen the file (otherwise the inode size will not >>>>>> refresh, this is an issue with existing kernels). >>>>>> >>>>> >>>>> Maybe we should fix the bug in Linux (and backport as necessary)? >>>>> >>>>> I think cd-rom assignment is sufficiently obscure that we can require >>>>> a fixed kernel instead of providing a workaround. >>>> >>>> Do reads fail after CD change? ?Or do they succeed and the size is just >>>> reported incorrectly? >>>> >>>> If it's the later, I'd agree that it needs fixing in the kernel. ?If >>>> it's the former, I'd say it's clearly a feature. >>> >>> In January 2010 I was seeing old data -- data from the prior CD -- in >>> the guest after the media change. >> >> Yikes. ?Is there a bug report for this? ?What are the steps to reproduce it? > > Not that I know of. It is reported by someone else last year as well: > http://www.mail-archive.com/kvm at vger.kernel.org/msg32999.html Thanks for the link. That looks like typical symptoms of missing media change (which can also legitimately happen if the guest does not poll). This should be fixed once the CD-ROM fixes are merged into QEMU and Linux. Stefan From jdenemar at redhat.com Tue Apr 5 14:09:10 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 5 Apr 2011 16:09:10 +0200 Subject: [libvirt] [PATCH] qemu: Support for overriding NPROC limit Message-ID: This patch adds max_processes option to qemu.conf which can be used to override system default limit on number of processes that are allowed to be running for qemu user. --- src/qemu/libvirtd_qemu.aug | 3 +++ src/qemu/qemu.conf | 7 +++++++ src/qemu/qemu_conf.c | 4 ++++ src/qemu/qemu_conf.h | 2 ++ src/qemu/qemu_process.c | 24 ++++++++++++++++++++++++ src/qemu/test_libvirtd_qemu.aug | 4 ++++ 6 files changed, 44 insertions(+), 0 deletions(-) diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index affd74e..ac30b8e 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -13,11 +13,13 @@ module Libvirtd_qemu = let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\"" let bool_val = store /0|1/ + let int_val = store /[0-9]+/ let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ "" let str_array_val = counter "el" . array_start . ( str_array_element . ( array_sep . str_array_element ) * ) ? . array_end let str_entry (kw:string) = [ key kw . value_sep . str_val ] let bool_entry (kw:string) = [ key kw . value_sep . bool_val ] + let int_entry (kw:string) = [ key kw . value_sep . int_val ] let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ] @@ -45,6 +47,7 @@ module Libvirtd_qemu = | bool_entry "clear_emulator_capabilities" | bool_entry "allow_disk_format_probing" | bool_entry "set_process_name" + | int_entry "max_processes" (* Each enty in the config is one of the following three ... *) let entry = vnc_entry diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index 364f555..c70050e 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -273,3 +273,10 @@ # its arguments) appear in process listings. # # set_process_name = 1 + + +# If max_processes is set to a positive integer, libvirt will use it to set +# maximum number of processes that can be run by qemu user. This can be used to +# override default value set by host OS. +# +# max_processes = 0 diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 9ba60b1..bb5421b 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -424,6 +424,10 @@ int qemudLoadDriverConfig(struct qemud_driver *driver, CHECK_TYPE ("set_process_name", VIR_CONF_LONG); if (p) driver->setProcessName = p->l; + p = virConfGetValue(conf, "max_processes"); + CHECK_TYPE("max_processes", VIR_CONF_LONG); + if (p) driver->maxProcesses = p->l; + virConfFree (conf); return 0; } diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 7c6fde7..94918f6 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -105,6 +105,8 @@ struct qemud_driver { unsigned int allowDiskFormatProbing : 1; unsigned int setProcessName : 1; + int maxProcesses; + virCapsPtr caps; /* An array of callbacks */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 48ecd5c..9ada24d 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include "qemu_process.h" #include "qemu_domain.h" @@ -1811,6 +1813,25 @@ qemuProcessPrepareChardevDevice(virDomainDefPtr def ATTRIBUTE_UNUSED, } +static int +qemuProcessLimits(struct qemud_driver *driver) +{ + if (driver->maxProcesses > 0) { + struct rlimit rlim; + + rlim.rlim_cur = rlim.rlim_max = driver->maxProcesses; + if (setrlimit(RLIMIT_NPROC, &rlim) < 0) { + virReportSystemError(errno, + _("cannot limit number of processes to %d"), + driver->maxProcesses); + return -1; + } + } + + return 0; +} + + struct qemuProcessHookData { virConnectPtr conn; virDomainObjPtr vm; @@ -1821,6 +1842,9 @@ static int qemuProcessHook(void *data) { struct qemuProcessHookData *h = data; + if (qemuProcessLimits(h->driver) < 0) + return -1; + /* This must take place before exec(), so that all QEMU * memory allocation is on the correct NUMA node */ diff --git a/src/qemu/test_libvirtd_qemu.aug b/src/qemu/test_libvirtd_qemu.aug index 8e477f5..917bd4f 100644 --- a/src/qemu/test_libvirtd_qemu.aug +++ b/src/qemu/test_libvirtd_qemu.aug @@ -111,6 +111,8 @@ clear_emulator_capabilities = 0 allow_disk_format_probing = 1 vnc_auto_unix_socket = 1 + +max_processes = 12345 " test Libvirtd_qemu.lns get conf = @@ -232,3 +234,5 @@ vnc_auto_unix_socket = 1 { "allow_disk_format_probing" = "1" } { "#empty" } { "vnc_auto_unix_socket" = "1" } +{ "#empty" } +{ "max_processes" = "12345" } -- 1.7.4.1 From eblake at redhat.com Tue Apr 5 14:25:26 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 08:25:26 -0600 Subject: [libvirt] [PATCH v3] Improve SCSI volume key generation In-Reply-To: <1302001854-2218-1-git-send-email-berrange@redhat.com> References: <1302001854-2218-1-git-send-email-berrange@redhat.com> Message-ID: <4D9B2656.5020402@redhat.com> On 04/05/2011 05:10 AM, Daniel P. Berrange wrote: > The SCSI volumes get a better 'key' field based on the fully > qualified volume path. All SCSI volumes have a unique serial > available in hardware which can be obtained by sending a > suitable SCSI command. Call out to udev's 'scsi_id' command > to fetch this value > > In v3: > > - Use virCommandSetOutputBuffer/virCommandRun instead > of VIR_FDOPEN > - Skip serial if it matches empty string > > * src/storage/storage_backend_scsi.c: Improve volume key > field value stability and uniqueness > --- > src/storage/storage_backend_scsi.c | 45 ++++++++++++++++++++++++++++++++--- > 1 files changed, 41 insertions(+), 4 deletions(-) > > +#ifdef HAVE_UDEV > + virCommandPtr cmd = virCommandNewArgList( > + "/lib/udev/scsi_id", > + "--replace-whitespace", > + "--whitelisted", > + "--device", dev, > + NULL > + ); > + > + /* Run the program and capture its output */ > + virCommandSetOutputBuffer(cmd, &serial); > + if (virCommandRun(cmd, NULL) < 0) > + goto cleanup; > +#endif > + > + if (serial && STRNEQ(serial, "")) { > + char *nl = strchr(serial, '\n'); > + if (nl) > + *nl = '\0'; > + } else { > + VIR_FREE(serial); > + if (!(serial = strdup(dev))) > + virReportOOMError(); > + } > + > +#ifdef HAVE_UDEV > +cleanup: > + virCommandFree(cmd); > +#endif It seems a bit weird to have two #ifdef sections; but I don't see any easy way to consolidate them and still properly return failure on a failed virCommandRun. ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Tue Apr 5 14:50:30 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 08:50:30 -0600 Subject: [libvirt] [PATCH] virsh: Fix a problem of argv parsing In-Reply-To: <1302007127-16185-1-git-send-email-jyang@redhat.com> References: <1302007127-16185-1-git-send-email-jyang@redhat.com> Message-ID: <4D9B2C36.4060205@redhat.com> On 04/05/2011 06:38 AM, Osier Yang wrote: > Problem example: > # virsh -d 5 vol-create --pool default col.xml > vol-create: pool(optdata): default > vol-create: pool(optdata): col.xml > error: command 'vol-create' requires option > > It gets same "vshCmdOptDef" for both "--pool default" > and "col.xml". > > This patch fixes it by increase "data_ct" when things like > "--pool default" is successfully parsed, so that could > get right "vshCmdOptDef" for the other arguments which > are not with option name together. While I agree that this patch appears to fix the problem, I'd feel much better if we _also_ added a test case to prove we don't regress in the future (especially since we might be making future changes to argument parsing to improve tab-completion or unambiguous prefix support). It looks like the following are impacted (at least these are the commands with more than one VSH_OT_DATA/VSH_OFLAG_REQ option): domblkstat domifstat domblkinfo save dump vcpupin setvcpus setmem setmaxmem domxml-from-native domxml-to-native migrate migrate-setmaxdowntime pool-define-as pool-create-as vol-create-as vol-create vol-create-from vol-clone vol-upload vol-download secret-set-value attach-device detach-device update-device attach-interface detach-interface attach-disk detach-disk snapshot-dumpxml snapshot-revert snapshot-delete qemu-monitor-command And since test:///default supports setvcpus, a valid test might be to copy the layout of virsh-schedinfo as framework, and test that all of these are equivalent: virsh -c test:///default setvcpus test 2 virsh -c test:///default setvcpus --domain test 2 virsh -c test:///default setvcpus --domain=test 2 virsh -c test:///default setvcpus test --count 2 virsh -c test:///default setvcpus test --count=2 virsh -c test:///default setvcpus --domain test --count 2 virsh -c test:///default setvcpus --domain=test --count 2 virsh -c test:///default setvcpus --domain test --count=2 virsh -c test:///default setvcpus --domain=test --count=2 virsh -c test:///default setvcpus --count 2 --domain test virsh -c test:///default setvcpus --count 2 --domain=test virsh -c test:///default setvcpus --count=2 --domain test virsh -c test:///default setvcpus --count=2 --domain=test -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From mcastrol at gmail.com Tue Apr 5 14:54:05 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Tue, 5 Apr 2011 16:54:05 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: <4D9AFF24.6060109@redhat.com> References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> Message-ID: Hello This is the log I got doing the restore. It's says that it coun't get the image, but the image is ok, because I can startup the guest. Neither I can migrate the guest, so I suppose I've a problem in my configuration. Thank you very much in advance. Marcela. 2011/4/5 Michal Novotny > Hi Marcela, > is any other guest on the host that cannot restore this VM working fine ? > > You could also try running the: > > */# LIBVIRT_DEBUG=1 virsh restore sv-chubut-2011-04-04-17:38 2> > virsh-restore.log > > /*command which would enable the libvirt logging and output the debug > log into the virsh-restore.log file. This file could be sent to the list > for analysis what's wrong. > > Thanks, > Michal > > On 04/05/2011 11:57 AM, Marcela Castro Le?n wrote: > > Hello Daniel > > Thank you for all your information, but I still didn't solve the > > problem. I tried the option you mention, with two differents guest > > into two differents host, but all the cases I've got: > > > > */virsh # restore sv-chubut-2011-04-04-17:38/* > > */error: Failed to restore domain from sv-chubut-2011-04-04-17:38/* > > */error: monitor socket did not show up.: Connection refused/* > > > > I cannot get any useful information (at least form me) on the log you > > mention. > > I'd appreciate a lot a new suggestion. > > Thanks > > Marcela > > > > > > > > > > 2011/4/4 Daniel P. Berrange > > > > > > On Sun, Apr 03, 2011 at 10:43:45AM +0200, Marcela Castro Le?n wrote: > > > Hello: > > > I need to know if I can use the restore operation (virsh o the > > equivalent in > > > libvirt) to recover a previous state of a guest, but recovered > > previously in > > > another host. > > > I did a test, but I got an error: > > > > > > The exactly sequence using virsh I testes is: > > > On [HOST SOURCE]: Using virsh > > > 1) save [domain] [file] > > > 2) restore file > > > 3) destroy [domain] > > > > > > On [HOST SOURCE] using ubuntu sh > > > 4) cp [guest.img] [guest.xml] [file] to HOST2 > > > > > > On [HOST TARGET] using virsh > > > 5) define [guest.xml] (using image on destination in HOST2) > > > 6) restore [file] > > > > As a general rule you should only ever 'restore' from a > > file *once*. This is because after the first restore > > operation, the guest may have made writes to its disk. > > Restoring a second time the guest OS will likely have > > an inconsistent view of the disk & will cause filesystem > > corruption. > > > > If you want to be able to restore from a saved image > > multiple times, you need to also take a snapshot of > > the disk image at the same time, and restore that > > snapshot when restoring the memory image. > > > > > > That aside, saving on one host & restoring on a > > different host is fine. So if you leave out steps > > 2+3 in your example above, then your data would > > still be safe. > > > > > The restore troughs the following message: > > > *virsh # restore sv-chubut-2011-04-01-09:58 > > > error: Failed to restore domain from sv-chubut-2011-04-01-09:58 > > > error: monitor socket did not show up.: Connection refused* > > > > There is probably some configuration difference on your 2nd host > > that prevented the VM from starting up. If you're lucky the file > > /var/log/libvirt/qemu/$NAME.log will tell you more > > > > Daniel > > -- > > |: http://berrange.com -o- > > http://www.flickr.com/photos/dberrange/ :| > > |: http://libvirt.org -o- > > http://virt-manager.org :| > > |: http://autobuild.org -o- > > http://search.cpan.org/~danberr/ > > :| > > |: http://entangle-photo.org -o- > > http://live.gnome.org/gtk-vnc :| > > > > > > > > -- > > libvir-list mailing list > > libvir-list at redhat.com > > https://www.redhat.com/mailman/listinfo/libvir-list > > > -- > Michal Novotny , RHCE > Virtualization Team (xen userspace), Red Hat > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: restore_sv-chubut-2011-04-04-17:38.log Type: text/x-log Size: 6075 bytes Desc: not available URL: From eblake at redhat.com Tue Apr 5 14:55:01 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 08:55:01 -0600 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <20110405132037.GC7195@orkuz.home> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> Message-ID: <4D9B2D45.4020606@redhat.com> On 04/05/2011 07:20 AM, Jiri Denemark wrote: > On Tue, Apr 05, 2011 at 14:47:22 +0800, Osier Yang wrote: >> Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to >> restore the domain from managedsave'ed image if it exists (by >> invoking "qemuDomainObjRestore"), but it unlinks the image even >> if restoring fails, which causes data loss. >> >> However, I'm not sure if it's the very correct way to fix it, >> if restoring fails, and we didn't remove the image, it will >> trys to restore from the image again next time, if that's >> not the user expected (e.g. the user made quite many changes >> on the guest), then it's a new problem. > > I think this patch is risky. You should either remove the state on error > (which is the current state) or fail domain start if managed state is present > but resuming from it fails. If you do something in the middle (your patch) you > will certainly end up corrupting domain's disks. What's more, I think we should consider removing the saved-state file on success for 'virsh restore file' - once a state has been restored, the guest is running and has likely modified its disks, which means that the saved (memory) state is no longer consistent with the new disk state, and a second restore of the saved file is asking for a different type of data corruption. That is, I think: virsh save dom file virsh restore file should leave file intact if and only if the restore failed, and: virsh managedsave dom virsh start should either fail but leave the (hidden) state file intact, or succeed and remove the state file. We have virsh managedsave-remove to properly delete the state file if the user determines that they want a fresh start rather than retrying the (hidden) state file. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From mcastrol at gmail.com Tue Apr 5 15:01:00 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Tue, 5 Apr 2011 17:01:00 +0200 Subject: [libvirt] LIBVIRT migration In-Reply-To: References: <20110401142611.GK29510@redhat.com> Message-ID: Hello: I did more tests, but I don't find the problem. this is a debug I've got setting LIBVIRT_DEBUG=1, I'd appreciate any help. Regards. Marcela. 2011/4/4 Marcela Castro Le?n > Hello > I'm having problem using migration. I'm working on ubuntu 10.4 and this > versions of libvirt and virsh: > virsh # version > Compiled against library: libvir 0.7.5 > Using library: libvir 0.7.5 > Using API: QEMU 0.7.5 > Running hypervisor: QEMU 0.12.3 > > This is the error. > *virsh # migrate scompi1 qemu+ssh://rionegro/system > error: Unknown failure > * > > This is the log on the destination, that show that there is no > communication problem, but it has a problem starting the guest on > destination. > > radic at rionegro:~$ sudo cat /var/log/libvirt/qemu/scompi1.log > [sudo] password for radic: > LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin > QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 -S -M pc-0.12 -enable-kvm -m > 4096 -smp 4 -name scompi1 -uuid 355123af-b683-9fa6-ca31-10506c9ab9da > -chardev > socket,id=monitor,path=/var/lib/libvirt/qemu/scompi1.monitor,server,nowait > -monitor chardev:monitor -boot c -drive > file=/home/radic/mvdata/imagenes/scompi1.img,if=ide,index=0,boot=on,format=raw > -drive if=ide,media=cdrom,index=2,format=raw -net > nic,macaddr=52:54:00:05:d1:2a,vlan=0,model=virtio,name=virtio.0 -net > tap,fd=33,vlan=0,name=tap.0 -chardev pty,id=serial0 -serial chardev:serial0 > -parallel none -usb -vnc 127.0.0.1:0 -vga cirrus -incoming tcp: > 0.0.0.0:49153 > char device redirected to /dev/pts/1 > LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin > QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 -S -M pc-0.12 -enable-kvm -m > 4096 -smp 4 -name scompi1 -uuid 355123af-b683-9fa6-ca31-10506c9ab9da > -chardev > socket,id=monitor,path=/var/lib/libvirt/qemu/scompi1.monitor,server,nowait > -monitor chardev:monitor -boot c -drive > file=/home/radic/mvdata/imagenes/scompi1.img,if=ide,index=0,boot=on,format=raw > -drive if=ide,media=cdrom,index=2,format=raw -net > nic,macaddr=52:54:00:05:d1:2a,vlan=0,model=virtio,name=virtio.0 -net > tap,fd=33,vlan=0,name=tap.0 -chardev pty,id=serial0 -serial chardev:serial0 > -parallel none -usb -vnc 127.0.0.1:0 -vga cirrus -incoming tcp: > 0.0.0.0:49154 > char device redirected to /dev/pts/2 > LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin > QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 -S -M pc-0.12 -enable-kvm -m > 4096 -smp 4 -name scompi1 -uuid 355123af-b683-9fa6-ca31-10506c9ab9da > -chardev > socket,id=monitor,path=/var/lib/libvirt/qemu/scompi1.monitor,server,nowait > -monitor chardev:monitor -boot c -drive > file=/home/radic/mvdata/imagenes/scompi1.img,if=ide,index=0,boot=on,format=raw > -drive if=ide,media=cdrom,index=2,format=raw -net > nic,macaddr=52:54:00:05:d1:2a,vlan=0,model=virtio,name=virtio.0 -net > tap,fd=33,vlan=0,name=tap.0 -chardev pty,id=serial0 -serial chardev:serial0 > -parallel none -usb -vnc 127.0.0.1:0 -vga cirrus -incoming tcp: > 0.0.0.0:49155 > char device redirected to /dev/pts/2 > > I'm attaching the xml of the scompi1 that i'm trying to migrate. > I'd apprciate a lot any help. > Marcela > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: mig_rionegro-1.log Type: text/x-log Size: 6071 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: mig_chubut-1.log Type: text/x-log Size: 6071 bytes Desc: not available URL: From berrange at redhat.com Tue Apr 5 15:03:07 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 5 Apr 2011 16:03:07 +0100 Subject: [libvirt] [PATCH 1/3] Don't use virSetCloseExec in event loop on Win32 Message-ID: <1302015789-488-1-git-send-email-berrange@redhat.com> The virSetCloseExec API returns -1 on Win32 since it cannot possibly work. Avoid calling it from the event loop since is not required in this case. * src/util/event_poll.c: Remove virSetCloseExec --- src/util/event_poll.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/util/event_poll.c b/src/util/event_poll.c index 91000e2..90788a4 100644 --- a/src/util/event_poll.c +++ b/src/util/event_poll.c @@ -658,10 +658,12 @@ int virEventPollInit(void) } if (pipe(eventLoop.wakeupfd) < 0 || - virSetNonBlock(eventLoop.wakeupfd[0]) < 0 || - virSetNonBlock(eventLoop.wakeupfd[1]) < 0 || +#ifndef WIN32 virSetCloseExec(eventLoop.wakeupfd[0]) < 0 || - virSetCloseExec(eventLoop.wakeupfd[1]) < 0) { + virSetCloseExec(eventLoop.wakeupfd[1]) < 0 || +#endif + virSetNonBlock(eventLoop.wakeupfd[0]) < 0 || + virSetNonBlock(eventLoop.wakeupfd[1]) < 0) { virReportSystemError(errno, "%s", _("Unable to setup wakeup pipe")); return -1; -- 1.7.4 From berrange at redhat.com Tue Apr 5 15:03:08 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 5 Apr 2011 16:03:08 +0100 Subject: [libvirt] [PATCH 2/3] Avoid compiler warnings about int -> void * casts In-Reply-To: <1302015789-488-1-git-send-email-berrange@redhat.com> References: <1302015789-488-1-git-send-email-berrange@redhat.com> Message-ID: <1302015789-488-2-git-send-email-berrange@redhat.com> GCC is a little confused about the cast of beginthread/beginthreadex from unsigned long -> void *. Go via an intermediate variable avoids the bogus warning, and makes the code a little cleaner * src/util/threads-win32.c: Avoid compiler warning in cast --- src/util/threads-win32.c | 18 +++++++++++------- 1 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/util/threads-win32.c b/src/util/threads-win32.c index ddb4737..5661437 100644 --- a/src/util/threads-win32.c +++ b/src/util/threads-win32.c @@ -262,6 +262,7 @@ int virThreadCreate(virThreadPtr thread, void *opaque) { struct virThreadArgs *args; + uintptr_t ret; if (VIR_ALLOC(args) < 0) return -1; @@ -271,17 +272,20 @@ int virThreadCreate(virThreadPtr thread, thread->joinable = joinable; if (joinable) { - thread->thread = (HANDLE)_beginthreadex(NULL, 0, - virThreadHelperJoinable, - args, 0, NULL); - if (thread->thread == 0) + ret = _beginthreadex(NULL, 0, + virThreadHelperJoinable, + args, 0, NULL); + if (ret == 0) return -1; } else { - thread->thread = (HANDLE)_beginthread(virThreadHelperDaemon, - 0, args); - if (thread->thread == (HANDLE)-1L) + ret = _beginthread(virThreadHelperDaemon, + 0, args); + if (ret == -1L) return -1; } + + thread->thread = (HANDLE)ret; + return 0; } -- 1.7.4 From berrange at redhat.com Tue Apr 5 15:03:09 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 5 Apr 2011 16:03:09 +0100 Subject: [libvirt] [PATCH 3/3] Don't try to enable stack protector on Win32 In-Reply-To: <1302015789-488-1-git-send-email-berrange@redhat.com> References: <1302015789-488-1-git-send-email-berrange@redhat.com> Message-ID: <1302015789-488-3-git-send-email-berrange@redhat.com> The GCC Win32 compiler will claim to support -fstack-protector, but if it actually gets triggered by a suitable code pattern, linking will fail. Other non-Linux OS likely suffer the same way with gcc. * m4/virt-compile-warnings.m4: Only use stack protector when the build target is Linux. --- m4/virt-compile-warnings.m4 | 16 +++++++++++----- 1 files changed, 11 insertions(+), 5 deletions(-) diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4 index 7e252d5..819da8f 100644 --- a/m4/virt-compile-warnings.m4 +++ b/m4/virt-compile-warnings.m4 @@ -98,11 +98,17 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ # Extra special flags gl_WARN_ADD([-Wp,-D_FORTIFY_SOURCE=2]) - dnl Fedora only uses -fstack-protector, but doesn't seem to - dnl be great overhead in adding -fstack-protector-all instead - dnl gl_WARN_ADD([-fstack-protector]) - gl_WARN_ADD([-fstack-protector-all]) - gl_WARN_ADD([--param=ssp-buffer-size=4]) + dnl -fstack-protector stuff passes gl_WARN_ADD with gcc + dnl on Mingw32, but fails when actually used + case $host in + *-*-linux*) + dnl Fedora only uses -fstack-protector, but doesn't seem to + dnl be great overhead in adding -fstack-protector-all instead + dnl gl_WARN_ADD([-fstack-protector]) + gl_WARN_ADD([-fstack-protector-all]) + gl_WARN_ADD([--param=ssp-buffer-size=4]) + ;; + esac gl_WARN_ADD([-fexceptions]) gl_WARN_ADD([-fasynchronous-unwind-tables]) gl_WARN_ADD([-fdiagnostics-show-option]) -- 1.7.4 From minovotn at redhat.com Tue Apr 5 15:09:46 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 05 Apr 2011 17:09:46 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> Message-ID: <4D9B30BA.6090906@redhat.com> Hi Marcela, I was investigating the log file and it seems like the image file cannot be opened on the remote host. According to the lost you're doing the restore on the host named rionegro so not the localhost. This seems like the saved guest image is not accessible from the rionegro system. Could you please try to connect to rionegro system using SSH and then connect to the default system hypervisor using: # virsh restore with no specification of remote system to connect to the default hypervisor (default is qemu:///system under root account). Also, what may be causing issues is the colon character (':') AFAIK so try renaming the image from sv-chubut-2011-04-04-17:38 to some other name without spaces and colon characters, e.g. to sv-chubut-2011-04-04-17-38 and try to restore this way. Since according to the code it's about opening file error I guess the remote system is not having access to the file. Michal On 04/05/2011 04:54 PM, Marcela Castro Le?n wrote: > Hello > This is the log I got doing the restore. It's says that it coun't get > the image, but the image is ok, because I can startup the guest. > Neither I can migrate the guest, so I suppose I've a problem in my > configuration. > Thank you very much in advance. > Marcela. > > 2011/4/5 Michal Novotny > > > Hi Marcela, > is any other guest on the host that cannot restore this VM working > fine ? > > You could also try running the: > > */# LIBVIRT_DEBUG=1 virsh restore sv-chubut-2011-04-04-17:38 2> > virsh-restore.log > > /*command which would enable the libvirt logging and output the debug > log into the virsh-restore.log file. This file could be sent to > the list > for analysis what's wrong. > > Thanks, > Michal > > On 04/05/2011 11:57 AM, Marcela Castro Le?n wrote: > > Hello Daniel > > Thank you for all your information, but I still didn't solve the > > problem. I tried the option you mention, with two differents guest > > into two differents host, but all the cases I've got: > > > > */virsh # restore sv-chubut-2011-04-04-17:38/* > > */error: Failed to restore domain from sv-chubut-2011-04-04-17:38/* > > */error: monitor socket did not show up.: Connection refused/* > > > > I cannot get any useful information (at least form me) on the > log you > > mention. > > I'd appreciate a lot a new suggestion. > > Thanks > > Marcela > > > > > > > > > > 2011/4/4 Daniel P. Berrange > > >> > > > > On Sun, Apr 03, 2011 at 10:43:45AM +0200, Marcela Castro > Le?n wrote: > > > Hello: > > > I need to know if I can use the restore operation (virsh o the > > equivalent in > > > libvirt) to recover a previous state of a guest, but recovered > > previously in > > > another host. > > > I did a test, but I got an error: > > > > > > The exactly sequence using virsh I testes is: > > > On [HOST SOURCE]: Using virsh > > > 1) save [domain] [file] > > > 2) restore file > > > 3) destroy [domain] > > > > > > On [HOST SOURCE] using ubuntu sh > > > 4) cp [guest.img] [guest.xml] [file] to HOST2 > > > > > > On [HOST TARGET] using virsh > > > 5) define [guest.xml] (using image on destination in HOST2) > > > 6) restore [file] > > > > As a general rule you should only ever 'restore' from a > > file *once*. This is because after the first restore > > operation, the guest may have made writes to its disk. > > Restoring a second time the guest OS will likely have > > an inconsistent view of the disk & will cause filesystem > > corruption. > > > > If you want to be able to restore from a saved image > > multiple times, you need to also take a snapshot of > > the disk image at the same time, and restore that > > snapshot when restoring the memory image. > > > > > > That aside, saving on one host & restoring on a > > different host is fine. So if you leave out steps > > 2+3 in your example above, then your data would > > still be safe. > > > > > The restore troughs the following message: > > > *virsh # restore sv-chubut-2011-04-01-09:58 > > > error: Failed to restore domain from > sv-chubut-2011-04-01-09:58 > > > error: monitor socket did not show up.: Connection refused* > > > > There is probably some configuration difference on your 2nd host > > that prevented the VM from starting up. If you're lucky the file > > /var/log/libvirt/qemu/$NAME.log will tell you more > > > > Daniel > > -- > > |: http://berrange.com -o- > > http://www.flickr.com/photos/dberrange/ :| > > |: http://libvirt.org -o- > > http://virt-manager.org :| > > |: http://autobuild.org -o- > > http://search.cpan.org/~danberr/ > > > :| > > |: http://entangle-photo.org -o- > > http://live.gnome.org/gtk-vnc :| > > > > > > > > -- > > libvir-list mailing list > > libvir-list at redhat.com > > https://www.redhat.com/mailman/listinfo/libvir-list > > > -- > Michal Novotny >, > RHCE > Virtualization Team (xen userspace), Red Hat > > -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From eblake at redhat.com Tue Apr 5 15:15:57 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 09:15:57 -0600 Subject: [libvirt] Using Restore in another host. In-Reply-To: <4D9B30BA.6090906@redhat.com> References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> Message-ID: <4D9B322D.9040309@redhat.com> On 04/05/2011 09:09 AM, Michal Novotny wrote: > Hi Marcela, > I was investigating the log file and it seems like the image file cannot > be opened on the remote host. Are you using SELinux, and is your shared storage on NFS? If so, did you run 'setsebool -P virt_use_nfs on' to let the destination properly access the shared storage from NFS? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From minovotn at redhat.com Tue Apr 5 15:17:28 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 05 Apr 2011 17:17:28 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: <4D9B322D.9040309@redhat.com> References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B322D.9040309@redhat.com> Message-ID: <4D9B3288.6080700@redhat.com> On 04/05/2011 05:15 PM, Eric Blake wrote: > On 04/05/2011 09:09 AM, Michal Novotny wrote: >> Hi Marcela, >> I was investigating the log file and it seems like the image file cannot >> be opened on the remote host. > Are you using SELinux, and is your shared storage on NFS? If so, did > you run 'setsebool -P virt_use_nfs on' to let the destination properly > access the shared storage from NFS? > Eric, I'm not too familiar with SELinux. Do you think the virFileOpenAs() would fail if the SELinux context won't be set properly? Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From eblake at redhat.com Tue Apr 5 15:19:30 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 09:19:30 -0600 Subject: [libvirt] [PATCH] qemu: Always reserves slot 0x02 for primary VGA. In-Reply-To: <1302011398-25541-1-git-send-email-jyang@redhat.com> References: <1302011398-25541-1-git-send-email-jyang@redhat.com> Message-ID: <4D9B3302.5010307@redhat.com> On 04/05/2011 07:49 AM, Osier Yang wrote: > To address https://bugzilla.redhat.com/show_bug.cgi?id=692355 > > This fix is to reserve slot 0x02 for primary VGA even if there > is no "video" specified in domain XML to avoid the problem. > --- > src/qemu/qemu_command.c | 13 ++++++++++--- > 1 files changed, 10 insertions(+), 3 deletions(-) ACK. I think that this is the correct patch, given the earlier comments on the same topic in https://www.redhat.com/archives/libvir-list/2011-March/msg01296.html -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From berrange at redhat.com Tue Apr 5 15:19:28 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 5 Apr 2011 16:19:28 +0100 Subject: [libvirt] [PATCH] Fix typo in systemtap tapset directrory name Message-ID: <1302016768-18964-1-git-send-email-berrange@redhat.com> The systemtap directory for tapsets is called /usr/share/systemtap/tapset Not /usr/share/systemtap/tapsets * daemon/Makefile.am,libvirt.spec.in: s/tapsets/tapset/ --- daemon/Makefile.am | 2 +- libvirt.spec.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 0fde04c..cacec1c 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -165,7 +165,7 @@ nodist_libvirtd_SOURCES = probes.h BUILT_SOURCES += probes.h -tapsetdir = $(datadir)/systemtap/tapsets +tapsetdir = $(datadir)/systemtap/tapset tapset_DATA = libvirtd.stp probes.h: probes.d diff --git a/libvirt.spec.in b/libvirt.spec.in index 724b9b7..4162fba 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -898,7 +898,7 @@ fi %config(noreplace) %{_sysconfdir}/sysconfig/libvirtd %config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf %if %{with_dtrace} -%{_datadir}/systemtap/tapsets/libvirtd.stp +%{_datadir}/systemtap/tapset/libvirtd.stp %endif %dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/qemu/ %dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/lxc/ -- 1.7.4 From mcastrol at gmail.com Tue Apr 5 15:20:31 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Tue, 5 Apr 2011 17:20:31 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: <4D9B30BA.6090906@redhat.com> References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> Message-ID: Hello OK, this is the new log. Now, the old error appeared again... *error: Failed to restore domain from XX error: monitor socket did not show up.: Connection refused * Regards. 2011/4/5 Michal Novotny > Hi Marcela, > I was investigating the log file and it seems like the image file cannot > be opened on the remote host. > > According to the lost you're doing the restore on the host named > rionegro so not the localhost. This seems like the saved guest image is > not accessible from the rionegro system. Could you please try to connect > to rionegro system using SSH and then connect to the default system > hypervisor using: > > # virsh restore > > with no specification of remote system to connect to the default > hypervisor (default is qemu:///system under root account). > > Also, what may be causing issues is the colon character (':') AFAIK so > try renaming the image from sv-chubut-2011-04-04-17:38 to some other > name without spaces and colon characters, e.g. to > sv-chubut-2011-04-04-17-38 and try to restore this way. > > Since according to the code it's about opening file error I guess the > remote system is not having access to the file. > > Michal > > On 04/05/2011 04:54 PM, Marcela Castro Le?n wrote: > > Hello > > This is the log I got doing the restore. It's says that it coun't get > > the image, but the image is ok, because I can startup the guest. > > Neither I can migrate the guest, so I suppose I've a problem in my > > configuration. > > Thank you very much in advance. > > Marcela. > > > > 2011/4/5 Michal Novotny >> > > > > Hi Marcela, > > is any other guest on the host that cannot restore this VM working > > fine ? > > > > You could also try running the: > > > > */# LIBVIRT_DEBUG=1 virsh restore sv-chubut-2011-04-04-17:38 2> > > virsh-restore.log > > > > /*command which would enable the libvirt logging and output the debug > > log into the virsh-restore.log file. This file could be sent to > > the list > > for analysis what's wrong. > > > > Thanks, > > Michal > > > > On 04/05/2011 11:57 AM, Marcela Castro Le?n wrote: > > > Hello Daniel > > > Thank you for all your information, but I still didn't solve the > > > problem. I tried the option you mention, with two differents guest > > > into two differents host, but all the cases I've got: > > > > > > */virsh # restore sv-chubut-2011-04-04-17:38/* > > > */error: Failed to restore domain from sv-chubut-2011-04-04-17:38/* > > > */error: monitor socket did not show up.: Connection refused/* > > > > > > I cannot get any useful information (at least form me) on the > > log you > > > mention. > > > I'd appreciate a lot a new suggestion. > > > Thanks > > > Marcela > > > > > > > > > > > > > > > 2011/4/4 Daniel P. Berrange > > > > >> > > > > > > On Sun, Apr 03, 2011 at 10:43:45AM +0200, Marcela Castro > > Le?n wrote: > > > > Hello: > > > > I need to know if I can use the restore operation (virsh o > the > > > equivalent in > > > > libvirt) to recover a previous state of a guest, but > recovered > > > previously in > > > > another host. > > > > I did a test, but I got an error: > > > > > > > > The exactly sequence using virsh I testes is: > > > > On [HOST SOURCE]: Using virsh > > > > 1) save [domain] [file] > > > > 2) restore file > > > > 3) destroy [domain] > > > > > > > > On [HOST SOURCE] using ubuntu sh > > > > 4) cp [guest.img] [guest.xml] [file] to HOST2 > > > > > > > > On [HOST TARGET] using virsh > > > > 5) define [guest.xml] (using image on destination in HOST2) > > > > 6) restore [file] > > > > > > As a general rule you should only ever 'restore' from a > > > file *once*. This is because after the first restore > > > operation, the guest may have made writes to its disk. > > > Restoring a second time the guest OS will likely have > > > an inconsistent view of the disk & will cause filesystem > > > corruption. > > > > > > If you want to be able to restore from a saved image > > > multiple times, you need to also take a snapshot of > > > the disk image at the same time, and restore that > > > snapshot when restoring the memory image. > > > > > > > > > That aside, saving on one host & restoring on a > > > different host is fine. So if you leave out steps > > > 2+3 in your example above, then your data would > > > still be safe. > > > > > > > The restore troughs the following message: > > > > *virsh # restore sv-chubut-2011-04-01-09:58 > > > > error: Failed to restore domain from > > sv-chubut-2011-04-01-09:58 > > > > error: monitor socket did not show up.: Connection refused* > > > > > > There is probably some configuration difference on your 2nd > host > > > that prevented the VM from starting up. If you're lucky the > file > > > /var/log/libvirt/qemu/$NAME.log will tell you more > > > > > > Daniel > > > -- > > > |: http://berrange.com -o- > > > http://www.flickr.com/photos/dberrange/ :| > > > |: http://libvirt.org -o- > > > http://virt-manager.org :| > > > |: http://autobuild.org -o- > > > http://search.cpan.org/~danberr/ > > > > > :| > > > |: http://entangle-photo.org -o- > > > http://live.gnome.org/gtk-vnc :| > > > > > > > > > > > > -- > > > libvir-list mailing list > > > libvir-list at redhat.com > > > https://www.redhat.com/mailman/listinfo/libvir-list > > > > > > -- > > Michal Novotny >, > > RHCE > > Virtualization Team (xen userspace), Red Hat > > > > > > > -- > Michal Novotny , RHCE > Virtualization Team (xen userspace), Red Hat > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- radic at rionegro:~/discoguest/mvdata/imagenes$ virsh 17:16:32.636: debug : virInitialize:336 : register drivers 17:16:32.636: debug : virRegisterDriver:837 : registering Test as driver 0 17:16:32.636: debug : virRegisterNetworkDriver:675 : registering Test as network driver 0 17:16:32.636: debug : virRegisterInterfaceDriver:706 : registering Test as interface driver 0 17:16:32.636: debug : virRegisterStorageDriver:737 : registering Test as storage driver 0 17:16:32.636: debug : virRegisterDeviceMonitor:768 : registering Test as device driver 0 17:16:32.636: debug : virRegisterSecretDriver:799 : registering Test as secret driver 0 17:16:32.637: debug : virRegisterDriver:837 : registering Xen as driver 1 17:16:32.637: debug : virRegisterDriver:837 : registering OPENVZ as driver 2 17:16:32.637: debug : vboxRegister:109 : VBoxCGlueInit failed, using dummy driver 17:16:32.637: debug : virRegisterDriver:837 : registering VBOX as driver 3 17:16:32.637: debug : virRegisterNetworkDriver:675 : registering VBOX as network driver 1 17:16:32.637: debug : virRegisterStorageDriver:737 : registering VBOX as storage driver 1 17:16:32.637: debug : virRegisterDriver:837 : registering remote as driver 4 17:16:32.637: debug : virRegisterNetworkDriver:675 : registering remote as network driver 2 17:16:32.637: debug : virRegisterInterfaceDriver:706 : registering remote as interface driver 1 17:16:32.637: debug : virRegisterStorageDriver:737 : registering remote as storage driver 2 17:16:32.637: debug : virRegisterDeviceMonitor:768 : registering remote as device driver 1 17:16:32.637: debug : virRegisterSecretDriver:799 : registering remote as secret driver 1 17:16:32.637: debug : virConnectOpenAuth:1337 : name=qemu:///system, auth=0x7ffcdc643b80, flags=0 17:16:32.637: debug : do_open:1106 : name "qemu:///system" to URI components: scheme qemu opaque (null) authority (null) server (null) user (null) port 0 path /system 17:16:32.637: debug : do_open:1116 : trying driver 0 (Test) ... 17:16:32.637: debug : do_open:1122 : driver 0 Test returned DECLINED 17:16:32.637: debug : do_open:1116 : trying driver 1 (Xen) ... 17:16:32.637: debug : do_open:1122 : driver 1 Xen returned DECLINED 17:16:32.637: debug : do_open:1116 : trying driver 2 (OPENVZ) ... 17:16:32.637: debug : do_open:1122 : driver 2 OPENVZ returned DECLINED 17:16:32.637: debug : do_open:1116 : trying driver 3 (VBOX) ... 17:16:32.637: debug : do_open:1122 : driver 3 VBOX returned DECLINED 17:16:32.637: debug : do_open:1116 : trying driver 4 (remote) ... 17:16:32.637: debug : doRemoteOpen:564 : proceeding with name = qemu:///system 17:16:32.637: debug : remoteIO:8455 : Do proc=66 serial=0 length=28 wait=(nil) 17:16:32.637: debug : remoteIO:8517 : We have the buck 66 0x7ffcdc896010 0x7ffcdc896010 17:16:32.638: debug : remoteIODecodeMessageLength:7939 : Got length, now need 64 total (60 more) 17:16:32.638: debug : remoteIOEventLoop:8381 : Giving up the buck 66 0x7ffcdc896010 (nil) 17:16:32.638: debug : remoteIO:8548 : All done with our call 66 (nil) 0x7ffcdc896010 17:16:32.638: debug : remoteIO:8455 : Do proc=1 serial=1 length=56 wait=(nil) 17:16:32.638: debug : remoteIO:8517 : We have the buck 1 0x10798e0 0x10798e0 17:16:32.638: debug : remoteIODecodeMessageLength:7939 : Got length, now need 56 total (52 more) 17:16:32.638: debug : remoteIOEventLoop:8381 : Giving up the buck 1 0x10798e0 (nil) 17:16:32.638: debug : remoteIO:8548 : All done with our call 1 (nil) 0x10798e0 17:16:32.638: debug : doRemoteOpen:917 : Adding Handler for remote events 17:16:32.638: debug : doRemoteOpen:924 : virEventAddHandle failed: No addHandleImpl defined. continuing without events. 17:16:32.638: debug : do_open:1122 : driver 4 remote returned SUCCESS 17:16:32.638: debug : do_open:1142 : network driver 0 Test returned DECLINED 17:16:32.638: debug : do_open:1142 : network driver 1 VBOX returned DECLINED 17:16:32.638: debug : do_open:1142 : network driver 2 remote returned SUCCESS 17:16:32.638: debug : do_open:1161 : interface driver 0 Test returned DECLINED 17:16:32.638: debug : do_open:1161 : interface driver 1 remote returned SUCCESS 17:16:32.638: debug : do_open:1181 : storage driver 0 Test returned DECLINED 17:16:32.638: debug : do_open:1181 : storage driver 1 VBOX returned DECLINED 17:16:32.638: debug : do_open:1181 : storage driver 2 remote returned SUCCESS 17:16:32.638: debug : do_open:1201 : node driver 0 Test returned DECLINED 17:16:32.638: debug : do_open:1201 : node driver 1 remote returned SUCCESS 17:16:32.638: debug : do_open:1228 : secret driver 0 Test returned DECLINED 17:16:32.638: debug : do_open:1228 : secret driver 1 remote returned SUCCESS Welcome to virsh, the virtualization interactive terminal. Type: 'help' for help with commands 'quit' to quit virsh # restore XX 17:16:36.271: debug : virDomainRestore:2283 : conn=0x1074070, from=XX 17:16:36.271: debug : remoteIO:8455 : Do proc=54 serial=2 length=76 wait=(nil) 17:16:36.271: debug : remoteIO:8517 : We have the buck 54 0x1094fc0 0x1094fc0 17:17:06.724: debug : remoteIODecodeMessageLength:7939 : Got length, now need 192 total (188 more) 17:17:06.724: debug : remoteIOEventLoop:8381 : Giving up the buck 54 0x1094fc0 (nil) 17:17:06.724: debug : remoteIO:8548 : All done with our call 54 (nil) 0x1094fc0 error: Failed to restore domain from XX error: monitor socket did not show up.: Connection refused virsh # From minovotn at redhat.com Tue Apr 5 15:22:08 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 05 Apr 2011 17:22:08 +0200 Subject: [libvirt] LIBVIRT migration In-Reply-To: References: <20110401142611.GK29510@redhat.com> Message-ID: <4D9B33A0.5010903@redhat.com> [snip] Are you sure the domain name is OK for the case of this attempt where you got the log files ? error: failed to get domain 'scmpich1' error: Domain not found: no domain with matching name 'scmpich1' This seems like the domain doesn't exist neither on source nor on target system. Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From mcastrol at gmail.com Tue Apr 5 15:25:08 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Tue, 5 Apr 2011 17:25:08 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: <4D9B322D.9040309@redhat.com> References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B322D.9040309@redhat.com> Message-ID: Hello I don't do this, I'd find out about it and set it. But, i don't know if this avoid the error, but I'm trying to restore the image from the host that is nfs server. I will execute, try again and tell you if I succeed. Thank you. Marcela 2011/4/5 Eric Blake > On 04/05/2011 09:09 AM, Michal Novotny wrote: > > Hi Marcela, > > I was investigating the log file and it seems like the image file cannot > > be opened on the remote host. > > Are you using SELinux, and is your shared storage on NFS? If so, did > you run 'setsebool -P virt_use_nfs on' to let the destination properly > access the shared storage from NFS? > > -- > Eric Blake eblake at redhat.com +1-801-349-2682 > Libvirt virtualization library http://libvirt.org > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From eblake at redhat.com Tue Apr 5 15:28:00 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 09:28:00 -0600 Subject: [libvirt] [PATCH] qemu: Support for overriding NPROC limit In-Reply-To: References: Message-ID: <4D9B3500.4080302@redhat.com> On 04/05/2011 08:09 AM, Jiri Denemark wrote: > This patch adds max_processes option to qemu.conf which can be used to > override system default limit on number of processes that are allowed to > be running for qemu user. > --- > src/qemu/libvirtd_qemu.aug | 3 +++ > src/qemu/qemu.conf | 7 +++++++ > src/qemu/qemu_conf.c | 4 ++++ > src/qemu/qemu_conf.h | 2 ++ > src/qemu/qemu_process.c | 24 ++++++++++++++++++++++++ > src/qemu/test_libvirtd_qemu.aug | 4 ++++ > 6 files changed, 44 insertions(+), 0 deletions(-) > @@ -1821,6 +1842,9 @@ static int qemuProcessHook(void *data) > { > struct qemuProcessHookData *h = data; > > + if (qemuProcessLimits(h->driver) < 0) > + return -1; Which UID is in effect at this point? While setrlimit() adjusts an inherited value, I'm a bit worried that tracks different limits per uid, and if the call is made while the real uid is root instead of qemu, then we might be affecting the wrong limit. Does this call need to be delayed until after the virSecurityManagerSetProcessLabel, or after we are sure that we have changed identities? But other than that question, the code looks sane, and I appreciate seeing the augeas modifications, too. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From minovotn at redhat.com Tue Apr 5 15:28:58 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 05 Apr 2011 17:28:58 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> Message-ID: <4D9B353A.9080800@redhat.com> Hi, what about /var/log/libvirt/qemu/$NAME.log file from the attempt? This seems like the monitor socket cannot be connected which may be the result of different version of QEMU on source and target system IMHO. Could you please provide result of # virsh version command from both source and target machine and most likely install both source and target machine? Thanks, Michal On 04/05/2011 05:20 PM, Marcela Castro Le?n wrote: > Hello > OK, this is the new log. Now, the old error appeared again... > /*error: Failed to restore domain from XX > error: monitor socket did not show up.: Connection refused > */ > > Regards. > > 2011/4/5 Michal Novotny > > > Hi Marcela, > I was investigating the log file and it seems like the image file > cannot > be opened on the remote host. > > According to the lost you're doing the restore on the host named > rionegro so not the localhost. This seems like the saved guest > image is > not accessible from the rionegro system. Could you please try to > connect > to rionegro system using SSH and then connect to the default system > hypervisor using: > > # virsh restore > > with no specification of remote system to connect to the default > hypervisor (default is qemu:///system under root account). > > Also, what may be causing issues is the colon character (':') AFAIK so > try renaming the image from sv-chubut-2011-04-04-17:38 to some other > name without spaces and colon characters, e.g. to > sv-chubut-2011-04-04-17-38 and try to restore this way. > > Since according to the code it's about opening file error I guess the > remote system is not having access to the file. > > Michal > > On 04/05/2011 04:54 PM, Marcela Castro Le?n wrote: > > Hello > > This is the log I got doing the restore. It's says that it > coun't get > > the image, but the image is ok, because I can startup the guest. > > Neither I can migrate the guest, so I suppose I've a problem in my > > configuration. > > Thank you very much in advance. > > Marcela. > > > > 2011/4/5 Michal Novotny >> > > > > Hi Marcela, > > is any other guest on the host that cannot restore this VM > working > > fine ? > > > > You could also try running the: > > > > */# LIBVIRT_DEBUG=1 virsh restore sv-chubut-2011-04-04-17:38 2> > > virsh-restore.log > > > > /*command which would enable the libvirt logging and output > the debug > > log into the virsh-restore.log file. This file could be sent to > > the list > > for analysis what's wrong. > > > > Thanks, > > Michal > > > > On 04/05/2011 11:57 AM, Marcela Castro Le?n wrote: > > > Hello Daniel > > > Thank you for all your information, but I still didn't > solve the > > > problem. I tried the option you mention, with two > differents guest > > > into two differents host, but all the cases I've got: > > > > > > */virsh # restore sv-chubut-2011-04-04-17:38/* > > > */error: Failed to restore domain from > sv-chubut-2011-04-04-17:38/* > > > */error: monitor socket did not show up.: Connection refused/* > > > > > > I cannot get any useful information (at least form me) on the > > log you > > > mention. > > > I'd appreciate a lot a new suggestion. > > > Thanks > > > Marcela > > > > > > > > > > > > > > > 2011/4/4 Daniel P. Berrange > > > > > > > >>> > > > > > > On Sun, Apr 03, 2011 at 10:43:45AM +0200, Marcela Castro > > Le?n wrote: > > > > Hello: > > > > I need to know if I can use the restore operation > (virsh o the > > > equivalent in > > > > libvirt) to recover a previous state of a guest, but > recovered > > > previously in > > > > another host. > > > > I did a test, but I got an error: > > > > > > > > The exactly sequence using virsh I testes is: > > > > On [HOST SOURCE]: Using virsh > > > > 1) save [domain] [file] > > > > 2) restore file > > > > 3) destroy [domain] > > > > > > > > On [HOST SOURCE] using ubuntu sh > > > > 4) cp [guest.img] [guest.xml] [file] to HOST2 > > > > > > > > On [HOST TARGET] using virsh > > > > 5) define [guest.xml] (using image on destination in > HOST2) > > > > 6) restore [file] > > > > > > As a general rule you should only ever 'restore' from a > > > file *once*. This is because after the first restore > > > operation, the guest may have made writes to its disk. > > > Restoring a second time the guest OS will likely have > > > an inconsistent view of the disk & will cause filesystem > > > corruption. > > > > > > If you want to be able to restore from a saved image > > > multiple times, you need to also take a snapshot of > > > the disk image at the same time, and restore that > > > snapshot when restoring the memory image. > > > > > > > > > That aside, saving on one host & restoring on a > > > different host is fine. So if you leave out steps > > > 2+3 in your example above, then your data would > > > still be safe. > > > > > > > The restore troughs the following message: > > > > *virsh # restore sv-chubut-2011-04-01-09:58 > > > > error: Failed to restore domain from > > sv-chubut-2011-04-01-09:58 > > > > error: monitor socket did not show up.: Connection > refused* > > > > > > There is probably some configuration difference on > your 2nd host > > > that prevented the VM from starting up. If you're > lucky the file > > > /var/log/libvirt/qemu/$NAME.log will tell you more > > > > > > Daniel > > > -- > > > |: http://berrange.com -o- > > > http://www.flickr.com/photos/dberrange/ :| > > > |: http://libvirt.org -o- > > > http://virt-manager.org :| > > > |: http://autobuild.org -o- > > > http://search.cpan.org/~danberr/ > > > > > > :| > > > |: http://entangle-photo.org -o- > > > http://live.gnome.org/gtk-vnc :| > > > > > > > > > > > > -- > > > libvir-list mailing list > > > libvir-list at redhat.com > > > > > https://www.redhat.com/mailman/listinfo/libvir-list > > > > > > -- > > Michal Novotny >>, > > RHCE > > Virtualization Team (xen userspace), Red Hat > > > > > > > -- > Michal Novotny >, > RHCE > Virtualization Team (xen userspace), Red Hat > > -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From eblake at redhat.com Tue Apr 5 15:31:17 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 09:31:17 -0600 Subject: [libvirt] [PATCH 1/3] Don't use virSetCloseExec in event loop on Win32 In-Reply-To: <1302015789-488-1-git-send-email-berrange@redhat.com> References: <1302015789-488-1-git-send-email-berrange@redhat.com> Message-ID: <4D9B35C5.7050908@redhat.com> On 04/05/2011 09:03 AM, Daniel P. Berrange wrote: > The virSetCloseExec API returns -1 on Win32 since it cannot > possibly work. Avoid calling it from the event loop since > is not required in this case. Well, it _could_ work if gnulib would relax a couple modules to LGPLv2+ instead of their current LGPLv3+. Meanwhile, mingw _does_ let us create a pipe already non-inheritible (that is, pipe2(fds, O_CLOEXEC) _does_ work on mingw as an LGPLv2+ gnulib solution). If you don't mind, I'd rather conditionally NAK this patch and try the pipe2 approach instead, since the added in-function #ifdefs detract from readability. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Tue Apr 5 15:32:22 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 09:32:22 -0600 Subject: [libvirt] [PATCH 2/3] Avoid compiler warnings about int -> void * casts In-Reply-To: <1302015789-488-2-git-send-email-berrange@redhat.com> References: <1302015789-488-1-git-send-email-berrange@redhat.com> <1302015789-488-2-git-send-email-berrange@redhat.com> Message-ID: <4D9B3606.4000701@redhat.com> On 04/05/2011 09:03 AM, Daniel P. Berrange wrote: > GCC is a little confused about the cast of beginthread/beginthreadex > from unsigned long -> void *. Go via an intermediate variable avoids > the bogus warning, and makes the code a little cleaner > > * src/util/threads-win32.c: Avoid compiler warning in cast > --- > src/util/threads-win32.c | 18 +++++++++++------- > 1 files changed, 11 insertions(+), 7 deletions(-) ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Tue Apr 5 15:33:05 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 09:33:05 -0600 Subject: [libvirt] [PATCH 3/3] Don't try to enable stack protector on Win32 In-Reply-To: <1302015789-488-3-git-send-email-berrange@redhat.com> References: <1302015789-488-1-git-send-email-berrange@redhat.com> <1302015789-488-3-git-send-email-berrange@redhat.com> Message-ID: <4D9B3631.8030902@redhat.com> On 04/05/2011 09:03 AM, Daniel P. Berrange wrote: > The GCC Win32 compiler will claim to support -fstack-protector, > but if it actually gets triggered by a suitable code pattern, > linking will fail. Other non-Linux OS likely suffer the same > way with gcc. > > * m4/virt-compile-warnings.m4: Only use stack protector when > the build target is Linux. > --- > m4/virt-compile-warnings.m4 | 16 +++++++++++----- > 1 files changed, 11 insertions(+), 5 deletions(-) ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Tue Apr 5 15:33:26 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 09:33:26 -0600 Subject: [libvirt] [PATCH] Fix typo in systemtap tapset directrory name In-Reply-To: <1302016768-18964-1-git-send-email-berrange@redhat.com> References: <1302016768-18964-1-git-send-email-berrange@redhat.com> Message-ID: <4D9B3646.1040905@redhat.com> On 04/05/2011 09:19 AM, Daniel P. Berrange wrote: > The systemtap directory for tapsets is called > > /usr/share/systemtap/tapset > > Not > > /usr/share/systemtap/tapsets > > * daemon/Makefile.am,libvirt.spec.in: s/tapsets/tapset/ > --- > daemon/Makefile.am | 2 +- > libvirt.spec.in | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Tue Apr 5 15:34:22 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 09:34:22 -0600 Subject: [libvirt] [PATCH] Fix typo in systemtap tapset directrory name In-Reply-To: <4D9B3646.1040905@redhat.com> References: <1302016768-18964-1-git-send-email-berrange@redhat.com> <4D9B3646.1040905@redhat.com> Message-ID: <4D9B367E.5080401@redhat.com> P.S. you might want to fix the typo in the commit title: s/directrory/directory/ On 04/05/2011 09:33 AM, Eric Blake wrote: > On 04/05/2011 09:19 AM, Daniel P. Berrange wrote: >> The systemtap directory for tapsets is called >> >> /usr/share/systemtap/tapset >> >> Not >> >> /usr/share/systemtap/tapsets >> >> * daemon/Makefile.am,libvirt.spec.in: s/tapsets/tapset/ >> --- >> daemon/Makefile.am | 2 +- >> libvirt.spec.in | 2 +- >> 2 files changed, 2 insertions(+), 2 deletions(-) > > ACK. > -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Tue Apr 5 15:42:47 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 09:42:47 -0600 Subject: [libvirt] Using Restore in another host. In-Reply-To: <4D9B3288.6080700@redhat.com> References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B322D.9040309@redhat.com> <4D9B3288.6080700@redhat.com> Message-ID: <4D9B3877.8000802@redhat.com> On 04/05/2011 09:17 AM, Michal Novotny wrote: > On 04/05/2011 05:15 PM, Eric Blake wrote: >> On 04/05/2011 09:09 AM, Michal Novotny wrote: >>> Hi Marcela, >>> I was investigating the log file and it seems like the image file cannot >>> be opened on the remote host. >> Are you using SELinux, and is your shared storage on NFS? If so, did >> you run 'setsebool -P virt_use_nfs on' to let the destination properly >> access the shared storage from NFS? >> > Eric, I'm not too familiar with SELinux. Do you think the > virFileOpenAs() would fail if the SELinux context won't be set properly? Yes, if you are running with SELinux enforcing, then it is possible for all attempts to open() to fail due to denied permissions, even with virFileOpenAs() trying different uids, if you haven't told SELinux to allow NFS images. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From mcastrol at gmail.com Tue Apr 5 15:59:32 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Tue, 5 Apr 2011 17:59:32 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: <4D9B353A.9080800@redhat.com> References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B353A.9080800@redhat.com> Message-ID: Hello The restore finished ok, I found at a log that was looking the image at an "old" location. Anyway, the image don't start well, but I've to revise all the configuration again, to see what's exactly is happening now. Thank you a lot, I learned a lot. The version are the same *source* radic at chubut:/var/log/libvirt/qemu$ virsh virsh # version Compiled against library: libvir 0.7.5 Using library: libvir 0.7.5 Using API: QEMU 0.7.5 Running hypervisor: QEMU 0.12.3 *target *radic at rionegro:~$ virsh virsh # version Compiled against library: libvir 0.7.5 Using library: libvir 0.7.5 Using API: QEMU 0.7.5 Running hypervisor: QEMU 0.12.3 Thank you very much!! Regards. 2011/4/5 Michal Novotny > Hi, > what about /var/log/libvirt/qemu/$NAME.log file from the attempt? This > seems like the monitor socket cannot be connected which may be the > result of different version of QEMU on source and target system IMHO. > Could you please provide result of > > # virsh version > > command from both source and target machine and most likely install both > source and target machine? > > Thanks, > Michal > > On 04/05/2011 05:20 PM, Marcela Castro Le?n wrote: > > Hello > > OK, this is the new log. Now, the old error appeared again... > > /*error: Failed to restore domain from XX > > error: monitor socket did not show up.: Connection refused > > */ > > > > Regards. > > > > 2011/4/5 Michal Novotny >> > > > > Hi Marcela, > > I was investigating the log file and it seems like the image file > > cannot > > be opened on the remote host. > > > > According to the lost you're doing the restore on the host named > > rionegro so not the localhost. This seems like the saved guest > > image is > > not accessible from the rionegro system. Could you please try to > > connect > > to rionegro system using SSH and then connect to the default system > > hypervisor using: > > > > # virsh restore > > > > with no specification of remote system to connect to the default > > hypervisor (default is qemu:///system under root account). > > > > Also, what may be causing issues is the colon character (':') AFAIK > so > > try renaming the image from sv-chubut-2011-04-04-17:38 to some other > > name without spaces and colon characters, e.g. to > > sv-chubut-2011-04-04-17-38 and try to restore this way. > > > > Since according to the code it's about opening file error I guess the > > remote system is not having access to the file. > > > > Michal > > > > On 04/05/2011 04:54 PM, Marcela Castro Le?n wrote: > > > Hello > > > This is the log I got doing the restore. It's says that it > > coun't get > > > the image, but the image is ok, because I can startup the guest. > > > Neither I can migrate the guest, so I suppose I've a problem in my > > > configuration. > > > Thank you very much in advance. > > > Marcela. > > > > > > 2011/4/5 Michal Novotny > > >> > > > > > > Hi Marcela, > > > is any other guest on the host that cannot restore this VM > > working > > > fine ? > > > > > > You could also try running the: > > > > > > */# LIBVIRT_DEBUG=1 virsh restore sv-chubut-2011-04-04-17:38 2> > > > virsh-restore.log > > > > > > /*command which would enable the libvirt logging and output > > the debug > > > log into the virsh-restore.log file. This file could be sent to > > > the list > > > for analysis what's wrong. > > > > > > Thanks, > > > Michal > > > > > > On 04/05/2011 11:57 AM, Marcela Castro Le?n wrote: > > > > Hello Daniel > > > > Thank you for all your information, but I still didn't > > solve the > > > > problem. I tried the option you mention, with two > > differents guest > > > > into two differents host, but all the cases I've got: > > > > > > > > */virsh # restore sv-chubut-2011-04-04-17:38/* > > > > */error: Failed to restore domain from > > sv-chubut-2011-04-04-17:38/* > > > > */error: monitor socket did not show up.: Connection > refused/* > > > > > > > > I cannot get any useful information (at least form me) on the > > > log you > > > > mention. > > > > I'd appreciate a lot a new suggestion. > > > > Thanks > > > > Marcela > > > > > > > > > > > > > > > > > > > > 2011/4/4 Daniel P. Berrange > > > > > > > > > > > >>> > > > > > > > > On Sun, Apr 03, 2011 at 10:43:45AM +0200, Marcela Castro > > > Le?n wrote: > > > > > Hello: > > > > > I need to know if I can use the restore operation > > (virsh o the > > > > equivalent in > > > > > libvirt) to recover a previous state of a guest, but > > recovered > > > > previously in > > > > > another host. > > > > > I did a test, but I got an error: > > > > > > > > > > The exactly sequence using virsh I testes is: > > > > > On [HOST SOURCE]: Using virsh > > > > > 1) save [domain] [file] > > > > > 2) restore file > > > > > 3) destroy [domain] > > > > > > > > > > On [HOST SOURCE] using ubuntu sh > > > > > 4) cp [guest.img] [guest.xml] [file] to HOST2 > > > > > > > > > > On [HOST TARGET] using virsh > > > > > 5) define [guest.xml] (using image on destination in > > HOST2) > > > > > 6) restore [file] > > > > > > > > As a general rule you should only ever 'restore' from a > > > > file *once*. This is because after the first restore > > > > operation, the guest may have made writes to its disk. > > > > Restoring a second time the guest OS will likely have > > > > an inconsistent view of the disk & will cause filesystem > > > > corruption. > > > > > > > > If you want to be able to restore from a saved image > > > > multiple times, you need to also take a snapshot of > > > > the disk image at the same time, and restore that > > > > snapshot when restoring the memory image. > > > > > > > > > > > > That aside, saving on one host & restoring on a > > > > different host is fine. So if you leave out steps > > > > 2+3 in your example above, then your data would > > > > still be safe. > > > > > > > > > The restore troughs the following message: > > > > > *virsh # restore sv-chubut-2011-04-01-09:58 > > > > > error: Failed to restore domain from > > > sv-chubut-2011-04-01-09:58 > > > > > error: monitor socket did not show up.: Connection > > refused* > > > > > > > > There is probably some configuration difference on > > your 2nd host > > > > that prevented the VM from starting up. If you're > > lucky the file > > > > /var/log/libvirt/qemu/$NAME.log will tell you more > > > > > > > > Daniel > > > > -- > > > > |: http://berrange.com -o- > > > > http://www.flickr.com/photos/dberrange/ :| > > > > |: http://libvirt.org -o- > > > > http://virt-manager.org :| > > > > |: http://autobuild.org -o- > > > > http://search.cpan.org/~danberr/ > > > > > > > > > :| > > > > |: http://entangle-photo.org -o- > > > > http://live.gnome.org/gtk-vnc :| > > > > > > > > > > > > > > > > -- > > > > libvir-list mailing list > > > > libvir-list at redhat.com > > > > > > > https://www.redhat.com/mailman/listinfo/libvir-list > > > > > > > > > -- > > > Michal Novotny > > >>, > > > RHCE > > > Virtualization Team (xen userspace), Red Hat > > > > > > > > > > > > -- > > Michal Novotny >, > > RHCE > > Virtualization Team (xen userspace), Red Hat > > > > > > > -- > Michal Novotny , RHCE > Virtualization Team (xen userspace), Red Hat > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From minovotn at redhat.com Tue Apr 5 16:01:29 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 05 Apr 2011 18:01:29 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B353A.9080800@redhat.com> Message-ID: <4D9B3CD9.7040905@redhat.com> On 04/05/2011 05:59 PM, Marcela Castro Le?n wrote: > Hello > The restore finished ok, I found at a log that was looking the image > at an "old" location. Anyway, the image don't start well, but I've to > revise all the configuration again, to see what's exactly is happening > now. Thank you a lot, I learned a lot. Hi, that's fine it passed however what do you mean by "the image don't start well" ? Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From mcastrol at gmail.com Tue Apr 5 16:07:08 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Tue, 5 Apr 2011 18:07:08 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: <4D9B3CD9.7040905@redhat.com> References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B353A.9080800@redhat.com> <4D9B3CD9.7040905@redhat.com> Message-ID: Yes, its say that recover all right and the guest is running, but I cannot connect doing ssh, and in the virt-manager say "connecting to graphical console". I've just found in the log: *radic at rionegro:/var/log/libvirt/qemu$ sudo cat chompi1.log * *LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 -S -M pc-0.12 -enable-kvm -m 4096 -smp 4 -name chompi1 -uuid 22f013aa-25d4-b317-9eac-b232692db8c7 -chardev socket,id=monitor,path=/var/lib/libvirt/qemu/chompi1.monitor,server,nowait -monitor chardev:monitor -boot c -drive file=/home/radic/mv/discoguest/chompi1.img,if=ide,index=0,boot=on,format=raw -drive if=ide,media=cdrom,index=2,format=raw -net nic,macaddr=52:54:00:82:ce:80,vlan=0,model=virtio,name=virtio.0 -net tap,fd=33,vlan=0,name=tap.0 -chardev pty,id=serial0 -serial chardev:serial0 -parallel none -usb -vnc 127.0.0.1:0 -vga cirrus -incoming exec:cat * *char device redirected to /dev/pts/1* *cat: -: Permission denied* *load of migration failed* 2011/4/5 Michal Novotny > On 04/05/2011 05:59 PM, Marcela Castro Le?n wrote: > > Hello > > The restore finished ok, I found at a log that was looking the image > > at an "old" location. Anyway, the image don't start well, but I've to > > revise all the configuration again, to see what's exactly is happening > > now. Thank you a lot, I learned a lot. > > Hi, > that's fine it passed however what do you mean by "the image don't start > well" ? > > Michal > > -- > Michal Novotny , RHCE > Virtualization Team (xen userspace), Red Hat > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From minovotn at redhat.com Tue Apr 5 16:09:02 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 05 Apr 2011 18:09:02 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B353A.9080800@redhat.com> <4D9B3CD9.7040905@redhat.com> Message-ID: <4D9B3E9E.3070704@redhat.com> On 04/05/2011 06:07 PM, Marcela Castro Le?n wrote: > Yes, its say that recover all right and the guest is running, but I > cannot connect doing ssh, and in the virt-manager say "connecting to > graphical console". > I've just found in the log: > > *radic at rionegro:/var/log/libvirt/qemu$ sudo cat chompi1.log * > *LC_ALL=C > PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin > QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 -S -M pc-0.12 > -enable-kvm -m 4096 -smp 4 -name chompi1 -uuid > 22f013aa-25d4-b317-9eac-b232692db8c7 -chardev > socket,id=monitor,path=/var/lib/libvirt/qemu/chompi1.monitor,server,nowait > -monitor chardev:monitor -boot c -drive > file=/home/radic/mv/discoguest/chompi1.img,if=ide,index=0,boot=on,format=raw > -drive if=ide,media=cdrom,index=2,format=raw -net > nic,macaddr=52:54:00:82:ce:80,vlan=0,model=virtio,name=virtio.0 -net > tap,fd=33,vlan=0,name=tap.0 -chardev pty,id=serial0 -serial > chardev:serial0 -parallel none -usb -vnc 127.0.0.1:0 > * Well, I guess this is the problem since you have the VNC server bound to 127.0.0.1 which is localhost-only access. You have to change the libvirt configuration to put 0.0.0.0 there instead to bind to all network interfaces and not just loopback interface. Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From crobinso at redhat.com Tue Apr 5 16:13:31 2011 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 05 Apr 2011 12:13:31 -0400 Subject: [libvirt] Regression in allocating ports for serial/parallel devs Message-ID: <4D9B3FAB.8090205@redhat.com> Hi Michal, The following commit introduced a regression: http://libvirt.org/git/?p=libvirt.git;a=commit;h=79c3fe4d1681cd94598d2bd42e38a98f51cb645d Now, defining a guest with XML like Will allocate to all 3. The reason is that target.port is never set to -1 unless the user specified some XML. A simple fix is: --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3265,6 +3265,8 @@ virDomainChrDefParseXML(virCapsPtr caps, return NULL; } + def->target.port = -1; + type = virXMLPropString(node, "type"); if (type == NULL) { def->source.type = VIR_DOMAIN_CHR_TYPE_PTY; But that doesn't solve the problem for users who are building ChrDef's by hand, like when converting between formats as xen and vmware drivers do. I didn't look at those users so they may be safe, but the interface should be improved. Maybe add a ChrDefNew function that sets the -1 default. Additionally we should add a qemuxml2xml test for this to prevent against future regressions. Thanks, Cole From mprivozn at redhat.com Tue Apr 5 16:12:52 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Tue, 5 Apr 2011 18:12:52 +0200 Subject: [libvirt] [PATCH v2 0/8] Add support for taking screenshots Message-ID: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> Diff to v1: - filename argument replaced with stream - returning file mime-type This patch series implements screenshots taking feature, which is accessible via new virDomainScreenshot API and 'screenshot' command in virsh. By now, 'flags' argument is not used, but can be later when specifying say image output format, etc. Talking of - output is hypervisor specific. QEMU output images in PPM, VirtualBox in PNG. Michal Privoznik (8): screenshot: Defining the public API screenshot: Defining the internal API screenshot: Implementing the public API screenshot: Implementing the remote protocol screenshot: Expose the new API in virsh virFDStream: Add option for delete file after it's opening qemu: Implement the driver methods vbox: Implement the driver methods daemon/remote.c | 61 +++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 +++ daemon/remote_dispatch_ret.h | 1 + daemon/remote_dispatch_table.h | 5 ++ include/libvirt/libvirt.h.in | 7 ++ src/driver.h | 5 ++ src/esx/esx_driver.c | 1 + src/fdstream.c | 25 ++++++-- src/fdstream.h | 6 +- src/libvirt.c | 56 +++++++++++++++++ src/libvirt_public.syms | 5 ++ src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 4 +- src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 82 +++++++++++++++++++++++++- src/qemu/qemu_monitor.c | 20 ++++++ src/qemu/qemu_monitor.h | 3 + src/qemu/qemu_monitor_json.c | 23 +++++++ src/qemu/qemu_monitor_json.h | 4 + src/qemu/qemu_monitor_text.c | 31 ++++++++++ src/qemu/qemu_monitor_text.h | 2 + src/remote/remote_driver.c | 38 ++++++++++++ src/remote/remote_protocol.c | 20 ++++++ src/remote/remote_protocol.h | 16 +++++ src/remote/remote_protocol.x | 12 ++++- src/storage/storage_driver.c | 4 +- src/test/test_driver.c | 1 + src/uml/uml_driver.c | 4 +- src/util/iohelper.c | 12 +++- src/vbox/vbox_tmpl.c | 114 +++++++++++++++++++++++++++++++++++ src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 4 +- src/xen/xen_driver.h | 1 + src/xen/xen_hypervisor.c | 1 + src/xen/xen_inotify.c | 1 + src/xen/xend_internal.c | 1 + src/xen/xm_internal.c | 1 + src/xen/xs_internal.c | 1 + src/xenapi/xenapi_driver.c | 1 + tools/virsh.c | 90 +++++++++++++++++++++++++++ tools/virsh.pod | 4 + 43 files changed, 664 insertions(+), 16 deletions(-) -- 1.7.4 From mprivozn at redhat.com Tue Apr 5 16:12:53 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Tue, 5 Apr 2011 18:12:53 +0200 Subject: [libvirt] [PATCH v2 1/8] screenshot: Defining the public API In-Reply-To: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> References: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> Message-ID: <1302019980-14957-2-git-send-email-mprivozn@redhat.com> Add public API for taking screenshots of current domain console. * include/libvirt/libvirt.h.in: add virDomainScreenshot * src/libvirt_public.syms: Stub code for new API --- include/libvirt/libvirt.h.in | 7 +++++++ src/libvirt_public.syms | 5 +++++ 2 files changed, 12 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index bd36015..556bf5b 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -670,6 +670,13 @@ int virDomainCoreDump (virDomainPtr domain, int flags); /* + * Screenshot of current domain console + */ +char * virDomainScreenshot (virDomainPtr domain, + virStreamPtr stream, + unsigned int flags); + +/* * Domain runtime information */ int virDomainGetInfo (virDomainPtr domain, diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b4aed41..5c9e6b4 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -436,4 +436,9 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8; +LIBVIRT_0.9.1 { + global: + virDomainScreenshot; +} LIBVIRT_0.9.0; + # .... define new API here using predicted next version number .... -- 1.7.4 From mprivozn at redhat.com Tue Apr 5 16:12:54 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Tue, 5 Apr 2011 18:12:54 +0200 Subject: [libvirt] [PATCH v2 2/8] screenshot: Defining the internal API In-Reply-To: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> References: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> Message-ID: <1302019980-14957-3-git-send-email-mprivozn@redhat.com> * src/driver.h: Stub code for new API * src/esx/esx_driver.c, src/libxl/libxl_driver.c, src/lxc/lxc_driver.c, src/openvz/openvz_driver.c, src/phyp/phyp_driver.c, src/qemu/qemu_driver.c, rc/remote/remote_driver.c, rc/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c, src/vmware/vmware_driver.c, src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_hypervisor.c, src/xen/xen_inotify.c, src/xen/xend_internal.c, src/xen/xm_internal.c, src/xen/xs_internal.c, src/xenapi/xenapi_driver.c: Add dummy entries in driver table for new APIs --- src/driver.h | 5 +++++ src/esx/esx_driver.c | 1 + src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 1 + src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xen/xen_driver.h | 1 + src/xen/xen_hypervisor.c | 1 + src/xen/xen_inotify.c | 1 + src/xen/xend_internal.c | 1 + src/xen/xm_internal.c | 1 + src/xen/xs_internal.c | 1 + src/xenapi/xenapi_driver.c | 1 + 20 files changed, 24 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index e5f91ca..999abab 100644 --- a/src/driver.h +++ b/src/driver.h @@ -176,6 +176,10 @@ typedef int const char *to, int flags); typedef char * + (*virDrvDomainScreenshot) (virDomainPtr domain, + virStreamPtr stream, + unsigned int flags); +typedef char * (*virDrvDomainDumpXML) (virDomainPtr dom, int flags); typedef char * @@ -566,6 +570,7 @@ struct _virDriver { virDrvDomainSave domainSave; virDrvDomainRestore domainRestore; virDrvDomainCoreDump domainCoreDump; + virDrvDomainScreenshot domainScreenshot; virDrvDomainSetVcpus domainSetVcpus; virDrvDomainSetVcpusFlags domainSetVcpusFlags; virDrvDomainGetVcpusFlags domainGetVcpusFlags; diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index deda372..2d52314 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4602,6 +4602,7 @@ static virDriver esxDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ esxDomainSetVcpus, /* domainSetVcpus */ esxDomainSetVcpusFlags, /* domainSetVcpusFlags */ esxDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 75f99c1..0c6635c 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2407,6 +2407,7 @@ static virDriver libxlDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ libxlDomainSetVcpus, /* domainSetVcpus */ libxlDomainSetVcpusFlags, /* domainSetVcpusFlags */ libxlDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e905302..ed40cb2 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2833,6 +2833,7 @@ static virDriver lxcDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ NULL, /* domainSetVcpus */ NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 4af28e9..c9a40e7 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1594,6 +1594,7 @@ static virDriver openvzDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ openvzDomainSetVcpus, /* domainSetVcpus */ openvzDomainSetVcpusFlags, /* domainSetVcpusFlags */ openvzDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index ddbc103..aaac1da 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -3999,6 +3999,7 @@ static virDriver phypDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ phypDomainSetCPU, /* domainSetVcpus */ phypDomainSetVcpusFlags, /* domainSetVcpusFlags */ phypDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 48fe266..a8e4db9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6853,6 +6853,7 @@ static virDriver qemuDriver = { qemudDomainSave, /* domainSave */ qemuDomainRestore, /* domainRestore */ qemudDomainCoreDump, /* domainCoreDump */ + NULL, /* domainScreenshot */ qemudDomainSetVcpus, /* domainSetVcpus */ qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 9310ddf..f5b7c55 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -11227,6 +11227,7 @@ static virDriver remote_driver = { remoteDomainSave, /* domainSave */ remoteDomainRestore, /* domainRestore */ remoteDomainCoreDump, /* domainCoreDump */ + NULL, /* domainScreenshot */ remoteDomainSetVcpus, /* domainSetVcpus */ remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 17f5ad9..5a33054 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5374,6 +5374,7 @@ static virDriver testDriver = { testDomainSave, /* domainSave */ testDomainRestore, /* domainRestore */ testDomainCoreDump, /* domainCoreDump */ + NULL, /* domainScreenshot */ testSetVcpus, /* domainSetVcpus */ testDomainSetVcpusFlags, /* domainSetVcpusFlags */ testDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 33849a0..00ab62d 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2180,6 +2180,7 @@ static virDriver umlDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ NULL, /* domainSetVcpus */ NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 0fbfba5..a87c6a5 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8564,6 +8564,7 @@ virDriver NAME(Driver) = { vboxDomainSave, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ vboxDomainSetVcpus, /* domainSetVcpus */ vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */ vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index b5e416b..926eca0 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -934,6 +934,7 @@ static virDriver vmwareDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ NULL, /* domainSetVcpus */ NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 9f47722..a883c15 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2068,6 +2068,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedDomainSave, /* domainSave */ xenUnifiedDomainRestore, /* domainRestore */ xenUnifiedDomainCoreDump, /* domainCoreDump */ + NULL, /* domainScreenshot */ xenUnifiedDomainSetVcpus, /* domainSetVcpus */ xenUnifiedDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenUnifiedDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/xen/xen_driver.h b/src/xen/xen_driver.h index 58b8561..8fb5832 100644 --- a/src/xen/xen_driver.h +++ b/src/xen/xen_driver.h @@ -93,6 +93,7 @@ struct xenUnifiedDriver { virDrvDomainSave domainSave; virDrvDomainRestore domainRestore; virDrvDomainCoreDump domainCoreDump; + virDrvDomainScreenshot domainScreenshot; virDrvDomainPinVcpu domainPinVcpu; virDrvDomainGetVcpus domainGetVcpus; virDrvListDefinedDomains listDefinedDomains; diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c index 8a9dae5..7fccaba 100644 --- a/src/xen/xen_hypervisor.c +++ b/src/xen/xen_hypervisor.c @@ -824,6 +824,7 @@ struct xenUnifiedDriver xenHypervisorDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ xenHypervisorPinVcpu, /* domainPinVcpu */ xenHypervisorGetVcpus, /* domainGetVcpus */ NULL, /* listDefinedDomains */ diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c index 5a997e6..d072fbb 100644 --- a/src/xen/xen_inotify.c +++ b/src/xen/xen_inotify.c @@ -72,6 +72,7 @@ struct xenUnifiedDriver xenInotifyDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ NULL, /* domainPinVcpu */ NULL, /* domainGetVcpus */ NULL, /* listDefinedDomains */ diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 04122ba..1ad074f 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -3866,6 +3866,7 @@ struct xenUnifiedDriver xenDaemonDriver = { xenDaemonDomainSave, /* domainSave */ xenDaemonDomainRestore, /* domainRestore */ xenDaemonDomainCoreDump, /* domainCoreDump */ + NULL, /* domainScreenshot */ xenDaemonDomainPinVcpu, /* domainPinVcpu */ xenDaemonDomainGetVcpus, /* domainGetVcpus */ xenDaemonListDefinedDomains, /* listDefinedDomains */ diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 9225808..889ac6c 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -103,6 +103,7 @@ struct xenUnifiedDriver xenXMDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ xenXMDomainPinVcpu, /* domainPinVcpu */ NULL, /* domainGetVcpus */ xenXMListDefinedDomains, /* listDefinedDomains */ diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c index d9aad1f..c17d5f9 100644 --- a/src/xen/xs_internal.c +++ b/src/xen/xs_internal.c @@ -65,6 +65,7 @@ struct xenUnifiedDriver xenStoreDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ NULL, /* domainPinVcpu */ NULL, /* domainGetVcpus */ NULL, /* listDefinedDomains */ diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 60b23c7..dd4d13d 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1816,6 +1816,7 @@ static virDriver xenapiDriver = { NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ + NULL, /* domainScreenshot */ xenapiDomainSetVcpus, /* domainSetVcpus */ xenapiDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenapiDomainGetVcpusFlags, /* domainGetVcpusFlags */ -- 1.7.4 From mprivozn at redhat.com Tue Apr 5 16:12:55 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Tue, 5 Apr 2011 18:12:55 +0200 Subject: [libvirt] [PATCH v2 3/8] screenshot: Implementing the public API In-Reply-To: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> References: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> Message-ID: <1302019980-14957-4-git-send-email-mprivozn@redhat.com> * src/libvirt.c: Stub for new API --- src/libvirt.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 56 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 85dfc58..9dc638e 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -2407,6 +2407,62 @@ error: } /** + * virDomainScreenshot: + * @domain: a domain object + * @stream: stream to use as output + * @flags: extra flags, currently unused + * + * Take a screenshot of current domain console as a stream. The image format + * is hypervisor specific. + * + * This call sets up a stream; subsequent use of stream API is necessary + * to transfer actual data, determine how much data is successfully + * transfered, and detect any errors. + * + * Returns a string representing the mime-type of the image format, or + * NULL upon error. The caller must free() the returned value. + */ +char * +virDomainScreenshot(virDomainPtr domain, + virStreamPtr stream, + unsigned int flags) +{ + VIR_DOMAIN_DEBUG(domain, "stream=%p flags=%u", stream, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return NULL; + } + if (!VIR_IS_STREAM(stream)) { + virLibConnError(VIR_ERR_INVALID_STREAM, __FUNCTION__); + return NULL; + } + if (domain->conn->flags & VIR_CONNECT_RO || + stream->conn->flags & VIR_CONNECT_RO) { + virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (domain->conn->driver->domainScreenshot) { + char * ret; + ret = domain->conn->driver->domainScreenshot(domain, stream, flags); + + if (ret == NULL) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return NULL; +} + +/** * virDomainShutdown: * @domain: a domain object * -- 1.7.4 From mprivozn at redhat.com Tue Apr 5 16:12:56 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Tue, 5 Apr 2011 18:12:56 +0200 Subject: [libvirt] [PATCH v2 4/8] screenshot: Implementing the remote protocol In-Reply-To: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> References: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> Message-ID: <1302019980-14957-5-git-send-email-mprivozn@redhat.com> * daemon/remote.c, src/remote/remote_driver.c: Implementation of screenshot API * src/remote/remote_protocol.x: Wire protocol definition * daemon/remote_dispatch_args.h, daemon/remote_dispatch_prototypes.h, daemon/remote_dispatch_ret.h, daemon/remote_dispatch_table.h, src/remote/remote_protocol.c, src/remote/remote_protocol.h: Re-generate --- daemon/remote.c | 61 +++++++++++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++ daemon/remote_dispatch_ret.h | 1 + daemon/remote_dispatch_table.h | 5 +++ src/remote/remote_driver.c | 39 +++++++++++++++++++++- src/remote/remote_protocol.c | 20 +++++++++++ src/remote/remote_protocol.h | 16 +++++++++ src/remote/remote_protocol.x | 12 ++++++- 9 files changed, 161 insertions(+), 2 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index dd85ef1..c289e52 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -2318,6 +2318,67 @@ remoteDispatchDomainCoreDump (struct qemud_server *server ATTRIBUTE_UNUSED, } static int +remoteDispatchDomainScreenshot (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *rerr, + remote_domain_screenshot_args *args, + remote_domain_screenshot_ret *ret) +{ + int rv = -1; + struct qemud_client_stream *stream = NULL; + virDomainPtr dom; + char *mime, **mime_p; + + ret->mime = NULL; + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); + goto cleanup; + } + + stream = remoteCreateClientStream(conn, hdr); + if (!stream) { + remoteDispatchConnError(rerr, conn); + goto cleanup; + } + + mime = virDomainScreenshot(dom, stream->st, args->flags); + if (mime == NULL) { + remoteDispatchConnError(rerr, conn); + goto cleanup; + } + + if (remoteAddClientStream(client, stream, 1) < 0) { + remoteDispatchConnError(rerr, conn); + virStreamAbort(stream->st); + goto cleanup; + } + + if (VIR_ALLOC(mime_p) < 0) { + remoteDispatchOOMError(rerr); + goto cleanup; + } + + *mime_p = strdup(mime); + if (*mime_p == NULL) { + remoteDispatchOOMError(rerr); + goto cleanup; + } + + ret->mime = mime_p; + rv = 0; + +cleanup: + virDomainFree(dom); + if (stream && rv != 0) + remoteFreeClientStream(client, stream); + return rv; +} + +static int remoteDispatchDomainSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index f9537d7..2be8003 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -178,3 +178,4 @@ remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; remote_storage_vol_upload_args val_remote_storage_vol_upload_args; remote_storage_vol_download_args val_remote_storage_vol_download_args; + remote_domain_screenshot_args val_remote_domain_screenshot_args; diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 18bf41d..582a8dd 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -546,6 +546,14 @@ static int remoteDispatchDomainSave( remote_error *err, remote_domain_save_args *args, void *ret); +static int remoteDispatchDomainScreenshot( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_screenshot_args *args, + remote_domain_screenshot_ret *ret); static int remoteDispatchDomainSetAutostart( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_ret.h b/daemon/remote_dispatch_ret.h index 114e832..1ecb8a9 100644 --- a/daemon/remote_dispatch_ret.h +++ b/daemon/remote_dispatch_ret.h @@ -140,3 +140,4 @@ remote_domain_is_updated_ret val_remote_domain_is_updated_ret; remote_get_sysinfo_ret val_remote_get_sysinfo_ret; remote_domain_get_blkio_parameters_ret val_remote_domain_get_blkio_parameters_ret; + remote_domain_screenshot_ret val_remote_domain_screenshot_ret; diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index b39f7c2..b058db3 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1052,3 +1052,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* DomainScreenshot => 210 */ + .fn = (dispatch_fn) remoteDispatchDomainScreenshot, + .args_filter = (xdrproc_t) xdr_remote_domain_screenshot_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_screenshot_ret, +}, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index f5b7c55..91a7651 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -11057,6 +11057,43 @@ remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque) remoteDriverUnlock(priv); } +static char * +remoteDomainScreenshot (virDomainPtr domain, + virStreamPtr st, + unsigned int flags) +{ + struct private_data *priv = domain->conn->privateData; + struct private_stream_data *privst = NULL; + remote_domain_screenshot_args args; + remote_domain_screenshot_ret ret; + char *rv = NULL; + + remoteDriverLock(priv); + + if (!(privst = remoteStreamOpen(st, + REMOTE_PROC_DOMAIN_SCREENSHOT, + priv->counter))) + goto done; + + st->driver = &remoteStreamDrv; + st->privateData = privst; + + make_nonnull_domain(&args.dom, domain); + args.flags = flags; + + memset(&ret, 0, sizeof(ret)); + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SCREENSHOT, + (xdrproc_t) xdr_remote_domain_screenshot_args, (char *) &args, + (xdrproc_t) xdr_remote_domain_screenshot_ret, (char *) &ret) == -1) + goto done; + + rv = ret.mime ? *ret.mime : NULL; + VIR_FREE(ret.mime); + +done: + remoteDriverUnlock(priv); + return rv; +} /* get_nonnull_domain and get_nonnull_network turn an on-wire * (name, uuid) pair into virDomainPtr or virNetworkPtr object. @@ -11227,7 +11264,7 @@ static virDriver remote_driver = { remoteDomainSave, /* domainSave */ remoteDomainRestore, /* domainRestore */ remoteDomainCoreDump, /* domainCoreDump */ - NULL, /* domainScreenshot */ + remoteDomainScreenshot, /* domainScreenshot */ remoteDomainSetVcpus, /* domainSetVcpus */ remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 5604371..a4deb67 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -1230,6 +1230,26 @@ xdr_remote_domain_core_dump_args (XDR *xdrs, remote_domain_core_dump_args *objp) } bool_t +xdr_remote_domain_screenshot_args (XDR *xdrs, remote_domain_screenshot_args *objp) +{ + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_screenshot_ret (XDR *xdrs, remote_domain_screenshot_ret *objp) +{ + + if (!xdr_remote_string (xdrs, &objp->mime)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_domain_dump_xml_args (XDR *xdrs, remote_domain_dump_xml_args *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index d9bf151..d1b02d6 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -666,6 +666,17 @@ struct remote_domain_core_dump_args { }; typedef struct remote_domain_core_dump_args remote_domain_core_dump_args; +struct remote_domain_screenshot_args { + remote_nonnull_domain dom; + u_int flags; +}; +typedef struct remote_domain_screenshot_args remote_domain_screenshot_args; + +struct remote_domain_screenshot_ret { + remote_string mime; +}; +typedef struct remote_domain_screenshot_ret remote_domain_screenshot_ret; + struct remote_domain_dump_xml_args { remote_nonnull_domain dom; int flags; @@ -2413,6 +2424,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_SCREENSHOT = 210, }; typedef enum remote_procedure remote_procedure; @@ -2541,6 +2553,8 @@ extern bool_t xdr_remote_domain_get_info_ret (XDR *, remote_domain_get_info_ret extern bool_t xdr_remote_domain_save_args (XDR *, remote_domain_save_args*); extern bool_t xdr_remote_domain_restore_args (XDR *, remote_domain_restore_args*); extern bool_t xdr_remote_domain_core_dump_args (XDR *, remote_domain_core_dump_args*); +extern bool_t xdr_remote_domain_screenshot_args (XDR *, remote_domain_screenshot_args*); +extern bool_t xdr_remote_domain_screenshot_ret (XDR *, remote_domain_screenshot_ret*); extern bool_t xdr_remote_domain_dump_xml_args (XDR *, remote_domain_dump_xml_args*); extern bool_t xdr_remote_domain_dump_xml_ret (XDR *, remote_domain_dump_xml_ret*); extern bool_t xdr_remote_domain_migrate_prepare_args (XDR *, remote_domain_migrate_prepare_args*); @@ -2898,6 +2912,8 @@ extern bool_t xdr_remote_domain_get_info_ret (); extern bool_t xdr_remote_domain_save_args (); extern bool_t xdr_remote_domain_restore_args (); extern bool_t xdr_remote_domain_core_dump_args (); +extern bool_t xdr_remote_domain_screenshot_args (); +extern bool_t xdr_remote_domain_screenshot_ret (); extern bool_t xdr_remote_domain_dump_xml_args (); extern bool_t xdr_remote_domain_dump_xml_ret (); extern bool_t xdr_remote_domain_migrate_prepare_args (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 675eccd..6e5d09a 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -714,6 +714,15 @@ struct remote_domain_core_dump_args { int flags; }; +struct remote_domain_screenshot_args { + remote_nonnull_domain dom; + unsigned int flags; +}; + +struct remote_domain_screenshot_ret { + remote_string mime; +}; + struct remote_domain_dump_xml_args { remote_nonnull_domain dom; int flags; @@ -2176,7 +2185,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_SCREENSHOT = 210 /* * Notice how the entries are grouped in sets of 10 ? -- 1.7.4 From mprivozn at redhat.com Tue Apr 5 16:12:57 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Tue, 5 Apr 2011 18:12:57 +0200 Subject: [libvirt] [PATCH v2 5/8] screenshot: Expose the new API in virsh In-Reply-To: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> References: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> Message-ID: <1302019980-14957-6-git-send-email-mprivozn@redhat.com> * tools/virsh.c: Add screenshot command * tools/virsh.pod: Document new command --- tools/virsh.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 4 ++ 2 files changed, 94 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index f2d2c9d..4080132 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1881,6 +1881,95 @@ cmdDump(vshControl *ctl, const vshCmd *cmd) return ret; } +static const vshCmdInfo info_screenshot[] = { + {"help", N_("take a screenshot of a current domain console and store it " + "into a file")}, + {"desc", N_("screenshot of a current domain console")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_screenshot[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("where to store the screenshot")}, + {NULL, 0, 0, NULL} +}; + +static int cmdScreenshotSink(virStreamPtr st ATTRIBUTE_UNUSED, + const char *bytes, size_t nbytes, void *opaque) +{ + int *fd = opaque; + + return safewrite(*fd, bytes, nbytes); +} + +static int +cmdScreenshot(vshControl *ctl, const vshCmd *cmd) { + virDomainPtr dom; + const char *name = NULL; + const char *file = NULL; + int fd = -1; + virStreamPtr st = NULL; + unsigned int flags = 0; /* currently unused */ + int ret = FALSE; + bool created = true; + char *mime = NULL; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return FALSE; + + if (vshCommandOptString(cmd, "file", &file) < 0) { + vshError(ctl, "%s", _("file must not be empty")); + return FALSE; + } + + if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + return FALSE; + + if ((fd = open(file, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) { + created = false; + if (errno != EEXIST || + (fd = open(file, O_WRONLY|O_TRUNC, 0666)) < 0) { + vshError(ctl, _("cannot create file %s"), file); + goto cleanup; + } + } + + st = virStreamNew(ctl->conn, 0); + + mime = virDomainScreenshot(dom, st, flags); + if (mime == NULL) { + vshError(ctl, _("could not take a screenshot of %s"), name); + goto cleanup; + } + + if (virStreamRecvAll(st, cmdScreenshotSink, &fd) < 0) { + vshError(ctl, _("could not receive data from domain %s"), name); + goto cleanup; + } + + if (VIR_CLOSE(fd) < 0) { + vshError(ctl, _("cannot close file %s"), file); + goto cleanup; + } + + if (virStreamFinish(st) < 0) { + vshError(ctl, _("cannot close stream on domain %s"), name); + goto cleanup; + } + + vshPrint(ctl, _("Screenshot saved to %s it's type is %s"), file, mime); + ret = TRUE; + +cleanup: + if (ret == FALSE && created) + unlink(file); + virDomainFree(dom); + if (st) + virStreamFree(st); + VIR_FORCE_CLOSE(fd); + return ret; +} + /* * "resume" command */ @@ -10699,6 +10788,7 @@ static const vshCmdDef domManagementCmds[] = { {"resume", cmdResume, opts_resume, info_resume}, {"save", cmdSave, opts_save, info_save}, {"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo}, + {"screenshot", cmdScreenshot, opts_screenshot, info_screenshot}, {"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem}, {"setmem", cmdSetmem, opts_setmem, info_setmem}, {"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus}, diff --git a/tools/virsh.pod b/tools/virsh.pod index f4bd294..e61f501 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -578,6 +578,10 @@ Therefore, -1 is a useful shorthand for 262144. B: The weight and cap parameters are defined only for the XEN_CREDIT scheduler and are now I. +=item B I I + +Takes a screenshot of a current domain console and stores it into a file. + =item B I B optional I<--config> I<--live> Change the memory allocation for a guest domain. -- 1.7.4 From mprivozn at redhat.com Tue Apr 5 16:12:58 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Tue, 5 Apr 2011 18:12:58 +0200 Subject: [libvirt] [PATCH v2 6/8] virFDStream: Add option for delete file after it's opening In-Reply-To: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> References: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> Message-ID: <1302019980-14957-7-git-send-email-mprivozn@redhat.com> This is needed if we want to transfer a temporary file. If the transfer is done with iohelper, we might run into a race condition, where we unlink() file before iohelper is executed. * src/fdstream.c, src/fdstream.h, src/util/iohelper.c: Add new option * src/lxc/lxc_driver.c, src/qemu/qemu_driver.c, src/storage/storage_driver.c, src/uml/uml_driver.c, src/xen/xen_driver.c: Expand existing function calls --- src/fdstream.c | 25 ++++++++++++++++++++----- src/fdstream.h | 6 ++++-- src/lxc/lxc_driver.c | 3 ++- src/qemu/qemu_driver.c | 3 ++- src/storage/storage_driver.c | 4 ++-- src/uml/uml_driver.c | 3 ++- src/util/iohelper.c | 12 ++++++++++-- src/xen/xen_driver.c | 3 ++- 8 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/fdstream.c b/src/fdstream.c index 3475bfd..5198a36 100644 --- a/src/fdstream.c +++ b/src/fdstream.c @@ -493,7 +493,8 @@ virFDStreamOpenFileInternal(virStreamPtr st, unsigned long long offset, unsigned long long length, int flags, - int mode) + int mode, + bool delete) { int fd = -1; int fds[2] = { -1, -1 }; @@ -554,6 +555,14 @@ virFDStreamOpenFileInternal(virStreamPtr st, virCommandAddArgFormat(cmd, "%d", mode); virCommandAddArgFormat(cmd, "%llu", offset); virCommandAddArgFormat(cmd, "%llu", length); + virCommandAddArgFormat(cmd, "%u", delete); + + /* when running iohelper we don't want to delete file now, + * because a race condition may occur in which we delete it + * before iohelper even opens it. We want iohelper to remove + * the file instead. + */ + delete = false; if (flags == O_RDONLY) { childfd = fds[1]; @@ -583,6 +592,9 @@ virFDStreamOpenFileInternal(virStreamPtr st, if (virFDStreamOpenInternal(st, fd, cmd, errfd, length) < 0) goto error; + if (delete) + unlink(path); + return 0; error: @@ -601,7 +613,8 @@ int virFDStreamOpenFile(virStreamPtr st, const char *path, unsigned long long offset, unsigned long long length, - int flags) + int flags, + bool delete) { if (flags & O_CREAT) { streamsReportError(VIR_ERR_INTERNAL_ERROR, @@ -611,7 +624,7 @@ int virFDStreamOpenFile(virStreamPtr st, } return virFDStreamOpenFileInternal(st, path, offset, length, - flags, 0); + flags, 0, delete); } int virFDStreamCreateFile(virStreamPtr st, @@ -619,9 +632,11 @@ int virFDStreamCreateFile(virStreamPtr st, unsigned long long offset, unsigned long long length, int flags, - mode_t mode) + mode_t mode, + bool delete) { return virFDStreamOpenFileInternal(st, path, offset, length, - flags | O_CREAT, mode); + flags | O_CREAT, + mode, delete); } diff --git a/src/fdstream.h b/src/fdstream.h index 6b395b6..a66902b 100644 --- a/src/fdstream.h +++ b/src/fdstream.h @@ -37,12 +37,14 @@ int virFDStreamOpenFile(virStreamPtr st, const char *path, unsigned long long offset, unsigned long long length, - int flags); + int flags, + bool delete); int virFDStreamCreateFile(virStreamPtr st, const char *path, unsigned long long offset, unsigned long long length, int flags, - mode_t mode); + mode_t mode, + bool delete); #endif /* __VIR_FDSTREAM_H_ */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index ed40cb2..5bf3212 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2782,7 +2782,8 @@ lxcDomainOpenConsole(virDomainPtr dom, goto cleanup; } - if (virFDStreamOpenFile(st, chr->source.data.file.path, 0, 0, O_RDWR) < 0) + if (virFDStreamOpenFile(st, chr->source.data.file.path, + 0, 0, O_RDWR, false) < 0) goto cleanup; ret = 0; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a8e4db9..9f0bad4 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6803,7 +6803,8 @@ qemuDomainOpenConsole(virDomainPtr dom, goto cleanup; } - if (virFDStreamOpenFile(st, chr->source.data.file.path, 0, 0, O_RDWR) < 0) + if (virFDStreamOpenFile(st, chr->source.data.file.path, + 0, 0, O_RDWR, false) < 0) goto cleanup; ret = 0; diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 1ea5d12..3a9a5f4 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -1588,7 +1588,7 @@ storageVolumeDownload(virStorageVolPtr obj, if (virFDStreamOpenFile(stream, vol->target.path, offset, length, - O_RDONLY) < 0) + O_RDONLY, false) < 0) goto out; ret = 0; @@ -1652,7 +1652,7 @@ storageVolumeUpload(virStorageVolPtr obj, if (virFDStreamOpenFile(stream, vol->target.path, offset, length, - O_WRONLY) < 0) + O_WRONLY, false) < 0) goto out; ret = 0; diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 00ab62d..4b81c43 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2130,7 +2130,8 @@ umlDomainOpenConsole(virDomainPtr dom, goto cleanup; } - if (virFDStreamOpenFile(st, chr->source.data.file.path, 0, 0, O_RDWR) < 0) + if (virFDStreamOpenFile(st, chr->source.data.file.path, + 0, 0, O_RDWR, false) < 0) goto cleanup; ret = 0; diff --git a/src/util/iohelper.c b/src/util/iohelper.c index d5821b9..f519d5a 100644 --- a/src/util/iohelper.c +++ b/src/util/iohelper.c @@ -146,6 +146,7 @@ int main(int argc, char **argv) unsigned long long length; int flags; int mode; + unsigned int delete; if (setlocale(LC_ALL, "") == NULL || bindtextdomain(PACKAGE, LOCALEDIR) == NULL || @@ -161,8 +162,8 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - if (argc != 6) { - fprintf(stderr, _("%s: syntax FILENAME FLAGS MODE OFFSET LENGTH\n"), argv[0]); + if (argc != 7) { + fprintf(stderr, _("%s: syntax FILENAME FLAGS MODE OFFSET LENGTH DELETE\n"), argv[0]); exit(EXIT_FAILURE); } @@ -186,10 +187,17 @@ int main(int argc, char **argv) fprintf(stderr, _("%s: malformed file length %s"), argv[0], argv[5]); exit(EXIT_FAILURE); } + if (virStrToLong_ui(argv[6], NULL, 10, &delete) < 0) { + fprintf(stderr, _("%s: malformed delete flag %s"), argv[0],argv[6]); + exit(EXIT_FAILURE); + } if (runIO(path, flags, mode, offset, length) < 0) goto error; + if (delete) + unlink(path); + return 0; error: diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index a883c15..358c307 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2019,7 +2019,8 @@ xenUnifiedDomainOpenConsole(virDomainPtr dom, goto cleanup; } - if (virFDStreamOpenFile(st, chr->source.data.file.path, 0, 0, O_RDWR) < 0) + if (virFDStreamOpenFile(st, chr->source.data.file.path, + 0, 0, O_RDWR, false) < 0) goto cleanup; ret = 0; -- 1.7.4 From mprivozn at redhat.com Tue Apr 5 16:12:59 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Tue, 5 Apr 2011 18:12:59 +0200 Subject: [libvirt] [PATCH v2 7/8] qemu: Implement the driver methods In-Reply-To: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> References: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> Message-ID: <1302019980-14957-8-git-send-email-mprivozn@redhat.com> * src/qemu/qemu_driver.c: new qemuDomainScreenshot() function * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, src/qemu/qemu_monitor_json.c, src/qemu/qemu_monitor_json.h, src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h: Monitor stubs --- src/qemu/qemu_driver.c | 80 +++++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_monitor.c | 20 ++++++++++ src/qemu/qemu_monitor.h | 3 ++ src/qemu/qemu_monitor_json.c | 23 ++++++++++++ src/qemu/qemu_monitor_json.h | 4 ++ src/qemu/qemu_monitor_text.c | 31 ++++++++++++++++ src/qemu/qemu_monitor_text.h | 2 + 7 files changed, 162 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 9f0bad4..1ea2174 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2384,6 +2384,84 @@ cleanup: return ret; } +static char * +qemuDomainScreenshot(virDomainPtr dom, + virStreamPtr st, + unsigned int flags ATTRIBUTE_UNUSED) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + qemuDomainObjPrivatePtr priv; + char *tmp = NULL; + int tmp_fd = -1; + char *ret = NULL; + + 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 matching uuid '%s'"), uuidstr); + goto cleanup; + } + + priv = vm->privateData; + + if (qemuDomainObjBeginJob(vm) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto endjob; + } + + if (virAsprintf(&tmp, "%s/qemu.screendump.XXXXXX", driver->cacheDir) < 0) { + virReportOOMError(); + goto endjob; + } + + if ((tmp_fd = mkstemp(tmp)) == -1) { + virReportSystemError(errno, _("mkstemp(\"%s\") failed"), tmp); + goto endjob; + } + + qemuDomainObjEnterMonitor(vm); + if (qemuMonitorScreendump(priv->mon, tmp) < 0) { + qemuDomainObjExitMonitor(vm); + goto endjob; + } + qemuDomainObjExitMonitor(vm); + + if (VIR_CLOSE(tmp_fd) < 0) { + virReportSystemError(errno, _("unable to close %s"), tmp); + goto endjob; + } + + if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY, true) < 0) { + qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to open stream")); + goto endjob; + } + + ret = strdup("image/x-portable-pixmap; charset=binary"); + +endjob: + VIR_FORCE_CLOSE(tmp_fd); + VIR_FREE(tmp); + + if (qemuDomainObjEndJob(vm) == 0) + vm = NULL; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + static void processWatchdogEvent(void *data, void *opaque) { int ret; @@ -6854,7 +6932,7 @@ static virDriver qemuDriver = { qemudDomainSave, /* domainSave */ qemuDomainRestore, /* domainRestore */ qemudDomainCoreDump, /* domainCoreDump */ - NULL, /* domainScreenshot */ + qemuDomainScreenshot, /* domainScreenshot */ qemudDomainSetVcpus, /* domainSetVcpus */ qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 2d28f8d..6834d29 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2228,3 +2228,23 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, ret = qemuMonitorTextArbitraryCommand(mon, cmd, reply); return ret; } + +int qemuMonitorScreendump(qemuMonitorPtr mon, + const char *file) +{ + int ret; + + VIR_DEBUG("mon=%p, file=%s", mon, file); + + if (!mon) { + qemuReportError(VIR_ERR_INVALID_ARG,"%s", + _("monitor must not be NULL")); + return -1; + } + + if (mon->json) + ret = qemuMonitorJSONScreendump(mon, file); + else + ret = qemuMonitorTextScreendump(mon, file); + return ret; +} diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c90219b..5c96f12 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -423,6 +423,9 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, char **reply, bool hmp); +int qemuMonitorScreendump(qemuMonitorPtr mon, + const char *file); + /** * When running two dd process and using <> redirection, we need a * shell that will not truncate files. These two strings serve that diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 20a78e1..df45e4b 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2513,3 +2513,26 @@ cleanup: return ret; } + +int qemuMonitorJSONScreendump(qemuMonitorPtr mon, + const char *file) +{ + int ret; + virJSONValuePtr cmd, reply = NULL; + + cmd = qemuMonitorJSONMakeCommand("screendump", + "s:filename", file, + NULL); + + if (!cmd) + return -1; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 086f0e1..bcfdd24 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -204,4 +204,8 @@ int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon, char **reply_str, bool hmp); +int qemuMonitorJSONScreendump(qemuMonitorPtr mon, + const char *file); + + #endif /* QEMU_MONITOR_JSON_H */ diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 53781c8..f71cf2d 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -2628,3 +2628,34 @@ int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, return ret; } + +/* Returns -1 on error, -2 if not supported */ +int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file) +{ + char *cmd = NULL; + char *reply = NULL; + int ret = -1; + + if (virAsprintf(&cmd, "screendump %s", file) < 0){ + virReportOOMError(); + goto cleanup; + } + + if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("taking screenshot failed")); + goto cleanup; + } + + if (strstr(reply, "unknown command:")) { + ret = -2; + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(reply); + VIR_FREE(cmd); + return ret; +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 0838a2b..773d33c 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -198,4 +198,6 @@ int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name); int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply); +int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file); + #endif /* QEMU_MONITOR_TEXT_H */ -- 1.7.4 From mprivozn at redhat.com Tue Apr 5 16:13:00 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Tue, 5 Apr 2011 18:13:00 +0200 Subject: [libvirt] [PATCH v2 8/8] vbox: Implement the driver methods In-Reply-To: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> References: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> Message-ID: <1302019980-14957-9-git-send-email-mprivozn@redhat.com> * src/vbox/vbox_tmpl.c: New vboxDomainScreenshot() function --- src/vbox/vbox_tmpl.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 113 insertions(+), 0 deletions(-) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index a87c6a5..53a3a88 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -36,6 +36,9 @@ #include #include +#include +#include +#include #include "internal.h" #include "datatypes.h" @@ -51,6 +54,9 @@ #include "nodeinfo.h" #include "logging.h" #include "vbox_driver.h" +#include "configmake.h" +#include "files.h" +#include "fdstream.h" /* This one changes from version to version. */ #if VBOX_API_VERSION == 2002 @@ -8522,6 +8528,109 @@ static char *vboxStorageVolGetPath(virStorageVolPtr vol) { return ret; } +#if VBOX_API_VERSION == 4000 +static char * +vboxDomainScreenshot(virDomainPtr dom, virStreamPtr st, + unsigned int flags ATTRIBUTE_UNUSED) +{ + VBOX_OBJECT_CHECK(dom->conn, char *, NULL); + IConsole *console = NULL; + vboxIID iid = VBOX_IID_INITIALIZER; + IMachine *machine = NULL; + nsresult rc; + char *tmp; + int tmp_fd = -1; + + vboxIIDFromUUID(&iid, dom->uuid); + rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); + if (NS_FAILED(rc)) { + vboxError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + return NULL; + } + + if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX", LOCALSTATEDIR) < 0) { + virReportOOMError(); + return NULL; + } + + if ((tmp_fd = mkstemp(tmp)) == -1) { + virReportSystemError(errno, _("mkstemp(\"%s\") failed"), tmp); + VIR_FREE(tmp); + return NULL; + } + + + rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); + if (NS_SUCCEEDED(rc)) { + rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console); + if (NS_SUCCEEDED(rc) && console) { + IDisplay *display = NULL; + + console->vtbl->GetDisplay(console, &display); + + if (display) { + PRUint32 width, height, bitsPerPixel; + PRUint32 screenDataSize; + PRUint8 *screenData; + + rc = display->vtbl->GetScreenResolution(display, 0, + &width, &height, + &bitsPerPixel); + + if (NS_FAILED(rc) || !width || !height) { + vboxError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to get screen resolution")); + goto endjob; + } + + rc = display->vtbl->TakeScreenShotPNGToArray(display, 0, + width, height, + &screenDataSize, + &screenData); + if (NS_FAILED(rc)) { + vboxError(VIR_ERR_OPERATION_FAILED, "%s", + _("failed to take screenshot")); + goto endjob; + } + + if (safewrite(tmp_fd, (char *) screenData, + screenDataSize) < 0) { + virReportSystemError(errno, _("unable to write data " + "to '%s'"), tmp); + goto endjob; + } + + if (VIR_CLOSE(tmp_fd) < 0) { + virReportSystemError(errno, _("unable to close %s"), tmp); + goto endjob; + } + + if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY, true) < 0) { + vboxError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to open stream")); + goto endjob; + } + + ret = strdup("image/png; charset=binary"); + +endjob: + VIR_FREE(screenData); + VBOX_RELEASE(display); + } + VBOX_RELEASE(console); + } + VBOX_SESSION_CLOSE(); + } + + VIR_FORCE_CLOSE(tmp_fd); + VIR_FREE(tmp); + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} +#endif /* VBOX_API_VERSION == 4000 */ + /** * Function Tables */ @@ -8564,7 +8673,11 @@ virDriver NAME(Driver) = { vboxDomainSave, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ +#if VBOX_API_VERSION == 4000 + vboxDomainScreenshot, /* domainScreenshot */ +#else NULL, /* domainScreenshot */ +#endif vboxDomainSetVcpus, /* domainSetVcpus */ vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */ vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */ -- 1.7.4 From mcastrol at gmail.com Tue Apr 5 16:16:42 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Tue, 5 Apr 2011 18:16:42 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: <4D9B3288.6080700@redhat.com> References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B322D.9040309@redhat.com> <4D9B3288.6080700@redhat.com> Message-ID: Hellol I've downloaded the policycoreutils, and then I execute on the nfs clients: *radic at santacruz:~/discoguest/aplicaciones/virsh$ setsebool -P virt_use_nfs on setsebool: SELinux is disabled. * It's enough? I understand that it's not working, but I don't find good information at internet. Thank you. Marcela 2011/4/5 Michal Novotny > On 04/05/2011 05:15 PM, Eric Blake wrote: > > On 04/05/2011 09:09 AM, Michal Novotny wrote: > >> Hi Marcela, > >> I was investigating the log file and it seems like the image file cannot > >> be opened on the remote host. > > Are you using SELinux, and is your shared storage on NFS? If so, did > > you run 'setsebool -P virt_use_nfs on' to let the destination properly > > access the shared storage from NFS? > > > Eric, I'm not too familiar with SELinux. Do you think the > virFileOpenAs() would fail if the SELinux context won't be set properly? > > Michal > > -- > Michal Novotny , RHCE > Virtualization Team (xen userspace), Red Hat > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From minovotn at redhat.com Tue Apr 5 16:17:41 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 05 Apr 2011 18:17:41 +0200 Subject: [libvirt] Regression in allocating ports for serial/parallel devs In-Reply-To: <4D9B3FAB.8090205@redhat.com> References: <4D9B3FAB.8090205@redhat.com> Message-ID: <4D9B40A5.60407@redhat.com> On 04/05/2011 06:13 PM, Cole Robinson wrote: > Hi Michal, > > The following commit introduced a regression: > > http://libvirt.org/git/?p=libvirt.git;a=commit;h=79c3fe4d1681cd94598d2bd42e38a98f51cb645d > > Now, defining a guest with XML like > > > > > > Will allocate to all 3. The reason is that > target.port is never set to -1 unless the user specified some > XML. A simple fix is: > > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -3265,6 +3265,8 @@ virDomainChrDefParseXML(virCapsPtr caps, > return NULL; > } > > + def->target.port = -1; > + > type = virXMLPropString(node, "type"); > if (type == NULL) { > def->source.type = VIR_DOMAIN_CHR_TYPE_PTY; > > But that doesn't solve the problem for users who are building ChrDef's > by hand, like when converting between formats as xen and vmware drivers > do. I didn't look at those users so they may be safe, but the interface > should be improved. Maybe add a ChrDefNew function that sets the -1 default. > > Additionally we should add a qemuxml2xml test for this to prevent > against future regressions. > > Thanks, > Cole Hi Cole, do you think it's worth implementing the ChrDefNew besides the ChrDef which we already have? There's a regression testing but maybe it's not for qemuxml2xml test. Adding DV to the CC list for his opinion whether he has some better idea about this. Thanks, Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From minovotn at redhat.com Tue Apr 5 16:19:06 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 05 Apr 2011 18:19:06 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B322D.9040309@redhat.com> <4D9B3288.6080700@redhat.com> Message-ID: <4D9B40FA.50601@redhat.com> On 04/05/2011 06:16 PM, Marcela Castro Le?n wrote: > Hellol > I've downloaded the policycoreutils, and then I execute on the nfs > clients: > > *radic at santacruz:~/discoguest/aplicaciones/virsh$ setsebool -P > virt_use_nfs on > setsebool: SELinux is disabled. > * > > It's enough? I understand that it's not working, but I don't find good > information at internet. > > Thank you. > Marcela That's fine since you have the SELinux disabled and therefore it can't cause any issues. Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From crobinso at redhat.com Tue Apr 5 16:30:56 2011 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 05 Apr 2011 12:30:56 -0400 Subject: [libvirt] Regression in allocating ports for serial/parallel devs In-Reply-To: <4D9B40A5.60407@redhat.com> References: <4D9B3FAB.8090205@redhat.com> <4D9B40A5.60407@redhat.com> Message-ID: <4D9B43C0.6060003@redhat.com> On 04/05/2011 12:17 PM, Michal Novotny wrote: > On 04/05/2011 06:13 PM, Cole Robinson wrote: >> Hi Michal, >> >> The following commit introduced a regression: >> >> http://libvirt.org/git/?p=libvirt.git;a=commit;h=79c3fe4d1681cd94598d2bd42e38a98f51cb645d >> >> Now, defining a guest with XML like >> >> >> >> >> >> Will allocate to all 3. The reason is that >> target.port is never set to -1 unless the user specified some >> XML. A simple fix is: >> >> --- a/src/conf/domain_conf.c >> +++ b/src/conf/domain_conf.c >> @@ -3265,6 +3265,8 @@ virDomainChrDefParseXML(virCapsPtr caps, >> return NULL; >> } >> >> + def->target.port = -1; >> + >> type = virXMLPropString(node, "type"); >> if (type == NULL) { >> def->source.type = VIR_DOMAIN_CHR_TYPE_PTY; >> >> But that doesn't solve the problem for users who are building ChrDef's >> by hand, like when converting between formats as xen and vmware drivers >> do. I didn't look at those users so they may be safe, but the interface >> should be improved. Maybe add a ChrDefNew function that sets the -1 default. >> >> Additionally we should add a qemuxml2xml test for this to prevent >> against future regressions. >> >> Thanks, >> Cole > > Hi Cole, > do you think it's worth implementing the ChrDefNew besides the ChrDef > which we already have? > ChrDefNew would be a constructor function, that would return an allocated ChrDefPtr. In fact I'd argue we should have these constructors for every device type, some others definitely need it at the moment (like controller which uses a similar -1 default). > There's a regression testing but maybe it's not for qemuxml2xml test. > Not sure I understand this sentence, but qemuxml2xml test is for round trip XML testing, which is what is needed here. There is already a couple examples where the round trip XML is expected to change, see for example tests/qemuxml2xmltest.c tests/qemuxml2argvdata/qemuxml2argv-console-compat-auto.xml tests/qemuxml2xmloutdata/qemuxml2xmlout-console-compat-auto.xml Thanks, Cole From jesse.cook at eads-na-security.com Tue Apr 5 16:55:18 2011 From: jesse.cook at eads-na-security.com (Jesse J Cook) Date: Tue, 05 Apr 2011 11:55:18 -0500 Subject: [libvirt] [PATCH] Allow relative path for qemu backing file In-Reply-To: <4D9A48AB.2090504@redhat.com> References: <1301275814-25480-1-git-send-email-jesse.cook@eads-na-security.com> <4D9A48AB.2090504@redhat.com> Message-ID: <1302022518.30580.52.camel@localhost.localdomain> On Mon, 2011-04-04 at 16:39 -0600, Eric Blake wrote: > On 03/27/2011 07:30 PM, Jesse Cook wrote: > > This patch enables the relative backing file path support provided by > > qemu-img create. > > > > If a relative path is specified for the backing file, it is converted > > to an absolute path using the storage pool path. The absolute path is > > used to verify that the backing file exists. If the backing file exists, > > the relative path is allowed and will be provided to qemu-img create. > > > > This patch takes the place of a previous patch: > > http://www.redhat.com/archives/libvir-list/2011-March/msg00179.html > > --- > > src/storage/storage_backend.c | 18 +++++++++++++++++- > > 1 files changed, 17 insertions(+), 1 deletions(-) > > Sorry for not reviewing this in time for 0.9.0. No Problem. It took me a while to get around to the fix. > > @@ -686,7 +689,20 @@ virStorageBackendCreateQemuImg(virConnectPtr conn, > > vol->backingStore.format); > > return -1; > > } > > - if (access(vol->backingStore.path, R_OK) != 0) { > > + > > + /* Convert relative backing store paths to absolute paths for access > > + * validation. > > + */ > > + if ('/' != *(vol->backingStore.path)) { > > + virAsprintf(&absolutePath, "%s/%s", pool->def->target.path, > > + vol->backingStore.path); > > + > > + } else { > > + virAsprintf(&absolutePath, "%s", vol->backingStore.path); > > strdup is more efficient here, and avoiding malloc in the first place > even more so. > > > + } > > + accessRetCode = access(absolutePath, R_OK); > > This could segfault on OOM. > > > + VIR_FREE(absolutePath); I believe there needs to be a NULL check here or absolute paths and virAsprintf errors will segfault. I can patch if you don't beat me to it. > > + if (accessRetCode != 0) { > > virReportSystemError(errno, > > _("inaccessible backing store volume %s"), > > vol->backingStore.path); > > ACK with nits fixed; so here's what I squashed in before pushing. I > also updated AUTHORS to pass 'make syntax-check'; feel free to let me > know off-list if you prefer any alternate spelling there (especially > since you sent v1 and v2 under different email aliases). > > diff --git i/src/storage/storage_backend.c w/src/storage/storage_backend.c > index 5f5565b..8af2878 100644 > --- i/src/storage/storage_backend.c > +++ w/src/storage/storage_backend.c > @@ -693,7 +693,6 @@ virStorageBackendCreateQemuImg(virConnectPtr conn, > > if (vol->backingStore.path) { > int accessRetCode = -1; > - > char *absolutePath = NULL; > > /* XXX: Not strictly required: qemu-img has an option a different > @@ -719,14 +718,14 @@ virStorageBackendCreateQemuImg(virConnectPtr conn, > /* Convert relative backing store paths to absolute paths for > access > * validation. > */ > - if ('/' != *(vol->backingStore.path)) { > + if ('/' != *(vol->backingStore.path) && > virAsprintf(&absolutePath, "%s/%s", pool->def->target.path, > - vol->backingStore.path); > - > - } else { > - virAsprintf(&absolutePath, "%s", vol->backingStore.path); > + vol->backingStore.path) < 0) { > + virReportOOMError(); > + return -1; > } > - accessRetCode = access(absolutePath, R_OK); > + accessRetCode = access(absolutePath ? absolutePath > + : vol->backingStore.path, R_OK); > VIR_FREE(absolutePath); > if (accessRetCode != 0) { > virReportSystemError(errno, > > -- Jesse Cook Research Scientist EADS NA Defense Security & Systems Solutions, Inc. (DS3) Email: jesse.cook at eads-na-security.com From eblake at redhat.com Tue Apr 5 16:55:40 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 10:55:40 -0600 Subject: [libvirt] [PATCH v2 6/8] virFDStream: Add option for delete file after it's opening In-Reply-To: <1302019980-14957-7-git-send-email-mprivozn@redhat.com> References: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> <1302019980-14957-7-git-send-email-mprivozn@redhat.com> Message-ID: <4D9B498B.7030309@redhat.com> On 04/05/2011 10:12 AM, Michal Privoznik wrote: > This is needed if we want to transfer a temporary file. If the > transfer is done with iohelper, we might run into a race condition, > where we unlink() file before iohelper is executed. > > * src/fdstream.c, src/fdstream.h, > src/util/iohelper.c: Add new option > * src/lxc/lxc_driver.c, src/qemu/qemu_driver.c, > src/storage/storage_driver.c, src/uml/uml_driver.c, > src/xen/xen_driver.c: Expand existing function calls I'm not convinced about this commit. We should instead be fixing iohelper to receive its file by fd inheritance, so that it doesn't have to open() in the first place. Then you don't need iohelper to worry about unlink(). -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Tue Apr 5 17:00:21 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 11:00:21 -0600 Subject: [libvirt] [PATCH] Allow relative path for qemu backing file In-Reply-To: <1302022518.30580.52.camel@localhost.localdomain> References: <1301275814-25480-1-git-send-email-jesse.cook@eads-na-security.com> <4D9A48AB.2090504@redhat.com> <1302022518.30580.52.camel@localhost.localdomain> Message-ID: <4D9B4AA5.6000303@redhat.com> On 04/05/2011 10:55 AM, Jesse J Cook wrote: >>> + if ('/' != *(vol->backingStore.path)) { >>> + virAsprintf(&absolutePath, "%s/%s", pool->def->target.path, >>> + vol->backingStore.path); >>> + >>> + } else { >>> + virAsprintf(&absolutePath, "%s", vol->backingStore.path); >> >> strdup is more efficient here, and avoiding malloc in the first place >> even more so. >> >>> + } >>> + accessRetCode = access(absolutePath, R_OK); >> >> This could segfault on OOM. >> >>> + VIR_FREE(absolutePath); > > I believe there needs to be a NULL check here or absolute paths and > virAsprintf errors will segfault. I can patch if you don't beat me to > it. How so? absolutePath was initialized as NULL; is only ever set to non-null by a successful virAsprintf, and VIR_FREE works correctly (no-op) on a NULL argument. Put another way, are you missing that VIR_FREE already has an embedded NULL check? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Tue Apr 5 17:08:53 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 5 Apr 2011 11:08:53 -0600 Subject: [libvirt] [PATCH] libxl: avoid compiler warning Message-ID: <1302023333-17185-1-git-send-email-eblake@redhat.com> cc1: warnings being treated as errors libxl/libxl_driver.c: In function 'libxlDomainSetVcpusFlags': libxl/libxl_driver.c:1570:14: error: cast from function call of type 'double' to non-matching type 'unsigned int' [-Wbad-function-cast] libxl/libxl_driver.c:1578:15: error: cast from function call of type 'double' to non-matching type 'unsigned int' [-Wbad-function-cast] This was the only use of floor() and ceil(), and floating-point is overkill for power-of-two manipulations. * src/libxl/libxl_driver.c (libxlDomainSetVcpusFlags): Avoid -lm for trivial computations. --- Pushing under the build-breaker rule. src/libxl/libxl_driver.c | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 75f99c1..8cc4469 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1567,15 +1567,14 @@ libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, if (!(def = virDomainObjGetPersistentDef(driver->caps, vm))) goto cleanup; - maplen = (unsigned int) ceil((double) nvcpus / 8); + maplen = VIR_CPU_MAPLEN(nvcpus); if (VIR_ALLOC_N(bitmask, maplen) < 0) { virReportOOMError(); goto cleanup; } - memset(bitmask, 0, maplen); for (i = 0; i < nvcpus; ++i) { - pos = (unsigned int) floor((double) i / 8); + pos = i / 8; bitmask[pos] |= 1 << (i % 8); } -- 1.7.4 From jesse.cook at eads-na-security.com Tue Apr 5 17:34:54 2011 From: jesse.cook at eads-na-security.com (Jesse J Cook) Date: Tue, 05 Apr 2011 12:34:54 -0500 Subject: [libvirt] [PATCH] Allow relative path for qemu backing file In-Reply-To: <4D9B4AA5.6000303@redhat.com> References: <1301275814-25480-1-git-send-email-jesse.cook@eads-na-security.com> <4D9A48AB.2090504@redhat.com> <1302022518.30580.52.camel@localhost.localdomain> <4D9B4AA5.6000303@redhat.com> Message-ID: <1302024894.30580.65.camel@localhost.localdomain> On Tue, 2011-04-05 at 11:00 -0600, Eric Blake wrote: > On 04/05/2011 10:55 AM, Jesse J Cook wrote: > >>> + if ('/' != *(vol->backingStore.path)) { > >>> + virAsprintf(&absolutePath, "%s/%s", pool->def->target.path, > >>> + vol->backingStore.path); > >>> + > >>> + } else { > >>> + virAsprintf(&absolutePath, "%s", vol->backingStore.path); > >> > >> strdup is more efficient here, and avoiding malloc in the first place > >> even more so. > >> > >>> + } > >>> + accessRetCode = access(absolutePath, R_OK); > >> > >> This could segfault on OOM. > >> > >>> + VIR_FREE(absolutePath); > > > > I believe there needs to be a NULL check here or absolute paths and > > virAsprintf errors will segfault. I can patch if you don't beat me to > > it. Disregard. The code is correct. > How so? absolutePath was initialized as NULL; is only ever set to > non-null by a successful virAsprintf, and VIR_FREE works correctly > (no-op) on a NULL argument. Put another way, are you missing that > VIR_FREE already has an embedded NULL check? > Thank you for resolving my fundamental misunderstanding regarding the behaviour of free(3). I did not realize free((void*)0) is safe. -- Jesse Cook Research Scientist EADS NA Defense Security & Systems Solutions, Inc. (DS3) 1476 N. Green Mount Rd O'Fallon, Illinois 62269 Office: 618.206.4032 x436 Email: jesse.cook at eads-na-security.com http://www.eads-na-security.com From minovotn at redhat.com Tue Apr 5 18:04:51 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 05 Apr 2011 20:04:51 +0200 Subject: [libvirt] [libvirt-php] API to add/remove disk to/from domain In-Reply-To: References: Message-ID: <4D9B59C3.2000203@redhat.com> Hi Conor, I've implemented 2 new API functions to easily add and remove disks from the guests. If you're interested please clone/pull the latest libvirt-php repository from libvirt.org website. The commit adding this support can be found at: http://libvirt.org/git/?p=libvirt-php.git;a=commit;h=d9996ba707917115843df8f82ef0e29198f66b77 Hope this helps, Michal On 04/01/2011 11:11 AM, Conor Murphy wrote: > Hi, > > How do I add/remove a disk to a domain using the libvirt-php API? > > Thanks, > Conor > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From jdenemar at redhat.com Tue Apr 5 19:46:09 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 5 Apr 2011 21:46:09 +0200 Subject: [libvirt] [PATCH] qemu: Support for overriding NPROC limit In-Reply-To: <4D9B3500.4080302@redhat.com> References: <4D9B3500.4080302@redhat.com> Message-ID: <20110405194609.GE7195@orkuz.home> On Tue, Apr 05, 2011 at 09:28:00 -0600, Eric Blake wrote: > On 04/05/2011 08:09 AM, Jiri Denemark wrote: > > This patch adds max_processes option to qemu.conf which can be used to > > override system default limit on number of processes that are allowed to > > be running for qemu user. > > --- > > src/qemu/libvirtd_qemu.aug | 3 +++ > > src/qemu/qemu.conf | 7 +++++++ > > src/qemu/qemu_conf.c | 4 ++++ > > src/qemu/qemu_conf.h | 2 ++ > > src/qemu/qemu_process.c | 24 ++++++++++++++++++++++++ > > src/qemu/test_libvirtd_qemu.aug | 4 ++++ > > 6 files changed, 44 insertions(+), 0 deletions(-) > > @@ -1821,6 +1842,9 @@ static int qemuProcessHook(void *data) > > { > > struct qemuProcessHookData *h = data; > > > > + if (qemuProcessLimits(h->driver) < 0) > > + return -1; > > Which UID is in effect at this point? While setrlimit() adjusts an > inherited value, I'm a bit worried that tracks different limits per uid, > and if the call is made while the real uid is root instead of qemu, then > we might be affecting the wrong limit. Does this call need to be > delayed until after the virSecurityManagerSetProcessLabel, or after we > are sure that we have changed identities? Actually it's important that we call setrlimit() before dropping root privileges since only such process can increase the limit. The NPROC limit is pretty confusing since it logically doesn't fit in setrlimit and by it gets unnatural behavior as a result of it being set via setrlimit. It only affects the limit seen by current process which will soon be executing qemu code. Jirka From eblake at redhat.com Tue Apr 5 20:12:03 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 14:12:03 -0600 Subject: [libvirt] [PATCH] qemu: Support for overriding NPROC limit In-Reply-To: <20110405194609.GE7195@orkuz.home> References: <4D9B3500.4080302@redhat.com> <20110405194609.GE7195@orkuz.home> Message-ID: <4D9B7793.3040809@redhat.com> On 04/05/2011 01:46 PM, Jiri Denemark wrote: > On Tue, Apr 05, 2011 at 09:28:00 -0600, Eric Blake wrote: >> On 04/05/2011 08:09 AM, Jiri Denemark wrote: >>> This patch adds max_processes option to qemu.conf which can be used to >>> override system default limit on number of processes that are allowed to >>> be running for qemu user. > > Actually it's important that we call setrlimit() before dropping root > privileges since only such process can increase the limit. Makes sense. > > The NPROC limit is pretty confusing since it logically doesn't fit in > setrlimit and by it gets unnatural behavior as a result of it being set via > setrlimit. It only affects the limit seen by current process which will soon > be executing qemu code. Yeah, there's no real way to confine the absolute number of processes owned by a single uid using just process inheritance; setrlimit only affects the number of processes that can be forked within a given hierarchy. At any rate, this patch is certainly better than what was previously available, I didn't see anything wrong with it, and you answered my question, so: ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From serge.hallyn at canonical.com Tue Apr 5 21:14:17 2011 From: serge.hallyn at canonical.com (Serge Hallyn) Date: Tue, 5 Apr 2011 16:14:17 -0500 Subject: [libvirt] [PATCH 1/1] Change locking for udev monitor and callbacks Message-ID: <20110405211417.GA10000@hallyn.com> We're seeing bugs apparently resulting from thread unsafety of libpciaccess, such as https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/726099 To prevent those, as suggested by danpb on irc, move the nodeDeviceLock(driverState) higher into the callers. In particular: udevDeviceMonitorStartup should hold the lock while calling udevEnumerateDevices(), and udevEventHandleCallback should hold it over its entire execution. It's not clear to me whether it is ok to hold the nodeDeviceLock while taking the virNodeDeviceObjLock(dev) on a device. If not, then the lock will need to be dropped around the calling of udevSetupSystemDev(), and udevAddOneDevice() may not actually be safe to call from higher layers with the driverstate lock held. libvirt 0.8.8 with this patch on it seems to work fine for me. Assuming it looks ok and I haven't done anything obviously dumb, I'll ask the bug submitters to try this patch. Signed-off-by: Serge Hallyn --- src/node_device/node_device_udev.c | 21 +++++++++------------ 1 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index 372f1d1..2139ef3 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -1202,7 +1202,6 @@ static int udevRemoveOneDevice(struct udev_device *device) int ret = 0; name = udev_device_get_syspath(device); - nodeDeviceLock(driverState); dev = virNodeDeviceFindBySysfsPath(&driverState->devs, name); if (dev != NULL) { @@ -1214,7 +1213,6 @@ static int udevRemoveOneDevice(struct udev_device *device) name); ret = -1; } - nodeDeviceUnlock(driverState); return ret; } @@ -1316,9 +1314,7 @@ static int udevAddOneDevice(struct udev_device *device) /* If this is a device change, the old definition will be freed * and the current definition will take its place. */ - nodeDeviceLock(driverState); dev = virNodeDeviceAssignDef(&driverState->devs, def); - nodeDeviceUnlock(driverState); if (dev == NULL) { VIR_ERROR(_("Failed to create device for '%s'"), def->name); @@ -1442,6 +1438,7 @@ static void udevEventHandleCallback(int watch ATTRIBUTE_UNUSED, const char *action = NULL; int udev_fd = -1; + nodeDeviceLock(driverState); udev_fd = udev_monitor_get_fd(udev_monitor); if (fd != udev_fd) { VIR_ERROR(_("File descriptor returned by udev %d does not " @@ -1470,6 +1467,7 @@ static void udevEventHandleCallback(int watch ATTRIBUTE_UNUSED, out: udev_device_unref(device); + nodeDeviceUnlock(driverState); return; } @@ -1647,10 +1645,9 @@ static int udevDeviceMonitorStartup(int privileged) priv->udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); if (priv->udev_monitor == NULL) { VIR_FREE(priv); - nodeDeviceUnlock(driverState); VIR_ERROR0(_("udev_monitor_new_from_netlink returned NULL")); ret = -1; - goto out; + goto out_unlock; } udev_monitor_enable_receiving(priv->udev_monitor); @@ -1670,26 +1667,26 @@ static int udevDeviceMonitorStartup(int privileged) VIR_EVENT_HANDLE_READABLE, udevEventHandleCallback, NULL, NULL); if (priv->watch == -1) { - nodeDeviceUnlock(driverState); ret = -1; - goto out; + goto out_unlock; } - nodeDeviceUnlock(driverState); - /* Create a fictional 'computer' device to root the device tree. */ if (udevSetupSystemDev() != 0) { ret = -1; - goto out; + goto out_unlock; } /* Populate with known devices */ if (udevEnumerateDevices(udev) != 0) { ret = -1; - goto out; + goto out_unlock; } +out_unlock: + nodeDeviceUnlock(driverState); + out: if (ret == -1) { udevDeviceMonitorShutdown(); -- 1.7.4.1 From eblake at redhat.com Tue Apr 5 22:51:38 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 5 Apr 2011 16:51:38 -0600 Subject: [libvirt] [PATCH] build: fix gitignore sorting Message-ID: <1302043898-2154-1-git-send-email-eblake@redhat.com> Make it so we don't have to 'git add -f' particular files like po/POTFILES.in all the time (tested by fixing one of our special-case files as part of the patch). * .gnulib: Update to latest. * bootstrap: Resync from coreutils. * .gitignore: Sort whitelist entries correctly, including ignoring files rather than directories. * m4/virt-compile-warnings.m4: Convert tabs to space. --- * .gnulib dec3475...f796520 (7): > bootstrap: compute gnulib_extra_files after updating build_aux > bootstrap: preserve git whitelist item sorting > maint.mk: Don't trigger sc_space_tab check. > areadlink, areadlinkat: rewrite in terms of careadlinkat > autoupdate > wmemchr, wcschr, wcsrchr, wcspbrk, wcsstr: Avoid errors in C++ mode. > wcpcpy, wcpncpy: Ensure declaration on glibc >= 2.13 systems. I'm also trying to patch 'man gitignore' with things I've learned from this exercise: http://marc.info/?t=130203248100003&r=1&w=2 .gitignore | 12 +++++----- .gnulib | 2 +- bootstrap | 46 +++++++++++++++++++++++++++++-------------- m4/virt-compile-warnings.m4 | 8 +++--- 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 24c96b5..35dbdde 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,3 @@ -!/m4/virt-*.m4 -!/po/*.po -!/po/POTFILES.in -!/po/libvirt.pot *#*# *.#*# *.a @@ -46,11 +42,11 @@ /libvirt.spec /ltconfig /ltmain.sh -/m4/ +/m4/* /maint.mk /mingw32-libvirt.spec /mkinstalldirs -/po/ +/po/* /proxy/ /src/libvirt_iohelper /tests/*.log @@ -67,3 +63,7 @@ results.log stamp-h stamp-h.in stamp-h1 +!/m4/virt-*.m4 +!/po/*.po +!/po/POTFILES.in +!/po/libvirt.pot diff --git a/.gnulib b/.gnulib index dec3475..f796520 160000 --- a/.gnulib +++ b/.gnulib @@ -1 +1 @@ -Subproject commit dec3475763be252103922a887920012eeb32dc26 +Subproject commit f79652003534e496bca1e49922ca521f12ca8051 diff --git a/bootstrap b/bootstrap index f004ad3..7cbb5dc 100755 --- a/bootstrap +++ b/bootstrap @@ -1,6 +1,6 @@ #! /bin/sh # Print a version string. -scriptversion=2011-03-03.12; # UTC +scriptversion=2011-04-05.18; # UTC # Bootstrap this package from checked-out sources. @@ -130,18 +130,7 @@ source_base=lib m4_base=m4 doc_base=doc tests_base=tests - -# Extra files from gnulib, which override files from other sources. -gnulib_extra_files=" - $build_aux/install-sh - $build_aux/missing - $build_aux/mdate-sh - $build_aux/texinfo.tex - $build_aux/depcomp - $build_aux/config.guess - $build_aux/config.sub - doc/INSTALL -" +gnulib_extra_files='' # Additional gnulib-tool options to use. Use "\newline" to break lines. gnulib_tool_option_extras= @@ -229,6 +218,18 @@ case "$0" in *) test -r "$0.conf" && . ./"$0.conf" ;; esac +# Extra files from gnulib, which override files from other sources. +test -z "${gnulib_extra_files}" && \ + gnulib_extra_files=" + $build_aux/install-sh + $build_aux/missing + $build_aux/mdate-sh + $build_aux/texinfo.tex + $build_aux/depcomp + $build_aux/config.guess + $build_aux/config.sub + doc/INSTALL +" if test "$vc_ignore" = auto; then vc_ignore= @@ -278,14 +279,29 @@ if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then exit 1 fi +# Ensure that lines starting with ! sort last, per gitignore conventions +# for whitelisting exceptions after a more generic blacklist pattern. +sort_patterns() { + sort -u "$@" | sed '/^!/ { + H + d + } + $ { + P + x + s/^\n// + }' +} + # If $STR is not already on a line by itself in $FILE, insert it, # sorting the new contents of the file and replacing $FILE with the result. insert_sorted_if_absent() { file=$1 str=$2 test -f $file || touch $file - echo "$str" | sort -u - $file | cmp - $file > /dev/null \ - || echo "$str" | sort -u - $file -o $file \ + echo "$str" | sort_patterns - $file | cmp - $file > /dev/null \ + || { echo "$str" | sort_patterns - $file > $file.bak \ + && mv $file.bak $file; } \ || exit 1 } diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4 index 819da8f..3ca0346 100644 --- a/m4/virt-compile-warnings.m4 +++ b/m4/virt-compile-warnings.m4 @@ -15,7 +15,7 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ case "$enable_compile_warnings" in no) try_compiler_flags="" - ;; + ;; yes|minimum|maximum|error) # List of warnings that are not relevant / wanted @@ -117,10 +117,10 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ then gl_WARN_ADD([-Werror]) fi - ;; + ;; *) - AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings) - ;; + AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings) + ;; esac WARN_LDFLAGS=$WARN_CFLAGS -- 1.7.4 From flameeyes at gmail.com Tue Apr 5 23:05:29 2011 From: flameeyes at gmail.com (Diego Elio =?ISO-8859-1?Q?Petten=F2?=) Date: Wed, 06 Apr 2011 01:05:29 +0200 Subject: [libvirt] [PATCH] qemu: Always reserves slot 0x02 for primary VGA. In-Reply-To: <1302011398-25541-1-git-send-email-jyang@redhat.com> References: <1302011398-25541-1-git-send-email-jyang@redhat.com> Message-ID: <1302044729.2330.48.camel@raven.home.flameeyes.eu> Il giorno mar, 05/04/2011 alle 21.49 +0800, Osier Yang ha scritto: > > This fix is to reserve slot 0x02 for primary VGA even if there > is no "video" specified in domain XML to avoid the problem. Could be related (and suggest the need for some further look into it), a Gentoo user reported a slot collision for virtio-blk as well: https://bugs.gentoo.org/show_bug.cgi?id=362197 -- Diego Elio Petten? ? Flameeyes http://blog.flameeyes.eu/ From eblake at redhat.com Tue Apr 5 23:27:17 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 05 Apr 2011 17:27:17 -0600 Subject: [libvirt] [PATCH 1/3] Don't use virSetCloseExec in event loop on Win32 In-Reply-To: <4D9B35C5.7050908@redhat.com> References: <1302015789-488-1-git-send-email-berrange@redhat.com> <4D9B35C5.7050908@redhat.com> Message-ID: <4D9BA555.1010302@redhat.com> On 04/05/2011 09:31 AM, Eric Blake wrote: > On 04/05/2011 09:03 AM, Daniel P. Berrange wrote: >> The virSetCloseExec API returns -1 on Win32 since it cannot >> possibly work. Avoid calling it from the event loop since >> is not required in this case. > > Well, it _could_ work if gnulib would relax a couple modules to LGPLv2+ > instead of their current LGPLv3+. > > Meanwhile, mingw _does_ let us create a pipe already non-inheritible > (that is, pipe2(fds, O_CLOEXEC) _does_ work on mingw as an LGPLv2+ > gnulib solution). > > If you don't mind, I'd rather conditionally NAK this patch and try the > pipe2 approach instead, since the added in-function #ifdefs detract from > readability. Like so, except that this is pending a gnulib license change first (I was wrong, gnulib's pipe2 is still LGPLv3+ at the moment). diff --git i/bootstrap.conf w/bootstrap.conf index 11d2199..95136ac 100644 --- i/bootstrap.conf +++ w/bootstrap.conf @@ -54,6 +54,7 @@ nonblocking perror physmem pipe-posix +pipe2 poll posix-shell pthread diff --git i/src/util/event_poll.c w/src/util/event_poll.c index 91000e2..cd1ff4a 100644 --- i/src/util/event_poll.c +++ w/src/util/event_poll.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "threads.h" #include "logging.h" @@ -657,11 +658,7 @@ int virEventPollInit(void) return -1; } - if (pipe(eventLoop.wakeupfd) < 0 || - virSetNonBlock(eventLoop.wakeupfd[0]) < 0 || - virSetNonBlock(eventLoop.wakeupfd[1]) < 0 || - virSetCloseExec(eventLoop.wakeupfd[0]) < 0 || - virSetCloseExec(eventLoop.wakeupfd[1]) < 0) { + if (pipe2(eventLoop.wakeupfd, O_CLOEXEC | O_NONBLOCK) < 0) { virReportSystemError(errno, "%s", _("Unable to setup wakeup pipe")); return -1; -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From james.barkley at gmail.com Tue Apr 5 23:37:20 2011 From: james.barkley at gmail.com (James Barkley) Date: Tue, 5 Apr 2011 19:37:20 -0400 Subject: [libvirt] ESX network functionality Message-ID: Greetings: I've added code to the ESX driver to support some basic network functionality. I'm pretty new to this list, so please tell me how to proceed with code review and patch submission (yes I've read the contributor guidelines on the wiki). It seems like people are emailing a patch file for every file they've changed, each in separate emails with [1 of N] in the subject, is that right? Or is it better to paste in code, get some feedback, and eventually attach the patch to the bug tracker item? I've updated the code for the ESX driver to be able to handle the following functions : - virNetworkLookupByName - virConnectNumOfDefinedNetworks - virConnectNumOfNetworks - virConnectListNetworks I basically mapped the VMware Managed Object Reference for networks into a few data structures and added the following functions to the internal driver API: - esxNumOfNetworks - esxListNetworks - esxNumOfDefinedNetworks - esxNetworkLookupByName - esxVI_LookupNetworkList - esxVI_LookupNetworkByName These functions were modeled after existing functions from the domain and storage libraries. The following files were touched: - esx_network_driver.c - esx_vi.c - esx_vi.h - esx_vi_generator.input thanks, -jb -------------- next part -------------- An HTML attachment was scrubbed... URL: From n-horiguchi at ah.jp.nec.com Wed Apr 6 00:44:49 2011 From: n-horiguchi at ah.jp.nec.com (Naoya Horiguchi) Date: Wed, 6 Apr 2011 09:44:49 +0900 Subject: [libvirt] [PATCH 2/2] qemu: extend logging to record guest configuration events In-Reply-To: <20110404145526.GE13616@redhat.com> References: <1301300027-5858-1-git-send-email-n-horiguchi@ah.jp.nec.com> <1301300027-5858-3-git-send-email-n-horiguchi@ah.jp.nec.com> <20110404145526.GE13616@redhat.com> Message-ID: <20110406004448.GB2901@spritzera.linux.bs1.fc.nec.co.jp> Hi, On Mon, Apr 04, 2011 at 03:55:26PM +0100, Daniel P. Berrange wrote: > On Mon, Mar 28, 2011 at 05:13:47PM +0900, Naoya Horiguchi wrote: > > The following events can be logged onto /var/log/libvirt/qemu/.log: > > > > starting/shutting down/suspending/resuming/migrating domains > > changing the amount of memory > > changing the number of VCPUs > > inserting/ejecting a media into/from CDROM/Floppy devices > > attaching/detaching PCI/SCSI/USB devices (including NICs and disks.) > > > > This patch generalizes qemudLog*() introduced in commit 93bc093ac > > to handle the whole range of qemu driver's events. > > > > This is useful for the same reason as explainged in the previous patch. > > I think we need to think about the question of logging > in a more thorough way. > > - libvirt.c: Logs invocation of every API call > - qemu/driver.c/qemu_audit.c: Logs major lifecycle changes & > any config change that is related host resources > - virterror.c: Logs any API call that results in an error > - qemu_driver.c: Logs a set of lifecycle/config changes > (your previous patch 1/2) at VIR_INFO > - qemu_driver.c: Logs a different set of lifecycle/config > changes in /var/log/libvirt/qemu/.loog Thank you for detailed explanation. > I don't think the latter two are particularly great because > they are only cover a fraction of the API calls in the QEMU > driver. libvirt.c has full logging cover, but it only covers > API calls, it doesn't indicate whether it was successful or > failed. I see. > For SystemTAP, we likely want to add probes to libvirt.c > which will log initial parameters, and the return values. > Our SystemTAP probe macros also generate log statements. > > A further complication is that /var/log/libvirt/qemu/$NAME.log > is intended for QEMU's stderr output. The only time that > libvirtd currently writes to it, is before QEMU starts and after > it has shutdown. OK. > This new patch means that libvirtd writes to it while QEMU is > running, which is not really safe because you can now end up > with 2 proceses writing to the same file at once. The log > messages may well get interleaved/corrupted by each other. > I don't think that is good for something that wants to be > used as a formal record of operations on a VM. > > I think that in each driver we only really want to have to > insert one set of formal "operation logging" calls. Since > we already have the audit APIs present, I think we could try > to make use of that to generate a record of operations against > a VM in some way. I didn't care about audit logging because it's not used in RHEL6.0. I tried this logging mechanism and made sure that this logging recorded enough information about operational events in /var/log/libvirt/libvirtd.log. This feature meets our demand, so I'll drop this patch. Thanks, Naoya From jyang at redhat.com Wed Apr 6 00:50:36 2011 From: jyang at redhat.com (Osier Yang) Date: Wed, 06 Apr 2011 08:50:36 +0800 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <4D9B2D45.4020606@redhat.com> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> <4D9B2D45.4020606@redhat.com> Message-ID: <4D9BB8DC.8040302@redhat.com> ? 2011?04?05? 22:55, Eric Blake ??: > On 04/05/2011 07:20 AM, Jiri Denemark wrote: >> On Tue, Apr 05, 2011 at 14:47:22 +0800, Osier Yang wrote: >>> Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to >>> restore the domain from managedsave'ed image if it exists (by >>> invoking "qemuDomainObjRestore"), but it unlinks the image even >>> if restoring fails, which causes data loss. >>> >>> However, I'm not sure if it's the very correct way to fix it, >>> if restoring fails, and we didn't remove the image, it will >>> trys to restore from the image again next time, if that's >>> not the user expected (e.g. the user made quite many changes >>> on the guest), then it's a new problem. >> >> I think this patch is risky. You should either remove the state on error >> (which is the current state) or fail domain start if managed state is present >> but resuming from it fails. If you do something in the middle (your patch) you >> will certainly end up corrupting domain's disks. > > What's more, I think we should consider removing the saved-state file on > success for 'virsh restore file' - once a state has been restored, the > guest is running and has likely modified its disks, which means that the > saved (memory) state is no longer consistent with the new disk state, > and a second restore of the saved file is asking for a different type of > data corruption. Hmm, I didn't think of this (data corruption), v3 comes. > > That is, I think: > > virsh save dom file > virsh restore file > > should leave file intact if and only if the restore failed, and: > > virsh managedsave dom > virsh start > > should either fail but leave the (hidden) state file intact, or succeed > and remove the state file. We have virsh managedsave-remove to properly > delete the state file if the user determines that they want a fresh > start rather than retrying the (hidden) state file. > From dwu at redhat.com Wed Apr 6 04:13:10 2011 From: dwu at redhat.com (Mark Wu) Date: Wed, 06 Apr 2011 12:13:10 +0800 Subject: [libvirt] qemu: Add timeout for monitor to avoid virsh getting stuck when monitor gets die. Message-ID: <4D9BE856.2090909@redhat.com> Hello Guys, When the qemu process becomes hung, virsh will get stuck on the hung guest and can't move forward. It can be reproduced by the following steps: 1. setup a virt guest with qemu-kvm, and start it 2. stop qemu process with following: kill -STOP `ps aux | grep qemu | grep -v grep | awk '{print $2}'` 3. run the following command: virsh list I think we can add a timeout for qemu monitor to resolve this problem: using virCondWaitUntil instead of virCondWait in qemuMonitorSend. What's your opinions? Thanks! -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: libvirt-qemu-monitor-timeout.patch URL: From dwu at redhat.com Wed Apr 6 04:15:38 2011 From: dwu at redhat.com (Mark Wu) Date: Wed, 06 Apr 2011 12:15:38 +0800 Subject: [libvirt] qemu: Add timeout for monitor to avoid virsh getting stuck when monitor gets die. Message-ID: <4D9BE8EA.7020001@redhat.com> Hello Guys, When the qemu process becomes hung, virsh will get stuck on the hung guest and can't move forward. It can be reproduced by the following steps: 1. setup a virt guest with qemu-kvm, and start it 2. stop qemu process with following: kill -STOP `ps aux | grep qemu | grep -v grep | awk '{print $2}'` 3. run the following command: virsh list I think we can add a timeout for qemu monitor to resolve this problem: using virCondWaitUntil instead of virCondWait in qemuMonitorSend. What's your opinions? Thanks! -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: libvirt-qemu-monitor-timeout.patch URL: From dwu at redhat.com Wed Apr 6 04:26:13 2011 From: dwu at redhat.com (Mark Wu) Date: Wed, 06 Apr 2011 12:26:13 +0800 Subject: [libvirt] qemu: Add timeout for monitor to avoid virsh getting stuck when monitor gets die. In-Reply-To: <4D9BE8EA.7020001@redhat.com> References: <4D9BE8EA.7020001@redhat.com> Message-ID: <4D9BEB65.4050705@redhat.com> Sorry for duplicated message. On 04/06/2011 12:15 PM, Mark Wu wrote: > Hello Guys, > > When the qemu process becomes hung, virsh will get stuck on the hung > guest and can't move forward. It can be reproduced by the following > steps: > > 1. setup a virt guest with qemu-kvm, and start it > 2. stop qemu process with following: > kill -STOP `ps aux | grep qemu | grep -v grep | awk '{print $2}'` > 3. run the following command: > virsh list > > I think we can add a timeout for qemu monitor to resolve this problem: > using virCondWaitUntil instead of virCondWait in qemuMonitorSend. > What's your opinions? > Thanks! > > > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list -------------- next part -------------- An HTML attachment was scrubbed... URL: From jyang at redhat.com Wed Apr 6 06:17:13 2011 From: jyang at redhat.com (Osier Yang) Date: Wed, 6 Apr 2011 14:17:13 +0800 Subject: [libvirt] [PATCH v3 1/2] qemu: Resolve data loss and data corruption of domain restoring. Message-ID: <1302070634-2597-1-git-send-email-jyang@redhat.com> Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to restore the domain from managedsave'ed image if it exists (by invoking "qemuDomainObjRestore"), but it unlinks the image even if restoring fails, which causes data loss. (This problem exists for "virsh managedsave dom; virsh start dom"). And keeping the saved state will cause data corruption if the user modified his disks and restore the domain second time from the saved state. (Problem exists for "virsh save dom; virsh restore dom"). The fix is to: * Don't unlink()s the managed saved state if the restoring fails. * Remove the saved state if restoring succeeded. --- src/qemu/qemu_driver.c | 17 ++++++++++++----- 1 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 48fe266..a618df4 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3171,6 +3171,9 @@ qemuDomainRestore(virConnectPtr conn, vm = NULL; } + if ((ret == 0) && (unlink(path) < 0)) + VIR_WARN("Failed to remove the saved state %s", path); + cleanup: virDomainDefFree(def); VIR_FORCE_CLOSE(fd); @@ -3423,18 +3426,22 @@ static int qemudDomainObjStart(virConnectPtr conn, /* * If there is a managed saved state restore it instead of starting - * from scratch. In any case the old state is removed. + * from scratch. */ managed_save = qemuDomainManagedSavePath(driver, vm); if ((managed_save) && (virFileExists(managed_save))) { ret = qemuDomainObjRestore(conn, driver, vm, managed_save); - if (unlink(managed_save) < 0) { - VIR_WARN("Failed to remove the managed state %s", managed_save); + if (ret == 0) { + if (unlink(managed_save) < 0) + VIR_WARN("Failed to remove the managed state %s", managed_save); + } else { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to restore from the managed state %s"), + managed_save); } - if (ret == 0) - goto cleanup; + goto cleanup; } ret = qemuProcessStart(conn, driver, vm, NULL, start_paused, -1, NULL, -- 1.7.4 From jyang at redhat.com Wed Apr 6 06:17:14 2011 From: jyang at redhat.com (Osier Yang) Date: Wed, 6 Apr 2011 14:17:14 +0800 Subject: [libvirt] [PATCH 2/2] doc: Update doc for restoring in virsh manual In-Reply-To: <1302070634-2597-1-git-send-email-jyang@redhat.com> References: <1302070634-2597-1-git-send-email-jyang@redhat.com> Message-ID: <1302070634-2597-2-git-send-email-jyang@redhat.com> --- tools/virsh.pod | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/tools/virsh.pod b/tools/virsh.pod index f4bd294..507686c 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -546,7 +546,8 @@ I parameter in the domain's XML definition. =item B I -Restores a domain from an B state file. See I for more info. +Restores a domain from an B state file. If restoring +succeeded, the state file will be removed. See I for more info. =item B I I -- 1.7.4 From wency at cn.fujitsu.com Wed Apr 6 06:21:00 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 06 Apr 2011 14:21:00 +0800 Subject: [libvirt] [PATCH] init path to NULL Message-ID: <4D9C064C.1040605@cn.fujitsu.com> This bug was introduce by commit 57162db8, and it will cause libvirtd crashed. --- src/util/pci.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/util/pci.c b/src/util/pci.c index 6ed96f4..a7b8caa 100644 --- a/src/util/pci.c +++ b/src/util/pci.c @@ -1180,7 +1180,7 @@ pciWaitForDeviceCleanup(pciDevice *dev, const char *matcher) static char * pciReadDeviceID(pciDevice *dev, const char *id_name) { - char *path; + char *path = NULL; char *id_str; if (pciDeviceFile(&path, dev->name, id_name) < 0) { -- 1.7.1 From jyang at redhat.com Wed Apr 6 06:24:42 2011 From: jyang at redhat.com (Osier Yang) Date: Wed, 06 Apr 2011 14:24:42 +0800 Subject: [libvirt] [PATCH] qemu: Always reserves slot 0x02 for primary VGA. In-Reply-To: <4D9B3302.5010307@redhat.com> References: <1302011398-25541-1-git-send-email-jyang@redhat.com> <4D9B3302.5010307@redhat.com> Message-ID: <4D9C072A.7020707@redhat.com> ? 2011?04?05? 23:19, Eric Blake ??: > On 04/05/2011 07:49 AM, Osier Yang wrote: >> To address https://bugzilla.redhat.com/show_bug.cgi?id=692355 >> >> This fix is to reserve slot 0x02 for primary VGA even if there >> is no "video" specified in domain XML to avoid the problem. >> --- >> src/qemu/qemu_command.c | 13 ++++++++++--- >> 1 files changed, 10 insertions(+), 3 deletions(-) > > ACK. I think that this is the correct patch, given the earlier comments > on the same topic in > https://www.redhat.com/archives/libvir-list/2011-March/msg01296.html > Thanks, applied, for the virtio-blk problem, will be a seperate patch. Regards Osier From matthias.bolte at googlemail.com Wed Apr 6 06:37:02 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Wed, 6 Apr 2011 08:37:02 +0200 Subject: [libvirt] ESX network functionality In-Reply-To: References: Message-ID: Sorry, I forgot to reply to your follow up question on the users list. 2011/4/6 James Barkley : > Greetings: > I've added code to the ESX driver to support some basic network > functionality. I'm pretty new to this list, so please tell me how to proceed > with code review and patch submission (yes I've read the contributor > guidelines on the wiki). It seems like people are emailing a patch file for > every file they've changed, each in separate emails with [1 of N] in the > subject, is that right? Or is it better to paste in code, get some feedback, > and eventually attach the patch to the bug tracker item? The normal approach is to have one commit/patch per logical self-contained change. After each commit/patch the codebase has to be in a compilable stage. For example you cannot add the code using the generated SOAP bindings, before you actually added them to the esx_vi_generator.input file. The [1 of N] style patch series are typically used for large changes that are split in several logical, self-contained parts. Splitting like this simplifies reviewing and later on figuring out bugs using git bisect. You typically don't split on a per file basis. In your case I'd suggest to create a single commit/patch for your addition, as it is one logical piece of work. You _could_ (but I don't recommend to) split it in multiple patches. For example one for the esx_vi_generator.input addition, one for the VI helper function additions and one for the actual driver functions, but I'd consider this to be too fine grained. > I've updated the code for the ESX driver to be able to handle the following > functions : > - virNetworkLookupByName > - virConnectNumOfDefinedNetworks > - virConnectNumOfNetworks > - virConnectListNetworks Is this sufficient to make virsh net-list work? > I basically mapped the VMware Managed Object Reference for networks into a > few data structures and added the following functions to the internal driver You mean the managed object called Network? They _seem_ to be the natural fit. But I'm not sure if that's the correct approach, as you cannot directly create/destroy such objects and they are bound in some way to the port groups on a virtual switch. Also I'm not sure about the exact semantics of networks and port groups. That's what I meant as I said about the mapping between libvirt and VMware. We need to be sure to use the right approach from the start to avoid making breaking changes across releases later on. > API: > - esxNumOfNetworks > - esxListNetworks > - esxNumOfDefinedNetworks I assume you made esxNumOfDefinedNetworks return 0 to get virsh net-list working as there network in the VMware context are always active. > - esxNetworkLookupByName > - esxVI_LookupNetworkList > - esxVI_LookupNetworkByName > These functions were modeled after existing functions from the domain and > storage libraries. The following files were touched: > - esx_network_driver.c > - esx_vi.c > - esx_vi.h > - esx_vi_generator.input Apart from the question whether the Network managed object is the correct match, the next step is to send your patch to this list to get a review. The recommended way for sending patches is git send-email. Matthias From matthias.bolte at googlemail.com Wed Apr 6 06:42:08 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Wed, 6 Apr 2011 08:42:08 +0200 Subject: [libvirt] [PATCH] init path to NULL In-Reply-To: <4D9C064C.1040605@cn.fujitsu.com> References: <4D9C064C.1040605@cn.fujitsu.com> Message-ID: 2011/4/6 Wen Congyang : > This bug was introduce by commit 57162db8, and it will cause libvirtd crashed. > > --- > ?src/util/pci.c | ? ?2 +- > ?1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/src/util/pci.c b/src/util/pci.c > index 6ed96f4..a7b8caa 100644 > --- a/src/util/pci.c > +++ b/src/util/pci.c > @@ -1180,7 +1180,7 @@ pciWaitForDeviceCleanup(pciDevice *dev, const char *matcher) > ?static char * > ?pciReadDeviceID(pciDevice *dev, const char *id_name) > ?{ > - ? ?char *path; > + ? ?char *path = NULL; > ? ? char *id_str; > > ? ? if (pciDeviceFile(&path, dev->name, id_name) < 0) { > -- > 1.7.1 > Oops... shows that I didn't tests this well enough :( ACK. Maybe you could make the commit summary more verbose, for example "pci: avoid invalid free, init path to NULL". Matthias From wency at cn.fujitsu.com Wed Apr 6 07:03:56 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 06 Apr 2011 15:03:56 +0800 Subject: [libvirt] [PATCH 2/3] reattach pci device when pciBindDeviceToStub() failed In-Reply-To: <4D9A4BFD.8090405@redhat.com> References: <4D90306A.6060805@cn.fujitsu.com> <4D90323D.4000008@cn.fujitsu.com> <4D9A4BFD.8090405@redhat.com> Message-ID: <4D9C105C.2030103@cn.fujitsu.com> At 04/05/2011 06:53 AM, Eric Blake Write: > On 03/28/2011 01:01 AM, Wen Congyang wrote: >> We should bind pci device to original driver when pciBindDeviceToStub() failed. >> If the pci device is not bound to any driver before calling pciBindDeviceToStub(), >> we should only unbind it from pci-stub. If it is bound to pci-stub, we should not >> unbid it from pci-stub. >> >> --- >> src/util/pci.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++------ >> 1 files changed, 80 insertions(+), 10 deletions(-) >> >> diff --git a/src/util/pci.c b/src/util/pci.c >> index 8d2dbb0..e30f5cf 100644 >> --- a/src/util/pci.c >> +++ b/src/util/pci.c >> @@ -65,6 +65,11 @@ struct _pciDevice { >> unsigned has_flr : 1; >> unsigned has_pm_reset : 1; >> unsigned managed : 1; >> + >> + /* used by reattach function */ >> + unsigned unbind_from_stub : 1; >> + unsigned remove_slot : 1; >> + unsigned reprobe : 1; >> }; >> >> struct _pciDeviceList { >> @@ -834,11 +839,25 @@ recheck: >> } >> >> >> +static int pciUnBindDeviceFromStub(pciDevice *dev, const char *driver); > > I would have used Unbind rather than UnBind, but that's cosmetic. Is it > possible to float that function up, instead of having to have a forward > declaration? I tend to topologically sort my static functions when > possible (again, cosmetic). Yes, 'Unbind' is better than UnBind. I will send a patch to rename it and float this function up. > >> static int >> pciBindDeviceToStub(pciDevice *dev, const char *driver) >> { >> char drvdir[PATH_MAX]; >> char path[PATH_MAX]; >> + int reprobe = 0; >> + int ret = 0; >> + >> + /* check whether the device is already bound to a driver */ >> + pciDriverDir(drvdir, sizeof(drvdir), driver); >> + pciDeviceFile(path, sizeof(path), dev->name, "driver"); > > Ouch - conflict with Matthias's patches to avoid PATH_MAX. If that goes > in first, your rebase might not be trivial, so it would be worth a v2. Yes, this patch conflicts with Matthias's patches. And his patches have been pushed. I will send v2. > > But overall, I think the idea of this patch is sane, and nothing obvious > jumped out at me as needing fixing other than rebase issues. > From james.barkley at gmail.com Wed Apr 6 07:07:15 2011 From: james.barkley at gmail.com (James Barkley) Date: Wed, 6 Apr 2011 03:07:15 -0400 Subject: [libvirt] ESX network functionality In-Reply-To: References: Message-ID: Matthias, Thanks for the terrific feedback. In answer to your questions: >Is this sufficient to make virsh net-list work? Yes, virsh net-list and also virsh net-info. I also checked both functions against freshly compiled ruby bindings. I also checked the sufficient error is given in virsh net-list when an invalid network is given. >You mean the managed object called Network? They _seem_ to be the >natural fit. But I'm not sure if that's the correct approach, as you >cannot directly create/destroy such objects and they are bound in some >way to the port groups on a virtual switch. Also I'm not sure about >he exact semantics of networks and port groups. Yes, I used the managed object called Network. It does get a little dicey with VMware due to the addition of port groups and virtual switches (admittedly, not sure how this works in most other hypervisors). You certainly can't have transient network objects, and any creation/destruction of a network object seems like it must necessarily involve either creation/destruction of a port group or creation/destruction of a vswitch. I believe using the Network managed object is the right approach, but am not yet 100% confident. My next task is to facilitate the creation of a new network through virNetworkDefineXML or virNetworkCreateXML. If you'd prefer, I can wait until I've completed this functionality to submit the patch, as it may drive me to adopt a different approach. >I assume you made esxNumOfDefinedNetworks return 0 to get virsh >net-list working as there network in the VMware context are always >active. Correct. I was debating on whether or not to have it loop through the network list and check the "active/inactive" just for thoroughness, but if you're fine with just returning 0 and commenting why, then I'll leave it. >The recommended way for sending patches is git send-email. Barring any other recommendations I'll figure out git send email and submit the patch to the list shortly. thanks, -jb On Wed, Apr 6, 2011 at 2:37 AM, Matthias Bolte < matthias.bolte at googlemail.com> wrote: > Sorry, I forgot to reply to your follow up question on the users list. > > 2011/4/6 James Barkley : > > Greetings: > > I've added code to the ESX driver to support some basic network > > functionality. I'm pretty new to this list, so please tell me how to > proceed > > with code review and patch submission (yes I've read the contributor > > guidelines on the wiki). It seems like people are emailing a patch file > for > > every file they've changed, each in separate emails with [1 of N] in the > > subject, is that right? Or is it better to paste in code, get some > feedback, > > and eventually attach the patch to the bug tracker item? > > The normal approach is to have one commit/patch per logical > self-contained change. After each commit/patch the codebase has to be > in a compilable stage. For example you cannot add the code using the > generated SOAP bindings, before you actually added them to the > esx_vi_generator.input file. > > The [1 of N] style patch series are typically used for large changes > that are split in several logical, self-contained parts. Splitting > like this simplifies reviewing and later on figuring out bugs using > git bisect. > > You typically don't split on a per file basis. > > In your case I'd suggest to create a single commit/patch for your > addition, as it is one logical piece of work. You _could_ (but I don't > recommend to) split it in multiple patches. For example one for the > esx_vi_generator.input addition, one for the VI helper function > additions and one for the actual driver functions, but I'd consider > this to be too fine grained. > > > I've updated the code for the ESX driver to be able to handle the > following > > functions : > > - virNetworkLookupByName > > - virConnectNumOfDefinedNetworks > > - virConnectNumOfNetworks > > - virConnectListNetworks > > Is this sufficient to make virsh net-list work? > > > I basically mapped the VMware Managed Object Reference for networks into > a > > few data structures and added the following functions to the internal > driver > > You mean the managed object called Network? They _seem_ to be the > natural fit. But I'm not sure if that's the correct approach, as you > cannot directly create/destroy such objects and they are bound in some > way to the port groups on a virtual switch. Also I'm not sure about > the exact semantics of networks and port groups. > > That's what I meant as I said about the mapping between libvirt and > VMware. We need to be sure to use the right approach from the start to > avoid making breaking changes across releases later on. > > > API: > > - esxNumOfNetworks > > - esxListNetworks > > - esxNumOfDefinedNetworks > > I assume you made esxNumOfDefinedNetworks return 0 to get virsh > net-list working as there network in the VMware context are always > active. > > > - esxNetworkLookupByName > > - esxVI_LookupNetworkList > > - esxVI_LookupNetworkByName > > These functions were modeled after existing functions from the domain and > > storage libraries. The following files were touched: > > - esx_network_driver.c > > - esx_vi.c > > - esx_vi.h > > - esx_vi_generator.input > > Apart from the question whether the Network managed object is the > correct match, the next step is to send your patch to this list to get > a review. The recommended way for sending patches is git send-email. > > Matthias > -------------- next part -------------- An HTML attachment was scrubbed... URL: From wency at cn.fujitsu.com Wed Apr 6 07:13:10 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 06 Apr 2011 15:13:10 +0800 Subject: [libvirt] [PATCH 2_1/3] rename pciUnBindDeviceFromStub() to pciUnbindDeviceFromStub() and float it up In-Reply-To: <4D9A4BFD.8090405@redhat.com> References: <4D90306A.6060805@cn.fujitsu.com> <4D90323D.4000008@cn.fujitsu.com> <4D9A4BFD.8090405@redhat.com> Message-ID: <4D9C1286.1090802@cn.fujitsu.com> This patch do the following things: 1. rename the function as 'Unbind' is better than 'UnBind'. 2. pciUnbindDeviceFromStub() will be used in the function pciBindDeviceToStub() in next patch. Float it up, instead of having to have a forward declaration --- src/util/pci.c | 134 ++++++++++++++++++++++++++++---------------------------- 1 files changed, 67 insertions(+), 67 deletions(-) diff --git a/src/util/pci.c b/src/util/pci.c index a7b8caa..e69813c 100644 --- a/src/util/pci.c +++ b/src/util/pci.c @@ -867,6 +867,72 @@ recheck: return NULL; } +static int +pciUnbindDeviceFromStub(pciDevice *dev, const char *driver) +{ + int result = -1; + char *drvdir = NULL; + char *path = NULL; + + /* If the device is bound to stub, unbind it. + */ + if (pciDriverDir(&drvdir, driver) < 0 || + pciDeviceFile(&path, dev->name, "driver") < 0) { + goto cleanup; + } + + if (virFileExists(drvdir) && virFileLinkPointsTo(path, drvdir)) { + if (pciDriverFile(&path, driver, "unbind") < 0) { + goto cleanup; + } + + if (virFileWriteStr(path, dev->name, 0) < 0) { + virReportSystemError(errno, + _("Failed to bind PCI device '%s' to %s"), + dev->name, driver); + goto cleanup; + } + } + + /* Xen's pciback.ko wants you to use remove_slot on the specific device */ + if (pciDriverFile(&path, driver, "remove_slot") < 0) { + goto cleanup; + } + + if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) { + virReportSystemError(errno, + _("Failed to remove slot for PCI device '%s' to %s"), + dev->name, driver); + goto cleanup; + } + + /* Trigger a re-probe of the device is not in the stub's dynamic + * ID table. If the stub is available, but 'remove_id' isn't + * available, then re-probing would just cause the device to be + * re-bound to the stub. + */ + if (pciDriverFile(&path, driver, "remove_id") < 0) { + goto cleanup; + } + + if (!virFileExists(drvdir) || virFileExists(path)) { + if (virFileWriteStr(PCI_SYSFS "drivers_probe", dev->name, 0) < 0) { + virReportSystemError(errno, + _("Failed to trigger a re-probe for PCI device '%s'"), + dev->name); + goto cleanup; + } + } + + result = 0; + +cleanup: + VIR_FREE(drvdir); + VIR_FREE(path); + + return result; +} + static int pciBindDeviceToStub(pciDevice *dev, const char *driver) @@ -983,72 +1049,6 @@ pciDettachDevice(pciDevice *dev, pciDeviceList *activeDevs) return pciBindDeviceToStub(dev, driver); } -static int -pciUnBindDeviceFromStub(pciDevice *dev, const char *driver) -{ - int result = -1; - char *drvdir = NULL; - char *path = NULL; - - /* If the device is bound to stub, unbind it. - */ - if (pciDriverDir(&drvdir, driver) < 0 || - pciDeviceFile(&path, dev->name, "driver") < 0) { - goto cleanup; - } - - if (virFileExists(drvdir) && virFileLinkPointsTo(path, drvdir)) { - if (pciDriverFile(&path, driver, "unbind") < 0) { - goto cleanup; - } - - if (virFileWriteStr(path, dev->name, 0) < 0) { - virReportSystemError(errno, - _("Failed to bind PCI device '%s' to %s"), - dev->name, driver); - goto cleanup; - } - } - - /* Xen's pciback.ko wants you to use remove_slot on the specific device */ - if (pciDriverFile(&path, driver, "remove_slot") < 0) { - goto cleanup; - } - - if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) { - virReportSystemError(errno, - _("Failed to remove slot for PCI device '%s' to %s"), - dev->name, driver); - goto cleanup; - } - - /* Trigger a re-probe of the device is not in the stub's dynamic - * ID table. If the stub is available, but 'remove_id' isn't - * available, then re-probing would just cause the device to be - * re-bound to the stub. - */ - if (pciDriverFile(&path, driver, "remove_id") < 0) { - goto cleanup; - } - - if (!virFileExists(drvdir) || virFileExists(path)) { - if (virFileWriteStr(PCI_SYSFS "drivers_probe", dev->name, 0) < 0) { - virReportSystemError(errno, - _("Failed to trigger a re-probe for PCI device '%s'"), - dev->name); - goto cleanup; - } - } - - result = 0; - -cleanup: - VIR_FREE(drvdir); - VIR_FREE(path); - - return result; -} - int pciReAttachDevice(pciDevice *dev, pciDeviceList *activeDevs) { @@ -1065,7 +1065,7 @@ pciReAttachDevice(pciDevice *dev, pciDeviceList *activeDevs) return -1; } - return pciUnBindDeviceFromStub(dev, driver); + return pciUnbindDeviceFromStub(dev, driver); } /* Certain hypervisors (like qemu/kvm) map the PCI bar(s) on -- 1.7.1 From wency at cn.fujitsu.com Wed Apr 6 07:13:14 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 06 Apr 2011 15:13:14 +0800 Subject: [libvirt] [PATCH 2_2/3] reattach pci device when pciBindDeviceToStub() failed In-Reply-To: <4D9A4BFD.8090405@redhat.com> References: <4D90306A.6060805@cn.fujitsu.com> <4D90323D.4000008@cn.fujitsu.com> <4D9A4BFD.8090405@redhat.com> Message-ID: <4D9C128A.7040309@cn.fujitsu.com> We should bind pci device to original driver when pciBindDeviceToStub() failed. If the pci device is not bound to any driver before calling pciBindDeviceToStub(), we should only unbind it from pci-stub. If it is bound to pci-stub, we should not unbid it from pci-stub. --- src/util/pci.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 91 insertions(+), 12 deletions(-) diff --git a/src/util/pci.c b/src/util/pci.c index e69813c..ec9a0b9 100644 --- a/src/util/pci.c +++ b/src/util/pci.c @@ -65,6 +65,11 @@ struct _pciDevice { unsigned has_flr : 1; unsigned has_pm_reset : 1; unsigned managed : 1; + + /* used by reattach function */ + unsigned unbind_from_stub : 1; + unsigned remove_slot : 1; + unsigned reprobe : 1; }; struct _pciDeviceList { @@ -874,6 +879,9 @@ pciUnbindDeviceFromStub(pciDevice *dev, const char *driver) char *drvdir = NULL; char *path = NULL; + if (!dev->unbind_from_stub) + goto remove_slot; + /* If the device is bound to stub, unbind it. */ if (pciDriverDir(&drvdir, driver) < 0 || @@ -888,11 +896,16 @@ pciUnbindDeviceFromStub(pciDevice *dev, const char *driver) if (virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, - _("Failed to bind PCI device '%s' to %s"), + _("Failed to unbind PCI device '%s' from %s"), dev->name, driver); goto cleanup; } } + dev->unbind_from_stub = 0; + +remove_slot: + if (!dev->remove_slot) + goto reprobe; /* Xen's pciback.ko wants you to use remove_slot on the specific device */ if (pciDriverFile(&path, driver, "remove_slot") < 0) { @@ -901,10 +914,17 @@ pciUnbindDeviceFromStub(pciDevice *dev, const char *driver) if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, - _("Failed to remove slot for PCI device '%s' to %s"), + _("Failed to remove slot for PCI device '%s' from %s"), dev->name, driver); goto cleanup; } + dev->remove_slot = 0; + +reprobe: + if (!dev->reprobe) { + result = 0; + goto cleanup; + } /* Trigger a re-probe of the device is not in the stub's dynamic * ID table. If the stub is available, but 'remove_id' isn't @@ -927,6 +947,11 @@ pciUnbindDeviceFromStub(pciDevice *dev, const char *driver) result = 0; cleanup: + /* do not do it again */ + dev->unbind_from_stub = 0; + dev->remove_slot = 0; + dev->reprobe = 0; + VIR_FREE(drvdir); VIR_FREE(path); @@ -940,6 +965,22 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) int result = -1; char *drvdir = NULL; char *path = NULL; + int reprobe = 0; + + /* check whether the device is already bound to a driver */ + if (pciDriverDir(&drvdir, driver) < 0 || + pciDeviceFile(&path, dev->name, "driver") < 0) { + goto cleanup; + } + + if (virFileExists(path)) { + if (virFileLinkPointsTo(path, drvdir)) { + /* The device is already bound to pci-stub */ + result = 0; + goto cleanup; + } + reprobe = 1; + } /* Add the PCI device ID to the stub's dynamic ID table; * this is needed to allow us to bind the device to the stub. @@ -950,7 +991,7 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) * bound by the stub. */ if (pciDriverFile(&path, driver, "new_id") < 0) { - return -1; + goto cleanup; } if (virFileWriteStr(path, dev->id, 0) < 0) { @@ -960,6 +1001,20 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) goto cleanup; } + /* check whether the device is bound to pci-stub when we write dev->id to + * new_id. + */ + if (pciDriverDir(&drvdir, driver) < 0 || + pciDeviceFile(&path, dev->name, "driver") < 0) { + goto remove_id; + } + + if (virFileLinkPointsTo(path, drvdir)) { + dev->unbind_from_stub = 1; + dev->remove_slot = 1; + goto remove_id; + } + /* If the device is already bound to a driver, unbind it. * Note, this will have rather unpleasant side effects if this * PCI device happens to be IDE controller for the disk hosting @@ -969,48 +1024,61 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) goto cleanup; } - if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) { - virReportSystemError(errno, - _("Failed to unbind PCI device '%s'"), dev->name); - goto cleanup; + if (virFileExists(path)) { + if (virFileWriteStr(path, dev->name, 0) < 0) { + virReportSystemError(errno, + _("Failed to unbind PCI device '%s'"), + dev->name); + goto cleanup; + } + dev->reprobe = reprobe; } /* If the device isn't already bound to pci-stub, try binding it now. */ if (pciDriverDir(&drvdir, driver) < 0 || pciDeviceFile(&path, dev->name, "driver") < 0) { - goto cleanup; + goto remove_id; } if (!virFileLinkPointsTo(path, drvdir)) { /* Xen's pciback.ko wants you to use new_slot first */ if (pciDriverFile(&path, driver, "new_slot") < 0) { - goto cleanup; + goto remove_id; } if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to add slot for PCI device '%s' to %s"), dev->name, driver); - goto cleanup; + goto remove_id; } + dev->remove_slot = 1; if (pciDriverFile(&path, driver, "bind") < 0) { - goto cleanup; + goto remove_id; } if (virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to bind PCI device '%s' to %s"), dev->name, driver); - goto cleanup; + goto remove_id; } + dev->unbind_from_stub = 1; } +remove_id: /* If 'remove_id' exists, remove the device id from pci-stub's dynamic * ID table so that 'drivers_probe' works below. */ if (pciDriverFile(&path, driver, "remove_id") < 0) { + /* We do not remove PCI ID from pci-stub, and we can not reprobe it */ + if (dev->reprobe) { + VIR_WARN("Not remove PCI ID '%s' from %s, and the device can" + "not be reprobed again.", dev->id, driver); + } + dev->reprobe = 0; goto cleanup; } @@ -1018,6 +1086,13 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) virReportSystemError(errno, _("Failed to remove PCI ID '%s' from %s"), dev->id, driver); + + /* remove PCI ID from pci-stub failed, and we can not reprobe it */ + if (dev->reprobe) { + VIR_WARN("Faile to remove PCI ID '%s' from %s, and the device can" + "not be reprobed again.", dev->id, driver); + } + dev->reprobe = 0; goto cleanup; } @@ -1027,6 +1102,10 @@ cleanup: VIR_FREE(drvdir); VIR_FREE(path); + if (result < 0) { + pciUnbindDeviceFromStub(dev, driver); + } + return result; } -- 1.7.1 From hutao at cn.fujitsu.com Wed Apr 6 07:18:44 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Wed, 6 Apr 2011 15:18:44 +0800 Subject: [libvirt] [PATCH 0/6] virObject for reference-counting Message-ID: This series adds a virObject structure that manages reference-counting. Some notes about referece-counting introduced by this series: A thread owns a virObject by incrementing its reference-count by 1. If a thread owns a virObject, the virObject is guarenteed not be freed until the thread releases ownership by decrementing its reference-count by 1. A thread can't access a virObject after it releases the ownership of virObject because it can be freed at anytime. A thread can own a virObject legally in these ways: - a thread owns a virObject that it creates. - a thread owns a virObject if another thread passes the ownership to it. Example: qemuMonitorOpen - a thread gets a virObject from a container. Example: virDomainFindByUUID - a container owns a virObject by incrementing its reference-count by 1 before adding it to the container - if a virObject is removed from a container its reference-count must be decremented by 1 By following these rules, there is no need to protect operations on an object's reference-count by an external lock. (like in old ways virDomainObj lock protects qemu monitor's ref-count.) This series is a draft and posted for early review. Any comments are welcome. Hu Tao (6): Add virObject and virAtomic. use virObject to manage reference-count of qemud_client use virObject to manage reference-count of virDomainObj qemu: use virObject to manages reference-counting for qemu monitor remove qemuDomainObjEnterMonitorWithDriver and qemuDomainObjExitMonitorWithDriver remove qemuDomainObjBeginJobWithDriver daemon/dispatch.c | 2 - daemon/libvirtd.c | 62 ++++++-- daemon/libvirtd.h | 5 +- src/Makefile.am | 2 + src/conf/domain_conf.c | 56 ++++---- src/conf/domain_conf.h | 6 +- src/libvirt_private.syms | 5 + src/openvz/openvz_conf.c | 8 +- src/qemu/qemu_domain.c | 121 +-------------- src/qemu/qemu_domain.h | 8 +- src/qemu/qemu_driver.c | 358 ++++++++++++++++++++------------------------- src/qemu/qemu_hotplug.c | 90 ++++++------ src/qemu/qemu_migration.c | 101 ++++++------- src/qemu/qemu_monitor.c | 109 ++++++++------- src/qemu/qemu_monitor.h | 4 +- src/qemu/qemu_process.c | 99 ++++++------- src/util/viratomic.c | 46 ++++++ src/util/viratomic.h | 30 ++++ src/util/virobject.c | 52 +++++++ src/util/virobject.h | 39 +++++ src/vmware/vmware_conf.c | 2 +- 21 files changed, 628 insertions(+), 577 deletions(-) create mode 100644 src/util/viratomic.c create mode 100644 src/util/viratomic.h create mode 100644 src/util/virobject.c create mode 100644 src/util/virobject.h -- 1.7.3.1 From hutao at cn.fujitsu.com Wed Apr 6 07:19:37 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Wed, 6 Apr 2011 15:19:37 +0800 Subject: [libvirt] [PATCH 1/6] Add virObject and virAtomic. In-Reply-To: References: Message-ID: virObject is the base struct that manages reference-counting for all structs that need the ability of reference-counting. virAtomic provides atomic operations which are thread-safe. --- src/Makefile.am | 2 + src/libvirt_private.syms | 5 ++++ src/util/viratomic.c | 46 ++++++++++++++++++++++++++++++++++++++++ src/util/viratomic.h | 30 ++++++++++++++++++++++++++ src/util/virobject.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ src/util/virobject.h | 39 ++++++++++++++++++++++++++++++++++ 6 files changed, 174 insertions(+), 0 deletions(-) create mode 100644 src/util/viratomic.c create mode 100644 src/util/viratomic.h create mode 100644 src/util/virobject.c create mode 100644 src/util/virobject.h diff --git a/src/Makefile.am b/src/Makefile.am index 9b54679..9e74060 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -81,6 +81,8 @@ UTIL_SOURCES = \ util/util.c util/util.h \ util/xml.c util/xml.h \ util/virtaudit.c util/virtaudit.h \ + util/viratomic.c util/viratomic.h \ + util/virobject.c util/virobject.h \ util/virterror.c util/virterror_internal.h EXTRA_DIST += util/threads-pthread.c util/threads-win32.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 65a86d3..98f8d6f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -993,3 +993,8 @@ virXPathUInt; virXPathULong; virXPathULongHex; virXPathULongLong; + +# object.h +virObjectInit; +virObjectRef; +virObjectUnref; diff --git a/src/util/viratomic.c b/src/util/viratomic.c new file mode 100644 index 0000000..629f189 --- /dev/null +++ b/src/util/viratomic.c @@ -0,0 +1,46 @@ +/* + * viratomic.c: atomic operations + * + * Copyright (C) 2011 Hu Tao + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Hu Tao + */ + +#include "viratomic.h" + +#ifdef WIN32 +long virAtomicInc(long *value) +{ + return InterlockedIncrement(value); +} + +long virAtomicDec(long *value) +{ + return InterlockedDecrement(value); +} +#else /* WIN32 */ +long virAtomicInc(long *value) +{ + return __sync_add_and_fetch(value, 1); +} + +long virAtomicDec(long *value) +{ + return __sync_sub_and_fetch(value, 1); +} +#endif /* WIN32 */ diff --git a/src/util/viratomic.h b/src/util/viratomic.h new file mode 100644 index 0000000..a10cb65 --- /dev/null +++ b/src/util/viratomic.h @@ -0,0 +1,30 @@ +/* + * viratomic.h: atomic operations + * + * Copyright (C) 2011 Hu Tao + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Hu Tao + */ + +#ifndef __VIR_ATOMIC_H +#define __VIR_ATOMIC_H + +long virAtomicInc(long *value); +long virAtomicDec(long *value); + +#endif /* __VIR_ATOMIC_H */ diff --git a/src/util/virobject.c b/src/util/virobject.c new file mode 100644 index 0000000..aeedbef --- /dev/null +++ b/src/util/virobject.c @@ -0,0 +1,52 @@ +/* + * virobject.c: base object that manages reference-counting + * + * Copyright (C) 2011 Hu Tao + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Hu Tao + */ + +#include "viratomic.h" +#include "virobject.h" +#include "logging.h" + +int virObjectInit(virObjectPtr obj, void (*free)(virObjectPtr obj)) +{ + if (!free) { + VIR_ERROR0("method free is required."); + return -1; + } + + obj->ref = 1; + obj->free = free; + + return 0; +} + +void virObjectRef(virObjectPtr obj) +{ + sa_assert(obj->ref > 0); + virAtomicInc(&obj->ref); +} + +void virObjectUnref(virObjectPtr obj) +{ + sa_assert(obj->ref > 0); + if (virAtomicDec(&obj->ref) == 0) + obj->free(obj); +} diff --git a/src/util/virobject.h b/src/util/virobject.h new file mode 100644 index 0000000..cd7d3e8 --- /dev/null +++ b/src/util/virobject.h @@ -0,0 +1,39 @@ +/* + * virobject.h: base object that manages reference-counting + * + * Copyright (C) 2011 Hu Tao + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Hu Tao + */ + +#ifndef __VIR_OBJECT_H +#define __VIR_OBJECT_H + +typedef struct _virObject virObject; +typedef virObject *virObjectPtr; + +struct _virObject { + long ref; + void (*free)(virObjectPtr obj); +}; + +int virObjectInit(virObjectPtr obj, void (*free)(virObjectPtr obj)); +void virObjectRef(virObjectPtr obj); +void virObjectUnref(virObjectPtr obj); + +#endif /* __VIR_OBJECT_H */ -- 1.7.3.1 -- Thanks, Hu Tao From hutao at cn.fujitsu.com Wed Apr 6 07:19:46 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Wed, 6 Apr 2011 15:19:46 +0800 Subject: [libvirt] [PATCH 2/6] use virObject to manage reference-count of qemud_client In-Reply-To: References: Message-ID: <8c080f20e7416da216a5a6ab8fcaff37e7abaf70.1302069479.git.hutao@cn.fujitsu.com> --- daemon/dispatch.c | 2 - daemon/libvirtd.c | 62 +++++++++++++++++++++++++++++++++++++++------------- daemon/libvirtd.h | 5 ++- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/daemon/dispatch.c b/daemon/dispatch.c index 4814017..b2d6927 100644 --- a/daemon/dispatch.c +++ b/daemon/dispatch.c @@ -524,9 +524,7 @@ remoteDispatchClientCall (struct qemud_server *server, */ rv = (data->fn)(server, client, conn, &msg->hdr, &rerr, &args, &ret); - virMutexLock(&server->lock); virMutexLock(&client->lock); - virMutexUnlock(&server->lock); xdr_free (data->args_filter, (char*)&args); diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 42cbe5d..d3ba97b 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -270,6 +270,8 @@ static void sig_fatal(int sig, siginfo_t * siginfo ATTRIBUTE_UNUSED, static void qemudDispatchClientEvent(int watch, int fd, int events, void *opaque); static void qemudDispatchServerEvent(int watch, int fd, int events, void *opaque); static int qemudStartWorker(struct qemud_server *server, struct qemud_worker *worker); +static void qemudClientRef(struct qemud_client *client); +static void qemudClientUnref(struct qemud_client *client); void qemudClientMessageQueuePush(struct qemud_client_message **queue, @@ -1338,6 +1340,8 @@ int qemudGetSocketIdentity(int fd, uid_t *uid, pid_t *pid) { #endif +static void qemudFreeClient(virObjectPtr obj); + static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket *sock) { int fd; virSocketAddr addr; @@ -1411,6 +1415,10 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket VIR_ERROR0(_("cannot initialize mutex")); goto error; } + if (virObjectInit(&client->obj, qemudFreeClient)) { + VIR_ERROR0(_("cannot initialize virobject")); + goto error; + } client->magic = QEMUD_CLIENT_MAGIC; client->fd = fd; @@ -1576,12 +1584,10 @@ static struct qemud_client *qemudPendingJob(struct qemud_server *server) { int i; for (i = 0 ; i < server->nclients ; i++) { - virMutexLock(&server->clients[i]->lock); if (server->clients[i]->dx) { - /* Delibrately don't unlock client - caller wants the lock */ + qemudClientRef(server->clients[i]); return server->clients[i]; } - virMutexUnlock(&server->clients[i]->lock); } return NULL; } @@ -1604,31 +1610,36 @@ static void *qemudWorker(void *data) } } if (worker->quitRequest) { - virMutexUnlock(&client->lock); virMutexUnlock(&server->lock); + qemudClientUnref(client); return NULL; } worker->processingCall = 1; virMutexUnlock(&server->lock); - /* We own a locked client now... */ - client->refs++; + virMutexLock(&client->lock); /* Remove our message from dispatch queue while we use it */ msg = qemudClientMessageQueueServe(&client->dx); + if (!msg) { + virMutexUnlock(&client->lock); + qemudClientUnref(client); + continue; + } + /* This function drops the lock during dispatch, * and re-acquires it before returning */ if (remoteDispatchClientRequest (server, client, msg) < 0) { VIR_FREE(msg); qemudDispatchClientFailure(client); - client->refs--; virMutexUnlock(&client->lock); + qemudClientUnref(client); continue; } - client->refs--; virMutexUnlock(&client->lock); + qemudClientUnref(client); virMutexLock(&server->lock); worker->processingCall = 0; @@ -2155,6 +2166,7 @@ qemudDispatchClientEvent(int watch, int fd, int events, void *opaque) { virMutexLock(&server->clients[i]->lock); if (server->clients[i]->watch == watch) { client = server->clients[i]; + qemudClientRef(client); break; } virMutexUnlock(&server->clients[i]->lock); @@ -2168,6 +2180,7 @@ qemudDispatchClientEvent(int watch, int fd, int events, void *opaque) { if (client->fd != fd) { virMutexUnlock(&client->lock); + qemudClientUnref(client); return; } @@ -2190,6 +2203,7 @@ qemudDispatchClientEvent(int watch, int fd, int events, void *opaque) { qemudDispatchClientFailure(client); virMutexUnlock(&client->lock); + qemudClientUnref(client); } @@ -2306,7 +2320,9 @@ static void qemudInactiveTimer(int timerid, void *data) { } } -static void qemudFreeClient(struct qemud_client *client) { +static void qemudFreeClient(virObjectPtr obj) { + struct qemud_client *client = (struct qemud_client *)obj; + while (client->rx) { struct qemud_client_message *msg = qemudClientMessageQueueServe(&client->rx); @@ -2333,6 +2349,16 @@ static void qemudFreeClient(struct qemud_client *client) { VIR_FREE(client); } +static void qemudClientRef(struct qemud_client *client) +{ + virObjectRef(&client->obj); +} + +static void qemudClientUnref(struct qemud_client *client) +{ + virObjectUnref(&client->obj); +} + static void *qemudRunLoop(void *opaque) { struct qemud_server *server = opaque; int timerid = -1; @@ -2396,13 +2422,17 @@ static void *qemudRunLoop(void *opaque) { reprocess: for (i = 0 ; i < server->nclients ; i++) { - int inactive; + struct qemud_client *client = NULL; virMutexLock(&server->clients[i]->lock); - inactive = server->clients[i]->fd == -1 - && server->clients[i]->refs == 0; - virMutexUnlock(&server->clients[i]->lock); - if (inactive) { - qemudFreeClient(server->clients[i]); + if (server->clients[i]->fd == -1) { + client = server->clients[i]; + server->clients[i] = NULL; + } + if (!client) { + virMutexUnlock(&server->clients[i]->lock); + } else { + virMutexUnlock(&client->lock); + qemudClientUnref(client); server->nclients--; if (i < server->nclients) memmove(server->clients + i, @@ -2451,7 +2481,7 @@ cleanup: } VIR_FREE(server->workers); for (i = 0; i < server->nclients; i++) - qemudFreeClient(server->clients[i]); + qemudClientUnref(server->clients[i]); server->nclients = 0; VIR_SHRINK_N(server->clients, server->nclients_max, server->nclients_max); diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h index d37c3fd..5ac4eb3 100644 --- a/daemon/libvirtd.h +++ b/daemon/libvirtd.h @@ -49,6 +49,7 @@ # include "logging.h" # include "threads.h" # include "network.h" +# include "virobject.h" # if WITH_DTRACE # ifndef LIBVIRTD_PROBES_H @@ -186,6 +187,8 @@ struct qemud_client_stream { /* Stores the per-client connection state */ struct qemud_client { + virObject obj; /* should be the first member */ + virMutex lock; int magic; @@ -243,8 +246,6 @@ struct qemud_client { * called, it will be set back to NULL if that succeeds. */ virConnectPtr conn; - int refs; - }; # define QEMUD_CLIENT_MAGIC 0x7788aaee -- 1.7.3.1 -- Thanks, Hu Tao From hutao at cn.fujitsu.com Wed Apr 6 07:19:55 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Wed, 6 Apr 2011 15:19:55 +0800 Subject: [libvirt] [PATCH 4/6] qemu: use virObject to manage reference-counting for qemu monitor In-Reply-To: References: Message-ID: <821a47bc81d57d652997fde0dec0010e3cad75d5.1302069479.git.hutao@cn.fujitsu.com> --- src/qemu/qemu_domain.c | 30 ++----------- src/qemu/qemu_migration.c | 2 - src/qemu/qemu_monitor.c | 109 ++++++++++++++++++++++++-------------------- src/qemu/qemu_monitor.h | 4 +- src/qemu/qemu_process.c | 32 +++++++------- 5 files changed, 81 insertions(+), 96 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 3a3c953..d11dc5f 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -560,9 +560,8 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) { qemuDomainObjPrivatePtr priv = obj->privateData; - qemuMonitorLock(priv->mon); - qemuMonitorRef(priv->mon); virDomainObjUnlock(obj); + qemuMonitorLock(priv->mon); } @@ -573,18 +572,9 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) void qemuDomainObjExitMonitor(virDomainObjPtr obj) { qemuDomainObjPrivatePtr priv = obj->privateData; - int refs; - - refs = qemuMonitorUnref(priv->mon); - - if (refs > 0) - qemuMonitorUnlock(priv->mon); + qemuMonitorUnlock(priv->mon); virDomainObjLock(obj); - - if (refs == 0) { - priv->mon = NULL; - } } @@ -601,10 +591,8 @@ void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, { qemuDomainObjPrivatePtr priv = obj->privateData; - qemuMonitorLock(priv->mon); - qemuMonitorRef(priv->mon); virDomainObjUnlock(obj); - qemuDriverUnlock(driver); + qemuMonitorLock(priv->mon); } @@ -617,19 +605,9 @@ void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, virDomainObjPtr obj) { qemuDomainObjPrivatePtr priv = obj->privateData; - int refs; - - refs = qemuMonitorUnref(priv->mon); - - if (refs > 0) - qemuMonitorUnlock(priv->mon); - qemuDriverLock(driver); + qemuMonitorUnlock(priv->mon); virDomainObjLock(obj); - - if (refs == 0) { - priv->mon = NULL; - } } void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver, diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 462e6be..6af2e24 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -224,11 +224,9 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) } virDomainObjUnlock(vm); - qemuDriverUnlock(driver); nanosleep(&ts, NULL); - qemuDriverLock(driver); virDomainObjLock(vm); } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 2d28f8d..98c55e7 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -37,6 +37,7 @@ #include "memory.h" #include "logging.h" #include "files.h" +#include "virobject.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -44,11 +45,10 @@ #define DEBUG_RAW_IO 0 struct _qemuMonitor { + virObject obj; virMutex lock; /* also used to protect fd */ virCond notify; - int refs; - int fd; int watch; int hasSendFD; @@ -203,35 +203,61 @@ void qemuMonitorUnlock(qemuMonitorPtr mon) } -static void qemuMonitorFree(qemuMonitorPtr mon) +static void doMonitorFree(virObjectPtr obj) { + qemuMonitorPtr mon = (qemuMonitorPtr)obj; + VIR_DEBUG("mon=%p", mon); if (mon->cb && mon->cb->destroy) (mon->cb->destroy)(mon, mon->vm); - if (virCondDestroy(&mon->notify) < 0) - {} + ignore_value(virCondDestroy(&mon->notify)); virMutexDestroy(&mon->lock); VIR_FREE(mon->buffer); VIR_FREE(mon); } -int qemuMonitorRef(qemuMonitorPtr mon) +static qemuMonitorPtr qemuMonitorAlloc(void) { - mon->refs++; - return mon->refs; -} + qemuMonitorPtr mon; -int qemuMonitorUnref(qemuMonitorPtr mon) -{ - mon->refs--; + if (VIR_ALLOC(mon) < 0) { + virReportOOMError(); + return NULL; + } - if (mon->refs == 0) { - qemuMonitorUnlock(mon); - qemuMonitorFree(mon); - return 0; + if (virObjectInit(&mon->obj, doMonitorFree)) { + VIR_FREE(mon); + return NULL; + } + + if (virMutexInit(&mon->lock) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot initialize monitor mutex")); + VIR_FREE(mon); + return NULL; } - return mon->refs; + if (virCondInit(&mon->notify) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot initialize monitor condition")); + virMutexDestroy(&mon->lock); + VIR_FREE(mon); + return NULL; + } + + mon->fd = -1; + + return mon; +} + +void qemuMonitorRef(qemuMonitorPtr mon) +{ + virObjectRef(&mon->obj); +} + +void qemuMonitorUnref(qemuMonitorPtr mon) +{ + virObjectUnref(&mon->obj); } static void @@ -239,9 +265,7 @@ qemuMonitorUnwatch(void *monitor) { qemuMonitorPtr mon = monitor; - qemuMonitorLock(mon); - if (qemuMonitorUnref(mon) > 0) - qemuMonitorUnlock(mon); + qemuMonitorUnref(mon); } static int @@ -521,7 +545,6 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) { /* lock access to the monitor and protect fd */ qemuMonitorLock(mon); - qemuMonitorRef(mon); #if DEBUG_IO VIR_DEBUG("Monitor %p I/O on watch %d fd %d events %d", mon, watch, fd, events); #endif @@ -598,13 +621,11 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) { /* Make sure anyone waiting wakes up now */ virCondSignal(&mon->notify); - if (qemuMonitorUnref(mon) > 0) - qemuMonitorUnlock(mon); + qemuMonitorUnlock(mon); VIR_DEBUG("Triggering EOF callback error? %d", failed); (eofNotify)(mon, vm, failed); } else { - if (qemuMonitorUnref(mon) > 0) - qemuMonitorUnlock(mon); + qemuMonitorUnlock(mon); } } @@ -623,30 +644,13 @@ qemuMonitorOpen(virDomainObjPtr vm, return NULL; } - if (VIR_ALLOC(mon) < 0) { - virReportOOMError(); + mon = qemuMonitorAlloc(); + if (!mon) return NULL; - } - if (virMutexInit(&mon->lock) < 0) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot initialize monitor mutex")); - VIR_FREE(mon); - return NULL; - } - if (virCondInit(&mon->notify) < 0) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot initialize monitor condition")); - virMutexDestroy(&mon->lock); - VIR_FREE(mon); - return NULL; - } - mon->fd = -1; - mon->refs = 1; mon->vm = vm; mon->json = json; mon->cb = cb; - qemuMonitorLock(mon); switch (config->type) { case VIR_DOMAIN_CHR_TYPE_UNIX: @@ -679,20 +683,25 @@ qemuMonitorOpen(virDomainObjPtr vm, } + /* mon will be accessed by qemuMonitorIO which is called in + * event thread, so ref it before passing it to the thread. + * + * Note: mon is unrefed in qemuMonitorUnwatch + */ + qemuMonitorRef(mon); if ((mon->watch = virEventAddHandle(mon->fd, VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_READABLE, qemuMonitorIO, mon, qemuMonitorUnwatch)) < 0) { + qemuMonitorUnref(mon); qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("unable to register monitor events")); goto cleanup; } - qemuMonitorRef(mon); VIR_DEBUG("New mon %p fd =%d watch=%d", mon, mon->fd, mon->watch); - qemuMonitorUnlock(mon); return mon; @@ -703,8 +712,8 @@ cleanup: * so kill the callbacks now. */ mon->cb = NULL; - qemuMonitorUnlock(mon); qemuMonitorClose(mon); + qemuMonitorUnref(mon); return NULL; } @@ -724,8 +733,8 @@ void qemuMonitorClose(qemuMonitorPtr mon) VIR_FORCE_CLOSE(mon->fd); } - if (qemuMonitorUnref(mon) > 0) - qemuMonitorUnlock(mon); + qemuMonitorUnlock(mon); + qemuMonitorUnref(mon); } @@ -778,7 +787,7 @@ int qemuMonitorHMPCommandWithFd(qemuMonitorPtr mon, if ((mon)->cb && (mon)->cb->callback) \ (ret) = ((mon)->cb->callback)(mon, __VA_ARGS__); \ qemuMonitorLock(mon); \ - ignore_value(qemuMonitorUnref(mon)); \ + qemuMonitorUnref(mon); \ } while (0) int qemuMonitorGetDiskSecret(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c90219b..4498c49 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -132,8 +132,8 @@ int qemuMonitorCheckHMP(qemuMonitorPtr mon, const char *cmd); void qemuMonitorLock(qemuMonitorPtr mon); void qemuMonitorUnlock(qemuMonitorPtr mon); -int qemuMonitorRef(qemuMonitorPtr mon); -int qemuMonitorUnref(qemuMonitorPtr mon) ATTRIBUTE_RETURN_CHECK; +void qemuMonitorRef(qemuMonitorPtr mon); +void qemuMonitorUnref(qemuMonitorPtr mon); /* These APIs are for use by the internal Text/JSON monitor impl code only */ int qemuMonitorSend(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 244b22a..4b9087f 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -107,7 +107,6 @@ qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED, VIR_DEBUG("Received EOF on %p '%s'", vm, vm->def->name); - qemuDriverLock(driver); virDomainObjLock(vm); if (!virDomainObjIsActive(vm)) { @@ -133,15 +132,17 @@ qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED, qemuProcessStop(driver, vm, 0); qemuAuditDomainStop(vm, hasError ? "failed" : "shutdown"); - if (!vm->persistent) + if (!vm->persistent) { + qemuDriverLock(driver); virDomainRemoveInactive(&driver->domains, vm); - else - virDomainObjUnlock(vm); + qemuDriverUnlock(driver); + } + + virDomainObjUnlock(vm); if (event) { qemuDomainEventQueue(driver, event); } - qemuDriverUnlock(driver); } @@ -602,8 +603,10 @@ static void qemuProcessHandleMonitorDestroy(qemuMonitorPtr mon, virDomainObjLock(vm); priv = vm->privateData; - if (priv->mon == mon) + if (priv->mon == mon) { priv->mon = NULL; + qemuMonitorUnref(mon); + } virDomainObjUnlock(vm); virDomainObjUnref(vm); } @@ -633,19 +636,11 @@ qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm) goto error; } - /* Hold an extra reference because we can't allow 'vm' to be - * deleted while the monitor is active */ - virDomainObjRef(vm); - priv->mon = qemuMonitorOpen(vm, priv->monConfig, priv->monJSON, &monitorCallbacks); - /* Safe to ignore value since ref count was incremented above */ - if (priv->mon == NULL) - virDomainObjUnref(vm); - if (virSecurityManagerClearSocketLabel(driver->securityManager, vm) < 0) { VIR_ERROR(_("Failed to clear security context for monitor for %s"), vm->def->name); @@ -657,6 +652,7 @@ qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm) goto error; } + qemuMonitorRef(priv->mon); qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorSetCapabilities(priv->mon); @@ -2471,8 +2467,12 @@ void qemuProcessStop(struct qemud_driver *driver, _("Failed to send SIGTERM to %s (%d)"), vm->def->name, vm->pid); - if (priv->mon) - qemuMonitorClose(priv->mon); + if (priv->mon) { + qemuMonitorPtr mon = priv->mon; + priv->mon = NULL; + qemuMonitorClose(mon); + qemuMonitorUnref(mon); + } if (priv->monConfig) { if (priv->monConfig->type == VIR_DOMAIN_CHR_TYPE_UNIX) -- 1.7.3.1 -- Thanks, Hu Tao From hutao at cn.fujitsu.com Wed Apr 6 07:19:51 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Wed, 6 Apr 2011 15:19:51 +0800 Subject: [libvirt] [PATCH 3/6] use virObject to manage reference-count of virDomainObj In-Reply-To: References: Message-ID: This patch also eliminates a dead-lock bug in qemuDomainObjBeginJobWithDriver: if virCondWaitUntil() timeouts, the thread tries to acquire qemu driver lock while holding virDomainObj lock. --- src/conf/domain_conf.c | 56 ++++---- src/conf/domain_conf.h | 6 +- src/openvz/openvz_conf.c | 8 +- src/qemu/qemu_domain.c | 32 ++--- src/qemu/qemu_domain.h | 2 +- src/qemu/qemu_driver.c | 304 ++++++++++++++++++++------------------------- src/qemu/qemu_migration.c | 45 +++---- src/qemu/qemu_process.c | 33 ++--- src/vmware/vmware_conf.c | 2 +- 9 files changed, 215 insertions(+), 273 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 90a1317..fc76a00 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -47,6 +47,7 @@ #include "storage_file.h" #include "files.h" #include "bitmap.h" +#include "virobject.h" #define VIR_FROM_THIS VIR_FROM_DOMAIN @@ -395,9 +396,7 @@ static void virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED) { virDomainObjPtr obj = payload; - virDomainObjLock(obj); - if (virDomainObjUnref(obj) > 0) - virDomainObjUnlock(obj); + virDomainObjUnref(obj); } int virDomainObjListInit(virDomainObjListPtr doms) @@ -437,7 +436,7 @@ virDomainObjPtr virDomainFindByID(const virDomainObjListPtr doms, virDomainObjPtr obj; obj = virHashSearch(doms->objs, virDomainObjListSearchID, &id); if (obj) - virDomainObjLock(obj); + virDomainObjRef(obj); return obj; } @@ -452,7 +451,7 @@ virDomainObjPtr virDomainFindByUUID(const virDomainObjListPtr doms, obj = virHashLookup(doms->objs, uuidstr); if (obj) - virDomainObjLock(obj); + virDomainObjRef(obj); return obj; } @@ -476,7 +475,7 @@ virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms, virDomainObjPtr obj; obj = virHashSearch(doms->objs, virDomainObjListSearchName, name); if (obj) - virDomainObjLock(obj); + virDomainObjRef(obj); return obj; } @@ -967,6 +966,12 @@ static void virDomainObjFree(virDomainObjPtr dom) { if (!dom) return; + virDomainObjUnref(dom); +} + +static void doDomainObjFree(virObjectPtr obj) +{ + virDomainObjPtr dom = (virDomainObjPtr)obj; VIR_DEBUG("obj=%p", dom); virDomainDefFree(dom->def); @@ -984,21 +989,13 @@ static void virDomainObjFree(virDomainObjPtr dom) void virDomainObjRef(virDomainObjPtr dom) { - dom->refs++; - VIR_DEBUG("obj=%p refs=%d", dom, dom->refs); + virObjectRef(&dom->obj); } -int virDomainObjUnref(virDomainObjPtr dom) +void virDomainObjUnref(virDomainObjPtr dom) { - dom->refs--; - VIR_DEBUG("obj=%p refs=%d", dom, dom->refs); - if (dom->refs == 0) { - virDomainObjUnlock(dom); - virDomainObjFree(dom); - return 0; - } - return dom->refs; + virObjectUnref(&dom->obj); } static virDomainObjPtr virDomainObjNew(virCapsPtr caps) @@ -1010,6 +1007,11 @@ static virDomainObjPtr virDomainObjNew(virCapsPtr caps) return NULL; } + if (virObjectInit(&domain->obj, doDomainObjFree)) { + VIR_FREE(domain); + return NULL; + } + if (caps->privateDataAllocFunc && !(domain->privateData = (caps->privateDataAllocFunc)())) { virReportOOMError(); @@ -1027,9 +1029,7 @@ static virDomainObjPtr virDomainObjNew(virCapsPtr caps) return NULL; } - virDomainObjLock(domain); domain->state = VIR_DOMAIN_SHUTOFF; - domain->refs = 1; virDomainSnapshotObjListInit(&domain->snapshots); @@ -1075,8 +1075,10 @@ virDomainObjPtr virDomainAssignDef(virCapsPtr caps, domain->def = def; virUUIDFormat(def->uuid, uuidstr); + virDomainObjRef(domain); if (virHashAddEntry(doms->objs, uuidstr, domain) < 0) { - VIR_FREE(domain); + virDomainObjUnref(domain); + virDomainObjFree(domain); return NULL; } @@ -1149,9 +1151,7 @@ virDomainObjGetPersistentDef(virCapsPtr caps, } /* - * The caller must hold a lock on the driver owning 'doms', - * and must also have locked 'dom', to ensure no one else - * is either waiting for 'dom' or still usingn it + * The caller must hold a lock on the driver owning 'doms'. */ void virDomainRemoveInactive(virDomainObjListPtr doms, virDomainObjPtr dom) @@ -1159,9 +1159,8 @@ void virDomainRemoveInactive(virDomainObjListPtr doms, char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->def->uuid, uuidstr); - virDomainObjUnlock(dom); - virHashRemoveEntry(doms->objs, uuidstr); + virDomainObjUnref(dom); } @@ -6146,7 +6145,7 @@ static virDomainObjPtr virDomainObjParseXML(virCapsPtr caps, error: /* obj was never shared, so unref should return 0 */ - ignore_value(virDomainObjUnref(obj)); + virDomainObjUnref(obj); return NULL; } @@ -8449,10 +8448,12 @@ static virDomainObjPtr virDomainLoadConfig(virCapsPtr caps, if (!(dom = virDomainAssignDef(caps, doms, def, false))) goto error; + virDomainObjLock(dom); dom->autostart = autostart; if (notify) (*notify)(dom, newVM, opaque); + virDomainObjUnlock(dom); VIR_FREE(configFile); VIR_FREE(autostartLink); @@ -8501,9 +8502,8 @@ static virDomainObjPtr virDomainLoadStatus(virCapsPtr caps, return obj; error: - /* obj was never shared, so unref should return 0 */ if (obj) - ignore_value(virDomainObjUnref(obj)); + virDomainObjUnref(obj); VIR_FREE(statusFile); return NULL; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 10e73cb..3218672 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -40,6 +40,7 @@ # include "nwfilter_conf.h" # include "macvtap.h" # include "sysinfo.h" +# include "virobject.h" /* Private component of virDomainXMLFlags */ typedef enum { @@ -1144,8 +1145,8 @@ struct _virDomainDef { typedef struct _virDomainObj virDomainObj; typedef virDomainObj *virDomainObjPtr; struct _virDomainObj { + virObject obj; virMutex lock; - int refs; int pid; int state; @@ -1226,8 +1227,7 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def, void virDomainDefFree(virDomainDefPtr vm); void virDomainObjRef(virDomainObjPtr vm); -/* Returns 1 if the object was freed, 0 if more refs exist */ -int virDomainObjUnref(virDomainObjPtr vm) ATTRIBUTE_RETURN_CHECK; +void virDomainObjUnref(virDomainObjPtr vm); /* live == true means def describes an active domain (being migrated or * restored) as opposed to a new persistent configuration of the domain */ diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c index 88cd4c8..c08ed3b 100644 --- a/src/openvz/openvz_conf.c +++ b/src/openvz/openvz_conf.c @@ -472,6 +472,11 @@ int openvzLoadDomains(struct openvz_driver *driver) { if (VIR_ALLOC(dom) < 0) goto no_memory; + if (virObjectInit(&dom->obj, NULL)) { + VIR_FREE(dom); + goto cleanup; + } + if (virMutexInit(&dom->lock) < 0) { openvzError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot initialize mutex")); @@ -489,7 +494,6 @@ int openvzLoadDomains(struct openvz_driver *driver) { else dom->state = VIR_DOMAIN_RUNNING; - dom->refs = 1; dom->pid = veid; dom->def->id = dom->state == VIR_DOMAIN_SHUTOFF ? -1 : veid; /* XXX OpenVZ doesn't appear to have concept of a transient domain */ @@ -554,7 +558,7 @@ int openvzLoadDomains(struct openvz_driver *driver) { VIR_FREE(outbuf); /* dom hasn't been shared yet, so unref should return 0 */ if (dom) - ignore_value(virDomainObjUnref(dom)); + virDomainObjUnref(dom); return -1; } diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index c2a1f9a..3a3c953 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -457,13 +457,13 @@ int qemuDomainObjBeginJob(virDomainObjPtr obj) } then = timeval_to_ms(now) + QEMU_JOB_WAIT_TIME; - virDomainObjRef(obj); + virDomainObjLock(obj); while (priv->jobActive) { if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) { - /* Safe to ignore value since ref count was incremented above */ - ignore_value(virDomainObjUnref(obj)); - if (errno == ETIMEDOUT) + int err = errno; + virDomainObjUnlock(obj); + if (err == ETIMEDOUT) qemuReportError(VIR_ERR_OPERATION_TIMEOUT, "%s", _("cannot acquire state change lock")); else @@ -482,12 +482,10 @@ int qemuDomainObjBeginJob(virDomainObjPtr obj) } /* - * obj must be locked before calling, qemud_driver must be locked - * * This must be called by anything that will change the VM state * in any way, or anything that will use the QEMU monitor. */ -int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, +int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver ATTRIBUTE_UNUSED, virDomainObjPtr obj) { qemuDomainObjPrivatePtr priv = obj->privateData; @@ -501,20 +499,18 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, } then = timeval_to_ms(now) + QEMU_JOB_WAIT_TIME; - virDomainObjRef(obj); - qemuDriverUnlock(driver); + virDomainObjLock(obj); while (priv->jobActive) { if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) { - /* Safe to ignore value since ref count was incremented above */ - ignore_value(virDomainObjUnref(obj)); - if (errno == ETIMEDOUT) + int err = errno; + virDomainObjUnlock(obj); + if (err == ETIMEDOUT) qemuReportError(VIR_ERR_OPERATION_TIMEOUT, "%s", _("cannot acquire state change lock")); else virReportSystemError(errno, "%s", _("cannot acquire job mutex")); - qemuDriverLock(driver); return -1; } } @@ -524,10 +520,6 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, priv->jobStart = timeval_to_ms(now); memset(&priv->jobInfo, 0, sizeof(priv->jobInfo)); - virDomainObjUnlock(obj); - qemuDriverLock(driver); - virDomainObjLock(obj); - return 0; } @@ -540,7 +532,7 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, * Returns remaining refcount on 'obj', maybe 0 to indicated it * was deleted */ -int qemuDomainObjEndJob(virDomainObjPtr obj) +void qemuDomainObjEndJob(virDomainObjPtr obj) { qemuDomainObjPrivatePtr priv = obj->privateData; @@ -551,7 +543,7 @@ int qemuDomainObjEndJob(virDomainObjPtr obj) memset(&priv->jobInfo, 0, sizeof(priv->jobInfo)); virCondSignal(&priv->jobCond); - return virDomainObjUnref(obj); + virDomainObjUnlock(obj); } @@ -655,7 +647,7 @@ void qemuDomainObjExitRemoteWithDriver(struct qemud_driver *driver, virDomainObjLock(obj); /* Safe to ignore value, since we incremented ref in * qemuDomainObjEnterRemoteWithDriver */ - ignore_value(virDomainObjUnref(obj)); + virDomainObjUnref(obj); } diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 8258900..12fd21d 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -97,7 +97,7 @@ void qemuDomainSetNamespaceHooks(virCapsPtr caps); int qemuDomainObjBeginJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; -int qemuDomainObjEndJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; +void qemuDomainObjEndJob(virDomainObjPtr obj); void qemuDomainObjEnterMonitor(virDomainObjPtr obj); void qemuDomainObjExitMonitor(virDomainObjPtr obj); void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 48fe266..db89402 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -139,7 +139,6 @@ qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaq struct qemuAutostartData *data = opaque; virErrorPtr err; - virDomainObjLock(vm); virResetLastError(); if (qemuDomainObjBeginJobWithDriver(data->driver, vm) < 0) { err = virGetLastError(); @@ -156,12 +155,8 @@ qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaq err ? err->message : _("unknown error")); } - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); } - - if (vm) - virDomainObjUnlock(vm); } @@ -1055,12 +1050,13 @@ static virDomainPtr qemudDomainLookupByID(virConnectPtr conn, goto cleanup; } + virDomainObjLock(vm); dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + virDomainObjUnlock(vm); + virDomainObjUnref(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); return dom; } @@ -1082,12 +1078,13 @@ static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn, goto cleanup; } + virDomainObjLock(vm); dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + virDomainObjUnlock(vm); + virDomainObjUnref(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); return dom; } @@ -1107,12 +1104,13 @@ static virDomainPtr qemudDomainLookupByName(virConnectPtr conn, goto cleanup; } + virDomainObjLock(vm); dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + virDomainObjUnlock(vm); + virDomainObjUnref(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); return dom; } @@ -1133,11 +1131,13 @@ static int qemuDomainIsActive(virDomainPtr dom) _("no domain with matching uuid '%s'"), uuidstr); goto cleanup; } + + virDomainObjLock(obj); ret = virDomainObjIsActive(obj); + virDomainObjUnlock(obj); + virDomainObjUnref(obj); cleanup: - if (obj) - virDomainObjUnlock(obj); return ret; } @@ -1157,11 +1157,13 @@ static int qemuDomainIsPersistent(virDomainPtr dom) _("no domain with matching uuid '%s'"), uuidstr); goto cleanup; } + virDomainObjLock(obj); ret = obj->persistent; + virDomainObjUnlock(obj); cleanup: if (obj) - virDomainObjUnlock(obj); + virDomainObjUnref(obj); return ret; } @@ -1181,11 +1183,13 @@ static int qemuDomainIsUpdated(virDomainPtr dom) _("no domain with matching uuid '%s'"), uuidstr); goto cleanup; } + virDomainObjLock(obj); ret = obj->updated; + virDomainObjUnlock(obj); cleanup: if (obj) - virDomainObjUnlock(obj); + virDomainObjUnref(obj); return ret; } @@ -1239,39 +1243,57 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, qemuDriverLock(driver); if (!(def = virDomainDefParseString(driver->caps, xml, - VIR_DOMAIN_XML_INACTIVE))) + VIR_DOMAIN_XML_INACTIVE))) { + qemuDriverUnlock(driver); goto cleanup; + } - if (virSecurityManagerVerify(driver->securityManager, def) < 0) + if (virSecurityManagerVerify(driver->securityManager, def) < 0) { + qemuDriverUnlock(driver); goto cleanup; + } - if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) + if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) { + qemuDriverUnlock(driver); goto cleanup; + } - if (qemudCanonicalizeMachine(driver, def) < 0) + if (qemudCanonicalizeMachine(driver, def) < 0) { + qemuDriverUnlock(driver); goto cleanup; + } - if (qemuDomainAssignPCIAddresses(def) < 0) + if (qemuDomainAssignPCIAddresses(def) < 0) { + qemuDriverUnlock(driver); goto cleanup; + } if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, - def, false))) + def, false))) { + qemuDriverUnlock(driver); goto cleanup; + } + + qemuDriverUnlock(driver); def = NULL; - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) { + virDomainObjUnref(vm); goto cleanup; /* XXXX free the 'vm' we created ? */ + } if (qemuProcessStart(conn, driver, vm, NULL, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1, NULL, VIR_VM_OP_CREATE) < 0) { qemuAuditDomainStart(vm, "booted", false); - if (qemuDomainObjEndJob(vm) > 0) - virDomainRemoveInactive(&driver->domains, - vm); - vm = NULL; + qemuDomainObjEndJob(vm); + qemuDriverLock(driver); + virDomainRemoveInactive(&driver->domains, + vm); + qemuDriverUnlock(driver); + virDomainObjUnref(vm); goto cleanup; } @@ -1283,17 +1305,13 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; - if (vm && - qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); + virDomainObjUnref(vm); cleanup: virDomainDefFree(def); - if (vm) - virDomainObjUnlock(vm); if (event) qemuDomainEventQueue(driver, event); - qemuDriverUnlock(driver); return dom; } @@ -1307,13 +1325,14 @@ static int qemudDomainSuspend(virDomainPtr dom) { 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; + return -1; } if (!virDomainObjIsActive(vm)) { qemuReportError(VIR_ERR_OPERATION_INVALID, @@ -1354,16 +1373,12 @@ static int qemudDomainSuspend(virDomainPtr dom) { } endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); - + virDomainObjUnref(vm); if (event) qemuDomainEventQueue(driver, event); - qemuDriverUnlock(driver); return ret; } @@ -1376,6 +1391,7 @@ static int qemudDomainResume(virDomainPtr dom) { qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -1409,15 +1425,12 @@ static int qemudDomainResume(virDomainPtr dom) { ret = 0; endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); + virDomainObjUnref(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); if (event) qemuDomainEventQueue(driver, event); - qemuDriverUnlock(driver); return ret; } @@ -1437,7 +1450,7 @@ static int qemudDomainShutdown(virDomainPtr dom) { virUUIDFormat(dom->uuid, uuidstr); qemuReportError(VIR_ERR_NO_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - goto cleanup; + return -1; } if (qemuDomainObjBeginJob(vm) < 0) @@ -1455,12 +1468,10 @@ static int qemudDomainShutdown(virDomainPtr dom) { qemuDomainObjExitMonitor(vm); endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); + virDomainObjUnref(vm); return ret; } @@ -1473,12 +1484,13 @@ static int qemudDomainDestroy(virDomainPtr dom) { 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; + return -1; } if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) @@ -1497,24 +1509,24 @@ static int qemudDomainDestroy(virDomainPtr dom) { qemuAuditDomainStop(vm, "destroyed"); if (!vm->persistent) { - if (qemuDomainObjEndJob(vm) > 0) - virDomainRemoveInactive(&driver->domains, - vm); + qemuDomainObjEndJob(vm); + virDomainObjUnref(vm); + qemuDriverLock(driver); + virDomainRemoveInactive(&driver->domains, vm); + qemuDriverUnlock(driver); vm = NULL; } ret = 0; endjob: - if (vm && - qemuDomainObjEndJob(vm) == 0) - vm = NULL; + if (vm) + qemuDomainObjEndJob(vm); cleanup: if (vm) - virDomainObjUnlock(vm); + virDomainObjUnref(vm); if (event) qemuDomainEventQueue(driver, event); - qemuDriverUnlock(driver); return ret; } @@ -1535,12 +1547,14 @@ static char *qemudDomainGetOSType(virDomainPtr dom) { goto cleanup; } + virDomainObjLock(vm); if (!(type = strdup(vm->def->os.type))) virReportOOMError(); + virDomainObjUnlock(vm); cleanup: if (vm) - virDomainObjUnlock(vm); + virDomainObjUnref(vm); return type; } @@ -1562,11 +1576,13 @@ static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) { goto cleanup; } + virDomainObjLock(vm); ret = vm->def->mem.max_balloon; + virDomainObjUnlock(vm); cleanup: if (vm) - virDomainObjUnlock(vm); + virDomainObjUnref(vm); return ret; } @@ -1594,18 +1610,18 @@ static int qemudDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, virUUIDFormat(dom->uuid, uuidstr); qemuReportError(VIR_ERR_NO_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - goto cleanup; + return -1; } + if (qemuDomainObjBeginJob(vm) < 0) + goto cleanup; + if (newmem > vm->def->mem.max_balloon) { qemuReportError(VIR_ERR_INVALID_ARG, "%s", _("cannot set memory higher than max memory")); - goto cleanup; + goto endjob; } - if (qemuDomainObjBeginJob(vm) < 0) - goto cleanup; - if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_MEM_LIVE)) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -1647,12 +1663,10 @@ static int qemudDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, ret = 0; endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); + virDomainObjUnref(vm); return ret; } @@ -1676,9 +1690,12 @@ static int qemudDomainGetInfo(virDomainPtr dom, virUUIDFormat(dom->uuid, uuidstr); qemuReportError(VIR_ERR_NO_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - goto cleanup; + return -1; } + if (qemuDomainObjBeginJob(vm) < 0) + goto cleanup; + info->state = vm->state; if (!virDomainObjIsActive(vm)) { @@ -1687,7 +1704,7 @@ static int qemudDomainGetInfo(virDomainPtr dom, if (qemudGetProcessInfo(&(info->cpuTime), NULL, vm->pid, 0) < 0) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("cannot read cputime for domain")); - goto cleanup; + goto endjob; } } @@ -1700,8 +1717,6 @@ static int qemudDomainGetInfo(virDomainPtr dom, (vm->def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_NONE)) { info->memory = vm->def->mem.max_balloon; } else if (!priv->jobActive) { - if (qemuDomainObjBeginJob(vm) < 0) - goto cleanup; if (!virDomainObjIsActive(vm)) err = 0; else { @@ -1709,10 +1724,6 @@ static int qemudDomainGetInfo(virDomainPtr dom, err = qemuMonitorGetBalloonInfo(priv->mon, &balloon); qemuDomainObjExitMonitor(vm); } - if (qemuDomainObjEndJob(vm) == 0) { - vm = NULL; - goto cleanup; - } if (err < 0) goto cleanup; @@ -1731,9 +1742,10 @@ static int qemudDomainGetInfo(virDomainPtr dom, info->nrVirtCpu = vm->def->vcpus; ret = 0; +endjob: + qemuDomainObjEndJob(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); + virDomainObjUnref(vm); return ret; } @@ -2006,9 +2018,8 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_SAVED); if (!vm->persistent) { - if (qemuDomainObjEndJob(vm) > 0) - virDomainRemoveInactive(&driver->domains, - vm); + qemuDomainObjEndJob(vm); + virDomainRemoveInactive(&driver->domains, vm); vm = NULL; } @@ -2021,8 +2032,8 @@ endjob: VIR_WARN0("Unable to resume guest CPUs after save failure"); } } - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + + qemuDomainObjEndJob(vm); } cleanup: @@ -2303,6 +2314,7 @@ static int qemudDomainCoreDump(virDomainPtr dom, qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -2311,11 +2323,12 @@ static int qemudDomainCoreDump(virDomainPtr dom, _("no domain with matching uuid '%s'"), uuidstr); goto cleanup; } - priv = vm->privateData; if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; + priv = vm->privateData; + if (!virDomainObjIsActive(vm)) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -2367,20 +2380,20 @@ endjob: } } - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; - else if ((ret == 0) && (flags & VIR_DUMP_CRASH) && !vm->persistent) { + qemuDomainObjEndJob(vm); + if ((ret == 0) && (flags & VIR_DUMP_CRASH) && !vm->persistent) { + qemuDriverLock(driver); virDomainRemoveInactive(&driver->domains, vm); + qemuDriverUnlock(driver); vm = NULL; } cleanup: - if (vm) - virDomainObjUnlock(vm); if (event) qemuDomainEventQueue(driver, event); - qemuDriverUnlock(driver); + if (vm) + virDomainObjUnref(vm); return ret; } @@ -2403,9 +2416,6 @@ static void processWatchdogEvent(void *data, void *opaque) break; } - qemuDriverLock(driver); - virDomainObjLock(wdEvent->vm); - if (qemuDomainObjBeginJobWithDriver(driver, wdEvent->vm) < 0) break; @@ -2429,10 +2439,7 @@ static void processWatchdogEvent(void *data, void *opaque) qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Resuming after dump failed")); - if (qemuDomainObjEndJob(wdEvent->vm) > 0) - virDomainObjUnlock(wdEvent->vm); - - qemuDriverUnlock(driver); + qemuDomainObjEndJob(wdEvent->vm); VIR_FREE(dumpfile); } @@ -2533,7 +2540,7 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, virUUIDFormat(dom->uuid, uuidstr); qemuReportError(VIR_ERR_NO_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - goto cleanup; + return -1; } if (qemuDomainObjBeginJob(vm) < 0) @@ -2608,12 +2615,10 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, ret = virDomainSaveConfig(driver->configDir, persistentDef); endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); + virDomainObjUnref(vm); return ret; } @@ -2645,7 +2650,7 @@ qemudDomainPinVcpu(virDomainPtr dom, virUUIDFormat(dom->uuid, uuidstr); qemuReportError(VIR_ERR_NO_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - goto cleanup; + return -1; } if (!virDomainObjIsActive(vm)) { @@ -2690,8 +2695,7 @@ qemudDomainPinVcpu(virDomainPtr dom, ret = 0; cleanup: - if (vm) - virDomainObjUnlock(vm); + virDomainObjUnref(vm); return ret; } @@ -2717,7 +2721,7 @@ qemudDomainGetVcpus(virDomainPtr dom, virUUIDFormat(dom->uuid, uuidstr); qemuReportError(VIR_ERR_NO_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - goto cleanup; + return -1; } if (!virDomainObjIsActive(vm)) { @@ -2780,8 +2784,7 @@ qemudDomainGetVcpus(virDomainPtr dom, ret = maxinfo; cleanup: - if (vm) - virDomainObjUnlock(vm); + virDomainObjUnref(vm); return ret; } @@ -3164,9 +3167,8 @@ qemuDomainRestore(virConnectPtr conn, ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, &header, path); - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; - else if (ret < 0 && !vm->persistent) { + qemuDomainObjEndJob(vm); + if (ret < 0 && !vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); vm = NULL; } @@ -3174,8 +3176,6 @@ qemuDomainRestore(virConnectPtr conn, cleanup: virDomainDefFree(def); VIR_FORCE_CLOSE(fd); - if (vm) - virDomainObjUnlock(vm); qemuDriverUnlock(driver); return ret; } @@ -3254,10 +3254,7 @@ static char *qemudDomainDumpXML(virDomainPtr dom, qemuDomainObjEnterMonitorWithDriver(driver, vm); err = qemuMonitorGetBalloonInfo(priv->mon, &balloon); qemuDomainObjExitMonitorWithDriver(driver, vm); - if (qemuDomainObjEndJob(vm) == 0) { - vm = NULL; - goto cleanup; - } + qemuDomainObjEndJob(vm); if (err < 0) goto cleanup; if (err > 0) @@ -3269,8 +3266,6 @@ static char *qemudDomainDumpXML(virDomainPtr dom, ret = qemuDomainFormatXML(driver, vm, flags); cleanup: - if (vm) - virDomainObjUnlock(vm); qemuDriverUnlock(driver); return ret; } @@ -3487,12 +3482,9 @@ qemudDomainStartWithFlags(virDomainPtr dom, unsigned int flags) (flags & VIR_DOMAIN_START_PAUSED) != 0); endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); qemuDriverUnlock(driver); return ret; } @@ -3859,8 +3851,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom, ret = -1; endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); cleanup: if (cgroup) @@ -3868,8 +3859,6 @@ cleanup: qemuCapsFree(qemuCaps); virDomainDeviceDefFree(dev); - if (vm) - virDomainObjUnlock(vm); qemuDriverUnlock(driver); return ret; } @@ -3993,8 +3982,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, ret = -1; endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); cleanup: if (cgroup) @@ -4002,8 +3990,6 @@ cleanup: qemuCapsFree(qemuCaps); virDomainDeviceDefFree(dev); - if (vm) - virDomainObjUnlock(vm); qemuDriverUnlock(driver); return ret; } @@ -4083,14 +4069,11 @@ static int qemudDomainDetachDevice(virDomainPtr dom, ret = -1; endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); cleanup: qemuCapsFree(qemuCaps); virDomainDeviceDefFree(dev); - if (vm) - virDomainObjUnlock(vm); qemuDriverUnlock(driver); return ret; } @@ -4802,12 +4785,9 @@ qemudDomainBlockStats (virDomainPtr dom, qemuDomainObjExitMonitor(vm); endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); return ret; } @@ -4906,12 +4886,9 @@ qemudDomainMemoryStats (virDomainPtr dom, "%s", _("domain is not running")); } - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); return ret; } @@ -5064,15 +5041,12 @@ qemudDomainMemoryPeek (virDomainPtr dom, ret = 0; endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); cleanup: VIR_FORCE_CLOSE(fd); unlink (tmp); VIR_FREE(tmp); - if (vm) - virDomainObjUnlock(vm); return ret; } @@ -5218,16 +5192,13 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom, qemuDomainObjExitMonitor(vm); } - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); } else { ret = 0; } cleanup: VIR_FORCE_CLOSE(fd); - if (vm) - virDomainObjUnlock(vm); return ret; } @@ -6067,8 +6038,8 @@ cleanup: _("resuming after snapshot failed")); } - if (qemuDomainObjEndJob(vm) == 0) - *vmptr = NULL; + qemuDomainObjEndJob(vm); + *vmptr = NULL; return ret; } @@ -6438,9 +6409,8 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT); if (!vm->persistent) { - if (qemuDomainObjEndJob(vm) > 0) - virDomainRemoveInactive(&driver->domains, vm); - vm = NULL; + qemuDomainObjEndJob(vm); + virDomainRemoveInactive(&driver->domains, vm); goto cleanup; } } @@ -6454,14 +6424,12 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, ret = 0; endjob: - if (vm && qemuDomainObjEndJob(vm) == 0) - vm = NULL; + if (vm) + qemuDomainObjEndJob(vm); cleanup: if (event) qemuDomainEventQueue(driver, event); - if (vm) - virDomainObjUnlock(vm); qemuDriverUnlock(driver); return ret; @@ -6675,12 +6643,9 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot, ret = qemuDomainSnapshotDiscard(driver, vm, snap); endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; + qemuDomainObjEndJob(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); qemuDriverUnlock(driver); return ret; } @@ -6727,14 +6692,9 @@ static int qemuDomainMonitorCommand(virDomainPtr domain, const char *cmd, qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp); qemuDomainObjExitMonitorWithDriver(driver, vm); - if (qemuDomainObjEndJob(vm) == 0) { - vm = NULL; - goto cleanup; - } + qemuDomainObjEndJob(vm); cleanup: - if (vm) - virDomainObjUnlock(vm); qemuDriverUnlock(driver); return ret; } diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 43741e1..462e6be 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -336,8 +336,8 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, qemuAuditDomainStart(vm, "migrated", false); qemuProcessStop(driver, vm, 0); if (!vm->persistent) { - if (qemuDomainObjEndJob(vm) > 0) - virDomainRemoveInactive(&driver->domains, vm); + qemuDomainObjEndJob(vm); + virDomainRemoveInactive(&driver->domains, vm); vm = NULL; } virReportSystemError(errno, "%s", @@ -353,9 +353,10 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, ret = 0; endjob: - if (vm && - qemuDomainObjEndJob(vm) == 0) + if (vm) { + qemuDomainObjEndJob(vm); vm = NULL; + } /* We set a fake job active which is held across * API calls until the finish() call. This prevents @@ -374,11 +375,8 @@ cleanup: virDomainDefFree(def); VIR_FORCE_CLOSE(dataFD[0]); VIR_FORCE_CLOSE(dataFD[1]); - if (vm) - virDomainObjUnlock(vm); if (event) qemuDomainEventQueue(driver, event); - qemuDriverUnlock(driver); return ret; } @@ -530,8 +528,8 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver, * should have already done that. */ if (!vm->persistent) { - if (qemuDomainObjEndJob(vm) > 0) - virDomainRemoveInactive(&driver->domains, vm); + qemuDomainObjEndJob(vm); + virDomainRemoveInactive(&driver->domains, vm); vm = NULL; } goto endjob; @@ -544,9 +542,10 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver, ret = 0; endjob: - if (vm && - qemuDomainObjEndJob(vm) == 0) + if (vm) { + qemuDomainObjEndJob(vm); vm = NULL; + } /* We set a fake job active which is held across * API calls until the finish() call. This prevents @@ -565,8 +564,6 @@ cleanup: virDomainDefFree(def); if (ret != 0) VIR_FREE(*uri_out); - if (vm) - virDomainObjUnlock(vm); if (event) qemuDomainEventQueue(driver, event); return ret; @@ -1090,8 +1087,8 @@ int qemuMigrationPerform(struct qemud_driver *driver, VIR_DOMAIN_EVENT_STOPPED_MIGRATED); if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) { virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm); - if (qemuDomainObjEndJob(vm) > 0) - virDomainRemoveInactive(&driver->domains, vm); + qemuDomainObjEndJob(vm); + virDomainRemoveInactive(&driver->domains, vm); vm = NULL; } ret = 0; @@ -1112,13 +1109,12 @@ endjob: VIR_DOMAIN_EVENT_RESUMED, VIR_DOMAIN_EVENT_RESUMED_MIGRATED); } - if (vm && - qemuDomainObjEndJob(vm) == 0) + if (vm) { + qemuDomainObjEndJob(vm); vm = NULL; + } cleanup: - if (vm) - virDomainObjUnlock(vm); if (event) qemuDomainEventQueue(driver, event); return ret; @@ -1266,20 +1262,19 @@ qemuMigrationFinish(struct qemud_driver *driver, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_FAILED); if (!vm->persistent) { - if (qemuDomainObjEndJob(vm) > 0) - virDomainRemoveInactive(&driver->domains, vm); + qemuDomainObjEndJob(vm); + virDomainRemoveInactive(&driver->domains, vm); vm = NULL; } } endjob: - if (vm && - qemuDomainObjEndJob(vm) == 0) + if (vm) { + qemuDomainObjEndJob(vm); vm = NULL; + } cleanup: - if (vm) - virDomainObjUnlock(vm); if (event) qemuDomainEventQueue(driver, event); return dom; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 48ecd5c..244b22a 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -604,8 +604,8 @@ static void qemuProcessHandleMonitorDestroy(qemuMonitorPtr mon, priv = vm->privateData; if (priv->mon == mon) priv->mon = NULL; - if (virDomainObjUnref(vm) > 0) - virDomainObjUnlock(vm); + virDomainObjUnlock(vm); + virDomainObjUnref(vm); } static qemuMonitorCallbacks monitorCallbacks = { @@ -644,7 +644,7 @@ qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm) /* Safe to ignore value since ref count was incremented above */ if (priv->mon == NULL) - ignore_value(virDomainObjUnref(vm)); + virDomainObjUnref(vm); if (virSecurityManagerClearSocketLabel(driver->securityManager, vm) < 0) { VIR_ERROR(_("Failed to clear security context for monitor for %s"), @@ -1940,10 +1940,6 @@ qemuProcessReconnect(void *payload, const void *name ATTRIBUTE_UNUSED, void *opa priv = obj->privateData; - /* Hold an extra reference because we can't allow 'vm' to be - * deleted if qemuConnectMonitor() failed */ - virDomainObjRef(obj); - /* XXX check PID liveliness & EXE path */ if (qemuConnectMonitor(driver, obj) < 0) goto error; @@ -1975,8 +1971,7 @@ qemuProcessReconnect(void *payload, const void *name ATTRIBUTE_UNUSED, void *opa if (obj->def->id >= driver->nextvmid) driver->nextvmid = obj->def->id + 1; - if (virDomainObjUnref(obj) > 0) - virDomainObjUnlock(obj); + virDomainObjUnlock(obj); qemuCapsFree(qemuCaps); return; @@ -1984,21 +1979,17 @@ qemuProcessReconnect(void *payload, const void *name ATTRIBUTE_UNUSED, void *opa error: qemuCapsFree(qemuCaps); if (!virDomainObjIsActive(obj)) { - if (virDomainObjUnref(obj) > 0) - virDomainObjUnlock(obj); + virDomainObjUnlock(obj); return; } - if (virDomainObjUnref(obj) > 0) { - /* We can't get the monitor back, so must kill the VM - * to remove danger of it ending up running twice if - * user tries to start it again later */ - qemuProcessStop(driver, obj, 0); - if (!obj->persistent) - virDomainRemoveInactive(&driver->domains, obj); - else - virDomainObjUnlock(obj); - } + /* We can't get the monitor back, so must kill the VM + * to remove danger of it ending up running twice if + * user tries to start it again later */ + qemuProcessStop(driver, obj, 0); + virDomainObjUnlock(obj); + if (!obj->persistent) + virDomainRemoveInactive(&driver->domains, obj); } /** diff --git a/src/vmware/vmware_conf.c b/src/vmware/vmware_conf.c index 6339248..6b59b18 100644 --- a/src/vmware/vmware_conf.c +++ b/src/vmware/vmware_conf.c @@ -205,7 +205,7 @@ cleanup: VIR_FREE(vmx); /* any non-NULL vm here has not been shared, so unref will return 0 */ if (vm) - ignore_value(virDomainObjUnref(vm)); + virDomainObjUnref(vm); return ret; } -- 1.7.3.1 -- Thanks, Hu Tao From hutao at cn.fujitsu.com Wed Apr 6 07:20:01 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Wed, 6 Apr 2011 15:20:01 +0800 Subject: [libvirt] [PATCH 5/6] remove qemuDomainObjEnterMonitorWithDriver and qemuDomainObjExitMonitorWithDriver In-Reply-To: References: Message-ID: Bodies of qemuDomainObjEnterMonitorWithDriver/qemuDomainObjExitMonitorWithDriver are the same as qemuDomainObjEnterMonitor/qemuDomainObjExitMonitor, so remove them. --- src/qemu/qemu_domain.c | 32 ---------------- src/qemu/qemu_domain.h | 4 -- src/qemu/qemu_driver.c | 20 +++++----- src/qemu/qemu_hotplug.c | 90 ++++++++++++++++++++++---------------------- src/qemu/qemu_migration.c | 46 +++++++++++----------- src/qemu/qemu_process.c | 36 +++++++++--------- 6 files changed, 96 insertions(+), 132 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index d11dc5f..b9bf8a4 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -578,38 +578,6 @@ void qemuDomainObjExitMonitor(virDomainObjPtr obj) } -/* - * obj must be locked before calling, qemud_driver must be locked - * - * To be called immediately before any QEMU monitor API call - * Must have already called qemuDomainObjBeginJob(). - * - * To be followed with qemuDomainObjExitMonitorWithDriver() once complete - */ -void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, - virDomainObjPtr obj) -{ - qemuDomainObjPrivatePtr priv = obj->privateData; - - virDomainObjUnlock(obj); - qemuMonitorLock(priv->mon); -} - - -/* obj must NOT be locked before calling, qemud_driver must be unlocked, - * and will be locked after returning - * - * Should be paired with an earlier qemuDomainObjEnterMonitorWithDriver() call - */ -void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, - virDomainObjPtr obj) -{ - qemuDomainObjPrivatePtr priv = obj->privateData; - - qemuMonitorUnlock(priv->mon); - virDomainObjLock(obj); -} - void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver, virDomainObjPtr obj) { diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 12fd21d..75ad5d9 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -100,10 +100,6 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, void qemuDomainObjEndJob(virDomainObjPtr obj); void qemuDomainObjEnterMonitor(virDomainObjPtr obj); void qemuDomainObjExitMonitor(virDomainObjPtr obj); -void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, - virDomainObjPtr obj); -void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, - virDomainObjPtr obj); void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver, virDomainObjPtr obj); void qemuDomainObjExitRemoteWithDriver(struct qemud_driver *driver, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index db89402..887a865 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3251,9 +3251,9 @@ static char *qemudDomainDumpXML(virDomainPtr dom, if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); err = qemuMonitorGetBalloonInfo(priv->mon, &balloon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuDomainObjEndJob(vm); if (err < 0) goto cleanup; @@ -6026,9 +6026,9 @@ qemuDomainSnapshotCreateActive(virConnectPtr conn, } } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); cleanup: if (resume && virDomainObjIsActive(vm) && @@ -6359,9 +6359,9 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, if (virDomainObjIsActive(vm)) { priv = vm->privateData; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); rc = qemuMonitorLoadSnapshot(priv->mon, snap->def->name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (rc < 0) goto endjob; } @@ -6478,10 +6478,10 @@ static int qemuDomainSnapshotDiscard(struct qemud_driver *driver, } else { priv = vm->privateData; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); /* we continue on even in the face of error */ qemuMonitorDeleteSnapshot(priv->mon, snap->def->name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); } if (snap == vm->current_snapshot) { @@ -6689,9 +6689,9 @@ static int qemuDomainMonitorCommand(virDomainPtr domain, const char *cmd, if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuDomainObjEndJob(vm); cleanup: diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index b03f774..c1e893b 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -91,7 +91,7 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver, goto error; priv = vm->privateData; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (disk->src) { const char *format = NULL; if (disk->type != VIR_DOMAIN_DISK_TYPE_DIR) { @@ -106,7 +106,7 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver, } else { ret = qemuMonitorEjectMedia(priv->mon, driveAlias, force); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditDisk(vm, origdisk, disk, "update", ret >= 0); @@ -178,7 +178,7 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver, goto error; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { ret = qemuMonitorAddDrive(priv->mon, drivestr); if (ret == 0) { @@ -201,7 +201,7 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver, memcpy(&disk->info.addr.pci, &guestAddr, sizeof(guestAddr)); } } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditDisk(vm, NULL, disk, "attach", ret >= 0); @@ -269,7 +269,7 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver, goto cleanup; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { ret = qemuMonitorAddDevice(priv->mon, devstr); } else { @@ -277,7 +277,7 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver, type, &controller->info.addr.pci); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (ret == 0) { controller->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; @@ -408,7 +408,7 @@ int qemuDomainAttachSCSIDisk(struct qemud_driver *driver, goto error; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { ret = qemuMonitorAddDrive(priv->mon, drivestr); if (ret == 0) { @@ -433,7 +433,7 @@ int qemuDomainAttachSCSIDisk(struct qemud_driver *driver, memcpy(&disk->info.addr.drive, &driveAddr, sizeof(driveAddr)); } } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditDisk(vm, NULL, disk, "attach", ret >= 0); @@ -501,7 +501,7 @@ int qemuDomainAttachUsbMassstorageDevice(struct qemud_driver *driver, goto error; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { ret = qemuMonitorAddDrive(priv->mon, drivestr); if (ret == 0) { @@ -516,7 +516,7 @@ int qemuDomainAttachUsbMassstorageDevice(struct qemud_driver *driver, } else { ret = qemuMonitorAddUSBDisk(priv->mon, disk->src); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditDisk(vm, NULL, disk, "attach", ret >= 0); @@ -629,24 +629,24 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, goto cleanup; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) && qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { if (qemuMonitorAddNetdev(priv->mon, netstr, tapfd, tapfd_name, vhostfd, vhostfd_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditNet(vm, NULL, net, "attach", false); goto cleanup; } } else { if (qemuMonitorAddHostNetwork(priv->mon, netstr, tapfd, tapfd_name, vhostfd, vhostfd_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditNet(vm, NULL, net, "attach", false); goto cleanup; } } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); VIR_FORCE_CLOSE(tapfd); VIR_FORCE_CLOSE(vhostfd); @@ -665,24 +665,24 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, goto try_remove; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { if (qemuMonitorAddDevice(priv->mon, nicstr) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditNet(vm, NULL, net, "attach", false); goto try_remove; } } else { if (qemuMonitorAddPCINetwork(priv->mon, nicstr, &guestAddr) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditNet(vm, NULL, net, "attach", false); goto try_remove; } net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; memcpy(&net->info.addr.pci, &guestAddr, sizeof(guestAddr)); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditNet(vm, NULL, net, "attach", true); @@ -719,11 +719,11 @@ try_remove: char *netdev_name; if (virAsprintf(&netdev_name, "host%s", net->info.alias) < 0) goto no_memory; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuMonitorRemoveNetdev(priv->mon, netdev_name) < 0) VIR_WARN("Failed to remove network backend for netdev %s", netdev_name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); VIR_FREE(netdev_name); } else { VIR_WARN0("Unable to remove network backend"); @@ -732,11 +732,11 @@ try_remove: char *hostnet_name; if (virAsprintf(&hostnet_name, "host%s", net->info.alias) < 0) goto no_memory; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) VIR_WARN("Failed to remove network backend for vlan %d, net %s", vlan, hostnet_name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); VIR_FREE(hostnet_name); } goto cleanup; @@ -792,18 +792,18 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, qemuCaps))) goto error; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr, configfd, configfd_name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); } else { virDomainDevicePCIAddress guestAddr; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorAddPCIHostDevice(priv->mon, &hostdev->source.subsys.u.pci, &guestAddr); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); hostdev->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; memcpy(&hostdev->info.addr.pci, &guestAddr, sizeof(guestAddr)); @@ -879,14 +879,14 @@ int qemuDomainAttachHostUsbDevice(struct qemud_driver *driver, goto error; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) ret = qemuMonitorAddDevice(priv->mon, devstr); else ret = qemuMonitorAddUSBDeviceExact(priv->mon, hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditHostdev(vm, hostdev, "attach", ret == 0); if (ret < 0) goto error; @@ -1143,7 +1143,7 @@ int qemuDomainDetachPciDiskDevice(struct qemud_driver *driver, goto cleanup; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { qemuDomainObjExitMonitor(vm); @@ -1160,7 +1160,7 @@ int qemuDomainDetachPciDiskDevice(struct qemud_driver *driver, /* disconnect guest from host device */ qemuMonitorDriveDel(priv->mon, drivestr); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditDisk(vm, detach, NULL, "detach", ret >= 0); @@ -1234,7 +1234,7 @@ int qemuDomainDetachDiskDevice(struct qemud_driver *driver, goto cleanup; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { qemuDomainObjExitMonitor(vm); goto cleanup; @@ -1243,7 +1243,7 @@ int qemuDomainDetachDiskDevice(struct qemud_driver *driver, /* disconnect guest from host device */ qemuMonitorDriveDel(priv->mon, drivestr); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditDisk(vm, detach, NULL, "detach", ret >= 0); @@ -1362,7 +1362,7 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver, goto cleanup; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) { qemuDomainObjExitMonitor(vm); @@ -1375,7 +1375,7 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver, goto cleanup; } } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (vm->def->ncontrollers > 1) { memmove(vm->def->controllers + i, @@ -1450,7 +1450,7 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver, goto cleanup; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { qemuDomainObjExitMonitor(vm); @@ -1460,7 +1460,7 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver, } else { if (qemuMonitorRemovePCIDevice(priv->mon, &detach->info.addr.pci) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditNet(vm, detach, NULL, "detach", false); goto cleanup; } @@ -1469,18 +1469,18 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver, if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) && qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditNet(vm, detach, NULL, "detach", false); goto cleanup; } } else { if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditNet(vm, detach, NULL, "detach", false); goto cleanup; } } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditNet(vm, detach, NULL, "detach", true); @@ -1576,13 +1576,13 @@ int qemuDomainDetachHostPciDevice(struct qemud_driver *driver, return -1; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); } else { ret = qemuMonitorRemovePCIDevice(priv->mon, &detach->info.addr.pci); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditHostdev(vm, detach, "detach", ret == 0); if (ret < 0) return -1; @@ -1679,9 +1679,9 @@ int qemuDomainDetachHostUsbDevice(struct qemud_driver *driver, return -1; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); qemuAuditHostdev(vm, detach, "detach", ret == 0); if (ret < 0) return -1; @@ -1755,7 +1755,7 @@ qemuDomainChangeGraphicsPasswords(struct qemud_driver *driver, if (!auth->passwd && !driver->vncPassword) return 0; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorSetPassword(priv->mon, type, auth->passwd ? auth->passwd : defaultPasswd, @@ -1798,7 +1798,7 @@ qemuDomainChangeGraphicsPasswords(struct qemud_driver *driver, } cleanup: - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); return ret; } diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 6af2e24..5076cd5 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -123,9 +123,9 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) if (priv->jobSignals & QEMU_JOB_SIGNAL_CANCEL) { priv->jobSignals ^= QEMU_JOB_SIGNAL_CANCEL; VIR_DEBUG0("Cancelling job at client request"); - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); rc = qemuMonitorMigrateCancel(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (rc < 0) { VIR_WARN0("Unable to cancel job"); } @@ -140,9 +140,9 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME; priv->jobSignalsData.migrateDowntime = 0; VIR_DEBUG("Setting migration downtime to %llums", ms); - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); rc = qemuMonitorSetMigrationDowntime(priv->mon, ms); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (rc < 0) VIR_WARN0("Unable to set migration downtime"); } else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_SPEED) { @@ -151,9 +151,9 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_SPEED; priv->jobSignalsData.migrateBandwidth = 0; VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth); - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); rc = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (rc < 0) VIR_WARN0("Unable to set migration speed"); } @@ -167,13 +167,13 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) goto cleanup; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); rc = qemuMonitorGetMigrationStatus(priv->mon, &status, &memProcessed, &memRemaining, &memTotal); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (rc < 0) { priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; @@ -602,10 +602,10 @@ static int doNativeMigrate(struct qemud_driver *driver, goto cleanup; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (resource > 0 && qemuMonitorSetMigrationSpeed(priv->mon, resource) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); goto cleanup; } @@ -617,10 +617,10 @@ static int doNativeMigrate(struct qemud_driver *driver, if (qemuMonitorMigrateToHost(priv->mon, background_flags, uribits->server, uribits->port) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); goto cleanup; } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (qemuMigrationWaitForCompletion(driver, vm) < 0) goto cleanup; @@ -804,7 +804,7 @@ static int doTunnelMigrate(struct qemud_driver *driver, } /* 3. start migration on source */ - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (flags & VIR_MIGRATE_NON_SHARED_DISK) background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK; if (flags & VIR_MIGRATE_NON_SHARED_INC) @@ -819,7 +819,7 @@ static int doTunnelMigrate(struct qemud_driver *driver, } else { internalret = -1; } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (internalret < 0) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("tunnelled migration monitor command failed")); @@ -838,16 +838,16 @@ static int doTunnelMigrate(struct qemud_driver *driver, /* it is also possible that the migrate didn't fail initially, but * rather failed later on. Check the output of "info migrate" */ - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuMonitorGetMigrationStatus(priv->mon, &status, &transferred, &remaining, &total) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); goto cancel; } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (status == QEMU_MONITOR_MIGRATION_STATUS_ERROR) { qemuReportError(VIR_ERR_OPERATION_FAILED, @@ -868,9 +868,9 @@ static int doTunnelMigrate(struct qemud_driver *driver, cancel: if (retval != 0 && virDomainObjIsActive(vm)) { - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); qemuMonitorMigrateCancel(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); } finish: @@ -1337,7 +1337,7 @@ qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm, restoreLabel = true; } - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (!compressor) { const char *args[] = { "cat", NULL }; @@ -1365,11 +1365,11 @@ qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm, if (virSetCloseExec(pipeFD[1]) < 0) { virReportSystemError(errno, "%s", _("Unable to set cloexec flag")); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); goto cleanup; } if (virCommandRunAsync(cmd, NULL) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); goto cleanup; } rc = qemuMonitorMigrateToFd(priv->mon, @@ -1384,7 +1384,7 @@ qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm, args, path, offset); } } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (rc < 0) goto cleanup; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 4b9087f..a2bd94c 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -654,9 +654,9 @@ qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm) qemuMonitorRef(priv->mon); - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorSetCapabilities(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); error: @@ -1062,9 +1062,9 @@ qemuProcessWaitForMonitor(struct qemud_driver* driver, goto cleanup; priv = vm->privateData; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorGetPtyPaths(priv->mon, paths); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); VIR_DEBUG("qemuMonitorGetPtyPaths returned %i", ret); if (ret == 0) @@ -1115,12 +1115,12 @@ qemuProcessDetectVcpuPIDs(struct qemud_driver *driver, /* What follows is now all KVM specific */ - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if ((ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids)) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); return -1; } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); /* Treat failure to get VCPU<->PID mapping as non-fatal */ if (ncpupids == 0) @@ -1313,10 +1313,10 @@ qemuProcessInitPasswords(virConnectPtr conn, goto cleanup; alias = vm->def->disks[i]->info.alias; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorSetDrivePassphrase(priv->mon, alias, secret); VIR_FREE(secret); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (ret < 0) goto cleanup; } @@ -1704,10 +1704,10 @@ qemuProcessInitPCIAddresses(struct qemud_driver *driver, int ret; qemuMonitorPCIAddress *addrs = NULL; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); naddrs = qemuMonitorGetAllPCIAddresses(priv->mon, &addrs); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); ret = qemuProcessDetectPCIAddresses(vm, addrs, naddrs); @@ -1860,9 +1860,9 @@ qemuProcessStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm, int ret; qemuDomainObjPrivatePtr priv = vm->privateData; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorStartCPUs(priv->mon, conn); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (ret == 0) { vm->state = VIR_DOMAIN_RUNNING; } @@ -1878,9 +1878,9 @@ int qemuProcessStopCPUs(struct qemud_driver *driver, virDomainObjPtr vm) qemuDomainObjPrivatePtr priv = vm->privateData; vm->state = VIR_DOMAIN_PAUSED; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorStopCPUs(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (ret < 0) { vm->state = oldState; } @@ -2351,12 +2351,12 @@ int qemuProcessStart(virConnectPtr conn, VIR_DEBUG0("Setting initial memory amount"); cur_balloon = vm->def->mem.cur_balloon; - qemuDomainObjEnterMonitorWithDriver(driver, vm); + qemuDomainObjEnterMonitor(vm); if (qemuMonitorSetBalloon(priv->mon, cur_balloon) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); goto cleanup; } - qemuDomainObjExitMonitorWithDriver(driver, vm); + qemuDomainObjExitMonitor(vm); if (!start_paused) { VIR_DEBUG0("Starting domain CPUs"); -- 1.7.3.1 -- Thanks, Hu Tao From hutao at cn.fujitsu.com Wed Apr 6 07:20:09 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Wed, 6 Apr 2011 15:20:09 +0800 Subject: [libvirt] [PATCH 6/6] remove qemuDomainObjBeginJobWithDriver In-Reply-To: References: Message-ID: <726cc7aabcbef1b27fa7db038a0a47695d105e45.1302069479.git.hutao@cn.fujitsu.com> The body of qemuDomainObjBeginJobWithDriver is the same as qemuDomainObjBeginJob, so remove it. --- src/qemu/qemu_domain.c | 41 ----------------------------------------- src/qemu/qemu_domain.h | 2 -- src/qemu/qemu_driver.c | 36 ++++++++++++++++++------------------ src/qemu/qemu_migration.c | 8 ++++---- 4 files changed, 22 insertions(+), 65 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index b9bf8a4..9a9088a 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -481,47 +481,6 @@ int qemuDomainObjBeginJob(virDomainObjPtr obj) return 0; } -/* - * This must be called by anything that will change the VM state - * in any way, or anything that will use the QEMU monitor. - */ -int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver ATTRIBUTE_UNUSED, - virDomainObjPtr obj) -{ - qemuDomainObjPrivatePtr priv = obj->privateData; - struct timeval now; - unsigned long long then; - - if (gettimeofday(&now, NULL) < 0) { - virReportSystemError(errno, "%s", - _("cannot get time of day")); - return -1; - } - then = timeval_to_ms(now) + QEMU_JOB_WAIT_TIME; - - virDomainObjLock(obj); - - while (priv->jobActive) { - if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) { - int err = errno; - virDomainObjUnlock(obj); - if (err == ETIMEDOUT) - qemuReportError(VIR_ERR_OPERATION_TIMEOUT, - "%s", _("cannot acquire state change lock")); - else - virReportSystemError(errno, - "%s", _("cannot acquire job mutex")); - return -1; - } - } - priv->jobActive = QEMU_JOB_UNSPECIFIED; - priv->jobSignals = 0; - memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData)); - priv->jobStart = timeval_to_ms(now); - memset(&priv->jobInfo, 0, sizeof(priv->jobInfo)); - - return 0; -} /* * obj must be locked before calling, qemud_driver does not matter diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 75ad5d9..500a882 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -95,8 +95,6 @@ void qemuDomainSetPrivateDataHooks(virCapsPtr caps); void qemuDomainSetNamespaceHooks(virCapsPtr caps); int qemuDomainObjBeginJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; -int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, - virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; void qemuDomainObjEndJob(virDomainObjPtr obj); void qemuDomainObjEnterMonitor(virDomainObjPtr obj); void qemuDomainObjExitMonitor(virDomainObjPtr obj); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 887a865..e1b49e8 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -140,7 +140,7 @@ qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaq virErrorPtr err; virResetLastError(); - if (qemuDomainObjBeginJobWithDriver(data->driver, vm) < 0) { + if (qemuDomainObjBeginJob(vm) < 0) { err = virGetLastError(); VIR_ERROR(_("Failed to start job on VM '%s': %s"), vm->def->name, @@ -1279,7 +1279,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, def = NULL; - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) { + if (qemuDomainObjBeginJob(vm) < 0) { virDomainObjUnref(vm); goto cleanup; /* XXXX free the 'vm' we created ? */ } @@ -1351,7 +1351,7 @@ static int qemudDomainSuspend(virDomainPtr dom) { ret = 0; goto cleanup; } else { - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; if (!virDomainObjIsActive(vm)) { @@ -1401,7 +1401,7 @@ static int qemudDomainResume(virDomainPtr dom) { goto cleanup; } - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; if (!virDomainObjIsActive(vm)) { @@ -1493,7 +1493,7 @@ static int qemudDomainDestroy(virDomainPtr dom) { return -1; } - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; if (!virDomainObjIsActive(vm)) { @@ -1849,7 +1849,7 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, priv = vm->privateData; - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; priv->jobActive = QEMU_JOB_SAVE; @@ -2324,7 +2324,7 @@ static int qemudDomainCoreDump(virDomainPtr dom, goto cleanup; } - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; priv = vm->privateData; @@ -2416,7 +2416,7 @@ static void processWatchdogEvent(void *data, void *opaque) break; } - if (qemuDomainObjBeginJobWithDriver(driver, wdEvent->vm) < 0) + if (qemuDomainObjBeginJob(wdEvent->vm) < 0) break; if (!virDomainObjIsActive(wdEvent->vm)) { @@ -3162,7 +3162,7 @@ qemuDomainRestore(virConnectPtr conn, } def = NULL; - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, &header, path); @@ -3248,7 +3248,7 @@ static char *qemudDomainDumpXML(virDomainPtr dom, /* Don't delay if someone's using the monitor, just use * existing most recent data instead */ if (!priv->jobActive) { - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; qemuDomainObjEnterMonitor(vm); @@ -3469,7 +3469,7 @@ qemudDomainStartWithFlags(virDomainPtr dom, unsigned int flags) goto cleanup; } - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; if (virDomainObjIsActive(vm)) { @@ -3729,7 +3729,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom, goto cleanup; } - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; if (!virDomainObjIsActive(vm)) { @@ -3909,7 +3909,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, goto cleanup; } - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; if (!virDomainObjIsActive(vm)) { @@ -4013,7 +4013,7 @@ static int qemudDomainDetachDevice(virDomainPtr dom, goto cleanup; } - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; if (!virDomainObjIsActive(vm)) { @@ -6007,7 +6007,7 @@ qemuDomainSnapshotCreateActive(virConnectPtr conn, bool resume = false; int ret = -1; - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) return -1; if (vm->state == VIR_DOMAIN_RUNNING) { @@ -6351,7 +6351,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, vm->current_snapshot = snap; - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; if (snap->def->state == VIR_DOMAIN_RUNNING @@ -6617,7 +6617,7 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot, goto cleanup; } - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN) { @@ -6687,7 +6687,7 @@ static int qemuDomainMonitorCommand(virDomainPtr domain, const char *cmd, hmp = !!(flags & VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP); - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; qemuDomainObjEnterMonitor(vm); ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp); diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 5076cd5..fb9009f 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -291,7 +291,7 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, def = NULL; priv = vm->privateData; - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; priv->jobActive = QEMU_JOB_MIGRATION_OUT; @@ -508,7 +508,7 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver, def = NULL; priv = vm->privateData; - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; priv->jobActive = QEMU_JOB_MIGRATION_OUT; @@ -1047,7 +1047,7 @@ int qemuMigrationPerform(struct qemud_driver *driver, int resume = 0; qemuDomainObjPrivatePtr priv = vm->privateData; - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; priv->jobActive = QEMU_JOB_MIGRATION_OUT; @@ -1181,7 +1181,7 @@ qemuMigrationFinish(struct qemud_driver *driver, priv->jobActive = QEMU_JOB_NONE; memset(&priv->jobInfo, 0, sizeof(priv->jobInfo)); - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; /* Did the migration go as planned? If yes, return the domain -- 1.7.3.1 -- Thanks, Hu Tao From wency at cn.fujitsu.com Wed Apr 6 07:25:18 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 06 Apr 2011 15:25:18 +0800 Subject: [libvirt] [PATCH 1/3] qemu: avoid qemu_driver being unlocked twice when virThreadPoolNew() failed In-Reply-To: <20110330054848.GA9404@localhost.localdomain> References: <20110330014929.GA14130@localhost.localdomain> <4D9295D8.6060507@cn.fujitsu.com> <4D92B2E7.5020705@cn.fujitsu.com> <20110330054848.GA9404@localhost.localdomain> Message-ID: <4D9C155E.8030901@cn.fujitsu.com> At 03/30/2011 01:48 PM, Hu Tao Write: > On Wed, Mar 30, 2011 at 12:34:47PM +0800, Wen Congyang wrote: >> --- >> src/qemu/qemu_driver.c | 4 ++++ >> 1 files changed, 4 insertions(+), 0 deletions(-) >> >> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c >> index dd12dc8..f843dc8 100644 >> --- a/src/qemu/qemu_driver.c >> +++ b/src/qemu/qemu_driver.c >> @@ -628,10 +628,14 @@ qemudStartup(int privileged) { >> >> qemuAutostartDomains(qemu_driver); >> >> + /* Lock qemu_drive again as we will modify it */ >> + qemuDriverLock(qemu_driver); >> qemu_driver->workerPool = virThreadPoolNew(0, 1, processWatchdogEvent, qemu_driver); >> if (!qemu_driver->workerPool) >> goto error; >> >> + qemuDriverUnlock(qemu_driver); >> + >> if (conn) >> virConnectClose(conn); >> >> -- >> 1.7.1 > > Looks strange although it's right, What about this? Hmm, we must create workerPool before auto starting domains, because we may use this pool during auto starting domains. I will send v2. > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 104e92d..91432ed 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -624,14 +624,14 @@ qemudStartup(int privileged) { > virHashForEach(qemu_driver->domains.objs, qemuDomainSnapshotLoad, > qemu_driver->snapshotDir); > > - qemuDriverUnlock(qemu_driver); > - > - qemuAutostartDomains(qemu_driver); > - > qemu_driver->workerPool = virThreadPoolNew(0, 1, processWatchdogEvent, qemu_driver); > if (!qemu_driver->workerPool) > goto error; > > + qemuDriverUnlock(qemu_driver); > + > + qemuAutostartDomains(qemu_driver); > + > if (conn) > virConnectClose(conn); > > From wency at cn.fujitsu.com Wed Apr 6 07:37:03 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 06 Apr 2011 15:37:03 +0800 Subject: [libvirt] [PATCH 3/3] hold an extra reference while handling watchdog event In-Reply-To: <20110330060528.GC9404@localhost.localdomain> References: <20110330014929.GA14130@localhost.localdomain> <4D9295D8.6060507@cn.fujitsu.com> <4D92B2E9.1050803@cn.fujitsu.com> <20110330060528.GC9404@localhost.localdomain> Message-ID: <4D9C181F.9090002@cn.fujitsu.com> At 03/30/2011 02:05 PM, Hu Tao Write: > On Wed, Mar 30, 2011 at 12:34:49PM +0800, Wen Congyang wrote: >> If the domain is not persistent, and qemu quited unexpectedly before >> calling processWatchdogEvent(), vm will be freed and the function >> processWatchdogEvent() will be dangerous. >> >> --- >> src/qemu/qemu_driver.c | 10 ++++++---- >> src/qemu/qemu_process.c | 4 ++++ >> 2 files changed, 10 insertions(+), 4 deletions(-) >> >> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c >> index d79d61b..c9c681f 100644 >> --- a/src/qemu/qemu_driver.c >> +++ b/src/qemu/qemu_driver.c >> @@ -2443,15 +2443,17 @@ static void processWatchdogEvent(void *data, void *opaque) >> } >> >> endjob: >> - if (qemuDomainObjEndJob(wdEvent->vm) == 0) >> - wdEvent->vm = NULL; >> + /* Safe to ignore value since ref count was incremented in >> + * qemuProcessHandleWatchdog(). >> + */ >> + ignore_value(qemuDomainObjEndJob(wdEvent->vm)); >> >> unlock: >> - if (wdEvent->vm) >> - virDomainObjUnlock(wdEvent->vm); >> qemuDriverUnlock(driver); >> >> cleanup: >> + if (virDomainObjUnref(wdEvent->vm) > 0) >> + virDomainObjUnlock(wdEvent->vm); > > These two lines should be protected by qemu driver lock. We should not unlock domain here as we reached here without locking domain. Will update this patch. > >> VIR_FREE(wdEvent); >> } >> >> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c >> index e31e1b4..cd8c726 100644 >> --- a/src/qemu/qemu_process.c >> +++ b/src/qemu/qemu_process.c >> @@ -426,6 +426,10 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, >> if (VIR_ALLOC(wdEvent) == 0) { >> wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP; >> wdEvent->vm = vm; >> + /* Hold an extra reference because we can't allow 'vm' to be >> + * deleted before handling watchdog event is finished. >> + */ >> + virDomainObjRef(vm); >> ignore_value(virThreadPoolSendJob(driver->workerPool, wdEvent)); >> } else >> virReportOOMError(); >> -- >> 1.7.1 > From wency at cn.fujitsu.com Wed Apr 6 07:53:11 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 06 Apr 2011 15:53:11 +0800 Subject: [libvirt] [PATCH 1/3] qemu: avoid qemu_driver being unlocked twice when virThreadPoolNew() failed Message-ID: <4D9C1BE7.3000200@cn.fujitsu.com> We do not lock qemu_driver when calling virThreadPoolNew(). If it failed, we will unlock qemu_driver. It is dangerous. We may use this pool during auto starting domains. So we must create it before calling qemuAutostartDomains(). Otherwise, libvirtd will crash. --- src/qemu/qemu_driver.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 48fe266..dd84f65 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -624,14 +624,14 @@ qemudStartup(int privileged) { virHashForEach(qemu_driver->domains.objs, qemuDomainSnapshotLoad, qemu_driver->snapshotDir); - qemuDriverUnlock(qemu_driver); - - qemuAutostartDomains(qemu_driver); - qemu_driver->workerPool = virThreadPoolNew(0, 1, processWatchdogEvent, qemu_driver); if (!qemu_driver->workerPool) goto error; + qemuDriverUnlock(qemu_driver); + + qemuAutostartDomains(qemu_driver); + if (conn) virConnectClose(conn); -- 1.7.1 From wency at cn.fujitsu.com Wed Apr 6 07:57:33 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 06 Apr 2011 15:57:33 +0800 Subject: [libvirt] [PATCH 2/3] qemu: unlock qemu driver and vm before returning from processWatchdogEvent() In-Reply-To: <4D9C1BE7.3000200@cn.fujitsu.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> Message-ID: <4D9C1CED.20202@cn.fujitsu.com> When the function processWatchdogEvent() failed, we only free wdEvent, but forget to unlock qemu driver and vm, free dumpfile. --- src/qemu/qemu_driver.c | 28 +++++++++++++++++++--------- 1 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index dd84f65..628cfe3 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2400,19 +2400,22 @@ static void processWatchdogEvent(void *data, void *opaque) wdEvent->vm->def->name, (unsigned int)time(NULL)) < 0) { virReportOOMError(); - break; + goto cleanup; } qemuDriverLock(driver); virDomainObjLock(wdEvent->vm); - if (qemuDomainObjBeginJobWithDriver(driver, wdEvent->vm) < 0) - break; + if (qemuDomainObjBeginJobWithDriver(driver, wdEvent->vm) < 0) { + VIR_FREE(dumpfile); + goto unlock; + } if (!virDomainObjIsActive(wdEvent->vm)) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); - break; + VIR_FREE(dumpfile); + goto endjob; } ret = doCoreDump(driver, @@ -2429,16 +2432,23 @@ static void processWatchdogEvent(void *data, void *opaque) qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Resuming after dump failed")); - if (qemuDomainObjEndJob(wdEvent->vm) > 0) - virDomainObjUnlock(wdEvent->vm); - - qemuDriverUnlock(driver); - VIR_FREE(dumpfile); } break; + default: + goto cleanup; } +endjob: + if (qemuDomainObjEndJob(wdEvent->vm) == 0) + wdEvent->vm = NULL; + +unlock: + if (wdEvent->vm) + virDomainObjUnlock(wdEvent->vm); + qemuDriverUnlock(driver); + +cleanup: VIR_FREE(wdEvent); } -- 1.7.1 From wency at cn.fujitsu.com Wed Apr 6 07:58:48 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 06 Apr 2011 15:58:48 +0800 Subject: [libvirt] [PATCH V2 3/3] hold an extra reference while handling watchdog event In-Reply-To: <4D9C1BE7.3000200@cn.fujitsu.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> Message-ID: <4D9C1D38.8090004@cn.fujitsu.com> If the domain is not persistent, and qemu quited unexpectedly before calling processWatchdogEvent(), vm will be freed and the function processWatchdogEvent() will be dangerous. --- src/qemu/qemu_driver.c | 12 ++++++++---- src/qemu/qemu_process.c | 4 ++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 628cfe3..d02891c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2436,15 +2436,19 @@ static void processWatchdogEvent(void *data, void *opaque) } break; default: - goto cleanup; + qemuDriverLock(driver); + virDomainObjLock(wdEvent->vm); + goto unlock; } endjob: - if (qemuDomainObjEndJob(wdEvent->vm) == 0) - wdEvent->vm = NULL; + /* Safe to ignore value since ref count was incremented in + * qemuProcessHandleWatchdog(). + */ + ignore_value(qemuDomainObjEndJob(wdEvent->vm)); unlock: - if (wdEvent->vm) + if (virDomainObjUnref(wdEvent->vm) > 0) virDomainObjUnlock(wdEvent->vm); qemuDriverUnlock(driver); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 48ecd5c..321374c 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -426,6 +426,10 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, if (VIR_ALLOC(wdEvent) == 0) { wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP; wdEvent->vm = vm; + /* Hold an extra reference because we can't allow 'vm' to be + * deleted before handling watchdog event is finished. + */ + virDomainObjRef(vm); ignore_value(virThreadPoolSendJob(driver->workerPool, wdEvent)); } else virReportOOMError(); -- 1.7.1 From amit.shah at redhat.com Wed Apr 6 08:07:12 2011 From: amit.shah at redhat.com (Amit Shah) Date: Wed, 6 Apr 2011 13:37:12 +0530 Subject: [libvirt] [Qemu-devel] [PATCH v2 3/3] raw-posix: Re-open host CD-ROM after media change In-Reply-To: <4D9ADE2A.2020201@redhat.com> References: <4D99C61E.3080600@redhat.com> <4D99C9ED.3020602@codemonkey.ws> <4D99CC74.9070703@redhat.com> <20110405064120.GB2872@amit-x200.redhat.com> <4D9AC940.5000502@redhat.com> <20110405080900.GE2872@amit-x200.redhat.com> <4D9ADA36.8040306@redhat.com> <20110405091203.GC27661@amit-x200.redhat.com> <4D9ADE2A.2020201@redhat.com> Message-ID: <20110406080712.GD20671@amit-x200.redhat.com> On (Tue) 05 Apr 2011 [12:17:30], Avi Kivity wrote: > >Guest kernel bug: CDROM change event missed, so the the revalidate > >call isn't made, which causes stale data (like disc size) to be used > >on newer media. > > > >qemu bug: We don't handle the GET_EVENT_STATUS_NOTIFICATION command > >from guests (which is a mandatory command acc. to scsi spec) which the > >guest uses to detect CDROM changes. Once this command is implemented, > >QEMU sends the required info the guest needs to detect CDROM changes. > >I have this implemented locally (also sent as RFC PATCH 2/3 in the > >'cdrom bug roundup' thread. > > > >So: even if qemu is updated to handle this command, the guest won't > >work correctly since it misses the event. > > Okay. We aren't responsible for guest kernel bugs, especially those > which apply to real hardware (we should make more effort for virtio > bugs). It's enough that we fix qemu here. Actually I forgot about this already: it is possible for a workaround in qemu: inject the event twice instead of once. ie, if the spec says 'SENSE_UNIT_ATTENTION' needs to be reset if some cmd is successful, don't reset it the first time. That's how I confirmed the kernel bug last week. It is such a horrible hack that I didn't want to keep it around at all :-) Amit From mcastrol at gmail.com Wed Apr 6 08:43:53 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Wed, 6 Apr 2011 10:43:53 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: <4D9B40FA.50601@redhat.com> References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B322D.9040309@redhat.com> <4D9B3288.6080700@redhat.com> <4D9B40FA.50601@redhat.com> Message-ID: Hello: I repeated all the test again and reproduce a similar situation. Apparently the restore is finished ok, and the guest is running but: a) I cannot connect to the guest trough ssh. b) I cannot enter to the guest using the virt-manager: It's say " Connecting to graphical console for guest". c) on the log /var/log/libvirt(qemu/chompi1.log say that an error happened during the restore. I'm sending the trace I did while restoring the file and the log. (both on target rionegro Thank you very much in advance. Marcela. 2011/4/5 Michal Novotny > On 04/05/2011 06:16 PM, Marcela Castro Le?n wrote: > > Hellol > > I've downloaded the policycoreutils, and then I execute on the nfs > > clients: > > > > *radic at santacruz:~/discoguest/aplicaciones/virsh$ setsebool -P > > virt_use_nfs on > > setsebool: SELinux is disabled. > > * > > > > It's enough? I understand that it's not working, but I don't find good > > information at internet. > > > > Thank you. > > Marcela > > That's fine since you have the SELinux disabled and therefore it can't > cause any issues. > > Michal > > -- > Michal Novotny , RHCE > Virtualization Team (xen userspace), Red Hat > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: chompi1.log Type: text/x-log Size: 774 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: restore-sv-chubut-1.log Type: text/x-log Size: 10332 bytes Desc: not available URL: From veillard at redhat.com Wed Apr 6 08:50:57 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 6 Apr 2011 16:50:57 +0800 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <4D9B2D45.4020606@redhat.com> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> <4D9B2D45.4020606@redhat.com> Message-ID: <20110406085057.GB24385@redhat.com> On Tue, Apr 05, 2011 at 08:55:01AM -0600, Eric Blake wrote: > On 04/05/2011 07:20 AM, Jiri Denemark wrote: > > On Tue, Apr 05, 2011 at 14:47:22 +0800, Osier Yang wrote: > >> Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to > >> restore the domain from managedsave'ed image if it exists (by > >> invoking "qemuDomainObjRestore"), but it unlinks the image even > >> if restoring fails, which causes data loss. > >> > >> However, I'm not sure if it's the very correct way to fix it, > >> if restoring fails, and we didn't remove the image, it will > >> trys to restore from the image again next time, if that's > >> not the user expected (e.g. the user made quite many changes > >> on the guest), then it's a new problem. > > > > I think this patch is risky. You should either remove the state on error > > (which is the current state) or fail domain start if managed state is present > > but resuming from it fails. If you do something in the middle (your patch) you > > will certainly end up corrupting domain's disks. > > What's more, I think we should consider removing the saved-state file on > success for 'virsh restore file' - once a state has been restored, the > guest is running and has likely modified its disks, which means that the > saved (memory) state is no longer consistent with the new disk state, > and a second restore of the saved file is asking for a different type of > data corruption. > > That is, I think: > > virsh save dom file > virsh restore file > > should leave file intact if and only if the restore failed, and: The problem there is that you are changing the command behaviour. The user may snapshot the disk separately and use this to implement a simplified domain snapshot. Doing the remove may avoid troubles for those not knowing what they are doing, but also break something for those who know what they are doing. In general I would tend to not change the established operation behaviour, especially on suddenly removing files owned by the user without asking. For managed save that's completely different due to the fact the file is owned by libvir, and removing is fine. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From jdenemar at redhat.com Wed Apr 6 08:51:43 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Wed, 6 Apr 2011 10:51:43 +0200 Subject: [libvirt] qemu: Add timeout for monitor to avoid virsh getting stuck when monitor gets die. In-Reply-To: <4D9BE856.2090909@redhat.com> References: <4D9BE856.2090909@redhat.com> Message-ID: <20110406085143.GF7195@orkuz.home> On Wed, Apr 06, 2011 at 12:13:10 +0800, Mark Wu wrote: > Hello Guys, > > When the qemu process becomes hung, virsh will get stuck on the hung > guest and can't move forward. It can be reproduced by the following steps: > > 1. setup a virt guest with qemu-kvm, and start it > 2. stop qemu process with following: > kill -STOP `ps aux | grep qemu | grep -v grep | awk '{print $2}'` > 3. run the following command: > virsh list > > I think we can add a timeout for qemu monitor to resolve this problem: > using virCondWaitUntil instead of virCondWait in qemuMonitorSend. What's > your opinions? This is not the right approach. Introducing a timeout into all monitor command send to qemu is a bad thing. I think the right approach is to have a simple API which would just return domain's state without talking to its monitor or doing other complicated stuff. The new API could then be used by virsh list to list all domains even though they are blocked on qemu monitor. After all, virsh is not really interested in current memory consumption of domains when listing them. The new API could also provide a reason which lead to current state so that one can see the reason even without watching for libvirt events. Jirka From berrange at redhat.com Wed Apr 6 08:59:21 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 6 Apr 2011 09:59:21 +0100 Subject: [libvirt] [PATCH v2 6/8] virFDStream: Add option for delete file after it's opening In-Reply-To: <4D9B498B.7030309@redhat.com> References: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> <1302019980-14957-7-git-send-email-mprivozn@redhat.com> <4D9B498B.7030309@redhat.com> Message-ID: <20110406085921.GA21112@redhat.com> On Tue, Apr 05, 2011 at 10:55:40AM -0600, Eric Blake wrote: > On 04/05/2011 10:12 AM, Michal Privoznik wrote: > > This is needed if we want to transfer a temporary file. If the > > transfer is done with iohelper, we might run into a race condition, > > where we unlink() file before iohelper is executed. > > > > * src/fdstream.c, src/fdstream.h, > > src/util/iohelper.c: Add new option > > * src/lxc/lxc_driver.c, src/qemu/qemu_driver.c, > > src/storage/storage_driver.c, src/uml/uml_driver.c, > > src/xen/xen_driver.c: Expand existing function calls > > I'm not convinced about this commit. We should instead be fixing > iohelper to receive its file by fd inheritance, so that it doesn't have > to open() in the first place. Then you don't need iohelper to worry > about unlink(). My intention was that iohelper could also do uid/gid changes in the future to cope with opening files on root squashing NFS. For that we'd want it to be doing the open, not libvirtd Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From jyang at redhat.com Wed Apr 6 09:02:36 2011 From: jyang at redhat.com (Osier Yang) Date: Wed, 06 Apr 2011 17:02:36 +0800 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <20110406085057.GB24385@redhat.com> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> <4D9B2D45.4020606@redhat.com> <20110406085057.GB24385@redhat.com> Message-ID: <4D9C2C2C.9050406@redhat.com> ? 2011?04?06? 16:50, Daniel Veillard ??: > On Tue, Apr 05, 2011 at 08:55:01AM -0600, Eric Blake wrote: >> On 04/05/2011 07:20 AM, Jiri Denemark wrote: >>> On Tue, Apr 05, 2011 at 14:47:22 +0800, Osier Yang wrote: >>>> Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to >>>> restore the domain from managedsave'ed image if it exists (by >>>> invoking "qemuDomainObjRestore"), but it unlinks the image even >>>> if restoring fails, which causes data loss. >>>> >>>> However, I'm not sure if it's the very correct way to fix it, >>>> if restoring fails, and we didn't remove the image, it will >>>> trys to restore from the image again next time, if that's >>>> not the user expected (e.g. the user made quite many changes >>>> on the guest), then it's a new problem. >>> >>> I think this patch is risky. You should either remove the state on error >>> (which is the current state) or fail domain start if managed state is present >>> but resuming from it fails. If you do something in the middle (your patch) you >>> will certainly end up corrupting domain's disks. >> >> What's more, I think we should consider removing the saved-state file on >> success for 'virsh restore file' - once a state has been restored, the >> guest is running and has likely modified its disks, which means that the >> saved (memory) state is no longer consistent with the new disk state, >> and a second restore of the saved file is asking for a different type of >> data corruption. >> >> That is, I think: >> >> virsh save dom file >> virsh restore file >> >> should leave file intact if and only if the restore failed, and: > > The problem there is that you are changing the command behaviour. > The user may snapshot the disk separately and use this to implement > a simplified domain snapshot. Doing the remove may avoid troubles > for those not knowing what they are doing, but also break something > for those who know what they are doing. Somehow this is true, but as we have API and virsh commands for snapshot specificly, is it fine to make a change on the virsh manual to tell the user about we remove the state file if restoring succeeded? I did that when doing v3 patch, :-) > In general I would tend to not change the established operation > behaviour, especially on suddenly removing files owned by the user > without asking. For managed save that's completely different due to the > fact the file is owned by libvir, and removing is fine. > > Daniel > From gross at univention.de Wed Apr 6 08:58:38 2011 From: gross at univention.de (=?UTF-8?q?Markus=20Gro=C3=9F?=) Date: Wed, 6 Apr 2011 10:58:38 +0200 Subject: [libvirt] [PATCH 0/4] Another set of functions for the libxl driver Message-ID: This patch set adds some more functions to the libxl driver. Best regards Markus Markus Gro? (4): Add domainIsUpdated to libxl driver Add domainSet/GetSchedulerParameters to libxl driver Add cputune support to libxl driver Add domainSave/Restore to libxl driver src/libxl/libxl_conf.h | 10 + src/libxl/libxl_driver.c | 517 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 485 insertions(+), 42 deletions(-) -- 1.7.4.3 From gross at univention.de Wed Apr 6 08:58:40 2011 From: gross at univention.de (=?UTF-8?q?Markus=20Gro=C3=9F?=) Date: Wed, 6 Apr 2011 10:58:40 +0200 Subject: [libvirt] [PATCH 2/4] Add domainSet/GetSchedulerParameters to libxl driver In-Reply-To: References: Message-ID: <9b00bcc6fc662af824e42854a3db06f79ee7b85c.1302079994.git.gross@univention.de> Libxenlight currently only supports the credit scheduler. Therefore setting or getting a parameter of other schedulers raise an error (for now). --- src/libxl/libxl_driver.c | 166 +++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 164 insertions(+), 2 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index e95c403..c760a23 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2286,6 +2286,168 @@ cleanup: } static int +libxlDomainGetSchedulerParameters(virDomainPtr dom, virSchedParameterPtr params, + int * nparams) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + libxlDomainObjPrivatePtr priv; + virDomainObjPtr vm; + libxl_sched_credit sc_info; + int sched_id; + int ret = -1; + + libxlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + libxlDriverUnlock(driver); + + if (!vm) { + libxlError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); + goto cleanup; + } + + if (!virDomainObjIsActive(vm)) { + libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); + goto cleanup; + } + + priv = vm->privateData; + + if ((sched_id = libxl_get_sched_id(&priv->ctx)) < 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to get scheduler id for domain '%d'" + " with libxenlight"), dom->id); + goto cleanup; + } + + if (sched_id != XEN_SCHEDULER_CREDIT) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Only 'credit' scheduler is supported")); + goto cleanup; + } + + if (*nparams != XEN_SCHED_CREDIT_NPARAM) { + libxlError(VIR_ERR_INVALID_ARG, "%s", _("Invalid parameter count")); + goto cleanup; + } + + if (libxl_sched_credit_domain_get(&priv->ctx, dom->id, &sc_info) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to get scheduler parameters for domain '%d'" + " with libxenlight"), dom->id); + goto cleanup; + } + + params[0].value.ui = sc_info.weight; + params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT; + if (virStrcpyStatic(params[0].field, "weight") == NULL) { + libxlError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Field weight too long for destination")); + goto cleanup; + } + + params[1].value.ui = sc_info.cap; + params[1].type = VIR_DOMAIN_SCHED_FIELD_UINT; + if (virStrcpyStatic(params[1].field, "cap") == NULL) { + libxlError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Field cap too long for destination")); + goto cleanup; + } + + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + +static int +libxlDomainSetSchedulerParameters(virDomainPtr dom, virSchedParameterPtr params, + int nparams) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + libxlDomainObjPrivatePtr priv; + virDomainObjPtr vm; + libxl_sched_credit sc_info; + int sched_id; + int i; + int ret = -1; + + libxlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + libxlDriverUnlock(driver); + + if (!vm) { + libxlError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); + goto cleanup; + } + + if (!virDomainObjIsActive(vm)) { + libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); + goto cleanup; + } + + priv = vm->privateData; + + if ((sched_id = libxl_get_sched_id(&priv->ctx)) < 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to get scheduler id for domain '%d'" + " with libxenlight"), dom->id); + goto cleanup; + } + + if (sched_id != XEN_SCHEDULER_CREDIT) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Only 'credit' scheduler is supported")); + goto cleanup; + } + + if (nparams != XEN_SCHED_CREDIT_NPARAM) { + libxlError(VIR_ERR_INVALID_ARG, "%s", _("Invalid parameter count")); + goto cleanup; + } + + for (i = 0; i < nparams; ++i) { + virSchedParameterPtr param = ¶ms[i]; + + if (STREQ(param->field, "weight")) { + if (param->type != VIR_DOMAIN_SCHED_FIELD_UINT) { + libxlError(VIR_ERR_INVALID_ARG, "%s", + _("invalid type for weight tunable, expected a 'uint'")); + goto cleanup; + } + sc_info.weight = params[i].value.ui; + + } else if (STREQ(param->field, "cap")) { + if (param->type != VIR_DOMAIN_SCHED_FIELD_UINT) { + libxlError(VIR_ERR_INVALID_ARG, "%s", + _("invalid type for cap tunable, expected a 'uint'")); + goto cleanup; + } + sc_info.cap = params[i].value.ui; + } else { + libxlError(VIR_ERR_INVALID_ARG, + _("Invalid parameter '%s'"), param->field); + goto cleanup; + } + } + + if (libxl_sched_credit_domain_set(&priv->ctx, dom->id, &sc_info) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to set scheduler parameters for domain '%d'" + " with libxenlight"), dom->id); + goto cleanup; + } + + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + +static int libxlDomainIsActive(virDomainPtr dom) { libxlDriverPrivatePtr driver = dom->conn->privateData; @@ -2453,8 +2615,8 @@ static virDriver libxlDriver = { libxlDomainGetAutostart, /* domainGetAutostart */ libxlDomainSetAutostart, /* domainSetAutostart */ libxlDomainGetSchedulerType,/* domainGetSchedulerType */ - NULL, /* domainGetSchedulerParameters */ - NULL, /* domainSetSchedulerParameters */ + libxlDomainGetSchedulerParameters,/* domainGetSchedulerParameters */ + libxlDomainSetSchedulerParameters,/* domainSetSchedulerParameters */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ -- 1.7.4.3 From gross at univention.de Wed Apr 6 08:58:39 2011 From: gross at univention.de (=?UTF-8?q?Markus=20Gro=C3=9F?=) Date: Wed, 6 Apr 2011 10:58:39 +0200 Subject: [libvirt] [PATCH 1/4] Add domainIsUpdated to libxl driver In-Reply-To: References: Message-ID: --- src/libxl/libxl_driver.c | 24 +++++++++++++++++++++++- 1 files changed, 23 insertions(+), 1 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 8cc4469..e95c403 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2330,6 +2330,28 @@ libxlDomainIsPersistent(virDomainPtr dom) } static int +libxlDomainIsUpdated(virDomainPtr dom) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + libxlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + libxlDriverUnlock(driver); + if (!vm) { + libxlError(VIR_ERR_NO_DOMAIN, NULL); + goto cleanup; + } + ret = vm->updated; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + +static int libxlDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID, virConnectDomainEventGenericCallback callback, void *opaque, virFreeCallback freecb) @@ -2456,7 +2478,7 @@ static virDriver libxlDriver = { NULL, /* IsSecure */ libxlDomainIsActive, /* DomainIsActive */ libxlDomainIsPersistent, /* DomainIsPersistent */ - NULL, /* domainIsUpdated */ + libxlDomainIsUpdated, /* domainIsUpdated */ NULL, /* cpuCompare */ NULL, /* cpuBaseline */ NULL, /* domainGetJobInfo */ -- 1.7.4.3 From gross at univention.de Wed Apr 6 08:58:41 2011 From: gross at univention.de (=?UTF-8?q?Markus=20Gro=C3=9F?=) Date: Wed, 6 Apr 2011 10:58:41 +0200 Subject: [libvirt] [PATCH 3/4] Add cputune support to libxl driver In-Reply-To: References: Message-ID: The nodeGetInfo code had to be moved into a helper function to reuse it without a virConnectPtr. --- src/libxl/libxl_driver.c | 143 ++++++++++++++++++++++++++++++++++------------ 1 files changed, 107 insertions(+), 36 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index c760a23..1539385 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -199,6 +199,46 @@ libxlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, virDomainObjUnlock(vm); } +static int +libxlDoNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info) +{ + libxl_physinfo phy_info; + const libxl_version_info* ver_info; + struct utsname utsname; + + if (libxl_get_physinfo(&driver->ctx, &phy_info)) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("libxl_get_physinfo_info failed")); + return -1; + } + + if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("libxl_get_version_info failed")); + return -1; + } + + uname(&utsname); + if (virStrncpy(info->model, + utsname.machine, + strlen(utsname.machine), + sizeof(info->model)) == NULL) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("machine type %s too big for destination"), + utsname.machine); + return -1; + } + + info->memory = phy_info.total_pages * (ver_info->pagesize / 1024); + info->cpus = phy_info.nr_cpus; + info->nodes = phy_info.nr_nodes; + info->cores = phy_info.cores_per_socket; + info->threads = phy_info.threads_per_core; + info->sockets = 1; + info->mhz = phy_info.cpu_khz / 1000; + return 0; +} + /* * Cleanup function for domain that has reached shutoff state. * @@ -391,6 +431,62 @@ error: return -1; } +static int +libxlDomainSetVcpuAffinites(libxlDriverPrivatePtr driver, virDomainObjPtr vm) +{ + libxlDomainObjPrivatePtr priv = vm->privateData; + virDomainDefPtr def = vm->def; + libxl_cpumap map; + uint8_t *cpumask = NULL; + uint8_t *cpumap = NULL; + virNodeInfo nodeinfo; + size_t cpumaplen; + unsigned int pos; + int vcpu, i; + int ret = -1; + + if (libxlDoNodeGetInfo(driver, &nodeinfo) < 0) + goto cleanup; + + cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo)); + + for (vcpu = 0; vcpu < def->cputune.nvcpupin; ++vcpu) { + if (vcpu != def->cputune.vcpupin[vcpu]->vcpuid) + continue; + + if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) { + virReportOOMError(); + goto cleanup; + } + + cpumask = (uint8_t*) def->cputune.vcpupin[vcpu]->cpumask; + + for (i = 0; i < VIR_DOMAIN_CPUMASK_LEN; ++i) { + if (cpumask[i]) { + pos = i / 8; + cpumap[pos] |= 1 << (i % 8); + } + } + + map.size = cpumaplen; + map.map = cpumap; + + if (libxl_set_vcpuaffinity(&priv->ctx, def->id, vcpu, &map) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to pin vcpu '%d' with libxenlight"), vcpu); + goto cleanup; + } + + VIR_FREE(cpumap); + } + + ret = 0; + +cleanup: + VIR_FREE(cpumap); + return ret; +} + /* * Start a domain through libxenlight. * @@ -440,6 +536,9 @@ libxlVmStart(libxlDriverPrivatePtr driver, if (libxlCreateDomEvents(vm) < 0) goto error; + if (libxlDomainSetVcpuAffinites(driver, vm) < 0) + goto error; + if (!start_paused) { libxl_domain_unpause(&priv->ctx, domid); vm->state = VIR_DOMAIN_RUNNING; @@ -869,42 +968,7 @@ libxlGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) static int libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) { - libxl_physinfo phy_info; - const libxl_version_info* ver_info; - libxlDriverPrivatePtr driver = conn->privateData; - struct utsname utsname; - - if (libxl_get_physinfo(&driver->ctx, &phy_info)) { - libxlError(VIR_ERR_INTERNAL_ERROR, - _("libxl_get_physinfo_info failed")); - return -1; - } - - if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) { - libxlError(VIR_ERR_INTERNAL_ERROR, - _("libxl_get_version_info failed")); - return -1; - } - - uname(&utsname); - if (virStrncpy(info->model, - utsname.machine, - strlen(utsname.machine), - sizeof(info->model)) == NULL) { - libxlError(VIR_ERR_INTERNAL_ERROR, - _("machine type %s too big for destination"), - utsname.machine); - return -1; - } - - info->memory = phy_info.total_pages * (ver_info->pagesize / 1024); - info->cpus = phy_info.nr_cpus; - info->nodes = phy_info.nr_nodes; - info->cores = phy_info.cores_per_socket; - info->threads = phy_info.threads_per_core; - info->sockets = 1; - info->mhz = phy_info.cpu_khz / 1000; - return 0; + return libxlDoNodeGetInfo(conn->privateData, info); } static char * @@ -1712,6 +1776,13 @@ libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap, _("Failed to pin vcpu '%d' with libxenlight"), vcpu); goto cleanup; } + + if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + "%s", _("failed to update or add vcpupin xml")); + goto cleanup; + } + ret = 0; cleanup: -- 1.7.4.3 From gross at univention.de Wed Apr 6 08:58:42 2011 From: gross at univention.de (=?UTF-8?q?Markus=20Gro=C3=9F?=) Date: Wed, 6 Apr 2011 10:58:42 +0200 Subject: [libvirt] =?utf-8?q?=5BPATCH_4/4=5D_Add_domainSave/Restore_to_lib?= =?utf-8?q?xl_driver?= In-Reply-To: References: Message-ID: --- src/libxl/libxl_conf.h | 10 +++ src/libxl/libxl_driver.c | 184 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 191 insertions(+), 3 deletions(-) diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index f2f0d8a..e28615b 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -1,5 +1,6 @@ /*---------------------------------------------------------------------------*/ /* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. + * Copyright (C) 2011 Univention GmbH. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,6 +18,7 @@ * * Authors: * Jim Fehlig + * Markus Gro? */ /*---------------------------------------------------------------------------*/ @@ -85,6 +87,14 @@ struct _libxlDomainObjPrivate { int eventHdl; }; +static const char libxlSavefileMagic[16]= "libvirt-xml\n \0 \r"; +typedef struct _libxlSavefileHeader libxlSavefileHeader; +typedef libxlSavefileHeader *libxlSavefileHeaderPtr; +struct _libxlSavefileHeader { + char magic[16]; /* magic id */ + uint32_t xmlLen; /* length of saved xml */ +}; + # define libxlError(code, ...) \ virReportErrorHelper(NULL, VIR_FROM_LIBXL, code, __FILE__, \ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 1539385..b02d4b7 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "internal.h" #include "logging.h" @@ -60,7 +61,6 @@ static libxlDriverPrivatePtr libxl_driver = NULL; - /* Function declarations */ static int libxlVmStart(libxlDriverPrivatePtr driver, @@ -1555,6 +1555,184 @@ libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) } static int +libxlDomainSave(virDomainPtr dom, const char * to) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + virDomainObjPtr vm; + libxlDomainObjPrivatePtr priv; + virDomainEventPtr event = NULL; + libxlSavefileHeader hdr; + libxl_domain_suspend_info s_info; + char * xml; + uint32_t xml_len; + int fd; + int ret = -1; + + libxlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + libxlError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + if (!virDomainObjIsActive(vm)) { + libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); + goto cleanup; + } + + priv = vm->privateData; + + if (vm->state != VIR_DOMAIN_PAUSED) { + memset(&s_info, 0, sizeof(s_info)); + + if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR, + getuid(), getgid(), 0)) < 0) { + virReportSystemError(-fd, + _("Failed to create domain save file '%s'"), + to); + goto cleanup; + } + + if ((xml = virDomainDefFormat(vm->def, 0)) == NULL) + goto cleanup; + xml_len = strlen(xml) + 1; + + memset(&hdr, 0, sizeof(hdr)); + memcpy(hdr.magic, libxlSavefileMagic, sizeof(hdr.magic)); + hdr.xmlLen = xml_len; + + if (safewrite(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("Failed to write save file header")); + goto cleanup; + } + + if (safewrite(fd, xml, xml_len) != xml_len) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("Failed to write xml description")); + goto cleanup; + } + + if (libxl_domain_suspend(&priv->ctx, &s_info, dom->id, fd) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to save domain '%d' with libxenlight"), + dom->id); + goto cleanup; + } + + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SAVED); + + if (libxlVmReap(driver, vm, 1) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to destroy domain '%d'"), dom->id); + goto cleanup; + } + + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + ret = 0; + } +cleanup: + VIR_FREE(xml); + if (VIR_CLOSE(fd) < 0) + virReportSystemError(errno, "%s", _("cannot close file")); + if (vm) + virDomainObjUnlock(vm); + if (event) + libxlDomainEventQueue(driver, event); + libxlDriverUnlock(driver); + return ret; +} + +static int +libxlDomainRestore(virConnectPtr conn, const char * from) +{ + libxlDriverPrivatePtr driver = conn->privateData; + virDomainDefPtr def = NULL; + virDomainObjPtr vm = NULL; + virDomainEventPtr event = NULL; + libxlSavefileHeader hdr; + char * xml = NULL; + int fd; + int ret = -1; + + libxlDriverLock(driver); + + if ((fd = virFileOpenAs(from, O_RDONLY, 0, getuid(), getgid(), 0)) < 0) { + libxlError(VIR_ERR_OPERATION_FAILED, + "%s", _("cannot read domain image")); + goto cleanup; + } + + if (saferead(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + libxlError(VIR_ERR_OPERATION_FAILED, + "%s", _("failed to read libxl header")); + goto cleanup; + } + + if (memcmp(hdr.magic, libxlSavefileMagic, sizeof(hdr.magic))) { + libxlError(VIR_ERR_INVALID_ARG, "%s", _("image magic is incorrect")); + goto cleanup; + } + + if (hdr.xmlLen <= 0) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("invalid XML length: %d"), hdr.xmlLen); + goto cleanup; + } + + if (VIR_ALLOC_N(xml, hdr.xmlLen) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (saferead(fd, xml, hdr.xmlLen) != hdr.xmlLen) { + libxlError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML")); + goto cleanup; + } + + if (!(def = virDomainDefParseString(driver->caps, xml, 0))) + goto cleanup; + + if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) + goto cleanup; + + if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def, false))) + goto cleanup; + + def = NULL; + + ret = libxlVmStart(driver, vm, false); + + if (ret == 0) { + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_RESTORED); + } else if (ret < 0 && !vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + +cleanup: + VIR_FREE(xml); + virDomainDefFree(def); + if (VIR_CLOSE(fd) < 0) + virReportSystemError(errno, "%s", _("cannot close file")); + if (vm) + virDomainObjUnlock(vm); + if (event) + libxlDomainEventQueue(driver, event); + libxlDriverUnlock(driver); + return ret; +} + +static int libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags) { @@ -2658,8 +2836,8 @@ static virDriver libxlDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ libxlDomainGetInfo, /* domainGetInfo */ - NULL, /* domainSave */ - NULL, /* domainRestore */ + libxlDomainSave, /* domainSave */ + libxlDomainRestore, /* domainRestore */ NULL, /* domainCoreDump */ libxlDomainSetVcpus, /* domainSetVcpus */ libxlDomainSetVcpusFlags, /* domainSetVcpusFlags */ -- 1.7.4.3 From berrange at redhat.com Wed Apr 6 09:13:49 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 6 Apr 2011 10:13:49 +0100 Subject: [libvirt] [PATCH] qemu: Always reserves slot 0x02 for primary VGA. In-Reply-To: <4D9C072A.7020707@redhat.com> References: <1302011398-25541-1-git-send-email-jyang@redhat.com> <4D9B3302.5010307@redhat.com> <4D9C072A.7020707@redhat.com> Message-ID: <20110406091349.GC21112@redhat.com> On Wed, Apr 06, 2011 at 02:24:42PM +0800, Osier Yang wrote: > ? 2011?04?05? 23:19, Eric Blake ??: > >On 04/05/2011 07:49 AM, Osier Yang wrote: > >>To address https://bugzilla.redhat.com/show_bug.cgi?id=692355 > >> > >>This fix is to reserve slot 0x02 for primary VGA even if there > >>is no "video" specified in domain XML to avoid the problem. > >>--- > >> src/qemu/qemu_command.c | 13 ++++++++++--- > >> 1 files changed, 10 insertions(+), 3 deletions(-) > > > >ACK. I think that this is the correct patch, given the earlier comments > >on the same topic in > >https://www.redhat.com/archives/libvir-list/2011-March/msg01296.html > > > > Thanks, applied, for the virtio-blk problem, will be a seperate patch. This patch has broken quite a few cases in the qemuxml2argvtest Since many data files didn't include a VGA card, many PCI slots need changing in them. Can you post a fix for it... Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From mprivozn at redhat.com Wed Apr 6 09:14:34 2011 From: mprivozn at redhat.com (=?UTF-8?B?TWljaGFsIFByw612b3puw61r?=) Date: Wed, 06 Apr 2011 11:14:34 +0200 Subject: [libvirt] [libvirt-snmp][PATCH v4 4/4] Add SNMP trap/notification support. In-Reply-To: <20110401111707.GH29510@redhat.com> References: <1301484030-19174-1-git-send-email-mprivozn@redhat.com> <1301484030-19174-5-git-send-email-mprivozn@redhat.com> <20110401111707.GH29510@redhat.com> Message-ID: <4D9C2EFA.5040000@redhat.com> On 04/01/2011 01:17 PM, Daniel P. Berrange wrote: > On Wed, Mar 30, 2011 at 01:20:30PM +0200, Michal Privoznik wrote: >> This patch adds support for domain lifecycle notification support >> over SNMP traps. SNMP subagent monitors any domain events and when >> something interesting happens, it sends a trap. >> >> Monitoring is done in a joinable thread using polling (used >> domain-events example from libvirt) so we won't block the agent itself. >> >> Some debug info can be printed out by setting LIBVIRT_SNMP_VERBOSE >> environment variable. >> --- > >> src/event.c | 193 ++++++++++++ >> src/event.h | 101 ++++++ > > You don't want to be copying those files. They are libvirt's > internal event driver setup code. You just want to be providing > an implementation fir that, which is what the next two files > do: > >> src/event_poll.c | 724 ++++++++++++++++++++++++++++++++++++++++++++ >> src/event_poll.h | 132 ++++++++ > > Yes, they are libvirt internal. But if i need to copy implementation of functions which uses another internals, e.g. virEventPollRunOnce() calls virMutexLock, virThreadSelf, etc. i need to provide them as well, don't i? This is why i copied so much. Or did i miss something? > Regards, > Daniel Michal From liyong at skybility.com Wed Apr 6 09:21:15 2011 From: liyong at skybility.com (Lyre) Date: Wed, 6 Apr 2011 17:21:15 +0800 Subject: [libvirt] [libvirt-php] Fixed minor memory leak Message-ID: <1302081675-15687-1-git-send-email-liyong@skybility.com> --- src/libvirt-php.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libvirt-php.c b/src/libvirt-php.c index b6a848f..7870fcf 100644 --- a/src/libvirt-php.c +++ b/src/libvirt-php.c @@ -222,8 +222,8 @@ PHP_MINFO_FUNCTION(libvirt) if (virGetVersion(&libVer,NULL,NULL)== 0) { - version=emalloc(100); - snprintf(version, 100, "%i.%i.%i", (long)((libVer/1000000) % 1000),(long)((libVer/1000) % 1000),(long)(libVer % 1000)); + char version[100]; + snprintf(version, sizeof(version), "%i.%i.%i", (long)((libVer/1000000) % 1000),(long)((libVer/1000) % 1000),(long)(libVer % 1000)); php_info_print_table_row(2, "Libvirt version", version); } @@ -3883,10 +3883,12 @@ PHP_FUNCTION(libvirt_list_active_domains) if (name==NULL) { efree (ids); + virDomainFree (domain); RETURN_FALSE; } add_next_index_string(return_value, name, 1); + virDomainFree (domain); } } efree(ids); -- 1.7.3.4 v From mcastrol at gmail.com Wed Apr 6 09:23:18 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Wed, 6 Apr 2011 11:23:18 +0200 Subject: [libvirt] LIBVIRT migration In-Reply-To: <4D9B33A0.5010903@redhat.com> References: <20110401142611.GK29510@redhat.com> <4D9B33A0.5010903@redhat.com> Message-ID: Hello: I did the migration test again and this are the result: a) I define the guest scmpich1 on "santacruz" b) scmpich1 started and I connected to it (ssh) OK (the debug is on create_scmpich.log) c) I migrate it to rionegro host. ** virsh # migrate scmpich1 qemu+ssh://rionegro/system It finish with *error: Unknown failure *(the debug of this is on mig_scmpich1.log) d) I send you the log of /var/log/libvirt/qemu/scmpich1 on origin (santacruz) and on target (rionegro). Thank you very much for your help. Marcela. 2011/4/5 Michal Novotny > [snip] > > Are you sure the domain name is OK for the case of this attempt where > you got the log files ? > > error: failed to get domain 'scmpich1' > error: Domain not found: no domain with matching name 'scmpich1' > > This seems like the domain doesn't exist neither on source nor on target > system. > > Michal > > > -- > Michal Novotny , RHCE > Virtualization Team (xen userspace), Red Hat > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: create-scmpich.log Type: text/x-log Size: 9338 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: mig_scmpich1.log Type: text/x-log Size: 13922 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: santacruz-scmpich1.log Type: text/x-log Size: 707 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: rionegro-scmpich1.log Type: text/x-log Size: 735 bytes Desc: not available URL: From jyang at redhat.com Wed Apr 6 09:27:28 2011 From: jyang at redhat.com (Osier Yang) Date: Wed, 06 Apr 2011 17:27:28 +0800 Subject: [libvirt] [PATCH] qemu: Always reserves slot 0x02 for primary VGA. In-Reply-To: <20110406091349.GC21112@redhat.com> References: <1302011398-25541-1-git-send-email-jyang@redhat.com> <4D9B3302.5010307@redhat.com> <4D9C072A.7020707@redhat.com> <20110406091349.GC21112@redhat.com> Message-ID: <4D9C3200.4070808@redhat.com> ? 2011?04?06? 17:13, Daniel P. Berrange ??: > On Wed, Apr 06, 2011 at 02:24:42PM +0800, Osier Yang wrote: >> ? 2011?04?05? 23:19, Eric Blake ??: >>> On 04/05/2011 07:49 AM, Osier Yang wrote: >>>> To address https://bugzilla.redhat.com/show_bug.cgi?id=692355 >>>> >>>> This fix is to reserve slot 0x02 for primary VGA even if there >>>> is no "video" specified in domain XML to avoid the problem. >>>> --- >>>> src/qemu/qemu_command.c | 13 ++++++++++--- >>>> 1 files changed, 10 insertions(+), 3 deletions(-) >>> >>> ACK. I think that this is the correct patch, given the earlier comments >>> on the same topic in >>> https://www.redhat.com/archives/libvir-list/2011-March/msg01296.html >>> >> >> Thanks, applied, for the virtio-blk problem, will be a seperate patch. > > This patch has broken quite a few cases in the qemuxml2argvtest > Since many data files didn't include a VGA card, many PCI slots > need changing in them. Can you post a fix for it... Yes, I'm doing it. > > Regards, > Daniel From berrange at redhat.com Wed Apr 6 10:02:58 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 6 Apr 2011 11:02:58 +0100 Subject: [libvirt] qemu: Add timeout for monitor to avoid virsh getting stuck when monitor gets die. In-Reply-To: <4D9BE856.2090909@redhat.com> References: <4D9BE856.2090909@redhat.com> Message-ID: <20110406100258.GD21112@redhat.com> On Wed, Apr 06, 2011 at 12:13:10PM +0800, Mark Wu wrote: > Hello Guys, > > When the qemu process becomes hung, virsh will get stuck on the > hung guest and can't move forward. It can be reproduced by the > following steps: > > 1. setup a virt guest with qemu-kvm, and start it > 2. stop qemu process with following: > kill -STOP `ps aux | grep qemu | grep -v grep | awk '{print $2}'` > 3. run the following command: > virsh list > > I think we can add a timeout for qemu monitor to resolve this > problem: using virCondWaitUntil instead of virCondWait in > qemuMonitorSend. What's your opinions? > > Thanks! > > diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c > index fca8590..65d8de9 100644 > --- a/src/qemu/qemu_monitor.c > +++ b/src/qemu/qemu_monitor.c > @@ -25,6 +25,7 @@ > > #include > #include > +#include > #include > #include > > @@ -691,11 +692,14 @@ int qemuMonitorClose(qemuMonitorPtr mon) > return refs; > } > > +#define QEMU_JOB_WAIT_TIME (1000ull * 30) > > int qemuMonitorSend(qemuMonitorPtr mon, > qemuMonitorMessagePtr msg) > { > int ret = -1; > + struct timeval now; > + unsigned long long then; > > if (mon->eofcb) { > msg->lastErrno = EIO; > @@ -706,7 +710,14 @@ int qemuMonitorSend(qemuMonitorPtr mon, > qemuMonitorUpdateWatch(mon); > > while (!mon->msg->finished) { > - if (virCondWait(&mon->notify, &mon->lock) < 0) > + if (gettimeofday(&now, NULL) < 0) { > + virReportSystemError(errno, "%s", > + _("cannot get time of day")); > + return -1; > + } > + then = (now.tv_sec * 1000ull) + (now.tv_usec / 1000); > + then += QEMU_JOB_WAIT_TIME; > + if (virCondWaitUntil(&mon->notify, &mon->lock, then) < 0) > goto cleanup; > } This may seem simple, but it has a lot of nasty consequences. Adding the timeout causes the thread to stop waiting for the monitor command reply, and returns an error for that API call. If QEMU should recover though, and more API calls are made which issue monitor commands, all those future commands will receive the wrong reply data. If we are going to allow a timeout when waiting for a reply to a monitor command, then we need to mark the monitor as 'broken' and forbid all future use of it until the VM is restarted. If it was a simple 'info' command, then we could potentially add code to read+discard the delayed reply later. If it was an action command though, we can't simply discard the delayed reply, because that will result in libvirt's view of the world becoming out of sync with QEMU. In certain cases we may be able to cope with this, by listening for event notifications. eg, if 'stop' command times out, and libvirt will thing the VM is still running, but if QEMU later completes it, then it will in fact be paused. We will see a 'PAUSED' event from QEMU that lets us re-sync our state. If something like a 'device_add' commands time out though, we have no way to gracefully recover. NB, I'm not saying your patch is wrong. In fact I think it is potentially a good idea, but we need to make sure we are able to safely deal with the consequences of timing out first. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Wed Apr 6 10:04:20 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 6 Apr 2011 11:04:20 +0100 Subject: [libvirt] [PATCH 1/1] Change locking for udev monitor and callbacks In-Reply-To: <20110405211417.GA10000@hallyn.com> References: <20110405211417.GA10000@hallyn.com> Message-ID: <20110406100420.GE21112@redhat.com> On Tue, Apr 05, 2011 at 04:14:17PM -0500, Serge Hallyn wrote: > We're seeing bugs apparently resulting from thread unsafety of > libpciaccess, such as > https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/726099 > To prevent those, as suggested by danpb on irc, move the > nodeDeviceLock(driverState) higher into the callers. In > particular: > > udevDeviceMonitorStartup should hold the lock while calling > udevEnumerateDevices(), and udevEventHandleCallback should hold it > over its entire execution. > > It's not clear to me whether it is ok to hold the > nodeDeviceLock while taking the virNodeDeviceObjLock(dev) on a > device. If not, then the lock will need to be dropped around > the calling of udevSetupSystemDev(), and udevAddOneDevice() > may not actually be safe to call from higher layers with the > driverstate lock held. > > libvirt 0.8.8 with this patch on it seems to work fine for me. > Assuming it looks ok and I haven't done anything obviously dumb, > I'll ask the bug submitters to try this patch. > > Signed-off-by: Serge Hallyn > --- > src/node_device/node_device_udev.c | 21 +++++++++------------ > 1 files changed, 9 insertions(+), 12 deletions(-) > > diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c > index 372f1d1..2139ef3 100644 > --- a/src/node_device/node_device_udev.c > +++ b/src/node_device/node_device_udev.c > @@ -1202,7 +1202,6 @@ static int udevRemoveOneDevice(struct udev_device *device) > int ret = 0; > > name = udev_device_get_syspath(device); > - nodeDeviceLock(driverState); > dev = virNodeDeviceFindBySysfsPath(&driverState->devs, name); > > if (dev != NULL) { > @@ -1214,7 +1213,6 @@ static int udevRemoveOneDevice(struct udev_device *device) > name); > ret = -1; > } > - nodeDeviceUnlock(driverState); > > return ret; > } > @@ -1316,9 +1314,7 @@ static int udevAddOneDevice(struct udev_device *device) > > /* If this is a device change, the old definition will be freed > * and the current definition will take its place. */ > - nodeDeviceLock(driverState); > dev = virNodeDeviceAssignDef(&driverState->devs, def); > - nodeDeviceUnlock(driverState); > > if (dev == NULL) { > VIR_ERROR(_("Failed to create device for '%s'"), def->name); > @@ -1442,6 +1438,7 @@ static void udevEventHandleCallback(int watch ATTRIBUTE_UNUSED, > const char *action = NULL; > int udev_fd = -1; > > + nodeDeviceLock(driverState); > udev_fd = udev_monitor_get_fd(udev_monitor); > if (fd != udev_fd) { > VIR_ERROR(_("File descriptor returned by udev %d does not " > @@ -1470,6 +1467,7 @@ static void udevEventHandleCallback(int watch ATTRIBUTE_UNUSED, > > out: > udev_device_unref(device); > + nodeDeviceUnlock(driverState); > return; > } > > @@ -1647,10 +1645,9 @@ static int udevDeviceMonitorStartup(int privileged) > priv->udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); > if (priv->udev_monitor == NULL) { > VIR_FREE(priv); > - nodeDeviceUnlock(driverState); > VIR_ERROR0(_("udev_monitor_new_from_netlink returned NULL")); > ret = -1; > - goto out; > + goto out_unlock; > } > > udev_monitor_enable_receiving(priv->udev_monitor); > @@ -1670,26 +1667,26 @@ static int udevDeviceMonitorStartup(int privileged) > VIR_EVENT_HANDLE_READABLE, > udevEventHandleCallback, NULL, NULL); > if (priv->watch == -1) { > - nodeDeviceUnlock(driverState); > ret = -1; > - goto out; > + goto out_unlock; > } > > - nodeDeviceUnlock(driverState); > - > /* Create a fictional 'computer' device to root the device tree. */ > if (udevSetupSystemDev() != 0) { > ret = -1; > - goto out; > + goto out_unlock; > } > > /* Populate with known devices */ > > if (udevEnumerateDevices(udev) != 0) { > ret = -1; > - goto out; > + goto out_unlock; > } > > +out_unlock: > + nodeDeviceUnlock(driverState); > + > out: > if (ret == -1) { > udevDeviceMonitorShutdown(); ACK, it looks good to me - serializing all access to the udev and libpciaccess APIs is a good conservative approach. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From minovotn at redhat.com Wed Apr 6 10:09:32 2011 From: minovotn at redhat.com (Michal Novotny) Date: Wed, 06 Apr 2011 12:09:32 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B322D.9040309@redhat.com> <4D9B3288.6080700@redhat.com> <4D9B40FA.50601@redhat.com> Message-ID: <4D9C3BDC.3010100@redhat.com> Hi, the interesting thing is the "Permission denied" message in the log file: LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 -S -M pc-0.12 -enable-kvm -m 4096 -smp 4 -name chompi1 -uuid 22f013aa-25d4-b317-9eac-b232692db8c7 -chardev socket,id=monitor,path=/var/lib/libvirt/qemu/chompi1.monitor,server,nowait -monitor chardev:monitor -boot c -drive file=/home/radic/mvdata/imagenes/chompi1.img,if=ide,index=0,boot=on,format=raw -drive if=ide,media=cdrom,index=2,format=raw -net nic,macaddr=52:54:00:82:ce:80,vlan=0,model=virtio,name=virtio.0 -net tap,fd=34,vlan=0,name=tap.0 -chardev pty,id=serial0 -serial chardev:serial0 -parallel none -usb -vnc 0.0.0.0:0 -vga cirrus -incoming exec:cat char device redirected to /dev/pts/2 cat: -: Permission denied <== THIS ONE load of migration failed I don't know much about the internal libvirt design since libvirt is not my primary space so I hope my e-mails from yesterday helped a little but I'll leave the rest for libvirt guys since I'm not having any other ideas what could be wrong there. Michal On 04/06/2011 10:43 AM, Marcela Castro Le?n wrote: > Hello: > I repeated all the test again and reproduce a similar situation. > Apparently the restore is finished ok, and the guest is running but: > a) I cannot connect to the guest trough ssh. > b) I cannot enter to the guest using the virt-manager: It's say " > Connecting to graphical console for guest". > c) on the log /var/log/libvirt(qemu/chompi1.log say that an error > happened during the restore. > > I'm sending the trace I did while restoring the file and the log. > (both on target rionegro > > Thank you very much in advance. > Marcela. > > > > 2011/4/5 Michal Novotny > > > On 04/05/2011 06:16 PM, Marcela Castro Le?n wrote: > > Hellol > > I've downloaded the policycoreutils, and then I execute on the nfs > > clients: > > > > *radic at santacruz:~/discoguest/aplicaciones/virsh$ setsebool -P > > virt_use_nfs on > > setsebool: SELinux is disabled. > > * > > > > It's enough? I understand that it's not working, but I don't > find good > > information at internet. > > > > Thank you. > > Marcela > > That's fine since you have the SELinux disabled and therefore it can't > cause any issues. > > Michal > > -- > Michal Novotny >, > RHCE > Virtualization Team (xen userspace), Red Hat > > -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From minovotn at redhat.com Wed Apr 6 10:16:18 2011 From: minovotn at redhat.com (Michal Novotny) Date: Wed, 06 Apr 2011 12:16:18 +0200 Subject: [libvirt] [libvirt-php] Fixed minor memory leak In-Reply-To: <1302081675-15687-1-git-send-email-liyong@skybility.com> References: <1302081675-15687-1-git-send-email-liyong@skybility.com> Message-ID: <4D9C3D72.8040302@redhat.com> On 04/06/2011 11:21 AM, Lyre wrote: > --- > src/libvirt-php.c | 6 ++++-- > 1 files changed, 4 insertions(+), 2 deletions(-) > > diff --git a/src/libvirt-php.c b/src/libvirt-php.c > index b6a848f..7870fcf 100644 > --- a/src/libvirt-php.c > +++ b/src/libvirt-php.c > @@ -222,8 +222,8 @@ PHP_MINFO_FUNCTION(libvirt) > > if (virGetVersion(&libVer,NULL,NULL)== 0) > { > - version=emalloc(100); > - snprintf(version, 100, "%i.%i.%i", (long)((libVer/1000000) % 1000),(long)((libVer/1000) % 1000),(long)(libVer % 1000)); > + char version[100]; > + snprintf(version, sizeof(version), "%i.%i.%i", (long)((libVer/1000000) % 1000),(long)((libVer/1000) % 1000),(long)(libVer % 1000)); > php_info_print_table_row(2, "Libvirt version", version); > } > > @@ -3883,10 +3883,12 @@ PHP_FUNCTION(libvirt_list_active_domains) > if (name==NULL) > { > efree (ids); > + virDomainFree (domain); > RETURN_FALSE; > } > > add_next_index_string(return_value, name, 1); > + virDomainFree (domain); > } > } > efree(ids); Good to fix this. Thanks a lot! Pushed now! Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From computernews at rambler.ru Wed Apr 6 10:26:32 2011 From: computernews at rambler.ru (computernews at rambler.ru) Date: Wed, 06 Apr 2011 13:26:32 +0300 Subject: [libvirt] virsh: Can't create .vmdk virtual disk over vCenter while over ESX it works well Message-ID: <4D9C3FD8.80108@rambler.ru> Hello, I am trying to create the virtual disk over "virsh". My target is the ESX server that is a part of the vCenter. That is why I connect to it using the vpx://-like URL. The connection itself is being established correctly. Commands like "list --all", "dumpxml " "vol-dumpxml " work perfectly well. What doesn't work for me at the moment is "vol-create --file --pool ". I would suspect that I am passing some parameters incorrectly and would be digging more into a documentation but I am getting the following response from the server: | virsh # vol-create --file vadp4.xml --pool "iscsi-esx4-1" error: Failed to create vol from vadp4.xml error: internal error Could not create volume: NotImplemented - Der angeforderte Vorgang wird vom Server nicht implementiert.| I have to admit that the very same command worked if I connect to ESX server directly (using esx://-like URL). My question is if it is planned to implement the virtual disk creation in case of vCentere is involved ? Reagrds -------------- next part -------------- An HTML attachment was scrubbed... URL: From jdenemar at redhat.com Wed Apr 6 11:21:16 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Wed, 6 Apr 2011 13:21:16 +0200 Subject: [libvirt] [PATCH] qemu: Support for overriding NPROC limit In-Reply-To: <4D9B7793.3040809@redhat.com> References: <4D9B3500.4080302@redhat.com> <20110405194609.GE7195@orkuz.home> <4D9B7793.3040809@redhat.com> Message-ID: <20110406112116.GH7195@orkuz.home> On Tue, Apr 05, 2011 at 14:12:03 -0600, Eric Blake wrote: > On 04/05/2011 01:46 PM, Jiri Denemark wrote: > > On Tue, Apr 05, 2011 at 09:28:00 -0600, Eric Blake wrote: > >> On 04/05/2011 08:09 AM, Jiri Denemark wrote: > >>> This patch adds max_processes option to qemu.conf which can be used to > >>> override system default limit on number of processes that are allowed to > >>> be running for qemu user. > > > > Actually it's important that we call setrlimit() before dropping root > > privileges since only such process can increase the limit. > > Makes sense. > > > > > The NPROC limit is pretty confusing since it logically doesn't fit in > > setrlimit and by it gets unnatural behavior as a result of it being set via > > setrlimit. It only affects the limit seen by current process which will soon > > be executing qemu code. > > Yeah, there's no real way to confine the absolute number of processes > owned by a single uid using just process inheritance; setrlimit only > affects the number of processes that can be forked within a given hierarchy. > > At any rate, this patch is certainly better than what was previously > available, I didn't see anything wrong with it, and you answered my > question, so: > > ACK. Thanks, pushed. Jirka From veillard at redhat.com Wed Apr 6 12:51:40 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 6 Apr 2011 20:51:40 +0800 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <4D9C2C2C.9050406@redhat.com> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> <4D9B2D45.4020606@redhat.com> <20110406085057.GB24385@redhat.com> <4D9C2C2C.9050406@redhat.com> Message-ID: <20110406125140.GC24385@redhat.com> On Wed, Apr 06, 2011 at 05:02:36PM +0800, Osier Yang wrote: > ? 2011?04?06? 16:50, Daniel Veillard ??: > >On Tue, Apr 05, 2011 at 08:55:01AM -0600, Eric Blake wrote: > >>should leave file intact if and only if the restore failed, and: > > > > The problem there is that you are changing the command behaviour. > >The user may snapshot the disk separately and use this to implement > >a simplified domain snapshot. Doing the remove may avoid troubles > >for those not knowing what they are doing, but also break something > >for those who know what they are doing. > > Somehow this is true, but as we have API and virsh commands > for snapshot specificly, is it fine to make a change on the virsh > manual to tell the user about we remove the state file if restoring > succeeded? I did that when doing v3 patch, :-) Still that can be considered a regression, that behaviour is the same since the introduction of the API years ago, we can't change it now just because we think it's cool. Document the fact that in general once the restore suceeded the file should be removed since the data are unlikely to be reusable without loss of integrity, but you can't change the behaviour. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From paolo.smiraglia at polito.it Wed Apr 6 13:10:59 2011 From: paolo.smiraglia at polito.it (Paolo Smiraglia) Date: Wed, 06 Apr 2011 15:10:59 +0200 Subject: [libvirt] Libvirt and IPSec (was: What about Trusted Virtual Domains???) Message-ID: <4D9C6663.3030504@polito.it> Hi to everyone! First of all, sorry for the thread subject change. Due to the several issues of the Libvirt implementation of the Trusted Virtual Domains (TVD), I decided to approach the topic in a modular manner. I think that the first step should be to define the IPSec support or, more in general, the secure tunnel support for Libvirt. I see the implementation divided in two step: 1. define a new driver called 'sectunnel' which describes a generic secure tunnel that will be established using several technologies (for now using only ipsec) 2. modify the existing 'network' driver by adding the possibility to specify the 'sectunnel' that the network have to use in the virtual network definition As an example, you can see below a possible XML definition of the network which use a secure tunnel and the corresponding 'sectunnel' XML definition: NETWORK DEFINITION ================== sec-net 3e3fce45-4f53-4fa7-bb32-11f34168b82b ... <--(specify the 'sectunnel' to use) SECTUNNEL DEFINITION ==================== sec-tun 8b7fd1b0-4463-43b7-8b6e-8006344aeb66 <--(specify the 'secret' which contains the pre-shared key) As you can see in the 'sectunnel' XML definition, I use a 'secret' element. This element is a Libvirt secret [1] and it stores the pre-shared key used by IPSec to establish the Security Associations (SA). Obviously this feature requires to define a new usage category in the 'secret' driver definition. Another possible way to establish the SA is to use the X.509 certificates. To this purpose, I think that the certificates already used by Libvirt to setup SSL/TLS remote connections, might be used. That's all! :-) What do you think about this possible IPSec implementation? Thanks in advance for the replies! Best regards, PAOLO LINK LIST --------- [1] http://libvirt.org/formatsecret.html -- PAOLO SMIRAGLIA Department of Control and Computer Engineering Mobile: +39 (333) 527 3593 Email: paolo.smiraglia at polito.it -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 6095 bytes Desc: S/MIME Cryptographic Signature URL: From dani at firewall-services.com Wed Apr 6 13:11:53 2011 From: dani at firewall-services.com (Daniel Berteaud) Date: Wed, 06 Apr 2011 15:11:53 +0200 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <20110406085057.GB24385@redhat.com> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> <4D9B2D45.4020606@redhat.com> <20110406085057.GB24385@redhat.com> Message-ID: <1302095513.21543.13.camel@germaine.lapiole.org> Le mercredi 06 avril 2011 ? 16:50 +0800, Daniel Veillard a ?crit : > > > > That is, I think: > > > > virsh save dom file > > virsh restore file > > > > should leave file intact if and only if the restore failed, and: > > The problem there is that you are changing the command behaviour. > The user may snapshot the disk separately and use this to implement > a simplified domain snapshot. Doing the remove may avoid troubles > for those not knowing what they are doing, but also break something > for those who know what they are doing. I completely agree, virsh restore shouldn't remove the saved state. I often use this and restore several time the same dump, because I independently save (and restore) the VM disk. I use this as domain snapshots function because of the current limitations of the snapshot API (only working for qcow2 image, and I only use LVM for performance reason, I'm pretty sure a lot of user also use LVM, and would like to keep the possibility to restore a saved state multiple time). Regards, Daniel > In general I would tend to not change the established operation > behaviour, especially on suddenly removing files owned by the user > without asking. For managed save that's completely different due to the > fact the file is owned by libvir, and removing is fine. > > Daniel > -- Daniel Berteaud FIREWALL-SERVICES SARL. Soci?t? de Services en Logiciels Libres Technop?le Montesquieu 33650 MARTILLAC Tel : 05 56 64 15 32 Fax : 05 56 64 15 32 Mail: daniel at firewall-services.com Web : http://www.firewall-services.com From eblake at redhat.com Wed Apr 6 14:21:56 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 08:21:56 -0600 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <20110406125140.GC24385@redhat.com> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> <4D9B2D45.4020606@redhat.com> <20110406085057.GB24385@redhat.com> <4D9C2C2C.9050406@redhat.com> <20110406125140.GC24385@redhat.com> Message-ID: <4D9C7704.70207@redhat.com> On 04/06/2011 06:51 AM, Daniel Veillard wrote: > On Wed, Apr 06, 2011 at 05:02:36PM +0800, Osier Yang wrote: >> ? 2011?04?06? 16:50, Daniel Veillard ??: >>> On Tue, Apr 05, 2011 at 08:55:01AM -0600, Eric Blake wrote: >>>> should leave file intact if and only if the restore failed, and: >>> >>> The problem there is that you are changing the command behaviour. >>> The user may snapshot the disk separately and use this to implement >>> a simplified domain snapshot. Doing the remove may avoid troubles >>> for those not knowing what they are doing, but also break something >>> for those who know what they are doing. >> >> Somehow this is true, but as we have API and virsh commands >> for snapshot specificly, is it fine to make a change on the virsh >> manual to tell the user about we remove the state file if restoring >> succeeded? I did that when doing v3 patch, :-) > > Still that can be considered a regression, that behaviour is the > same since the introduction of the API years ago, we can't change it now > just because we think it's cool. > Document the fact that in general once the restore suceeded the > file should be removed since the data are unlikely to be reusable > without loss of integrity, but you can't change the behaviour. What about this proposal, for being less severe? If we can open the file read-write, then we modify it on a successful restore to change a bit to mark that the image is suspect. Loading then looks for that bit, and fails to restore an image with the bit set unless you pass a --force option. Of course, if the image is read-only, we can't mark the bit stating that the image has been successfully restored, so the best we can do in that case is just print a warning suggesting that since the restore is successful, the user should remove the file. But I agree that since we have already got releases in the wild that do not delete the file, that we cannot change behavior to delete it at this point. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 6 14:25:27 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 08:25:27 -0600 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <1302095513.21543.13.camel@germaine.lapiole.org> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> <4D9B2D45.4020606@redhat.com> <20110406085057.GB24385@redhat.com> <1302095513.21543.13.camel@germaine.lapiole.org> Message-ID: <4D9C77D7.8030603@redhat.com> On 04/06/2011 07:11 AM, Daniel Berteaud wrote: >> The problem there is that you are changing the command behaviour. >> The user may snapshot the disk separately and use this to implement >> a simplified domain snapshot. Doing the remove may avoid troubles >> for those not knowing what they are doing, but also break something >> for those who know what they are doing. > > I completely agree, virsh restore shouldn't remove the saved state. I > often use this and restore several time the same dump, because I > independently save (and restore) the VM disk. Hmm, I should read the full thread before replying. Altering a saved image to mark it as successfully restored would potentially interfere with this usage pattern (you'd either have to pass --force to the restore to override the bit, or we'd have to introduce a new command that can be used to easily remove the bit to be called in tandem with rewinding disk state back to its earlier point). I guess what that means for today is that this patch series should focus just on managedsave behavior, and for save/restore should focus only on documentation. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jyang at redhat.com Wed Apr 6 16:05:19 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 07 Apr 2011 00:05:19 +0800 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <4D9C7704.70207@redhat.com> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> <4D9B2D45.4020606@redhat.com> <20110406085057.GB24385@redhat.com> <4D9C2C2C.9050406@redhat.com> <20110406125140.GC24385@redhat.com> <4D9C7704.70207@redhat.com> Message-ID: <4D9C8F3F.4060700@redhat.com> ? 2011?04?06? 22:21, Eric Blake ??: > On 04/06/2011 06:51 AM, Daniel Veillard wrote: >> On Wed, Apr 06, 2011 at 05:02:36PM +0800, Osier Yang wrote: >>> ? 2011?04?06? 16:50, Daniel Veillard ??: >>>> On Tue, Apr 05, 2011 at 08:55:01AM -0600, Eric Blake wrote: >>>>> should leave file intact if and only if the restore failed, and: >>>> >>>> The problem there is that you are changing the command behaviour. >>>> The user may snapshot the disk separately and use this to implement >>>> a simplified domain snapshot. Doing the remove may avoid troubles >>>> for those not knowing what they are doing, but also break something >>>> for those who know what they are doing. >>> >>> Somehow this is true, but as we have API and virsh commands >>> for snapshot specificly, is it fine to make a change on the virsh >>> manual to tell the user about we remove the state file if restoring >>> succeeded? I did that when doing v3 patch, :-) >> >> Still that can be considered a regression, that behaviour is the >> same since the introduction of the API years ago, we can't change it now >> just because we think it's cool. Agree >> Document the fact that in general once the restore suceeded the >> file should be removed since the data are unlikely to be reusable >> without loss of integrity, but you can't change the behaviour. Agree > > What about this proposal, for being less severe? If we can open the > file read-write, then we modify it on a successful restore to change a > bit to mark that the image is suspect. Loading then looks for that bit, > and fails to restore an image with the bit set unless you pass a --force > option. > Sounds a good idea, but doesn't it also breaks the behaviour? it means all the apps need to introduce a new flag then if I understand your meaning right. > Of course, if the image is read-only, we can't mark the bit stating that > the image has been successfully restored, so the best we can do in that > case is just print a warning suggesting that since the restore is > successful, the user should remove the file. > > But I agree that since we have already got releases in the wild that do > not delete the file, that we cannot change behavior to delete it at this > point. I'm thinking: 1) don't change the behaviour, which means won't try to remove the state file when restoring succeeded. 2) VIR_WARN to tell user the state file should be removed once the restoring succeeded. 3) Update docs to tell the state file should be remove once the restoring succeeded. Regards Osier From jyang at redhat.com Wed Apr 6 16:09:35 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 07 Apr 2011 00:09:35 +0800 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <4D9C77D7.8030603@redhat.com> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> <4D9B2D45.4020606@redhat.com> <20110406085057.GB24385@redhat.com> <1302095513.21543.13.camel@germaine.lapiole.org> <4D9C77D7.8030603@redhat.com> Message-ID: <4D9C903F.6080200@redhat.com> ? 2011?04?06? 22:25, Eric Blake ??: > On 04/06/2011 07:11 AM, Daniel Berteaud wrote: >>> The problem there is that you are changing the command behaviour. >>> The user may snapshot the disk separately and use this to implement >>> a simplified domain snapshot. Doing the remove may avoid troubles >>> for those not knowing what they are doing, but also break something >>> for those who know what they are doing. >> >> I completely agree, virsh restore shouldn't remove the saved state. I >> often use this and restore several time the same dump, because I >> independently save (and restore) the VM disk. > > Hmm, I should read the full thread before replying. Altering a saved > image to mark it as successfully restored would potentially interfere > with this usage pattern (you'd either have to pass --force to the > restore to override the bit, or we'd have to introduce a new command > that can be used to easily remove the bit to be called in tandem with > rewinding disk state back to its earlier point). > > I guess what that means for today is that this patch series should focus > just on managedsave behavior, and for save/restore should focus only on > documentation. > Oh, okay, I should read the full thread either. :-) > > > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list From jyang at redhat.com Wed Apr 6 16:09:55 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 07 Apr 2011 00:09:55 +0800 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <4D9C77D7.8030603@redhat.com> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> <4D9B2D45.4020606@redhat.com> <20110406085057.GB24385@redhat.com> <1302095513.21543.13.camel@germaine.lapiole.org> <4D9C77D7.8030603@redhat.com> Message-ID: <4D9C9053.20304@redhat.com> ? 2011?04?06? 22:25, Eric Blake ??: > On 04/06/2011 07:11 AM, Daniel Berteaud wrote: >>> The problem there is that you are changing the command behaviour. >>> The user may snapshot the disk separately and use this to implement >>> a simplified domain snapshot. Doing the remove may avoid troubles >>> for those not knowing what they are doing, but also break something >>> for those who know what they are doing. >> >> I completely agree, virsh restore shouldn't remove the saved state. I >> often use this and restore several time the same dump, because I >> independently save (and restore) the VM disk. > > Hmm, I should read the full thread before replying. Altering a saved > image to mark it as successfully restored would potentially interfere > with this usage pattern (you'd either have to pass --force to the > restore to override the bit, or we'd have to introduce a new command > that can be used to easily remove the bit to be called in tandem with > rewinding disk state back to its earlier point). > > I guess what that means for today is that this patch series should focus > just on managedsave behavior, and for save/restore should focus only on > documentation. > Oh, okay, I should read the full thread too. :) > > > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list From eblake at redhat.com Wed Apr 6 16:18:09 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 6 Apr 2011 10:18:09 -0600 Subject: [libvirt] [PATCH] tests: fix recent test failures In-Reply-To: <4D9C3200.4070808@redhat.com> References: <4D9C3200.4070808@redhat.com> Message-ID: <1302106689-19772-1-git-send-email-eblake@redhat.com> * tests/qemuxml2argvdata/qemuxml2argv-*.args: Reflect reserved VGA port change. --- Pushing under the build-breaker rule - the fix was pretty straightforward. .../qemuxml2argv-balloon-device-auto.args | 2 +- .../qemuxml2argvdata/qemuxml2argv-boot-order.args | 6 +++--- .../qemuxml2argv-channel-guestfwd.args | 2 +- .../qemuxml2argv-channel-virtio-auto.args | 6 +++--- .../qemuxml2argv-channel-virtio.args | 2 +- .../qemuxml2argv-console-compat-chardev.args | 2 +- .../qemuxml2argv-console-virtio.args | 4 ++-- .../qemuxml2argv-disk-drive-readonly-disk.args | 2 +- .../qemuxml2argv-disk-scsi-device-auto.args | 4 ++-- .../qemuxml2argv-disk-scsi-device.args | 4 ++-- .../qemuxml2argv-disk-usb-device.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-fs9p.args | 4 ++-- .../qemuxml2argv-hostdev-pci-address-device.args | 2 +- .../qemuxml2argv-hostdev-usb-address-device.args | 2 +- .../qemuxml2argv-net-virtio-device.args | 4 ++-- .../qemuxml2argv-net-virtio-netdev.args | 4 ++-- .../qemuxml2argv-parallel-tcp-chardev.args | 2 +- .../qemuxml2argv-serial-dev-chardev.args | 2 +- .../qemuxml2argv-serial-file-chardev.args | 2 +- .../qemuxml2argv-serial-many-chardev.args | 2 +- .../qemuxml2argv-serial-pty-chardev.args | 2 +- .../qemuxml2argv-serial-tcp-chardev.args | 2 +- .../qemuxml2argv-serial-tcp-telnet-chardev.args | 2 +- .../qemuxml2argv-serial-udp-chardev.args | 2 +- .../qemuxml2argv-serial-unix-chardev.args | 2 +- .../qemuxml2argv-serial-vc-chardev.args | 2 +- .../qemuxml2argv-smartcard-controller.args | 2 +- .../qemuxml2argv-smartcard-host-certificates.args | 2 +- .../qemuxml2argv-smartcard-host.args | 2 +- ...emuxml2argv-smartcard-passthrough-spicevmc.args | 2 +- .../qemuxml2argv-smartcard-passthrough-tcp.args | 2 +- .../qemuxml2argv-sound-device.args | 6 +++--- .../qemuxml2argv-watchdog-device.args | 2 +- 33 files changed, 45 insertions(+), 45 deletions(-) diff --git a/tests/qemuxml2argvdata/qemuxml2argv-balloon-device-auto.args b/tests/qemuxml2argvdata/qemuxml2argv-balloon-device-auto.args index b23d08d..0b07f47 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-balloon-device-auto.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-balloon-device-auto.args @@ -2,4 +2,4 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ /dev/HostVG/QEMUGuest1 -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,\ -addr=0x2 +addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-order.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-order.args index 296f004..23249f3 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-boot-order.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-order.args @@ -3,11 +3,11 @@ pc -m 214 -smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,\ nowait -no-acpi -drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-ide0-0-0 \ -device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 -drive \ file=sheepdog:example.org:6000:image,if=none,id=drive-virtio-disk0 -device \ -virtio-blk-pci,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0,\ +virtio-blk-pci,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0,\ bootindex=3 -drive file=/root/boot.iso,if=none,media=cdrom,id=drive-ide0-1-0 \ -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0,\ bootindex=1 -drive file=/dev/null,if=none,id=drive-fdc0-0-1 -global \ isa-fdc.driveB=drive-fdc0-0-1 -global isa-fdc.bootindexB=4 -device \ -virtio-net-pci,vlan=0,id=net0,mac=00:11:22:33:44:55,bus=pci.0,addr=0x2,\ +virtio-net-pci,vlan=0,id=net0,mac=00:11:22:33:44:55,bus=pci.0,addr=0x3,\ bootindex=2 -net user,vlan=0,name=hostnet0 -usb -device virtio-balloon-pci,\ -id=balloon0,bus=pci.0,addr=0x4 +id=balloon0,bus=pci.0,addr=0x5 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-guestfwd.args b/tests/qemuxml2argvdata/qemuxml2argv-channel-guestfwd.args index f2796f1..665fb1e 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-channel-guestfwd.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-guestfwd.args @@ -4,4 +4,4 @@ id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\ id=monitor,mode=readline -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -chardev \ pipe,id=charchannel0,path=/tmp/guestfwd -netdev user,\ guestfwd=tcp:10.0.2.1:4600,chardev=charchannel0,id=user-channel0 -usb -device \ -virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args index 3c9f43d..e3fbc24 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args @@ -1,9 +1,9 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \ -virtio-serial-pci,id=virtio-serial0,max_ports=16,vectors=4,bus=pci.0,addr=0x2 \ +virtio-serial-pci,id=virtio-serial0,max_ports=16,vectors=4,bus=pci.0,addr=0x3 \ -device virtio-serial-pci,id=virtio-serial1,bus=pci.0,addr=0xa -device \ -virtio-serial-pci,id=virtio-serial2,bus=pci.0,addr=0x3 -hda \ +virtio-serial-pci,id=virtio-serial2,bus=pci.0,addr=0x4 -hda \ /dev/HostVG/QEMUGuest1 -chardev pty,id=charchannel0 -device virtserialport,\ bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,\ name=org.linux-kvm.port.0 -chardev pty,id=charchannel1 -device virtserialport,\ @@ -17,4 +17,4 @@ virtserialport,bus=virtio-serial1.0,nr=4,chardev=charchannel4,id=channel4,\ name=org.linux-kvm.port.ooh -chardev pty,id=charchannel5 -device \ virtserialport,bus=virtio-serial2.0,nr=1,chardev=charchannel5,id=channel5,\ name=org.linux-kvm.port.lla -usb -device virtio-balloon-pci,id=balloon0,\ -bus=pci.0,addr=0x4 +bus=pci.0,addr=0x5 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args index 4e2d33e..5356bcc 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args @@ -5,4 +5,4 @@ virtio-serial-pci,id=virtio-serial1,bus=pci.0,addr=0xa -hda \ /dev/HostVG/QEMUGuest1 -chardev pty,id=charchannel0 -device virtserialport,\ bus=virtio-serial1.0,nr=3,chardev=charchannel0,id=channel0,\ name=org.linux-kvm.port.foo -usb -device virtio-balloon-pci,id=balloon0,\ -bus=pci.0,addr=0x2 +bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-compat-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-console-compat-chardev.args index dd4a8d4..4a6202e 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-console-compat-chardev.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-console-compat-chardev.args @@ -3,4 +3,4 @@ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,\ id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\ id=monitor,mode=readline -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -chardev \ pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -usb \ --device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args index a896c81..7e852ff 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args @@ -1,7 +1,7 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \ -virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x2 -hda \ +virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x3 -hda \ /dev/HostVG/QEMUGuest1 -chardev pty,id=charconsole0 -device virtconsole,\ chardev=charconsole0,id=console0 -usb -device virtio-balloon-pci,id=balloon0,\ -bus=pci.0,addr=0x3 +bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-readonly-disk.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-readonly-disk.args index f885776..af3a7d4 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-readonly-disk.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-readonly-disk.args @@ -5,4 +5,4 @@ file=/dev/HostVG/QEMUGuest1,if=none,id=drive-ide0-0-0 -device ide-drive,\ bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 -drive file=/dev/sr0,if=none,\ media=cdrom,id=drive-ide0-1-0,readonly=on -device ide-drive,bus=ide.1,unit=0,\ drive=drive-ide0-1-0,id=ide0-1-0 -usb -device virtio-balloon-pci,id=balloon0,\ -bus=pci.0,addr=0x2 +bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-device-auto.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-device-auto.args index ae7cffd..0efa768 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-device-auto.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-device-auto.args @@ -1,8 +1,8 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device lsi,id=scsi0,\ -bus=pci.0,addr=0x2 -drive file=/dev/HostVG/QEMUGuest1,if=none,\ +bus=pci.0,addr=0x3 -drive file=/dev/HostVG/QEMUGuest1,if=none,\ id=drive-ide0-0-0 -device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,\ id=ide0-0-0 -drive file=/tmp/scsidisk.img,if=none,id=drive-scsi0-0-0 -device \ scsi-disk,bus=scsi0.0,scsi-id=0,drive=drive-scsi0-0-0,id=scsi0-0-0 -usb \ --device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-device.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-device.args index ae7cffd..0efa768 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-device.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-device.args @@ -1,8 +1,8 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device lsi,id=scsi0,\ -bus=pci.0,addr=0x2 -drive file=/dev/HostVG/QEMUGuest1,if=none,\ +bus=pci.0,addr=0x3 -drive file=/dev/HostVG/QEMUGuest1,if=none,\ id=drive-ide0-0-0 -device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,\ id=ide0-0-0 -drive file=/tmp/scsidisk.img,if=none,id=drive-scsi0-0-0 -device \ scsi-disk,bus=scsi0.0,scsi-id=0,drive=drive-scsi0-0-0,id=scsi0-0-0 -usb \ --device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-usb-device.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-usb-device.args index e036a4d..b6d90c6 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-disk-usb-device.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-usb-device.args @@ -4,4 +4,4 @@ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -drive \ file=/dev/HostVG/QEMUGuest1,if=none,id=drive-ide0-0-0 -device ide-drive,\ bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 -drive file=/tmp/usbdisk.img,\ if=none,id=drive-usb-disk0 -device usb-storage,drive=drive-usb-disk0,\ -id=usb-disk0 -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +id=usb-disk0 -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-fs9p.args b/tests/qemuxml2argvdata/qemuxml2argv-fs9p.args index 237bad3..6487fec 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-fs9p.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-fs9p.args @@ -3,5 +3,5 @@ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ /dev/HostVG/QEMUGuest1 -fsdev local,security_model=passthrough,id=fsdev-fs0,\ path=/export/to/guest -device virtio-9p-pci,id=fs0,fsdev=fsdev-fs0,\ -mount_tag=/import/from/host,bus=pci.0,addr=0x2 -usb -device virtio-balloon-pci,\ -id=balloon0,bus=pci.0,addr=0x3 +mount_tag=/import/from/host,bus=pci.0,addr=0x3 -usb -device virtio-balloon-pci,\ +id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address-device.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address-device.args index d30c1e1..3a890ae 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address-device.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address-device.args @@ -2,4 +2,4 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ /dev/HostVG/QEMUGuest2 -usb -device pci-assign,host=06:12.5,id=hostdev0,\ -bus=pci.0,addr=0x2 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 +bus=pci.0,addr=0x3 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-usb-address-device.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-usb-address-device.args index 890c069..d655d2d 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-usb-address-device.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-usb-address-device.args @@ -2,4 +2,4 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ /dev/HostVG/QEMUGuest1 -usb -device usb-host,hostbus=14,hostaddr=6,id=hostdev0 \ --device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args index 843c3e9..b9c0941 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args @@ -2,5 +2,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ /dev/HostVG/QEMUGuest1 -device virtio-net-pci,tx=bh,vlan=0,id=net0,\ -mac=00:11:22:33:44:55,bus=pci.0,addr=0x2 -net user,vlan=0,name=hostnet0 -usb \ --device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 +mac=00:11:22:33:44:55,bus=pci.0,addr=0x3 -net user,vlan=0,name=hostnet0 -usb \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev.args b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev.args index fe479cc..09c817c 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-netdev.args @@ -2,5 +2,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ /dev/HostVG/QEMUGuest1 -netdev user,id=hostnet0 -device virtio-net-pci,\ -netdev=hostnet0,id=net0,mac=00:11:22:33:44:55,bus=pci.0,addr=0x2 -usb -device \ -virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 +netdev=hostnet0,id=net0,mac=00:11:22:33:44:55,bus=pci.0,addr=0x3 -usb -device \ +virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-parallel-tcp-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-parallel-tcp-chardev.args index 9260a3b..5d37f81 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-parallel-tcp-chardev.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-parallel-tcp-chardev.args @@ -4,4 +4,4 @@ id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\ id=monitor,mode=readline -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -chardev \ socket,id=charparallel0,host=127.0.0.1,port=9999,server,nowait -device \ isa-parallel,chardev=charparallel0,id=parallel0 -usb -device \ -virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-dev-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-dev-chardev.args index bbcc138..a85504f 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-serial-dev-chardev.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-dev-chardev.args @@ -3,4 +3,4 @@ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,\ id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\ id=monitor,mode=readline -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -chardev \ tty,id=charserial0,path=/dev/ttyS2 -device isa-serial,chardev=charserial0,\ -id=serial0 -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +id=serial0 -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-file-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-file-chardev.args index 3ca5c9b..cd3b964 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-serial-file-chardev.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-file-chardev.args @@ -4,4 +4,4 @@ id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\ id=monitor,mode=readline -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -chardev \ file,id=charserial0,path=/tmp/serial.log -device isa-serial,\ chardev=charserial0,id=serial0 -usb -device virtio-balloon-pci,id=balloon0,\ -bus=pci.0,addr=0x2 +bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-many-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-many-chardev.args index 71de5a5..f341a86 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-serial-many-chardev.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-many-chardev.args @@ -5,4 +5,4 @@ id=monitor,mode=readline -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -chardev \ pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -chardev \ file,id=charserial1,path=/tmp/serial.log -device isa-serial,\ chardev=charserial1,id=serial1 -usb -device virtio-balloon-pci,id=balloon0,\ -bus=pci.0,addr=0x2 +bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-pty-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-pty-chardev.args index dd4a8d4..4a6202e 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-serial-pty-chardev.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-pty-chardev.args @@ -3,4 +3,4 @@ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,\ id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\ id=monitor,mode=readline -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -chardev \ pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -usb \ --device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev.args index d8059b5..7b770c2 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev.args @@ -4,4 +4,4 @@ id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\ id=monitor,mode=readline -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -chardev \ socket,id=charserial0,host=127.0.0.1,port=9999 -device isa-serial,\ chardev=charserial0,id=serial0 -usb -device virtio-balloon-pci,id=balloon0,\ -bus=pci.0,addr=0x2 +bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-telnet-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-telnet-chardev.args index 7a4a163..bcdcff1 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-telnet-chardev.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-telnet-chardev.args @@ -4,4 +4,4 @@ id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\ id=monitor,mode=readline -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -chardev \ socket,id=charserial0,host=127.0.0.1,port=9999,telnet,server,nowait -device \ isa-serial,chardev=charserial0,id=serial0 -usb -device virtio-balloon-pci,\ -id=balloon0,bus=pci.0,addr=0x2 +id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-udp-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-udp-chardev.args index 7525110..362d860 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-serial-udp-chardev.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-udp-chardev.args @@ -4,4 +4,4 @@ id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\ id=monitor,mode=readline -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -chardev \ udp,id=charserial0,host=127.0.0.1,port=9998,localaddr=127.0.0.1,localport=9999 \ -device isa-serial,chardev=charserial0,id=serial0 -usb -device \ -virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-unix-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-unix-chardev.args index 79f4ba6..60c5b94 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-serial-unix-chardev.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-unix-chardev.args @@ -4,4 +4,4 @@ id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\ id=monitor,mode=readline -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -chardev \ socket,id=charserial0,path=/tmp/serial.sock -device isa-serial,\ chardev=charserial0,id=serial0 -usb -device virtio-balloon-pci,id=balloon0,\ -bus=pci.0,addr=0x2 +bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-vc-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-vc-chardev.args index 55ca1ab..b878010 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-serial-vc-chardev.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-vc-chardev.args @@ -3,4 +3,4 @@ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,\ id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\ id=monitor,mode=readline -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -chardev \ vc,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -usb \ --device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args index a0ee85e..e30b6ae 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args @@ -4,4 +4,4 @@ socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ usb-ccid,id=ccid0 -device \ ccid-card-emulated,backend=nss-emulated,id=smartcard0,bus=ccid0.0 -usb \ --device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args index 46bf38a..0b2142f 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args @@ -5,4 +5,4 @@ chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ usb-ccid,id=ccid0 -device \ ccid-card-emulated,backend=certificates,cert1=cert1,cert2=cert2,cert3=cert3\ ,database=/etc/pki/nssdb,id=smartcard0,bus=ccid0.0 -usb -device \ -virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args index a0ee85e..e30b6ae 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args @@ -4,4 +4,4 @@ socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ usb-ccid,id=ccid0 -device \ ccid-card-emulated,backend=nss-emulated,id=smartcard0,bus=ccid0.0 -usb \ --device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-spicevmc.args b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-spicevmc.args index 8408a3e..4a3ecf5 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-spicevmc.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-spicevmc.args @@ -4,4 +4,4 @@ socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ usb-ccid,id=ccid0 -chardev spicevmc,id=charsmartcard0,name=smartcard \ -device ccid-card-passthru,chardev=charsmartcard0,id=smartcard0,bus=ccid0.0 \ --usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +-usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args index 159ca87..73fc5f5 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args @@ -5,4 +5,4 @@ chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ usb-ccid,id=ccid0 -chardev \ socket,id=charsmartcard0,host=127.0.0.1,port=2001,server,nowait \ -device ccid-card-passthru,chardev=charsmartcard0,id=smartcard0,bus=ccid0.0 \ --usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +-usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-sound-device.args b/tests/qemuxml2argvdata/qemuxml2argv-sound-device.args index 9e1be52..0a09c41 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-sound-device.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-sound-device.args @@ -2,7 +2,7 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ /dev/HostVG/QEMUGuest1 -usb -soundhw pcspk -device ES1370,id=sound1,bus=pci.0,\ -addr=0x2 -device sb16,id=sound2 -device AC97,id=sound3,bus=pci.0,addr=0x3 \ --device intel-hda,id=sound4,bus=pci.0,addr=0x4 -device hda-duplex,\ +addr=0x3 -device sb16,id=sound2 -device AC97,id=sound3,bus=pci.0,addr=0x4 \ +-device intel-hda,id=sound4,bus=pci.0,addr=0x5 -device hda-duplex,\ id=sound4-codec0,bus=sound4.0,cad=0 -device virtio-balloon-pci,id=balloon0,\ -bus=pci.0,addr=0x5 +bus=pci.0,addr=0x6 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-watchdog-device.args b/tests/qemuxml2argvdata/qemuxml2argv-watchdog-device.args index 1913eeb..14224bb 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-watchdog-device.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-watchdog-device.args @@ -2,4 +2,4 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ /dev/HostVG/QEMUGuest1 -usb -device ib700,id=watchdog0 -watchdog-action \ -poweroff -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 +poweroff -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 -- 1.7.4 From eblake at redhat.com Wed Apr 6 16:26:05 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 10:26:05 -0600 Subject: [libvirt] [PATCH 1/1] Change locking for udev monitor and callbacks In-Reply-To: <20110406100420.GE21112@redhat.com> References: <20110405211417.GA10000@hallyn.com> <20110406100420.GE21112@redhat.com> Message-ID: <4D9C941D.3000804@redhat.com> On 04/06/2011 04:04 AM, Daniel P. Berrange wrote: > On Tue, Apr 05, 2011 at 04:14:17PM -0500, Serge Hallyn wrote: >> We're seeing bugs apparently resulting from thread unsafety of >> libpciaccess, such as >> https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/726099 >> To prevent those, as suggested by danpb on irc, move the >> nodeDeviceLock(driverState) higher into the callers. In >> particular: >> libvirt 0.8.8 with this patch on it seems to work fine for me. >> Assuming it looks ok and I haven't done anything obviously dumb, >> I'll ask the bug submitters to try this patch. > > ACK, it looks good to me - serializing all access to the udev > and libpciaccess APIs is a good conservative approach. I've gone ahead and pushed this; if your bug submitters still have further problems, we can address those in separate patches. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 6 16:32:58 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 10:32:58 -0600 Subject: [libvirt] Using Restore in another host. In-Reply-To: <4D9C3BDC.3010100@redhat.com> References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B322D.9040309@redhat.com> <4D9B3288.6080700@redhat.com> <4D9B40FA.50601@redhat.com> <4D9C3BDC.3010100@redhat.com> Message-ID: <4D9C95BA.2080608@redhat.com> On 04/06/2011 04:09 AM, Michal Novotny wrote: > Hi, > the interesting thing is the "Permission denied" message in the log file: > > LC_ALL=C > PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin > QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 -S -M pc-0.12 > -enable-kvm -m 4096 -smp 4 -name chompi1 -uuid > 22f013aa-25d4-b317-9eac-b232692db8c7 -chardev > socket,id=monitor,path=/var/lib/libvirt/qemu/chompi1.monitor,server,nowait > -monitor chardev:monitor -boot c -drive > file=/home/radic/mvdata/imagenes/chompi1.img,if=ide,index=0,boot=on,format=raw > -drive if=ide,media=cdrom,index=2,format=raw -net > nic,macaddr=52:54:00:82:ce:80,vlan=0,model=virtio,name=virtio.0 -net > tap,fd=34,vlan=0,name=tap.0 -chardev pty,id=serial0 -serial > chardev:serial0 -parallel none -usb -vnc 0.0.0.0:0 -vga cirrus -incoming > exec:cat > char device redirected to /dev/pts/2 > cat: -: Permission denied <== THIS ONE > load of migration failed > > I don't know much about the internal libvirt design since libvirt is not > my primary space so I hope my e-mails from yesterday helped a little but > I'll leave the rest for libvirt guys since I'm not having any other > ideas what could be wrong there. That's a weird error - cat is complaining that it can't read stdin, which is usually a symptom associated with SELinux permissions. But you said earlier in this thread that you aren't using SELinux. Are you using AppArmor? At any rate, does upgrading to libvirt 0.9.0 improve the situation? exec: migration has always been risky (there are various data races involved in coordinating multiple processes, where qemu is using popen() to manage the use or even opening the file), and so newer libvirt uses fd: migration (where the fd is already open, so we don't even have to worry about permissions from qemu's point of view). -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From serge.hallyn at canonical.com Wed Apr 6 17:04:42 2011 From: serge.hallyn at canonical.com (Serge Hallyn) Date: Wed, 6 Apr 2011 12:04:42 -0500 Subject: [libvirt] [PATCH 1/1] Change locking for udev monitor and callbacks In-Reply-To: <4D9C941D.3000804@redhat.com> References: <20110405211417.GA10000@hallyn.com> <20110406100420.GE21112@redhat.com> <4D9C941D.3000804@redhat.com> Message-ID: <20110406170442.GA32271@hallyn.com> Quoting Eric Blake (eblake at redhat.com): > On 04/06/2011 04:04 AM, Daniel P. Berrange wrote: > > On Tue, Apr 05, 2011 at 04:14:17PM -0500, Serge Hallyn wrote: > >> We're seeing bugs apparently resulting from thread unsafety of > >> libpciaccess, such as > >> https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/726099 > >> To prevent those, as suggested by danpb on irc, move the > >> nodeDeviceLock(driverState) higher into the callers. In > >> particular: > > >> libvirt 0.8.8 with this patch on it seems to work fine for me. > >> Assuming it looks ok and I haven't done anything obviously dumb, > >> I'll ask the bug submitters to try this patch. > > > > > ACK, it looks good to me - serializing all access to the udev > > and libpciaccess APIs is a good conservative approach. > > I've gone ahead and pushed this; if your bug submitters still have > further problems, we can address those in separate patches. Great, thanks. -serge From eblake at redhat.com Wed Apr 6 17:28:37 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 6 Apr 2011 11:28:37 -0600 Subject: [libvirt] [PATCH] docs: document freecell --all Message-ID: <1302110917-10123-1-git-send-email-eblake@redhat.com> Based on a smaller patch developed by Moritoshi Oshiro: https://bugzilla.redhat.com/show_bug.cgi?id=693963 * tools/virsh.pod (freecell): Mention all, and clarify that optional cellno requires --cellno. --- I think this is the first case where virsh.pod is trying to convey mutually exclusive options; does the resulting layout look reasonable? tools/virsh.pod | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/virsh.pod b/tools/virsh.pod index f4bd294..2e98d5b 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -314,10 +314,11 @@ crashed. =back -=item B optional I +=item B optional { I<--cellno> B | I<--all> } Prints the available amount of memory on the machine or within a -NUMA cell if I is provided. +NUMA cell if I is provided. If I<--all> is provided instead +of I<--cellno>, then show the information on all NUMA cells. =item B I -- 1.7.4 From eblake at redhat.com Wed Apr 6 19:14:45 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 13:14:45 -0600 Subject: [libvirt] [PATCH 2_1/3] rename pciUnBindDeviceFromStub() to pciUnbindDeviceFromStub() and float it up In-Reply-To: <4D9C1286.1090802@cn.fujitsu.com> References: <4D90306A.6060805@cn.fujitsu.com> <4D90323D.4000008@cn.fujitsu.com> <4D9A4BFD.8090405@redhat.com> <4D9C1286.1090802@cn.fujitsu.com> Message-ID: <4D9CBBA5.1020509@redhat.com> On 04/06/2011 01:13 AM, Wen Congyang wrote: > This patch do the following things: > 1. rename the function as 'Unbind' is better than 'UnBind'. > 2. pciUnbindDeviceFromStub() will be used in the function pciBindDeviceToStub() in > next patch. Float it up, instead of having to have a forward declaration > > --- > src/util/pci.c | 134 ++++++++++++++++++++++++++++---------------------------- > 1 files changed, 67 insertions(+), 67 deletions(-) ACK, and thanks for splitting the code motion into its own patch (much easier to review that way). -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 6 19:21:03 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 13:21:03 -0600 Subject: [libvirt] [PATCH 2_2/3] reattach pci device when pciBindDeviceToStub() failed In-Reply-To: <4D9C128A.7040309@cn.fujitsu.com> References: <4D90306A.6060805@cn.fujitsu.com> <4D90323D.4000008@cn.fujitsu.com> <4D9A4BFD.8090405@redhat.com> <4D9C128A.7040309@cn.fujitsu.com> Message-ID: <4D9CBD1F.7010809@redhat.com> On 04/06/2011 01:13 AM, Wen Congyang wrote: > > We should bind pci device to original driver when pciBindDeviceToStub() failed. > If the pci device is not bound to any driver before calling pciBindDeviceToStub(), > we should only unbind it from pci-stub. If it is bound to pci-stub, we should not > unbid it from pci-stub. s/unbid/unbind/ > +remove_id: > /* If 'remove_id' exists, remove the device id from pci-stub's dynamic > * ID table so that 'drivers_probe' works below. > */ > if (pciDriverFile(&path, driver, "remove_id") < 0) { > + /* We do not remove PCI ID from pci-stub, and we can not reprobe it */ > + if (dev->reprobe) { > + VIR_WARN("Not remove PCI ID '%s' from %s, and the device can" > + "not be reprobed again.", dev->id, driver); s/Not remove/Could not remove/ s/can not/cannot/ s/reprobed again/probed again/ > @@ -1018,6 +1086,13 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) > virReportSystemError(errno, > _("Failed to remove PCI ID '%s' from %s"), > dev->id, driver); > + > + /* remove PCI ID from pci-stub failed, and we can not reprobe it */ > + if (dev->reprobe) { > + VIR_WARN("Faile to remove PCI ID '%s' from %s, and the device can" > + "not be reprobed again.", dev->id, driver); s/Faile /Failed / s/reprobed again/probed again/ ACK with those warning message grammar cleanups. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 6 19:30:23 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 13:30:23 -0600 Subject: [libvirt] [PATCH v3 1/2] qemu: Resolve data loss and data corruption of domain restoring. In-Reply-To: <1302070634-2597-1-git-send-email-jyang@redhat.com> References: <1302070634-2597-1-git-send-email-jyang@redhat.com> Message-ID: <4D9CBF4F.8060900@redhat.com> On 04/06/2011 12:17 AM, Osier Yang wrote: > Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to > restore the domain from managedsave'ed image if it exists (by > invoking "qemuDomainObjRestore"), but it unlinks the image even > if restoring fails, which causes data loss. (This problem exists > for "virsh managedsave dom; virsh start dom"). > > And keeping the saved state will cause data corruption if the > user modified his disks and restore the domain second time from > the saved state. (Problem exists for "virsh save dom; virsh > restore dom"). Based on subsequent conversation on v2, we need v4. > > The fix is to: > * Don't unlink()s the managed saved state if the restoring > fails. Good > * Remove the saved state if restoring succeeded. Bad > +++ b/src/qemu/qemu_driver.c > @@ -3171,6 +3171,9 @@ qemuDomainRestore(virConnectPtr conn, > vm = NULL; > } > > + if ((ret == 0) && (unlink(path) < 0)) > + VIR_WARN("Failed to remove the saved state %s", path); Drop this hunk. > + > cleanup: > virDomainDefFree(def); > VIR_FORCE_CLOSE(fd); > @@ -3423,18 +3426,22 @@ static int qemudDomainObjStart(virConnectPtr conn, > > /* > * If there is a managed saved state restore it instead of starting > - * from scratch. In any case the old state is removed. > + * from scratch. > */ > managed_save = qemuDomainManagedSavePath(driver, vm); > if ((managed_save) && (virFileExists(managed_save))) { If managed_save is NULL, then we should be skipping to cleanup (qemuDomainManagedSavePath already reported OOM), rather than silently falling back to normal startup. > ret = qemuDomainObjRestore(conn, driver, vm, managed_save); > > - if (unlink(managed_save) < 0) { > - VIR_WARN("Failed to remove the managed state %s", managed_save); > + if (ret == 0) { > + if (unlink(managed_save) < 0) > + VIR_WARN("Failed to remove the managed state %s", managed_save); > + } else { > + qemuReportError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to restore from the managed state %s"), > + managed_save); This overwrites the error message from qemuDomainObjRestore, possibly losing useful information. I think you can just drop this else clause. > } > > - if (ret == 0) > - goto cleanup; > + goto cleanup; > } > > ret = qemuProcessStart(conn, driver, vm, NULL, start_paused, -1, NULL, > -- > 1.7.4 > > -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 6 19:34:43 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 13:34:43 -0600 Subject: [libvirt] [PATCH 2/2] doc: Update doc for restoring in virsh manual In-Reply-To: <1302070634-2597-2-git-send-email-jyang@redhat.com> References: <1302070634-2597-1-git-send-email-jyang@redhat.com> <1302070634-2597-2-git-send-email-jyang@redhat.com> Message-ID: <4D9CC053.4020807@redhat.com> On 04/06/2011 12:17 AM, Osier Yang wrote: > --- > tools/virsh.pod | 3 ++- > 1 files changed, 2 insertions(+), 1 deletions(-) > > diff --git a/tools/virsh.pod b/tools/virsh.pod > index f4bd294..507686c 100644 > --- a/tools/virsh.pod > +++ b/tools/virsh.pod > @@ -546,7 +546,8 @@ I parameter in the domain's XML definition. > > =item B I > > -Restores a domain from an B state file. See I for more info. > +Restores a domain from an B state file. If restoring > +succeeded, the state file will be removed. See I for more info. NACK. Based on subsequent discussion on v2, this should instead be something like: To avoid corrupting file system contents within the guest, you should not reuse a saved state file after a successful restore unless you have also taken steps to revert the guest's storage volumes back to the contents they had when the domain state file was created. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 6 19:47:34 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 6 Apr 2011 13:47:34 -0600 Subject: [libvirt] [PATCH] virsh: fix mingw startup In-Reply-To: <4D9BA555.1010302@redhat.com> References: <4D9BA555.1010302@redhat.com> Message-ID: <1302119254-20506-1-git-send-email-eblake@redhat.com> * .gnulib: Update to latest, for pipe2. * bootstrap.conf (gnulib_modules): Add pipe2. * src/util/event_poll.c (virEventPollInit): Use it, to avoid problematic virSetCloseExec on mingw. --- The gnulib changes to pipe2 are now in. * .gnulib f796520...2255b86 (4): > verify: use _Static_assert if available > Remove leftover generated .h files after config.status changed. > Ensure to rebuild generated .h files when config.status has changed. > pipe2: Relicense under LGPLv2+. This assumes that my earlier .gnulib modification patch is also in: https://www.redhat.com/archives/libvir-list/2011-April/msg00297.html although I can rebase as needed. .gnulib | 2 +- bootstrap.conf | 3 ++- src/util/event_poll.c | 7 ++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.gnulib b/.gnulib index f796520..2255b86 160000 --- a/.gnulib +++ b/.gnulib @@ -1 +1 @@ -Subproject commit f79652003534e496bca1e49922ca521f12ca8051 +Subproject commit 2255b865130df1feadea60779babd6889285186e diff --git a/bootstrap.conf b/bootstrap.conf index 11d2199..95136ac 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -54,6 +54,7 @@ nonblocking perror physmem pipe-posix +pipe2 poll posix-shell pthread diff --git a/src/util/event_poll.c b/src/util/event_poll.c index 91000e2..cd1ff4a 100644 --- a/src/util/event_poll.c +++ b/src/util/event_poll.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "threads.h" #include "logging.h" @@ -657,11 +658,7 @@ int virEventPollInit(void) return -1; } - if (pipe(eventLoop.wakeupfd) < 0 || - virSetNonBlock(eventLoop.wakeupfd[0]) < 0 || - virSetNonBlock(eventLoop.wakeupfd[1]) < 0 || - virSetCloseExec(eventLoop.wakeupfd[0]) < 0 || - virSetCloseExec(eventLoop.wakeupfd[1]) < 0) { + if (pipe2(eventLoop.wakeupfd, O_CLOEXEC | O_NONBLOCK) < 0) { virReportSystemError(errno, "%s", _("Unable to setup wakeup pipe")); return -1; -- 1.7.4 From eblake at redhat.com Wed Apr 6 20:19:57 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 14:19:57 -0600 Subject: [libvirt] [PATCH 1/6] Add virObject and virAtomic. In-Reply-To: References: Message-ID: <4D9CCAED.4040508@redhat.com> On 04/06/2011 01:19 AM, Hu Tao wrote: > virObject is the base struct that manages reference-counting > for all structs that need the ability of reference-counting. > > virAtomic provides atomic operations which are thread-safe. > --- > src/Makefile.am | 2 + > src/libvirt_private.syms | 5 ++++ > src/util/viratomic.c | 46 ++++++++++++++++++++++++++++++++++++++++ > src/util/viratomic.h | 30 ++++++++++++++++++++++++++ > src/util/virobject.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ > src/util/virobject.h | 39 ++++++++++++++++++++++++++++++++++ > 6 files changed, 174 insertions(+), 0 deletions(-) > create mode 100644 src/util/viratomic.c > create mode 100644 src/util/viratomic.h > create mode 100644 src/util/virobject.c > create mode 100644 src/util/virobject.h > +++ b/src/libvirt_private.syms > @@ -993,3 +993,8 @@ virXPathUInt; > virXPathULong; > virXPathULongHex; > virXPathULongLong; > + > +# object.h virobject.h, and float this section to appear before virtaudit.h (hmm, maybe we should do a preliminary patch to rename that to viraudit.h, so that we aren't mixing vir vs. virt in quite so many places). > +virObjectInit; > +virObjectRef; > +virObjectUnref; Missing exports from viratomic.h. > diff --git a/src/util/viratomic.c b/src/util/viratomic.c > new file mode 100644 > index 0000000..629f189 > --- /dev/null > +++ b/src/util/viratomic.c > @@ -0,0 +1,46 @@ > + > +#ifdef WIN32 > +long virAtomicInc(long *value) > +{ > + return InterlockedIncrement(value); > +} > + > +long virAtomicDec(long *value) > +{ > + return InterlockedDecrement(value); This is an OS-specific replacement. > +} > +#else /* WIN32 */ > +long virAtomicInc(long *value) > +{ > + return __sync_add_and_fetch(value, 1); This is a gcc builtin, and will fail to compile with other C99 compilers. Meanwhile, won't the gcc builtin just work for mingw (that is, no need to use the OS-specific InterlockedIncrement if you have the compiler builtin instead). I think this file needs three implementations: #if defined __GNUC__ || use compiler builtins of __sync_add_and_fetch #elif defined WIN32 use OS primitives, like InterlockedIncrement #else we're hosed when it comes to lightweight versions, but we can still implement a heavyweight replacement that uses virMutex #endif > +++ b/src/util/viratomic.h > @@ -0,0 +1,30 @@ > +#ifndef __VIR_ATOMIC_H > +#define __VIR_ATOMIC_H > + > +long virAtomicInc(long *value); > +long virAtomicDec(long *value); Mark both of these ATTRIBUTE_NONNULL(1) I'm debating whether they should also be marked ATTRIBUTE_RETURN_CHECK > +++ b/src/util/virobject.c > @@ -0,0 +1,52 @@ > + > +#include "viratomic.h" > +#include "virobject.h" > +#include "logging.h" > + > +int virObjectInit(virObjectPtr obj, void (*free)(virObjectPtr obj)) You should declare a typedef: typedef void (*virObjectFreer)(virObjectPtr); then it becomes simpler to read: int virObjectInit(virObjectPtr obj, virObjectFreer f) Use a different name (I used freer/f above) to avoid -Wshadow warnings with free(). > +{ > + if (!free) { Especially since shadowing means it's impossible to tell if this statement is always true (the address of free() exists) or conditional (there is a local variable named free shadowing the global function), and context-sensitive code reviews are tougher :) > + VIR_ERROR0("method free is required."); > + return -1; > + } Should this function also check and return -1 if obj->free was not NULL on entry (that is, guarantee that you can't initialize an object twice)? > + > + obj->ref = 1; > + obj->free = free; > + > + return 0; > +} > + > +void virObjectRef(virObjectPtr obj) > +{ > + sa_assert(obj->ref > 0); This is useless. It only helps static analyzers (like clang), > + virAtomicInc(&obj->ref); but there's nothing to analyze that depends on knowing the value was positive. I'm debating whether to do checking. Maybe we should do: if (virAtomicInc(&obj->ref) < 2) VIR_WARN("invalid call to virObjectRef"); > +void virObjectUnref(virObjectPtr obj) > +{ > + sa_assert(obj->ref > 0); Again, I'm not sure that this buys anything. But we may want to do: int ref = virAtomicDec(&obj->ref); if (ref < 0) VIR_WARN("invalid call to virObjectUnref"); else if (ref == 0) obj->free(obj) > + if (virAtomicDec(&obj->ref) == 0) > + obj->free(obj); > +} > diff --git a/src/util/virobject.h b/src/util/virobject.h > new file mode 100644 > index 0000000..cd7d3e8 > --- /dev/null > +++ b/src/util/virobject.h > + > +typedef struct _virObject virObject; > +typedef virObject *virObjectPtr; > + > +struct _virObject { > + long ref; > + void (*free)(virObjectPtr obj); Is virObjectPtr the right thing to use here? If we assume that all clients will always have a virObjectPtr as their first member, then they can cast that back into the larger object. Is void* opaque any better, although that then it requires a third parameter for virObjectInit? Maybe it's worth some documentation on intended use in this header (am I getting this usage right? I haven't looked at how you used it later in the series, but am just guessing): struct _virFoo { virObject obj; /* Must be first member */ ... }; static void virFooFree(virObjectPtr obj) { virFooPtr foo = obj; ... } virFooPtr virFooNew(void) { virFooPtr foo; if (VIR_ALLOC(foo) < 0) { virReportOOMError(); return NULL; } virObjectInit(&foo->obj, virFooFree); ... return foo; } > +}; > + > +int virObjectInit(virObjectPtr obj, void (*free)(virObjectPtr obj)); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK > +void virObjectRef(virObjectPtr obj); ATTRIBUTE_NONNULL(1) Also, should this return the current reference count? Not all callers will need it, but returning void is harsh if someone might be able to use it. > +void virObjectUnref(virObjectPtr obj); Likewise. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jfehlig at novell.com Wed Apr 6 21:10:47 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Wed, 6 Apr 2011 15:10:47 -0600 Subject: [libvirt] [PATCH] Fix build for older gcc Message-ID: <1302124247-17386-1-git-send-email-jfehlig@novell.com> With gcc 4.3.4 I'm seeing the following warning failure cc1: warnings being treated as errors cc1: error: -funit-at-a-time is required for inlining of functions that are only called once [-Wdisabled-optimization] Add -funit-at-a-time to WARN_CFLAGS. --- m4/virt-compile-warnings.m4 | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4 index 819da8f..8df6f9c 100644 --- a/m4/virt-compile-warnings.m4 +++ b/m4/virt-compile-warnings.m4 @@ -112,6 +112,7 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ gl_WARN_ADD([-fexceptions]) gl_WARN_ADD([-fasynchronous-unwind-tables]) gl_WARN_ADD([-fdiagnostics-show-option]) + gl_WARN_ADD([-funit-at-a-time]) if test "$enable_compile_warnings" = "error" then -- 1.7.3.1 From eblake at redhat.com Wed Apr 6 21:18:54 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 15:18:54 -0600 Subject: [libvirt] [PATCH 2/6] use virObject to manage reference-count of qemud_client In-Reply-To: <8c080f20e7416da216a5a6ab8fcaff37e7abaf70.1302069479.git.hutao@cn.fujitsu.com> References: <8c080f20e7416da216a5a6ab8fcaff37e7abaf70.1302069479.git.hutao@cn.fujitsu.com> Message-ID: <4D9CD8BE.5010905@redhat.com> On 04/06/2011 01:19 AM, Hu Tao wrote: > --- > daemon/dispatch.c | 2 - > daemon/libvirtd.c | 62 +++++++++++++++++++++++++++++++++++++++------------- > daemon/libvirtd.h | 5 ++- > 3 files changed, 49 insertions(+), 20 deletions(-) > Looks like a sane conversion to me, once patch 1/6 is in good shape. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 6 21:19:51 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 15:19:51 -0600 Subject: [libvirt] [PATCH] Fix build for older gcc In-Reply-To: <1302124247-17386-1-git-send-email-jfehlig@novell.com> References: <1302124247-17386-1-git-send-email-jfehlig@novell.com> Message-ID: <4D9CD8F7.7080606@redhat.com> On 04/06/2011 03:10 PM, Jim Fehlig wrote: > With gcc 4.3.4 I'm seeing the following warning failure > > cc1: warnings being treated as errors > cc1: error: -funit-at-a-time is required for inlining of functions > that are only called once [-Wdisabled-optimization] > > Add -funit-at-a-time to WARN_CFLAGS. > --- ACK, please push (I'm seeing the same thing on Cygwin, where gcc is also at 4.3.4). -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jfehlig at novell.com Wed Apr 6 21:28:06 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Wed, 06 Apr 2011 15:28:06 -0600 Subject: [libvirt] [PATCH] Fix build for older gcc In-Reply-To: <4D9CD8F7.7080606@redhat.com> References: <1302124247-17386-1-git-send-email-jfehlig@novell.com> <4D9CD8F7.7080606@redhat.com> Message-ID: <4D9CDAE6.6050902@novell.com> Eric Blake wrote: > On 04/06/2011 03:10 PM, Jim Fehlig wrote: > >> With gcc 4.3.4 I'm seeing the following warning failure >> >> cc1: warnings being treated as errors >> cc1: error: -funit-at-a-time is required for inlining of functions >> that are only called once [-Wdisabled-optimization] >> >> Add -funit-at-a-time to WARN_CFLAGS. >> --- >> > > ACK, please push (I'm seeing the same thing on Cygwin, where gcc is also > at 4.3.4). > Ok, pushed. Thanks. From eblake at redhat.com Wed Apr 6 21:30:50 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 15:30:50 -0600 Subject: [libvirt] [PATCH 0/6] virObject for reference-counting In-Reply-To: References: Message-ID: <4D9CDB8A.7000304@redhat.com> On 04/06/2011 01:18 AM, Hu Tao wrote: > This series adds a virObject structure that manages reference-counting. > > Some notes about referece-counting introduced by this series: > > A thread owns a virObject by incrementing its reference-count by 1. > If a thread owns a virObject, the virObject is guarenteed not be > freed until the thread releases ownership by decrementing its > reference-count by 1. A thread can't access a virObject after it > releases the ownership of virObject because it can be freed at > anytime. > > A thread can own a virObject legally in these ways: > > - a thread owns a virObject that it creates. > - a thread owns a virObject if another thread passes the ownership > to it. Example: qemuMonitorOpen > - a thread gets a virObject from a container. > Example: virDomainFindByUUID > - a container owns a virObject by incrementing its reference-count > by 1 before adding it to the container > - if a virObject is removed from a container its reference-count > must be decremented by 1 > > By following these rules, there is no need to protect operations on > an object's reference-count by an external lock. (like in old ways > virDomainObj lock protects qemu monitor's ref-count.) These rules _need_ to be part of the patch series, preferably added at the same time as patch 1/6 (see for example how src/qemu/THREADS.txt documents threading issues related to qemu). I don't know whether virobject.h or a standalone document is better (but if you do a standalone document, then virobject.h should at least mention it). -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 6 22:33:56 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 16:33:56 -0600 Subject: [libvirt] [PATCH 3/6] use virObject to manage reference-count of virDomainObj In-Reply-To: References: Message-ID: <4D9CEA54.6000402@redhat.com> On 04/06/2011 01:19 AM, Hu Tao wrote: > This patch also eliminates a dead-lock bug in > qemuDomainObjBeginJobWithDriver: if virCondWaitUntil() timeouts, the > thread tries to acquire qemu driver lock while holding virDomainObj > lock. Let's please separate that bug fix into a separate patch which gets applied as soon as possible. > --- > src/conf/domain_conf.c | 56 ++++---- > src/conf/domain_conf.h | 6 +- > src/openvz/openvz_conf.c | 8 +- > src/qemu/qemu_domain.c | 32 ++--- > src/qemu/qemu_domain.h | 2 +- > src/qemu/qemu_driver.c | 304 ++++++++++++++++++++------------------------- > src/qemu/qemu_migration.c | 45 +++---- > src/qemu/qemu_process.c | 33 ++--- > src/vmware/vmware_conf.c | 2 +- > 9 files changed, 215 insertions(+), 273 deletions(-) > int virDomainObjListInit(virDomainObjListPtr doms) > @@ -437,7 +436,7 @@ virDomainObjPtr virDomainFindByID(const virDomainObjListPtr doms, > virDomainObjPtr obj; > obj = virHashSearch(doms->objs, virDomainObjListSearchID, &id); > if (obj) > - virDomainObjLock(obj); > + virDomainObjRef(obj); Wow - changing the semantics so the object is not locked by default, just referenced. > @@ -1010,6 +1007,11 @@ static virDomainObjPtr virDomainObjNew(virCapsPtr caps) > return NULL; > } > > + if (virObjectInit(&domain->obj, doDomainObjFree)) { > + VIR_FREE(domain); > + return NULL; Hmm. virObjectInit used VIR_ERROR, which logs, but doesn't call into virtError. By returning NULL here, a user will get the dreaded "Unknown error" message since we didn't hook into the virterror machinery. Should virObjectInit instead be using virReportErrorHelper? Or is it considered a coding bug to ever have virObjectInit fail in the first place, so we don't really have to worry about that. > @@ -1075,8 +1075,10 @@ virDomainObjPtr virDomainAssignDef(virCapsPtr caps, > domain->def = def; > > virUUIDFormat(def->uuid, uuidstr); > + virDomainObjRef(domain); > if (virHashAddEntry(doms->objs, uuidstr, domain) < 0) { It seems like incrementing ref count on container addition and decrementing it on removal are common actions. Would it simplify code any by making a wrapper for virHashAddEntry: int virHashAddObjEntry(virHashTablePtr, const void *name, virObjectPtr *data) which does the referencing as part of adding/removing a virObject from a hash table, rather than making all callers track it? The only potential drawback to that is that if you use the wrong function, the referencing doesn't happen. Or maybe even make virHashCreateFull take a bool parameter of whether the data must be a virObjectPtr, so you don't have to wrap virHashAddObjEntry (and since virHashRemoveEntry doesn't really have any way to create a virHashRemoveObjEntry wrapper, but it would need to be in on the game of automatic reference count manipulations any time we know the table hashes only virObjects as data). > @@ -1149,9 +1151,7 @@ virDomainObjGetPersistentDef(virCapsPtr caps, > } > > /* > - * The caller must hold a lock on the driver owning 'doms', > - * and must also have locked 'dom', to ensure no one else > - * is either waiting for 'dom' or still usingn it > + * The caller must hold a lock on the driver owning 'doms'. While touching that line, fix the spacing: s/lock on/lock on/ > @@ -1159,9 +1159,8 @@ void virDomainRemoveInactive(virDomainObjListPtr doms, > char uuidstr[VIR_UUID_STRING_BUFLEN]; > virUUIDFormat(dom->def->uuid, uuidstr); > > - virDomainObjUnlock(dom); > - > virHashRemoveEntry(doms->objs, uuidstr); > + virDomainObjUnref(dom); Hmm, this means you are dereferencing dom->def->uuid while holding the driver lock but without holding the domain lock. If there is another place in code that holds the domain lock but not the driver lock, couldn't that cause a bad read of dom->def? I don't think you can blindly get rid of holding the lock on dom unless we make additional rules about which members of dom are safe to modify (for example, stating that dom->def cannot be modified unless you hold the driver lock), but that's hard to audit. :( > @@ -6146,7 +6145,7 @@ static virDomainObjPtr virDomainObjParseXML(virCapsPtr caps, > > error: > /* obj was never shared, so unref should return 0 */ > - ignore_value(virDomainObjUnref(obj)); > + virDomainObjUnref(obj); Do we also want to delete the comment, since it only served to justify why we were using ignore_value()? > @@ -8449,10 +8448,12 @@ static virDomainObjPtr virDomainLoadConfig(virCapsPtr caps, > if (!(dom = virDomainAssignDef(caps, doms, def, false))) > goto error; > > + virDomainObjLock(dom); > dom->autostart = autostart; > > if (notify) > (*notify)(dom, newVM, opaque); > + virDomainObjUnlock(dom); > > VIR_FREE(configFile); > VIR_FREE(autostartLink); Ouch, this changes virDomainLoadConfig so that it returns an unlocked domain, but virDomainLoadAllConfigs assumed that domain was still locked and you now have a double-unlock. > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > index c2a1f9a..3a3c953 100644 > --- a/src/qemu/qemu_domain.c > +++ b/src/qemu/qemu_domain.c > @@ -457,13 +457,13 @@ int qemuDomainObjBeginJob(virDomainObjPtr obj) > } > then = timeval_to_ms(now) + QEMU_JOB_WAIT_TIME; > > - virDomainObjRef(obj); > + virDomainObjLock(obj); This grabbed obj->privateData while obj was not locked. Is that safe, or do you need to float the initialization of priv down? > > while (priv->jobActive) { > if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) { > - /* Safe to ignore value since ref count was incremented above */ > - ignore_value(virDomainObjUnref(obj)); > - if (errno == ETIMEDOUT) > + int err = errno; > + virDomainObjUnlock(obj); > + if (err == ETIMEDOUT) Good catch that pre-patch, errno was untouched by virDomainObjUnref, but post-patch, you need to preserve errno before unlocking. > qemuReportError(VIR_ERR_OPERATION_TIMEOUT, > "%s", _("cannot acquire state change lock")); > else > @@ -482,12 +482,10 @@ int qemuDomainObjBeginJob(virDomainObjPtr obj) > } > > /* > - * obj must be locked before calling, qemud_driver must be locked > - * > * This must be called by anything that will change the VM state > * in any way, or anything that will use the QEMU monitor. > */ > -int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, > +int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver ATTRIBUTE_UNUSED, If we no longer care if driver was locked or unlocked, can we do a followup patch that simplifies all callers to just use qemuDomainObjBeginJob and delete this variant? But I don't think you can get away with it; see below... > virDomainObjPtr obj) > { > qemuDomainObjPrivatePtr priv = obj->privateData; > @@ -501,20 +499,18 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, > } > then = timeval_to_ms(now) + QEMU_JOB_WAIT_TIME; > > - virDomainObjRef(obj); > - qemuDriverUnlock(driver); ...don't think you can delete this line... > + virDomainObjLock(obj); Again, locking after you already grabbed priv. > > while (priv->jobActive) { > if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) { Ouch. You just broke the no sleeping while holding locks rule - previously, virCondWaitUntil was called with no locks, now you are calling it while holding both driver and domain lock. :( > - /* Safe to ignore value since ref count was incremented above */ > - ignore_value(virDomainObjUnref(obj)); > - if (errno == ETIMEDOUT) > + int err = errno; > + virDomainObjUnlock(obj); > + if (err == ETIMEDOUT) > qemuReportError(VIR_ERR_OPERATION_TIMEOUT, > "%s", _("cannot acquire state change lock")); > else > virReportSystemError(errno, > "%s", _("cannot acquire job mutex")); > - qemuDriverLock(driver); Yep, this is the deadlock fix; pre-patch was definitely trying to regrab the driver lock while still holding the domain lock. But given that you _do_ have to regain driver lock (thanks to the blocking of virCondWaitUntil), I'm afraid your fix will instead have to look like... > return -1; > } > } > @@ -524,10 +520,6 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, > priv->jobStart = timeval_to_ms(now); > memset(&priv->jobInfo, 0, sizeof(priv->jobInfo)); > > - virDomainObjUnlock(obj); > - qemuDriverLock(driver); > - virDomainObjLock(obj); ...these lines, which also must remain (although possibly modified a bit, if you are changing semantics to guarantee that you don't have to have obj locked prior to calling this function). > +++ b/src/qemu/qemu_driver.c > @@ -139,7 +139,6 @@ qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaq > struct qemuAutostartData *data = opaque; > virErrorPtr err; > > - virDomainObjLock(vm); > virResetLastError(); > if (qemuDomainObjBeginJobWithDriver(data->driver, vm) < 0) { > err = virGetLastError(); > @@ -156,12 +155,8 @@ qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaq > err ? err->message : _("unknown error")); > } > > - if (qemuDomainObjEndJob(vm) == 0) > - vm = NULL; > + qemuDomainObjEndJob(vm); > } > - > - if (vm) > - virDomainObjUnlock(vm); > } Ah, so it qemuDomainObjBeginJobWithDriver is called while domain lock not held on entry but exits with it held on success, and qemuDomainObjEndJob is the counterpart that releases the domain lock. Makes for some more compact code everywhere else. :) > @@ -1239,39 +1243,57 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, > > qemuDriverLock(driver); > if (!(def = virDomainDefParseString(driver->caps, xml, > - VIR_DOMAIN_XML_INACTIVE))) > + VIR_DOMAIN_XML_INACTIVE))) { > + qemuDriverUnlock(driver); > goto cleanup; > + } > > - if (virSecurityManagerVerify(driver->securityManager, def) < 0) > + if (virSecurityManagerVerify(driver->securityManager, def) < 0) { > + qemuDriverUnlock(driver); > goto cleanup; > + } > > - if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) > + if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) { > + qemuDriverUnlock(driver); > goto cleanup; > + } Why must every caller unlock the driver, instead of factoring it once into the cleanup? I'd almost rather see a second label, as in: goto cleanup_locked; cleanup_locked: qemuDriverUnlock(driver); goto cleanup; > + } > + > + qemuDriverUnlock(driver); > > def = NULL; > > - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) > + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) { With old semantics, you can't call qemuDomainObjBeginJobWithDriver if driver is unlocked (then again, you just changed the body of that method to not care if driver was locked, which matches with you just unlocking it a couple lines ago). Then again, maybe we don't need BeginJobWithDriver after all, if all of your conversions have changed things to no longer hold the driver lock before beginning a job. > @@ -1307,13 +1325,14 @@ static int qemudDomainSuspend(virDomainPtr dom) { > > 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; > + return -1; > } > if (!virDomainObjIsActive(vm)) { > qemuReportError(VIR_ERR_OPERATION_INVALID, > @@ -1354,16 +1373,12 @@ static int qemudDomainSuspend(virDomainPtr dom) { > } > > endjob: > - if (qemuDomainObjEndJob(vm) == 0) > - vm = NULL; > + qemuDomainObjEndJob(vm); Ouch - this change means you are accessing virDomainSaveStatus(driver->caps, driver->stateDir, vm) without holding the driver lock. Is that safe? (I don't know that caps or stateDir ever change after creation, so maybe it is safe after all). Likewise you call qemuProcessStopCPUs(driver, vm), which used to assume driver was locked - is that safe? I think a lot of this file will have the same questions, so I won't review the rest of qemu_domain.c very closely on this round. > @@ -1090,8 +1087,8 @@ int qemuMigrationPerform(struct qemud_driver *driver, > VIR_DOMAIN_EVENT_STOPPED_MIGRATED); > if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) { > virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm); > - if (qemuDomainObjEndJob(vm) > 0) > - virDomainRemoveInactive(&driver->domains, vm); > + qemuDomainObjEndJob(vm); > + virDomainRemoveInactive(&driver->domains, vm); > vm = NULL; Wonky spacing. > @@ -644,7 +644,7 @@ qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm) > > /* Safe to ignore value since ref count was incremented above */ > if (priv->mon == NULL) > - ignore_value(virDomainObjUnref(vm)); > + virDomainObjUnref(vm); Another case where the comment is out of date once you delete the ignore_value(). > +++ b/src/vmware/vmware_conf.c > @@ -205,7 +205,7 @@ cleanup: > VIR_FREE(vmx); > /* any non-NULL vm here has not been shared, so unref will return 0 */ > if (vm) > - ignore_value(virDomainObjUnref(vm)); > + virDomainObjUnref(vm); And another stale comment. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jfehlig at novell.com Wed Apr 6 22:36:27 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Wed, 06 Apr 2011 16:36:27 -0600 Subject: [libvirt] [PATCH 1/4] Add domainIsUpdated to libxl driver In-Reply-To: References: Message-ID: <4D9CEAEB.6040405@novell.com> Markus Gro? wrote: > --- > src/libxl/libxl_driver.c | 24 +++++++++++++++++++++++- > 1 files changed, 23 insertions(+), 1 deletions(-) > > diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c > index 8cc4469..e95c403 100644 > --- a/src/libxl/libxl_driver.c > +++ b/src/libxl/libxl_driver.c > @@ -2330,6 +2330,28 @@ libxlDomainIsPersistent(virDomainPtr dom) > } > > static int > +libxlDomainIsUpdated(virDomainPtr dom) > +{ > + libxlDriverPrivatePtr driver = dom->conn->privateData; > + virDomainObjPtr vm; > + int ret = -1; > + > + libxlDriverLock(driver); > + vm = virDomainFindByUUID(&driver->domains, dom->uuid); > + libxlDriverUnlock(driver); > + if (!vm) { > + libxlError(VIR_ERR_NO_DOMAIN, NULL); > + goto cleanup; > + } > + ret = vm->updated; > + > +cleanup: > + if (vm) > + virDomainObjUnlock(vm); > + return ret; > +} > + > +static int > libxlDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID, > virConnectDomainEventGenericCallback callback, > void *opaque, virFreeCallback freecb) > @@ -2456,7 +2478,7 @@ static virDriver libxlDriver = { > NULL, /* IsSecure */ > libxlDomainIsActive, /* DomainIsActive */ > libxlDomainIsPersistent, /* DomainIsPersistent */ > - NULL, /* domainIsUpdated */ > + libxlDomainIsUpdated, /* domainIsUpdated */ > NULL, /* cpuCompare */ > NULL, /* cpuBaseline */ > NULL, /* domainGetJobInfo */ > ACK, and pushed. Thanks Markus. Regards, Jim From eblake at redhat.com Wed Apr 6 23:06:38 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 6 Apr 2011 17:06:38 -0600 Subject: [libvirt] [PATCH] build: avoid compiler warning on cygwin Message-ID: <1302131198-24160-1-git-send-email-eblake@redhat.com> In file included from util/threads.c:31: util/threads-pthread.c: In function 'virThreadSelfID': util/threads-pthread.c:214: warning: cast from function call of type 'pthread_t' to non-matching type 'int' [-Wbad-function-cast] * src/util/threads-pthread.c (virThreadSelfID) [!SYS_gettid]: Add intermediate cast to shut up gcc. --- Pushing under the build-breaker rule. src/util/threads-pthread.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/threads-pthread.c b/src/util/threads-pthread.c index f812045..898c4d4 100644 --- a/src/util/threads-pthread.c +++ b/src/util/threads-pthread.c @@ -1,7 +1,7 @@ /* * threads-pthread.c: basic thread synchronization primitives * - * Copyright (C) 2009-2010 Red Hat, Inc. + * Copyright (C) 2009-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -211,7 +211,7 @@ int virThreadSelfID(void) tid = syscall(SYS_gettid); return (int)tid; #else - return (int)pthread_self(); + return (int)(void *)pthread_self(); #endif } -- 1.7.4 From eblake at redhat.com Wed Apr 6 23:14:37 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 17:14:37 -0600 Subject: [libvirt] [PATCH 5/6] remove qemuDomainObjEnterMonitorWithDriver and qemuDomainObjExitMonitorWithDriver In-Reply-To: References: Message-ID: <4D9CF3DD.4050006@redhat.com> On 04/06/2011 01:20 AM, Hu Tao wrote: > Bodies of qemuDomainObjEnterMonitorWithDriver/qemuDomainObjExitMonitorWithDriver > are the same as qemuDomainObjEnterMonitor/qemuDomainObjExitMonitor, so > remove them. > --- > src/qemu/qemu_domain.c | 32 ---------------- > src/qemu/qemu_domain.h | 4 -- > src/qemu/qemu_driver.c | 20 +++++----- > src/qemu/qemu_hotplug.c | 90 ++++++++++++++++++++++---------------------- > src/qemu/qemu_migration.c | 46 +++++++++++----------- > src/qemu/qemu_process.c | 36 +++++++++--------- > 6 files changed, 96 insertions(+), 132 deletions(-) Aha - I should have previewed the patch series first, before raising the same point in my review of patch 3. I'm still not convinced that we can get away with this, if any of the callers had previously been calling with driver locked, because driver lock must be dropped before waiting for the condition variable. But if we can, then it's a nice concept. I've run out of review time for today, though, so I haven't reviewed this one closely (nor 4 or 6), and probably won't look at them until we resolve the bigger issues I raised earlier on patches 1 and 3 when you post a v2 of the series. Even documenting in the commit message of patch 3 that you are intentionally changing semantics of no longer calling with driver locked, but saving the cleanup for a later patch, would be helpful. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 6 23:15:35 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 17:15:35 -0600 Subject: [libvirt] [PATCH 6/6] remove qemuDomainObjBeginJobWithDriver In-Reply-To: <726cc7aabcbef1b27fa7db038a0a47695d105e45.1302069479.git.hutao@cn.fujitsu.com> References: <726cc7aabcbef1b27fa7db038a0a47695d105e45.1302069479.git.hutao@cn.fujitsu.com> Message-ID: <4D9CF417.8000608@redhat.com> On 04/06/2011 01:20 AM, Hu Tao wrote: > The body of qemuDomainObjBeginJobWithDriver is the same as > qemuDomainObjBeginJob, so remove it. > --- > src/qemu/qemu_domain.c | 41 ----------------------------------------- > src/qemu/qemu_domain.h | 2 -- > src/qemu/qemu_driver.c | 36 ++++++++++++++++++------------------ > src/qemu/qemu_migration.c | 8 ++++---- > 4 files changed, 22 insertions(+), 65 deletions(-) You also need to patch src/qemu/THREADS.txt to reflect this consolidation. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From veillard at redhat.com Thu Apr 7 01:01:03 2011 From: veillard at redhat.com (Daniel Veillard) Date: Thu, 7 Apr 2011 09:01:03 +0800 Subject: [libvirt] [PATCH] qemu: Do not unlink managedsave image if restoring fails. In-Reply-To: <4D9C7704.70207@redhat.com> References: <1301986042-13725-1-git-send-email-jyang@redhat.com> <20110405132037.GC7195@orkuz.home> <4D9B2D45.4020606@redhat.com> <20110406085057.GB24385@redhat.com> <4D9C2C2C.9050406@redhat.com> <20110406125140.GC24385@redhat.com> <4D9C7704.70207@redhat.com> Message-ID: <20110407010103.GD24385@redhat.com> On Wed, Apr 06, 2011 at 08:21:56AM -0600, Eric Blake wrote: > On 04/06/2011 06:51 AM, Daniel Veillard wrote: > > On Wed, Apr 06, 2011 at 05:02:36PM +0800, Osier Yang wrote: > >> ? 2011?04?06? 16:50, Daniel Veillard ??: > >>> On Tue, Apr 05, 2011 at 08:55:01AM -0600, Eric Blake wrote: > >> Somehow this is true, but as we have API and virsh commands > >> for snapshot specificly, is it fine to make a change on the virsh > >> manual to tell the user about we remove the state file if restoring > >> succeeded? I did that when doing v3 patch, :-) > > > > Still that can be considered a regression, that behaviour is the > > same since the introduction of the API years ago, we can't change it now > > just because we think it's cool. > > Document the fact that in general once the restore suceeded the > > file should be removed since the data are unlikely to be reusable > > without loss of integrity, but you can't change the behaviour. > > What about this proposal, for being less severe? If we can open the > file read-write, then we modify it on a successful restore to change a > bit to mark that the image is suspect. technically the beginning of the image is an XML dump of the domain if I remember correctly, we could try to do something smart in there to do the detection. > Loading then looks for that bit, > and fails to restore an image with the bit set unless you pass a --force > option. That's still a regression, existing code using for example the LVM for snapshot independantly of our API will still break. > But I agree that since we have already got releases in the wild that do > not delete the file, that we cannot change behavior to delete it at this > point. Same for being able to restore, as there are legitimate uses. I would be okay for a warning to be emitted if we detect a subsequent restore but we cannot make the operation to fail by default in my opinion. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From ubuntukids at gmail.com Thu Apr 7 01:46:47 2011 From: ubuntukids at gmail.com (UbuntuKids China) Date: Thu, 7 Apr 2011 09:46:47 +0800 Subject: [libvirt] the storage API requires capacity even using backingStore Message-ID: Hi, I am using the storage API to create a new qemu image volume which has backingStore. It requires capacity to be set and uses the specified capacity as the size of the new volume. This causes issues if the specified capacity is not the same as the backingStore file's. It's not easy to get the capacity of the backing file in some cases. And qemu-img/kvm-img doesn't require a size option if it uses backing file. Is there any thing I could do to avoid this case? Or it needs a patch? Thanks a lot. BR UbuntuKids -- Ubuntu For Kids in China -------------- next part -------------- An HTML attachment was scrubbed... URL: From jyang at redhat.com Thu Apr 7 02:01:35 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 07 Apr 2011 10:01:35 +0800 Subject: [libvirt] [PATCH v3 1/2] qemu: Resolve data loss and data corruption of domain restoring. In-Reply-To: <4D9CBF4F.8060900@redhat.com> References: <1302070634-2597-1-git-send-email-jyang@redhat.com> <4D9CBF4F.8060900@redhat.com> Message-ID: <4D9D1AFF.9050400@redhat.com> ? 2011?04?07? 03:30, Eric Blake ??: > On 04/06/2011 12:17 AM, Osier Yang wrote: >> Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to >> restore the domain from managedsave'ed image if it exists (by >> invoking "qemuDomainObjRestore"), but it unlinks the image even >> if restoring fails, which causes data loss. (This problem exists >> for "virsh managedsave dom; virsh start dom"). >> >> And keeping the saved state will cause data corruption if the >> user modified his disks and restore the domain second time from >> the saved state. (Problem exists for "virsh save dom; virsh >> restore dom"). > > Based on subsequent conversation on v2, we need v4. > >> >> The fix is to: >> * Don't unlink()s the managed saved state if the restoring >> fails. > > Good > >> * Remove the saved state if restoring succeeded. > > Bad > >> +++ b/src/qemu/qemu_driver.c >> @@ -3171,6 +3171,9 @@ qemuDomainRestore(virConnectPtr conn, >> vm = NULL; >> } >> >> + if ((ret == 0)&& (unlink(path)< 0)) >> + VIR_WARN("Failed to remove the saved state %s", path); > > Drop this hunk. > Hum >> + >> cleanup: >> virDomainDefFree(def); >> VIR_FORCE_CLOSE(fd); >> @@ -3423,18 +3426,22 @@ static int qemudDomainObjStart(virConnectPtr conn, >> >> /* >> * If there is a managed saved state restore it instead of starting >> - * from scratch. In any case the old state is removed. >> + * from scratch. >> */ >> managed_save = qemuDomainManagedSavePath(driver, vm); >> if ((managed_save)&& (virFileExists(managed_save))) { > > If managed_save is NULL, then we should be skipping to cleanup > (qemuDomainManagedSavePath already reported OOM), rather than silently > falling back to normal startup. No, qemuDomainObjStart is also used by qemuDomainStartWithFlags, skipping to cleanup when managed_save is NULL will break the starting of all domains which don't have managed state file. That's risky. > >> ret = qemuDomainObjRestore(conn, driver, vm, managed_save); >> >> - if (unlink(managed_save)< 0) { >> - VIR_WARN("Failed to remove the managed state %s", managed_save); >> + if (ret == 0) { >> + if (unlink(managed_save)< 0) >> + VIR_WARN("Failed to remove the managed state %s", managed_save); >> + } else { >> + qemuReportError(VIR_ERR_INTERNAL_ERROR, >> + _("Failed to restore from the managed state %s"), >> + managed_save); > > This overwrites the error message from qemuDomainObjRestore, possibly > losing useful information. I think you can just drop this else clause. This makes sense. Thanks > >> } >> >> - if (ret == 0) >> - goto cleanup; >> + goto cleanup; >> } >> >> ret = qemuProcessStart(conn, driver, vm, NULL, start_paused, -1, NULL, >> -- >> 1.7.4 >> >> > From jyang at redhat.com Thu Apr 7 02:19:58 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 7 Apr 2011 10:19:58 +0800 Subject: [libvirt] [PATCH v4] qemu: Unlink the managed state only if restoring succeeded Message-ID: <1302142798-21817-1-git-send-email-jyang@redhat.com> Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to restore the domain from managedsave'ed image if it exists (by invoking "qemuDomainObjRestore"), but it unlinks the image even if restoring fails, which causes data loss. (This problem exists for "virsh managedsave dom; virsh start dom"). The fix is to: * Don't unlink()s the managed saved state if the restoring fails. * Add doc for restoring in virsh mannual to tell user it's not encourage to reuse a saved state file. --- src/qemu/qemu_driver.c | 8 +++----- tools/virsh.pod | 6 +++++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 48fe266..fdd58c7 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3423,18 +3423,16 @@ static int qemudDomainObjStart(virConnectPtr conn, /* * If there is a managed saved state restore it instead of starting - * from scratch. In any case the old state is removed. + * from scratch. The old state is removed once the restoring succeeded. */ managed_save = qemuDomainManagedSavePath(driver, vm); if ((managed_save) && (virFileExists(managed_save))) { ret = qemuDomainObjRestore(conn, driver, vm, managed_save); - if (unlink(managed_save) < 0) { + if ((ret == 0) && (unlink(managed_save) < 0)) VIR_WARN("Failed to remove the managed state %s", managed_save); - } - if (ret == 0) - goto cleanup; + goto cleanup; } ret = qemuProcessStart(conn, driver, vm, NULL, start_paused, -1, NULL, diff --git a/tools/virsh.pod b/tools/virsh.pod index f4bd294..6319373 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -546,7 +546,11 @@ I parameter in the domain's XML definition. =item B I -Restores a domain from an B state file. See I for more info. +Restores a domain from an B state file. See I for more info. + +B: To avoid corrupting file system contents within the domain, you +should not reuse the saved state file to B unless you are convinced +with reverting the domain to the previous state. =item B I I -- 1.7.4 From eblake at redhat.com Thu Apr 7 02:21:33 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 06 Apr 2011 20:21:33 -0600 Subject: [libvirt] [PATCH v3 1/2] qemu: Resolve data loss and data corruption of domain restoring. In-Reply-To: <4D9D1AFF.9050400@redhat.com> References: <1302070634-2597-1-git-send-email-jyang@redhat.com> <4D9CBF4F.8060900@redhat.com> <4D9D1AFF.9050400@redhat.com> Message-ID: <4D9D1FAD.6040400@redhat.com> On 04/06/2011 08:01 PM, Osier Yang wrote: >>> managed_save = qemuDomainManagedSavePath(driver, vm); >>> if ((managed_save)&& (virFileExists(managed_save))) { >> >> If managed_save is NULL, then we should be skipping to cleanup >> (qemuDomainManagedSavePath already reported OOM), rather than silently >> falling back to normal startup. > > No, qemuDomainObjStart is also used by qemuDomainStartWithFlags, > skipping to cleanup when managed_save is NULL will break the > starting of all domains which don't have managed state file. > > That's risky. Ignoring OOM is risky. If managed_save is NULL, we are out of memory, and we should fail the command; that's the only time that qemuDomainManagedSavePath returns NULL. We don't know if there was a save file or not. And even if there was not a file, we'd probably run out of memory again if we attempt normal setup. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jyang at redhat.com Thu Apr 7 02:24:51 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 07 Apr 2011 10:24:51 +0800 Subject: [libvirt] [PATCH v3 1/2] qemu: Resolve data loss and data corruption of domain restoring. In-Reply-To: <4D9D1FAD.6040400@redhat.com> References: <1302070634-2597-1-git-send-email-jyang@redhat.com> <4D9CBF4F.8060900@redhat.com> <4D9D1AFF.9050400@redhat.com> <4D9D1FAD.6040400@redhat.com> Message-ID: <4D9D2073.1020206@redhat.com> ? 2011?04?07? 10:21, Eric Blake ??: > On 04/06/2011 08:01 PM, Osier Yang wrote: >>>> managed_save = qemuDomainManagedSavePath(driver, vm); >>>> if ((managed_save)&& (virFileExists(managed_save))) { >>> >>> If managed_save is NULL, then we should be skipping to cleanup >>> (qemuDomainManagedSavePath already reported OOM), rather than silently >>> falling back to normal startup. >> >> No, qemuDomainObjStart is also used by qemuDomainStartWithFlags, >> skipping to cleanup when managed_save is NULL will break the >> starting of all domains which don't have managed state file. >> >> That's risky. > > Ignoring OOM is risky. If managed_save is NULL, we are out of memory, > and we should fail the command; that's the only time that > qemuDomainManagedSavePath returns NULL. We don't know if there was a > save file or not. And even if there was not a file, we'd probably run > out of memory again if we attempt normal setup. > Oh, I misunderstand your meaning here, forget about it, v5 comes. :) From jyang at redhat.com Thu Apr 7 02:31:52 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 7 Apr 2011 10:31:52 +0800 Subject: [libvirt] [PATCH v5] qemu: Remove the managed state file only if restoring succeeded Message-ID: <1302143512-23422-1-git-send-email-jyang@redhat.com> 1) Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to restore the domain from managedsave'ed image if it exists (by invoking "qemuDomainObjRestore"), but it unlinks the image even if restoring fails, which causes data loss. (This problem exists for "virsh managedsave dom; virsh start dom"). The fix for is to unlink the managed state file only if restoring succeeded. 2) For "virsh save dom; virsh restore dom;", it can cause data corruption if one reuse the saved state file for restoring. Add doc to tell user about it. 3) In "qemuDomainObjStart", if "managed_save" is NULL, we shouldn't fallback to start the domain, skipping it to cleanup as a incidental fix. Discovered by Eric. --- src/qemu/qemu_driver.c | 12 +++++++----- tools/virsh.pod | 6 +++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 48fe266..a84780b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3423,18 +3423,20 @@ static int qemudDomainObjStart(virConnectPtr conn, /* * If there is a managed saved state restore it instead of starting - * from scratch. In any case the old state is removed. + * from scratch. The old state is removed once the restoring succeeded. */ managed_save = qemuDomainManagedSavePath(driver, vm); + + if (!managed_save) + goto cleanup; + if ((managed_save) && (virFileExists(managed_save))) { ret = qemuDomainObjRestore(conn, driver, vm, managed_save); - if (unlink(managed_save) < 0) { + if ((ret == 0) && (unlink(managed_save) < 0)) VIR_WARN("Failed to remove the managed state %s", managed_save); - } - if (ret == 0) - goto cleanup; + goto cleanup; } ret = qemuProcessStart(conn, driver, vm, NULL, start_paused, -1, NULL, diff --git a/tools/virsh.pod b/tools/virsh.pod index f4bd294..6319373 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -546,7 +546,11 @@ I parameter in the domain's XML definition. =item B I -Restores a domain from an B state file. See I for more info. +Restores a domain from an B state file. See I for more info. + +B: To avoid corrupting file system contents within the domain, you +should not reuse the saved state file to B unless you are convinced +with reverting the domain to the previous state. =item B I I -- 1.7.4 From veillard at redhat.com Thu Apr 7 02:42:53 2011 From: veillard at redhat.com (Daniel Veillard) Date: Thu, 7 Apr 2011 10:42:53 +0800 Subject: [libvirt] qemu: Add timeout for monitor to avoid virsh getting stuck when monitor gets die. In-Reply-To: <20110406100258.GD21112@redhat.com> References: <4D9BE856.2090909@redhat.com> <20110406100258.GD21112@redhat.com> Message-ID: <20110407024253.GE24385@redhat.com> On Wed, Apr 06, 2011 at 11:02:58AM +0100, Daniel P. Berrange wrote: > On Wed, Apr 06, 2011 at 12:13:10PM +0800, Mark Wu wrote: > > Hello Guys, > > > > When the qemu process becomes hung, virsh will get stuck on the > > hung guest and can't move forward. It can be reproduced by the > > following steps: > > > > 1. setup a virt guest with qemu-kvm, and start it > > 2. stop qemu process with following: > > kill -STOP `ps aux | grep qemu | grep -v grep | awk '{print $2}'` > > 3. run the following command: > > virsh list > > > > I think we can add a timeout for qemu monitor to resolve this > > problem: using virCondWaitUntil instead of virCondWait in > > qemuMonitorSend. What's your opinions? > > > > Thanks! > > > > > diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c > > index fca8590..65d8de9 100644 > > --- a/src/qemu/qemu_monitor.c > > +++ b/src/qemu/qemu_monitor.c > > @@ -25,6 +25,7 @@ > > > > #include > > #include > > +#include > > #include > > #include > > > > @@ -691,11 +692,14 @@ int qemuMonitorClose(qemuMonitorPtr mon) > > return refs; > > } > > > > +#define QEMU_JOB_WAIT_TIME (1000ull * 30) > > > > int qemuMonitorSend(qemuMonitorPtr mon, > > qemuMonitorMessagePtr msg) > > { > > int ret = -1; > > + struct timeval now; > > + unsigned long long then; > > > > if (mon->eofcb) { > > msg->lastErrno = EIO; > > @@ -706,7 +710,14 @@ int qemuMonitorSend(qemuMonitorPtr mon, > > qemuMonitorUpdateWatch(mon); > > > > while (!mon->msg->finished) { > > - if (virCondWait(&mon->notify, &mon->lock) < 0) > > + if (gettimeofday(&now, NULL) < 0) { > > + virReportSystemError(errno, "%s", > > + _("cannot get time of day")); > > + return -1; > > + } > > + then = (now.tv_sec * 1000ull) + (now.tv_usec / 1000); > > + then += QEMU_JOB_WAIT_TIME; > > + if (virCondWaitUntil(&mon->notify, &mon->lock, then) < 0) > > goto cleanup; > > } > > This may seem simple, but it has a lot of nasty consequences. > > Adding the timeout causes the thread to stop waiting for the > monitor command reply, and returns an error for that API call. > > If QEMU should recover though, and more API calls are made > which issue monitor commands, all those future commands will > receive the wrong reply data. > > If we are going to allow a timeout when waiting for a reply > to a monitor command, then we need to mark the monitor as > 'broken' and forbid all future use of it until the VM is > restarted. > > If it was a simple 'info' command, then we could potentially > add code to read+discard the delayed reply later. > > If it was an action command though, we can't simply discard > the delayed reply, because that will result in libvirt's > view of the world becoming out of sync with QEMU. In certain > cases we may be able to cope with this, by listening for > event notifications. > > eg, if 'stop' command times out, and libvirt will thing the > VM is still running, but if QEMU later completes it, then > it will in fact be paused. We will see a 'PAUSED' event from > QEMU that lets us re-sync our state. > > If something like a 'device_add' commands time out though, we > have no way to gracefully recover. > > > NB, I'm not saying your patch is wrong. In fact I think it is > potentially a good idea, but we need to make sure we are able > to safely deal with the consequences of timing out first. What I wonder is if we shouldn't do more tight monitoring of the subprocesses instead of just relying on the pipe to the monitor to just detect exit. At least on linux we could use /proc/$pid/status to get more information about the process state, this would allow to detect maybe ahead of time things like stopped processes or abnormal activity. The problem as you said is that once we sent a command to the monitor, not waiting for the answer put the whole communication at risk, Ideally we should be able to signal the qemu child that we want to reset the interface like the reset button on a VT220 terminal sending a break through the serial line, it would be really useful to have something to reset asynchronously data on a QEmu monitor. I don't know what would be the best way to implement this on an Unix/Linux pipe though. But I agree using a timeout and aborting in the current framework doesn't work. I also agree with Jirka that a simpler API for just listing state not involving a round-trip to the app would be a significant improvement. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From wency at cn.fujitsu.com Thu Apr 7 05:16:45 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Thu, 07 Apr 2011 13:16:45 +0800 Subject: [libvirt] [PATCH] init path to NULL In-Reply-To: References: <4D9C064C.1040605@cn.fujitsu.com> Message-ID: <4D9D48BD.8030408@cn.fujitsu.com> At 04/06/2011 02:42 PM, Matthias Bolte Write: > 2011/4/6 Wen Congyang : >> This bug was introduce by commit 57162db8, and it will cause libvirtd crashed. >> >> --- >> src/util/pci.c | 2 +- >> 1 files changed, 1 insertions(+), 1 deletions(-) >> >> diff --git a/src/util/pci.c b/src/util/pci.c >> index 6ed96f4..a7b8caa 100644 >> --- a/src/util/pci.c >> +++ b/src/util/pci.c >> @@ -1180,7 +1180,7 @@ pciWaitForDeviceCleanup(pciDevice *dev, const char *matcher) >> static char * >> pciReadDeviceID(pciDevice *dev, const char *id_name) >> { >> - char *path; >> + char *path = NULL; >> char *id_str; >> >> if (pciDeviceFile(&path, dev->name, id_name) < 0) { >> -- >> 1.7.1 >> > > Oops... shows that I didn't tests this well enough :( > > ACK. > > Maybe you could make the commit summary more verbose, for example > "pci: avoid invalid free, init path to NULL". Thanks, pushed with commit summary changed. > > Matthias > From wency at cn.fujitsu.com Thu Apr 7 05:18:42 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Thu, 07 Apr 2011 13:18:42 +0800 Subject: [libvirt] [PATCH 2_2/3] reattach pci device when pciBindDeviceToStub() failed In-Reply-To: <4D9CBD1F.7010809@redhat.com> References: <4D90306A.6060805@cn.fujitsu.com> <4D90323D.4000008@cn.fujitsu.com> <4D9A4BFD.8090405@redhat.com> <4D9C128A.7040309@cn.fujitsu.com> <4D9CBD1F.7010809@redhat.com> Message-ID: <4D9D4932.4080908@cn.fujitsu.com> At 04/07/2011 03:21 AM, Eric Blake Write: > On 04/06/2011 01:13 AM, Wen Congyang wrote: >> >> We should bind pci device to original driver when pciBindDeviceToStub() failed. >> If the pci device is not bound to any driver before calling pciBindDeviceToStub(), >> we should only unbind it from pci-stub. If it is bound to pci-stub, we should not >> unbid it from pci-stub. > > s/unbid/unbind/ > >> +remove_id: >> /* If 'remove_id' exists, remove the device id from pci-stub's dynamic >> * ID table so that 'drivers_probe' works below. >> */ >> if (pciDriverFile(&path, driver, "remove_id") < 0) { >> + /* We do not remove PCI ID from pci-stub, and we can not reprobe it */ >> + if (dev->reprobe) { >> + VIR_WARN("Not remove PCI ID '%s' from %s, and the device can" >> + "not be reprobed again.", dev->id, driver); > > s/Not remove/Could not remove/ > s/can not/cannot/ > s/reprobed again/probed again/ > >> @@ -1018,6 +1086,13 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) >> virReportSystemError(errno, >> _("Failed to remove PCI ID '%s' from %s"), >> dev->id, driver); >> + >> + /* remove PCI ID from pci-stub failed, and we can not reprobe it */ >> + if (dev->reprobe) { >> + VIR_WARN("Faile to remove PCI ID '%s' from %s, and the device can" >> + "not be reprobed again.", dev->id, driver); > > s/Faile /Failed / > s/reprobed again/probed again/ > > ACK with those warning message grammar cleanups. I fix these warning message grammar, and pushed these serial patches. Thanks for reviewing. > From matthias.bolte at googlemail.com Thu Apr 7 07:02:36 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Thu, 7 Apr 2011 09:02:36 +0200 Subject: [libvirt] virsh: Can't create .vmdk virtual disk over vCenter while over ESX it works well In-Reply-To: <4D9C3FD8.80108@rambler.ru> References: <4D9C3FD8.80108@rambler.ru> Message-ID: 2011/4/6 computernews at rambler.ru : > Hello, > > I am trying to create the virtual disk over "virsh". My target is the ESX > server that is a part of the vCenter. That is why I connect to it using the > vpx://-like URL. The connection itself is being established correctly. > Commands like "list --all", "dumpxml " "vol-dumpxml " work > perfectly well. What doesn't work for me at the moment is "vol-create --file > --pool ". I would suspect that I am passing some > parameters incorrectly and would be digging more into a documentation but I > am getting the following response from the server: > > virsh # vol-create --file vadp4.xml --pool "iscsi-esx4-1" > error: Failed to create vol from vadp4.xml > error: internal error Could not create volume: NotImplemented - Der > angeforderte > ?Vorgang wird vom Server nicht implementiert. > > I have to admit that the very same command worked if I connect to ESX server > directly (using esx://-like URL). > > My question is if it is planned to implement the virtual disk creation in > case of vCentere is involved ? The error message is a bit misleading, but expected. The NotImplemented error actually comes from the vCenter Server, that doesn't seem to support forwarding CreateVirtualDisk_Task calls to the ESX servers. I haven't figured out yet how the vSphere Client connected to a vCenter Server manages to do disk creation. So you could consider this a missing workaround in libvirt, or the lack of proper knowledge about how to do disk creation via a vCenter Server. Matthias From matthias.bolte at googlemail.com Thu Apr 7 07:16:33 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Thu, 7 Apr 2011 09:16:33 +0200 Subject: [libvirt] ESX network functionality In-Reply-To: References: Message-ID: 2011/4/6 James Barkley : > Yes, I used the managed object called Network. It does get a little dicey > with VMware due to the addition of port groups and virtual switches > (admittedly, not sure how this works in most other hypervisors). You > certainly can't have transient network objects, and any creation/destruction > of a network object seems like it must necessarily involve either > creation/destruction of a port group or creation/destruction of a vswitch. I > believe using the Network managed object is the right approach, but am not > yet 100% confident. My next task is to facilitate the creation of a new > network through virNetworkDefineXML or virNetworkCreateXML. If you'd prefer, > I can wait until I've completed this functionality to submit the patch, as > it may drive me to adopt a different approach. The docs about the Network object say that they are created and destroyed automatically as needed. Did you try if a port group without virtual machines attached to it has a corresponding Network object? You could send your current code for an initial review, as the implementation for virNetworkDefineXML should go into a second patch. I think you cannot implement virNetworkCreateXML as that's supposed to create a transient network and that's not how network work. On the other hand, what would be the semantic of virNetworkCreate and virNetworkDestroy? Those require that there is some kind of power switch on the networks, like the power state of the virtual machines. So the life cycle of a network is not entirely clear to me yet. >>I assume you made esxNumOfDefinedNetworks return 0 to get virsh >>net-list working as there network in the VMware context are always >>active. > Correct. I was debating on whether or not to have it loop through the > network list and check the "active/inactive" just for thoroughness, but if > you're fine with just returning 0 and commenting why, then I'll leave it. Is there actually something like an active/inactive state for a network? >>The recommended way for sending patches is git send-email. > Barring any other recommendations I'll figure out git send email and submit > the patch to the list shortly. You can also use git format-patch and attach the patch file as plaintext to an email, but sending patches inline in email (like git send email does) is the preferred way. Matthias > thanks, > -jb > > On Wed, Apr 6, 2011 at 2:37 AM, Matthias Bolte > wrote: >> >> Sorry, I forgot to reply to your follow up question on the users list. >> >> 2011/4/6 James Barkley : >> > Greetings: >> > I've added code to the ESX driver to support some basic network >> > functionality. I'm pretty new to this list, so please tell me how to >> > proceed >> > with code review and patch submission (yes I've read the contributor >> > guidelines on the wiki). It seems like people are emailing a patch file >> > for >> > every file they've changed, each in separate emails with [1 of N] in the >> > subject, is that right? Or is it better to paste in code, get some >> > feedback, >> > and eventually attach the patch to the bug tracker item? >> >> The normal approach is to have one commit/patch per logical >> self-contained change. After each commit/patch the codebase has to be >> in a compilable stage. For example you cannot add the code using the >> generated SOAP bindings, before you actually added them to the >> esx_vi_generator.input file. >> >> The [1 of N] style patch series are typically used for large changes >> that are split in several logical, self-contained parts. Splitting >> like this simplifies reviewing and later on figuring out bugs using >> git bisect. >> >> You typically don't split on a per file basis. >> >> In your case I'd suggest to create a single commit/patch for your >> addition, as it is one logical piece of work. You _could_ (but I don't >> recommend to) split it in multiple patches. For example one for the >> esx_vi_generator.input addition, one for the VI helper function >> additions and one for the actual driver functions, but I'd consider >> this to be too fine grained. >> >> > I've updated the code for the ESX driver to be able to handle the >> > following >> > functions : >> > - virNetworkLookupByName >> > - virConnectNumOfDefinedNetworks >> > - virConnectNumOfNetworks >> > - virConnectListNetworks >> >> Is this sufficient to make virsh net-list work? >> >> > I basically mapped the VMware Managed Object Reference for networks into >> > a >> > few data structures and added the following functions to the internal >> > driver >> >> You mean the managed object called Network? They _seem_ to be the >> natural fit. But I'm not sure if that's the correct approach, as you >> cannot directly create/destroy such objects and they are bound in some >> way to the port groups on a virtual switch. Also I'm not sure about >> the exact semantics of networks and port groups. >> >> That's what I meant as I said about the mapping between libvirt and >> VMware. We need to be sure to use the right approach from the start to >> avoid making breaking changes across releases later on. >> >> > API: >> > - esxNumOfNetworks >> > - esxListNetworks >> > - esxNumOfDefinedNetworks >> >> I assume you made esxNumOfDefinedNetworks return 0 to get virsh >> net-list working as there network in the VMware context are always >> active. >> >> > - esxNetworkLookupByName >> > - esxVI_LookupNetworkList >> > - esxVI_LookupNetworkByName >> > These functions were modeled after existing functions from the domain >> > and >> > storage libraries. The following files were touched: >> > - esx_network_driver.c >> > - esx_vi.c >> > - esx_vi.h >> > - esx_vi_generator.input >> >> Apart from the question whether the Network managed object is the >> correct match, the next step is to send your patch to this list to get >> a review. The recommended way for sending patches is git send-email. >> >> Matthias > > From veillard at redhat.com Thu Apr 7 07:21:34 2011 From: veillard at redhat.com (Daniel Veillard) Date: Thu, 7 Apr 2011 15:21:34 +0800 Subject: [libvirt] [PATCH v5] qemu: Remove the managed state file only if restoring succeeded In-Reply-To: <1302143512-23422-1-git-send-email-jyang@redhat.com> References: <1302143512-23422-1-git-send-email-jyang@redhat.com> Message-ID: <20110407072134.GF24385@redhat.com> On Thu, Apr 07, 2011 at 10:31:52AM +0800, Osier Yang wrote: > 1) Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to > restore the domain from managedsave'ed image if it exists (by > invoking "qemuDomainObjRestore"), but it unlinks the image even > if restoring fails, which causes data loss. (This problem exists > for "virsh managedsave dom; virsh start dom"). > > The fix for is to unlink the managed state file only if restoring > succeeded. > > 2) For "virsh save dom; virsh restore dom;", it can cause data > corruption if one reuse the saved state file for restoring. Add > doc to tell user about it. > > 3) In "qemuDomainObjStart", if "managed_save" is NULL, we shouldn't > fallback to start the domain, skipping it to cleanup as a incidental > fix. Discovered by Eric. > > --- > src/qemu/qemu_driver.c | 12 +++++++----- > tools/virsh.pod | 6 +++++- > 2 files changed, 12 insertions(+), 6 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 48fe266..a84780b 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -3423,18 +3423,20 @@ static int qemudDomainObjStart(virConnectPtr conn, > > /* > * If there is a managed saved state restore it instead of starting > - * from scratch. In any case the old state is removed. > + * from scratch. The old state is removed once the restoring succeeded. > */ > managed_save = qemuDomainManagedSavePath(driver, vm); > + > + if (!managed_save) > + goto cleanup; > + > if ((managed_save) && (virFileExists(managed_save))) { > ret = qemuDomainObjRestore(conn, driver, vm, managed_save); > > - if (unlink(managed_save) < 0) { > + if ((ret == 0) && (unlink(managed_save) < 0)) > VIR_WARN("Failed to remove the managed state %s", managed_save); > - } > > - if (ret == 0) > - goto cleanup; > + goto cleanup; > } > > ret = qemuProcessStart(conn, driver, vm, NULL, start_paused, -1, NULL, > diff --git a/tools/virsh.pod b/tools/virsh.pod > index f4bd294..6319373 100644 > --- a/tools/virsh.pod > +++ b/tools/virsh.pod > @@ -546,7 +546,11 @@ I parameter in the domain's XML definition. > > =item B I > > -Restores a domain from an B state file. See I for more info. > +Restores a domain from an B state file. See I for more info. > + > +B: To avoid corrupting file system contents within the domain, you > +should not reuse the saved state file to B unless you are convinced > +with reverting the domain to the previous state. > > =item B I I ACK, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From hutao at cn.fujitsu.com Thu Apr 7 07:49:15 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Thu, 7 Apr 2011 15:49:15 +0800 Subject: [libvirt] [PATCH 1/6] Add virObject and virAtomic. In-Reply-To: <4D9CCAED.4040508@redhat.com> References: <4D9CCAED.4040508@redhat.com> Message-ID: <20110407074915.GB7711@localhost.localdomain> On Wed, Apr 06, 2011 at 02:19:57PM -0600, Eric Blake wrote: > On 04/06/2011 01:19 AM, Hu Tao wrote: > > virObject is the base struct that manages reference-counting > > for all structs that need the ability of reference-counting. > > > > virAtomic provides atomic operations which are thread-safe. > > --- > > src/Makefile.am | 2 + > > src/libvirt_private.syms | 5 ++++ > > src/util/viratomic.c | 46 ++++++++++++++++++++++++++++++++++++++++ > > src/util/viratomic.h | 30 ++++++++++++++++++++++++++ > > src/util/virobject.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ > > src/util/virobject.h | 39 ++++++++++++++++++++++++++++++++++ > > 6 files changed, 174 insertions(+), 0 deletions(-) > > create mode 100644 src/util/viratomic.c > > create mode 100644 src/util/viratomic.h > > create mode 100644 src/util/virobject.c > > create mode 100644 src/util/virobject.h > > > +++ b/src/libvirt_private.syms > > @@ -993,3 +993,8 @@ virXPathUInt; > > virXPathULong; > > virXPathULongHex; > > virXPathULongLong; > > + > > +# object.h > > virobject.h, and float this section to appear before virtaudit.h (hmm, Oops, there are always things escape from under your nose:( > maybe we should do a preliminary patch to rename that to viraudit.h, so > that we aren't mixing vir vs. virt in quite so many places). > > > +virObjectInit; > > +virObjectRef; > > +virObjectUnref; > > Missing exports from viratomic.h. Why the linker doesn't complain about this this time? > > > diff --git a/src/util/viratomic.c b/src/util/viratomic.c > > new file mode 100644 > > index 0000000..629f189 > > --- /dev/null > > +++ b/src/util/viratomic.c > > @@ -0,0 +1,46 @@ > > > + > > +#ifdef WIN32 > > +long virAtomicInc(long *value) > > +{ > > + return InterlockedIncrement(value); > > +} > > + > > +long virAtomicDec(long *value) > > +{ > > + return InterlockedDecrement(value); > > This is an OS-specific replacement. > > > +} > > +#else /* WIN32 */ > > +long virAtomicInc(long *value) > > +{ > > + return __sync_add_and_fetch(value, 1); > > This is a gcc builtin, and will fail to compile with other C99 Yes. > compilers. Meanwhile, won't the gcc builtin just work for mingw (that Not sure about this. I don't have a mingw environment to test, but I trust gcc and guess it does. > is, no need to use the OS-specific InterlockedIncrement if you have the > compiler builtin instead). > > I think this file needs three implementations: > > #if defined __GNUC__ || > use compiler builtins of __sync_add_and_fetch > #elif defined WIN32 > use OS primitives, like InterlockedIncrement > #else > we're hosed when it comes to lightweight versions, but we can still > implement a heavyweight replacement that uses virMutex > #endif Agreed, this is a better way. > > > +++ b/src/util/viratomic.h > > @@ -0,0 +1,30 @@ > > > +#ifndef __VIR_ATOMIC_H > > +#define __VIR_ATOMIC_H > > + > > +long virAtomicInc(long *value); > > +long virAtomicDec(long *value); > > Mark both of these ATTRIBUTE_NONNULL(1) OK. > > I'm debating whether they should also be marked ATTRIBUTE_RETURN_CHECK No, there are cases you just want to inc/dec a value but do not check the modified value. > > > +++ b/src/util/virobject.c > > @@ -0,0 +1,52 @@ > > + > > +#include "viratomic.h" > > +#include "virobject.h" > > +#include "logging.h" > > + > > +int virObjectInit(virObjectPtr obj, void (*free)(virObjectPtr obj)) > > You should declare a typedef: > > typedef void (*virObjectFreer)(virObjectPtr); > > then it becomes simpler to read: > > int virObjectInit(virObjectPtr obj, virObjectFreer f) > > Use a different name (I used freer/f above) to avoid -Wshadow warnings > with free(). OK. > > > +{ > > + if (!free) { > > Especially since shadowing means it's impossible to tell if this > statement is always true (the address of free() exists) or conditional > (there is a local variable named free shadowing the global function), > and context-sensitive code reviews are tougher :) > > > + VIR_ERROR0("method free is required."); > > + return -1; > > + } > > Should this function also check and return -1 if obj->free was not NULL > on entry (that is, guarantee that you can't initialize an object twice)? Agreed. And it is dangerous to initialize an object more than once because the ref count may already changed and a second initializaton just do the wrong thing. > > > + > > + obj->ref = 1; > > + obj->free = free; > > + > > + return 0; > > +} > > + > > +void virObjectRef(virObjectPtr obj) > > +{ > > + sa_assert(obj->ref > 0); > > This is useless. It only helps static analyzers (like clang), > > > + virAtomicInc(&obj->ref); > > but there's nothing to analyze that depends on knowing the value was > positive. > > I'm debating whether to do checking. Maybe we should do: > > if (virAtomicInc(&obj->ref) < 2) This means bad things happened, and it is not enough to just give a warning. Think about this: two threads visit an object whose memory is corrupted that it's ref count becomes 0 but it doesn't get freed. thread 1: thread 2: ref the object (ref count becomes 1) unref the object (ref count becomes 0, object being freed) do something with the object, but it is already freed by thread 2 We should catch abnormal ref count by some way(if not sa_assert) > VIR_WARN("invalid call to virObjectRef"); > > > +void virObjectUnref(virObjectPtr obj) > > +{ > > + sa_assert(obj->ref > 0); > > Again, I'm not sure that this buys anything. But we may want to do: > > int ref = virAtomicDec(&obj->ref); > if (ref < 0) > VIR_WARN("invalid call to virObjectUnref"); > else if (ref == 0) > obj->free(obj) > > > + if (virAtomicDec(&obj->ref) == 0) > > + obj->free(obj); > > +} > > diff --git a/src/util/virobject.h b/src/util/virobject.h > > new file mode 100644 > > index 0000000..cd7d3e8 > > --- /dev/null > > +++ b/src/util/virobject.h > > > + > > +typedef struct _virObject virObject; > > +typedef virObject *virObjectPtr; > > + > > +struct _virObject { > > + long ref; > > + void (*free)(virObjectPtr obj); > > Is virObjectPtr the right thing to use here? If we assume that all > clients will always have a virObjectPtr as their first member, then they > can cast that back into the larger object. Is void* opaque any better, Exactly the way(you have already saw my other patches when I was typing this:)) > although that then it requires a third parameter for virObjectInit? > Maybe it's worth some documentation on intended use in this header (am I OK. > getting this usage right? I haven't looked at how you used it later in > the series, but am just guessing): > > struct _virFoo { > virObject obj; /* Must be first member */ > ... > }; > static void virFooFree(virObjectPtr obj) > { > virFooPtr foo = obj; > ... > } > virFooPtr virFooNew(void) > { > virFooPtr foo; > if (VIR_ALLOC(foo) < 0) { > virReportOOMError(); > return NULL; > } > virObjectInit(&foo->obj, virFooFree); > ... > return foo; > } > > > > +}; > > + > > +int virObjectInit(virObjectPtr obj, void (*free)(virObjectPtr obj)); > > ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK > > > +void virObjectRef(virObjectPtr obj); > > ATTRIBUTE_NONNULL(1) > > Also, should this return the current reference count? Not all callers > will need it, but returning void is harsh if someone might be able to > use it. No. It is meaningless to return the current reference count, because it may already changed by others after the caller reads the returned value on which it is not safe to make some choice. > > > +void virObjectUnref(virObjectPtr obj); > > Likewise. > > -- > Eric Blake eblake at redhat.com +1-801-349-2682 > Libvirt virtualization library http://libvirt.org > From hutao at cn.fujitsu.com Thu Apr 7 07:51:58 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Thu, 7 Apr 2011 15:51:58 +0800 Subject: [libvirt] [PATCH 0/6] virObject for reference-counting In-Reply-To: <4D9CDB8A.7000304@redhat.com> References: <4D9CDB8A.7000304@redhat.com> Message-ID: <20110407075158.GC7711@localhost.localdomain> On Wed, Apr 06, 2011 at 03:30:50PM -0600, Eric Blake wrote: > On 04/06/2011 01:18 AM, Hu Tao wrote: > > This series adds a virObject structure that manages reference-counting. > > > > Some notes about referece-counting introduced by this series: > > > > A thread owns a virObject by incrementing its reference-count by 1. > > If a thread owns a virObject, the virObject is guarenteed not be > > freed until the thread releases ownership by decrementing its > > reference-count by 1. A thread can't access a virObject after it > > releases the ownership of virObject because it can be freed at > > anytime. > > > > A thread can own a virObject legally in these ways: > > > > - a thread owns a virObject that it creates. > > - a thread owns a virObject if another thread passes the ownership > > to it. Example: qemuMonitorOpen > > - a thread gets a virObject from a container. > > Example: virDomainFindByUUID > > - a container owns a virObject by incrementing its reference-count > > by 1 before adding it to the container > > - if a virObject is removed from a container its reference-count > > must be decremented by 1 > > > > By following these rules, there is no need to protect operations on > > an object's reference-count by an external lock. (like in old ways > > virDomainObj lock protects qemu monitor's ref-count.) > > These rules _need_ to be part of the patch series, preferably added at > the same time as patch 1/6 (see for example how src/qemu/THREADS.txt > documents threading issues related to qemu). I don't know whether > virobject.h or a standalone document is better (but if you do a > standalone document, then virobject.h should at least mention it). OK. Will put it in virobject.h in next version. > > -- > Eric Blake eblake at redhat.com +1-801-349-2682 > Libvirt virtualization library http://libvirt.org > From wency at cn.fujitsu.com Thu Apr 7 08:42:40 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Thu, 07 Apr 2011 16:42:40 +0800 Subject: [libvirt] [PATCH 1/6] Enhance the streams helper to support plain file I/O In-Reply-To: <1300901798-5017-2-git-send-email-berrange@redhat.com> References: <1300901798-5017-1-git-send-email-berrange@redhat.com> <1300901798-5017-2-git-send-email-berrange@redhat.com> Message-ID: <4D9D7900.5060304@cn.fujitsu.com> At 03/24/2011 01:36 AM, Daniel P. Berrange Write: > The O_NONBLOCK flag doesn't work as desired on plain files > or block devices. Introduce an I/O helper program that does > the blocking I/O operations, communicating over a pipe that > can support O_NONBLOCK > > * src/fdstream.c, src/fdstream.h: Add non-blocking I/O > on plain files/block devices > * src/Makefile.am, src/util/iohelper.c: I/O helper program > * src/qemu/qemu_driver.c, src/lxc/lxc_driver.c, > src/uml/uml_driver.c, src/xen/xen_driver.c: Update for > streams API change > --- > po/POTFILES.in | 1 + > src/Makefile.am | 12 +++ > src/fdstream.c | 233 ++++++++++++++++++++++++++++++++++++------------ > src/fdstream.h | 5 + > src/lxc/lxc_driver.c | 2 +- > src/qemu/qemu_driver.c | 2 +- > src/uml/uml_driver.c | 2 +- > src/util/iohelper.c | 203 +++++++++++++++++++++++++++++++++++++++++ > src/xen/xen_driver.c | 2 +- > 9 files changed, 402 insertions(+), 60 deletions(-) > create mode 100644 src/util/iohelper.c > > diff --git a/po/POTFILES.in b/po/POTFILES.in > index 805e5ca..12adb3e 100644 > --- a/po/POTFILES.in > +++ b/po/POTFILES.in > @@ -94,6 +94,7 @@ src/util/event_poll.c > src/util/hash.c > src/util/hooks.c > src/util/hostusb.c > +src/util/iohelper.c > src/util/interface.c > src/util/iptables.c > src/util/json.c > diff --git a/src/Makefile.am b/src/Makefile.am > index c3729a6..1d8115b 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -380,6 +380,9 @@ STORAGE_DRIVER_DISK_SOURCES = \ > STORAGE_HELPER_DISK_SOURCES = \ > storage/parthelper.c > > +UTIL_IO_HELPER_SOURCES = \ > + util/iohelper.c > + > # Network filters > NWFILTER_DRIVER_SOURCES = \ > nwfilter/nwfilter_driver.h nwfilter/nwfilter_driver.c \ > @@ -1203,6 +1206,15 @@ EXTRA_DIST += $(LIBVIRT_QEMU_SYMBOL_FILE) > > libexec_PROGRAMS = > > +libexec_PROGRAMS += libvirt_iohelper > +libvirt_iohelper_SOURCES = $(UTIL_IO_HELPER_SOURCES) > +libvirt_iohelper_LDFLAGS = $(WARN_LDFLAGS) $(AM_LDFLAGS) > +libvirt_iohelper_LDADD = \ > + libvirt_util.la \ > + ../gnulib/lib/libgnu.la > + > +libvirt_iohelper_CFLAGS = $(AM_CFLAGS) > + Is libvirt_iohelper for libvirtd? libvirt_iohelper is provided by libvirt-.rpm, but we still install it when we build withoud libvirtd. We will meet the following problems: Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/wency/rpmbuild/BUILDROOT/libvirt-0.9.0-1.el6.x86_64 error: Installed (but unpackaged) file(s) found: /usr/libexec/libvirt_iohelper > if WITH_STORAGE_DISK > if WITH_LIBVIRTD > libexec_PROGRAMS += libvirt_parthelper From jean-baptiste.rouault at diateam.net Thu Apr 7 08:47:44 2011 From: jean-baptiste.rouault at diateam.net (Jean-Baptiste Rouault) Date: Thu, 7 Apr 2011 10:47:44 +0200 Subject: [libvirt] [PATCH] docs: remove "returns" word from beginning of lines Message-ID: <1302166064-29080-1-git-send-email-jean-baptiste.rouault@diateam.net> Move "returns" keyword from beginning of API doc lines when it does not describe return values. Maybe the API doc extractor could be changed to look for "returns: " to avoid such confusion. --- src/libvirt.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 85dfc58..344e921 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -10097,8 +10097,8 @@ error: * * The virDomainPtr object handle passed into the callback upon delivery * of an event is only valid for the duration of execution of the callback. - * If the callback wishes to keep the domain object after the callback - * returns, it shall take a reference to it, by calling virDomainRef. + * If the callback wishes to keep the domain object after the callback returns, + * it shall take a reference to it, by calling virDomainRef. * The reference can be released once the object is no longer required * by calling virDomainFree. * @@ -12727,8 +12727,8 @@ error: * * The virDomainPtr object handle passed into the callback upon delivery * of an event is only valid for the duration of execution of the callback. - * If the callback wishes to keep the domain object after the callback - * returns, it shall take a reference to it, by calling virDomainRef. + * If the callback wishes to keep the domain object after the callback returns, + * it shall take a reference to it, by calling virDomainRef. * The reference can be released once the object is no longer required * by calling virDomainFree. * -- 1.7.0.4 From jyang at redhat.com Thu Apr 7 09:00:00 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 07 Apr 2011 17:00:00 +0800 Subject: [libvirt] [PATCH v5] qemu: Remove the managed state file only if restoring succeeded In-Reply-To: <20110407072134.GF24385@redhat.com> References: <1302143512-23422-1-git-send-email-jyang@redhat.com> <20110407072134.GF24385@redhat.com> Message-ID: <4D9D7D10.6070608@redhat.com> ? 2011?04?07? 15:21, Daniel Veillard ??: > On Thu, Apr 07, 2011 at 10:31:52AM +0800, Osier Yang wrote: >> 1) Both "qemuDomainStartWithFlags" and "qemuAutostartDomain" try to >> restore the domain from managedsave'ed image if it exists (by >> invoking "qemuDomainObjRestore"), but it unlinks the image even >> if restoring fails, which causes data loss. (This problem exists >> for "virsh managedsave dom; virsh start dom"). >> >> The fix for is to unlink the managed state file only if restoring >> succeeded. >> >> 2) For "virsh save dom; virsh restore dom;", it can cause data >> corruption if one reuse the saved state file for restoring. Add >> doc to tell user about it. >> >> 3) In "qemuDomainObjStart", if "managed_save" is NULL, we shouldn't >> fallback to start the domain, skipping it to cleanup as a incidental >> fix. Discovered by Eric. >> >> --- >> src/qemu/qemu_driver.c | 12 +++++++----- >> tools/virsh.pod | 6 +++++- >> 2 files changed, 12 insertions(+), 6 deletions(-) >> >> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c >> index 48fe266..a84780b 100644 >> --- a/src/qemu/qemu_driver.c >> +++ b/src/qemu/qemu_driver.c >> @@ -3423,18 +3423,20 @@ static int qemudDomainObjStart(virConnectPtr conn, >> >> /* >> * If there is a managed saved state restore it instead of starting >> - * from scratch. In any case the old state is removed. >> + * from scratch. The old state is removed once the restoring succeeded. >> */ >> managed_save = qemuDomainManagedSavePath(driver, vm); >> + >> + if (!managed_save) >> + goto cleanup; >> + >> if ((managed_save)&& (virFileExists(managed_save))) { >> ret = qemuDomainObjRestore(conn, driver, vm, managed_save); >> >> - if (unlink(managed_save)< 0) { >> + if ((ret == 0)&& (unlink(managed_save)< 0)) >> VIR_WARN("Failed to remove the managed state %s", managed_save); >> - } >> >> - if (ret == 0) >> - goto cleanup; >> + goto cleanup; >> } >> >> ret = qemuProcessStart(conn, driver, vm, NULL, start_paused, -1, NULL, >> diff --git a/tools/virsh.pod b/tools/virsh.pod >> index f4bd294..6319373 100644 >> --- a/tools/virsh.pod >> +++ b/tools/virsh.pod >> @@ -546,7 +546,11 @@ I parameter in the domain's XML definition. >> >> =item B I >> >> -Restores a domain from an B state file. See I for more info. >> +Restores a domain from an B state file. See I for more info. >> + >> +B: To avoid corrupting file system contents within the domain, you >> +should not reuse the saved state file to B unless you are convinced >> +with reverting the domain to the previous state. >> >> =item B I I > > ACK, thanks ! > > Daniel > Thanks, applied. Osier From berrange at redhat.com Thu Apr 7 09:33:03 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 7 Apr 2011 10:33:03 +0100 Subject: [libvirt] [PATCH 3/6] use virObject to manage reference-count of virDomainObj In-Reply-To: References: Message-ID: <20110407093303.GB3669@redhat.com> On Wed, Apr 06, 2011 at 03:19:51PM +0800, Hu Tao wrote: > This patch also eliminates a dead-lock bug in > qemuDomainObjBeginJobWithDriver: if virCondWaitUntil() timeouts, the > thread tries to acquire qemu driver lock while holding virDomainObj > lock. > --- > src/conf/domain_conf.c | 56 ++++---- > src/conf/domain_conf.h | 6 +- > src/openvz/openvz_conf.c | 8 +- > src/qemu/qemu_domain.c | 32 ++--- > src/qemu/qemu_domain.h | 2 +- > src/qemu/qemu_driver.c | 304 ++++++++++++++++++++------------------------- > src/qemu/qemu_migration.c | 45 +++---- > src/qemu/qemu_process.c | 33 ++--- > src/vmware/vmware_conf.c | 2 +- > 9 files changed, 215 insertions(+), 273 deletions(-) > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index 90a1317..fc76a00 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -47,6 +47,7 @@ > #include "storage_file.h" > #include "files.h" > #include "bitmap.h" > +#include "virobject.h" > > #define VIR_FROM_THIS VIR_FROM_DOMAIN > > @@ -395,9 +396,7 @@ static void > virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED) > { > virDomainObjPtr obj = payload; > - virDomainObjLock(obj); > - if (virDomainObjUnref(obj) > 0) > - virDomainObjUnlock(obj); > + virDomainObjUnref(obj); > } > > int virDomainObjListInit(virDomainObjListPtr doms) > @@ -437,7 +436,7 @@ virDomainObjPtr virDomainFindByID(const virDomainObjListPtr doms, > virDomainObjPtr obj; > obj = virHashSearch(doms->objs, virDomainObjListSearchID, &id); > if (obj) > - virDomainObjLock(obj); > + virDomainObjRef(obj); > return obj; > } > > @@ -452,7 +451,7 @@ virDomainObjPtr virDomainFindByUUID(const virDomainObjListPtr doms, > > obj = virHashLookup(doms->objs, uuidstr); > if (obj) > - virDomainObjLock(obj); > + virDomainObjRef(obj); > return obj; > } > > @@ -476,7 +475,7 @@ virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms, > virDomainObjPtr obj; > obj = virHashSearch(doms->objs, virDomainObjListSearchName, name); > if (obj) > - virDomainObjLock(obj); > + virDomainObjRef(obj); > return obj; > } This is a major change in semantics, which makes pretty much every single caller non-thread safe, unless the callers are all changed todo virDomainObjLock immediately after calling this. So I don't really see the point in this - it just means more code duplication. > > @@ -967,6 +966,12 @@ static void virDomainObjFree(virDomainObjPtr dom) > { > if (!dom) > return; > + virDomainObjUnref(dom); > +} > + > +static void doDomainObjFree(virObjectPtr obj) > +{ > + virDomainObjPtr dom = (virDomainObjPtr)obj; > > VIR_DEBUG("obj=%p", dom); > virDomainDefFree(dom->def); > @@ -984,21 +989,13 @@ static void virDomainObjFree(virDomainObjPtr dom) > > void virDomainObjRef(virDomainObjPtr dom) > { > - dom->refs++; > - VIR_DEBUG("obj=%p refs=%d", dom, dom->refs); > + virObjectRef(&dom->obj); > } > > > -int virDomainObjUnref(virDomainObjPtr dom) > +void virDomainObjUnref(virDomainObjPtr dom) > { > - dom->refs--; > - VIR_DEBUG("obj=%p refs=%d", dom, dom->refs); > - if (dom->refs == 0) { > - virDomainObjUnlock(dom); > - virDomainObjFree(dom); > - return 0; > - } > - return dom->refs; > + virObjectUnref(&dom->obj); > } > > static virDomainObjPtr virDomainObjNew(virCapsPtr caps) > @@ -1010,6 +1007,11 @@ static virDomainObjPtr virDomainObjNew(virCapsPtr caps) > return NULL; > } > > + if (virObjectInit(&domain->obj, doDomainObjFree)) { > + VIR_FREE(domain); > + return NULL; > + } > + > if (caps->privateDataAllocFunc && > !(domain->privateData = (caps->privateDataAllocFunc)())) { > virReportOOMError(); > @@ -1027,9 +1029,7 @@ static virDomainObjPtr virDomainObjNew(virCapsPtr caps) > return NULL; > } > > - virDomainObjLock(domain); > domain->state = VIR_DOMAIN_SHUTOFF; > - domain->refs = 1; > > virDomainSnapshotObjListInit(&domain->snapshots); > > @@ -1075,8 +1075,10 @@ virDomainObjPtr virDomainAssignDef(virCapsPtr caps, > domain->def = def; > > virUUIDFormat(def->uuid, uuidstr); > + virDomainObjRef(domain); > if (virHashAddEntry(doms->objs, uuidstr, domain) < 0) { > - VIR_FREE(domain); > + virDomainObjUnref(domain); > + virDomainObjFree(domain); > return NULL; > } Simiarly here, you're now requiring all callers to manually obtain a lock. > @@ -1239,39 +1243,57 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, > > qemuDriverLock(driver); > if (!(def = virDomainDefParseString(driver->caps, xml, > - VIR_DOMAIN_XML_INACTIVE))) > + VIR_DOMAIN_XML_INACTIVE))) { > + qemuDriverUnlock(driver); > goto cleanup; > + } > > - if (virSecurityManagerVerify(driver->securityManager, def) < 0) > + if (virSecurityManagerVerify(driver->securityManager, def) < 0) { > + qemuDriverUnlock(driver); > goto cleanup; > + } > > - if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) > + if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) { > + qemuDriverUnlock(driver); > goto cleanup; > + } > > - if (qemudCanonicalizeMachine(driver, def) < 0) > + if (qemudCanonicalizeMachine(driver, def) < 0) { > + qemuDriverUnlock(driver); > goto cleanup; > + } > > - if (qemuDomainAssignPCIAddresses(def) < 0) > + if (qemuDomainAssignPCIAddresses(def) < 0) { > + qemuDriverUnlock(driver); > goto cleanup; > + } > > if (!(vm = virDomainAssignDef(driver->caps, > &driver->domains, > - def, false))) > + def, false))) { > + qemuDriverUnlock(driver); > goto cleanup; > + } > + > + qemuDriverUnlock(driver); driver is now unlocked.... > > def = NULL; > > - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) > + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) { > + virDomainObjUnref(vm); ...but this method *requires* driver to be locked. > goto cleanup; /* XXXX free the 'vm' we created ? */ > + } > > if (qemuProcessStart(conn, driver, vm, NULL, > (flags & VIR_DOMAIN_START_PAUSED) != 0, > -1, NULL, VIR_VM_OP_CREATE) < 0) { > qemuAuditDomainStart(vm, "booted", false); ...and this method writes to 'driver', so it is now unsafe. > - if (qemuDomainObjEndJob(vm) > 0) > - virDomainRemoveInactive(&driver->domains, > - vm); > - vm = NULL; > + qemuDomainObjEndJob(vm); > + qemuDriverLock(driver); > + virDomainRemoveInactive(&driver->domains, > + vm); > + qemuDriverUnlock(driver); > + virDomainObjUnref(vm); > goto cleanup; > } > > @@ -1283,17 +1305,13 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, > dom = virGetDomain(conn, vm->def->name, vm->def->uuid); > if (dom) dom->id = vm->def->id; > > - if (vm && > - qemuDomainObjEndJob(vm) == 0) > - vm = NULL; > + qemuDomainObjEndJob(vm); > + virDomainObjUnref(vm); > > cleanup: > virDomainDefFree(def); > - if (vm) > - virDomainObjUnlock(vm); > if (event) > qemuDomainEventQueue(driver, event); > - qemuDriverUnlock(driver); > return dom; > } And all the usage of 'vm' in this method is now completely unlocked and unsafe. > > @@ -1307,13 +1325,14 @@ static int qemudDomainSuspend(virDomainPtr dom) { > > 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; > + return -1; > } > if (!virDomainObjIsActive(vm)) { > qemuReportError(VIR_ERR_OPERATION_INVALID, > @@ -1354,16 +1373,12 @@ static int qemudDomainSuspend(virDomainPtr dom) { > } > > endjob: > - if (qemuDomainObjEndJob(vm) == 0) > - vm = NULL; > + qemuDomainObjEndJob(vm); > > cleanup: > - if (vm) > - virDomainObjUnlock(vm); > - > + virDomainObjUnref(vm); > if (event) > qemuDomainEventQueue(driver, event); > - qemuDriverUnlock(driver); > return ret; > } Also now completely unsafe since 'vm' is never locked while making changes to it. [cut rest of patch] I don't see how any of this patch is threadsafe now that virtually no methods are acquiring the 'vm' lock. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Thu Apr 7 09:38:34 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 7 Apr 2011 10:38:34 +0100 Subject: [libvirt] [PATCH 4/6] qemu: use virObject to manage reference-counting for qemu monitor In-Reply-To: <821a47bc81d57d652997fde0dec0010e3cad75d5.1302069479.git.hutao@cn.fujitsu.com> References: <821a47bc81d57d652997fde0dec0010e3cad75d5.1302069479.git.hutao@cn.fujitsu.com> Message-ID: <20110407093834.GC3669@redhat.com> On Wed, Apr 06, 2011 at 03:19:55PM +0800, Hu Tao wrote: > --- > src/qemu/qemu_domain.c | 30 ++----------- > src/qemu/qemu_migration.c | 2 - > src/qemu/qemu_monitor.c | 109 ++++++++++++++++++++++++-------------------- > src/qemu/qemu_monitor.h | 4 +- > src/qemu/qemu_process.c | 32 +++++++------- > 5 files changed, 81 insertions(+), 96 deletions(-) > > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > index 3a3c953..d11dc5f 100644 > --- a/src/qemu/qemu_domain.c > +++ b/src/qemu/qemu_domain.c > @@ -560,9 +560,8 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) > { > qemuDomainObjPrivatePtr priv = obj->privateData; > > - qemuMonitorLock(priv->mon); > - qemuMonitorRef(priv->mon); > virDomainObjUnlock(obj); > + qemuMonitorLock(priv->mon); > } > > > @@ -573,18 +572,9 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) > void qemuDomainObjExitMonitor(virDomainObjPtr obj) > { > qemuDomainObjPrivatePtr priv = obj->privateData; > - int refs; > - > - refs = qemuMonitorUnref(priv->mon); > - > - if (refs > 0) > - qemuMonitorUnlock(priv->mon); > > + qemuMonitorUnlock(priv->mon); > virDomainObjLock(obj); > - > - if (refs == 0) { > - priv->mon = NULL; > - } > } > > > @@ -601,10 +591,8 @@ void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, > { > qemuDomainObjPrivatePtr priv = obj->privateData; > > - qemuMonitorLock(priv->mon); > - qemuMonitorRef(priv->mon); > virDomainObjUnlock(obj); > - qemuDriverUnlock(driver); > + qemuMonitorLock(priv->mon); > } > > > @@ -617,19 +605,9 @@ void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, > virDomainObjPtr obj) > { > qemuDomainObjPrivatePtr priv = obj->privateData; > - int refs; > - > - refs = qemuMonitorUnref(priv->mon); > - > - if (refs > 0) > - qemuMonitorUnlock(priv->mon); > > - qemuDriverLock(driver); > + qemuMonitorUnlock(priv->mon); > virDomainObjLock(obj); > - > - if (refs == 0) { > - priv->mon = NULL; > - } > } This means that the 'driver' lock is now whenever any QEMU monitor command is runing, which blocks the entire driver. > > void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver, > diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c > index 462e6be..6af2e24 100644 > --- a/src/qemu/qemu_migration.c > +++ b/src/qemu/qemu_migration.c > @@ -224,11 +224,9 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) > } > > virDomainObjUnlock(vm); > - qemuDriverUnlock(driver); > > nanosleep(&ts, NULL); > > - qemuDriverLock(driver); > virDomainObjLock(vm); > } Holding the 'driver' lock while sleeping blocks the entire QEMU driver. > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > index 244b22a..4b9087f 100644 > --- a/src/qemu/qemu_process.c > +++ b/src/qemu/qemu_process.c > @@ -107,7 +107,6 @@ qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > > VIR_DEBUG("Received EOF on %p '%s'", vm, vm->def->name); > > - qemuDriverLock(driver); > virDomainObjLock(vm); > > if (!virDomainObjIsActive(vm)) { > @@ -133,15 +132,17 @@ qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > qemuProcessStop(driver, vm, 0); > qemuAuditDomainStop(vm, hasError ? "failed" : "shutdown"); > > - if (!vm->persistent) > + if (!vm->persistent) { > + qemuDriverLock(driver); > virDomainRemoveInactive(&driver->domains, vm); > - else > - virDomainObjUnlock(vm); > + qemuDriverUnlock(driver); > + } > + > + virDomainObjUnlock(vm); > > if (event) { > qemuDomainEventQueue(driver, event); > } > - qemuDriverUnlock(driver); > } This violates the lock ordering rules. The 'driver' lock *must* be obtained *before* any 'vm' lock is held. Now we have some places in the code which do lock(vm) lock(driver) and other places which do lock(driver) lock(vm) so 2 threads can trivially deadlock waiting for each other Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From hutao at cn.fujitsu.com Thu Apr 7 09:41:26 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Thu, 7 Apr 2011 17:41:26 +0800 Subject: [libvirt] [PATCH 3/6] use virObject to manage reference-count of virDomainObj In-Reply-To: <4D9CEA54.6000402@redhat.com> References: <4D9CEA54.6000402@redhat.com> Message-ID: <20110407094126.GD7711@localhost.localdomain> On Wed, Apr 06, 2011 at 04:33:56PM -0600, Eric Blake wrote: > On 04/06/2011 01:19 AM, Hu Tao wrote: > > This patch also eliminates a dead-lock bug in > > qemuDomainObjBeginJobWithDriver: if virCondWaitUntil() timeouts, the > > thread tries to acquire qemu driver lock while holding virDomainObj > > lock. > > Let's please separate that bug fix into a separate patch which gets > applied as soon as possible. > > > --- > > src/conf/domain_conf.c | 56 ++++---- > > src/conf/domain_conf.h | 6 +- > > src/openvz/openvz_conf.c | 8 +- > > src/qemu/qemu_domain.c | 32 ++--- > > src/qemu/qemu_domain.h | 2 +- > > src/qemu/qemu_driver.c | 304 ++++++++++++++++++++------------------------- > > src/qemu/qemu_migration.c | 45 +++---- > > src/qemu/qemu_process.c | 33 ++--- > > src/vmware/vmware_conf.c | 2 +- > > 9 files changed, 215 insertions(+), 273 deletions(-) > > > int virDomainObjListInit(virDomainObjListPtr doms) > > @@ -437,7 +436,7 @@ virDomainObjPtr virDomainFindByID(const virDomainObjListPtr doms, > > virDomainObjPtr obj; > > obj = virHashSearch(doms->objs, virDomainObjListSearchID, &id); > > if (obj) > > - virDomainObjLock(obj); > > + virDomainObjRef(obj); > > Wow - changing the semantics so the object is not locked by default, > just referenced. > > > @@ -1010,6 +1007,11 @@ static virDomainObjPtr virDomainObjNew(virCapsPtr caps) > > return NULL; > > } > > > > + if (virObjectInit(&domain->obj, doDomainObjFree)) { > > + VIR_FREE(domain); > > + return NULL; > > Hmm. virObjectInit used VIR_ERROR, which logs, but doesn't call into > virtError. By returning NULL here, a user will get the dreaded "Unknown > error" message since we didn't hook into the virterror machinery. > Should virObjectInit instead be using virReportErrorHelper? Or is it How to use virReportErrorHelper in this case? > considered a coding bug to ever have virObjectInit fail in the first > place, so we don't really have to worry about that. Sorry for my bad English, I don't understand this sentence. > > > @@ -1075,8 +1075,10 @@ virDomainObjPtr virDomainAssignDef(virCapsPtr caps, > > domain->def = def; > > > > virUUIDFormat(def->uuid, uuidstr); > > + virDomainObjRef(domain); > > if (virHashAddEntry(doms->objs, uuidstr, domain) < 0) { > > It seems like incrementing ref count on container addition and > decrementing it on removal are common actions. Would it simplify code > any by making a wrapper for virHashAddEntry: > > int virHashAddObjEntry(virHashTablePtr, const void *name, virObjectPtr > *data) > > which does the referencing as part of adding/removing a virObject from a > hash table, rather than making all callers track it? Agreed. But this needs many changes I think it is better to do it in a seperate patch. > > The only potential drawback to that is that if you use the wrong > function, the referencing doesn't happen. Or maybe even make > virHashCreateFull take a bool parameter of whether the data must be a > virObjectPtr, so you don't have to wrap virHashAddObjEntry (and since > virHashRemoveEntry doesn't really have any way to create a > virHashRemoveObjEntry wrapper, but it would need to be in on the game of > automatic reference count manipulations any time we know the table > hashes only virObjects as data). Would it be better to have two types of hashtable, one hashes only virObjects, the other hashes data except virObjects? this can minimize the impact brought by the change of hashtable to existing code. > > > @@ -1149,9 +1151,7 @@ virDomainObjGetPersistentDef(virCapsPtr caps, > > } > > > > /* > > - * The caller must hold a lock on the driver owning 'doms', > > - * and must also have locked 'dom', to ensure no one else > > - * is either waiting for 'dom' or still usingn it > > + * The caller must hold a lock on the driver owning 'doms'. > > While touching that line, fix the spacing: > s/lock on/lock on/ OK. > > > @@ -1159,9 +1159,8 @@ void virDomainRemoveInactive(virDomainObjListPtr doms, > > char uuidstr[VIR_UUID_STRING_BUFLEN]; > > virUUIDFormat(dom->def->uuid, uuidstr); > > > > - virDomainObjUnlock(dom); > > - > > virHashRemoveEntry(doms->objs, uuidstr); > > + virDomainObjUnref(dom); > > Hmm, this means you are dereferencing dom->def->uuid while holding the > driver lock but without holding the domain lock. If there is another > place in code that holds the domain lock but not the driver lock, > couldn't that cause a bad read of dom->def? I don't think you can > blindly get rid of holding the lock on dom unless we make additional > rules about which members of dom are safe to modify (for example, > stating that dom->def cannot be modified unless you hold the driver > lock), but that's hard to audit. :( Don't understand you very well here. Let me explain what I understand: If a dom is added into a hashtable, then it is not safe to modify its uuid since it is the key of dom in hashtable. And we have to make some rules about when the uuid can be modified(say, hold the driver lock first when dom is in hashtable). If I understand correctly, then I think the simple way to modify the uuid is to remove the dom from hashtable, modify uuid, then reinsert it into hashtable. The qemu driver lock here is to protect the hashtable objs(remove entry), not for unref dom. However, I think this code should be better like this: qemu driver lock dom = virHashRemoveEntry(); /* not be exactly but a way to get the removed dom */ qemu driver unlock unref dom > > > > @@ -6146,7 +6145,7 @@ static virDomainObjPtr virDomainObjParseXML(virCapsPtr caps, > > > > error: > > /* obj was never shared, so unref should return 0 */ > > - ignore_value(virDomainObjUnref(obj)); > > + virDomainObjUnref(obj); > > Do we also want to delete the comment, since it only served to justify > why we were using ignore_value()? OK. > > > @@ -8449,10 +8448,12 @@ static virDomainObjPtr virDomainLoadConfig(virCapsPtr caps, > > if (!(dom = virDomainAssignDef(caps, doms, def, false))) > > goto error; > > > > + virDomainObjLock(dom); > > dom->autostart = autostart; > > > > if (notify) > > (*notify)(dom, newVM, opaque); > > + virDomainObjUnlock(dom); > > > > VIR_FREE(configFile); > > VIR_FREE(autostartLink); > > Ouch, this changes virDomainLoadConfig so that it returns an unlocked > domain, but virDomainLoadAllConfigs assumed that domain was still locked > and you now have a double-unlock. Will check this carefully. > > > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > > index c2a1f9a..3a3c953 100644 > > --- a/src/qemu/qemu_domain.c > > +++ b/src/qemu/qemu_domain.c > > @@ -457,13 +457,13 @@ int qemuDomainObjBeginJob(virDomainObjPtr obj) > > } > > then = timeval_to_ms(now) + QEMU_JOB_WAIT_TIME; > > > > - virDomainObjRef(obj); > > + virDomainObjLock(obj); > > This grabbed obj->privateData while obj was not locked. Is that safe, > or do you need to float the initialization of priv down? Yes, you are right. > > > > > while (priv->jobActive) { > > if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) { > > - /* Safe to ignore value since ref count was incremented above */ > > - ignore_value(virDomainObjUnref(obj)); > > - if (errno == ETIMEDOUT) > > + int err = errno; > > + virDomainObjUnlock(obj); > > + if (err == ETIMEDOUT) > > Good catch that pre-patch, errno was untouched by virDomainObjUnref, but > post-patch, you need to preserve errno before unlocking. > > > qemuReportError(VIR_ERR_OPERATION_TIMEOUT, > > "%s", _("cannot acquire state change lock")); > > else > > @@ -482,12 +482,10 @@ int qemuDomainObjBeginJob(virDomainObjPtr obj) > > } > > > > /* > > - * obj must be locked before calling, qemud_driver must be locked > > - * > > * This must be called by anything that will change the VM state > > * in any way, or anything that will use the QEMU monitor. > > */ > > -int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, > > +int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver ATTRIBUTE_UNUSED, > > If we no longer care if driver was locked or unlocked, can we do a > followup patch that simplifies all callers to just use > qemuDomainObjBeginJob and delete this variant? But I don't think you > can get away with it; see below... > > > virDomainObjPtr obj) > > { > > qemuDomainObjPrivatePtr priv = obj->privateData; > > @@ -501,20 +499,18 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, > > } > > then = timeval_to_ms(now) + QEMU_JOB_WAIT_TIME; > > > > - virDomainObjRef(obj); > > - qemuDriverUnlock(driver); > > ...don't think you can delete this line... > > > + virDomainObjLock(obj); > > Again, locking after you already grabbed priv. > > > > > while (priv->jobActive) { > > if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) { > > Ouch. You just broke the no sleeping while holding locks rule - > previously, virCondWaitUntil was called with no locks, now you are > calling it while holding both driver and domain lock. :( > > > - /* Safe to ignore value since ref count was incremented above */ > > - ignore_value(virDomainObjUnref(obj)); > > - if (errno == ETIMEDOUT) > > + int err = errno; > > + virDomainObjUnlock(obj); > > + if (err == ETIMEDOUT) > > qemuReportError(VIR_ERR_OPERATION_TIMEOUT, > > "%s", _("cannot acquire state change lock")); > > else > > virReportSystemError(errno, > > "%s", _("cannot acquire job mutex")); > > - qemuDriverLock(driver); > > Yep, this is the deadlock fix; pre-patch was definitely trying to regrab > the driver lock while still holding the domain lock. But given that you > _do_ have to regain driver lock (thanks to the blocking of > virCondWaitUntil), I'm afraid your fix will instead have to look like... > > > return -1; > > } > > } > > @@ -524,10 +520,6 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, > > priv->jobStart = timeval_to_ms(now); > > memset(&priv->jobInfo, 0, sizeof(priv->jobInfo)); > > > > - virDomainObjUnlock(obj); > > - qemuDriverLock(driver); > > - virDomainObjLock(obj); > > ...these lines, which also must remain (although possibly modified a > bit, if you are changing semantics to guarantee that you don't have to > have obj locked prior to calling this function). > > > +++ b/src/qemu/qemu_driver.c > > @@ -139,7 +139,6 @@ qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaq > > struct qemuAutostartData *data = opaque; > > virErrorPtr err; > > > > - virDomainObjLock(vm); > > virResetLastError(); > > if (qemuDomainObjBeginJobWithDriver(data->driver, vm) < 0) { > > err = virGetLastError(); > > @@ -156,12 +155,8 @@ qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaq > > err ? err->message : _("unknown error")); > > } > > > > - if (qemuDomainObjEndJob(vm) == 0) > > - vm = NULL; > > + qemuDomainObjEndJob(vm); > > } > > - > > - if (vm) > > - virDomainObjUnlock(vm); > > } > > Ah, so it qemuDomainObjBeginJobWithDriver is called while domain lock > not held on entry but exits with it held on success, and > qemuDomainObjEndJob is the counterpart that releases the domain lock. > Makes for some more compact code everywhere else. :) > > > @@ -1239,39 +1243,57 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, > > > > qemuDriverLock(driver); > > if (!(def = virDomainDefParseString(driver->caps, xml, > > - VIR_DOMAIN_XML_INACTIVE))) > > + VIR_DOMAIN_XML_INACTIVE))) { > > + qemuDriverUnlock(driver); > > goto cleanup; > > + } > > > > - if (virSecurityManagerVerify(driver->securityManager, def) < 0) > > + if (virSecurityManagerVerify(driver->securityManager, def) < 0) { > > + qemuDriverUnlock(driver); > > goto cleanup; > > + } > > > > - if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) > > + if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) { > > + qemuDriverUnlock(driver); > > goto cleanup; > > + } > > Why must every caller unlock the driver, instead of factoring it once > into the cleanup? I'd almost rather see a second label, as in: > > goto cleanup_locked; > > > cleanup_locked: > qemuDriverUnlock(driver); > goto cleanup; OK, makes code cleaner. > > > + } > > + > > + qemuDriverUnlock(driver); > > > > def = NULL; > > > > - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) > > + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) { > > With old semantics, you can't call qemuDomainObjBeginJobWithDriver if > driver is unlocked (then again, you just changed the body of that method > to not care if driver was locked, which matches with you just unlocking > it a couple lines ago). Then again, maybe we don't need > BeginJobWithDriver after all, if all of your conversions have changed > things to no longer hold the driver lock before beginning a job. > > > @@ -1307,13 +1325,14 @@ static int qemudDomainSuspend(virDomainPtr dom) { > > > > 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; > > + return -1; > > } > > if (!virDomainObjIsActive(vm)) { > > qemuReportError(VIR_ERR_OPERATION_INVALID, > > @@ -1354,16 +1373,12 @@ static int qemudDomainSuspend(virDomainPtr dom) { > > } > > > > endjob: > > - if (qemuDomainObjEndJob(vm) == 0) > > - vm = NULL; > > + qemuDomainObjEndJob(vm); > > Ouch - this change means you are accessing > virDomainSaveStatus(driver->caps, driver->stateDir, vm) without holding > the driver lock. Is that safe? (I don't know that caps or stateDir > ever change after creation, so maybe it is safe after all). Likewise Yes, not safe here. Since the semantics of qemuDomainObjBeginJobWithDriver is changed, and many places call it, I have to check every place and test the change. In next version I plan to split the series into patches like this: first a patch changes virDomainObj to inherit from virObject, second a patch changes qemuDomainObjBeginJobWithDriver, then each patch for a place that calls qemuDomainObjBeginJobWithDriver. Is this reasonable? Or a better way? > you call qemuProcessStopCPUs(driver, vm), which used to assume driver > was locked - is that safe? As you have already noticed, the semantics of qemuDomainObjBeginJobWithDriver and qemuEnterMonitorWithDriver(patch 4) are changed, qemu driver lock have not to be hold before calling them. So if this patch is applied, patch 4 should also be applied. > > I think a lot of this file will have the same questions, so I won't > review the rest of qemu_domain.c very closely on this round. > > > @@ -1090,8 +1087,8 @@ int qemuMigrationPerform(struct qemud_driver *driver, > > VIR_DOMAIN_EVENT_STOPPED_MIGRATED); > > if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) { > > virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm); > > - if (qemuDomainObjEndJob(vm) > 0) > > - virDomainRemoveInactive(&driver->domains, vm); > > + qemuDomainObjEndJob(vm); > > + virDomainRemoveInactive(&driver->domains, vm); > > vm = NULL; > > Wonky spacing. > > > @@ -644,7 +644,7 @@ qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm) > > > > /* Safe to ignore value since ref count was incremented above */ > > if (priv->mon == NULL) > > - ignore_value(virDomainObjUnref(vm)); > > + virDomainObjUnref(vm); > > Another case where the comment is out of date once you delete the > ignore_value(). Will remove it. > > > +++ b/src/vmware/vmware_conf.c > > @@ -205,7 +205,7 @@ cleanup: > > VIR_FREE(vmx); > > /* any non-NULL vm here has not been shared, so unref will return 0 */ > > if (vm) > > - ignore_value(virDomainObjUnref(vm)); > > + virDomainObjUnref(vm); > > And another stale comment. Will remove it. > > -- > Eric Blake eblake at redhat.com +1-801-349-2682 > Libvirt virtualization library http://libvirt.org > From jyang at redhat.com Thu Apr 7 10:04:19 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 07 Apr 2011 18:04:19 +0800 Subject: [libvirt] qemu: Add timeout for monitor to avoid virsh getting stuck when monitor gets die. In-Reply-To: <20110406085143.GF7195@orkuz.home> References: <4D9BE856.2090909@redhat.com> <20110406085143.GF7195@orkuz.home> Message-ID: <4D9D8C23.8080104@redhat.com> ? 2011?04?06? 16:51, Jiri Denemark ??: > On Wed, Apr 06, 2011 at 12:13:10 +0800, Mark Wu wrote: >> Hello Guys, >> >> When the qemu process becomes hung, virsh will get stuck on the hung >> guest and can't move forward. It can be reproduced by the following steps: >> >> 1. setup a virt guest with qemu-kvm, and start it >> 2. stop qemu process with following: >> kill -STOP `ps aux | grep qemu | grep -v grep | awk '{print $2}'` >> 3. run the following command: >> virsh list >> >> I think we can add a timeout for qemu monitor to resolve this problem: >> using virCondWaitUntil instead of virCondWait in qemuMonitorSend. What's >> your opinions? > > This is not the right approach. Introducing a timeout into all monitor command > send to qemu is a bad thing. I think the right approach is to have a simple > API which would just return domain's state without talking to its monitor or > doing other complicated stuff. The new API could then be used by virsh list to > list all domains even though they are blocked on qemu monitor. After all, > virsh is not really interested in current memory consumption of domains when > listing them. > IMHO this won't work, if you restart libvirtd after the monitor gets dead, you even can't get connection to libvirtd anymore, see: http://www.redhat.com/archives/libvir-list/2011-March/msg01422.html How to reproduce: 1. setup a virt guest with qemu-kvm, and start it 2. stop qemu process with following: # kill -STOP `ps aux | grep qemu | grep -v grep | awk '{print $2}'` 3. run the following command: 4. # service libvirtd restart 5. # virsh (hangs here) > The new API could also provide a reason which lead to current state so that > one can see the reason even without watching for libvirt events. > > Jirka > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list From jdenemar at redhat.com Thu Apr 7 10:17:17 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Thu, 7 Apr 2011 12:17:17 +0200 Subject: [libvirt] qemu: Add timeout for monitor to avoid virsh getting stuck when monitor gets die. In-Reply-To: <4D9D8C23.8080104@redhat.com> References: <4D9BE856.2090909@redhat.com> <20110406085143.GF7195@orkuz.home> <4D9D8C23.8080104@redhat.com> Message-ID: <20110407101717.GI7195@orkuz.home> On Thu, Apr 07, 2011 at 18:04:19 +0800, Osier Yang wrote: > ? 2011?04?06? 16:51, Jiri Denemark ??: > > This is not the right approach. Introducing a timeout into all monitor command > > send to qemu is a bad thing. I think the right approach is to have a simple > > API which would just return domain's state without talking to its monitor or > > doing other complicated stuff. The new API could then be used by virsh list to > > list all domains even though they are blocked on qemu monitor. After all, > > virsh is not really interested in current memory consumption of domains when > > listing them. > > > > IMHO this won't work, if you restart libvirtd after the monitor gets > dead, you even can't get connection to libvirtd anymore, see: > > http://www.redhat.com/archives/libvir-list/2011-March/msg01422.html > > How to reproduce: > 1. setup a virt guest with qemu-kvm, and start it > 2. stop qemu process with following: > # kill -STOP `ps aux | grep qemu | grep -v grep | awk '{print $2}'` > 3. run the following command: > 4. # service libvirtd restart > 5. # virsh (hangs here) Yes, but that's a separate issue, IMHO. virsh hangs at this point since libvirtd doesn't even get to the point when it is able to accept connections from client. So introducing a timeout to some specific operations to help solve this issue might be the right approach but doing all commands with timeout is certainly not what we should do. Daniel described all the issues very nicely in his detailed email. Jirka From jyang at redhat.com Thu Apr 7 10:39:27 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 07 Apr 2011 18:39:27 +0800 Subject: [libvirt] qemu: Add timeout for monitor to avoid virsh getting stuck when monitor gets die. In-Reply-To: <20110407101717.GI7195@orkuz.home> References: <4D9BE856.2090909@redhat.com> <20110406085143.GF7195@orkuz.home> <4D9D8C23.8080104@redhat.com> <20110407101717.GI7195@orkuz.home> Message-ID: <4D9D945F.80302@redhat.com> ? 2011?04?07? 18:17, Jiri Denemark ??: > On Thu, Apr 07, 2011 at 18:04:19 +0800, Osier Yang wrote: >> ? 2011?04?06? 16:51, Jiri Denemark ??: >>> This is not the right approach. Introducing a timeout into all monitor command >>> send to qemu is a bad thing. I think the right approach is to have a simple >>> API which would just return domain's state without talking to its monitor or >>> doing other complicated stuff. The new API could then be used by virsh list to >>> list all domains even though they are blocked on qemu monitor. After all, >>> virsh is not really interested in current memory consumption of domains when >>> listing them. >>> >> >> IMHO this won't work, if you restart libvirtd after the monitor gets >> dead, you even can't get connection to libvirtd anymore, see: >> >> http://www.redhat.com/archives/libvir-list/2011-March/msg01422.html >> >> How to reproduce: >> 1. setup a virt guest with qemu-kvm, and start it >> 2. stop qemu process with following: >> # kill -STOP `ps aux | grep qemu | grep -v grep | awk '{print $2}'` >> 3. run the following command: >> 4. # service libvirtd restart >> 5. # virsh (hangs here) > > Yes, but that's a separate issue, IMHO. virsh hangs at this point since > libvirtd doesn't even get to the point when it is able to accept connections > from client. So introducing a timeout to some specific operations to help > solve this issue might be the right approach but doing all commands with > timeout is certainly not what we should do. Daniel described all the issues > very nicely in his detailed email. Oh, I didn't mean your proposal won't work for "virsh list", that will work well I guess. :) I meant if we consider "virsh list can't work if the monitor dies" as a problem, then we need to solve the even more bad problem --- libvirtd can't accept connection anymore if it's restarted. Regards Osier From stefanb at linux.vnet.ibm.com Thu Apr 7 11:40:20 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Thu, 07 Apr 2011 07:40:20 -0400 Subject: [libvirt] [PATCH] [RFC] PPC Linux: Fix some problems Message-ID: <4D9DA2A4.9030205@linux.vnet.ibm.com> The following patch fixes some problems on powerpc Linux machines when trying to start an x86-based VM using qemu. In the order as the hunks appear the fix the following problems: - Qemu on (my) powerpc machine for some reason takes a long time for it to create its UnixIO socket. It's like 9 seconds or so and probably more once on a busy system. So increase the timeout for waiting for that socket to appear. - VM saved images written on an x86 host have a header in little endian format. So, when checking the 32 bit int for the header version and if the version is out-of-range swap the endianess of the header and try again and only then fail. This also then works when the big endian host has written the header in big endian format and now the VM is supposed to resume on a little endina host. - Setting the CPU affinity doesn't seem to work at all on (my) PPC host. So rather than failing the start of a VM when nodeGetInfo/virNodeGetInfo fail, make the setting of the CPU affinity pass on powerpc machines so the VM at least starts. Signed-off-by: Stefan Berger --- src/qemu/qemu_driver.c | 15 +++++++++++++++ src/qemu/qemu_monitor.c | 4 ++++ src/qemu/qemu_process.c | 10 +++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) Index: libvirt/src/qemu/qemu_monitor.c =================================================================== --- libvirt.orig/src/qemu/qemu_monitor.c +++ libvirt/src/qemu/qemu_monitor.c @@ -249,7 +249,11 @@ qemuMonitorOpenUnix(const char *monitor) { struct sockaddr_un addr; int monfd; +#if defined(__powerpc64__) || defined(__powerpc__) + int timeout = 30; /* In seconds */ +#else int timeout = 3; /* In seconds */ +#endif int ret, i = 0; if ((monfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "qemu_driver.h" @@ -1882,6 +1883,15 @@ struct qemud_save_header { int unused[15]; }; +static inline void +bswap_header(struct qemud_save_header *hdr) { + hdr->version = bswap_32(hdr->version); + hdr->xml_len = bswap_32(hdr->xml_len); + hdr->was_running = bswap_32(hdr->was_running); + hdr->compressed = bswap_32(hdr->compressed); +} + + /* return -errno on failure, or 0 on success */ static int qemuDomainSaveHeader(int fd, const char *path, char *xml, @@ -3091,6 +3101,11 @@ qemuDomainSaveImageOpen(struct qemud_dri } if (header.version > QEMUD_SAVE_VERSION) { + /* try to convert endianess */ + bswap_header(&header); + } + + if (header.version > QEMUD_SAVE_VERSION) { qemuReportError(VIR_ERR_OPERATION_FAILED, _("image version is not supported (%d > %d)"), header.version, QEMUD_SAVE_VERSION); Index: libvirt/src/qemu/qemu_process.c =================================================================== --- libvirt.orig/src/qemu/qemu_process.c +++ libvirt/src/qemu/qemu_process.c @@ -1239,7 +1239,11 @@ qemuProcessInitCpuAffinity(virDomainObjP VIR_DEBUG0("Setting CPU affinity"); if (nodeGetInfo(NULL, &nodeinfo) < 0) +#if defined (__powerpc64__) || defined (__powerpc__) + return 0; +#else return -1; +#endif /* setaffinity fails if you set bits for CPUs which * aren't present, so we have to limit ourselves */ @@ -1295,7 +1299,11 @@ qemuProcessSetVcpuAffinites(virConnectPt int vcpu, cpumaplen, hostcpus, maxcpu; if (virNodeGetInfo(conn, &nodeinfo) != 0) { - return -1; +#if defined (__powerpc64__) || defined (__powerpc__) + return 0; +#else + return -1; +#endif } if (!def->cputune.nvcpupin) From laine at laine.org Thu Apr 7 14:54:20 2011 From: laine at laine.org (Laine Stump) Date: Thu, 7 Apr 2011 10:54:20 -0400 Subject: [libvirt] [PATCH] docs: add an IPv6 address to network XML examples Message-ID: <1302188060-16317-1-git-send-email-laine@laine.org> It was just pointed out that, although I added documentation for the IPv6 additions to the network XML, I neglected to use those additions in the xamples. This patch adds an IPv6 address to each of the examples except for the "default" network, since that is a faithful reproduction of the default network config that's automatically installed, which doesn't include any IPv6 address (for good reason - because there is no such thing as IPv6 NAT, there is no one IPv6 address that would work for all installations). --- docs/formatnetwork.html.in | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in index c6969eb..589aaff 100644 --- a/docs/formatnetwork.html.in +++ b/docs/formatnetwork.html.in @@ -121,6 +121,7 @@ <host mac="00:16:3e:3e:a9:1a" name="bar.example.com" ip="192.168.122.11" /> </dhcp> </ip> + <ip family="ipv6" address="2001:8794:ca2:2::1" prefix="64" /> </network>
    @@ -226,6 +227,7 @@ <range start="192.168.122.2" end="192.168.122.254" /> </dhcp> </ip> + <ip family="ipv6" address="2001:8794:ca2:2::1" prefix="64" /> </network>

    Routed network config

    @@ -249,6 +251,7 @@ <range start="192.168.122.2" end="192.168.122.254" /> </dhcp> </ip> + <ip family="ipv6" address="2001:8794:ca2:2::1" prefix="64" /> </network>

    Isolated network config

    @@ -270,6 +273,7 @@ <range start="192.168.152.2" end="192.168.152.254" /> </dhcp> </ip> + <ip family="ipv6" address="2001:8794:ca2:3::1" prefix="64" /> </network> -- 1.7.3.4 From eblake at redhat.com Thu Apr 7 14:56:43 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 08:56:43 -0600 Subject: [libvirt] [PATCH v5] qemu: Remove the managed state file only if restoring succeeded In-Reply-To: <1302143512-23422-1-git-send-email-jyang@redhat.com> References: <1302143512-23422-1-git-send-email-jyang@redhat.com> Message-ID: <4D9DD0AB.8030202@redhat.com> On 04/06/2011 08:31 PM, Osier Yang wrote: > managed_save = qemuDomainManagedSavePath(driver, vm); > + > + if (!managed_save) > + goto cleanup; > + > if ((managed_save) && (virFileExists(managed_save))) { This second check for non-NULL managed_save is now redundant. > +++ b/tools/virsh.pod > @@ -546,7 +546,11 @@ I parameter in the domain's XML definition. > > =item B I > > -Restores a domain from an B state file. See I for more info. > +Restores a domain from an B state file. See I for more info. Sorry for not noticing sooner, but we could do some grammar cleanups. Does this look like a reasonable followup? diff --git i/src/qemu/qemu_driver.c w/src/qemu/qemu_driver.c index a84780b..0734a76 100644 --- i/src/qemu/qemu_driver.c +++ w/src/qemu/qemu_driver.c @@ -3430,7 +3430,7 @@ static int qemudDomainObjStart(virConnectPtr conn, if (!managed_save) goto cleanup; - if ((managed_save) && (virFileExists(managed_save))) { + if (virFileExists(managed_save)) { ret = qemuDomainObjRestore(conn, driver, vm, managed_save); if ((ret == 0) && (unlink(managed_save) < 0)) diff --git i/tools/virsh.pod w/tools/virsh.pod index 6319373..9ce6905 100644 --- i/tools/virsh.pod +++ w/tools/virsh.pod @@ -546,11 +546,12 @@ I parameter in the domain's XML definition. =item B I -Restores a domain from an B state file. See I for more info. +Restores a domain from a B state file. See I for more info. B: To avoid corrupting file system contents within the domain, you -should not reuse the saved state file to B unless you are convinced -with reverting the domain to the previous state. +should not reuse the saved state file for a second B unless +you have also reverted all storage volumes back to the same contents +as when the state file was created. =item B I I -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From laine at laine.org Thu Apr 7 15:02:48 2011 From: laine at laine.org (Laine Stump) Date: Thu, 07 Apr 2011 11:02:48 -0400 Subject: [libvirt] [PATCH] virsh: fix mingw startup In-Reply-To: <1302119254-20506-1-git-send-email-eblake@redhat.com> References: <4D9BA555.1010302@redhat.com> <1302119254-20506-1-git-send-email-eblake@redhat.com> Message-ID: <4D9DD218.6000302@laine.org> On 04/06/2011 03:47 PM, Eric Blake wrote: > * .gnulib: Update to latest, for pipe2. > * bootstrap.conf (gnulib_modules): Add pipe2. > * src/util/event_poll.c (virEventPollInit): Use it, to avoid > problematic virSetCloseExec on mingw. > --- > > The gnulib changes to pipe2 are now in. > > * .gnulib f796520...2255b86 (4): > > verify: use _Static_assert if available > > Remove leftover generated .h files after config.status changed. > > Ensure to rebuild generated .h files when config.status has changed. > > pipe2: Relicense under LGPLv2+. > > This assumes that my earlier .gnulib modification patch is also in: > https://www.redhat.com/archives/libvir-list/2011-April/msg00297.html > although I can rebase as needed. > > .gnulib | 2 +- > bootstrap.conf | 3 ++- > src/util/event_poll.c | 7 ++----- > 3 files changed, 5 insertions(+), 7 deletions(-) ACK. From laine at laine.org Thu Apr 7 15:24:04 2011 From: laine at laine.org (Laine Stump) Date: Thu, 07 Apr 2011 11:24:04 -0400 Subject: [libvirt] patch review tool for libvirt patches? Message-ID: <4D9DD714.8060105@laine.org> Now that 0.9.0 is out, I'd like to ask everyone's opinions about patch review tools. I've been noticing lately that the volume of libvirt patches has increased significantly, and it's getting more and more difficult for me to keep up with reading the traffic, much less doing my part to review the patches. It would be very helpful if I could just see a view of pending patches, each properly colorcoded (or, even better, hidden) based on a patch being ACKed, deprecated, someone else in process of reviewing, etc. I know there are a few tools available, but I've never used any of them and wonder if anyone else has, and if they might be able to make a recommendation on something the libvirt project could use (or maybe something I could just use myself by sending a list feed into an application). I'm sending this message 1) to see if others are feeling the pressure of the extra traffic too (or is my brain just processing more slowly :-/), and 2) to learn what your opinions are of setting up such a system for libvirt (for *optional* use only), and any opinions you have on what's available (or maybe you could provide a recipe for how you already manage all the patches without going crazy). Here's my list of requirements; feel free to add/shoot down: 1) usage must be optional, so it must be able to update itself via monitoring messages on the list (a minimal amount of change/addition to the current message flow might be acceptable, but nothing major, and encountering PATCH/review/ACK messages as currently sent shouldn't make it blow up). 2) keep track of patches that are posted, NACKed, ACKed, re-posted (deprecating the original), and pushed (this should be done by monitoring git, not by looking at emails, as I've noticed patches are often pushed without a corresponding message to the list). 3) would also be nice if there was a place in the UI that those wanting to could "take" a patch for review so that two people didn't spend a lot of time on something not requiring that much attention, at the expense of other ignored patches. 4) maintain patchsets according to the "n/n" notation in the header (I mention this because one comment I saw about Gerrit said that it didn't do this). 5) provide some sort of interface for viewing the patch, annotating it with comments, and sending that back to the list as an ACK/NACK or simply a comment. 6) provide a simple way to save a patchset to files that can be "git am"ed (or maybe even do it for you, automatically creating a branch first, etc. This could possibly even be extended into a command to push a given patchset) 7) (of course it must be open source. Do I even need to say that? :-)) Ideally, a person wanting to use this system should be able to setup their email to filter all libvir-list traffic containing "PATCH" in the subject line, then create an account on the patch review system and handle all patch review via the tool's interface Here's a list of tool that Rich Jones came up with in another discussion on the same topic, along with a few others that were mentioned in the ensuing discussion. To the right, I've included comments from others that seemed interesting to me. Please point out any that you disagree with! Gerrit (https://code.google.com/p/gerrit) "The assumption that one issue == one patch is too deeply embedded" Kiln (http://www.fogcreek.com/kiln/) (proprietary, so probably shouldn't be considered) Patchwork (http://ozlabs.org/~jk/projects/patchwork/) (used by Linux kernel& kvm maintainers) http://www.reviewboard.org/ "didn't work well with git" Also someone pointed out that gitorious has code review aids: http://blog.gitorious.org/2009/11/06/awesome-code-review/ If I were going to investigate one of these and try setting it up, which do you think would have the greatest likelyhood of success (if any)? From eblake at redhat.com Thu Apr 7 15:41:04 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 09:41:04 -0600 Subject: [libvirt] [PATCH] docs: add an IPv6 address to network XML examples In-Reply-To: <1302188060-16317-1-git-send-email-laine@laine.org> References: <1302188060-16317-1-git-send-email-laine@laine.org> Message-ID: <4D9DDB10.1050707@redhat.com> On 04/07/2011 08:54 AM, Laine Stump wrote: > It was just pointed out that, although I added documentation for the > IPv6 additions to the network XML, I neglected to use those additions > in the xamples. This patch adds an IPv6 address to each of the s/xamples/examples/ > examples except for the "default" network, since that is a faithful > reproduction of the default network config that's automatically > installed, which doesn't include any IPv6 address (for good reason - > because there is no such thing as IPv6 NAT, there is no one IPv6 > address that would work for all installations). > --- > docs/formatnetwork.html.in | 4 ++++ > 1 files changed, 4 insertions(+), 0 deletions(-) ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jfehlig at novell.com Thu Apr 7 16:25:09 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Thu, 07 Apr 2011 10:25:09 -0600 Subject: [libvirt] [PATCH 2/4] Add domainSet/GetSchedulerParameters to libxl driver In-Reply-To: <9b00bcc6fc662af824e42854a3db06f79ee7b85c.1302079994.git.gross@univention.de> References: <9b00bcc6fc662af824e42854a3db06f79ee7b85c.1302079994.git.gross@univention.de> Message-ID: <4D9DE565.4040309@novell.com> Markus Gro? wrote: > Libxenlight currently only supports the credit scheduler. > Therefore setting or getting a parameter of other > schedulers raise an error (for now). > --- > src/libxl/libxl_driver.c | 166 +++++++++++++++++++++++++++++++++++++++++++++- > 1 files changed, 164 insertions(+), 2 deletions(-) > > diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c > index e95c403..c760a23 100644 > --- a/src/libxl/libxl_driver.c > +++ b/src/libxl/libxl_driver.c > @@ -2286,6 +2286,168 @@ cleanup: > } > > static int > +libxlDomainGetSchedulerParameters(virDomainPtr dom, virSchedParameterPtr params, > + int * nparams) > In most libvirt code that would be 'int *nparams'. > +{ > + libxlDriverPrivatePtr driver = dom->conn->privateData; > + libxlDomainObjPrivatePtr priv; > + virDomainObjPtr vm; > + libxl_sched_credit sc_info; > + int sched_id; > + int ret = -1; > + > + libxlDriverLock(driver); > + vm = virDomainFindByUUID(&driver->domains, dom->uuid); > + libxlDriverUnlock(driver); > + > + if (!vm) { > + libxlError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); > + goto cleanup; > + } > + > + if (!virDomainObjIsActive(vm)) { > + libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); > + goto cleanup; > + } > Is this API restricted to active domains only? I suppose schedule parameters are classified as runtime tunables, and not defined in persistent config. > + > + priv = vm->privateData; > + > + if ((sched_id = libxl_get_sched_id(&priv->ctx)) < 0) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to get scheduler id for domain '%d'" > + " with libxenlight"), dom->id); > + goto cleanup; > + } > + > + if (sched_id != XEN_SCHEDULER_CREDIT) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("Only 'credit' scheduler is supported")); > + goto cleanup; > + } > + > + if (*nparams != XEN_SCHED_CREDIT_NPARAM) { > + libxlError(VIR_ERR_INVALID_ARG, "%s", _("Invalid parameter count")); > + goto cleanup; > + } > + > + if (libxl_sched_credit_domain_get(&priv->ctx, dom->id, &sc_info) != 0) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to get scheduler parameters for domain '%d'" > + " with libxenlight"), dom->id); > + goto cleanup; > + } > + > + params[0].value.ui = sc_info.weight; > + params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT; > The libxl_sched_credit fields are int, but treated as unsigned internally. Using UINT plays nicely with "legacy" weight and cap handling in virsh and is the correct type to use here IMO. ACK. I fixed the whitespace issue noted above and pushed. Thanks Markus. Regards, Jim > + if (virStrcpyStatic(params[0].field, "weight") == NULL) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + "%s", _("Field weight too long for destination")); > + goto cleanup; > + } > + > + params[1].value.ui = sc_info.cap; > + params[1].type = VIR_DOMAIN_SCHED_FIELD_UINT; > + if (virStrcpyStatic(params[1].field, "cap") == NULL) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + "%s", _("Field cap too long for destination")); > + goto cleanup; > + } > + > + ret = 0; > + > +cleanup: > + if (vm) > + virDomainObjUnlock(vm); > + return ret; > +} > + > +static int > +libxlDomainSetSchedulerParameters(virDomainPtr dom, virSchedParameterPtr params, > + int nparams) > +{ > + libxlDriverPrivatePtr driver = dom->conn->privateData; > + libxlDomainObjPrivatePtr priv; > + virDomainObjPtr vm; > + libxl_sched_credit sc_info; > + int sched_id; > + int i; > + int ret = -1; > + > + libxlDriverLock(driver); > + vm = virDomainFindByUUID(&driver->domains, dom->uuid); > + libxlDriverUnlock(driver); > + > + if (!vm) { > + libxlError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); > + goto cleanup; > + } > + > + if (!virDomainObjIsActive(vm)) { > + libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); > + goto cleanup; > + } > + > + priv = vm->privateData; > + > + if ((sched_id = libxl_get_sched_id(&priv->ctx)) < 0) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to get scheduler id for domain '%d'" > + " with libxenlight"), dom->id); > + goto cleanup; > + } > + > + if (sched_id != XEN_SCHEDULER_CREDIT) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("Only 'credit' scheduler is supported")); > + goto cleanup; > + } > + > + if (nparams != XEN_SCHED_CREDIT_NPARAM) { > + libxlError(VIR_ERR_INVALID_ARG, "%s", _("Invalid parameter count")); > + goto cleanup; > + } > + > + for (i = 0; i < nparams; ++i) { > + virSchedParameterPtr param = ¶ms[i]; > + > + if (STREQ(param->field, "weight")) { > + if (param->type != VIR_DOMAIN_SCHED_FIELD_UINT) { > + libxlError(VIR_ERR_INVALID_ARG, "%s", > + _("invalid type for weight tunable, expected a 'uint'")); > + goto cleanup; > + } > + sc_info.weight = params[i].value.ui; > + > + } else if (STREQ(param->field, "cap")) { > + if (param->type != VIR_DOMAIN_SCHED_FIELD_UINT) { > + libxlError(VIR_ERR_INVALID_ARG, "%s", > + _("invalid type for cap tunable, expected a 'uint'")); > + goto cleanup; > + } > + sc_info.cap = params[i].value.ui; > + } else { > + libxlError(VIR_ERR_INVALID_ARG, > + _("Invalid parameter '%s'"), param->field); > + goto cleanup; > + } > + } > + > + if (libxl_sched_credit_domain_set(&priv->ctx, dom->id, &sc_info) != 0) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to set scheduler parameters for domain '%d'" > + " with libxenlight"), dom->id); > + goto cleanup; > + } > + > + ret = 0; > + > +cleanup: > + if (vm) > + virDomainObjUnlock(vm); > + return ret; > +} > + > +static int > libxlDomainIsActive(virDomainPtr dom) > { > libxlDriverPrivatePtr driver = dom->conn->privateData; > @@ -2453,8 +2615,8 @@ static virDriver libxlDriver = { > libxlDomainGetAutostart, /* domainGetAutostart */ > libxlDomainSetAutostart, /* domainSetAutostart */ > libxlDomainGetSchedulerType,/* domainGetSchedulerType */ > - NULL, /* domainGetSchedulerParameters */ > - NULL, /* domainSetSchedulerParameters */ > + libxlDomainGetSchedulerParameters,/* domainGetSchedulerParameters */ > + libxlDomainSetSchedulerParameters,/* domainSetSchedulerParameters */ > NULL, /* domainMigratePrepare */ > NULL, /* domainMigratePerform */ > NULL, /* domainMigrateFinish */ > From jfehlig at novell.com Thu Apr 7 16:41:34 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Thu, 07 Apr 2011 10:41:34 -0600 Subject: [libvirt] [PATCH 1/6] Enhance the streams helper to support plain file I/O In-Reply-To: <4D9D7900.5060304@cn.fujitsu.com> References: <1300901798-5017-1-git-send-email-berrange@redhat.com> <1300901798-5017-2-git-send-email-berrange@redhat.com> <4D9D7900.5060304@cn.fujitsu.com> Message-ID: <4D9DE93E.5070700@novell.com> Wen Congyang wrote: > At 03/24/2011 01:36 AM, Daniel P. Berrange Write: > >> The O_NONBLOCK flag doesn't work as desired on plain files >> or block devices. Introduce an I/O helper program that does >> the blocking I/O operations, communicating over a pipe that >> can support O_NONBLOCK >> >> * src/fdstream.c, src/fdstream.h: Add non-blocking I/O >> on plain files/block devices >> * src/Makefile.am, src/util/iohelper.c: I/O helper program >> * src/qemu/qemu_driver.c, src/lxc/lxc_driver.c, >> src/uml/uml_driver.c, src/xen/xen_driver.c: Update for >> streams API change >> --- >> po/POTFILES.in | 1 + >> src/Makefile.am | 12 +++ >> src/fdstream.c | 233 ++++++++++++++++++++++++++++++++++++------------ >> src/fdstream.h | 5 + >> src/lxc/lxc_driver.c | 2 +- >> src/qemu/qemu_driver.c | 2 +- >> src/uml/uml_driver.c | 2 +- >> src/util/iohelper.c | 203 +++++++++++++++++++++++++++++++++++++++++ >> src/xen/xen_driver.c | 2 +- >> 9 files changed, 402 insertions(+), 60 deletions(-) >> create mode 100644 src/util/iohelper.c >> >> diff --git a/po/POTFILES.in b/po/POTFILES.in >> index 805e5ca..12adb3e 100644 >> --- a/po/POTFILES.in >> +++ b/po/POTFILES.in >> @@ -94,6 +94,7 @@ src/util/event_poll.c >> src/util/hash.c >> src/util/hooks.c >> src/util/hostusb.c >> +src/util/iohelper.c >> src/util/interface.c >> src/util/iptables.c >> src/util/json.c >> diff --git a/src/Makefile.am b/src/Makefile.am >> index c3729a6..1d8115b 100644 >> --- a/src/Makefile.am >> +++ b/src/Makefile.am >> @@ -380,6 +380,9 @@ STORAGE_DRIVER_DISK_SOURCES = \ >> STORAGE_HELPER_DISK_SOURCES = \ >> storage/parthelper.c >> >> +UTIL_IO_HELPER_SOURCES = \ >> + util/iohelper.c >> + >> # Network filters >> NWFILTER_DRIVER_SOURCES = \ >> nwfilter/nwfilter_driver.h nwfilter/nwfilter_driver.c \ >> @@ -1203,6 +1206,15 @@ EXTRA_DIST += $(LIBVIRT_QEMU_SYMBOL_FILE) >> >> libexec_PROGRAMS = >> >> +libexec_PROGRAMS += libvirt_iohelper >> +libvirt_iohelper_SOURCES = $(UTIL_IO_HELPER_SOURCES) >> +libvirt_iohelper_LDFLAGS = $(WARN_LDFLAGS) $(AM_LDFLAGS) >> +libvirt_iohelper_LDADD = \ >> + libvirt_util.la \ >> + ../gnulib/lib/libgnu.la >> + >> +libvirt_iohelper_CFLAGS = $(AM_CFLAGS) >> + >> > > Is libvirt_iohelper for libvirtd? > > libvirt_iohelper is provided by libvirt-.rpm, but we still install it > when we build withoud libvirtd. We will meet the following problems: > > Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/wency/rpmbuild/BUILDROOT/libvirt-0.9.0-1.el6.x86_64 > error: Installed (but unpackaged) file(s) found: > /usr/libexec/libvirt_iohelper > I met the same problem and added libvirt-iohelper to our client package. Is it used in client-only configuration? Regards, Jim From laine at laine.org Thu Apr 7 17:03:41 2011 From: laine at laine.org (Laine Stump) Date: Thu, 07 Apr 2011 13:03:41 -0400 Subject: [libvirt] [PATCH] docs: add an IPv6 address to network XML examples In-Reply-To: <4D9DDB10.1050707@redhat.com> References: <1302188060-16317-1-git-send-email-laine@laine.org> <4D9DDB10.1050707@redhat.com> Message-ID: <4D9DEE6D.9080208@laine.org> On 04/07/2011 11:41 AM, Eric Blake wrote: > On 04/07/2011 08:54 AM, Laine Stump wrote: >> It was just pointed out that, although I added documentation for the >> IPv6 additions to the network XML, I neglected to use those additions >> in the xamples. This patch adds an IPv6 address to each of the > s/xamples/examples/ > >> examples except for the "default" network, since that is a faithful >> reproduction of the default network config that's automatically >> installed, which doesn't include any IPv6 address (for good reason - >> because there is no such thing as IPv6 NAT, there is no one IPv6 >> address that would work for all installations). >> --- >> docs/formatnetwork.html.in | 4 ++++ >> 1 files changed, 4 insertions(+), 0 deletions(-) > ACK. Thanks. Fixed and pushed. From berrange at redhat.com Thu Apr 7 18:21:26 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 7 Apr 2011 19:21:26 +0100 Subject: [libvirt] patch review tool for libvirt patches? In-Reply-To: <4D9DD714.8060105@laine.org> References: <4D9DD714.8060105@laine.org> Message-ID: <20110407182126.GA2719@redhat.com> On Thu, Apr 07, 2011 at 11:24:04AM -0400, Laine Stump wrote: > Now that 0.9.0 is out, I'd like to ask everyone's opinions about > patch review tools. > > I've been noticing lately that the volume of libvirt patches has > increased significantly, and it's getting more and more difficult > for me to keep up with reading the traffic, much less doing my part > to review the patches. It would be very helpful if I could just see > a view of pending patches, each properly colorcoded (or, even > better, hidden) based on a patch being ACKed, deprecated, someone > else in process of reviewing, etc. I know there are a few tools > available, but I've never used any of them and wonder if anyone else > has, and if they might be able to make a recommendation on something > the libvirt project could use (or maybe something I could just use > myself by sending a list feed into an application). > > I'm sending this message 1) to see if others are feeling the > pressure of the extra traffic too (or is my brain just processing > more slowly :-/), and 2) to learn what your opinions are of setting > up such a system for libvirt (for *optional* use only), and any > opinions you have on what's available (or maybe you could provide a > recipe for how you already manage all the patches without going > crazy). > > Here's my list of requirements; feel free to add/shoot down: > > 1) usage must be optional, so it must be able to update itself via > monitoring messages on the list (a minimal amount of change/addition > to the current message flow might be acceptable, but nothing major, > and encountering PATCH/review/ACK messages as currently sent > shouldn't make it blow up). > > 2) keep track of patches that are posted, NACKed, ACKed, re-posted > (deprecating the original), and pushed (this should be done by > monitoring git, not by looking at emails, as I've noticed patches > are often pushed without a corresponding message to the list). > > 3) would also be nice if there was a place in the UI that those > wanting to could "take" a patch for review so that two people didn't > spend a lot of time on something not requiring that much attention, > at the expense of other ignored patches. > > 4) maintain patchsets according to the "n/n" notation in the header > (I mention this because one comment I saw about Gerrit said that it > didn't do this). > > 5) provide some sort of interface for viewing the patch, annotating > it with comments, and sending that back to the list as an ACK/NACK > or simply a comment. > > 6) provide a simple way to save a patchset to files that can be "git > am"ed (or maybe even do it for you, automatically creating a branch > first, etc. This could possibly even be extended into a command to > push a given patchset) > > 7) (of course it must be open source. Do I even need to say that? :-)) > > Ideally, a person wanting to use this system should be able to setup > their email to filter all libvir-list traffic containing "PATCH" in > the subject line, then create an account on the patch review system > and handle all patch review via the tool's interface > > Here's a list of tool that Rich Jones came up with in another > discussion on the same topic, along with a few others that were > mentioned in the ensuing discussion. To the right, I've included > comments from others that seemed interesting to me. Please point out > any that you disagree with! > > Gerrit (https://code.google.com/p/gerrit) "The assumption that one issue == one patch is too deeply embedded" > > Kiln (http://www.fogcreek.com/kiln/) (proprietary, so probably shouldn't be considered) > > Patchwork (http://ozlabs.org/~jk/projects/patchwork/) (used by Linux kernel& kvm maintainers) > > > http://www.reviewboard.org/ "didn't work well with git" > > > Also someone pointed out that gitorious has code review aids: > > http://blog.gitorious.org/2009/11/06/awesome-code-review/ > > > If I were going to investigate one of these and try setting it up, > which do you think would have the greatest likelyhood of success > (if any)? For me, any tool which requires visiting a web UI to submit or view patch code review comments/feedback is a non-starter. All code review feedback must be on the mailing list, and correctly threaded. In other words, it would be a tool which serves a 'reporting' or 'tracking' patch series, not a code review management system. AFAICT, patchwork is the only one expressly designed in this manner. Their website sums it up nicely: "patchwork should supplement mailing lists, not replace them Patchwork isn't intended to replace a community mailing list; that's why you can't comment on a patch in patchwork. If this were the case, then there would be two forums of discussion on patches, which fragments the patch review process. Developers who don't use patchwork would get left out of the discussion." To also add to that, public mailing lists are a very good archival system for code review / discussions. Once in a mailing list, you can be pretty sure it'll never disappear from the web & is always searchable from google. The same can't be said of most web apps. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Thu Apr 7 18:29:29 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 7 Apr 2011 19:29:29 +0100 Subject: [libvirt] [PATCH 1/6] Enhance the streams helper to support plain file I/O In-Reply-To: <4D9DE93E.5070700@novell.com> References: <1300901798-5017-1-git-send-email-berrange@redhat.com> <1300901798-5017-2-git-send-email-berrange@redhat.com> <4D9D7900.5060304@cn.fujitsu.com> <4D9DE93E.5070700@novell.com> Message-ID: <20110407182929.GB2719@redhat.com> On Thu, Apr 07, 2011 at 10:41:34AM -0600, Jim Fehlig wrote: > Wen Congyang wrote: > > At 03/24/2011 01:36 AM, Daniel P. Berrange Write: > > > >> The O_NONBLOCK flag doesn't work as desired on plain files > >> or block devices. Introduce an I/O helper program that does > >> the blocking I/O operations, communicating over a pipe that > >> can support O_NONBLOCK > >> > >> * src/fdstream.c, src/fdstream.h: Add non-blocking I/O > >> on plain files/block devices > >> * src/Makefile.am, src/util/iohelper.c: I/O helper program > >> * src/qemu/qemu_driver.c, src/lxc/lxc_driver.c, > >> src/uml/uml_driver.c, src/xen/xen_driver.c: Update for > >> streams API change > >> --- > >> po/POTFILES.in | 1 + > >> src/Makefile.am | 12 +++ > >> src/fdstream.c | 233 ++++++++++++++++++++++++++++++++++++------------ > >> src/fdstream.h | 5 + > >> src/lxc/lxc_driver.c | 2 +- > >> src/qemu/qemu_driver.c | 2 +- > >> src/uml/uml_driver.c | 2 +- > >> src/util/iohelper.c | 203 +++++++++++++++++++++++++++++++++++++++++ > >> src/xen/xen_driver.c | 2 +- > >> 9 files changed, 402 insertions(+), 60 deletions(-) > >> create mode 100644 src/util/iohelper.c > >> > >> diff --git a/po/POTFILES.in b/po/POTFILES.in > >> index 805e5ca..12adb3e 100644 > >> --- a/po/POTFILES.in > >> +++ b/po/POTFILES.in > >> @@ -94,6 +94,7 @@ src/util/event_poll.c > >> src/util/hash.c > >> src/util/hooks.c > >> src/util/hostusb.c > >> +src/util/iohelper.c > >> src/util/interface.c > >> src/util/iptables.c > >> src/util/json.c > >> diff --git a/src/Makefile.am b/src/Makefile.am > >> index c3729a6..1d8115b 100644 > >> --- a/src/Makefile.am > >> +++ b/src/Makefile.am > >> @@ -380,6 +380,9 @@ STORAGE_DRIVER_DISK_SOURCES = \ > >> STORAGE_HELPER_DISK_SOURCES = \ > >> storage/parthelper.c > >> > >> +UTIL_IO_HELPER_SOURCES = \ > >> + util/iohelper.c > >> + > >> # Network filters > >> NWFILTER_DRIVER_SOURCES = \ > >> nwfilter/nwfilter_driver.h nwfilter/nwfilter_driver.c \ > >> @@ -1203,6 +1206,15 @@ EXTRA_DIST += $(LIBVIRT_QEMU_SYMBOL_FILE) > >> > >> libexec_PROGRAMS = > >> > >> +libexec_PROGRAMS += libvirt_iohelper > >> +libvirt_iohelper_SOURCES = $(UTIL_IO_HELPER_SOURCES) > >> +libvirt_iohelper_LDFLAGS = $(WARN_LDFLAGS) $(AM_LDFLAGS) > >> +libvirt_iohelper_LDADD = \ > >> + libvirt_util.la \ > >> + ../gnulib/lib/libgnu.la > >> + > >> +libvirt_iohelper_CFLAGS = $(AM_CFLAGS) > >> + > >> > > > > Is libvirt_iohelper for libvirtd? > > > > libvirt_iohelper is provided by libvirt-.rpm, but we still install it > > when we build withoud libvirtd. We will meet the following problems: > > > > Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/wency/rpmbuild/BUILDROOT/libvirt-0.9.0-1.el6.x86_64 > > error: Installed (but unpackaged) file(s) found: > > /usr/libexec/libvirt_iohelper > > > > I met the same problem and added libvirt-iohelper to our client > package. Is it used in client-only configuration? It is only currently used in the QEMU or storage drivers, which are both daemon based. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From jfehlig at novell.com Thu Apr 7 18:31:51 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Thu, 07 Apr 2011 12:31:51 -0600 Subject: [libvirt] [PATCH 3/4] Add cputune support to libxl driver In-Reply-To: References: Message-ID: <4D9E0317.5000506@novell.com> Markus Gro? wrote: > The nodeGetInfo code had to be moved into a helper > function to reuse it without a virConnectPtr. > Sounds good. > --- > src/libxl/libxl_driver.c | 143 ++++++++++++++++++++++++++++++++++------------ > 1 files changed, 107 insertions(+), 36 deletions(-) > > diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c > index c760a23..1539385 100644 > --- a/src/libxl/libxl_driver.c > +++ b/src/libxl/libxl_driver.c > @@ -199,6 +199,46 @@ libxlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, > virDomainObjUnlock(vm); > } > > +static int > +libxlDoNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info) > +{ > + libxl_physinfo phy_info; > + const libxl_version_info* ver_info; > + struct utsname utsname; > + > + if (libxl_get_physinfo(&driver->ctx, &phy_info)) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("libxl_get_physinfo_info failed")); > + return -1; > + } > + > + if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("libxl_get_version_info failed")); > + return -1; > + } > + > + uname(&utsname); > + if (virStrncpy(info->model, > + utsname.machine, > + strlen(utsname.machine), > + sizeof(info->model)) == NULL) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("machine type %s too big for destination"), > + utsname.machine); > + return -1; > + } > + > + info->memory = phy_info.total_pages * (ver_info->pagesize / 1024); > + info->cpus = phy_info.nr_cpus; > + info->nodes = phy_info.nr_nodes; > + info->cores = phy_info.cores_per_socket; > + info->threads = phy_info.threads_per_core; > + info->sockets = 1; > + info->mhz = phy_info.cpu_khz / 1000; > + return 0; > +} > + > /* > * Cleanup function for domain that has reached shutoff state. > * > @@ -391,6 +431,62 @@ error: > return -1; > } > > +static int > +libxlDomainSetVcpuAffinites(libxlDriverPrivatePtr driver, virDomainObjPtr vm) > +{ > + libxlDomainObjPrivatePtr priv = vm->privateData; > + virDomainDefPtr def = vm->def; > + libxl_cpumap map; > + uint8_t *cpumask = NULL; > + uint8_t *cpumap = NULL; > + virNodeInfo nodeinfo; > + size_t cpumaplen; > + unsigned int pos; > + int vcpu, i; > + int ret = -1; > + > + if (libxlDoNodeGetInfo(driver, &nodeinfo) < 0) > + goto cleanup; > + > + cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo)); > + > + for (vcpu = 0; vcpu < def->cputune.nvcpupin; ++vcpu) { > + if (vcpu != def->cputune.vcpupin[vcpu]->vcpuid) > + continue; > + > + if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) { > + virReportOOMError(); > + goto cleanup; > + } > + > + cpumask = (uint8_t*) def->cputune.vcpupin[vcpu]->cpumask; > + > + for (i = 0; i < VIR_DOMAIN_CPUMASK_LEN; ++i) { > + if (cpumask[i]) { > + pos = i / 8; > + cpumap[pos] |= 1 << (i % 8); > + } > + } > + > + map.size = cpumaplen; > + map.map = cpumap; > + > + if (libxl_set_vcpuaffinity(&priv->ctx, def->id, vcpu, &map) != 0) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to pin vcpu '%d' with libxenlight"), vcpu); > + goto cleanup; > + } > + > + VIR_FREE(cpumap); > + } > + > + ret = 0; > + > +cleanup: > + VIR_FREE(cpumap); > + return ret; > +} > + > /* > * Start a domain through libxenlight. > * > @@ -440,6 +536,9 @@ libxlVmStart(libxlDriverPrivatePtr driver, > if (libxlCreateDomEvents(vm) < 0) > goto error; > > + if (libxlDomainSetVcpuAffinites(driver, vm) < 0) > + goto error; > + > if (!start_paused) { > libxl_domain_unpause(&priv->ctx, domid); > vm->state = VIR_DOMAIN_RUNNING; > @@ -869,42 +968,7 @@ libxlGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) > static int > libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) > { > - libxl_physinfo phy_info; > - const libxl_version_info* ver_info; > - libxlDriverPrivatePtr driver = conn->privateData; > - struct utsname utsname; > - > - if (libxl_get_physinfo(&driver->ctx, &phy_info)) { > - libxlError(VIR_ERR_INTERNAL_ERROR, > - _("libxl_get_physinfo_info failed")); > - return -1; > - } > - > - if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) { > - libxlError(VIR_ERR_INTERNAL_ERROR, > - _("libxl_get_version_info failed")); > - return -1; > - } > - > - uname(&utsname); > - if (virStrncpy(info->model, > - utsname.machine, > - strlen(utsname.machine), > - sizeof(info->model)) == NULL) { > - libxlError(VIR_ERR_INTERNAL_ERROR, > - _("machine type %s too big for destination"), > - utsname.machine); > - return -1; > - } > - > - info->memory = phy_info.total_pages * (ver_info->pagesize / 1024); > - info->cpus = phy_info.nr_cpus; > - info->nodes = phy_info.nr_nodes; > - info->cores = phy_info.cores_per_socket; > - info->threads = phy_info.threads_per_core; > - info->sockets = 1; > - info->mhz = phy_info.cpu_khz / 1000; > - return 0; > + return libxlDoNodeGetInfo(conn->privateData, info); > } > > static char * > @@ -1712,6 +1776,13 @@ libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap, > _("Failed to pin vcpu '%d' with libxenlight"), vcpu); > goto cleanup; > } > + > + if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + "%s", _("failed to update or add vcpupin xml")); > + goto cleanup; > + } > + > I'm not sure about this hunk. The cputune info is in memory but not saved anywhere. E.g. # virsh start domU # virsh vcpupin domU 0 0,1,2 # virsh dumpxml domU | grep vcpupin # restart libvirtd # virsh dumpxml domU | grep vcpupin # I think config in driver->stateDir needs updated to handle this case. # virsh start domU # virsh vcpuping domU 0 0,1,2 # virsh shutdown domU # wait for shutdown # virsh dumpxml domU | grep vcpupin # restart libvirtd # virsh dumpxml domU | grep vcpupin # Once the domain is shutdown, the affinitiy config should be removed right? Documentation for virDomainPinVcpu states: "This command only changes the runtime configuration of the domain, so can only be called on an active domain". Regards, Jim From eblake at redhat.com Thu Apr 7 18:56:43 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 12:56:43 -0600 Subject: [libvirt] [PATCH 3/6] use virObject to manage reference-count of virDomainObj In-Reply-To: <20110407094126.GD7711@localhost.localdomain> References: <4D9CEA54.6000402@redhat.com> <20110407094126.GD7711@localhost.localdomain> Message-ID: <4D9E08EB.1070807@redhat.com> On 04/07/2011 03:41 AM, Hu Tao wrote: >>> @@ -1010,6 +1007,11 @@ static virDomainObjPtr virDomainObjNew(virCapsPtr caps) >>> return NULL; >>> } >>> >>> + if (virObjectInit(&domain->obj, doDomainObjFree)) { >>> + VIR_FREE(domain); >>> + return NULL; >> >> Hmm. virObjectInit used VIR_ERROR, which logs, but doesn't call into >> virtError. By returning NULL here, a user will get the dreaded "Unknown >> error" message since we didn't hook into the virterror machinery. >> Should virObjectInit instead be using virReportErrorHelper? Or is it > > How to use virReportErrorHelper in this case? > >> considered a coding bug to ever have virObjectInit fail in the first >> place, so we don't really have to worry about that. > > Sorry for my bad English, I don't understand this sentence. Basically, I was envisioning: # define virObjectReportError(code, ...) \ virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) and calling virObjectReportError() instead of VIR_ERROR() for any failure inside of virobject.c. VIR_ERROR only hooks up to the log file, but virReportErrorHelper _also_ hooks up to the remote procedure call (which means that if the error happens due to someone making an API call, they get the message back rather than just a cryptic "Unknown error"). But if we can guarantee that the only possible errors are due to coding mistakes (and in reality, that's true), then I'd almost go so far as to do make virObjectInit return void instead of int (callers need not check for failure), and inside virObjectInit do: if (obj->free) { VIR_ERROR ("Coding bug encountered, aborting"); abort (); } Gnulib already has uses of abort() in places that can only be reached by pure coding bugs, even though libvirt.git does not currently have anything like that. On the other hand, there's a difference between errors in virObjectInit() (which are only possible due to severe coding bugs and easy to audit that they will never hit without ever risking an abort() escaping into released code) vs. errors in virObjectUnref() (if we've unreferenced an object too many times, it's hard to tell which place in the code was the culprit, so the bug may escape in to a release and a library should avoid abort() at all costs in released code). At any rate, any time we hit a reference counting bug, it is in our best interest to do something loud and obvious that a bug occurred, to make it easier to fix the bug, rather than trying to proceed with invalid data. >> The only potential drawback to that is that if you use the wrong >> function, the referencing doesn't happen. Or maybe even make >> virHashCreateFull take a bool parameter of whether the data must be a >> virObjectPtr, so you don't have to wrap virHashAddObjEntry (and since >> virHashRemoveEntry doesn't really have any way to create a >> virHashRemoveObjEntry wrapper, but it would need to be in on the game of >> automatic reference count manipulations any time we know the table >> hashes only virObjects as data). > > Would it be better to have two types of hashtable, one hashes only > virObjects, the other hashes data except virObjects? this can minimize > the impact brought by the change of hashtable to existing code. Proving something is a virObject can be done via type-safe wrapper functions, but only for functions that take a data argument in the first place (virHashRemoveEntry does not). But in the opposite direction, how can you prove something is not a virObject? I don't think you can forbid that (nor do you necessarily want to; it might make sense to hash void* which happens to be virObject but where the container does not plan on owning the object). I think the best you can do is adding helper methods that operate only if you request and promise to only use virObject as the data, and adding a bool flag to virHashCreateFull seems the least invasive way to do it. > If a dom is added into a hashtable, then it is not safe to modify its > uuid since it is the key of dom in hashtable. And we have to make some > rules about when the uuid can be modified(say, hold the driver lock > first when dom is in hashtable). Yes, for a given object, especially if that object is hashed by a subset of itself, then the data being used as a hash key must not be modified. And we don't modify domain uuid's after creation (if we need a new uuid, we are creating a new domain rather than modifying an existing one). But without documenting which fields are constant and can be accessed without obtaining a lock and which must not be modified after the constructor, compared to the remaining fields that must only be read or written while holding the lock, is on a case-by-case basis per struct that inherits from virObject. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From laine at laine.org Thu Apr 7 19:26:24 2011 From: laine at laine.org (Laine Stump) Date: Thu, 07 Apr 2011 15:26:24 -0400 Subject: [libvirt] [PATCH] build: fix gitignore sorting In-Reply-To: <1302043898-2154-1-git-send-email-eblake@redhat.com> References: <1302043898-2154-1-git-send-email-eblake@redhat.com> Message-ID: <4D9E0FE0.9090208@laine.org> On 04/05/2011 06:51 PM, Eric Blake wrote: > Make it so we don't have to 'git add -f' particular files like > po/POTFILES.in all the time (tested by fixing one of our > special-case files as part of the patch). > > * .gnulib: Update to latest. > * bootstrap: Resync from coreutils. > * .gitignore: Sort whitelist entries correctly, including ignoring > files rather than directories. > * m4/virt-compile-warnings.m4: Convert tabs to space. > --- > > * .gnulib dec3475...f796520 (7): > > bootstrap: compute gnulib_extra_files after updating build_aux > > bootstrap: preserve git whitelist item sorting > > maint.mk: Don't trigger sc_space_tab check. > > areadlink, areadlinkat: rewrite in terms of careadlinkat > > autoupdate > > wmemchr, wcschr, wcsrchr, wcspbrk, wcsstr: Avoid errors in C++ mode. > > wcpcpy, wcpncpy: Ensure declaration on glibc>= 2.13 systems. > > I'm also trying to patch 'man gitignore' with things I've learned > from this exercise: http://marc.info/?t=130203248100003&r=1&w=2 > > .gitignore | 12 +++++----- > .gnulib | 2 +- > bootstrap | 46 +++++++++++++++++++++++++++++-------------- > m4/virt-compile-warnings.m4 | 8 +++--- > 4 files changed, 42 insertions(+), 26 deletions(-) ACK (once Eric explained the sed construct I'd never seen before :-) > +# Ensure that lines starting with ! sort last, per gitignore conventions > +# for whitelisting exceptions after a more generic blacklist pattern. > +sort_patterns() { > + sort -u "$@" | sed '/^!/ { > + H > + d > + } > + $ { > + P > + x > + s/^\n// > + }' > +} Yeah, that's the one... From stefanb at linux.vnet.ibm.com Thu Apr 7 19:47:08 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Thu, 07 Apr 2011 15:47:08 -0400 Subject: [libvirt] [PATCH v2] nwfilters: support for TCP flags evaluation Message-ID: <4D9E14BC.4010009@linux.vnet.ibm.com> This patch adds support for the evaluation of TCP flags in nwfilters. It adds documentation to the web page and extends the tests as well. Also, the nwfilter schema is extended. The following are some example for rules using the tcp flags: Signed-off-by: Stefan Berger --- docs/formatnwfilter.html.in | 10 ++ docs/schemas/nwfilter.rng | 16 ++++ src/conf/nwfilter_conf.c | 115 +++++++++++++++++++++++++++--- src/conf/nwfilter_conf.h | 9 ++ src/libvirt_private.syms | 1 src/nwfilter/nwfilter_ebiptables_driver.c | 9 ++ tests/nwfilterxml2xmlin/tcp-test.xml | 12 +++ tests/nwfilterxml2xmlout/tcp-test.xml | 12 +++ 8 files changed, 174 insertions(+), 10 deletions(-) Index: libvirt-acl/src/conf/nwfilter_conf.c =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.c +++ libvirt-acl/src/conf/nwfilter_conf.c @@ -5,7 +5,8 @@ * Copyright (C) 2006-2011 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * - * Copyright (C) 2010 IBM Corporation + * Copyright (C) 2010-2011 IBM Corporation + * Copyright (C) 2010-2011 Stefan Berger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -726,17 +727,23 @@ printStringItems(virBufferPtr buf, const int32_t flags, const char *sep) { unsigned int i, c = 0; - int32_t last_attr = 0; + int32_t mask = 0x1; - for (i = 0; int_map[i].val; i++) { - if (last_attr != int_map[i].attr && - flags & int_map[i].attr) { - if (c >= 1) - virBufferVSprintf(buf, "%s", sep); - virBufferVSprintf(buf, "%s", int_map[i].val); - c++; + while (mask) { + if ((mask & flags)) { + for (i = 0; int_map[i].val; i++) { + if (mask == int_map[i].attr) { + if (c >= 1) + virBufferVSprintf(buf, "%s", sep); + virBufferVSprintf(buf, "%s", int_map[i].val); + c++; + } + } + flags ^= mask; + if (!flags) + break; } - last_attr = int_map[i].attr; + mask <<= 1; } return 0; @@ -799,6 +806,87 @@ stateFormatter(virBufferPtr buf, } + +static const struct int_map tcpFlags[] = { + INTMAP_ENTRY(0x1 , "FIN"), + INTMAP_ENTRY(0x2 , "SYN"), + INTMAP_ENTRY(0x4 , "RST"), + INTMAP_ENTRY(0x8 , "PSH"), + INTMAP_ENTRY(0x10, "ACK"), + INTMAP_ENTRY(0x20, "URG"), + INTMAP_ENTRY(0x3F, "ALL"), + INTMAP_ENTRY(0x0 , "NONE"), + INTMAP_ENTRY_LAST +}; + + +static bool +tcpFlagsValidator(enum attrDatatype datatype ATTRIBUTE_UNUSED, union data *val, + virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED, + nwItemDesc *item) +{ + bool rc = false; + char *s_mask = val->c; + char *sep = strchr(val->c, '/'); + char *s_flags; + int32_t mask = 0, flags = 0; + + if (!sep) + return false; + + s_flags = sep + 1; + + *sep = '\0'; + + if (!parseStringItems(tcpFlags, s_mask , &mask , ',') && + !parseStringItems(tcpFlags, s_flags, &flags, ',')) { + item->u.tcpFlags.mask = mask & 0x3f; + item->u.tcpFlags.flags = flags & 0x3f; + rc = true; + } + + *sep = '/'; + + return rc; +} + + +static void +printTCPFlags(virBufferPtr buf, uint8_t flags) +{ + if (flags == 0) + virBufferAddLit(buf, "NONE"); + else if (flags == 0x3f) + virBufferAddLit(buf, "ALL"); + else + printStringItems(buf, tcpFlags, flags, ","); +} + + +void +virNWFilterPrintTCPFlags(virBufferPtr buf, + uint8_t mask, char sep, uint8_t flags) +{ + printTCPFlags(buf, mask); + virBufferAddChar(buf, sep); + printTCPFlags(buf, flags); +} + + +static bool +tcpFlagsFormatter(virBufferPtr buf, + virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED, + nwItemDesc *item) +{ + virNWFilterPrintTCPFlags(buf, + item->u.tcpFlags.mask, + '/', + item->u.tcpFlags.flags); + + return true; +} + + #define COMMON_MAC_PROPS(STRUCT) \ {\ .name = SRCMACADDR,\ @@ -1104,6 +1192,13 @@ static const virXMLAttr2Struct tcpAttrib .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX, .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.dataTCPOption), }, + { + .name = "flags", + .datatype = DATATYPE_STRING, + .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.dataTCPFlags), + .validator = tcpFlagsValidator, + .formatter = tcpFlagsFormatter, + }, COMMENT_PROP_IPHDR(tcpHdrFilter), { .name = NULL, Index: libvirt-acl/src/conf/nwfilter_conf.h =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.h +++ libvirt-acl/src/conf/nwfilter_conf.h @@ -122,6 +122,10 @@ struct _nwItemDesc { uint16_t u16; char protocolID[10]; char *string; + struct { + uint8_t mask; + uint8_t flags; + } tcpFlags; } u; }; @@ -242,6 +246,7 @@ struct _tcpHdrFilterDef { ipHdrDataDef ipHdr; portDataDef portData; nwItemDesc dataTCPOption; + nwItemDesc dataTCPFlags; }; @@ -667,6 +672,10 @@ void virNWFilterCallbackDriversLock(void void virNWFilterCallbackDriversUnlock(void); +void virNWFilterPrintTCPFlags(virBufferPtr buf, uint8_t mask, + char sep, uint8_t flags); + + VIR_ENUM_DECL(virNWFilterRuleAction); VIR_ENUM_DECL(virNWFilterRuleDirection); VIR_ENUM_DECL(virNWFilterRuleProtocol); Index: libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_ebiptables_driver.c +++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c @@ -1204,6 +1204,15 @@ _iptablesCreateRuleInstance(int directio &prefix)) goto err_exit; + if (HAS_ENTRY_ITEM(&rule->p.tcpHdrFilter.dataTCPFlags)) { + virBufferVSprintf(&buf, " %s --tcp-flags ", + ENTRY_GET_NEG_SIGN(&rule->p.tcpHdrFilter.dataTCPFlags)); + virNWFilterPrintTCPFlags(&buf, + rule->p.tcpHdrFilter.dataTCPFlags.u.tcpFlags.mask, + ' ', + rule->p.tcpHdrFilter.dataTCPFlags.u.tcpFlags.flags); + } + if (iptablesHandlePortData(&buf, vars, &rule->p.tcpHdrFilter.portData, Index: libvirt-acl/docs/schemas/nwfilter.rng =================================================================== --- libvirt-acl.orig/docs/schemas/nwfilter.rng +++ libvirt-acl/docs/schemas/nwfilter.rng @@ -81,6 +81,7 @@ + @@ -184,6 +185,7 @@ + @@ -606,6 +608,14 @@ + + + + + + + + @@ -872,4 +882,10 @@ ((NEW|ESTABLISHED|RELATED|INVALID)(,(NEW|ESTABLISHED|RELATED|INVALID))*|NONE) + + + + ((SYN|ACK|URG|PSH|FIN|RST)(,(SYN|ACK|URG|PSH|FIN|RST))*|ALL|NONE)/((SYN|ACK|URG|PSH|FIN|RST)(,(SYN|ACK|URG|PSH|FIN|RST))*|ALL|NONE) + + Index: libvirt-acl/docs/formatnwfilter.html.in =================================================================== --- libvirt-acl.orig/docs/formatnwfilter.html.in +++ libvirt-acl/docs/formatnwfilter.html.in @@ -755,6 +755,11 @@ STRING comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE + + flags (Since 0.9.1) + STRING + TCP-only: format of mask/flags with mask and flags each being a comma separated list of SYN,ACK,URG,PSH,FIN,RST or NONE or ALL +



    @@ -1040,6 +1045,11 @@ STRING comma separated list of NEW,ESTABLISHED,RELATED,INVALID or NONE + + flags (Since 0.9.1) + STRING + TCP-only: format of mask/flags with mask and flags each being a comma separated list of SYN,ACK,URG,PSH,FIN,RST or NONE or ALL +



    Index: libvirt-acl/src/libvirt_private.syms =================================================================== --- libvirt-acl.orig/src/libvirt_private.syms +++ libvirt-acl/src/libvirt_private.syms @@ -683,6 +683,7 @@ virNWFilterObjRemove; virNWFilterObjSaveDef; virNWFilterObjUnlock; virNWFilterPrintStateMatchFlags; +virNWFilterPrintTCPFlags; virNWFilterRegisterCallbackDriver; virNWFilterRuleActionTypeToString; virNWFilterRuleProtocolTypeToString; Index: libvirt-acl/tests/nwfilterxml2xmlin/tcp-test.xml =================================================================== --- libvirt-acl.orig/tests/nwfilterxml2xmlin/tcp-test.xml +++ libvirt-acl/tests/nwfilterxml2xmlin/tcp-test.xml @@ -19,4 +19,16 @@ srcportstart='255' srcportend='256' dstportstart='65535' dstportend='65536'/> + + + + + + + + + + + + Index: libvirt-acl/tests/nwfilterxml2xmlout/tcp-test.xml =================================================================== --- libvirt-acl.orig/tests/nwfilterxml2xmlout/tcp-test.xml +++ libvirt-acl/tests/nwfilterxml2xmlout/tcp-test.xml @@ -9,4 +9,16 @@ + + + + + + + + + + + + From jfehlig at novell.com Thu Apr 7 21:02:21 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Thu, 07 Apr 2011 15:02:21 -0600 Subject: [libvirt] [PATCH 4/4] Add domainSave/Restore to libxl driver In-Reply-To: References: Message-ID: <4D9E265D.3070608@novell.com> Markus Gro? wrote: > --- > src/libxl/libxl_conf.h | 10 +++ > src/libxl/libxl_driver.c | 184 +++++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 191 insertions(+), 3 deletions(-) > > diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h > index f2f0d8a..e28615b 100644 > --- a/src/libxl/libxl_conf.h > +++ b/src/libxl/libxl_conf.h > @@ -1,5 +1,6 @@ > /*---------------------------------------------------------------------------*/ > /* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. > + * Copyright (C) 2011 Univention GmbH. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public > @@ -17,6 +18,7 @@ > * > * Authors: > * Jim Fehlig > + * Markus Gro? > */ > /*---------------------------------------------------------------------------*/ > > @@ -85,6 +87,14 @@ struct _libxlDomainObjPrivate { > int eventHdl; > }; > > +static const char libxlSavefileMagic[16]= "libvirt-xml\n \0 \r"; > +typedef struct _libxlSavefileHeader libxlSavefileHeader; > +typedef libxlSavefileHeader *libxlSavefileHeaderPtr; > +struct _libxlSavefileHeader { > + char magic[16]; /* magic id */ > + uint32_t xmlLen; /* length of saved xml */ > +}; > I think we should pad the header, similar to qemu driver, and provide a version field. > + > > # define libxlError(code, ...) \ > virReportErrorHelper(NULL, VIR_FROM_LIBXL, code, __FILE__, \ > diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c > index 1539385..b02d4b7 100644 > --- a/src/libxl/libxl_driver.c > +++ b/src/libxl/libxl_driver.c > @@ -29,6 +29,7 @@ > #include > #include > #include > +#include > > #include "internal.h" > #include "logging.h" > @@ -60,7 +61,6 @@ > > static libxlDriverPrivatePtr libxl_driver = NULL; > > - > /* Function declarations */ > static int > libxlVmStart(libxlDriverPrivatePtr driver, > @@ -1555,6 +1555,184 @@ libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) > } > > static int > +libxlDomainSave(virDomainPtr dom, const char * to) > +{ > + libxlDriverPrivatePtr driver = dom->conn->privateData; > + virDomainObjPtr vm; > + libxlDomainObjPrivatePtr priv; > + virDomainEventPtr event = NULL; > + libxlSavefileHeader hdr; > + libxl_domain_suspend_info s_info; > + char * xml; > + uint32_t xml_len; > + int fd; > + int ret = -1; > + > + libxlDriverLock(driver); > + vm = virDomainFindByUUID(&driver->domains, dom->uuid); > + > + if (!vm) { > + char uuidstr[VIR_UUID_STRING_BUFLEN]; > + virUUIDFormat(dom->uuid, uuidstr); > + libxlError(VIR_ERR_NO_DOMAIN, > + _("No domain with matching uuid '%s'"), uuidstr); > + goto cleanup; > + } > + > + if (!virDomainObjIsActive(vm)) { > + libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); > + goto cleanup; > + } > + > + priv = vm->privateData; > + > + if (vm->state != VIR_DOMAIN_PAUSED) { > + memset(&s_info, 0, sizeof(s_info)); > + > + if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR, > + getuid(), getgid(), 0)) < 0) { > + virReportSystemError(-fd, > + _("Failed to create domain save file '%s'"), > + to); > + goto cleanup; > + } > + > + if ((xml = virDomainDefFormat(vm->def, 0)) == NULL) > + goto cleanup; > + xml_len = strlen(xml) + 1; > + > + memset(&hdr, 0, sizeof(hdr)); > + memcpy(hdr.magic, libxlSavefileMagic, sizeof(hdr.magic)); > + hdr.xmlLen = xml_len; > + > + if (safewrite(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { > + libxlError(VIR_ERR_OPERATION_FAILED, > + _("Failed to write save file header")); > + goto cleanup; > + } > + > + if (safewrite(fd, xml, xml_len) != xml_len) { > + libxlError(VIR_ERR_OPERATION_FAILED, > + _("Failed to write xml description")); > + goto cleanup; > + } > + > + if (libxl_domain_suspend(&priv->ctx, &s_info, dom->id, fd) != 0) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to save domain '%d' with libxenlight"), > + dom->id); > + goto cleanup; > + } > + > + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, > + VIR_DOMAIN_EVENT_STOPPED_SAVED); > + > + if (libxlVmReap(driver, vm, 1) != 0) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to destroy domain '%d'"), dom->id); > + goto cleanup; > + } > + > + if (!vm->persistent) { > + virDomainRemoveInactive(&driver->domains, vm); > + vm = NULL; > + } > + ret = 0; > + } > +cleanup: > + VIR_FREE(xml); > + if (VIR_CLOSE(fd) < 0) > + virReportSystemError(errno, "%s", _("cannot close file")); > + if (vm) > + virDomainObjUnlock(vm); > + if (event) > + libxlDomainEventQueue(driver, event); > + libxlDriverUnlock(driver); > + return ret; > +} > + > +static int > +libxlDomainRestore(virConnectPtr conn, const char * from) > +{ > + libxlDriverPrivatePtr driver = conn->privateData; > + virDomainDefPtr def = NULL; > + virDomainObjPtr vm = NULL; > + virDomainEventPtr event = NULL; > + libxlSavefileHeader hdr; > + char * xml = NULL; > + int fd; > + int ret = -1; > + > + libxlDriverLock(driver); > + > + if ((fd = virFileOpenAs(from, O_RDONLY, 0, getuid(), getgid(), 0)) < 0) { > + libxlError(VIR_ERR_OPERATION_FAILED, > + "%s", _("cannot read domain image")); > + goto cleanup; > + } > + > + if (saferead(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { > + libxlError(VIR_ERR_OPERATION_FAILED, > + "%s", _("failed to read libxl header")); > + goto cleanup; > + } > + > + if (memcmp(hdr.magic, libxlSavefileMagic, sizeof(hdr.magic))) { > + libxlError(VIR_ERR_INVALID_ARG, "%s", _("image magic is incorrect")); > + goto cleanup; > + } > + > + if (hdr.xmlLen <= 0) { > + libxlError(VIR_ERR_OPERATION_FAILED, > + _("invalid XML length: %d"), hdr.xmlLen); > + goto cleanup; > + } > + > + if (VIR_ALLOC_N(xml, hdr.xmlLen) < 0) { > + virReportOOMError(); > + goto cleanup; > + } > + > + if (saferead(fd, xml, hdr.xmlLen) != hdr.xmlLen) { > + libxlError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML")); > + goto cleanup; > + } > + > + if (!(def = virDomainDefParseString(driver->caps, xml, 0))) > + goto cleanup; > + > + if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) > + goto cleanup; > + > + if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def, false))) > + goto cleanup; > + > + def = NULL; > + > + ret = libxlVmStart(driver, vm, false); > This starts a new domain. To restore a domain, you need to use libxl_domain_create_restore(). Regards, Jim > + > + if (ret == 0) { > + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, > + VIR_DOMAIN_EVENT_STARTED_RESTORED); > + } else if (ret < 0 && !vm->persistent) { > + virDomainRemoveInactive(&driver->domains, vm); > + vm = NULL; > + } > + > +cleanup: > + VIR_FREE(xml); > + virDomainDefFree(def); > + if (VIR_CLOSE(fd) < 0) > + virReportSystemError(errno, "%s", _("cannot close file")); > + if (vm) > + virDomainObjUnlock(vm); > + if (event) > + libxlDomainEventQueue(driver, event); > + libxlDriverUnlock(driver); > + return ret; > +} > + > +static int > libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, > unsigned int flags) > { > @@ -2658,8 +2836,8 @@ static virDriver libxlDriver = { > NULL, /* domainSetBlkioParameters */ > NULL, /* domainGetBlkioParameters */ > libxlDomainGetInfo, /* domainGetInfo */ > - NULL, /* domainSave */ > - NULL, /* domainRestore */ > + libxlDomainSave, /* domainSave */ > + libxlDomainRestore, /* domainRestore */ > NULL, /* domainCoreDump */ > libxlDomainSetVcpus, /* domainSetVcpus */ > libxlDomainSetVcpusFlags, /* domainSetVcpusFlags */ > From eblake at redhat.com Thu Apr 7 21:29:52 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 15:29:52 -0600 Subject: [libvirt] [PATCH] virsh: fix mingw startup In-Reply-To: <4D9DD218.6000302@laine.org> References: <4D9BA555.1010302@redhat.com> <1302119254-20506-1-git-send-email-eblake@redhat.com> <4D9DD218.6000302@laine.org> Message-ID: <4D9E2CD0.4050303@redhat.com> On 04/07/2011 09:02 AM, Laine Stump wrote: > On 04/06/2011 03:47 PM, Eric Blake wrote: >> * .gnulib: Update to latest, for pipe2. >> * bootstrap.conf (gnulib_modules): Add pipe2. >> * src/util/event_poll.c (virEventPollInit): Use it, to avoid >> problematic virSetCloseExec on mingw. >> --- >> >> The gnulib changes to pipe2 are now in. >> >> * .gnulib f796520...2255b86 (4): >> > verify: use _Static_assert if available >> > Remove leftover generated .h files after config.status changed. >> > Ensure to rebuild generated .h files when config.status has >> changed. >> > pipe2: Relicense under LGPLv2+. >> >> This assumes that my earlier .gnulib modification patch is also in: >> https://www.redhat.com/archives/libvir-list/2011-April/msg00297.html >> although I can rebase as needed. >> >> .gnulib | 2 +- >> bootstrap.conf | 3 ++- >> src/util/event_poll.c | 7 ++----- >> 3 files changed, 5 insertions(+), 7 deletions(-) > > ACK. Thanks; pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 7 21:30:00 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 15:30:00 -0600 Subject: [libvirt] [PATCH] build: fix gitignore sorting In-Reply-To: <4D9E0FE0.9090208@laine.org> References: <1302043898-2154-1-git-send-email-eblake@redhat.com> <4D9E0FE0.9090208@laine.org> Message-ID: <4D9E2CD8.4020607@redhat.com> On 04/07/2011 01:26 PM, Laine Stump wrote: > On 04/05/2011 06:51 PM, Eric Blake wrote: >> Make it so we don't have to 'git add -f' particular files like >> po/POTFILES.in all the time (tested by fixing one of our >> special-case files as part of the patch). >> >> * .gnulib: Update to latest. >> * bootstrap: Resync from coreutils. >> * .gitignore: Sort whitelist entries correctly, including ignoring >> files rather than directories. >> * m4/virt-compile-warnings.m4: Convert tabs to space. >> --- > > ACK (once Eric explained the sed construct I'd never seen before :-) Thanks; pushed. > >> +# Ensure that lines starting with ! sort last, per gitignore conventions >> +# for whitelisting exceptions after a more generic blacklist pattern. >> +sort_patterns() { >> + sort -u "$@" | sed Sed has two buffers - the pattern space (which gets printed for every line of input unless it is empty) and the hold space (which is used for scratch work). '/^!/ { >> + H >> + d >> + } For all lines that start with !, append a newline and that line into the hold space, then delete the line from the pattern space (so skip printing ! lines the first time through). >> + $ { >> + P >> + x >> + s/^\n// >> + }' On the last line, print the line like normal, then exchange pattern and buffer spaces, remove the extra leading newline that got put in the hold space on the first ! line, then print all the deferred ! lines. > Yeah, that's the one... I don't blame you for asking - sed's got some pretty arcane (but cool) features. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From agl at us.ibm.com Thu Apr 7 21:32:00 2011 From: agl at us.ibm.com (Adam Litke) Date: Thu, 7 Apr 2011 16:32:00 -0500 Subject: [libvirt] [PATCH 2/6] virDomainStreamDisk: Add public symbols to libvirt API In-Reply-To: <1302211924-28517-1-git-send-email-agl@us.ibm.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> Message-ID: <1302211924-28517-3-git-send-email-agl@us.ibm.com> * src/libvirt.c: implement the main entry points * src/libvirt_public.syms: add them to the exported symbols Signed-off-by: Adam Litke --- src/libvirt.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 ++ 2 files changed, 120 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 85dfc58..15c5ddc 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -5928,6 +5928,121 @@ error: } /** + * virDomainStreamDisk: + * @dom: pointer to the domain object + * @path: path to the block device + * @offset: when streaming a single disk unit, the offset of the unit to stream + * @flags: flags to control disk streaming behavior + * + * Returns: Next offset or 0 on success, -1 on failure. + */ +unsigned long long +virDomainStreamDisk(virDomainPtr dom, + const char *path, + unsigned long long offset, + unsigned int flags) +{ + virConnectPtr conn; + unsigned long long ret = -1; + + VIR_DOMAIN_DEBUG(dom, "path=%p, offset=%llu, flags=%u", + path, offset, flags); + + if (path == NULL) { + virLibDomainError (VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (flags == VIR_STREAM_DISK_START || flags == VIR_STREAM_DISK_STOP) { + if (offset != 0) { + virLibDomainError (VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + } else if (flags != VIR_STREAM_DISK_ONE) { + virLibDomainError (VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + virResetLastError(); + if (!VIR_IS_CONNECTED_DOMAIN (dom)) { + virLibDomainError (VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return -1; + } + + conn = dom->conn; + if (conn->driver->domainStreamDisk) { + ret = conn->driver->domainStreamDisk (dom, path, offset, flags); + if (ret == -1) + goto error; + return ret; + } + + virLibDomainError (VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(dom->conn); + return -1; +} + +/** + * virDomainStreamDiskInfo: + * @dom: pointer to the domain object + * @states: An array of virStreamDiskState structures to store stream info + * @nr_states: The maximimum number of stream states to report + * @flags: future flags, use 0 for now + * + * Returns: The number of streams reported or -1 on failure. + */ +int +virDomainStreamDiskInfo(virDomainPtr dom, + virStreamDiskStatePtr states, + unsigned int nr_states, + unsigned int flags) +{ + virConnectPtr conn; + int ret = -1; + + VIR_DOMAIN_DEBUG(dom, "states=%p, nr_states=%u, flags=%u", + states, nr_states, flags); + + if (states == NULL) { + virLibDomainError (VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (nr_states == 0) { + virLibDomainError (VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (flags != 0) { + virLibDomainError (VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + virResetLastError(); + if (!VIR_IS_CONNECTED_DOMAIN (dom)) { + virLibDomainError (VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + return -1; + } + + conn = dom->conn; + if (conn->driver->domainStreamDiskInfo) { + ret = conn->driver->domainStreamDiskInfo (dom, states, nr_states, + flags); + if (ret == -1) + goto error; + return ret; + } + + virLibDomainError (VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(dom->conn); + return -1; +} + +/** * virNodeGetCellsFreeMemory: * @conn: pointer to the hypervisor connection * @freeMems: pointer to the array of unsigned long long diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b4aed41..185186a 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -437,3 +437,8 @@ LIBVIRT_0.9.0 { } LIBVIRT_0.8.8; # .... define new API here using predicted next version number .... +LIBVIRT_0.9.1 { + global: + virDomainStreamDisk; + virDomainStreamDiskInfo; +} LIBVIRT_0.9.0; -- 1.7.3 From agl at us.ibm.com Thu Apr 7 21:32:03 2011 From: agl at us.ibm.com (Adam Litke) Date: Thu, 7 Apr 2011 16:32:03 -0500 Subject: [libvirt] [PATCH 5/6] Add new disk streaming commands to virsh In-Reply-To: <1302211924-28517-1-git-send-email-agl@us.ibm.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> Message-ID: <1302211924-28517-6-git-send-email-agl@us.ibm.com> Define two new virsh commands: one to control disk streaming and one to print the status of active disk streams. * tools/virsh.c: implement the new commands Signed-off-by: Adam Litke --- tools/virsh.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 133 insertions(+), 1 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index f2d2c9d..edffc61 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -3999,6 +3999,137 @@ done: } /* + * "domstreamdisk" command + */ +static const vshCmdInfo info_domstreamdisk[] = { + {"help", gettext_noop("Stream data to a disk")}, + {"desc", gettext_noop("Stream data to a disk connected to a running domain")}, + { NULL, NULL }, +}; + +static const vshCmdOptDef opts_domstreamdisk[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")}, + {"start", VSH_OT_BOOL, VSH_OFLAG_NONE, N_("Start streaming a disk") }, + {"stop", VSH_OT_BOOL, VSH_OFLAG_NONE, N_("Stop streaming a disk") }, + {"incremental", VSH_OT_BOOL, VSH_OFLAG_NONE, N_("Perform an incremental stream") }, + {"path", VSH_OT_DATA, VSH_OFLAG_REQ, N_("block device")}, + {"offset", VSH_OT_DATA, VSH_OFLAG_NONE, N_("Device offset for incremental stream")}, + { NULL, 0, 0, NULL }, +}; + +static int +cmdDomStreamDisk(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + const char *name, *path; + unsigned long long offset, next; + unsigned int flags, start, stop, incr; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return FALSE; + + flags = start = stop = incr = 0; + if (vshCommandOptBool(cmd, "start")) { + start = 1; + flags = VIR_STREAM_DISK_START; + } + if (vshCommandOptBool(cmd, "stop")) { + stop = 1; + flags = VIR_STREAM_DISK_STOP; + } + if (vshCommandOptBool(cmd, "incremental")) { + incr = 1; + flags = VIR_STREAM_DISK_ONE; + } + if (start + stop + incr != 1) { + vshError(ctl, _("Exactly one mode: --start, --stop, --incremental, " + "is required")); + return FALSE; + } + + if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + return FALSE; + + if (vshCommandOptString(cmd, "path", &path) < 0) + return FALSE; + + if (flags == VIR_STREAM_DISK_ONE) { + if (vshCommandOptULongLong(cmd, "offset", &offset) < 0) { + vshError(ctl, _("An offset is required for incremental streaming")); + virDomainFree(dom); + return FALSE; + } + } else { + offset = 0; + } + + next = virDomainStreamDisk(dom, path, offset, flags); + if (next == (unsigned long long) -1) { + virDomainFree(dom); + return FALSE; + } + + if (flags == VIR_STREAM_DISK_START) + vshPrint (ctl, "Stream successfully started\n"); + else if (flags == VIR_STREAM_DISK_STOP) + vshPrint (ctl, "Stream successfully stopped\n"); + else + vshPrint (ctl, "Strem successful. Continue at offset %llu\n", next); + + virDomainFree(dom); + return TRUE; +} + +/* + * "domstreamdiskinfo" command + */ +static const vshCmdInfo info_domstreamdiskinfo[] = { + {"help", gettext_noop("Get disk streaming status for a domain")}, + {"desc", gettext_noop("Get disk streaming status for a running domain")}, + { NULL, NULL }, +}; + +static const vshCmdOptDef opts_domstreamdiskinfo[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")}, + { NULL, 0, 0, NULL }, +}; + +static int +cmdDomStreamDiskInfo(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + const char *name; + struct _virStreamDiskState streams[VIR_STREAM_DISK_MAX_STREAMS]; + int nr_streams, i; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return FALSE; + + if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + return FALSE; + + nr_streams = virDomainStreamDiskInfo(dom, streams, + VIR_STREAM_DISK_MAX_STREAMS, 0); + if (nr_streams < 0) { + vshError(ctl, _("Failed to get disk stream information for domain %s"), + name); + virDomainFree(dom); + return FALSE; + } + + vshPrint (ctl, "%-30s %-10s %-10s\n", _("Device"), _("Offset"), + _("Size")); + vshPrint (ctl, "----------------------------------------------------\n"); + for (i = 0; i < nr_streams; i++) { + vshPrint (ctl, "%-30s %-10llu %-10llu\n", streams[i].path, + streams[i].offset, streams[i].size); + } + + virDomainFree(dom); + return TRUE; +} + +/* * "net-autostart" command */ static const vshCmdInfo info_network_autostart[] = { @@ -10682,6 +10813,8 @@ static const vshCmdDef domManagementCmds[] = { {"domjobabort", cmdDomjobabort, opts_domjobabort, info_domjobabort}, {"domjobinfo", cmdDomjobinfo, opts_domjobinfo, info_domjobinfo}, {"domname", cmdDomname, opts_domname, info_domname}, + {"domstreamdisk", cmdDomStreamDisk, opts_domstreamdisk, info_domstreamdisk}, + {"domstreamdiskinfo", cmdDomStreamDiskInfo, opts_domstreamdiskinfo, info_domstreamdiskinfo}, {"domuuid", cmdDomuuid, opts_domuuid, info_domuuid}, {"domxml-from-native", cmdDomXMLFromNative, opts_domxmlfromnative, info_domxmlfromnative}, {"domxml-to-native", cmdDomXMLToNative, opts_domxmltonative, info_domxmltonative}, @@ -11279,7 +11412,6 @@ vshCommandOptULongLong(const vshCmd *cmd, const char *name, return ret; } - /* * Returns TRUE/FALSE if the option exists */ -- 1.7.3 From agl at us.ibm.com Thu Apr 7 21:32:04 2011 From: agl at us.ibm.com (Adam Litke) Date: Thu, 7 Apr 2011 16:32:04 -0500 Subject: [libvirt] [PATCH 6/6] python: Add python bindings for virDomainStreamDisk[Info] In-Reply-To: <1302211924-28517-1-git-send-email-agl@us.ibm.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> Message-ID: <1302211924-28517-7-git-send-email-agl@us.ibm.com> Enable virDomainStreamDiskInfo in the python API. dom.StreamDiskInfo() will return a list containing a dictionary for each active stream. Each dictionary contains items to report: the disk alias, the current stream offset, and the total disk size. virDomainStreamDisk() works with the automatic wrappers. * python/generator.py: reenable bindings for this entry point * python/libvirt-override-api.xml python/libvirt-override.c: the generator can't handle this new function, add the new binding, and the XML description Signed-off-by: Adam Litke --- python/generator.py | 4 +-- python/libvirt-override-api.xml | 5 ++++ python/libvirt-override.c | 46 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/python/generator.py b/python/generator.py index 69ffcad..2c5f6b2 100755 --- a/python/generator.py +++ b/python/generator.py @@ -166,8 +166,6 @@ def enum(type, name, value): functions_failed = [] functions_skipped = [ "virConnectListDomains", - "virDomainStreamDisk", - "virDomainStreamDiskInfo", ] skipped_modules = { @@ -182,7 +180,6 @@ skipped_types = { 'virConnectDomainEventIOErrorCallback': "No function types in python", 'virConnectDomainEventGraphicsCallback': "No function types in python", 'virEventAddHandleFunc': "No function types in python", - 'virStreamDiskStatePtr': "Not implemented yet", } ####################################################################### @@ -344,6 +341,7 @@ skip_impl = ( 'virNodeDeviceListCaps', 'virConnectBaselineCPU', 'virDomainRevertToSnapshot', + 'virDomainStreamDiskInfo', ) diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml index 54deeb5..9a74551 100644 --- a/python/libvirt-override-api.xml +++ b/python/libvirt-override-api.xml @@ -308,5 +308,10 @@ + + collect information about active disk streams + + + diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 4a9b432..984d3ef 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -3508,6 +3508,51 @@ libvirt_virConnectDomainEventDeregisterAny(ATTRIBUTE_UNUSED PyObject * self, return (py_retval); } +static PyObject * +libvirt_virDomainStreamDiskInfo(PyObject *self ATTRIBUTE_UNUSED, + PyObject *args) { + virDomainPtr domain; + PyObject *pyobj_domain; + unsigned int nr_streams, i; + struct _virStreamDiskState streams[VIR_STREAM_DISK_MAX_STREAMS]; + PyObject *ret; + + if (!PyArg_ParseTuple(args, (char *)"O:virDomainStreamDiskInfo", + &pyobj_domain)) + return(NULL); + domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + + nr_streams = virDomainStreamDiskInfo(domain, streams, + VIR_STREAM_DISK_MAX_STREAMS, 0); + if (nr_streams == -1) + return VIR_PY_NONE; + + if ((ret = PyList_New(nr_streams)) == NULL) + return VIR_PY_NONE; + + for (i = 0; i < nr_streams; i++) { + PyObject *dict = PyDict_New(); + if (dict == NULL) + goto error; + PyDict_SetItem(dict, libvirt_constcharPtrWrap("path"), + libvirt_constcharPtrWrap(streams[i].path)); + PyDict_SetItem(dict, libvirt_constcharPtrWrap("offset"), + libvirt_ulonglongWrap(streams[i].offset)); + PyDict_SetItem(dict, libvirt_constcharPtrWrap("size"), + libvirt_ulonglongWrap(streams[i].size)); + PyList_SetItem(ret, i, dict); + } + return ret; + +error: + for (i = 0; i < PyList_Size(ret); i++) { + PyObject *item = PyList_GET_ITEM(ret, i); + Py_XDECREF(item); + } + Py_DECREF(ret); + return VIR_PY_NONE; +} + /************************************************************************ * * @@ -3585,6 +3630,7 @@ static PyMethodDef libvirtMethods[] = { {(char *) "virDomainGetJobInfo", libvirt_virDomainGetJobInfo, METH_VARARGS, NULL}, {(char *) "virDomainSnapshotListNames", libvirt_virDomainSnapshotListNames, METH_VARARGS, NULL}, {(char *) "virDomainRevertToSnapshot", libvirt_virDomainRevertToSnapshot, METH_VARARGS, NULL}, + {(char *) "virDomainStreamDiskInfo", libvirt_virDomainStreamDiskInfo, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; -- 1.7.3 From agl at us.ibm.com Thu Apr 7 21:31:59 2011 From: agl at us.ibm.com (Adam Litke) Date: Thu, 7 Apr 2011 16:31:59 -0500 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: <1302211924-28517-1-git-send-email-agl@us.ibm.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> Message-ID: <1302211924-28517-2-git-send-email-agl@us.ibm.com> Set up the types for the disk streaming functions and insert it into the virDriver structure definition. Because of static initializers, update every driver and set the new field to NULL. * include/libvirt/libvirt.h.in: new API * src/driver.h src/*/*_driver.c src/vbox/vbox_tmpl.c: add the new entry to the driver structure * python/generator.py: fix compiler errors, the actual python bindings are implemented later Signed-off-by: Adam Litke --- include/libvirt/libvirt.h.in | 34 ++++++++++++++++++++++++++++++++++ python/generator.py | 3 +++ src/driver.h | 11 +++++++++++ src/esx/esx_driver.c | 2 ++ src/lxc/lxc_driver.c | 2 ++ src/openvz/openvz_driver.c | 2 ++ src/phyp/phyp_driver.c | 2 ++ src/qemu/qemu_driver.c | 2 ++ src/remote/remote_driver.c | 2 ++ src/test/test_driver.c | 2 ++ src/uml/uml_driver.c | 2 ++ src/vbox/vbox_tmpl.c | 2 ++ src/vmware/vmware_driver.c | 2 ++ src/xen/xen_driver.c | 2 ++ 14 files changed, 70 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index bd36015..7c7686d 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1143,6 +1143,40 @@ int virDomainUpdateDeviceFlags(virDomainPtr domain, const char *xml, unsigned int flags); /* + * Disk Streaming + */ +typedef enum { + VIR_STREAM_DISK_ONE = 1, /* Stream a single disk unit */ + VIR_STREAM_DISK_START = 2, /* Stream the entire disk */ + VIR_STREAM_DISK_STOP = 4, /* Stop streaming a disk */ +} virDomainStreamDiskFlags; + +#define VIR_STREAM_PATH_BUFLEN 1024 +#define VIR_STREAM_DISK_MAX_STREAMS 10 + +typedef struct _virStreamDiskState virStreamDiskState; +struct _virStreamDiskState { + char path[VIR_STREAM_PATH_BUFLEN]; + /* + * The unit of measure for size and offset is unspecified. These fields + * are meant to indicate the progress of a continuous streaming operation. + */ + unsigned long long offset; /* Current offset of active streaming */ + unsigned long long size; /* Disk size */ +}; +typedef virStreamDiskState *virStreamDiskStatePtr; + +unsigned long long virDomainStreamDisk(virDomainPtr dom, + const char *path, + unsigned long long offset, + unsigned int flags); + +int virDomainStreamDiskInfo(virDomainPtr dom, + virStreamDiskStatePtr states, + unsigned int nr_states, + unsigned int flags); + +/* * NUMA support */ diff --git a/python/generator.py b/python/generator.py index 4fa4f65..69ffcad 100755 --- a/python/generator.py +++ b/python/generator.py @@ -166,6 +166,8 @@ def enum(type, name, value): functions_failed = [] functions_skipped = [ "virConnectListDomains", + "virDomainStreamDisk", + "virDomainStreamDiskInfo", ] skipped_modules = { @@ -180,6 +182,7 @@ skipped_types = { 'virConnectDomainEventIOErrorCallback': "No function types in python", 'virConnectDomainEventGraphicsCallback': "No function types in python", 'virEventAddHandleFunc': "No function types in python", + 'virStreamDiskStatePtr': "Not implemented yet", } ####################################################################### diff --git a/src/driver.h b/src/driver.h index e5f91ca..b333075 100644 --- a/src/driver.h +++ b/src/driver.h @@ -505,6 +505,15 @@ typedef int (*virDrvDomainSnapshotDelete)(virDomainSnapshotPtr snapshot, unsigned int flags); +typedef unsigned long long + (*virDrvDomainStreamDisk)(virDomainPtr dom, const char *path, + unsigned long long offset, unsigned int flags); + +typedef int + (*virDrvDomainStreamDiskInfo)(virDomainPtr dom, + virStreamDiskStatePtr states, + unsigned int nr_states, unsigned int flags); + typedef int (*virDrvQemuDomainMonitorCommand)(virDomainPtr domain, const char *cmd, char **result, unsigned int flags); @@ -639,6 +648,8 @@ struct _virDriver { virDrvDomainSnapshotDelete domainSnapshotDelete; virDrvQemuDomainMonitorCommand qemuDomainMonitorCommand; virDrvDomainOpenConsole domainOpenConsole; + virDrvDomainStreamDisk domainStreamDisk; + virDrvDomainStreamDiskInfo domainStreamDiskInfo; }; typedef int diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index deda372..22a8cb7 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4675,6 +4675,8 @@ static virDriver esxDriver = { esxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainStreamDisk */ + NULL, /* domainStreamDiskInfo */ }; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e905302..f6f7d83 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2906,6 +2906,8 @@ static virDriver lxcDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ lxcDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainStreamDisk */ + NULL, /* domainStreamDiskInfo */ }; static virStateDriver lxcStateDriver = { diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 4af28e9..ef52e1e 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1667,6 +1667,8 @@ static virDriver openvzDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainStreamDisk */ + NULL, /* domainStreamDiskInfo */ }; int openvzRegister(void) { diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index ddbc103..5555d7b 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -4072,6 +4072,8 @@ static virDriver phypDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainStreamDisk */ + NULL, /* domainStreamDiskInfo */ }; static virStorageDriver phypStorageDriver = { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a84780b..5e2d725 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6928,6 +6928,8 @@ static virDriver qemuDriver = { qemuDomainSnapshotDelete, /* domainSnapshotDelete */ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ qemuDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainStreamDisk */ + NULL, /* domainStreamDiskInfo */ }; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 9310ddf..29c9ff6 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -11300,6 +11300,8 @@ static virDriver remote_driver = { remoteDomainSnapshotDelete, /* domainSnapshotDelete */ remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ remoteDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainStreamDisk */ + NULL, /* domainStreamDiskInfo */ }; static virNetworkDriver network_driver = { diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 17f5ad9..72929d8 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5447,6 +5447,8 @@ static virDriver testDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainStreamDisk */ + NULL, /* domainStreamDiskInfo */ }; static virNetworkDriver testNetworkDriver = { diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 33849a0..2f64f47 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2253,6 +2253,8 @@ static virDriver umlDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ umlDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainStreamDisk */ + NULL, /* domainStreamDiskInfo */ }; static int diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 0fbfba5..03286fc 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8647,6 +8647,8 @@ virDriver NAME(Driver) = { vboxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainStreamDisk */ + NULL, /* domainStreamDiskInfo */ }; virNetworkDriver NAME(NetworkDriver) = { diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index b5e416b..49d86e8 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -1007,6 +1007,8 @@ static virDriver vmwareDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainStreamDisk */ + NULL, /* domainStreamDiskInfo */ }; int diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 9f47722..516919e 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2141,6 +2141,8 @@ static virDriver xenUnifiedDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ xenUnifiedDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainStreamDisk */ + NULL, /* domainStreamDiskInfo */ }; /** -- 1.7.3 From agl at us.ibm.com Thu Apr 7 21:31:58 2011 From: agl at us.ibm.com (Adam Litke) Date: Thu, 7 Apr 2011 16:31:58 -0500 Subject: [libvirt] [PATCH 0/6] Add disk streaming API to libvirt Message-ID: <1302211924-28517-1-git-send-email-agl@us.ibm.com> I've been working with Anthony Liguori and Stefan Hajnoczi to enable data streaming to copy-on-read disk images in qemu. This work is working its way through review and I expect it to be upstream soon as part of the support for the new QED disk image format. Disk streaming is extremely useful when provisioning domains from a central repository of template images. Currently the domain must be provisioned by either: 1) copying the template image to local storage before the VM can be started or, 2) creating a qcow2 image that backs to a base image in the remote repository. Option 1 can introduce a significant delay when provisioning large disks. Option 2 introduces a permanent dependency on a remote service and increased network load to satisfy disk reads. Device streaming provides the "instant-on" benefits of option 2 without introducing a permanent dependency to the image repository. Once the VM is started, the contents of the disk can be streamed to the local image in parallel. Once streaming is finished, the domain has a complete and coherent copy of the image and no longer depends on the central image repository. Qemu will support two streaming modes: full device and single sector. Full device streaming is the easiest to use because one command will cause the whole device to be streamed as fast as possible. Single sector mode can be used if one wants to throttle streaming to reduce I/O pressure. In this mode, a management tool issues individual commands to stream single sectors. To enable this support in libvirt, I propose the following API... virDomainStreamDisk() will start or stop a full device stream or stream a single sector of a device. The behavior is controlled by setting virDomainStreamDiskFlags. When either starting or stopping a full device stream, the return value is either 0 or -1 to indicate whether the operation succeeded. For a single sector stream, a device offset is returned (or -1 on failure). This value can be used to continue streaming with a subsequent call to virDomainStreamDisk(). virDomainStreamDiskInfo() returns information about active full device streams (the device alias, current streaming position, and total size). Adam Litke (6): Add new API virDomainStreamDisk[Info] to header and drivers virDomainStreamDisk: Add public symbols to libvirt API Implement disk streaming in the qemu driver Add disk streaming support to the remote driver Add new disk streaming commands to virsh python: Add python bindings for virDomainStreamDisk[Info] b/daemon/remote.c | 96 ++++++++++++++++++++ b/daemon/remote_dispatch_args.h | 2 b/daemon/remote_dispatch_prototypes.h | 16 +++ b/daemon/remote_dispatch_ret.h | 2 b/daemon/remote_dispatch_table.h | 10 ++ b/include/libvirt/libvirt.h.in | 34 +++++++ b/python/generator.py | 4 b/python/libvirt-override-api.xml | 5 + b/python/libvirt-override.c | 46 +++++++++ b/src/driver.h | 11 ++ b/src/esx/esx_driver.c | 2 b/src/libvirt.c | 115 ++++++++++++++++++++++++ b/src/libvirt_public.syms | 5 + b/src/lxc/lxc_driver.c | 2 b/src/openvz/openvz_driver.c | 2 b/src/phyp/phyp_driver.c | 2 b/src/qemu/qemu_driver.c | 77 +++++++++++++++- b/src/qemu/qemu_monitor.c | 42 ++++++++ b/src/qemu/qemu_monitor.h | 6 + b/src/qemu/qemu_monitor_json.c | 108 ++++++++++++++++++++++ b/src/qemu/qemu_monitor_json.h | 7 + b/src/qemu/qemu_monitor_text.c | 162 ++++++++++++++++++++++++++++++++++ b/src/qemu/qemu_monitor_text.h | 8 + b/src/remote/remote_driver.c | 87 +++++++++++++++++- b/src/remote/remote_protocol.c | 63 +++++++++++++ b/src/remote/remote_protocol.h | 51 ++++++++++ b/src/remote/remote_protocol.x | 37 +++++++ b/src/test/test_driver.c | 2 b/src/uml/uml_driver.c | 2 b/src/vbox/vbox_tmpl.c | 2 b/src/vmware/vmware_driver.c | 2 b/src/xen/xen_driver.c | 2 b/tools/virsh.c | 134 +++++++++++++++++++++++++++- python/generator.py | 3 src/qemu/qemu_driver.c | 2 src/remote/remote_driver.c | 2 36 files changed, 1144 insertions(+), 9 deletions(-) From agl at us.ibm.com Thu Apr 7 21:32:01 2011 From: agl at us.ibm.com (Adam Litke) Date: Thu, 7 Apr 2011 16:32:01 -0500 Subject: [libvirt] [PATCH 3/6] Implement disk streaming in the qemu driver In-Reply-To: <1302211924-28517-1-git-send-email-agl@us.ibm.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> Message-ID: <1302211924-28517-4-git-send-email-agl@us.ibm.com> Add support for: starting/stopping full device streaming, streaming a single sector, and getting the status of streaming. These operations are done by using the 'stream' and 'info stream' qemu monitor commands. * src/qemu/qemu_driver.c src/qemu/qemu_monitor_text.[ch]: implement disk streaming by using the stream and info stream text monitor commands * src/qemu/qemu_monitor_json.[ch]: implement commands using the qmp monitor Signed-off-by: Adam Litke --- src/qemu/qemu_driver.c | 77 +++++++++++++++++++- src/qemu/qemu_monitor.c | 42 +++++++++++ src/qemu/qemu_monitor.h | 6 ++ src/qemu/qemu_monitor_json.c | 108 ++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 7 ++ src/qemu/qemu_monitor_text.c | 162 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 8 ++ 7 files changed, 408 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5e2d725..fee9e1e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6687,6 +6687,79 @@ cleanup: return ret; } +static unsigned long long +qemudDomainStreamDisk (virDomainPtr dom, const char *path, + unsigned long long offset, unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + unsigned long long ret = -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)) { + qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); + ret = qemuMonitorStreamDisk(priv->mon, path, offset, flags); + qemuDomainObjExitMonitor(vm); + } else { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + } + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + +static int +qemudDomainStreamDiskInfo (virDomainPtr dom, virStreamDiskStatePtr states, + unsigned int nr_states, + unsigned int flags ATTRIBUTE_UNUSED) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + unsigned int ret = -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)) { + qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); + ret = qemuMonitorStreamDiskInfo(priv->mon, states, nr_states); + qemuDomainObjExitMonitor(vm); + } else { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + } + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + static int qemuDomainMonitorCommand(virDomainPtr domain, const char *cmd, char **result, unsigned int flags) { @@ -6928,8 +7001,8 @@ static virDriver qemuDriver = { qemuDomainSnapshotDelete, /* domainSnapshotDelete */ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ qemuDomainOpenConsole, /* domainOpenConsole */ - NULL, /* domainStreamDisk */ - NULL, /* domainStreamDiskInfo */ + qemudDomainStreamDisk, /* domainStreamDisk */ + qemudDomainStreamDiskInfo, /* domainStreamDiskInfo */ }; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 2d28f8d..fcb8561 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2213,6 +2213,48 @@ int qemuMonitorDeleteSnapshot(qemuMonitorPtr mon, const char *name) return ret; } +unsigned long long +qemuMonitorStreamDisk(qemuMonitorPtr mon, const char *path, + unsigned long long offset, unsigned int flags) +{ + unsigned long long ret; + + VIR_DEBUG("mon=%p, path=%p, offset=%llu, flags=%u", mon, path, offset, + flags); + + if (!mon) { + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + + if (mon->json) + ret = qemuMonitorJSONStreamDisk(mon, path, offset, flags); + else + ret = qemuMonitorTextStreamDisk(mon, path, offset, flags); + return ret; +} + +int qemuMonitorStreamDiskInfo(qemuMonitorPtr mon, virStreamDiskStatePtr states, + unsigned int nr_states) +{ + int ret; + + VIR_DEBUG("mon=%p, states=%p, nr_states=%u", mon, states, nr_states); + + if (!mon) { + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + + if (mon->json) + ret = qemuMonitorJSONStreamDiskInfo(mon, states, nr_states); + else + ret = qemuMonitorTextStreamDiskInfo(mon, states, nr_states); + return ret; +} + int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply, diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c90219b..feb49dd 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -418,6 +418,12 @@ int qemuMonitorCreateSnapshot(qemuMonitorPtr mon, const char *name); int qemuMonitorLoadSnapshot(qemuMonitorPtr mon, const char *name); int qemuMonitorDeleteSnapshot(qemuMonitorPtr mon, const char *name); +unsigned long long +qemuMonitorStreamDisk(qemuMonitorPtr mon, const char *path, + unsigned long long offset, unsigned int flags); +int qemuMonitorStreamDiskInfo(qemuMonitorPtr mon, virStreamDiskStatePtr states, + unsigned int nr_states); + int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 20a78e1..84250ab 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2477,6 +2477,114 @@ cleanup: return ret; } +static int qemuMonitorJSONExtractStreamState(virJSONValuePtr reply, + virStreamDiskStatePtr state) +{ + virJSONValuePtr data; + int ret = -1; + const char *path; + unsigned long long offset, size; + + if (!(data = virJSONValueObjectGet(reply, "return"))) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("stream reply was missing return data")); + goto cleanup; + } + + if ((path = virJSONValueObjectGetString(data, "device"))) { + if (virJSONValueObjectGetNumberUlong(data, "offset", &offset) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("stream reply was missing offset")); + goto cleanup; + } + if (virJSONValueObjectGetNumberUlong(data, "len", &size) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("stream reply was missing len")); + goto cleanup; + } + + memcpy(state->path, path, strlen(path)); + state->offset = offset; + state->size = size; + ret = 1; + } else { + /* No currently active streams */ + ret = 0; + } + +cleanup: + return ret; +} + +unsigned long long +qemuMonitorJSONStreamDisk(qemuMonitorPtr mon, const char *path, + unsigned long long offset, unsigned int flags) +{ + virJSONValuePtr cmd = NULL; + virJSONValuePtr reply = NULL; + struct _virStreamDiskState state; + int rc; + unsigned long long ret = -1; + + if (flags == VIR_STREAM_DISK_START) + cmd = qemuMonitorJSONMakeCommand("stream", "b:all", "true", + "s:device", path, NULL); + else if (flags == VIR_STREAM_DISK_STOP) + cmd = qemuMonitorJSONMakeCommand("stream", "b:stop", "true", + "s:device", path, NULL); + else if (flags == VIR_STREAM_DISK_ONE) + cmd = qemuMonitorJSONMakeCommand("stream", "s:device", path, + "i:offset", offset, NULL); + else + qemuReportError(VIR_ERR_INTERNAL_ERROR, "Invalid argument for flags: " + "%u", flags); + + if (!cmd) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + goto cleanup; + + if (qemuMonitorJSONCheckError(cmd, reply) < 0) + goto cleanup; + + rc = qemuMonitorJSONExtractStreamState(reply, &state); + if (rc == 0 && (flags == VIR_STREAM_DISK_START || + flags == VIR_STREAM_DISK_STOP)) + ret = 0; + if (rc == 1 && flags == VIR_STREAM_DISK_ONE) + ret = state.offset; + +cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + +int qemuMonitorJSONStreamDiskInfo(qemuMonitorPtr mon, + virStreamDiskStatePtr states, + unsigned int nr_states) +{ + virJSONValuePtr cmd = NULL; + virJSONValuePtr reply = NULL; + int ret = -1; + + /* Qemu only supports one stream at a time */ + nr_states = 1; + + cmd = qemuMonitorJSONMakeCommand("query-stream", NULL); + if (!cmd) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + goto cleanup; + ret = qemuMonitorJSONExtractStreamState(reply, states); +cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon, const char *cmd_str, char **reply_str, diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 086f0e1..1236d47 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -199,6 +199,13 @@ int qemuMonitorJSONCreateSnapshot(qemuMonitorPtr mon, const char *name); int qemuMonitorJSONLoadSnapshot(qemuMonitorPtr mon, const char *name); int qemuMonitorJSONDeleteSnapshot(qemuMonitorPtr mon, const char *name); +unsigned long long +qemuMonitorJSONStreamDisk(qemuMonitorPtr mon, const char *path, + unsigned long long offset, unsigned int flags); +int qemuMonitorJSONStreamDiskInfo(qemuMonitorPtr mon, + virStreamDiskStatePtr states, + unsigned int nr_states); + int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon, const char *cmd_str, char **reply_str, diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 53781c8..b44d606 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -2608,6 +2608,168 @@ cleanup: return ret; } +static int qemuMonitorParseStreamInfo(char *text, + virStreamDiskStatePtr state) +{ + char *p; + unsigned long long data; + unsigned int device_len; + + memset(state->path, 0, VIR_STREAM_PATH_BUFLEN); + state->offset = 0; + state->size = 0; + + if (strstr(text, "Device '") && strstr(text, "' not found")) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Device not found")); + return -1; + } + + if (strstr(text, "expects a sector size less than device length")) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("Offset parameter is greater than the device size")); + return -1; + } + + if (strstr(text, "Device '") && strstr(text, "' is in use")) { + qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("Another streaming operation is in progress")); + return -1; + } + + if (strstr(text, "No such process")) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("There is no active stream to stop")); + return -1; + } + + if (strstr(text, "No active stream") || STREQ(text, "")) + return 0; + + if ((text = STRSKIP(text, "Streaming device ")) == NULL) + return -1; + + /* Parse the device path */ + p = strstr(text, ": Completed "); + if (!p) + return -1; + + device_len = (unsigned int)(p - text); + if (device_len >= VIR_STREAM_PATH_BUFLEN) { + qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", + "Device name is too long"); + return -1; + } + + if (sprintf((char *)&state->path, "%.*s", device_len, text) < 0) { + qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", + "Unable to store device name"); + return -1; + } + text = p + 12; /* Skip over ": Completed " */ + + /* Parse the current sector offset */ + if (virStrToLong_ull (text, &p, 10, &data)) + return -1; + state->offset = (size_t) data; + text = p; + + /* Parse the total number of sectors */ + if (!STRPREFIX(text, " of ")) + return -1; + text += 4; + if (virStrToLong_ull (text, &p, 10, &data)) + return -1; + state->size = (size_t) data; + text = p; + + /* Verify the ending */ + if (!STRPREFIX(text, " sectors")) + return -1; + + return 1; +} + +unsigned long long +qemuMonitorTextStreamDisk(qemuMonitorPtr mon, const char *path, + unsigned long long offset, unsigned int flags) +{ + char *cmd; + char *reply = NULL; + int rc; + unsigned long long ret = -1; + virStreamDiskState state; + + if (flags == VIR_STREAM_DISK_START) + rc = virAsprintf(&cmd, "stream -a %s", path); + else if (flags == VIR_STREAM_DISK_STOP) + rc = virAsprintf(&cmd, "stream -s %s", path); + else if (flags == VIR_STREAM_DISK_ONE) + rc = virAsprintf(&cmd, "stream %s %llu", path, offset); + else { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s%u", + _("invalid value for flags: "), flags); + return -1; + } + + if (rc < 0) { + virReportOOMError(); + return -1; + } + + if (qemuMonitorHMPCommand(mon, cmd, &reply)) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("failed to perform stream command '%s'"), + cmd); + goto cleanup; + } + + rc = qemuMonitorParseStreamInfo(reply, &state); + if (rc == 0 && (flags == VIR_STREAM_DISK_START || + flags == VIR_STREAM_DISK_STOP)) + ret = 0; /* A successful full disk start or stop produces no output */ + if (rc == 1 && flags == VIR_STREAM_DISK_ONE) + ret = state.offset; + +cleanup: + VIR_FREE(cmd); + VIR_FREE(reply); + return ret; +} + +int qemuMonitorTextStreamDiskInfo(qemuMonitorPtr mon, + virStreamDiskStatePtr states, + unsigned int nr_states) +{ + char *cmd; + char *reply = NULL; + int ret = -1; + + /* Qemu only supports one stream at a time */ + nr_states = 1; + + if (virAsprintf(&cmd, "info stream") < 0) { + virReportOOMError(); + return -1; + } + + if (qemuMonitorHMPCommand(mon, cmd, &reply)) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("failed to perform stream command '%s'"), + cmd); + goto cleanup; + } + + ret = qemuMonitorParseStreamInfo(reply, states); + if (ret == -1) + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("Failed to parse monitor output: '%s'"), reply); + +cleanup: + VIR_FREE(cmd); + VIR_FREE(reply); + return ret; +} + int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply) { diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 0838a2b..b048a54 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -195,6 +195,14 @@ int qemuMonitorTextCreateSnapshot(qemuMonitorPtr mon, const char *name); int qemuMonitorTextLoadSnapshot(qemuMonitorPtr mon, const char *name); int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name); +unsigned long long +qemuMonitorTextStreamDisk(qemuMonitorPtr mon, const char *path, + unsigned long long offset, unsigned int flags); +int qemuMonitorTextStreamDiskInfo(qemuMonitorPtr mon, + virStreamDiskStatePtr states, + unsigned int nr_states); + + int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply); -- 1.7.3 From agl at us.ibm.com Thu Apr 7 21:32:02 2011 From: agl at us.ibm.com (Adam Litke) Date: Thu, 7 Apr 2011 16:32:02 -0500 Subject: [libvirt] [PATCH 4/6] Add disk streaming support to the remote driver In-Reply-To: <1302211924-28517-1-git-send-email-agl@us.ibm.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> Message-ID: <1302211924-28517-5-git-send-email-agl@us.ibm.com> * src/remote/remote_protocol.x: provide defines for the new entry points * src/remote/remote_driver.c daemon/remote.c: implement the client and server side * daemon/remote_dispatch_args.h daemon/remote_dispatch_prototypes.h daemon/remote_dispatch_ret.h daemon/remote_dispatch_table.h src/remote/remote_protocol.c src/remote/remote_protocol.h: generated stubs Signed-off-by: Adam Litke --- daemon/remote.c | 96 +++++++++++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 2 + daemon/remote_dispatch_prototypes.h | 16 ++++++ daemon/remote_dispatch_ret.h | 2 + daemon/remote_dispatch_table.h | 10 ++++ src/remote/remote_driver.c | 87 +++++++++++++++++++++++++++++++- src/remote/remote_protocol.c | 63 +++++++++++++++++++++++ src/remote/remote_protocol.h | 51 ++++++++++++++++++ src/remote/remote_protocol.x | 37 +++++++++++++- 9 files changed, 361 insertions(+), 3 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index dd85ef1..87bb11b 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -7024,6 +7024,102 @@ cleanup: return rc; } +static int +remoteDispatchDomainStreamDisk (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_stream_disk_args *args, + remote_domain_stream_disk_ret *ret) +{ + virDomainPtr dom; + const char *path; + unsigned long long offset; + unsigned int flags; + int rc; + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + path = args->path; + offset = args->offset; + flags = args->flags; + + rc = virDomainStreamDisk(dom, path, offset, flags); + if (rc == (unsigned long long) -1) { + remoteDispatchConnError(rerr, conn); + return -1; + } + ret->offset = rc; + return 0; +} + +static int +remoteDispatchDomainStreamDiskInfo (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_stream_disk_info_args *args, + remote_domain_stream_disk_info_ret *ret) +{ + virDomainPtr dom; + struct _virStreamDiskState *states; + unsigned int nr_states, flags, i; + int nr_returned; + + if (args->nr_results > REMOTE_DOMAIN_STREAM_DISK_STATES_MAX) { + remoteDispatchFormatError (rerr, "%s", + _("nr_results > REMOTE_DOMAIN_STREAM_DISK_STATES_MAX")); + return -1; + } + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + nr_states = args->nr_results; + flags = args->flags; + + /* Allocate array of stats structs for making dispatch call */ + if (VIR_ALLOC_N(states, nr_states) < 0) { + virDomainFree (dom); + remoteDispatchOOMError(rerr); + return -1; + } + + nr_returned = virDomainStreamDiskInfo (dom, states, nr_states, flags); + virDomainFree (dom); + if (nr_returned < 0) { + VIR_FREE(states); + remoteDispatchConnError(rerr, conn); + return -1; + } + + /* Allocate return buffer */ + if (VIR_ALLOC_N(ret->states.states_val, nr_returned) < 0) { + VIR_FREE(states); + remoteDispatchOOMError(rerr); + return -1; + } + + /* Copy the stats into the return structure */ + ret->states.states_len = nr_returned; + for (i = 0; i < nr_returned; i++) { + ret->states.states_val[i].path.path_val = strdup(states[i].path); + ret->states.states_val[i].path.path_len = strlen(states[i].path); + ret->states.states_val[i].offset = states[i].offset; + ret->states.states_val[i].size = states[i].size; + } + VIR_FREE(states); + return 0; +} static int remoteDispatchDomainEventsRegisterAny (struct qemud_server *server ATTRIBUTE_UNUSED, diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index f9537d7..c36a836 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -178,3 +178,5 @@ remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; remote_storage_vol_upload_args val_remote_storage_vol_upload_args; remote_storage_vol_download_args val_remote_storage_vol_download_args; + remote_domain_stream_disk_args val_remote_domain_stream_disk_args; + remote_domain_stream_disk_info_args val_remote_domain_stream_disk_info_args; diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 18bf41d..de9c5bb 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -682,6 +682,22 @@ static int remoteDispatchDomainSnapshotNum( remote_error *err, remote_domain_snapshot_num_args *args, remote_domain_snapshot_num_ret *ret); +static int remoteDispatchDomainStreamDisk( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_stream_disk_args *args, + remote_domain_stream_disk_ret *ret); +static int remoteDispatchDomainStreamDiskInfo( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_stream_disk_info_args *args, + remote_domain_stream_disk_info_ret *ret); static int remoteDispatchDomainSuspend( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_ret.h b/daemon/remote_dispatch_ret.h index 114e832..2e2df6e 100644 --- a/daemon/remote_dispatch_ret.h +++ b/daemon/remote_dispatch_ret.h @@ -140,3 +140,5 @@ remote_domain_is_updated_ret val_remote_domain_is_updated_ret; remote_get_sysinfo_ret val_remote_get_sysinfo_ret; remote_domain_get_blkio_parameters_ret val_remote_domain_get_blkio_parameters_ret; + remote_domain_stream_disk_ret val_remote_domain_stream_disk_ret; + remote_domain_stream_disk_info_ret val_remote_domain_stream_disk_info_ret; diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index b39f7c2..100b274 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1052,3 +1052,13 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* DomainStreamDisk => 210 */ + .fn = (dispatch_fn) remoteDispatchDomainStreamDisk, + .args_filter = (xdrproc_t) xdr_remote_domain_stream_disk_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_stream_disk_ret, +}, +{ /* DomainStreamDiskInfo => 211 */ + .fn = (dispatch_fn) remoteDispatchDomainStreamDiskInfo, + .args_filter = (xdrproc_t) xdr_remote_domain_stream_disk_info_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_stream_disk_info_ret, +}, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 29c9ff6..95ed42f 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -9511,6 +9511,89 @@ done: return rv; } +static unsigned long long +remoteDomainStreamDisk(virDomainPtr domain, const char *path, + unsigned long long offset, unsigned int flags) +{ + unsigned long long rv = (unsigned long long) -1; + + remote_domain_stream_disk_args args; + remote_domain_stream_disk_ret ret; + struct private_data *priv = domain->conn->privateData; + + args.offset = offset; + args.flags = flags; + args.path = strdup(path); + if (args.path == NULL) { + virReportOOMError(); + return -1; + } + + remoteDriverLock(priv); + make_nonnull_domain (&args.dom, domain); + memset (&ret, 0, sizeof ret); + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_STREAM_DISK, + (xdrproc_t) xdr_remote_domain_stream_disk_args, + (char *) &args, + (xdrproc_t) xdr_remote_domain_stream_disk_ret, + (char *) &ret) == -1) + goto done; + + rv = ret.offset; + xdr_free((xdrproc_t) xdr_remote_domain_stream_disk_ret, (char *) &ret); + +done: + remoteDriverUnlock(priv); + VIR_FREE(args.path); + return rv; +} + +static int remoteDomainStreamDiskInfo(virDomainPtr domain, + virStreamDiskStatePtr states, + unsigned int nr_states, + unsigned int flags) +{ + int rv = -1; + remote_domain_stream_disk_info_args args; + remote_domain_stream_disk_info_ret ret; + struct private_data *priv = domain->conn->privateData; + unsigned int i; + + remoteDriverLock(priv); + + make_nonnull_domain (&args.dom, domain); + if (nr_states > REMOTE_DOMAIN_STREAM_DISK_STATES_MAX) { + remoteError(VIR_ERR_RPC, + _("too many disk stream stats requested: %d > %d"), + nr_states, REMOTE_DOMAIN_STREAM_DISK_STATES_MAX); + goto done; + } + args.nr_results = nr_states; + args.flags = flags; + memset (&ret, 0, sizeof ret); + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_STREAM_DISK_INFO, + (xdrproc_t) xdr_remote_domain_stream_disk_info_args, + (char *) &args, + (xdrproc_t) xdr_remote_domain_stream_disk_info_ret, + (char *) &ret) == -1) + goto done; + + for (i = 0; i < ret.states.states_len; i++) { + strncpy (states[i].path, ret.states.states_val[i].path.path_val, + VIR_STREAM_PATH_BUFLEN); + states[i].offset = ret.states.states_val[i].offset; + states[i].size = ret.states.states_val[i].size; + } + rv = ret.states.states_len; + xdr_free((xdrproc_t) xdr_remote_domain_stream_disk_info_ret, (char *) &ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + static int remoteDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID, @@ -11300,8 +11383,8 @@ static virDriver remote_driver = { remoteDomainSnapshotDelete, /* domainSnapshotDelete */ remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ remoteDomainOpenConsole, /* domainOpenConsole */ - NULL, /* domainStreamDisk */ - NULL, /* domainStreamDiskInfo */ + remoteDomainStreamDisk, /* domainStreamDisk */ + remoteDomainStreamDiskInfo, /* domainStreamDiskInfo */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 5604371..6b79767 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -1693,6 +1693,69 @@ xdr_remote_domain_set_autostart_args (XDR *xdrs, remote_domain_set_autostart_arg } bool_t +xdr_remote_domain_stream_disk_args (XDR *xdrs, remote_domain_stream_disk_args *objp) +{ + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_remote_nonnull_string (xdrs, &objp->path)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->offset)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_stream_disk_ret (XDR *xdrs, remote_domain_stream_disk_ret *objp) +{ + + if (!xdr_uint64_t (xdrs, &objp->offset)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_stream_disk_info_args (XDR *xdrs, remote_domain_stream_disk_info_args *objp) +{ + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->nr_results)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_stream_disk_state (XDR *xdrs, remote_stream_disk_state *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->path.path_val; + + if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->path.path_len, VIR_STREAM_PATH_BUFLEN, + sizeof (char), (xdrproc_t) xdr_char)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->offset)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->size)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_stream_disk_info_ret (XDR *xdrs, remote_domain_stream_disk_info_ret *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->states.states_val; + + if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->states.states_len, REMOTE_DOMAIN_STREAM_DISK_STATES_MAX, + sizeof (remote_stream_disk_state), (xdrproc_t) xdr_remote_stream_disk_state)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_num_of_networks_ret (XDR *xdrs, remote_num_of_networks_ret *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index d9bf151..88fa0e6 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -68,6 +68,7 @@ typedef remote_nonnull_string *remote_string; #define REMOTE_SECRET_VALUE_MAX 65536 #define REMOTE_SECRET_UUID_LIST_MAX 16384 #define REMOTE_CPU_BASELINE_MAX 256 +#define REMOTE_DOMAIN_STREAM_DISK_STATES_MAX VIR_STREAM_DISK_MAX_STREAMS typedef char remote_uuid[VIR_UUID_BUFLEN]; @@ -945,6 +946,44 @@ struct remote_domain_set_autostart_args { }; typedef struct remote_domain_set_autostart_args remote_domain_set_autostart_args; +struct remote_domain_stream_disk_args { + remote_nonnull_domain dom; + remote_nonnull_string path; + uint64_t offset; + u_int flags; +}; +typedef struct remote_domain_stream_disk_args remote_domain_stream_disk_args; + +struct remote_domain_stream_disk_ret { + uint64_t offset; +}; +typedef struct remote_domain_stream_disk_ret remote_domain_stream_disk_ret; + +struct remote_domain_stream_disk_info_args { + remote_nonnull_domain dom; + u_int nr_results; + u_int flags; +}; +typedef struct remote_domain_stream_disk_info_args remote_domain_stream_disk_info_args; + +struct remote_stream_disk_state { + struct { + u_int path_len; + char *path_val; + } path; + uint64_t offset; + uint64_t size; +}; +typedef struct remote_stream_disk_state remote_stream_disk_state; + +struct remote_domain_stream_disk_info_ret { + struct { + u_int states_len; + remote_stream_disk_state *states_val; + } states; +}; +typedef struct remote_domain_stream_disk_info_ret remote_domain_stream_disk_info_ret; + struct remote_num_of_networks_ret { int num; }; @@ -2413,6 +2452,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_STREAM_DISK = 210, + REMOTE_PROC_DOMAIN_STREAM_DISK_INFO = 211, }; typedef enum remote_procedure remote_procedure; @@ -2581,6 +2622,11 @@ extern bool_t xdr_remote_domain_update_device_flags_args (XDR *, remote_domain_ extern bool_t xdr_remote_domain_get_autostart_args (XDR *, remote_domain_get_autostart_args*); extern bool_t xdr_remote_domain_get_autostart_ret (XDR *, remote_domain_get_autostart_ret*); extern bool_t xdr_remote_domain_set_autostart_args (XDR *, remote_domain_set_autostart_args*); +extern bool_t xdr_remote_domain_stream_disk_args (XDR *, remote_domain_stream_disk_args*); +extern bool_t xdr_remote_domain_stream_disk_ret (XDR *, remote_domain_stream_disk_ret*); +extern bool_t xdr_remote_domain_stream_disk_info_args (XDR *, remote_domain_stream_disk_info_args*); +extern bool_t xdr_remote_stream_disk_state (XDR *, remote_stream_disk_state*); +extern bool_t xdr_remote_domain_stream_disk_info_ret (XDR *, remote_domain_stream_disk_info_ret*); extern bool_t xdr_remote_num_of_networks_ret (XDR *, remote_num_of_networks_ret*); extern bool_t xdr_remote_list_networks_args (XDR *, remote_list_networks_args*); extern bool_t xdr_remote_list_networks_ret (XDR *, remote_list_networks_ret*); @@ -2938,6 +2984,11 @@ extern bool_t xdr_remote_domain_update_device_flags_args (); extern bool_t xdr_remote_domain_get_autostart_args (); extern bool_t xdr_remote_domain_get_autostart_ret (); extern bool_t xdr_remote_domain_set_autostart_args (); +extern bool_t xdr_remote_domain_stream_disk_args (); +extern bool_t xdr_remote_domain_stream_disk_ret (); +extern bool_t xdr_remote_domain_stream_disk_info_args (); +extern bool_t xdr_remote_stream_disk_state (); +extern bool_t xdr_remote_domain_stream_disk_info_ret (); extern bool_t xdr_remote_num_of_networks_ret (); extern bool_t xdr_remote_list_networks_args (); extern bool_t xdr_remote_list_networks_ret (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 675eccd..268aec7 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -191,6 +191,11 @@ const REMOTE_SECRET_UUID_LIST_MAX = 16384; */ const REMOTE_CPU_BASELINE_MAX = 256; +/* + * Maximum number of active disk streams that can be reported + */ +const REMOTE_DOMAIN_STREAM_DISK_STATES_MAX = VIR_STREAM_DISK_MAX_STREAMS; + /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ typedef opaque remote_uuid[VIR_UUID_BUFLEN]; @@ -917,6 +922,33 @@ struct remote_domain_set_autostart_args { int autostart; }; +struct remote_domain_stream_disk_args { + remote_nonnull_domain dom; + remote_nonnull_string path; + unsigned hyper offset; + unsigned int flags; +}; + +struct remote_domain_stream_disk_ret { + unsigned hyper offset; +}; + +struct remote_domain_stream_disk_info_args { + remote_nonnull_domain dom; + unsigned int nr_results; + unsigned int flags; +}; + +struct remote_stream_disk_state { + char path; + unsigned hyper offset; + unsigned hyper size; +}; + +struct remote_domain_stream_disk_info_ret { + remote_stream_disk_state states; +}; + /* Network calls: */ struct remote_num_of_networks_ret { @@ -2176,7 +2208,10 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_STREAM_DISK = 210, + + REMOTE_PROC_DOMAIN_STREAM_DISK_INFO = 211 /* * Notice how the entries are grouped in sets of 10 ? -- 1.7.3 From eblake at redhat.com Thu Apr 7 21:47:46 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 15:47:46 -0600 Subject: [libvirt] [PATCH v2] nwfilters: support for TCP flags evaluation In-Reply-To: <4D9E14BC.4010009@linux.vnet.ibm.com> References: <4D9E14BC.4010009@linux.vnet.ibm.com> Message-ID: <4D9E3102.2030901@redhat.com> On 04/07/2011 01:47 PM, Stefan Berger wrote: > This patch adds support for the evaluation of TCP flags in nwfilters. > > It adds documentation to the web page and extends the tests as well. > Also, the nwfilter schema is extended. > > The following are some example for rules using the tcp flags: > > > > > > > > > > Signed-off-by: Stefan Berger > > --- > docs/formatnwfilter.html.in | 10 ++ > docs/schemas/nwfilter.rng | 16 ++++ > src/conf/nwfilter_conf.c | 115 > +++++++++++++++++++++++++++--- > src/conf/nwfilter_conf.h | 9 ++ > src/libvirt_private.syms | 1 > src/nwfilter/nwfilter_ebiptables_driver.c | 9 ++ > tests/nwfilterxml2xmlin/tcp-test.xml | 12 +++ > tests/nwfilterxml2xmlout/tcp-test.xml | 12 +++ > 8 files changed, 174 insertions(+), 10 deletions(-) ACK, looks reasonable to me, with one optimization nit fixed: > + int32_t mask = 0x1; > > - for (i = 0; int_map[i].val; i++) { > - if (last_attr != int_map[i].attr && > - flags & int_map[i].attr) { > - if (c >= 1) > - virBufferVSprintf(buf, "%s", sep); > - virBufferVSprintf(buf, "%s", int_map[i].val); > - c++; > + while (mask) { > + if ((mask & flags)) { > + for (i = 0; int_map[i].val; i++) { > + if (mask == int_map[i].attr) { > + if (c >= 1) > + virBufferVSprintf(buf, "%s", sep); > + virBufferVSprintf(buf, "%s", int_map[i].val); > + c++; > + } > + } > + flags ^= mask; > + if (!flags) > + break; This if condition should be after... > } this brace; otherwise, if flags == 0 on entry, then you will (needlessly) iterate through all 32 bits of mask, rather than breaking on the first iteration. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 7 22:07:36 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 16:07:36 -0600 Subject: [libvirt] [PATCH v2 6/8] virFDStream: Add option for delete file after it's opening In-Reply-To: <20110406085921.GA21112@redhat.com> References: <1302019980-14957-1-git-send-email-mprivozn@redhat.com> <1302019980-14957-7-git-send-email-mprivozn@redhat.com> <4D9B498B.7030309@redhat.com> <20110406085921.GA21112@redhat.com> Message-ID: <4D9E35A8.5060002@redhat.com> On 04/06/2011 02:59 AM, Daniel P. Berrange wrote: > On Tue, Apr 05, 2011 at 10:55:40AM -0600, Eric Blake wrote: >> On 04/05/2011 10:12 AM, Michal Privoznik wrote: >>> This is needed if we want to transfer a temporary file. If the >>> transfer is done with iohelper, we might run into a race condition, >>> where we unlink() file before iohelper is executed. >>> >>> * src/fdstream.c, src/fdstream.h, >>> src/util/iohelper.c: Add new option >>> * src/lxc/lxc_driver.c, src/qemu/qemu_driver.c, >>> src/storage/storage_driver.c, src/uml/uml_driver.c, >>> src/xen/xen_driver.c: Expand existing function calls >> >> I'm not convinced about this commit. We should instead be fixing >> iohelper to receive its file by fd inheritance, so that it doesn't have >> to open() in the first place. Then you don't need iohelper to worry >> about unlink(). > > My intention was that iohelper could also do uid/gid changes > in the future to cope with opening files on root squashing > NFS. For that we'd want it to be doing the open, not libvirtd Even if the parent process does virFileOpenAs? I think we've already got all the uid/gid changes covered in the parent process, without having to offload that into the child and coordinate a second open(); and even if we don't, fchmod/fchown are better than a second open()/chmod()/chown(). -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 7 22:12:51 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 16:12:51 -0600 Subject: [libvirt] [BUG] Managed save qemu state gets deleted after failed resume In-Reply-To: <4D95FD4B.9080008@redhat.com> References: <201103301024.50356.hahn@univention.de> <4D95FD4B.9080008@redhat.com> Message-ID: <4D9E36E3.6060000@redhat.com> On 04/01/2011 10:28 AM, Eric Blake wrote: > On 03/30/2011 02:24 AM, Philipp Hahn wrote: >> Hello, >> >> I haven't had time to provide a fix, but still want you to inform you about a >> bug: If resuming a saved VM fails with Qemu-0.14, the managed save state >> file /var/lib/libvirt/qemu/save/$VM.save is still deleted. I think it would >> be better to only delete the state after an successful resume. > >> >> This issue is tracked in our (German) bug-tracker at >> > > Thanks for the link. Should be fixed now (modulo anyone approving my followup patch to tweak the 'man virsh' wording): https://www.redhat.com/archives/libvir-list/2011-April/msg00405.html -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jfehlig at novell.com Thu Apr 7 22:13:33 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Thu, 7 Apr 2011 16:13:33 -0600 Subject: [libvirt] [PATCH] build: Install libxenlight log dir Message-ID: <1302214413-22855-1-git-send-email-jfehlig@novell.com> Add $localstatedir/log/libvirt/libxl when building libxenlight driver --- src/Makefile.am | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 9b54679..3649106 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1275,6 +1275,7 @@ endif if WITH_LIBXL $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/libxl" $(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/libxl" + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/log/libvirt/libxl" endif if WITH_UML $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/uml" @@ -1316,6 +1317,7 @@ endif if WITH_LIBXL rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/libxl" ||: rmdir "$(DESTDIR)$(localstatedir)/run/libvirt/libxl" ||: + rmdir "$(DESTDIR)$(localstatedir)/log/libvirt/libxl" ||: endif if WITH_UML rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/uml" ||: -- 1.7.3.1 From eblake at redhat.com Thu Apr 7 22:22:23 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 16:22:23 -0600 Subject: [libvirt] [PATCH] setmaxmem: remove the code to invoke virDomainSetMemory in cmdSetmaxmem In-Reply-To: <20110317105625.GD24807@redhat.com> References: <4D807BD1.5030208@jp.fujitsu.com> <20110317105625.GD24807@redhat.com> Message-ID: <4D9E391F.6030805@redhat.com> On 03/17/2011 04:56 AM, Daniel P. Berrange wrote: > On Wed, Mar 16, 2011 at 05:58:57PM +0900, Taku Izumi wrote: >> >> When the new maximum memory size becomes less than the current memory size, >> I think it is not the libvirt client but the each driver that decides the behavior >> (reject the operation or shrink the current memory size). >> > > ACK Pushed. Oh dear - we missed this one for 0.9.0, even though it was acked in plenty of time. I'm starting to agree with Laine's proposal that having a mailing-list based helper engine that parses out known pending patch series would be helpful to avoid losing these in the flurry of a busy inbox. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 7 22:23:36 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 16:23:36 -0600 Subject: [libvirt] [PATCH] build: Install libxenlight log dir In-Reply-To: <1302214413-22855-1-git-send-email-jfehlig@novell.com> References: <1302214413-22855-1-git-send-email-jfehlig@novell.com> Message-ID: <4D9E3968.2060202@redhat.com> On 04/07/2011 04:13 PM, Jim Fehlig wrote: > Add $localstatedir/log/libvirt/libxl when building libxenlight driver > --- > src/Makefile.am | 2 ++ > 1 files changed, 2 insertions(+), 0 deletions(-) > > diff --git a/src/Makefile.am b/src/Makefile.am > index 9b54679..3649106 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -1275,6 +1275,7 @@ endif > if WITH_LIBXL > $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/libxl" > $(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/libxl" > + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/log/libvirt/libxl" ACK. But does this also need any specfile changes as a followup? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 7 22:34:39 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 16:34:39 -0600 Subject: [libvirt] [PATCH 2/4] maxmem: introduces VIR_DOMAIN_MEM_MAXIMUM flag In-Reply-To: <4D94116A.4050003@jp.fujitsu.com> References: <4D940EEE.2090603@jp.fujitsu.com> <4D94116A.4050003@jp.fujitsu.com> Message-ID: <4D9E3BFF.6020903@redhat.com> On 03/30/2011 11:30 PM, Taku Izumi wrote: > > This patch introduces VIR_DOMAIN_MEM_MAXIMUM flag. > > Signed-off-by: Taku Izumi > --- > include/libvirt/libvirt.h.in | 1 + > src/libvirt.c | 2 ++ > 2 files changed, 3 insertions(+) > > Index: libvirt/include/libvirt/libvirt.h.in > =================================================================== > --- libvirt.orig/include/libvirt/libvirt.h.in > +++ libvirt/include/libvirt/libvirt.h.in > @@ -857,6 +857,7 @@ typedef enum { > VIR_DOMAIN_MEM_CURRENT= 0, /* affect current domain */ This part of the patch doesn't exist. Am I missing some other patch series that should have been applied first? [goes back and re-reads - yep, you said so in mail 0/4]. OK, I'll review that first. But I've now applied 1/4 from this series from when it was first acked. > VIR_DOMAIN_MEM_LIVE = (1 << 0), /* affect active domain */ > VIR_DOMAIN_MEM_CONFIG = (1 << 1), /* affect next boot */ > + VIR_DOMAIN_MEM_MAXIMUM= (1 << 2), /* affect Max rather than current */ I'll probably reindent things to put a space before = and line up the other lines, but that's trivial. > Index: libvirt/src/libvirt.c > =================================================================== > --- libvirt.orig/src/libvirt.c > +++ libvirt/src/libvirt.c > @@ -2869,6 +2869,8 @@ error: > * the XML description on the domain. If neither flag is specified > * (=VIR_DOMAIN_MEM_CURRENT), behavior is different depending on hypervisor. > * > + * If @flags incluces VIR_DOMAIN_MEM_MAXIMUM, > + * Incomplete sentence. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jfehlig at novell.com Thu Apr 7 22:33:43 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Thu, 07 Apr 2011 16:33:43 -0600 Subject: [libvirt] [PATCH] build: Install libxenlight log dir In-Reply-To: <4D9E3968.2060202@redhat.com> References: <1302214413-22855-1-git-send-email-jfehlig@novell.com> <4D9E3968.2060202@redhat.com> Message-ID: <4D9E3BC7.3090502@novell.com> Eric Blake wrote: > On 04/07/2011 04:13 PM, Jim Fehlig wrote: > >> Add $localstatedir/log/libvirt/libxl when building libxenlight driver >> --- >> src/Makefile.am | 2 ++ >> 1 files changed, 2 insertions(+), 0 deletions(-) >> >> diff --git a/src/Makefile.am b/src/Makefile.am >> index 9b54679..3649106 100644 >> --- a/src/Makefile.am >> +++ b/src/Makefile.am >> @@ -1275,6 +1275,7 @@ endif >> if WITH_LIBXL >> $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/libxl" >> $(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/libxl" >> + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/log/libvirt/libxl" >> > > ACK. But does this also need any specfile changes as a followup? > It's already included in the spec file %if %{with_libxl} %dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/libxl/ %endif I'll push this one shortly. Regards, Jim From eblake at redhat.com Thu Apr 7 23:23:41 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 17:23:41 -0600 Subject: [libvirt] [PATCH 1/3] setmem: introduce VIR_DOMAIN_MEM_CURRENT flag In-Reply-To: <4D898969.5050308@jp.fujitsu.com> References: <4D8987A5.30203@jp.fujitsu.com> <4D898969.5050308@jp.fujitsu.com> Message-ID: <4D9E477D.9070509@redhat.com> On 03/22/2011 11:47 PM, Taku Izumi wrote: > > This patch introduces VIR_DOMAIN_MEM_CURRENT flag and > modifies virDomainSetMemoryFlags function to support it. > > > /* Memory size modification flags. */ > typedef enum { > + VIR_DOMAIN_MEM_CURRENT= 0, /* affect current domain */ I tweaked the spacing here. > VIR_DOMAIN_MEM_LIVE = (1 << 0), /* affect active domain */ > VIR_DOMAIN_MEM_CONFIG = (1 << 1), /* affect next boot */ > } virDomainMemoryModFlags; > Index: libvirt/src/libvirt.c > =================================================================== > --- libvirt.orig/src/libvirt.c > +++ libvirt/src/libvirt.c > @@ -2862,10 +2862,12 @@ error: > * to Domain0 i.e. the domain where the application runs. > * This funcation may requires privileged access to the hypervisor. Oops, let's fix that typo in "funcation" while we're here. > * > - * @flags must include VIR_DOMAIN_MEM_LIVE to affect a running > - * domain (which may fail if domain is not active), or > - * VIR_DOMAIN_MEM_CONFIG to affect the next boot via the XML > - * description of the domain. Both flags may be set. > + * @flags may include VIR_DOMAIN_MEM_LIVE or VIR_DOMAIN_MEM_CONFIG. > + * Both flags may be set. If VIR_DOMAIN_MEM_LIVE is set, the change affects > + * a running domain and may fail if domain is not active. > + * If VIR_DOMAIN_MEM_CONFIG is set, the change affects the next boot via > + * the XML description on the domain. If neither flag is specified > + * (=VIR_DOMAIN_MEM_CURRENT), behavior is different depending on hypervisor. I tweaked this wording a bit. > * > * Returns 0 in case of success, -1 in case of failure. > */ > @@ -2891,8 +2893,7 @@ virDomainSetMemoryFlags(virDomainPtr dom > goto error; > } > > - if (memory < 4096 || > - (flags & (VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_CONFIG)) == 0) { > + if (memory < 4096) { > virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); > goto error; > } Here's what I squashed in before pushing: diff --git i/include/libvirt/libvirt.h.in w/include/libvirt/libvirt.h.in index c9129bc..d765412 100644 --- i/include/libvirt/libvirt.h.in +++ w/include/libvirt/libvirt.h.in @@ -854,9 +854,9 @@ int virDomainGetMemoryParameters(virDomainPtr domain, /* Memory size modification flags. */ typedef enum { - VIR_DOMAIN_MEM_CURRENT= 0, /* affect current domain */ - VIR_DOMAIN_MEM_LIVE = (1 << 0), /* affect active domain */ - VIR_DOMAIN_MEM_CONFIG = (1 << 1), /* affect next boot */ + VIR_DOMAIN_MEM_CURRENT = 0, /* affect current domain state */ + VIR_DOMAIN_MEM_LIVE = (1 << 0), /* affect active domain */ + VIR_DOMAIN_MEM_CONFIG = (1 << 1), /* affect next boot */ } virDomainMemoryModFlags; diff --git i/src/libvirt.c w/src/libvirt.c index ee11643..dde4bd4 100644 --- i/src/libvirt.c +++ w/src/libvirt.c @@ -2822,14 +2822,17 @@ error: * Dynamically change the target amount of physical memory allocated to a * domain. If domain is NULL, then this change the amount of memory reserved * to Domain0 i.e. the domain where the application runs. - * This funcation may requires privileged access to the hypervisor. + * This function may requires privileged access to the hypervisor. * * @flags may include VIR_DOMAIN_MEM_LIVE or VIR_DOMAIN_MEM_CONFIG. * Both flags may be set. If VIR_DOMAIN_MEM_LIVE is set, the change affects - * a running domain and may fail if domain is not active. - * If VIR_DOMAIN_MEM_CONFIG is set, the change affects the next boot via - * the XML description on the domain. If neither flag is specified - * (=VIR_DOMAIN_MEM_CURRENT), behavior is different depending on hypervisor. + * a running domain and will fail if domain is not active. + * If VIR_DOMAIN_MEM_CONFIG is set, the change affects persistent state, + * and will fail for transient domains. If neither flag is specified + * (that is, @flags is VIR_DOMAIN_MEM_CURRENT), then an inactive domain + * modifies persistent setup, while an active domain is hypervisor-dependent + * on whether just live or both live and persistent state is changed. + * Not all hypervisors can support all flag combinations. * * Returns 0 in case of success, -1 in case of failure. */ -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 7 23:23:45 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 17:23:45 -0600 Subject: [libvirt] [PATCH 2/3] setmem: add virDomainSetMemroyFlags(, , VIR_DOMAIN_MEM_CURRENT) support to qemu driver In-Reply-To: <4D8989A8.8050609@jp.fujitsu.com> References: <4D8987A5.30203@jp.fujitsu.com> <4D8989A8.8050609@jp.fujitsu.com> Message-ID: <4D9E4781.8040506@redhat.com> Long subject line. 'git shortlog -20' should give you a feel for how to shorten this; I went with: setmem: add VIR_DOMAIN_MEM_CURRENT support to qemu On 03/22/2011 11:48 PM, Taku Izumi wrote: > > This patch adds virDomainSetMemroyFlags(,,VIR_DOMAIN_MEM_CURRENT) support s/Memroy/Memory/ > code to qemu driver. > > Signed-off-by: Taku Izumi > --- > src/qemu/qemu_driver.c | 18 +++++++++++------- > 1 file changed, 11 insertions(+), 7 deletions(-) > > Index: libvirt/src/qemu/qemu_driver.c > =================================================================== > --- libvirt.orig/src/qemu/qemu_driver.c > +++ libvirt/src/qemu/qemu_driver.c > @@ -1575,16 +1575,11 @@ static int qemudDomainSetMemoryFlags(vir > qemuDomainObjPrivatePtr priv; > virDomainObjPtr vm; > virDomainDefPtr persistentDef = NULL; > - int ret = -1, r; > + int ret = -1, r, isActive; Hmm, based on the name, I would have guessed isActive is better as a bool. > > virCheckFlags(VIR_DOMAIN_MEM_LIVE | > VIR_DOMAIN_MEM_CONFIG, -1); > > - if ((flags & (VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_CONFIG)) == 0) { > - qemuReportError(VIR_ERR_INVALID_ARG, > - _("invalid flag combination: (0x%x)"), flags); > - } > - > qemuDriverLock(driver); > vm = virDomainFindByUUID(&driver->domains, dom->uuid); > qemuDriverUnlock(driver); > @@ -1605,7 +1600,16 @@ static int qemudDomainSetMemoryFlags(vir > if (qemuDomainObjBeginJob(vm) < 0) > goto cleanup; > > - if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_MEM_LIVE)) { > + isActive = virDomainObjIsActive(vm); Surprisingly, virDomainObjIsActive returns int instead of bool. Well, no longer :) > + > + if (flags == VIR_DOMAIN_MEM_CURRENT) { > + if (isActive) > + flags = VIR_DOMAIN_MEM_LIVE; > + else > + flags = VIR_DOMAIN_MEM_CONFIG; > + } > + > + if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) { > qemuReportError(VIR_ERR_OPERATION_INVALID, > "%s", _("domain is not running")); > goto endjob; I squashed this in, then pushed: diff --git i/src/conf/domain_conf.h w/src/conf/domain_conf.h index 10e73cb..95bd11e 100644 --- i/src/conf/domain_conf.h +++ w/src/conf/domain_conf.h @@ -1172,7 +1172,7 @@ struct _virDomainObjList { virHashTable *objs; }; -static inline int +static inline bool virDomainObjIsActive(virDomainObjPtr dom) { return dom->def->id != -1; diff --git i/src/qemu/qemu_driver.c w/src/qemu/qemu_driver.c index c0e706c..6a0bf24 100644 --- i/src/qemu/qemu_driver.c +++ w/src/qemu/qemu_driver.c @@ -1576,7 +1576,8 @@ static int qemudDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, qemuDomainObjPrivatePtr priv; virDomainObjPtr vm; virDomainDefPtr persistentDef = NULL; - int ret = -1, r, isActive; + int ret = -1, r; + bool isActive; virCheckFlags(VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_CONFIG, -1); -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 7 23:23:49 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 07 Apr 2011 17:23:49 -0600 Subject: [libvirt] [PATCH 3/3] setmem: add --current option to virsh setmem command In-Reply-To: <4D8989E8.2090804@jp.fujitsu.com> References: <4D8987A5.30203@jp.fujitsu.com> <4D8989E8.2090804@jp.fujitsu.com> Message-ID: <4D9E4785.1020800@redhat.com> On 03/22/2011 11:49 PM, Taku Izumi wrote: > > This patch adds the new option (--current) to the "virsh setmem" command. > When --current option is specified, it affects a "current" domain. > The word "current" denotes that if a domain is running, it affects > a running domain only; otherwise it affects a persistent domain. > > Signed-off-by: Taku Izumi > --- > tools/virsh.c | 20 +++++++++++++++----- > tools/virsh.pod | 7 +++++-- All right - you remembered to update the docs at the same time! > + if (current) { > + if (live || config) { > + vshError(ctl, "%s", _("--current must be specified exclusively")); > + return FALSE; > + } > + flags = VIR_DOMAIN_MEM_CURRENT; > + } else { > + if (config) > + flags |= VIR_DOMAIN_MEM_CONFIG; > if (live) > flags |= VIR_DOMAIN_MEM_LIVE; > + /* neither option is specified */ > + if (!live && !config) > + flags = -1; > } > > if (!vshConnectionUsability(ctl, ctl->conn)) > @@ -2972,7 +2982,7 @@ cmdSetmem(vshControl *ctl, const vshCmd > return FALSE; > } > > - if (!flags) { > + if (flags == -1) { > if (virDomainSetMemory(dom, kilobytes) != 0) { Looks reasonable. > +++ libvirt/tools/virsh.pod > @@ -578,12 +578,15 @@ Therefore, -1 is a useful shorthand for > B: The weight and cap parameters are defined only for the > XEN_CREDIT scheduler and are now I. > > -=item B I B optional I<--config> I<--live> > +=item B I B optional I<--config> I<--live> I<--current> I wrapped this at 80 columns. > > Change the memory allocation for a guest domain. > If I<--live> is specified, perform a memory balloon of a running guest. > If I<--config> is specified, affect the next boot of a persistent guest. > -Both flags may be given. If neither flag is given, I<--live> is assumed. > +If I<--current> is specified, affect a current guest. I tweaked this to 'current guest state (active or persistent)'. > +Both I<--live> and I<--config> flags may be given, but I<--current> is > +exclusive. If neither flag is specified, behavior is different depending > +on hypervisor. ACK and applied. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From stefanb at linux.vnet.ibm.com Thu Apr 7 23:32:36 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Thu, 07 Apr 2011 19:32:36 -0400 Subject: [libvirt] [PATCH v2] nwfilters: support for TCP flags evaluation In-Reply-To: <4D9E3102.2030901@redhat.com> References: <4D9E14BC.4010009@linux.vnet.ibm.com> <4D9E3102.2030901@redhat.com> Message-ID: <4D9E4994.2060107@linux.vnet.ibm.com> On 04/07/2011 05:47 PM, Eric Blake wrote: > On 04/07/2011 01:47 PM, Stefan Berger wrote: >> This patch adds support for the evaluation of TCP flags in nwfilters. >> >> It adds documentation to the web page and extends the tests as well. >> Also, the nwfilter schema is extended. >> >> The following are some example for rules using the tcp flags: >> >> >> >> >> >> >> >> >> >> Signed-off-by: Stefan Berger >> >> --- >> docs/formatnwfilter.html.in | 10 ++ >> docs/schemas/nwfilter.rng | 16 ++++ >> src/conf/nwfilter_conf.c | 115 >> +++++++++++++++++++++++++++--- >> src/conf/nwfilter_conf.h | 9 ++ >> src/libvirt_private.syms | 1 >> src/nwfilter/nwfilter_ebiptables_driver.c | 9 ++ >> tests/nwfilterxml2xmlin/tcp-test.xml | 12 +++ >> tests/nwfilterxml2xmlout/tcp-test.xml | 12 +++ >> 8 files changed, 174 insertions(+), 10 deletions(-) > ACK, looks reasonable to me, with one optimization nit fixed: > >> + int32_t mask = 0x1; >> >> - for (i = 0; int_map[i].val; i++) { >> - if (last_attr != int_map[i].attr&& >> - flags& int_map[i].attr) { >> - if (c>= 1) >> - virBufferVSprintf(buf, "%s", sep); >> - virBufferVSprintf(buf, "%s", int_map[i].val); >> - c++; >> + while (mask) { >> + if ((mask& flags)) { >> + for (i = 0; int_map[i].val; i++) { >> + if (mask == int_map[i].attr) { >> + if (c>= 1) >> + virBufferVSprintf(buf, "%s", sep); >> + virBufferVSprintf(buf, "%s", int_map[i].val); >> + c++; >> + } >> + } >> + flags ^= mask; >> + if (!flags) >> + break; > This if condition should be after... > >> } > this brace; otherwise, if flags == 0 on entry, then you will > (needlessly) iterate through all 32 bits of mask, rather than breaking > on the first iteration. > Excellent! I'll modify and push. Stefan From stefanb at linux.vnet.ibm.com Fri Apr 8 00:33:31 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Thu, 07 Apr 2011 20:33:31 -0400 Subject: [libvirt] [TCK][PATCH] nwfilter: test support for TCP flags evaluation In-Reply-To: <20110401162418.GM29510@redhat.com> References: <4D95FA9C.4070706@linux.vnet.ibm.com> <20110401162418.GM29510@redhat.com> Message-ID: <4D9E57DB.7070203@linux.vnet.ibm.com> On 04/01/2011 12:24 PM, Daniel P. Berrange wrote: > On Fri, Apr 01, 2011 at 12:17:32PM -0400, Stefan Berger wrote: >> This patch extends an existing test with test cases for the TCP flags. >> >> Signed-off-by: Stefan Berger >> > ACK Pushed Stefan > Daniel From jyang at redhat.com Fri Apr 8 01:09:35 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 08 Apr 2011 09:09:35 +0800 Subject: [libvirt] [PATCH v5] qemu: Remove the managed state file only if restoring succeeded In-Reply-To: <4D9DD0AB.8030202@redhat.com> References: <1302143512-23422-1-git-send-email-jyang@redhat.com> <4D9DD0AB.8030202@redhat.com> Message-ID: <4D9E604F.5080404@redhat.com> ? 2011?04?07? 22:56, Eric Blake ??: > On 04/06/2011 08:31 PM, Osier Yang wrote: >> managed_save = qemuDomainManagedSavePath(driver, vm); >> + >> + if (!managed_save) >> + goto cleanup; >> + >> if ((managed_save)&& (virFileExists(managed_save))) { > > This second check for non-NULL managed_save is now redundant. Argh, it my fault. > >> +++ b/tools/virsh.pod >> @@ -546,7 +546,11 @@ I parameter in the domain's XML definition. >> >> =item B I >> >> -Restores a domain from an B state file. See I for more info. >> +Restores a domain from an B state file. See I for more info. > > Sorry for not noticing sooner, but we could do some grammar cleanups. > > Does this look like a reasonable followup? > > diff --git i/src/qemu/qemu_driver.c w/src/qemu/qemu_driver.c > index a84780b..0734a76 100644 > --- i/src/qemu/qemu_driver.c > +++ w/src/qemu/qemu_driver.c > @@ -3430,7 +3430,7 @@ static int qemudDomainObjStart(virConnectPtr conn, > if (!managed_save) > goto cleanup; > > - if ((managed_save)&& (virFileExists(managed_save))) { > + if (virFileExists(managed_save)) { > ret = qemuDomainObjRestore(conn, driver, vm, managed_save); > > if ((ret == 0)&& (unlink(managed_save)< 0)) > diff --git i/tools/virsh.pod w/tools/virsh.pod > index 6319373..9ce6905 100644 > --- i/tools/virsh.pod > +++ w/tools/virsh.pod > @@ -546,11 +546,12 @@ I parameter in the domain's XML definition. > > =item B I > > -Restores a domain from an B state file. See I for > more info. > +Restores a domain from a B state file. See I for more > info. > > B: To avoid corrupting file system contents within the domain, you > -should not reuse the saved state file to B unless you are > convinced > -with reverting the domain to the previous state. > +should not reuse the saved state file for a second B unless > +you have also reverted all storage volumes back to the same contents > +as when the state file was created. Doesn't reuse implies the "second, third, ...." B ? :) But anyway, it looks more clear, good to me. > > =item B I I > > > From hutao at cn.fujitsu.com Fri Apr 8 03:23:47 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Fri, 8 Apr 2011 11:23:47 +0800 Subject: [libvirt] [PATCH 3/6] use virObject to manage reference-count of virDomainObj In-Reply-To: <20110407093303.GB3669@redhat.com> References: <20110407093303.GB3669@redhat.com> Message-ID: <20110408032347.GG7711@localhost.localdomain> On Thu, Apr 07, 2011 at 10:33:03AM +0100, Daniel P. Berrange wrote: > On Wed, Apr 06, 2011 at 03:19:51PM +0800, Hu Tao wrote: > > This patch also eliminates a dead-lock bug in > > qemuDomainObjBeginJobWithDriver: if virCondWaitUntil() timeouts, the > > thread tries to acquire qemu driver lock while holding virDomainObj > > lock. > > --- > > src/conf/domain_conf.c | 56 ++++---- > > src/conf/domain_conf.h | 6 +- > > src/openvz/openvz_conf.c | 8 +- > > src/qemu/qemu_domain.c | 32 ++--- > > src/qemu/qemu_domain.h | 2 +- > > src/qemu/qemu_driver.c | 304 ++++++++++++++++++++------------------------- > > src/qemu/qemu_migration.c | 45 +++---- > > src/qemu/qemu_process.c | 33 ++--- > > src/vmware/vmware_conf.c | 2 +- > > 9 files changed, 215 insertions(+), 273 deletions(-) > > > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > > index 90a1317..fc76a00 100644 > > --- a/src/conf/domain_conf.c > > +++ b/src/conf/domain_conf.c > > @@ -47,6 +47,7 @@ > > #include "storage_file.h" > > #include "files.h" > > #include "bitmap.h" > > +#include "virobject.h" > > > > #define VIR_FROM_THIS VIR_FROM_DOMAIN > > > > @@ -395,9 +396,7 @@ static void > > virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED) > > { > > virDomainObjPtr obj = payload; > > - virDomainObjLock(obj); > > - if (virDomainObjUnref(obj) > 0) > > - virDomainObjUnlock(obj); > > + virDomainObjUnref(obj); > > } > > > > int virDomainObjListInit(virDomainObjListPtr doms) > > @@ -437,7 +436,7 @@ virDomainObjPtr virDomainFindByID(const virDomainObjListPtr doms, > > virDomainObjPtr obj; > > obj = virHashSearch(doms->objs, virDomainObjListSearchID, &id); > > if (obj) > > - virDomainObjLock(obj); > > + virDomainObjRef(obj); > > return obj; > > } > > > > @@ -452,7 +451,7 @@ virDomainObjPtr virDomainFindByUUID(const virDomainObjListPtr doms, > > > > obj = virHashLookup(doms->objs, uuidstr); > > if (obj) > > - virDomainObjLock(obj); > > + virDomainObjRef(obj); > > return obj; > > } > > > > @@ -476,7 +475,7 @@ virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms, > > virDomainObjPtr obj; > > obj = virHashSearch(doms->objs, virDomainObjListSearchName, name); > > if (obj) > > - virDomainObjLock(obj); > > + virDomainObjRef(obj); > > return obj; > > } > > This is a major change in semantics, which makes pretty much > every single caller non-thread safe, unless the callers are > all changed todo virDomainObjLock immediately after calling > this. So I don't really see the point in this - it just means > more code duplication. If we do this: obj = virHashSearch(doms->objs, virDomainObjListSearchName, name); if (obj) virDomainObjLock(obj); return obj; And at the meantime another thread removes the same obj from doms->objs and frees it, than we are accessing a freed obj. lock doesn't help prevent object from being freed. > > > > > @@ -967,6 +966,12 @@ static void virDomainObjFree(virDomainObjPtr dom) > > { > > if (!dom) > > return; > > + virDomainObjUnref(dom); > > +} > > + > > +static void doDomainObjFree(virObjectPtr obj) > > +{ > > + virDomainObjPtr dom = (virDomainObjPtr)obj; > > > > VIR_DEBUG("obj=%p", dom); > > virDomainDefFree(dom->def); > > @@ -984,21 +989,13 @@ static void virDomainObjFree(virDomainObjPtr dom) > > > > void virDomainObjRef(virDomainObjPtr dom) > > { > > - dom->refs++; > > - VIR_DEBUG("obj=%p refs=%d", dom, dom->refs); > > + virObjectRef(&dom->obj); > > } > > > > > > -int virDomainObjUnref(virDomainObjPtr dom) > > +void virDomainObjUnref(virDomainObjPtr dom) > > { > > - dom->refs--; > > - VIR_DEBUG("obj=%p refs=%d", dom, dom->refs); > > - if (dom->refs == 0) { > > - virDomainObjUnlock(dom); > > - virDomainObjFree(dom); > > - return 0; > > - } > > - return dom->refs; > > + virObjectUnref(&dom->obj); > > } > > > > static virDomainObjPtr virDomainObjNew(virCapsPtr caps) > > @@ -1010,6 +1007,11 @@ static virDomainObjPtr virDomainObjNew(virCapsPtr caps) > > return NULL; > > } > > > > + if (virObjectInit(&domain->obj, doDomainObjFree)) { > > + VIR_FREE(domain); > > + return NULL; > > + } > > + > > if (caps->privateDataAllocFunc && > > !(domain->privateData = (caps->privateDataAllocFunc)())) { > > virReportOOMError(); > > @@ -1027,9 +1029,7 @@ static virDomainObjPtr virDomainObjNew(virCapsPtr caps) > > return NULL; > > } > > > > - virDomainObjLock(domain); > > domain->state = VIR_DOMAIN_SHUTOFF; > > - domain->refs = 1; > > > > virDomainSnapshotObjListInit(&domain->snapshots); > > > > @@ -1075,8 +1075,10 @@ virDomainObjPtr virDomainAssignDef(virCapsPtr caps, > > domain->def = def; > > > > virUUIDFormat(def->uuid, uuidstr); > > + virDomainObjRef(domain); > > if (virHashAddEntry(doms->objs, uuidstr, domain) < 0) { > > - VIR_FREE(domain); > > + virDomainObjUnref(domain); > > + virDomainObjFree(domain); > > return NULL; > > } > > Simiarly here, you're now requiring all callers to manually obtain > a lock. That is the desired result, lock right before do read/write and unlock it as soon as possible. > > > @@ -1239,39 +1243,57 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, > > > > qemuDriverLock(driver); > > if (!(def = virDomainDefParseString(driver->caps, xml, > > - VIR_DOMAIN_XML_INACTIVE))) > > + VIR_DOMAIN_XML_INACTIVE))) { > > + qemuDriverUnlock(driver); > > goto cleanup; > > + } > > > > - if (virSecurityManagerVerify(driver->securityManager, def) < 0) > > + if (virSecurityManagerVerify(driver->securityManager, def) < 0) { > > + qemuDriverUnlock(driver); > > goto cleanup; > > + } > > > > - if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) > > + if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) { > > + qemuDriverUnlock(driver); > > goto cleanup; > > + } > > > > - if (qemudCanonicalizeMachine(driver, def) < 0) > > + if (qemudCanonicalizeMachine(driver, def) < 0) { > > + qemuDriverUnlock(driver); > > goto cleanup; > > + } > > > > - if (qemuDomainAssignPCIAddresses(def) < 0) > > + if (qemuDomainAssignPCIAddresses(def) < 0) { > > + qemuDriverUnlock(driver); > > goto cleanup; > > + } > > > > if (!(vm = virDomainAssignDef(driver->caps, > > &driver->domains, > > - def, false))) > > + def, false))) { > > + qemuDriverUnlock(driver); > > goto cleanup; > > + } > > + > > + qemuDriverUnlock(driver); > > driver is now unlocked.... > > > > > def = NULL; > > > > - if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) > > + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) { > > + virDomainObjUnref(vm); > > ...but this method *requires* driver to be locked. > > > goto cleanup; /* XXXX free the 'vm' we created ? */ > > + } > > > > if (qemuProcessStart(conn, driver, vm, NULL, > > (flags & VIR_DOMAIN_START_PAUSED) != 0, > > -1, NULL, VIR_VM_OP_CREATE) < 0) { > > qemuAuditDomainStart(vm, "booted", false); > > ...and this method writes to 'driver', so it is now unsafe. > > > - if (qemuDomainObjEndJob(vm) > 0) > > - virDomainRemoveInactive(&driver->domains, > > - vm); > > - vm = NULL; > > + qemuDomainObjEndJob(vm); > > + qemuDriverLock(driver); > > + virDomainRemoveInactive(&driver->domains, > > + vm); > > + qemuDriverUnlock(driver); > > + virDomainObjUnref(vm); > > goto cleanup; > > } > > > > @@ -1283,17 +1305,13 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, > > dom = virGetDomain(conn, vm->def->name, vm->def->uuid); > > if (dom) dom->id = vm->def->id; > > > > - if (vm && > > - qemuDomainObjEndJob(vm) == 0) > > - vm = NULL; > > + qemuDomainObjEndJob(vm); > > + virDomainObjUnref(vm); > > > > cleanup: > > virDomainDefFree(def); > > - if (vm) > > - virDomainObjUnlock(vm); > > if (event) > > qemuDomainEventQueue(driver, event); > > - qemuDriverUnlock(driver); > > return dom; > > } > > > And all the usage of 'vm' in this method is now completely > unlocked and unsafe. > > > > > > @@ -1307,13 +1325,14 @@ static int qemudDomainSuspend(virDomainPtr dom) { > > > > 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; > > + return -1; > > } > > if (!virDomainObjIsActive(vm)) { > > qemuReportError(VIR_ERR_OPERATION_INVALID, > > @@ -1354,16 +1373,12 @@ static int qemudDomainSuspend(virDomainPtr dom) { > > } > > > > endjob: > > - if (qemuDomainObjEndJob(vm) == 0) > > - vm = NULL; > > + qemuDomainObjEndJob(vm); > > > > cleanup: > > - if (vm) > > - virDomainObjUnlock(vm); > > - > > + virDomainObjUnref(vm); > > if (event) > > qemuDomainEventQueue(driver, event); > > - qemuDriverUnlock(driver); > > return ret; > > } > > Also now completely unsafe since 'vm' is never locked while > making changes to it. Yes. Will improve qemudDomainSuspend. > > [cut rest of patch] > > I don't see how any of this patch is threadsafe now that virtually > no methods are acquiring the 'vm' lock. qemuDomainObjBeginJob does acquire vm lock. > > > Daniel > -- > |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| > |: http://libvirt.org -o- http://virt-manager.org :| > |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| > |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From wency at cn.fujitsu.com Fri Apr 8 03:26:47 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Fri, 08 Apr 2011 11:26:47 +0800 Subject: [libvirt] [PATCH] do not build libvirt_iohelper when building without libvirtd Message-ID: <4D9E8077.1080003@cn.fujitsu.com> The libexec program libvirt_iohelper is only for libvirtd. If we build rpm without libvirtd, we will receive the following messages: Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/wency/rpmbuild/BUILDROOT/libvirt-0.9.0-1.el6.x86_64 error: Installed (but unpackaged) file(s) found: /usr/libexec/libvirt_iohelper --- src/Makefile.am | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 3649106..dce866e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1183,6 +1183,7 @@ EXTRA_DIST += $(LIBVIRT_QEMU_SYMBOL_FILE) libexec_PROGRAMS = +if WITH_LIBVIRTD libexec_PROGRAMS += libvirt_iohelper libvirt_iohelper_SOURCES = $(UTIL_IO_HELPER_SOURCES) libvirt_iohelper_LDFLAGS = $(WARN_LDFLAGS) $(AM_LDFLAGS) @@ -1191,6 +1192,7 @@ libvirt_iohelper_LDADD = \ ../gnulib/lib/libgnu.la libvirt_iohelper_CFLAGS = $(AM_CFLAGS) +endif if WITH_STORAGE_DISK if WITH_LIBVIRTD -- 1.7.1 From hutao at cn.fujitsu.com Fri Apr 8 03:07:44 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Fri, 8 Apr 2011 11:07:44 +0800 Subject: [libvirt] [PATCH 4/6] qemu: use virObject to manage reference-counting for qemu monitor In-Reply-To: <20110407093834.GC3669@redhat.com> References: <821a47bc81d57d652997fde0dec0010e3cad75d5.1302069479.git.hutao@cn.fujitsu.com> <20110407093834.GC3669@redhat.com> Message-ID: <20110408030744.GF7711@localhost.localdomain> On Thu, Apr 07, 2011 at 10:38:34AM +0100, Daniel P. Berrange wrote: > On Wed, Apr 06, 2011 at 03:19:55PM +0800, Hu Tao wrote: > > --- > > src/qemu/qemu_domain.c | 30 ++----------- > > src/qemu/qemu_migration.c | 2 - > > src/qemu/qemu_monitor.c | 109 ++++++++++++++++++++++++-------------------- > > src/qemu/qemu_monitor.h | 4 +- > > src/qemu/qemu_process.c | 32 +++++++------- > > 5 files changed, 81 insertions(+), 96 deletions(-) > > > > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > > index 3a3c953..d11dc5f 100644 > > --- a/src/qemu/qemu_domain.c > > +++ b/src/qemu/qemu_domain.c > > @@ -560,9 +560,8 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) > > { > > qemuDomainObjPrivatePtr priv = obj->privateData; > > > > - qemuMonitorLock(priv->mon); > > - qemuMonitorRef(priv->mon); > > virDomainObjUnlock(obj); > > + qemuMonitorLock(priv->mon); > > } > > > > > > @@ -573,18 +572,9 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) > > void qemuDomainObjExitMonitor(virDomainObjPtr obj) > > { > > qemuDomainObjPrivatePtr priv = obj->privateData; > > - int refs; > > - > > - refs = qemuMonitorUnref(priv->mon); > > - > > - if (refs > 0) > > - qemuMonitorUnlock(priv->mon); > > > > + qemuMonitorUnlock(priv->mon); > > virDomainObjLock(obj); > > - > > - if (refs == 0) { > > - priv->mon = NULL; > > - } > > } > > > > > > @@ -601,10 +591,8 @@ void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, > > { > > qemuDomainObjPrivatePtr priv = obj->privateData; > > > > - qemuMonitorLock(priv->mon); > > - qemuMonitorRef(priv->mon); > > virDomainObjUnlock(obj); > > - qemuDriverUnlock(driver); > > + qemuMonitorLock(priv->mon); > > } > > > > > > @@ -617,19 +605,9 @@ void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, > > virDomainObjPtr obj) > > { > > qemuDomainObjPrivatePtr priv = obj->privateData; > > - int refs; > > - > > - refs = qemuMonitorUnref(priv->mon); > > - > > - if (refs > 0) > > - qemuMonitorUnlock(priv->mon); > > > > - qemuDriverLock(driver); > > + qemuMonitorUnlock(priv->mon); > > virDomainObjLock(obj); > > - > > - if (refs == 0) { > > - priv->mon = NULL; > > - } > > } > > This means that the 'driver' lock is now whenever any QEMU > monitor command is runing, which blocks the entire driver. qemuDomainObjEnterMonitorWithDriver is now called without holding qemu driver lock. > > > > > void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver, > > diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c > > index 462e6be..6af2e24 100644 > > --- a/src/qemu/qemu_migration.c > > +++ b/src/qemu/qemu_migration.c > > @@ -224,11 +224,9 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) > > } > > > > virDomainObjUnlock(vm); > > - qemuDriverUnlock(driver); > > > > nanosleep(&ts, NULL); > > > > - qemuDriverLock(driver); > > virDomainObjLock(vm); > > } > > Holding the 'driver' lock while sleeping blocks the entire > QEMU driver. Now qemuMigrationWaitForCompletion should be called without holding qemu driver lock. > > > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > > index 244b22a..4b9087f 100644 > > --- a/src/qemu/qemu_process.c > > +++ b/src/qemu/qemu_process.c > > @@ -107,7 +107,6 @@ qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > > > > VIR_DEBUG("Received EOF on %p '%s'", vm, vm->def->name); > > > > - qemuDriverLock(driver); > > virDomainObjLock(vm); > > > > if (!virDomainObjIsActive(vm)) { > > @@ -133,15 +132,17 @@ qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > > qemuProcessStop(driver, vm, 0); > > qemuAuditDomainStop(vm, hasError ? "failed" : "shutdown"); > > > > - if (!vm->persistent) > > + if (!vm->persistent) { > > + qemuDriverLock(driver); > > virDomainRemoveInactive(&driver->domains, vm); > > - else > > - virDomainObjUnlock(vm); > > + qemuDriverUnlock(driver); > > + } > > + > > + virDomainObjUnlock(vm); > > > > if (event) { > > qemuDomainEventQueue(driver, event); > > } > > - qemuDriverUnlock(driver); > > } > > This violates the lock ordering rules. The 'driver' lock *must* be > obtained *before* any 'vm' lock is held. Excepting for introducing virObject for reference-counting, this series also simplifies the usage of lock: if you want to read/write qemu driver data, it is enough to first acquire qemu driver lock only; if you want to read/write virDomainObj data, it is enough to first acquire virDomainObj lock only; same for others. And we'd better to avoid acquiring two locks at the same time. So yes, the code here is problematic, it should be ideally like this: virDomainObjLock(vm); if (!vm->persistent) { lock_hashtable(doms); /* hashtable's own lock to protect itself */ virDomainRemoveInactive(doms, vm); unlock_hashtable(doms); } virDomainObjUnlock(vm); But it lacks hashtable lock, how about change the code like this: virDomainObjLock(vm); persistent = vm->persistent; virDomainObjUnlock(vm); /* chances that others change vm->persistent and we remove vm mistakenly :( */ if (!persistent) { qemuDriverLock(driver); virDomainRemoveInactive(doms, vm); qemuDriverUnlock(driver); } Or is there a better way? > > Now we have some places in the code which do > > lock(vm) > lock(driver) > > and other places which do > > lock(driver) > lock(vm) > > so 2 threads can trivially deadlock waiting for each other > > Daniel > -- > |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| > |: http://libvirt.org -o- http://virt-manager.org :| > |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| > |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From izumi.taku at jp.fujitsu.com Fri Apr 8 04:55:22 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Fri, 08 Apr 2011 13:55:22 +0900 Subject: [libvirt] [PATCH v2 0/3] configure inactive domains' maximum memory size Message-ID: <4D9E953A.4070102@jp.fujitsu.com> Hi all, This patchset enables us to configure inactive domain's maximum memory size. v1 -> v2: - recreate based on 0.9.0 - fix some typo *[PATCH 1/3] maxmem: introduces VIR_DOMAIN_MEM_MAXIMUM flag *[PATCH 2/3] maxmem: implement virDomainSetMaxMemory API of the qemu driver *[PATCH 3/3] setmaxmem: add the new options to "virsh setmaxmem" command Best regards, Taku Izumi From izumi.taku at jp.fujitsu.com Fri Apr 8 05:07:27 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Fri, 08 Apr 2011 14:07:27 +0900 Subject: [libvirt] [PATCH 1/3] maxmem: introduces VIR_DOMAIN_MEM_MAXIMUM flag In-Reply-To: <4D9E953A.4070102@jp.fujitsu.com> References: <4D9E953A.4070102@jp.fujitsu.com> Message-ID: <4D9E980F.5090904@jp.fujitsu.com> This patch introduces VIR_DOMAIN_MEM_MAXIMUM flag. Signed-off-by: Taku Izumi --- include/libvirt/libvirt.h.in | 1 + src/libvirt.c | 2 ++ 2 files changed, 3 insertions(+) Index: libvirt/include/libvirt/libvirt.h.in =================================================================== --- libvirt.orig/include/libvirt/libvirt.h.in +++ libvirt/include/libvirt/libvirt.h.in @@ -857,6 +857,7 @@ typedef enum { VIR_DOMAIN_MEM_CURRENT = 0, /* affect current domain state */ VIR_DOMAIN_MEM_LIVE = (1 << 0), /* affect active domain */ VIR_DOMAIN_MEM_CONFIG = (1 << 1), /* affect next boot */ + VIR_DOMAIN_MEM_MAXIMUM = (1 << 2), /* affect Max rather than current */ } virDomainMemoryModFlags; Index: libvirt/src/libvirt.c =================================================================== --- libvirt.orig/src/libvirt.c +++ libvirt/src/libvirt.c @@ -2832,6 +2832,8 @@ error: * (that is, @flags is VIR_DOMAIN_MEM_CURRENT), then an inactive domain * modifies persistent setup, while an active domain is hypervisor-dependent * on whether just live or both live and persistent state is changed. + * If VIR_DOMAIN_MEM_MAXIMUM is set, the change affects domain's maximum memory + * size rather than current memory size. * Not all hypervisors can support all flag combinations. * * Returns 0 in case of success, -1 in case of failure. From izumi.taku at jp.fujitsu.com Fri Apr 8 05:08:13 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Fri, 08 Apr 2011 14:08:13 +0900 Subject: [libvirt] [PATCH 2/3] maxmem: implement virDomainSetMaxMemory API of the qemu driver In-Reply-To: <4D9E953A.4070102@jp.fujitsu.com> References: <4D9E953A.4070102@jp.fujitsu.com> Message-ID: <4D9E983D.4070100@jp.fujitsu.com> This patch implements the code to support virDomainSetMaxMemory API, and to support VIR_DOMAIN_MEM_MAXIMUM flag in qemudDomainSetMemoryFlags function. As a result, we can change the maximum memory size of inactive QEMU guests. Signed-off-by: Taku Izumi --- src/qemu/qemu_driver.c | 81 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 24 deletions(-) Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -1580,7 +1580,8 @@ static int qemudDomainSetMemoryFlags(vir bool isActive; virCheckFlags(VIR_DOMAIN_MEM_LIVE | - VIR_DOMAIN_MEM_CONFIG, -1); + VIR_DOMAIN_MEM_CONFIG | + VIR_DOMAIN_MEM_MAXIMUM, -1); qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -1593,12 +1594,6 @@ static int qemudDomainSetMemoryFlags(vir goto cleanup; } - if (newmem > vm->def->mem.max_balloon) { - qemuReportError(VIR_ERR_INVALID_ARG, - "%s", _("cannot set memory higher than max memory")); - goto cleanup; - } - if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; @@ -1610,6 +1605,12 @@ static int qemudDomainSetMemoryFlags(vir else flags = VIR_DOMAIN_MEM_CONFIG; } + if (flags == VIR_DOMAIN_MEM_MAXIMUM) { + if (isActive) + flags = VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_MAXIMUM; + else + flags = VIR_DOMAIN_MEM_CONFIG | VIR_DOMAIN_MEM_MAXIMUM; + } if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) { qemuReportError(VIR_ERR_OPERATION_INVALID, @@ -1627,27 +1628,54 @@ static int qemudDomainSetMemoryFlags(vir goto endjob; } - if (flags & VIR_DOMAIN_MEM_LIVE) { - priv = vm->privateData; - qemuDomainObjEnterMonitor(vm); - r = qemuMonitorSetBalloon(priv->mon, newmem); - qemuDomainObjExitMonitor(vm); - qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", r == 1); - if (r < 0) - goto endjob; + if (flags & VIR_DOMAIN_MEM_MAXIMUM) { + /* resize the maximum memory */ - /* Lack of balloon support is a fatal error */ - if (r == 0) { + if (flags & VIR_DOMAIN_MEM_LIVE) { qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot set memory of an active domain")); + _("cannot resize the maximum memory on an active domain")); goto endjob; } - } - if (flags& VIR_DOMAIN_MEM_CONFIG) { - persistentDef->mem.cur_balloon = newmem; - ret = virDomainSaveConfig(driver->configDir, persistentDef); - goto endjob; + if (flags & VIR_DOMAIN_MEM_CONFIG) { + persistentDef->mem.max_balloon = newmem; + if (persistentDef->mem.cur_balloon > newmem) + persistentDef->mem.cur_balloon = newmem; + ret = virDomainSaveConfig(driver->configDir, persistentDef); + goto endjob; + } + + } else { + /* resize the current memory */ + + if (newmem > vm->def->mem.max_balloon) { + qemuReportError(VIR_ERR_INVALID_ARG, + "%s", _("cannot set memory higher than max memory")); + goto endjob; + } + + if (flags & VIR_DOMAIN_MEM_LIVE) { + priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); + r = qemuMonitorSetBalloon(priv->mon, newmem); + qemuDomainObjExitMonitor(vm); + qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", r == 1); + if (r < 0) + goto endjob; + + /* Lack of balloon support is a fatal error */ + if (r == 0) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot set memory of an active domain")); + goto endjob; + } + } + + if (flags & VIR_DOMAIN_MEM_CONFIG) { + persistentDef->mem.cur_balloon = newmem; + ret = virDomainSaveConfig(driver->configDir, persistentDef); + goto endjob; + } } ret = 0; @@ -1665,6 +1693,11 @@ static int qemudDomainSetMemory(virDomai return qemudDomainSetMemoryFlags(dom, newmem, VIR_DOMAIN_MEM_LIVE); } +static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) { + return qemudDomainSetMemoryFlags(dom, memory, + VIR_DOMAIN_MEM_MAXIMUM | VIR_DOMAIN_MEM_LIVE); +} + static int qemudDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { struct qemud_driver *driver = dom->conn->privateData; @@ -6849,7 +6882,7 @@ static virDriver qemuDriver = { qemudDomainDestroy, /* domainDestroy */ qemudDomainGetOSType, /* domainGetOSType */ qemudDomainGetMaxMemory, /* domainGetMaxMemory */ - NULL, /* domainSetMaxMemory */ + qemudDomainSetMaxMemory, /* domainSetMaxMemory */ qemudDomainSetMemory, /* domainSetMemory */ qemudDomainSetMemoryFlags, /* domainSetMemoryFlags */ qemuDomainSetMemoryParameters, /* domainSetMemoryParameters */ From izumi.taku at jp.fujitsu.com Fri Apr 8 05:08:52 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Fri, 08 Apr 2011 14:08:52 +0900 Subject: [libvirt] [PATCH 3/3] setmaxmem: add the new options to "virsh setmaxmem" command In-Reply-To: <4D9E953A.4070102@jp.fujitsu.com> References: <4D9E953A.4070102@jp.fujitsu.com> Message-ID: <4D9E9864.1060805@jp.fujitsu.com> This patch adds the new options (--live, --config, and --current) to "virsh setmaxmem" command. The behavior of above options is the same as that of "virsh setmem". When the --config option is specified, a modofication is effective for the persistent domain, while the --live option is specified, a modification is effective for an active domain. The --current option is specified, it affects a current domain. Signed-off-by: Taku Izumi --- tools/virsh.c | 35 ++++++++++++++++++++++++++++++++--- tools/virsh.pod | 16 ++++++++++------ 2 files changed, 42 insertions(+), 9 deletions(-) Index: libvirt/tools/virsh.c =================================================================== --- libvirt.orig/tools/virsh.c +++ libvirt/tools/virsh.c @@ -3020,6 +3020,9 @@ static const vshCmdInfo info_setmaxmem[] static const vshCmdOptDef opts_setmaxmem[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, {"kilobytes", VSH_OT_INT, VSH_OFLAG_REQ, N_("maximum memory limit in kilobytes")}, + {"config", VSH_OT_BOOL, 0, N_("affect next boot")}, + {"live", VSH_OT_BOOL, 0, N_("affect running domain")}, + {"current", VSH_OT_BOOL, 0, N_("affect current domain")}, {NULL, 0, 0, NULL} }; @@ -3030,6 +3033,25 @@ cmdSetmaxmem(vshControl *ctl, const vshC virDomainInfo info; int kilobytes = 0; int ret = TRUE; + int config = vshCommandOptBool(cmd, "config"); + int live = vshCommandOptBool(cmd, "live"); + int current = vshCommandOptBool(cmd, "current"); + int flags = VIR_DOMAIN_MEM_MAXIMUM; + + if (current) { + if(live || config) { + vshError(ctl, "%s", _("--current must be specified exclusively")); + return FALSE; + } + } else { + if (config) + flags |= VIR_DOMAIN_MEM_CONFIG; + if (live) + flags |= VIR_DOMAIN_MEM_LIVE; + /* neither option is specified */ + if (!live && !config) + flags = -1; + } if (!vshConnectionUsability(ctl, ctl->conn)) return FALSE; @@ -3054,9 +3076,16 @@ cmdSetmaxmem(vshControl *ctl, const vshC return FALSE; } - if (virDomainSetMaxMemory(dom, kilobytes) != 0) { - vshError(ctl, "%s", _("Unable to change MaxMemorySize")); - ret = FALSE; + if (flags == -1) { + if (virDomainSetMaxMemory(dom, kilobytes) != 0) { + vshError(ctl, "%s", _("Unable to change MaxMemorySize")); + ret = FALSE; + } + } else { + if (virDomainSetMemoryFlags(dom, kilobytes, flags) < 0) { + vshError(ctl, "%s", _("Unable to change MaxMemorySize")); + ret = FALSE; + } } virDomainFree(dom); Index: libvirt/tools/virsh.pod =================================================================== --- libvirt.orig/tools/virsh.pod +++ libvirt/tools/virsh.pod @@ -601,12 +601,18 @@ rounds the parameter up unless the kB ar For Xen, you can only adjust the memory of a running domain if the domain is paravirtualized or running the PV balloon driver. -=item B I B +=item B I B optional I<--config> I<--live> +I<--current> -Change the maximum memory allocation limit for an inactive guest domain. +Change the maximum memory allocation limit for a guest domain. +If I<--live> is specified, affect a running guest. +If I<--config> is specified, affect the next boot of a persistent guest. +If I<--current> is specified, affect the current guest state. +Both I<--live> and I<--current> flags may be given, but I<--current> is +exclusive. If no flag is specified, behavior is different depending +on hypervisor. -This command works for at least the Xen and vSphere/ESX hypervisors, -but not for QEMU/KVM. +This command works for at least the Xen, QEMU/KVM and vSphere/ESX hypervisors. Some hypervisors require a larger granularity than kilobytes, rounding up requests that are not an even multiple of the desired amount. vSphere/ESX @@ -614,8 +620,6 @@ is one of these, requiring the parameter vSphere/ESX, 263168 (257MB) would be rounded up because it's not a multiple of 4MB, while 266240 (260MB) is valid without rounding. -Note, to change the maximum memory allocation for a QEMU/KVM guest domain, -use the virsh B command instead to update its XML element. =item B I optional I<--hard-limit> B optional I<--soft-limit> B optional I<--swap-hard-limit> From izumi.taku at jp.fujitsu.com Fri Apr 8 05:14:07 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Fri, 08 Apr 2011 14:14:07 +0900 Subject: [libvirt] [PATCH v2 0/4] RFC: vcpupin: configure inactive domains' CPU affinity setting Message-ID: <4D9E999F.5070505@jp.fujitsu.com> Hi all, This patchset enables us to configure inactive domains' CPU affinity setting. The basic technique is the same as that of "virsh setmem" command. => http://www.redhat.com/archives/libvir-list/2011-March/msg00013.html v1 -> v2: - recreate based on 0.9.0 - add "CURRENT" mode *[PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) *[PATCH 2/4] vcpupin: implement the code to address the new API in the qemu driver *[PATCH 3/4] vcpupin: implement the remote protocol to address the new API *[PATCH 4/4] vcpupin: add the new options to "virsh vcpupin" command Best regards, Taku Izumi From izumi.taku at jp.fujitsu.com Fri Apr 8 05:20:31 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Fri, 08 Apr 2011 14:20:31 +0900 Subject: [libvirt] [PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) In-Reply-To: <4D9E999F.5070505@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> Message-ID: <4D9E9B1F.1040500@jp.fujitsu.com> This patch introduces a new libvirt API (virDomainPinVcpuFlags) Signed-off-by: Taku Izumi --- include/libvirt/libvirt.h.in | 6 +++ src/driver.h | 7 +++ src/libvirt.c | 83 +++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 4 ++ src/lxc/lxc_driver.c | 1 src/openvz/openvz_driver.c | 1 src/phyp/phyp_driver.c | 1 src/qemu/qemu_driver.c | 1 src/remote/remote_driver.c | 1 src/test/test_driver.c | 1 src/uml/uml_driver.c | 1 src/vbox/vbox_tmpl.c | 1 src/vmware/vmware_driver.c | 1 src/xen/xen_driver.c | 1 src/xenapi/xenapi_driver.c | 1 15 files changed, 111 insertions(+) Index: libvirt/include/libvirt/libvirt.h.in =================================================================== --- libvirt.orig/include/libvirt/libvirt.h.in +++ libvirt/include/libvirt/libvirt.h.in @@ -1017,6 +1017,7 @@ typedef virVcpuInfo *virVcpuInfoPtr; /* Flags for controlling virtual CPU hot-plugging. */ typedef enum { + VIR_DOMAIN_VCPU_CURRENT = 0, /* Affect current domain state */ /* Must choose at least one of these two bits; SetVcpus can choose both */ VIR_DOMAIN_VCPU_LIVE = (1 << 0), /* Affect active domain */ VIR_DOMAIN_VCPU_CONFIG = (1 << 1), /* Affect next boot */ @@ -1037,6 +1038,11 @@ int virDomainPinVcpu unsigned int vcpu, unsigned char *cpumap, int maplen); +int virDomainPinVcpuFlags (virDomainPtr domain, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags); /** * VIR_USE_CPU: Index: libvirt/src/driver.h =================================================================== --- libvirt.orig/src/driver.h +++ libvirt/src/driver.h @@ -220,6 +220,12 @@ typedef int unsigned char *cpumap, int maplen); typedef int + (*virDrvDomainPinVcpuFlags) (virDomainPtr domain, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags); +typedef int (*virDrvDomainGetVcpus) (virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, @@ -570,6 +576,7 @@ struct _virDriver { virDrvDomainSetVcpusFlags domainSetVcpusFlags; virDrvDomainGetVcpusFlags domainGetVcpusFlags; virDrvDomainPinVcpu domainPinVcpu; + virDrvDomainPinVcpuFlags domainPinVcpuFlags; virDrvDomainGetVcpus domainGetVcpus; virDrvDomainGetMaxVcpus domainGetMaxVcpus; virDrvDomainGetSecurityLabel domainGetSecurityLabel; Index: libvirt/src/libvirt.c =================================================================== --- libvirt.orig/src/libvirt.c +++ libvirt/src/libvirt.c @@ -5461,6 +5461,89 @@ error: } /** + * virDomainPinVcpuFlags: + * @domain: pointer to domain object, or NULL for Domain0 + * @vcpu: virtual CPU number + * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN) + * Each bit set to 1 means that corresponding CPU is usable. + * Bytes are stored in little-endian order: CPU0-7, 8-15... + * In each byte, lowest CPU number is least significant bit. + * @maplen: number of bytes in cpumap, from 1 up to size of CPU map in + * underlying virtualization system (Xen...). + * If maplen < size, missing bytes are set to zero. + * If maplen > size, failure code is returned. + * @flags: an OR'ed subset of virDomainVcpuFlags + * + * Dynamically change the real CPUs which can be allocated to a virtual CPU. + * This function requires privileged access to the hypervisor. + * + * @flags may include VIR_DOMAIN_VCPU_LIVE or VIR_DOMAIN_VCPU_CONFIG. + * Both flags may be set, but VIR_DOMAIN_VCPU_MAXIMUM cannot be set. + * If VIR_DOMAIN_VCPU_LIVE is set, the change affects a running domain + * and may fail if domain is not alive. + * If VIR_DOMAIN_VCPU_CONFIG is set, the change affects persistent state, + * and will fail for transient domains. + * If neither flag is specified (tha is, @flags is VIR_DOMAIN_VCPU_CURRENT), + * then an inactive domain modifies persistent setup, while an active domain + * is hypervisor-dependent on whether just live or both live and persistent + * state is changed. + * Not all hypervisors can support all flag combinations. + * + * Returns 0 in case of success, -1 in case of failure. + * + */ +int +virDomainPinVcpuFlags(virDomainPtr domain, unsigned int vcpu, + unsigned char *cpumap, int maplen, unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "vcpu=%u, cpumap=%p, maplen=%d flags=%u", + vcpu, cpumap, maplen, flags); + + virResetLastError(); + + if (flags & ~(VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if ((vcpu > 32000) || (cpumap == NULL) || (maplen < 1)) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainPinVcpuFlags) { + int ret; + ret = conn->driver->domainPinVcpuFlags (domain, vcpu, cpumap, maplen, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; + +} + +/** * virDomainGetVcpus: * @domain: pointer to domain object, or NULL for Domain0 * @info: pointer to an array of virVcpuInfo structures (OUT) Index: libvirt/src/libvirt_public.syms =================================================================== --- libvirt.orig/src/libvirt_public.syms +++ libvirt/src/libvirt_public.syms @@ -436,4 +436,8 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8; +LIBVIRT_0.9.1 { + virDomainPinVcpuFlags; +} LIBVIRT_0.9.0; + # .... define new API here using predicted next version number .... Index: libvirt/src/lxc/lxc_driver.c =================================================================== --- libvirt.orig/src/lxc/lxc_driver.c +++ libvirt/src/lxc/lxc_driver.c @@ -2837,6 +2837,7 @@ static virDriver lxcDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/openvz/openvz_driver.c =================================================================== --- libvirt.orig/src/openvz/openvz_driver.c +++ libvirt/src/openvz/openvz_driver.c @@ -1598,6 +1598,7 @@ static virDriver openvzDriver = { openvzDomainSetVcpusFlags, /* domainSetVcpusFlags */ openvzDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/phyp/phyp_driver.c =================================================================== --- libvirt.orig/src/phyp/phyp_driver.c +++ libvirt/src/phyp/phyp_driver.c @@ -4003,6 +4003,7 @@ static virDriver phypDriver = { phypDomainSetVcpusFlags, /* domainSetVcpusFlags */ phypDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ phypGetLparCPUMAX, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -6864,6 +6864,7 @@ static virDriver qemuDriver = { qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ qemudDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ qemudDomainGetVcpus, /* domainGetVcpus */ qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */ Index: libvirt/src/remote/remote_driver.c =================================================================== --- libvirt.orig/src/remote/remote_driver.c +++ libvirt/src/remote/remote_driver.c @@ -11231,6 +11231,7 @@ static virDriver remote_driver = { remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ remoteDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ remoteDomainGetVcpus, /* domainGetVcpus */ remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */ remoteDomainGetSecurityLabel, /* domainGetSecurityLabel */ Index: libvirt/src/test/test_driver.c =================================================================== --- libvirt.orig/src/test/test_driver.c +++ libvirt/src/test/test_driver.c @@ -5378,6 +5378,7 @@ static virDriver testDriver = { testDomainSetVcpusFlags, /* domainSetVcpusFlags */ testDomainGetVcpusFlags, /* domainGetVcpusFlags */ testDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ testDomainGetVcpus, /* domainGetVcpus */ testDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/uml/uml_driver.c =================================================================== --- libvirt.orig/src/uml/uml_driver.c +++ libvirt/src/uml/uml_driver.c @@ -2184,6 +2184,7 @@ static virDriver umlDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/vbox/vbox_tmpl.c =================================================================== --- libvirt.orig/src/vbox/vbox_tmpl.c +++ libvirt/src/vbox/vbox_tmpl.c @@ -8568,6 +8568,7 @@ virDriver NAME(Driver) = { vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */ vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ vboxDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/vmware/vmware_driver.c =================================================================== --- libvirt.orig/src/vmware/vmware_driver.c +++ libvirt/src/vmware/vmware_driver.c @@ -938,6 +938,7 @@ static virDriver vmwareDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/xen/xen_driver.c =================================================================== --- libvirt.orig/src/xen/xen_driver.c +++ libvirt/src/xen/xen_driver.c @@ -2072,6 +2072,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenUnifiedDomainGetVcpusFlags, /* domainGetVcpusFlags */ xenUnifiedDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ xenUnifiedDomainGetVcpus, /* domainGetVcpus */ xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/xenapi/xenapi_driver.c =================================================================== --- libvirt.orig/src/xenapi/xenapi_driver.c +++ libvirt/src/xenapi/xenapi_driver.c @@ -1820,6 +1820,7 @@ static virDriver xenapiDriver = { xenapiDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenapiDomainGetVcpusFlags, /* domainGetVcpusFlags */ xenapiDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ xenapiDomainGetVcpus, /* domainGetVcpus */ xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ From izumi.taku at jp.fujitsu.com Fri Apr 8 05:21:37 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Fri, 08 Apr 2011 14:21:37 +0900 Subject: [libvirt] [PATCH 2/4] vcpupin: implement the code to address the new API in the qemu driver In-Reply-To: <4D9E999F.5070505@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> Message-ID: <4D9E9B61.9090504@jp.fujitsu.com> This patch implements the code to address the new API (virDomainPinVcpuFlags) in the qemu driver. Signed-off-by: Taku Izumi --- src/qemu/qemu_driver.c | 94 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 22 deletions(-) Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -2630,17 +2630,24 @@ qemudDomainSetVcpus(virDomainPtr dom, un static int -qemudDomainPinVcpu(virDomainPtr dom, - unsigned int vcpu, - unsigned char *cpumap, - int maplen) { +qemudDomainPinVcpuFlags(virDomainPtr dom, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags) { + struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; + virDomainDefPtr persistentDef = NULL; int maxcpu, hostcpus; virNodeInfo nodeinfo; int ret = -1; + bool isActive; qemuDomainObjPrivatePtr priv; + virCheckFlags(VIR_DOMAIN_VCPU_LIVE | + VIR_DOMAIN_VCPU_CONFIG, -1); + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); qemuDriverUnlock(driver); @@ -2653,7 +2660,15 @@ qemudDomainPinVcpu(virDomainPtr dom, goto cleanup; } - if (!virDomainObjIsActive(vm)) { + isActive = virDomainObjIsActive(vm); + if (flags == VIR_DOMAIN_VCPU_CURRENT) { + if (isActive) + flags = VIR_DOMAIN_VCPU_LIVE; + else + flags = VIR_DOMAIN_VCPU_CONFIG; + } + + if (!isActive && (flags & VIR_DOMAIN_VCPU_LIVE)) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",_("cannot pin vcpus on an inactive domain")); goto cleanup; @@ -2668,27 +2683,54 @@ qemudDomainPinVcpu(virDomainPtr dom, goto cleanup; } - if (nodeGetInfo(dom->conn, &nodeinfo) < 0) - goto cleanup; + if (flags & VIR_DOMAIN_VCPU_CONFIG) { + if (!vm->persistent) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot change persistent config of a transient domain")); + goto cleanup; + } + if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm))) + goto cleanup; + } - hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo); - maxcpu = maplen * 8; - if (maxcpu > hostcpus) - maxcpu = hostcpus; + if (flags & VIR_DOMAIN_VCPU_LIVE) { - if (priv->vcpupids != NULL) { - if (virProcessInfoSetAffinity(priv->vcpupids[vcpu], - cpumap, maplen, maxcpu) < 0) + if (nodeGetInfo(dom->conn, &nodeinfo) < 0) goto cleanup; - } else { - qemuReportError(VIR_ERR_NO_SUPPORT, - "%s", _("cpu affinity is not supported")); - goto cleanup; + + hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo); + maxcpu = maplen * 8; + if (maxcpu > hostcpus) + maxcpu = hostcpus; + + if (priv->vcpupids != NULL) { + if (virProcessInfoSetAffinity(priv->vcpupids[vcpu], + cpumap, maplen, maxcpu) < 0) + goto cleanup; + } else { + qemuReportError(VIR_ERR_NO_SUPPORT, + "%s", _("cpu affinity is not supported")); + goto cleanup; + } + + if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("failed to update or add vcpupin xml of a running domain")); + goto cleanup; + } + } - if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("failed to update or add vcpupin xml")); + if (flags & VIR_DOMAIN_VCPU_CONFIG) { + + if (virDomainVcpupinAdd(persistentDef, cpumap, maplen, vcpu) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("failed to update or add vcpupin xml of a persistent domain")); + goto cleanup; + } + ret = virDomainSaveConfig(driver->configDir, persistentDef); goto cleanup; } @@ -2701,6 +2743,14 @@ cleanup: } static int +qemudDomainPinVcpu(virDomainPtr dom, + unsigned int vcpu, + unsigned char *cpumap, + int maplen) { + return qemudDomainPinVcpuFlags(dom, vcpu, cpumap, maplen, VIR_DOMAIN_VCPU_LIVE); +} + +static int qemudDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo, @@ -6864,7 +6914,7 @@ static virDriver qemuDriver = { qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ qemudDomainPinVcpu, /* domainPinVcpu */ - NULL, /* domainPinVcpuFlags */ + qemudDomainPinVcpuFlags, /* domainPinVcpuFlags */ qemudDomainGetVcpus, /* domainGetVcpus */ qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */ From izumi.taku at jp.fujitsu.com Fri Apr 8 05:22:15 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Fri, 08 Apr 2011 14:22:15 +0900 Subject: [libvirt] [PATCH 3/4] vcpupin: implement the remote protocol to address the new API In-Reply-To: <4D9E999F.5070505@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> Message-ID: <4D9E9B87.6080606@jp.fujitsu.com> This patch implements the remote protocol to address the new API (virDomainPinVcpuFlags). Signed-off-by: Taku Izumi --- daemon/remote.c | 37 +++++++++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 daemon/remote_dispatch_prototypes.h | 8 +++++++ daemon/remote_dispatch_table.h | 5 ++++ src/remote/remote_driver.c | 40 +++++++++++++++++++++++++++++++++++- src/remote/remote_protocol.c | 16 ++++++++++++++ src/remote/remote_protocol.h | 14 ++++++++++++ src/remote/remote_protocol.x | 10 ++++++++- src/remote_protocol-structs | 9 ++++++++ 9 files changed, 138 insertions(+), 2 deletions(-) Index: libvirt/daemon/remote.c =================================================================== --- libvirt.orig/daemon/remote.c +++ libvirt/daemon/remote.c @@ -2196,6 +2196,43 @@ remoteDispatchDomainPinVcpu (struct qemu } static int +remoteDispatchDomainPinVcpuFlags (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_pin_vcpu_flags_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virDomainPtr dom; + int rv; + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + if (args->cpumap.cpumap_len > REMOTE_CPUMAP_MAX) { + virDomainFree(dom); + remoteDispatchFormatError (rerr, "%s", _("cpumap_len > REMOTE_CPUMAP_MAX")); + return -1; + } + + rv = virDomainPinVcpuFlags (dom, args->vcpu, + (unsigned char *) args->cpumap.cpumap_val, + args->cpumap.cpumap_len, + args->flags); + if (rv == -1) { + remoteDispatchConnError(rerr, conn); + virDomainFree(dom); + return -1; + } + virDomainFree(dom); + return 0; +} + +static int remoteDispatchDomainReboot (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, Index: libvirt/daemon/remote_dispatch_args.h =================================================================== --- libvirt.orig/daemon/remote_dispatch_args.h +++ libvirt/daemon/remote_dispatch_args.h @@ -178,3 +178,4 @@ remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; remote_storage_vol_upload_args val_remote_storage_vol_upload_args; remote_storage_vol_download_args val_remote_storage_vol_download_args; + remote_domain_pin_vcpu_flags_args val_remote_domain_pin_vcpu_flags_args; Index: libvirt/daemon/remote_dispatch_prototypes.h =================================================================== --- libvirt.orig/daemon/remote_dispatch_prototypes.h +++ libvirt/daemon/remote_dispatch_prototypes.h @@ -506,6 +506,14 @@ static int remoteDispatchDomainPinVcpu( remote_error *err, remote_domain_pin_vcpu_args *args, void *ret); +static int remoteDispatchDomainPinVcpuFlags( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_pin_vcpu_flags_args *args, + void *ret); static int remoteDispatchDomainReboot( struct qemud_server *server, struct qemud_client *client, Index: libvirt/daemon/remote_dispatch_table.h =================================================================== --- libvirt.orig/daemon/remote_dispatch_table.h +++ libvirt/daemon/remote_dispatch_table.h @@ -1052,3 +1052,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* DomainPinVcpuFlags => 210 */ + .fn = (dispatch_fn) remoteDispatchDomainPinVcpuFlags, + .args_filter = (xdrproc_t) xdr_remote_domain_pin_vcpu_flags_args, + .ret_filter = (xdrproc_t) xdr_void, +}, Index: libvirt/src/remote/remote_driver.c =================================================================== --- libvirt.orig/src/remote/remote_driver.c +++ libvirt/src/remote/remote_driver.c @@ -3046,6 +3046,44 @@ done: } static int +remoteDomainPinVcpuFlags (virDomainPtr domain, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags) +{ + int rv = -1; + remote_domain_pin_vcpu_flags_args args; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + if (maplen > REMOTE_CPUMAP_MAX) { + remoteError(VIR_ERR_RPC, + _("map length greater than maximum: %d > %d"), + maplen, REMOTE_CPUMAP_MAX); + goto done; + } + + make_nonnull_domain (&args.dom, domain); + args.vcpu = vcpu; + args.cpumap.cpumap_len = maplen; + args.cpumap.cpumap_val = (char *) cpumap; + args.flags = flags; + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS, + (xdrproc_t) xdr_remote_domain_pin_vcpu_flags_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int remoteDomainGetVcpus (virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, @@ -11231,7 +11269,7 @@ static virDriver remote_driver = { remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ remoteDomainPinVcpu, /* domainPinVcpu */ - NULL, /* domainPinVcpuFlags */ + remoteDomainPinVcpuFlags, /* domainPinVcpuFlags */ remoteDomainGetVcpus, /* domainGetVcpus */ remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */ remoteDomainGetSecurityLabel, /* domainGetSecurityLabel */ Index: libvirt/src/remote/remote_protocol.c =================================================================== --- libvirt.orig/src/remote/remote_protocol.c +++ libvirt/src/remote/remote_protocol.c @@ -1521,6 +1521,22 @@ xdr_remote_domain_pin_vcpu_args (XDR *xd } bool_t +xdr_remote_domain_pin_vcpu_flags_args (XDR *xdrs, remote_domain_pin_vcpu_flags_args *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->cpumap.cpumap_val; + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_int (xdrs, &objp->vcpu)) + return FALSE; + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cpumap.cpumap_len, REMOTE_CPUMAP_MAX)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_domain_get_vcpus_args (XDR *xdrs, remote_domain_get_vcpus_args *objp) { Index: libvirt/src/remote/remote_protocol.h =================================================================== --- libvirt.orig/src/remote/remote_protocol.h +++ libvirt/src/remote/remote_protocol.h @@ -841,6 +841,17 @@ struct remote_domain_pin_vcpu_args { }; typedef struct remote_domain_pin_vcpu_args remote_domain_pin_vcpu_args; +struct remote_domain_pin_vcpu_flags_args { + remote_nonnull_domain dom; + int vcpu; + struct { + u_int cpumap_len; + char *cpumap_val; + } cpumap; + u_int flags; +}; +typedef struct remote_domain_pin_vcpu_flags_args remote_domain_pin_vcpu_flags_args; + struct remote_domain_get_vcpus_args { remote_nonnull_domain dom; int maxinfo; @@ -2413,6 +2424,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS = 210, }; typedef enum remote_procedure remote_procedure; @@ -2566,6 +2578,7 @@ extern bool_t xdr_remote_domain_set_vcp extern bool_t xdr_remote_domain_get_vcpus_flags_args (XDR *, remote_domain_get_vcpus_flags_args*); extern bool_t xdr_remote_domain_get_vcpus_flags_ret (XDR *, remote_domain_get_vcpus_flags_ret*); extern bool_t xdr_remote_domain_pin_vcpu_args (XDR *, remote_domain_pin_vcpu_args*); +extern bool_t xdr_remote_domain_pin_vcpu_flags_args (XDR *, remote_domain_pin_vcpu_flags_args*); extern bool_t xdr_remote_domain_get_vcpus_args (XDR *, remote_domain_get_vcpus_args*); extern bool_t xdr_remote_domain_get_vcpus_ret (XDR *, remote_domain_get_vcpus_ret*); extern bool_t xdr_remote_domain_get_max_vcpus_args (XDR *, remote_domain_get_max_vcpus_args*); @@ -2923,6 +2936,7 @@ extern bool_t xdr_remote_domain_set_vcpu extern bool_t xdr_remote_domain_get_vcpus_flags_args (); extern bool_t xdr_remote_domain_get_vcpus_flags_ret (); extern bool_t xdr_remote_domain_pin_vcpu_args (); +extern bool_t xdr_remote_domain_pin_vcpu_flags_args (); extern bool_t xdr_remote_domain_get_vcpus_args (); extern bool_t xdr_remote_domain_get_vcpus_ret (); extern bool_t xdr_remote_domain_get_max_vcpus_args (); Index: libvirt/src/remote/remote_protocol.x =================================================================== --- libvirt.orig/src/remote/remote_protocol.x +++ libvirt/src/remote/remote_protocol.x @@ -843,6 +843,13 @@ struct remote_domain_pin_vcpu_args { opaque cpumap; }; +struct remote_domain_pin_vcpu_flags_args { + remote_nonnull_domain dom; + int vcpu; + opaque cpumap; + unsigned int flags; +}; + struct remote_domain_get_vcpus_args { remote_nonnull_domain dom; int maxinfo; @@ -2176,7 +2183,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS = 210 /* * Notice how the entries are grouped in sets of 10 ? Index: libvirt/src/remote_protocol-structs =================================================================== --- libvirt.orig/src/remote_protocol-structs +++ libvirt/src/remote_protocol-structs @@ -528,6 +528,15 @@ struct remote_domain_pin_vcpu_args { char * cpumap_val; } cpumap; }; +struct remote_domain_pin_vcpu_flags_args { + remote_nonnull_domain dom; + int vcpu; + struct { + u_int cpumap_len; + char * cpumap_val; + } cpumap; + u_int flags; +}; struct remote_domain_get_vcpus_args { remote_nonnull_domain dom; int maxinfo; From izumi.taku at jp.fujitsu.com Fri Apr 8 05:23:00 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Fri, 08 Apr 2011 14:23:00 +0900 Subject: [libvirt] [PATCH 4/4] vcpupin: add the new options to "virsh vcpupin" command In-Reply-To: <4D9E999F.5070505@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> Message-ID: <4D9E9BB4.1070804@jp.fujitsu.com> This patch adds the new option (--live, --config and --current) to "virsh vcpupin" command. The behavior of above aption is the same as that of "virsh setmem", "virsh setvcpus", and whatnot. When the --config option is specified, the command affects a persistent domain, while --live option is specified, it affects a running (live) domain. The --current option cannot be used with --config or --live at the same time, and when --current is specified, it affects a "current" domain. Signed-off-by: Taku Izumi --- tools/virsh.c | 33 +++++++++++++++++++++++++++++++-- tools/virsh.pod | 8 +++++++- 2 files changed, 38 insertions(+), 3 deletions(-) Index: libvirt/tools/virsh.c =================================================================== --- libvirt.orig/tools/virsh.c +++ libvirt/tools/virsh.c @@ -2721,6 +2721,9 @@ static const vshCmdOptDef opts_vcpupin[] {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, {"vcpu", VSH_OT_INT, VSH_OFLAG_REQ, N_("vcpu number")}, {"cpulist", VSH_OT_DATA, VSH_OFLAG_REQ, N_("host cpu number(s) (comma separated)")}, + {"config", VSH_OT_BOOL, 0, N_("affect next boot")}, + {"live", VSH_OT_BOOL, 0, N_("affect running domain")}, + {"current", VSH_OT_BOOL, 0, N_("affect current domain")}, {NULL, 0, 0, NULL} }; @@ -2737,6 +2740,26 @@ cmdVcpupin(vshControl *ctl, const vshCmd int cpumaplen; int i; enum { expect_num, expect_num_or_comma } state; + int config = vshCommandOptBool(cmd, "config"); + int live = vshCommandOptBool(cmd, "live"); + int current = vshCommandOptBool(cmd, "current"); + int flags = 0; + + if (current) { + if (live || config) { + vshError(ctl, "%s", _("--current must be specified exclusively")); + return FALSE; + } + flags = VIR_DOMAIN_VCPU_CURRENT; + } else { + if (config) + flags |= VIR_DOMAIN_VCPU_CONFIG; + if (live) + flags |= VIR_DOMAIN_VCPU_LIVE; + /* neither option is specified */ + if (!live && !config) + flags = -1; + } if (!vshConnectionUsability(ctl, ctl->conn)) return FALSE; @@ -2833,8 +2856,14 @@ cmdVcpupin(vshControl *ctl, const vshCmd cpulist++; } while (cpulist); - if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) { - ret = FALSE; + if (flags == -1) { + if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) { + ret = FALSE; + } + } else { + if (virDomainPinVcpuFlags(dom, vcpu, cpumap, cpumaplen, flags) != 0) { + ret = FALSE; + } } VIR_FREE(cpumap); Index: libvirt/tools/virsh.pod =================================================================== --- libvirt.orig/tools/virsh.pod +++ libvirt/tools/virsh.pod @@ -749,10 +749,16 @@ values; these two flags cannot both be s Returns basic information about the domain virtual CPUs, like the number of vCPUs, the running time, the affinity to physical processors. -=item B I I I +=item B I I I optional I<--live> I<--config> +I<--current> Pin domain VCPUs to host physical CPUs. The I number must be provided and I is a comma separated list of physical CPU numbers. +If I<--live> is specified, affect a running guest. +If I<--config> is specified, affect the next boot of a persistent guest. +If I<--current> is specified, affect the current guest state. +Both I<--live> and I<--config> flags may be given, but I<--current> is exclusive. +If no flag is specified, behavior is different depending on hypervisor. =item B I From wency at cn.fujitsu.com Fri Apr 8 06:26:00 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Fri, 08 Apr 2011 14:26:00 +0800 Subject: [libvirt] [PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) In-Reply-To: <4D9E9B1F.1040500@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> <4D9E9B1F.1040500@jp.fujitsu.com> Message-ID: <4D9EAA78.3050801@cn.fujitsu.com> At 04/08/2011 01:20 PM, Taku Izumi Write: > > This patch introduces a new libvirt API (virDomainPinVcpuFlags) > > Signed-off-by: Taku Izumi > --- > include/libvirt/libvirt.h.in | 6 +++ > src/driver.h | 7 +++ > src/libvirt.c | 83 +++++++++++++++++++++++++++++++++++++++++++ > src/libvirt_public.syms | 4 ++ > src/lxc/lxc_driver.c | 1 > src/openvz/openvz_driver.c | 1 > src/phyp/phyp_driver.c | 1 > src/qemu/qemu_driver.c | 1 > src/remote/remote_driver.c | 1 > src/test/test_driver.c | 1 > src/uml/uml_driver.c | 1 > src/vbox/vbox_tmpl.c | 1 > src/vmware/vmware_driver.c | 1 > src/xen/xen_driver.c | 1 > src/xenapi/xenapi_driver.c | 1 > 15 files changed, 111 insertions(+) > > Index: libvirt/include/libvirt/libvirt.h.in > =================================================================== > --- libvirt.orig/include/libvirt/libvirt.h.in > +++ libvirt/include/libvirt/libvirt.h.in > @@ -1017,6 +1017,7 @@ typedef virVcpuInfo *virVcpuInfoPtr; > > /* Flags for controlling virtual CPU hot-plugging. */ > typedef enum { > + VIR_DOMAIN_VCPU_CURRENT = 0, /* Affect current domain state */ > /* Must choose at least one of these two bits; SetVcpus can choose both */ > VIR_DOMAIN_VCPU_LIVE = (1 << 0), /* Affect active domain */ > VIR_DOMAIN_VCPU_CONFIG = (1 << 1), /* Affect next boot */ > @@ -1037,6 +1038,11 @@ int virDomainPinVcpu > unsigned int vcpu, > unsigned char *cpumap, > int maplen); > +int virDomainPinVcpuFlags (virDomainPtr domain, > + unsigned int vcpu, > + unsigned char *cpumap, > + int maplen, > + unsigned int flags); > > /** > * VIR_USE_CPU: > Index: libvirt/src/driver.h > =================================================================== > --- libvirt.orig/src/driver.h > +++ libvirt/src/driver.h > @@ -220,6 +220,12 @@ typedef int > unsigned char *cpumap, > int maplen); > typedef int > + (*virDrvDomainPinVcpuFlags) (virDomainPtr domain, Please use tab between 'virDrvDomainPinVcpuFlags)' and '(virDomainPtr' instead of space as we use tab in all the other places. > + unsigned int vcpu, > + unsigned char *cpumap, > + int maplen, > + unsigned int flags); > +typedef int > (*virDrvDomainGetVcpus) (virDomainPtr domain, > virVcpuInfoPtr info, > int maxinfo, > @@ -570,6 +576,7 @@ struct _virDriver { > virDrvDomainSetVcpusFlags domainSetVcpusFlags; > virDrvDomainGetVcpusFlags domainGetVcpusFlags; > virDrvDomainPinVcpu domainPinVcpu; > + virDrvDomainPinVcpuFlags domainPinVcpuFlags; Please use tab between virDrvDomainPinVcpuFlags and domainPinVcpuFlags. > virDrvDomainGetVcpus domainGetVcpus; > virDrvDomainGetMaxVcpus domainGetMaxVcpus; > virDrvDomainGetSecurityLabel domainGetSecurityLabel; > Index: libvirt/src/libvirt.c > =================================================================== > --- libvirt.orig/src/libvirt.c > +++ libvirt/src/libvirt.c > @@ -5461,6 +5461,89 @@ error: > } > > /** > + * virDomainPinVcpuFlags: > + * @domain: pointer to domain object, or NULL for Domain0 > + * @vcpu: virtual CPU number > + * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN) > + * Each bit set to 1 means that corresponding CPU is usable. > + * Bytes are stored in little-endian order: CPU0-7, 8-15... > + * In each byte, lowest CPU number is least significant bit. > + * @maplen: number of bytes in cpumap, from 1 up to size of CPU map in > + * underlying virtualization system (Xen...). > + * If maplen < size, missing bytes are set to zero. > + * If maplen > size, failure code is returned. > + * @flags: an OR'ed subset of virDomainVcpuFlags > + * > + * Dynamically change the real CPUs which can be allocated to a virtual CPU. > + * This function requires privileged access to the hypervisor. > + * > + * @flags may include VIR_DOMAIN_VCPU_LIVE or VIR_DOMAIN_VCPU_CONFIG. > + * Both flags may be set, but VIR_DOMAIN_VCPU_MAXIMUM cannot be set. > + * If VIR_DOMAIN_VCPU_LIVE is set, the change affects a running domain > + * and may fail if domain is not alive. > + * If VIR_DOMAIN_VCPU_CONFIG is set, the change affects persistent state, > + * and will fail for transient domains. > + * If neither flag is specified (tha is, @flags is VIR_DOMAIN_VCPU_CURRENT), s/tha/that/ > + * then an inactive domain modifies persistent setup, while an active domain > + * is hypervisor-dependent on whether just live or both live and persistent > + * state is changed. > + * Not all hypervisors can support all flag combinations. > + * > + * Returns 0 in case of success, -1 in case of failure. > + * > + */ > +int > +virDomainPinVcpuFlags(virDomainPtr domain, unsigned int vcpu, > + unsigned char *cpumap, int maplen, unsigned int flags) > +{ > + virConnectPtr conn; > + > + VIR_DOMAIN_DEBUG(domain, "vcpu=%u, cpumap=%p, maplen=%d flags=%u", s/maplen=%d flags=%u/maplen=%d, flags=%u/ > + vcpu, cpumap, maplen, flags); > + > + virResetLastError(); > + > + if (flags & ~(VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) { > + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); > + virDispatchError(NULL); > + return -1; > + } Why we check the flags here? We can check it in hypervisor's implementation. > + > + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { > + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); > + virDispatchError(NULL); > + return -1; > + } > + > + if (domain->conn->flags & VIR_CONNECT_RO) { > + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); > + goto error; > + } > + > + if ((vcpu > 32000) || (cpumap == NULL) || (maplen < 1)) { > + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); > + goto error; > + } > + > + conn = domain->conn; > + > + if (conn->driver->domainPinVcpuFlags) { > + int ret; > + ret = conn->driver->domainPinVcpuFlags (domain, vcpu, cpumap, maplen, flags); There is no need to add space between 'domainPinVcpuFlags' and '(domain', it is old coding style. > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + virDispatchError(domain->conn); > + return -1; > + > +} > + > +/** > * virDomainGetVcpus: > * @domain: pointer to domain object, or NULL for Domain0 > * @info: pointer to an array of virVcpuInfo structures (OUT) > Index: libvirt/src/libvirt_public.syms > =================================================================== > --- libvirt.orig/src/libvirt_public.syms > +++ libvirt/src/libvirt_public.syms > @@ -436,4 +436,8 @@ LIBVIRT_0.9.0 { > virStorageVolUpload; > } LIBVIRT_0.8.8; > > +LIBVIRT_0.9.1 { > + virDomainPinVcpuFlags; > +} LIBVIRT_0.9.0; > + > # .... define new API here using predicted next version number .... > Index: libvirt/src/lxc/lxc_driver.c > =================================================================== > --- libvirt.orig/src/lxc/lxc_driver.c > +++ libvirt/src/lxc/lxc_driver.c > @@ -2837,6 +2837,7 @@ static virDriver lxcDriver = { > NULL, /* domainSetVcpusFlags */ > NULL, /* domainGetVcpusFlags */ > NULL, /* domainPinVcpu */ > + NULL, /* domainPinVcpuFlags */ > NULL, /* domainGetVcpus */ > NULL, /* domainGetMaxVcpus */ > NULL, /* domainGetSecurityLabel */ > Index: libvirt/src/openvz/openvz_driver.c > =================================================================== > --- libvirt.orig/src/openvz/openvz_driver.c > +++ libvirt/src/openvz/openvz_driver.c > @@ -1598,6 +1598,7 @@ static virDriver openvzDriver = { > openvzDomainSetVcpusFlags, /* domainSetVcpusFlags */ > openvzDomainGetVcpusFlags, /* domainGetVcpusFlags */ > NULL, /* domainPinVcpu */ > + NULL, /* domainPinVcpuFlags */ > NULL, /* domainGetVcpus */ > openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */ > NULL, /* domainGetSecurityLabel */ > Index: libvirt/src/phyp/phyp_driver.c > =================================================================== > --- libvirt.orig/src/phyp/phyp_driver.c > +++ libvirt/src/phyp/phyp_driver.c > @@ -4003,6 +4003,7 @@ static virDriver phypDriver = { > phypDomainSetVcpusFlags, /* domainSetVcpusFlags */ > phypDomainGetVcpusFlags, /* domainGetVcpusFlags */ > NULL, /* domainPinVcpu */ > + NULL, /* domainPinVcpuFlags */ > NULL, /* domainGetVcpus */ > phypGetLparCPUMAX, /* domainGetMaxVcpus */ > NULL, /* domainGetSecurityLabel */ > Index: libvirt/src/qemu/qemu_driver.c > =================================================================== > --- libvirt.orig/src/qemu/qemu_driver.c > +++ libvirt/src/qemu/qemu_driver.c > @@ -6864,6 +6864,7 @@ static virDriver qemuDriver = { > qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ > qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ > qemudDomainPinVcpu, /* domainPinVcpu */ > + NULL, /* domainPinVcpuFlags */ > qemudDomainGetVcpus, /* domainGetVcpus */ > qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ > qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */ > Index: libvirt/src/remote/remote_driver.c > =================================================================== > --- libvirt.orig/src/remote/remote_driver.c > +++ libvirt/src/remote/remote_driver.c > @@ -11231,6 +11231,7 @@ static virDriver remote_driver = { > remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ > remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ > remoteDomainPinVcpu, /* domainPinVcpu */ > + NULL, /* domainPinVcpuFlags */ > remoteDomainGetVcpus, /* domainGetVcpus */ > remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */ > remoteDomainGetSecurityLabel, /* domainGetSecurityLabel */ > Index: libvirt/src/test/test_driver.c > =================================================================== > --- libvirt.orig/src/test/test_driver.c > +++ libvirt/src/test/test_driver.c > @@ -5378,6 +5378,7 @@ static virDriver testDriver = { > testDomainSetVcpusFlags, /* domainSetVcpusFlags */ > testDomainGetVcpusFlags, /* domainGetVcpusFlags */ > testDomainPinVcpu, /* domainPinVcpu */ > + NULL, /* domainPinVcpuFlags */ > testDomainGetVcpus, /* domainGetVcpus */ > testDomainGetMaxVcpus, /* domainGetMaxVcpus */ > NULL, /* domainGetSecurityLabel */ > Index: libvirt/src/uml/uml_driver.c > =================================================================== > --- libvirt.orig/src/uml/uml_driver.c > +++ libvirt/src/uml/uml_driver.c > @@ -2184,6 +2184,7 @@ static virDriver umlDriver = { > NULL, /* domainSetVcpusFlags */ > NULL, /* domainGetVcpusFlags */ > NULL, /* domainPinVcpu */ > + NULL, /* domainPinVcpuFlags */ > NULL, /* domainGetVcpus */ > NULL, /* domainGetMaxVcpus */ > NULL, /* domainGetSecurityLabel */ > Index: libvirt/src/vbox/vbox_tmpl.c > =================================================================== > --- libvirt.orig/src/vbox/vbox_tmpl.c > +++ libvirt/src/vbox/vbox_tmpl.c > @@ -8568,6 +8568,7 @@ virDriver NAME(Driver) = { > vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */ > vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */ > NULL, /* domainPinVcpu */ > + NULL, /* domainPinVcpuFlags */ > NULL, /* domainGetVcpus */ > vboxDomainGetMaxVcpus, /* domainGetMaxVcpus */ > NULL, /* domainGetSecurityLabel */ > Index: libvirt/src/vmware/vmware_driver.c > =================================================================== > --- libvirt.orig/src/vmware/vmware_driver.c > +++ libvirt/src/vmware/vmware_driver.c > @@ -938,6 +938,7 @@ static virDriver vmwareDriver = { > NULL, /* domainSetVcpusFlags */ > NULL, /* domainGetVcpusFlags */ > NULL, /* domainPinVcpu */ > + NULL, /* domainPinVcpuFlags */ > NULL, /* domainGetVcpus */ > NULL, /* domainGetMaxVcpus */ > NULL, /* domainGetSecurityLabel */ > Index: libvirt/src/xen/xen_driver.c > =================================================================== > --- libvirt.orig/src/xen/xen_driver.c > +++ libvirt/src/xen/xen_driver.c > @@ -2072,6 +2072,7 @@ static virDriver xenUnifiedDriver = { > xenUnifiedDomainSetVcpusFlags, /* domainSetVcpusFlags */ > xenUnifiedDomainGetVcpusFlags, /* domainGetVcpusFlags */ > xenUnifiedDomainPinVcpu, /* domainPinVcpu */ > + NULL, /* domainPinVcpuFlags */ > xenUnifiedDomainGetVcpus, /* domainGetVcpus */ > xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */ > NULL, /* domainGetSecurityLabel */ > Index: libvirt/src/xenapi/xenapi_driver.c > =================================================================== > --- libvirt.orig/src/xenapi/xenapi_driver.c > +++ libvirt/src/xenapi/xenapi_driver.c > @@ -1820,6 +1820,7 @@ static virDriver xenapiDriver = { > xenapiDomainSetVcpusFlags, /* domainSetVcpusFlags */ > xenapiDomainGetVcpusFlags, /* domainGetVcpusFlags */ > xenapiDomainPinVcpu, /* domainPinVcpu */ > + NULL, /* domainPinVcpuFlags */ > xenapiDomainGetVcpus, /* domainGetVcpus */ > xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */ > NULL, /* domainGetSecurityLabel */ > > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list > From hutao at cn.fujitsu.com Fri Apr 8 07:16:19 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Fri, 8 Apr 2011 15:16:19 +0800 Subject: [libvirt] [PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) In-Reply-To: <4D9E9B1F.1040500@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> <4D9E9B1F.1040500@jp.fujitsu.com> Message-ID: <20110408071619.GA28690@localhost.localdomain> > Index: libvirt/src/lxc/lxc_driver.c > =================================================================== > --- libvirt.orig/src/lxc/lxc_driver.c > +++ libvirt/src/lxc/lxc_driver.c > @@ -2837,6 +2837,7 @@ static virDriver lxcDriver = { > NULL, /* domainSetVcpusFlags */ > NULL, /* domainGetVcpusFlags */ > NULL, /* domainPinVcpu */ > + NULL, /* domainPinVcpuFlags */ should also add this line to src/esx/esx_driver.c From veillard at redhat.com Fri Apr 8 07:19:47 2011 From: veillard at redhat.com (Daniel Veillard) Date: Fri, 8 Apr 2011 15:19:47 +0800 Subject: [libvirt] [PATCH] libxl: missing directory creation for logs Message-ID: <20110408071947.GC30371@redhat.com> Libvirt-0.9.0 wasn't building for Fedora 16, the spec file referenced a log directory missing in teh install tree. After checking that the code actually needed that directory, the following patch solves the problem, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -------------- next part -------------- diff --git a/src/Makefile.am b/src/Makefile.am index 9b54679..099f21a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1275,6 +1275,7 @@ endif if WITH_LIBXL $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/libxl" $(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/libxl" + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/log/libvirt/libxl" endif if WITH_UML $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/uml" From hutao at cn.fujitsu.com Fri Apr 8 07:32:41 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Fri, 8 Apr 2011 15:32:41 +0800 Subject: [libvirt] [PATCH v2 0/4] RFC: vcpupin: configure inactive domains' CPU affinity setting In-Reply-To: <4D9E999F.5070505@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> Message-ID: <20110408073241.GB28690@localhost.localdomain> On Fri, Apr 08, 2011 at 02:14:07PM +0900, Taku Izumi wrote: > Hi all, > > This patchset enables us to configure inactive domains' CPU affinity setting. > > The basic technique is the same as that of "virsh setmem" command. > => http://www.redhat.com/archives/libvir-list/2011-March/msg00013.html > > v1 -> v2: > - recreate based on 0.9.0 > - add "CURRENT" mode > > *[PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) > *[PATCH 2/4] vcpupin: implement the code to address the new API in the qemu driver > *[PATCH 3/4] vcpupin: implement the remote protocol to address the new API > *[PATCH 4/4] vcpupin: add the new options to "virsh vcpupin" command > > Best regards, > Taku Izumi Two suggestions: - when vcpupin an inactive domain, it gives an error message like this: error: Requested operation is not valid: cannot pin vcpus on an inactive domain After applying this series, this is not true anymore. I think a message like this is more helpful: Failed to pin vcpus on inactive domain, please check the --config option. - While it can vcpupin an inactive domain, it seems reasonable to be able to view vcpuinfo of inactive domain, so would a patch to vcpuinfo command be included? From jyang at redhat.com Fri Apr 8 07:32:47 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 08 Apr 2011 15:32:47 +0800 Subject: [libvirt] [PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) In-Reply-To: <4D9E9B1F.1040500@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> <4D9E9B1F.1040500@jp.fujitsu.com> Message-ID: <4D9EBA1F.1020005@redhat.com> ? 2011?04?08? 13:20, Taku Izumi ??: > > This patch introduces a new libvirt API (virDomainPinVcpuFlags) > > Signed-off-by: Taku Izumi > --- > include/libvirt/libvirt.h.in | 6 +++ > src/driver.h | 7 +++ > src/libvirt.c | 83 +++++++++++++++++++++++++++++++++++++++++++ > src/libvirt_public.syms | 4 ++ > src/lxc/lxc_driver.c | 1 > src/openvz/openvz_driver.c | 1 > src/phyp/phyp_driver.c | 1 > src/qemu/qemu_driver.c | 1 > src/remote/remote_driver.c | 1 > src/test/test_driver.c | 1 > src/uml/uml_driver.c | 1 > src/vbox/vbox_tmpl.c | 1 > src/vmware/vmware_driver.c | 1 > src/xen/xen_driver.c | 1 > src/xenapi/xenapi_driver.c | 1 > 15 files changed, 111 insertions(+) Lacks of changes on "libxl/libxl_driver.c" for xenlight driver. Regards Osier From veillard at redhat.com Fri Apr 8 07:36:49 2011 From: veillard at redhat.com (Daniel Veillard) Date: Fri, 8 Apr 2011 15:36:49 +0800 Subject: [libvirt] patch review tool for libvirt patches? In-Reply-To: <20110407182126.GA2719@redhat.com> References: <4D9DD714.8060105@laine.org> <20110407182126.GA2719@redhat.com> Message-ID: <20110408073649.GD30371@redhat.com> On Thu, Apr 07, 2011 at 07:21:26PM +0100, Daniel P. Berrange wrote: > On Thu, Apr 07, 2011 at 11:24:04AM -0400, Laine Stump wrote: > > Now that 0.9.0 is out, I'd like to ask everyone's opinions about > > patch review tools. [...] > > I'm sending this message 1) to see if others are feeling the > > pressure of the extra traffic too (or is my brain just processing > > more slowly :-/), Definitely, but I'm getting old maybe that's the reason :-) > > and 2) to learn what your opinions are of setting > > up such a system for libvirt (for *optional* use only), and any > > opinions you have on what's available (or maybe you could provide a > > recipe for how you already manage all the patches without going > > crazy). Why not ... > > Here's my list of requirements; feel free to add/shoot down: My own requirement is that it should not be intrusive, optional, and actually enhance productivity, not decrease it :-) [...] > > If I were going to investigate one of these and try setting it up, > > which do you think would have the greatest likelyhood of success > > (if any)? > > For me, any tool which requires visiting a web UI to submit or view > patch code review comments/feedback is a non-starter. All code review > feedback must be on the mailing list, and correctly threaded. > In other words, it would be a tool which serves a 'reporting' or > 'tracking' patch series, not a code review management system. agreed > AFAICT, patchwork is the only one expressly designed in this > manner. Their website sums it up nicely: > > "patchwork should supplement mailing lists, not replace them > > Patchwork isn't intended to replace a community mailing list; > that's why you can't comment on a patch in patchwork. If this > were the case, then there would be two forums of discussion > on patches, which fragments the patch review process. Developers > who don't use patchwork would get left out of the discussion." > > To also add to that, public mailing lists are a very good archival > system for code review / discussions. Once in a mailing list, you > can be pretty sure it'll never disappear from the web & is always > searchable from google. The same can't be said of most web apps. Very much agree. One of the key point of Open Source devel is that the design discussions, pros, cons and associated voices including dissenting ones are in the open and logged forever. Basically what would help me is something tracking git and the list and telling me "that has been applied", "that's an old version", "this need review" , "this was ACK'ed but never commited". I'm not sure patchwork really processes automatically, if I look at the qemu-devel example [1] I see only stuff in NEW, if you need manual intervention to set the status, it creates more work, so I hope there is something better. Whether it has a web UI or not is not necessarily important, a tracker which would post status to the list would be IMHO just fine (and possibly slight more efficient since I would be in the same context, and not having to go out of my mail to reach a browser). Daniel [1] http://patchwork.ozlabs.org/project/qemu-devel/list/?order=state&page=5 -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From gross at univention.de Fri Apr 8 07:40:19 2011 From: gross at univention.de (Markus Gross) Date: Fri, 08 Apr 2011 09:40:19 +0200 Subject: [libvirt] [PATCH 4/4] Add domainSave/Restore to libxl driver In-Reply-To: <4D9E265D.3070608@novell.com> References: <4D9E265D.3070608@novell.com> Message-ID: <20110408094019.14905o7gekarxxpc@mail.univention.de> Thanks Jim for the review of patch 3 and 4. I will rework them and post a v2 as soon as I am back from vacation. Cheers, Markus Quoting Jim Fehlig : > Markus Gro? wrote: >> --- >> src/libxl/libxl_conf.h | 10 +++ >> src/libxl/libxl_driver.c | 184 >> +++++++++++++++++++++++++++++++++++++++++++++- >> 2 files changed, 191 insertions(+), 3 deletions(-) >> >> diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h >> index f2f0d8a..e28615b 100644 >> --- a/src/libxl/libxl_conf.h >> +++ b/src/libxl/libxl_conf.h >> @@ -1,5 +1,6 @@ >> >> /*---------------------------------------------------------------------------*/ >> /* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. >> + * Copyright (C) 2011 Univention GmbH. >> * >> * This library is free software; you can redistribute it and/or >> * modify it under the terms of the GNU Lesser General Public >> @@ -17,6 +18,7 @@ >> * >> * Authors: >> * Jim Fehlig >> + * Markus Gro? >> */ >> >> /*---------------------------------------------------------------------------*/ >> >> @@ -85,6 +87,14 @@ struct _libxlDomainObjPrivate { >> int eventHdl; >> }; >> >> +static const char libxlSavefileMagic[16]= "libvirt-xml\n \0 \r"; >> +typedef struct _libxlSavefileHeader libxlSavefileHeader; >> +typedef libxlSavefileHeader *libxlSavefileHeaderPtr; >> +struct _libxlSavefileHeader { >> + char magic[16]; /* magic id */ >> + uint32_t xmlLen; /* length of saved xml */ >> +}; >> > > I think we should pad the header, similar to qemu driver, and provide a > version field. > >> + >> >> # define libxlError(code, ...) \ >> virReportErrorHelper(NULL, VIR_FROM_LIBXL, code, __FILE__, \ >> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c >> index 1539385..b02d4b7 100644 >> --- a/src/libxl/libxl_driver.c >> +++ b/src/libxl/libxl_driver.c >> @@ -29,6 +29,7 @@ >> #include >> #include >> #include >> +#include >> >> #include "internal.h" >> #include "logging.h" >> @@ -60,7 +61,6 @@ >> >> static libxlDriverPrivatePtr libxl_driver = NULL; >> >> - >> /* Function declarations */ >> static int >> libxlVmStart(libxlDriverPrivatePtr driver, >> @@ -1555,6 +1555,184 @@ libxlDomainGetInfo(virDomainPtr dom, >> virDomainInfoPtr info) >> } >> >> static int >> +libxlDomainSave(virDomainPtr dom, const char * to) >> +{ >> + libxlDriverPrivatePtr driver = dom->conn->privateData; >> + virDomainObjPtr vm; >> + libxlDomainObjPrivatePtr priv; >> + virDomainEventPtr event = NULL; >> + libxlSavefileHeader hdr; >> + libxl_domain_suspend_info s_info; >> + char * xml; >> + uint32_t xml_len; >> + int fd; >> + int ret = -1; >> + >> + libxlDriverLock(driver); >> + vm = virDomainFindByUUID(&driver->domains, dom->uuid); >> + >> + if (!vm) { >> + char uuidstr[VIR_UUID_STRING_BUFLEN]; >> + virUUIDFormat(dom->uuid, uuidstr); >> + libxlError(VIR_ERR_NO_DOMAIN, >> + _("No domain with matching uuid '%s'"), uuidstr); >> + goto cleanup; >> + } >> + >> + if (!virDomainObjIsActive(vm)) { >> + libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is >> not running")); >> + goto cleanup; >> + } >> + >> + priv = vm->privateData; >> + >> + if (vm->state != VIR_DOMAIN_PAUSED) { >> + memset(&s_info, 0, sizeof(s_info)); >> + >> + if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, >> S_IRUSR|S_IWUSR, >> + getuid(), getgid(), 0)) < 0) { >> + virReportSystemError(-fd, >> + _("Failed to create domain save >> file '%s'"), >> + to); >> + goto cleanup; >> + } >> + >> + if ((xml = virDomainDefFormat(vm->def, 0)) == NULL) >> + goto cleanup; >> + xml_len = strlen(xml) + 1; >> + >> + memset(&hdr, 0, sizeof(hdr)); >> + memcpy(hdr.magic, libxlSavefileMagic, sizeof(hdr.magic)); >> + hdr.xmlLen = xml_len; >> + >> + if (safewrite(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { >> + libxlError(VIR_ERR_OPERATION_FAILED, >> + _("Failed to write save file header")); >> + goto cleanup; >> + } >> + >> + if (safewrite(fd, xml, xml_len) != xml_len) { >> + libxlError(VIR_ERR_OPERATION_FAILED, >> + _("Failed to write xml description")); >> + goto cleanup; >> + } >> + >> + if (libxl_domain_suspend(&priv->ctx, &s_info, dom->id, fd) != 0) { >> + libxlError(VIR_ERR_INTERNAL_ERROR, >> + _("Failed to save domain '%d' with libxenlight"), >> + dom->id); >> + goto cleanup; >> + } >> + >> + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, >> + VIR_DOMAIN_EVENT_STOPPED_SAVED); >> + >> + if (libxlVmReap(driver, vm, 1) != 0) { >> + libxlError(VIR_ERR_INTERNAL_ERROR, >> + _("Failed to destroy domain '%d'"), dom->id); >> + goto cleanup; >> + } >> + >> + if (!vm->persistent) { >> + virDomainRemoveInactive(&driver->domains, vm); >> + vm = NULL; >> + } >> + ret = 0; >> + } >> +cleanup: >> + VIR_FREE(xml); >> + if (VIR_CLOSE(fd) < 0) >> + virReportSystemError(errno, "%s", _("cannot close file")); >> + if (vm) >> + virDomainObjUnlock(vm); >> + if (event) >> + libxlDomainEventQueue(driver, event); >> + libxlDriverUnlock(driver); >> + return ret; >> +} >> + >> +static int >> +libxlDomainRestore(virConnectPtr conn, const char * from) >> +{ >> + libxlDriverPrivatePtr driver = conn->privateData; >> + virDomainDefPtr def = NULL; >> + virDomainObjPtr vm = NULL; >> + virDomainEventPtr event = NULL; >> + libxlSavefileHeader hdr; >> + char * xml = NULL; >> + int fd; >> + int ret = -1; >> + >> + libxlDriverLock(driver); >> + >> + if ((fd = virFileOpenAs(from, O_RDONLY, 0, getuid(), getgid(), >> 0)) < 0) { >> + libxlError(VIR_ERR_OPERATION_FAILED, >> + "%s", _("cannot read domain image")); >> + goto cleanup; >> + } >> + >> + if (saferead(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { >> + libxlError(VIR_ERR_OPERATION_FAILED, >> + "%s", _("failed to read libxl header")); >> + goto cleanup; >> + } >> + >> + if (memcmp(hdr.magic, libxlSavefileMagic, sizeof(hdr.magic))) { >> + libxlError(VIR_ERR_INVALID_ARG, "%s", _("image magic is >> incorrect")); >> + goto cleanup; >> + } >> + >> + if (hdr.xmlLen <= 0) { >> + libxlError(VIR_ERR_OPERATION_FAILED, >> + _("invalid XML length: %d"), hdr.xmlLen); >> + goto cleanup; >> + } >> + >> + if (VIR_ALLOC_N(xml, hdr.xmlLen) < 0) { >> + virReportOOMError(); >> + goto cleanup; >> + } >> + >> + if (saferead(fd, xml, hdr.xmlLen) != hdr.xmlLen) { >> + libxlError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to >> read XML")); >> + goto cleanup; >> + } >> + >> + if (!(def = virDomainDefParseString(driver->caps, xml, 0))) >> + goto cleanup; >> + >> + if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) >> + goto cleanup; >> + >> + if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, >> def, false))) >> + goto cleanup; >> + >> + def = NULL; >> + >> + ret = libxlVmStart(driver, vm, false); >> > > This starts a new domain. To restore a domain, you need to use > libxl_domain_create_restore(). > > Regards, > Jim > >> + >> + if (ret == 0) { >> + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, >> + VIR_DOMAIN_EVENT_STARTED_RESTORED); >> + } else if (ret < 0 && !vm->persistent) { >> + virDomainRemoveInactive(&driver->domains, vm); >> + vm = NULL; >> + } >> + >> +cleanup: >> + VIR_FREE(xml); >> + virDomainDefFree(def); >> + if (VIR_CLOSE(fd) < 0) >> + virReportSystemError(errno, "%s", _("cannot close file")); >> + if (vm) >> + virDomainObjUnlock(vm); >> + if (event) >> + libxlDomainEventQueue(driver, event); >> + libxlDriverUnlock(driver); >> + return ret; >> +} >> + >> +static int >> libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, >> unsigned int flags) >> { >> @@ -2658,8 +2836,8 @@ static virDriver libxlDriver = { >> NULL, /* domainSetBlkioParameters */ >> NULL, /* domainGetBlkioParameters */ >> libxlDomainGetInfo, /* domainGetInfo */ >> - NULL, /* domainSave */ >> - NULL, /* domainRestore */ >> + libxlDomainSave, /* domainSave */ >> + libxlDomainRestore, /* domainRestore */ >> NULL, /* domainCoreDump */ >> libxlDomainSetVcpus, /* domainSetVcpus */ >> libxlDomainSetVcpusFlags, /* domainSetVcpusFlags */ >> > From hutao at cn.fujitsu.com Fri Apr 8 07:51:44 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Fri, 8 Apr 2011 15:51:44 +0800 Subject: [libvirt] [PATCH 1/3] maxmem: introduces VIR_DOMAIN_MEM_MAXIMUM flag In-Reply-To: <4D9E980F.5090904@jp.fujitsu.com> References: <4D9E953A.4070102@jp.fujitsu.com> <4D9E980F.5090904@jp.fujitsu.com> Message-ID: <20110408075144.GA6374@localhost.localdomain> On Fri, Apr 08, 2011 at 02:07:27PM +0900, Taku Izumi wrote: > > This patch introduces VIR_DOMAIN_MEM_MAXIMUM flag. > > Signed-off-by: Taku Izumi > --- > include/libvirt/libvirt.h.in | 1 + > src/libvirt.c | 2 ++ > 2 files changed, 3 insertions(+) > > Index: libvirt/include/libvirt/libvirt.h.in > =================================================================== > --- libvirt.orig/include/libvirt/libvirt.h.in > +++ libvirt/include/libvirt/libvirt.h.in > @@ -857,6 +857,7 @@ typedef enum { > VIR_DOMAIN_MEM_CURRENT = 0, /* affect current domain state */ This patch doesn't apply, the file in my git tree doesn't have the above line. (I've double-checked and made sure I didn't make a mistake) Would you mind to have a check on your tree? > VIR_DOMAIN_MEM_LIVE = (1 << 0), /* affect active domain */ > VIR_DOMAIN_MEM_CONFIG = (1 << 1), /* affect next boot */ > + VIR_DOMAIN_MEM_MAXIMUM = (1 << 2), /* affect Max rather than current */ > } virDomainMemoryModFlags; > > > Index: libvirt/src/libvirt.c > =================================================================== > --- libvirt.orig/src/libvirt.c > +++ libvirt/src/libvirt.c > @@ -2832,6 +2832,8 @@ error: > * (that is, @flags is VIR_DOMAIN_MEM_CURRENT), then an inactive domain > * modifies persistent setup, while an active domain is hypervisor-dependent > * on whether just live or both live and persistent state is changed. > + * If VIR_DOMAIN_MEM_MAXIMUM is set, the change affects domain's maximum memory > + * size rather than current memory size. > * Not all hypervisors can support all flag combinations. > * > * Returns 0 in case of success, -1 in case of failure. > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list From mcastrol at gmail.com Fri Apr 8 08:18:35 2011 From: mcastrol at gmail.com (=?ISO-8859-1?Q?Marcela_Castro_Le=F3n?=) Date: Fri, 8 Apr 2011 10:18:35 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: <4D9C95BA.2080608@redhat.com> References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B322D.9040309@redhat.com> <4D9B3288.6080700@redhat.com> <4D9B40FA.50601@redhat.com> <4D9C3BDC.3010100@redhat.com> <4D9C95BA.2080608@redhat.com> Message-ID: Hello I'm thinking to upgrade the libvirt to solve the problem as you said in your last mail. But I've installed the package using "apt-get install" and I can''t get higher version of all the packages involves doing an upgrade in ubuntu (I'm using 10.04) Can you suggest-me "an easy" way to upgrate the libvirt? Thank you very much. Marcela 2011/4/6 Eric Blake > On 04/06/2011 04:09 AM, Michal Novotny wrote: > > Hi, > > the interesting thing is the "Permission denied" message in the log file: > > > > LC_ALL=C > > PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin > > QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 -S -M pc-0.12 > > -enable-kvm -m 4096 -smp 4 -name chompi1 -uuid > > 22f013aa-25d4-b317-9eac-b232692db8c7 -chardev > > > socket,id=monitor,path=/var/lib/libvirt/qemu/chompi1.monitor,server,nowait > > -monitor chardev:monitor -boot c -drive > > > file=/home/radic/mvdata/imagenes/chompi1.img,if=ide,index=0,boot=on,format=raw > > -drive if=ide,media=cdrom,index=2,format=raw -net > > nic,macaddr=52:54:00:82:ce:80,vlan=0,model=virtio,name=virtio.0 -net > > tap,fd=34,vlan=0,name=tap.0 -chardev pty,id=serial0 -serial > > chardev:serial0 -parallel none -usb -vnc 0.0.0.0:0 -vga cirrus -incoming > > exec:cat > > char device redirected to /dev/pts/2 > > cat: -: Permission denied <== THIS ONE > > load of migration failed > > > > I don't know much about the internal libvirt design since libvirt is not > > my primary space so I hope my e-mails from yesterday helped a little but > > I'll leave the rest for libvirt guys since I'm not having any other > > ideas what could be wrong there. > > That's a weird error - cat is complaining that it can't read stdin, > which is usually a symptom associated with SELinux permissions. But you > said earlier in this thread that you aren't using SELinux. Are you > using AppArmor? > > At any rate, does upgrading to libvirt 0.9.0 improve the situation? > exec: migration has always been risky (there are various data races > involved in coordinating multiple processes, where qemu is using popen() > to manage the use or even opening the file), and so newer libvirt uses > fd: migration (where the fd is already open, so we don't even have to > worry about permissions from qemu's point of view). > > -- > Eric Blake eblake at redhat.com +1-801-349-2682 > Libvirt virtualization library http://libvirt.org > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From minovotn at redhat.com Fri Apr 8 08:22:13 2011 From: minovotn at redhat.com (Michal Novotny) Date: Fri, 08 Apr 2011 10:22:13 +0200 Subject: [libvirt] Using Restore in another host. In-Reply-To: References: <20110404102013.GB13616@redhat.com> <4D9AFF24.6060109@redhat.com> <4D9B30BA.6090906@redhat.com> <4D9B322D.9040309@redhat.com> <4D9B3288.6080700@redhat.com> <4D9B40FA.50601@redhat.com> <4D9C3BDC.3010100@redhat.com> <4D9C95BA.2080608@redhat.com> Message-ID: <4D9EC5B5.9090806@redhat.com> Hi, I think the best thing would be to download it directly from libvirt.org site and install it. It's not the easiest way but it's the best way IMHO. You can find relevant information there: http://libvirt.org/compiling.html Michal On 04/08/2011 10:18 AM, Marcela Castro Le?n wrote: > Hello > I'm thinking to upgrade the libvirt to solve the problem as you said > in your last mail. > But I've installed the package using "apt-get install" and I can''t > get higher version of all the packages involves doing an upgrade in > ubuntu (I'm using 10.04) > Can you suggest-me "an easy" way to upgrate the libvirt? > Thank you very much. > Marcela > > > > 2011/4/6 Eric Blake > > > On 04/06/2011 04:09 AM, Michal Novotny wrote: > > Hi, > > the interesting thing is the "Permission denied" message in the > log file: > > > > LC_ALL=C > > PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin > > QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 -S -M pc-0.12 > > -enable-kvm -m 4096 -smp 4 -name chompi1 -uuid > > 22f013aa-25d4-b317-9eac-b232692db8c7 -chardev > > > socket,id=monitor,path=/var/lib/libvirt/qemu/chompi1.monitor,server,nowait > > -monitor chardev:monitor -boot c -drive > > > file=/home/radic/mvdata/imagenes/chompi1.img,if=ide,index=0,boot=on,format=raw > > -drive if=ide,media=cdrom,index=2,format=raw -net > > nic,macaddr=52:54:00:82:ce:80,vlan=0,model=virtio,name=virtio.0 -net > > tap,fd=34,vlan=0,name=tap.0 -chardev pty,id=serial0 -serial > > chardev:serial0 -parallel none -usb -vnc 0.0.0.0:0 > -vga cirrus -incoming > > exec:cat > > char device redirected to /dev/pts/2 > > cat: -: Permission denied <== THIS ONE > > load of migration failed > > > > I don't know much about the internal libvirt design since > libvirt is not > > my primary space so I hope my e-mails from yesterday helped a > little but > > I'll leave the rest for libvirt guys since I'm not having any other > > ideas what could be wrong there. > > That's a weird error - cat is complaining that it can't read stdin, > which is usually a symptom associated with SELinux permissions. > But you > said earlier in this thread that you aren't using SELinux. Are you > using AppArmor? > > At any rate, does upgrading to libvirt 0.9.0 improve the situation? > exec: migration has always been risky (there are various data races > involved in coordinating multiple processes, where qemu is using > popen() > to manage the use or even opening the file), and so newer libvirt uses > fd: migration (where the fd is already open, so we don't even have to > worry about permissions from qemu's point of view). > > -- > Eric Blake eblake at redhat.com > +1-801-349-2682 > Libvirt virtualization library http://libvirt.org > > -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From hutao at cn.fujitsu.com Fri Apr 8 08:24:39 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Fri, 8 Apr 2011 16:24:39 +0800 Subject: [libvirt] [PATCH 1/3] maxmem: introduces VIR_DOMAIN_MEM_MAXIMUM flag In-Reply-To: <20110408075144.GA6374@localhost.localdomain> References: <4D9E953A.4070102@jp.fujitsu.com> <4D9E980F.5090904@jp.fujitsu.com> <20110408075144.GA6374@localhost.localdomain> Message-ID: <20110408082439.GB6374@localhost.localdomain> On Fri, Apr 08, 2011 at 03:51:44PM +0800, Hu Tao wrote: > On Fri, Apr 08, 2011 at 02:07:27PM +0900, Taku Izumi wrote: > > > > This patch introduces VIR_DOMAIN_MEM_MAXIMUM flag. > > > > Signed-off-by: Taku Izumi > > --- > > include/libvirt/libvirt.h.in | 1 + > > src/libvirt.c | 2 ++ > > 2 files changed, 3 insertions(+) > > > > Index: libvirt/include/libvirt/libvirt.h.in > > =================================================================== > > --- libvirt.orig/include/libvirt/libvirt.h.in > > +++ libvirt/include/libvirt/libvirt.h.in > > @@ -857,6 +857,7 @@ typedef enum { > > VIR_DOMAIN_MEM_CURRENT = 0, /* affect current domain state */ > > This patch doesn't apply, the file in my git tree doesn't have the above > line. (I've double-checked and made sure I didn't make a mistake) > Would you mind to have a check on your tree? Sorry, my problem here. There is lag on our git server. From jyang at redhat.com Fri Apr 8 08:51:53 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 8 Apr 2011 16:51:53 +0800 Subject: [libvirt] Add filesystem pool formatting (v4) Message-ID: <1302252716-31890-1-git-send-email-jyang@redhat.com> This patch series are based on Dave Allan's previous posts: https://www.redhat.com/archives/libvir-list/2010-June/msg00040.html I rebased them and make changes per last feedback from Eric, and also other some small changes. The following patches add the ability to format filesystem pools when the appropriate flags are passed to pool build. As before, I have implemented two new flags: VIR_STORAGE_POOL_BUILD_NO_OVERWRITE causes the build to probe for an existing pool of the requested type. The build operation formats the filesystem if it does not find an existing filesystem of that type. VIR_STORAGE_POOL_BUILD_OVERWRITE causes the build to format unconditionally. These patches incorporate all the feedback received on earlier versions. The incremental is pretty unhelpful, so these are complete replacement patches. Dave From jyang at redhat.com Fri Apr 8 08:51:54 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 8 Apr 2011 16:51:54 +0800 Subject: [libvirt] [PATCH 1/3] storage: Add mkfs and libblkid to build system In-Reply-To: <1302252716-31890-1-git-send-email-jyang@redhat.com> References: <1302252716-31890-1-git-send-email-jyang@redhat.com> Message-ID: <1302252716-31890-2-git-send-email-jyang@redhat.com> New changes: * Define LIBBLKID_REQUIRED, which is missed in previous posts. * Remove libblkid requires per Eric's feedback. --- configure.ac | 26 ++++++++++++++++++++++++++ libvirt.spec.in | 4 ++++ src/Makefile.am | 4 ++++ 3 files changed, 34 insertions(+), 0 deletions(-) diff --git a/configure.ac b/configure.ac index 190bf40..184236c 100644 --- a/configure.ac +++ b/configure.ac @@ -68,6 +68,7 @@ DEVMAPPER_REQUIRED=1.0.0 LIBCURL_REQUIRED="7.18.0" LIBPCAP_REQUIRED="1.0.0" LIBNL_REQUIRED="1.1" +LIBBLKID_REQUIRED="2.18" dnl Checks for C compiler. AC_PROG_CC @@ -1593,12 +1594,15 @@ fi if test "$with_storage_fs" = "yes" || test "$with_storage_fs" = "check"; then AC_PATH_PROG([MOUNT], [mount], [], [$PATH:/sbin:/usr/sbin]) AC_PATH_PROG([UMOUNT], [umount], [], [$PATH:/sbin:/usr/sbin]) + AC_PATH_PROG([MKFS], [mkfs], [], [$PATH:/sbin:/usr/sbin]) if test "$with_storage_fs" = "yes" ; then if test -z "$MOUNT" ; then AC_MSG_ERROR([We need mount for FS storage driver]) ; fi if test -z "$UMOUNT" ; then AC_MSG_ERROR([We need umount for FS storage driver]) ; fi + if test -z "$MKFS" ; then AC_MSG_ERROR([We need mkfs for FS storage driver]) ; fi else if test -z "$MOUNT" ; then with_storage_fs=no ; fi if test -z "$UMOUNT" ; then with_storage_fs=no ; fi + if test -z "$MKFS" ; then with_storage_fs=no ; fi if test "$with_storage_fs" = "check" ; then with_storage_fs=yes ; fi fi @@ -1609,6 +1613,8 @@ if test "$with_storage_fs" = "yes" || test "$with_storage_fs" = "check"; then [Location or name of the mount program]) AC_DEFINE_UNQUOTED([UMOUNT],["$UMOUNT"], [Location or name of the mount program]) + AC_DEFINE_UNQUOTED([MKFS],["$MKFS"], + [Location or name of the mkfs program]) fi fi AM_CONDITIONAL([WITH_STORAGE_FS], [test "$with_storage_fs" = "yes"]) @@ -2238,6 +2244,26 @@ if test "$with_nwfilter" = "yes" ; then fi AM_CONDITIONAL([WITH_NWFILTER], [test "$with_nwfilter" = "yes"]) +dnl libblkid is used by several storage drivers; therefore we probe +dnl for it unconditionally. +AC_ARG_WITH([libblkid], + [AS_HELP_STRING([--with-libblkid], + [use libblkid to scan for filesystems and partitions @<:@default=check@:>@])], + [], + [with_libblkid=check]) + +if test "x$with_libblkid" = "xyes" || test "x$with_libblkid" = "xcheck"; then + PKG_CHECK_MODULES([BLKID], + [blkid >= $LIBBLKID_REQUIRED], + [with_libblkid="yes"], + [with_libblkid="no"]) +fi + +if test "x$with_libblkid" = "xyes"; then + AC_DEFINE([HAVE_LIBBLKID], [1], [libblkid is present]) +fi +AM_CONDITIONAL([HAVE_LIBBLKID], [test "x$with_libblkid" = "xyes"]) + AC_ARG_WITH([qemu-user], AC_HELP_STRING([--with-qemu-user], [username to run QEMU system instance as @<:@default=root@:>@]), [QEMU_USER=${withval}], diff --git a/libvirt.spec.in b/libvirt.spec.in index 4162fba..88f65da 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -265,6 +265,10 @@ Requires: PolicyKit >= 0.6 %endif %if %{with_storage_fs} Requires: nfs-utils +# For mkfs +Requires: nfs-utils +# For pool-build probing for existing pools +BuildRequires: libblkid-devel >= 2.17 # For glusterfs %if 0%{?fedora} >= 11 Requires: glusterfs-client >= 2.0.1 diff --git a/src/Makefile.am b/src/Makefile.am index 3649106..f6cb52d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -900,6 +900,10 @@ if WITH_DRIVER_MODULES libvirt_driver_storage_la_LIBADD += ../gnulib/lib/libgnu.la libvirt_driver_storage_la_LDFLAGS += -module -avoid-version endif +if HAVE_LIBBLKID +libvirt_driver_storage_la_CFLAGS += $(BLKID_CFLAGS) +libvirt_driver_storage_la_LIBADD += $(BLKID_LIBS) +endif libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_SOURCES) libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_FS_SOURCES) endif -- 1.7.4 From jyang at redhat.com Fri Apr 8 08:51:55 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 8 Apr 2011 16:51:55 +0800 Subject: [libvirt] [PATCH 2/3] Storage: Add fs pool formatting In-Reply-To: <1302252716-31890-1-git-send-email-jyang@redhat.com> References: <1302252716-31890-1-git-send-email-jyang@redhat.com> Message-ID: <1302252716-31890-3-git-send-email-jyang@redhat.com> Previous description from Dave Allan. This patch adds the ability to make the filesystem for a filesystem pool during a pool build. The patch adds two new flags, no overwrite and overwrite, to control when mkfs gets executed. By default, the patch preserves the current behavior, i.e., if no flags are specified, pool build on a filesystem pool only makes the directory on which the filesystem will be mounted. If the no overwrite flag is specified, the target device is checked to determine if a filesystem of the type specified in the pool is present. If a filesystem of that type is already present, mkfs is not executed and the build call returns an error. Otherwise, mkfs is executed and any data present on the device is overwritten. If the overwrite flag is specified, mkfs is always executed, and any existing data on the target device is overwritten unconditionally. Changes per feedback from eblake: * Made probe & overwrite flags exclusive * Changed LDFLAGS to LIBADD in Makefile.am * Added missing virCheckFlags() * Fixed copyright dates * Removed cast of char * passed to libblkid and replaced it with a strdup'd copy * Changed flags to an unsigned int in virsh.c Changes per feedback from Dan B. * Changed probe flag to no-overwrite * Moved libblkid probe code into storage_backend_fs.c New changes: (per last feedback from Eric) * s/VIR_STORAGE_POOL_PROBE_BUILT/VIR_STORAGE_POOL_BUILT/ * Remove the internal function exporting in libvirt_private.syms * Correct wonky spacing --- include/libvirt/libvirt.h.in | 6 +- include/libvirt/virterror.h | 2 + src/libvirt.c | 5 +- src/storage/storage_backend_fs.c | 191 +++++++++++++++++++++++++++++++++++++- src/storage/storage_backend_fs.h | 7 ++ src/util/virterror.c | 64 ++++++++----- 6 files changed, 242 insertions(+), 33 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index d765412..e43c98a 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1335,8 +1335,10 @@ typedef enum { typedef enum { VIR_STORAGE_POOL_BUILD_NEW = 0, /* Regular build from scratch */ - VIR_STORAGE_POOL_BUILD_REPAIR = 1, /* Repair / reinitialize */ - VIR_STORAGE_POOL_BUILD_RESIZE = 2 /* Extend existing pool */ + VIR_STORAGE_POOL_BUILD_REPAIR = (1 << 0), /* Repair / reinitialize */ + VIR_STORAGE_POOL_BUILD_RESIZE = (1 << 1), /* Extend existing pool */ + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE = (1 << 2), /* Do not overwrite existing pool */ + VIR_STORAGE_POOL_BUILD_OVERWRITE = (1 << 3), /* Overwrite data */ } virStoragePoolBuildFlags; typedef enum { diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 0708e02..33fbe9a 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -231,6 +231,8 @@ typedef enum { VIR_ERR_INVALID_DOMAIN_SNAPSHOT = 71,/* invalid domain snapshot */ VIR_ERR_NO_DOMAIN_SNAPSHOT = 72, /* domain snapshot not found */ VIR_ERR_INVALID_STREAM = 73, /* stream pointer not valid */ + VIR_ERR_STORAGE_PROBE_FAILED = 74, /* storage pool proble failed */ + VIR_ERR_STORAGE_POOL_BUILT = 75, /* storage pool already built */ } virErrorNumber; /** diff --git a/src/libvirt.c b/src/libvirt.c index dde4bd4..03d870b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -8001,7 +8001,10 @@ error: /** * virStoragePoolBuild: * @pool: pointer to storage pool - * @flags: future flags, use 0 for now + * @flags: flags to control pool build behaviour + * + * Currently only filesystem pool accepts flags VIR_STORAGE_POOL_BUILD_OVERWRITE + * and VIR_STORAGE_POOL_BUILD_NO_OVERWRITE. * * Build the underlying storage pool * diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index 0a6b074..54afa7c 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -33,6 +33,10 @@ #include #include +#if HAVE_LIBBLKID +# include +#endif + #include #include #include @@ -45,6 +49,7 @@ #include "memory.h" #include "xml.h" #include "files.h" +#include "logging.h" #define VIR_FROM_THIS VIR_FROM_STORAGE @@ -533,13 +538,173 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED, } #endif /* WITH_STORAGE_FS */ +#if HAVE_LIBBLKID +static virStoragePoolProbeResult +virStorageBackendFileSystemProbe(const char *device, + const char *format) { + + virStoragePoolProbeResult ret = FILESYSTEM_PROBE_ERROR; + blkid_probe probe = NULL; + const char *fstype = NULL; + char *names[2], *libblkid_format = NULL; + + VIR_DEBUG("Probing for existing filesystem of type %s on device %s", + format, device); + + if (blkid_known_fstype(format) == 0) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Not capable of probing for " + "filesystem of type %s"), + format); + goto error; + } + + probe = blkid_new_probe_from_filename(device); + if (probe == NULL) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Failed to create filesystem probe " + "for device %s"), + device); + goto error; + } + + if ((libblkid_format = strdup(format)) == NULL) { + virReportOOMError(); + goto error; + } + + names[0] = libblkid_format; + names[1] = NULL; + + blkid_probe_filter_superblocks_type(probe, + BLKID_FLTR_ONLYIN, + names); + + if (blkid_do_probe(probe) != 0) { + VIR_INFO("No filesystem of type '%s' found on device '%s'", + format, device); + ret = FILESYSTEM_PROBE_NOT_FOUND; + } else if (blkid_probe_lookup_value(probe, "TYPE", &fstype, NULL) == 0) { + virStorageReportError(VIR_ERR_STORAGE_POOL_BUILT, + _("Existing filesystem of type '%s' found on " + "device '%s'"), + fstype, device); + ret = FILESYSTEM_PROBE_FOUND; + } + + if (blkid_do_probe(probe) != 1) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Found additional probes to run, " + "filesystem probing may be incorrect")); + ret = FILESYSTEM_PROBE_ERROR; + } + +error: + VIR_FREE(libblkid_format); + + if (probe != NULL) { + blkid_free_probe(probe); + } + + return ret; +} + +#else /* #if HAVE_LIBBLKID */ + +static virStoragePoolProbeResult +virStorageBackendFileSystemProbe(const char *device ATTRIBUTE_UNUSED, + const char *format ATTRIBUTE_UNUSED) +{ + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("probing for filesystems is unsupported " + "by this build")); + + return FILESYSTEM_PROBE_ERROR; +} + +#endif /* #if HAVE_LIBBLKID */ + +static int +virStorageBackendExecuteMKFS(const char *device, + const char *format) +{ + int ret = 0; + const char *mkfsargv[5] = { MKFS, + "-t", + format, + device, + NULL }; + + if (virRun(mkfsargv, NULL) < 0) { + virReportSystemError(errno, + _("Failed to make filesystem of " + "type '%s' on device '%s'"), + format, device); + ret = -1; + } + + return ret; +} + + +static int +virStorageBackendMakeFileSystem(virStoragePoolObjPtr pool, + unsigned int flags) +{ + const char *device = NULL, *format = NULL; + bool ok_to_mkfs = false; + int ret = -1; + + if (pool->def->source.devices == NULL) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("No source device specified when formatting pool '%s'"), + pool->def->name); + goto error; + } + + device = pool->def->source.devices[0].path; + format = virStoragePoolFormatFileSystemTypeToString(pool->def->source.format); + VIR_DEBUG("source device: '%s' format: '%s'", device, format); + + if (!virFileExists(device)) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("Source device does not exist when formatting pool '%s'"), + pool->def->name); + goto error; + } + + if (flags & VIR_STORAGE_POOL_BUILD_OVERWRITE) { + ok_to_mkfs = true; + } else if (flags & VIR_STORAGE_POOL_BUILD_NO_OVERWRITE && + virStorageBackendFileSystemProbe(device, format) == + FILESYSTEM_PROBE_NOT_FOUND) { + ok_to_mkfs = true; + } + + if (ok_to_mkfs) { + ret = virStorageBackendExecuteMKFS(device, format); + } + +error: + return ret; +} + + /** * @conn connection to report errors against * @pool storage pool to build + * @flags controls the pool formating behaviour * * Build a directory or FS based storage pool. * + * If no flag is set, it only makes the directory; If + * VIR_STORAGE_POOL_BUILD_NO_OVERWRITE set, it probes to determine if + * a filesystem already exists on the target device, returning an error + * if exists, or using mkfs to format the target device if not; If + * VIR_STORAGE_POOL_BUILD_OVERWRITE is set, mkfs is always executed, + * any existed data on the target device is overwritten unconditionally. + * * - If it is a FS based pool, mounts the unlying source device on the pool * * Returns 0 on success, -1 on error @@ -547,11 +712,23 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED, static int virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, - unsigned int flags ATTRIBUTE_UNUSED) + unsigned int flags) { int err, ret = -1; - char *parent; - char *p; + char *parent = NULL; + char *p = NULL; + + virCheckFlags(VIR_STORAGE_POOL_BUILD_OVERWRITE | + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, ret); + + if (flags == (VIR_STORAGE_POOL_BUILD_OVERWRITE | + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE)) { + + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("Overwrite and no overwrite flags" + " are mutually exclusive")); + goto error; + } if ((parent = strdup(pool->def->target.path)) == NULL) { virReportOOMError(); @@ -601,7 +778,13 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, goto error; } } - ret = 0; + + if (flags != 0) { + ret = virStorageBackendMakeFileSystem(pool, flags); + } else { + ret = 0; + } + error: VIR_FREE(parent); return ret; diff --git a/src/storage/storage_backend_fs.h b/src/storage/storage_backend_fs.h index 7def53e..394e552 100644 --- a/src/storage/storage_backend_fs.h +++ b/src/storage/storage_backend_fs.h @@ -29,6 +29,13 @@ # if WITH_STORAGE_FS extern virStorageBackend virStorageBackendFileSystem; extern virStorageBackend virStorageBackendNetFileSystem; + +typedef enum { + FILESYSTEM_PROBE_FOUND, + FILESYSTEM_PROBE_NOT_FOUND, + FILESYSTEM_PROBE_ERROR, +} virStoragePoolProbeResult; + # endif extern virStorageBackend virStorageBackendDirectory; diff --git a/src/util/virterror.c b/src/util/virterror.c index b7d8924..4450a43 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -1041,63 +1041,75 @@ virErrorMsg(virErrorNumber error, const char *info) break; case VIR_ERR_NO_STORAGE_POOL: if (info == NULL) - errmsg = _("Storage pool not found"); + errmsg = _("Storage pool not found"); else - errmsg = _("Storage pool not found: %s"); + errmsg = _("Storage pool not found: %s"); break; case VIR_ERR_NO_STORAGE_VOL: if (info == NULL) - errmsg = _("Storage volume not found"); + errmsg = _("Storage volume not found"); else - errmsg = _("Storage volume not found: %s"); + errmsg = _("Storage volume not found: %s"); + break; + case VIR_ERR_STORAGE_PROBE_FAILED: + if (info == NULL) + errmsg = _("Storage pool probe failed"); + else + errmsg = _("Storage pool probe failed: %s"); + break; + case VIR_ERR_STORAGE_POOL_BUILT: + if (info == NULL) + errmsg = _("Storage pool already built"); + else + errmsg = _("Storage pool already built: %s"); break; case VIR_ERR_INVALID_STORAGE_POOL: if (info == NULL) - errmsg = _("invalid storage pool pointer in"); + errmsg = _("invalid storage pool pointer in"); else - errmsg = _("invalid storage pool pointer in %s"); + errmsg = _("invalid storage pool pointer in %s"); break; case VIR_ERR_INVALID_STORAGE_VOL: if (info == NULL) - errmsg = _("invalid storage volume pointer in"); + errmsg = _("invalid storage volume pointer in"); else - errmsg = _("invalid storage volume pointer in %s"); + errmsg = _("invalid storage volume pointer in %s"); break; case VIR_WAR_NO_STORAGE: if (info == NULL) - errmsg = _("Failed to find a storage driver"); + errmsg = _("Failed to find a storage driver"); else - errmsg = _("Failed to find a storage driver: %s"); + errmsg = _("Failed to find a storage driver: %s"); break; case VIR_WAR_NO_NODE: if (info == NULL) - errmsg = _("Failed to find a node driver"); + errmsg = _("Failed to find a node driver"); else - errmsg = _("Failed to find a node driver: %s"); + errmsg = _("Failed to find a node driver: %s"); break; case VIR_ERR_INVALID_NODE_DEVICE: if (info == NULL) - errmsg = _("invalid node device pointer"); + errmsg = _("invalid node device pointer"); else - errmsg = _("invalid node device pointer in %s"); + errmsg = _("invalid node device pointer in %s"); break; case VIR_ERR_NO_NODE_DEVICE: if (info == NULL) - errmsg = _("Node device not found"); + errmsg = _("Node device not found"); else - errmsg = _("Node device not found: %s"); + errmsg = _("Node device not found: %s"); break; case VIR_ERR_NO_SECURITY_MODEL: if (info == NULL) - errmsg = _("Security model not found"); + errmsg = _("Security model not found"); else - errmsg = _("Security model not found: %s"); + errmsg = _("Security model not found: %s"); break; case VIR_ERR_OPERATION_INVALID: if (info == NULL) - errmsg = _("Requested operation is not valid"); + errmsg = _("Requested operation is not valid"); else - errmsg = _("Requested operation is not valid: %s"); + errmsg = _("Requested operation is not valid: %s"); break; case VIR_WAR_NO_INTERFACE: if (info == NULL) @@ -1149,21 +1161,21 @@ virErrorMsg(virErrorNumber error, const char *info) break; case VIR_ERR_INVALID_NWFILTER: if (info == NULL) - errmsg = _("Invalid network filter"); + errmsg = _("Invalid network filter"); else - errmsg = _("Invalid network filter: %s"); + errmsg = _("Invalid network filter: %s"); break; case VIR_ERR_NO_NWFILTER: if (info == NULL) - errmsg = _("Network filter not found"); + errmsg = _("Network filter not found"); else - errmsg = _("Network filter not found: %s"); + errmsg = _("Network filter not found: %s"); break; case VIR_ERR_BUILD_FIREWALL: if (info == NULL) - errmsg = _("Error while building firewall"); + errmsg = _("Error while building firewall"); else - errmsg = _("Error while building firewall: %s"); + errmsg = _("Error while building firewall: %s"); break; case VIR_ERR_CONFIG_UNSUPPORTED: if (info == NULL) -- 1.7.4 From jyang at redhat.com Fri Apr 8 08:51:56 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 8 Apr 2011 16:51:56 +0800 Subject: [libvirt] [PATCH 3/3] storage: Add virsh support for fs pool formating In-Reply-To: <1302252716-31890-1-git-send-email-jyang@redhat.com> References: <1302252716-31890-1-git-send-email-jyang@redhat.com> Message-ID: <1302252716-31890-4-git-send-email-jyang@redhat.com> New changes: Add doc --- tools/virsh.c | 13 ++++++++++++- tools/virsh.pod | 12 +++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index e186c75..c9fbbf8 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -5723,6 +5723,8 @@ static const vshCmdInfo info_pool_build[] = { static const vshCmdOptDef opts_pool_build[] = { {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")}, + {"no-overwrite", VSH_OT_BOOL, 0, N_("do not overwrite an existing pool of this type")}, + {"overwrite", VSH_OT_BOOL, 0, N_("overwrite any existing data")}, {NULL, 0, 0, NULL} }; @@ -5731,6 +5733,7 @@ cmdPoolBuild(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; int ret = TRUE; + unsigned int flags = 0; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) @@ -5739,7 +5742,15 @@ cmdPoolBuild(vshControl *ctl, const vshCmd *cmd) if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) return FALSE; - if (virStoragePoolBuild(pool, 0) == 0) { + if (vshCommandOptBool (cmd, "no-overwrite")) { + flags |= VIR_STORAGE_POOL_BUILD_NO_OVERWRITE; + } + + if (vshCommandOptBool (cmd, "overwrite")) { + flags |= VIR_STORAGE_POOL_BUILD_OVERWRITE; + } + + if (virStoragePoolBuild(pool, flags) == 0) { vshPrint(ctl, _("Pool %s built\n"), name); } else { vshError(ctl, _("Failed to build pool %s"), name); diff --git a/tools/virsh.pod b/tools/virsh.pod index 580e1dc..7975d30 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -940,10 +940,20 @@ query is performed. Configure whether I should automatically start at boot. -=item B I +=item B I optional I<--overwrite> +I<--no-overwite> Build a given pool. +Options I<--overwrite> and I<--no-overwrite> can only be used for +B a filesystem pool. If neither of them is specified, +B on a filesystem pool only makes the directory; If +I<--no-overwrite> is specified, it probes to determine if a +filesystem already exists on the target device, returning an error +if exists, or using mkfs to format the target device if not; If +I<--overwrite> is specified, mkfs is always executed, any existed +data on the target device is overwritten unconditionally. + =item B I Create and start a pool object from the XML I. -- 1.7.4 From berrange at redhat.com Fri Apr 8 08:57:16 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 8 Apr 2011 09:57:16 +0100 Subject: [libvirt] [PATCH 4/6] qemu: use virObject to manage reference-counting for qemu monitor In-Reply-To: <20110408030744.GF7711@localhost.localdomain> References: <821a47bc81d57d652997fde0dec0010e3cad75d5.1302069479.git.hutao@cn.fujitsu.com> <20110407093834.GC3669@redhat.com> <20110408030744.GF7711@localhost.localdomain> Message-ID: <20110408085716.GA7187@redhat.com> On Fri, Apr 08, 2011 at 11:07:44AM +0800, Hu Tao wrote: > On Thu, Apr 07, 2011 at 10:38:34AM +0100, Daniel P. Berrange wrote: > > On Wed, Apr 06, 2011 at 03:19:55PM +0800, Hu Tao wrote: > > > --- > > > src/qemu/qemu_domain.c | 30 ++----------- > > > src/qemu/qemu_migration.c | 2 - > > > src/qemu/qemu_monitor.c | 109 ++++++++++++++++++++++++-------------------- > > > src/qemu/qemu_monitor.h | 4 +- > > > src/qemu/qemu_process.c | 32 +++++++------- > > > 5 files changed, 81 insertions(+), 96 deletions(-) > > > > > > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > > > index 3a3c953..d11dc5f 100644 > > > --- a/src/qemu/qemu_domain.c > > > +++ b/src/qemu/qemu_domain.c > > > @@ -560,9 +560,8 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) > > > { > > > qemuDomainObjPrivatePtr priv = obj->privateData; > > > > > > - qemuMonitorLock(priv->mon); > > > - qemuMonitorRef(priv->mon); > > > virDomainObjUnlock(obj); > > > + qemuMonitorLock(priv->mon); > > > } > > > > > > > > > @@ -573,18 +572,9 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) > > > void qemuDomainObjExitMonitor(virDomainObjPtr obj) > > > { > > > qemuDomainObjPrivatePtr priv = obj->privateData; > > > - int refs; > > > - > > > - refs = qemuMonitorUnref(priv->mon); > > > - > > > - if (refs > 0) > > > - qemuMonitorUnlock(priv->mon); > > > > > > + qemuMonitorUnlock(priv->mon); > > > virDomainObjLock(obj); > > > - > > > - if (refs == 0) { > > > - priv->mon = NULL; > > > - } > > > } > > > > > > > > > @@ -601,10 +591,8 @@ void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, > > > { > > > qemuDomainObjPrivatePtr priv = obj->privateData; > > > > > > - qemuMonitorLock(priv->mon); > > > - qemuMonitorRef(priv->mon); > > > virDomainObjUnlock(obj); > > > - qemuDriverUnlock(driver); > > > + qemuMonitorLock(priv->mon); > > > } > > > > > > > > > @@ -617,19 +605,9 @@ void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, > > > virDomainObjPtr obj) > > > { > > > qemuDomainObjPrivatePtr priv = obj->privateData; > > > - int refs; > > > - > > > - refs = qemuMonitorUnref(priv->mon); > > > - > > > - if (refs > 0) > > > - qemuMonitorUnlock(priv->mon); > > > > > > - qemuDriverLock(driver); > > > + qemuMonitorUnlock(priv->mon); > > > virDomainObjLock(obj); > > > - > > > - if (refs == 0) { > > > - priv->mon = NULL; > > > - } > > > } > > > > This means that the 'driver' lock is now whenever any QEMU > > monitor command is runing, which blocks the entire driver. > > qemuDomainObjEnterMonitorWithDriver is now called without holding qemu > driver lock. Well, this and the other changes in this series are completely altering all the locking rules used throughout the QEMU driver, with no clear explanation of what you are actually doing. Please read src/qemu/THREADS.txt and then provide an equivalent document explaining what you think the new rules should be, otherwise it is impossible to tell if these patches are at all threadsafe. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From jyang at redhat.com Fri Apr 8 09:06:35 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 08 Apr 2011 17:06:35 +0800 Subject: [libvirt] [PATCH 2/3] Storage: Add fs pool formatting In-Reply-To: <1302252716-31890-3-git-send-email-jyang@redhat.com> References: <1302252716-31890-1-git-send-email-jyang@redhat.com> <1302252716-31890-3-git-send-email-jyang@redhat.com> Message-ID: <4D9ED01B.7030903@redhat.com> ? 2011?04?08? 16:51, Osier Yang ??: > Previous description from Dave Allan. > > > This patch adds the ability to make the filesystem for a filesystem > pool during a pool build. > > The patch adds two new flags, no overwrite and overwrite, to control > when mkfs gets executed. By default, the patch preserves the > current behavior, i.e., if no flags are specified, pool build on a > filesystem pool only makes the directory on which the filesystem > will be mounted. > > If the no overwrite flag is specified, the target device is checked > to determine if a filesystem of the type specified in the pool is > present. If a filesystem of that type is already present, mkfs is > not executed and the build call returns an error. Otherwise, mkfs > is executed and any data present on the device is overwritten. > > If the overwrite flag is specified, mkfs is always executed, and any > existing data on the target device is overwritten unconditionally. > > Changes per feedback from eblake: > * Made probe& overwrite flags exclusive > * Changed LDFLAGS to LIBADD in Makefile.am > * Added missing virCheckFlags() > * Fixed copyright dates > * Removed cast of char * passed to libblkid and replaced it with a strdup'd copy > * Changed flags to an unsigned int in virsh.c > > Changes per feedback from Dan B. > * Changed probe flag to no-overwrite > * Moved libblkid probe code into storage_backend_fs.c > > > New changes: (per last feedback from Eric) > * s/VIR_STORAGE_POOL_PROBE_BUILT/VIR_STORAGE_POOL_BUILT/ > * Remove the internal function exporting in libvirt_private.syms > * Correct wonky spacing > > --- > include/libvirt/libvirt.h.in | 6 +- > include/libvirt/virterror.h | 2 + > src/libvirt.c | 5 +- > src/storage/storage_backend_fs.c | 191 +++++++++++++++++++++++++++++++++++++- > src/storage/storage_backend_fs.h | 7 ++ > src/util/virterror.c | 64 ++++++++----- > 6 files changed, 242 insertions(+), 33 deletions(-) > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > index d765412..e43c98a 100644 > --- a/include/libvirt/libvirt.h.in > +++ b/include/libvirt/libvirt.h.in > @@ -1335,8 +1335,10 @@ typedef enum { > > typedef enum { > VIR_STORAGE_POOL_BUILD_NEW = 0, /* Regular build from scratch */ > - VIR_STORAGE_POOL_BUILD_REPAIR = 1, /* Repair / reinitialize */ > - VIR_STORAGE_POOL_BUILD_RESIZE = 2 /* Extend existing pool */ > + VIR_STORAGE_POOL_BUILD_REPAIR = (1<< 0), /* Repair / reinitialize */ > + VIR_STORAGE_POOL_BUILD_RESIZE = (1<< 1), /* Extend existing pool */ > + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE = (1<< 2), /* Do not overwrite existing pool */ > + VIR_STORAGE_POOL_BUILD_OVERWRITE = (1<< 3), /* Overwrite data */ > } virStoragePoolBuildFlags; > > typedef enum { > diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h > index 0708e02..33fbe9a 100644 > --- a/include/libvirt/virterror.h > +++ b/include/libvirt/virterror.h > @@ -231,6 +231,8 @@ typedef enum { > VIR_ERR_INVALID_DOMAIN_SNAPSHOT = 71,/* invalid domain snapshot */ > VIR_ERR_NO_DOMAIN_SNAPSHOT = 72, /* domain snapshot not found */ > VIR_ERR_INVALID_STREAM = 73, /* stream pointer not valid */ > + VIR_ERR_STORAGE_PROBE_FAILED = 74, /* storage pool proble failed */ > + VIR_ERR_STORAGE_POOL_BUILT = 75, /* storage pool already built */ > } virErrorNumber; > > /** > diff --git a/src/libvirt.c b/src/libvirt.c > index dde4bd4..03d870b 100644 > --- a/src/libvirt.c > +++ b/src/libvirt.c > @@ -8001,7 +8001,10 @@ error: > /** > * virStoragePoolBuild: > * @pool: pointer to storage pool > - * @flags: future flags, use 0 for now > + * @flags: flags to control pool build behaviour > + * > + * Currently only filesystem pool accepts flags VIR_STORAGE_POOL_BUILD_OVERWRITE > + * and VIR_STORAGE_POOL_BUILD_NO_OVERWRITE. > * > * Build the underlying storage pool > * > diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c > index 0a6b074..54afa7c 100644 > --- a/src/storage/storage_backend_fs.c > +++ b/src/storage/storage_backend_fs.c > @@ -33,6 +33,10 @@ > #include > #include > > +#if HAVE_LIBBLKID > +# include > +#endif > + > #include > #include > #include > @@ -45,6 +49,7 @@ > #include "memory.h" > #include "xml.h" > #include "files.h" > +#include "logging.h" > > #define VIR_FROM_THIS VIR_FROM_STORAGE > > @@ -533,13 +538,173 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED, > } > #endif /* WITH_STORAGE_FS */ > > +#if HAVE_LIBBLKID > +static virStoragePoolProbeResult > +virStorageBackendFileSystemProbe(const char *device, > + const char *format) { > + > + virStoragePoolProbeResult ret = FILESYSTEM_PROBE_ERROR; > + blkid_probe probe = NULL; > + const char *fstype = NULL; > + char *names[2], *libblkid_format = NULL; > + > + VIR_DEBUG("Probing for existing filesystem of type %s on device %s", > + format, device); > + > + if (blkid_known_fstype(format) == 0) { > + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, > + _("Not capable of probing for " > + "filesystem of type %s"), > + format); > + goto error; > + } > + > + probe = blkid_new_probe_from_filename(device); > + if (probe == NULL) { > + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, > + _("Failed to create filesystem probe " > + "for device %s"), > + device); > + goto error; > + } > + > + if ((libblkid_format = strdup(format)) == NULL) { > + virReportOOMError(); > + goto error; > + } > + > + names[0] = libblkid_format; > + names[1] = NULL; > + > + blkid_probe_filter_superblocks_type(probe, > + BLKID_FLTR_ONLYIN, > + names); > + > + if (blkid_do_probe(probe) != 0) { > + VIR_INFO("No filesystem of type '%s' found on device '%s'", > + format, device); > + ret = FILESYSTEM_PROBE_NOT_FOUND; > + } else if (blkid_probe_lookup_value(probe, "TYPE",&fstype, NULL) == 0) { > + virStorageReportError(VIR_ERR_STORAGE_POOL_BUILT, > + _("Existing filesystem of type '%s' found on " > + "device '%s'"), > + fstype, device); > + ret = FILESYSTEM_PROBE_FOUND; > + } > + > + if (blkid_do_probe(probe) != 1) { > + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, > + _("Found additional probes to run, " > + "filesystem probing may be incorrect")); > + ret = FILESYSTEM_PROBE_ERROR; > + } > + > +error: > + VIR_FREE(libblkid_format); > + > + if (probe != NULL) { > + blkid_free_probe(probe); > + } > + > + return ret; > +} > + > +#else /* #if HAVE_LIBBLKID */ > + > +static virStoragePoolProbeResult > +virStorageBackendFileSystemProbe(const char *device ATTRIBUTE_UNUSED, > + const char *format ATTRIBUTE_UNUSED) > +{ > + virStorageReportError(VIR_ERR_OPERATION_INVALID, > + _("probing for filesystems is unsupported " > + "by this build")); > + > + return FILESYSTEM_PROBE_ERROR; > +} > + > +#endif /* #if HAVE_LIBBLKID */ > + > +static int > +virStorageBackendExecuteMKFS(const char *device, > + const char *format) > +{ > + int ret = 0; > + const char *mkfsargv[5] = { MKFS, > + "-t", > + format, > + device, > + NULL }; Ah, I kept in my mind to change this to virCommandRun, but forgot finally. > + > + if (virRun(mkfsargv, NULL)< 0) { > + virReportSystemError(errno, > + _("Failed to make filesystem of " > + "type '%s' on device '%s'"), > + format, device); > + ret = -1; > + } > + > + return ret; > +} > + > + > +static int > +virStorageBackendMakeFileSystem(virStoragePoolObjPtr pool, > + unsigned int flags) > +{ > + const char *device = NULL, *format = NULL; > + bool ok_to_mkfs = false; > + int ret = -1; > + > + if (pool->def->source.devices == NULL) { > + virStorageReportError(VIR_ERR_OPERATION_INVALID, > + _("No source device specified when formatting pool '%s'"), > + pool->def->name); > + goto error; > + } > + > + device = pool->def->source.devices[0].path; > + format = virStoragePoolFormatFileSystemTypeToString(pool->def->source.format); > + VIR_DEBUG("source device: '%s' format: '%s'", device, format); > + > + if (!virFileExists(device)) { > + virStorageReportError(VIR_ERR_OPERATION_INVALID, > + _("Source device does not exist when formatting pool '%s'"), > + pool->def->name); > + goto error; > + } > + > + if (flags& VIR_STORAGE_POOL_BUILD_OVERWRITE) { > + ok_to_mkfs = true; > + } else if (flags& VIR_STORAGE_POOL_BUILD_NO_OVERWRITE&& > + virStorageBackendFileSystemProbe(device, format) == > + FILESYSTEM_PROBE_NOT_FOUND) { > + ok_to_mkfs = true; > + } > + > + if (ok_to_mkfs) { > + ret = virStorageBackendExecuteMKFS(device, format); > + } > + > +error: > + return ret; > +} > + > + > > /** > * @conn connection to report errors against > * @pool storage pool to build > + * @flags controls the pool formating behaviour > * > * Build a directory or FS based storage pool. > * > + * If no flag is set, it only makes the directory; If > + * VIR_STORAGE_POOL_BUILD_NO_OVERWRITE set, it probes to determine if > + * a filesystem already exists on the target device, returning an error > + * if exists, or using mkfs to format the target device if not; If > + * VIR_STORAGE_POOL_BUILD_OVERWRITE is set, mkfs is always executed, > + * any existed data on the target device is overwritten unconditionally. > + * > * - If it is a FS based pool, mounts the unlying source device on the pool > * > * Returns 0 on success, -1 on error > @@ -547,11 +712,23 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED, > static int > virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, > virStoragePoolObjPtr pool, > - unsigned int flags ATTRIBUTE_UNUSED) > + unsigned int flags) > { > int err, ret = -1; > - char *parent; > - char *p; > + char *parent = NULL; > + char *p = NULL; > + > + virCheckFlags(VIR_STORAGE_POOL_BUILD_OVERWRITE | > + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, ret); > + > + if (flags == (VIR_STORAGE_POOL_BUILD_OVERWRITE | > + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE)) { > + > + virStorageReportError(VIR_ERR_OPERATION_INVALID, > + _("Overwrite and no overwrite flags" > + " are mutually exclusive")); > + goto error; > + } > > if ((parent = strdup(pool->def->target.path)) == NULL) { > virReportOOMError(); > @@ -601,7 +778,13 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, > goto error; > } > } > - ret = 0; > + > + if (flags != 0) { > + ret = virStorageBackendMakeFileSystem(pool, flags); > + } else { > + ret = 0; > + } > + > error: > VIR_FREE(parent); > return ret; > diff --git a/src/storage/storage_backend_fs.h b/src/storage/storage_backend_fs.h > index 7def53e..394e552 100644 > --- a/src/storage/storage_backend_fs.h > +++ b/src/storage/storage_backend_fs.h > @@ -29,6 +29,13 @@ > # if WITH_STORAGE_FS > extern virStorageBackend virStorageBackendFileSystem; > extern virStorageBackend virStorageBackendNetFileSystem; > + > +typedef enum { > + FILESYSTEM_PROBE_FOUND, > + FILESYSTEM_PROBE_NOT_FOUND, > + FILESYSTEM_PROBE_ERROR, > +} virStoragePoolProbeResult; > + > # endif > extern virStorageBackend virStorageBackendDirectory; > > diff --git a/src/util/virterror.c b/src/util/virterror.c > index b7d8924..4450a43 100644 > --- a/src/util/virterror.c > +++ b/src/util/virterror.c > @@ -1041,63 +1041,75 @@ virErrorMsg(virErrorNumber error, const char *info) > break; > case VIR_ERR_NO_STORAGE_POOL: > if (info == NULL) > - errmsg = _("Storage pool not found"); > + errmsg = _("Storage pool not found"); > else > - errmsg = _("Storage pool not found: %s"); > + errmsg = _("Storage pool not found: %s"); > break; > case VIR_ERR_NO_STORAGE_VOL: > if (info == NULL) > - errmsg = _("Storage volume not found"); > + errmsg = _("Storage volume not found"); > else > - errmsg = _("Storage volume not found: %s"); > + errmsg = _("Storage volume not found: %s"); > + break; > + case VIR_ERR_STORAGE_PROBE_FAILED: > + if (info == NULL) > + errmsg = _("Storage pool probe failed"); > + else > + errmsg = _("Storage pool probe failed: %s"); > + break; > + case VIR_ERR_STORAGE_POOL_BUILT: > + if (info == NULL) > + errmsg = _("Storage pool already built"); > + else > + errmsg = _("Storage pool already built: %s"); > break; > case VIR_ERR_INVALID_STORAGE_POOL: > if (info == NULL) > - errmsg = _("invalid storage pool pointer in"); > + errmsg = _("invalid storage pool pointer in"); > else > - errmsg = _("invalid storage pool pointer in %s"); > + errmsg = _("invalid storage pool pointer in %s"); > break; > case VIR_ERR_INVALID_STORAGE_VOL: > if (info == NULL) > - errmsg = _("invalid storage volume pointer in"); > + errmsg = _("invalid storage volume pointer in"); > else > - errmsg = _("invalid storage volume pointer in %s"); > + errmsg = _("invalid storage volume pointer in %s"); > break; > case VIR_WAR_NO_STORAGE: > if (info == NULL) > - errmsg = _("Failed to find a storage driver"); > + errmsg = _("Failed to find a storage driver"); > else > - errmsg = _("Failed to find a storage driver: %s"); > + errmsg = _("Failed to find a storage driver: %s"); > break; > case VIR_WAR_NO_NODE: > if (info == NULL) > - errmsg = _("Failed to find a node driver"); > + errmsg = _("Failed to find a node driver"); > else > - errmsg = _("Failed to find a node driver: %s"); > + errmsg = _("Failed to find a node driver: %s"); > break; > case VIR_ERR_INVALID_NODE_DEVICE: > if (info == NULL) > - errmsg = _("invalid node device pointer"); > + errmsg = _("invalid node device pointer"); > else > - errmsg = _("invalid node device pointer in %s"); > + errmsg = _("invalid node device pointer in %s"); > break; > case VIR_ERR_NO_NODE_DEVICE: > if (info == NULL) > - errmsg = _("Node device not found"); > + errmsg = _("Node device not found"); > else > - errmsg = _("Node device not found: %s"); > + errmsg = _("Node device not found: %s"); > break; > case VIR_ERR_NO_SECURITY_MODEL: > if (info == NULL) > - errmsg = _("Security model not found"); > + errmsg = _("Security model not found"); > else > - errmsg = _("Security model not found: %s"); > + errmsg = _("Security model not found: %s"); > break; > case VIR_ERR_OPERATION_INVALID: > if (info == NULL) > - errmsg = _("Requested operation is not valid"); > + errmsg = _("Requested operation is not valid"); > else > - errmsg = _("Requested operation is not valid: %s"); > + errmsg = _("Requested operation is not valid: %s"); > break; > case VIR_WAR_NO_INTERFACE: > if (info == NULL) > @@ -1149,21 +1161,21 @@ virErrorMsg(virErrorNumber error, const char *info) > break; > case VIR_ERR_INVALID_NWFILTER: > if (info == NULL) > - errmsg = _("Invalid network filter"); > + errmsg = _("Invalid network filter"); > else > - errmsg = _("Invalid network filter: %s"); > + errmsg = _("Invalid network filter: %s"); > break; > case VIR_ERR_NO_NWFILTER: > if (info == NULL) > - errmsg = _("Network filter not found"); > + errmsg = _("Network filter not found"); > else > - errmsg = _("Network filter not found: %s"); > + errmsg = _("Network filter not found: %s"); > break; > case VIR_ERR_BUILD_FIREWALL: > if (info == NULL) > - errmsg = _("Error while building firewall"); > + errmsg = _("Error while building firewall"); > else > - errmsg = _("Error while building firewall: %s"); > + errmsg = _("Error while building firewall: %s"); > break; > case VIR_ERR_CONFIG_UNSUPPORTED: > if (info == NULL) From hutao at cn.fujitsu.com Fri Apr 8 09:09:22 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Fri, 8 Apr 2011 17:09:22 +0800 Subject: [libvirt] [PATCH 4/6] qemu: use virObject to manage reference-counting for qemu monitor In-Reply-To: <20110408085716.GA7187@redhat.com> References: <821a47bc81d57d652997fde0dec0010e3cad75d5.1302069479.git.hutao@cn.fujitsu.com> <20110407093834.GC3669@redhat.com> <20110408030744.GF7711@localhost.localdomain> <20110408085716.GA7187@redhat.com> Message-ID: <20110408090922.GA9748@localhost.localdomain> On Fri, Apr 08, 2011 at 09:57:16AM +0100, Daniel P. Berrange wrote: > On Fri, Apr 08, 2011 at 11:07:44AM +0800, Hu Tao wrote: > > On Thu, Apr 07, 2011 at 10:38:34AM +0100, Daniel P. Berrange wrote: > > > On Wed, Apr 06, 2011 at 03:19:55PM +0800, Hu Tao wrote: > > > > --- > > > > src/qemu/qemu_domain.c | 30 ++----------- > > > > src/qemu/qemu_migration.c | 2 - > > > > src/qemu/qemu_monitor.c | 109 ++++++++++++++++++++++++-------------------- > > > > src/qemu/qemu_monitor.h | 4 +- > > > > src/qemu/qemu_process.c | 32 +++++++------- > > > > 5 files changed, 81 insertions(+), 96 deletions(-) > > > > > > > > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > > > > index 3a3c953..d11dc5f 100644 > > > > --- a/src/qemu/qemu_domain.c > > > > +++ b/src/qemu/qemu_domain.c > > > > @@ -560,9 +560,8 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) > > > > { > > > > qemuDomainObjPrivatePtr priv = obj->privateData; > > > > > > > > - qemuMonitorLock(priv->mon); > > > > - qemuMonitorRef(priv->mon); > > > > virDomainObjUnlock(obj); > > > > + qemuMonitorLock(priv->mon); > > > > } > > > > > > > > > > > > @@ -573,18 +572,9 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) > > > > void qemuDomainObjExitMonitor(virDomainObjPtr obj) > > > > { > > > > qemuDomainObjPrivatePtr priv = obj->privateData; > > > > - int refs; > > > > - > > > > - refs = qemuMonitorUnref(priv->mon); > > > > - > > > > - if (refs > 0) > > > > - qemuMonitorUnlock(priv->mon); > > > > > > > > + qemuMonitorUnlock(priv->mon); > > > > virDomainObjLock(obj); > > > > - > > > > - if (refs == 0) { > > > > - priv->mon = NULL; > > > > - } > > > > } > > > > > > > > > > > > @@ -601,10 +591,8 @@ void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, > > > > { > > > > qemuDomainObjPrivatePtr priv = obj->privateData; > > > > > > > > - qemuMonitorLock(priv->mon); > > > > - qemuMonitorRef(priv->mon); > > > > virDomainObjUnlock(obj); > > > > - qemuDriverUnlock(driver); > > > > + qemuMonitorLock(priv->mon); > > > > } > > > > > > > > > > > > @@ -617,19 +605,9 @@ void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, > > > > virDomainObjPtr obj) > > > > { > > > > qemuDomainObjPrivatePtr priv = obj->privateData; > > > > - int refs; > > > > - > > > > - refs = qemuMonitorUnref(priv->mon); > > > > - > > > > - if (refs > 0) > > > > - qemuMonitorUnlock(priv->mon); > > > > > > > > - qemuDriverLock(driver); > > > > + qemuMonitorUnlock(priv->mon); > > > > virDomainObjLock(obj); > > > > - > > > > - if (refs == 0) { > > > > - priv->mon = NULL; > > > > - } > > > > } > > > > > > This means that the 'driver' lock is now whenever any QEMU > > > monitor command is runing, which blocks the entire driver. > > > > qemuDomainObjEnterMonitorWithDriver is now called without holding qemu > > driver lock. > > Well, this and the other changes in this series are completely > altering all the locking rules used throughout the QEMU > driver, with no clear explanation of what you are actually > doing. Please read src/qemu/THREADS.txt and then provide an > equivalent document explaining what you think the new rules > should be, otherwise it is impossible to tell if these patches > are at all threadsafe. Sorry I didn't make this clear, will do in next version. From veillard at redhat.com Fri Apr 8 10:44:47 2011 From: veillard at redhat.com (Daniel Veillard) Date: Fri, 8 Apr 2011 18:44:47 +0800 Subject: [libvirt] [PATCH] build: Install libxenlight log dir In-Reply-To: <1302214413-22855-1-git-send-email-jfehlig@novell.com> References: <1302214413-22855-1-git-send-email-jfehlig@novell.com> Message-ID: <20110408104447.GD24838@redhat.com> On Thu, Apr 07, 2011 at 04:13:33PM -0600, Jim Fehlig wrote: > Add $localstatedir/log/libvirt/libxl when building libxenlight driver > --- > src/Makefile.am | 2 ++ > 1 files changed, 2 insertions(+), 0 deletions(-) > > diff --git a/src/Makefile.am b/src/Makefile.am > index 9b54679..3649106 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -1275,6 +1275,7 @@ endif > if WITH_LIBXL > $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/libxl" > $(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/libxl" > + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/log/libvirt/libxl" > endif > if WITH_UML > $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/uml" > @@ -1316,6 +1317,7 @@ endif > if WITH_LIBXL > rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/libxl" ||: > rmdir "$(DESTDIR)$(localstatedir)/run/libvirt/libxl" ||: > + rmdir "$(DESTDIR)$(localstatedir)/log/libvirt/libxl" ||: > endif > if WITH_UML > rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/uml" ||: Heh, I discovered independantly the first part but forgot the second, ACK ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Fri Apr 8 10:45:28 2011 From: veillard at redhat.com (Daniel Veillard) Date: Fri, 8 Apr 2011 18:45:28 +0800 Subject: [libvirt] [PATCH] libxl: missing directory creation for logs In-Reply-To: <20110408071947.GC30371@redhat.com> References: <20110408071947.GC30371@redhat.com> Message-ID: <20110408104528.GE24838@redhat.com> On Fri, Apr 08, 2011 at 03:19:47PM +0800, Daniel Veillard wrote: > Libvirt-0.9.0 wasn't building for Fedora 16, the spec file referenced > a log directory missing in teh install tree. After checking that the > code actually needed that directory, the following patch solves the > problem, Self NAK, Jim' patch does it and is more complete. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Fri Apr 8 10:48:34 2011 From: veillard at redhat.com (Daniel Veillard) Date: Fri, 8 Apr 2011 18:48:34 +0800 Subject: [libvirt] [PATCH] do not build libvirt_iohelper when building without libvirtd In-Reply-To: <4D9E8077.1080003@cn.fujitsu.com> References: <4D9E8077.1080003@cn.fujitsu.com> Message-ID: <20110408104834.GF24838@redhat.com> On Fri, Apr 08, 2011 at 11:26:47AM +0800, Wen Congyang wrote: > The libexec program libvirt_iohelper is only for libvirtd. If we build rpm > without libvirtd, we will receive the following messages: > > Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/wency/rpmbuild/BUILDROOT/libvirt-0.9.0-1.el6.x86_64 > error: Installed (but unpackaged) file(s) found: > /usr/libexec/libvirt_iohelper > > --- > src/Makefile.am | 2 ++ > 1 files changed, 2 insertions(+), 0 deletions(-) > > diff --git a/src/Makefile.am b/src/Makefile.am > index 3649106..dce866e 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -1183,6 +1183,7 @@ EXTRA_DIST += $(LIBVIRT_QEMU_SYMBOL_FILE) > > libexec_PROGRAMS = > > +if WITH_LIBVIRTD > libexec_PROGRAMS += libvirt_iohelper > libvirt_iohelper_SOURCES = $(UTIL_IO_HELPER_SOURCES) > libvirt_iohelper_LDFLAGS = $(WARN_LDFLAGS) $(AM_LDFLAGS) > @@ -1191,6 +1192,7 @@ libvirt_iohelper_LDADD = \ > ../gnulib/lib/libgnu.la > > libvirt_iohelper_CFLAGS = $(AM_CFLAGS) > +endif > > if WITH_STORAGE_DISK > if WITH_LIBVIRTD sounds right, ACK Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From usui at mxm.nes.nec.co.jp Fri Apr 8 11:19:32 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 8 Apr 2011 20:19:32 +0900 Subject: [libvirt] [PATCHv2 0/6] Add virNodeGetCpuTime() API Message-ID: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> Hi, This is v2 of virNodeGetCpuTime() API. It returns cpu utilization or cumulative cpu time of the node from /proc/stat since node boots up. This patch only supports linux host. Changes v1->v2 - Change user I/F like virDomainGetMemoryStats() - It can return either cpu utilization or cumulative cpu time of the node depends on each driver. Minoru Usui (6): [v2 1/6] virNodeGetCPUTime: Expose new API [v2 2/6] virNodeGetCPUTime: Define internal driver API [v2 3/6] virNodeGetCPUTime: Implement public API [v2 4/6] virNodeGetCPUTime: Implement remote protocol [v2 5/6] virNodeGetCPUTime: Implement virsh support [v2 6/6] virNodeGetCPUTime: Implement linux support daemon/remote.c | 48 +++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 +++ daemon/remote_dispatch_ret.h | 1 + daemon/remote_dispatch_table.h | 5 ++ include/libvirt/libvirt.h.in | 64 +++++++++++++++++++++++ src/driver.h | 8 +++ src/esx/esx_driver.c | 1 + src/libvirt.c | 70 +++++++++++++++++++++++++ src/libvirt_private.syms | 1 + src/libvirt_public.syms | 5 ++ src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/nodeinfo.c | 78 ++++++++++++++++++++++++++++ src/nodeinfo.h | 5 ++- src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 38 ++++++++++++++ src/remote/remote_protocol.c | 33 ++++++++++++ src/remote/remote_protocol.h | 28 ++++++++++ src/remote/remote_protocol.x | 20 +++++++- src/remote_protocol-structs | 14 +++++ src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xenapi/xenapi_driver.c | 1 + tools/virsh.c | 96 +++++++++++++++++++++++++++++++++++ tools/virsh.pod | 4 ++ 31 files changed, 537 insertions(+), 2 deletions(-) -- Minoru Usui From usui at mxm.nes.nec.co.jp Fri Apr 8 11:33:12 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 8 Apr 2011 20:33:12 +0900 Subject: [libvirt] [PATCHv2 1/6] virNodeGetCPUTime: Expose new API In-Reply-To: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> Message-ID: <20110408203312.90723b75.usui@mxm.nes.nec.co.jp> virNodeGetCPUTime: Expose new API Signed-off-by: Minoru Usui --- include/libvirt/libvirt.h.in | 64 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++ 2 files changed, 69 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index bd36015..154c138 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -228,6 +228,57 @@ struct _virNodeInfo { unsigned int threads;/* number of threads per core */ }; +/** + * virNodeCpuTime: + * + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing + * the information for the cpu time of the node. + */ + +/** + * Cpu Time Statistics Tags: + */ +typedef enum { + /* + * The cumulative CPU time which spends by kernel, + * when the node booting up.(in nanoseconds). + */ + VIR_NODE_CPU_TIME_KERNEL = 0, + /* + * The cumulative CPU time which spends by user processes, + * when the node booting up.(in nanoseconds). + */ + VIR_NODE_CPU_TIME_USER = 1, + /* + * The cumulative idle CPU time, + * when the node booting up.(in nanoseconds). + */ + VIR_NODE_CPU_TIME_IDLE = 2, + /* + * The cumulative I/O wait CPU time, + * when the node booting up.(in nanoseconds). + */ + VIR_NODE_CPU_TIME_IOWAIT = 3, + /* + * The CPU utilization. + * The usage value is in percent and 100% represents all CPUs on + * the server. + */ + VIR_NODE_CPU_TIME_UTILIZATION = 4, + + /* + * The number of statistics supported by this version of the interface. + * To add new statistics, add them to the enum and increase this value. + */ + VIR_NODE_CPU_TIME_NR = 5, +} virNodeCpuTimeTags; + +typedef struct _virNodeCpuTime virNodeCpuTime; + +struct _virNodeCpuTime { + virNodeCpuTimeTags tag; + unsigned long long val; +}; /** * virDomainSchedParameterType: @@ -460,6 +511,14 @@ int virDomainMigrateSetMaxSpeed(virDomainPtr domain, typedef virNodeInfo *virNodeInfoPtr; /** + * virNodeCpuTimePtr: + * + * a virNodeCpuTimePtr is a pointer to a virNodeCpuTime structure. + */ + +typedef virNodeCpuTime *virNodeCpuTimePtr; + +/** * virConnectFlags * * Flags when opening a connection to a hypervisor @@ -593,6 +652,11 @@ int virNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info); char * virConnectGetCapabilities (virConnectPtr conn); +int virNodeGetCpuTime (virConnectPtr conn, + virNodeCpuTimePtr stats, + unsigned int nr_stats, + unsigned int flags); + unsigned long long virNodeGetFreeMemory (virConnectPtr conn); int virNodeGetSecurityModel (virConnectPtr conn, diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b4aed41..d292bdd 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -436,4 +436,9 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8; +LIBVIRT_0.9.1 { + global: + virNodeGetCpuTime; +} LIBVIRT_0.9.0; + # .... define new API here using predicted next version number .... -- 1.7.1 -- Minoru Usui From usui at mxm.nes.nec.co.jp Fri Apr 8 11:34:14 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 8 Apr 2011 20:34:14 +0900 Subject: [libvirt] [PATCHv2 2/6] virNodeGetCPUTime: Define internal driver API In-Reply-To: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> Message-ID: <20110408203414.1e30f0d9.usui@mxm.nes.nec.co.jp> virNodeGetCPUTime: Define internal driver API Signed-off-by: Minoru Usui --- src/driver.h | 8 ++++++++ src/esx/esx_driver.c | 1 + src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 1 + src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xenapi/xenapi_driver.c | 1 + 14 files changed, 21 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index e5f91ca..e03bcd4 100644 --- a/src/driver.h +++ b/src/driver.h @@ -347,6 +347,13 @@ typedef struct _virDriver virDriver; typedef virDriver *virDriverPtr; typedef int + (*virDrvNodeGetCpuTime) + (virConnectPtr conn, + struct _virNodeCpuTime *stats, + unsigned int nr_stats, + unsigned int flags); + +typedef int (*virDrvNodeGetCellsFreeMemory) (virConnectPtr conn, unsigned long long *freeMems, @@ -602,6 +609,7 @@ struct _virDriver { virDrvDomainBlockPeek domainBlockPeek; virDrvDomainMemoryPeek domainMemoryPeek; virDrvDomainGetBlockInfo domainGetBlockInfo; + virDrvNodeGetCpuTime nodeGetCpuTime; virDrvNodeGetCellsFreeMemory nodeGetCellsFreeMemory; virDrvNodeGetFreeMemory getFreeMemory; virDrvDomainEventRegister domainEventRegister; diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index deda372..6e55949 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4638,6 +4638,7 @@ static virDriver esxDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ NULL, /* nodeGetCellsFreeMemory */ esxNodeGetFreeMemory, /* nodeGetFreeMemory */ NULL, /* domainEventRegister */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 75f99c1..a9907a1 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2443,6 +2443,7 @@ static virDriver libxlDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ NULL, /* nodeGetCellsFreeMemory */ libxlNodeGetFreeMemory, /* getFreeMemory */ libxlDomainEventRegister, /* domainEventRegister */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e905302..0e0c325 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2869,6 +2869,7 @@ static virDriver lxcDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + nodeGetCpuTime, /* nodeGetCpuTime */ nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ nodeGetFreeMemory, /* getFreeMemory */ lxcDomainEventRegister, /* domainEventRegister */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index fb30c37..7335c8d 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1617,6 +1617,7 @@ static virDriver openvzDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ NULL, /* nodeGetCellsFreeMemory */ NULL, /* getFreeMemory */ NULL, /* domainEventRegister */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index b17d90b..e274cef 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -4026,6 +4026,7 @@ static virDriver phypDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ NULL, /* nodeGetCellsFreeMemory */ NULL, /* getFreeMemory */ NULL, /* domainEventRegister */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 48fe266..dca8f5c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6889,6 +6889,7 @@ static virDriver qemuDriver = { qemudDomainBlockPeek, /* domainBlockPeek */ qemudDomainMemoryPeek, /* domainMemoryPeek */ qemuDomainGetBlockInfo, /* domainGetBlockInfo */ + nodeGetCpuTime, /* nodeGetCpuTime */ nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ nodeGetFreeMemory, /* getFreeMemory */ qemuDomainEventRegister, /* domainEventRegister */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 166968a..8bac0cc 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -11261,6 +11261,7 @@ static virDriver remote_driver = { remoteDomainBlockPeek, /* domainBlockPeek */ remoteDomainMemoryPeek, /* domainMemoryPeek */ remoteDomainGetBlockInfo, /* domainGetBlockInfo */ + remoteNodeGetCpuTime, /* nodeGetCpuTime */ remoteNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ remoteNodeGetFreeMemory, /* getFreeMemory */ remoteDomainEventRegister, /* domainEventRegister */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 17f5ad9..f122935 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5410,6 +5410,7 @@ static virDriver testDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ NULL, /* getFreeMemory */ testDomainEventRegister, /* domainEventRegister */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index e2bd5f2..93fb59e 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2212,6 +2212,7 @@ static virDriver umlDriver = { umlDomainBlockPeek, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + nodeGetCpuTime, /* nodeGetCpuTime */ nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ nodeGetFreeMemory, /* getFreeMemory */ NULL, /* domainEventRegister */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 0fbfba5..d500ab2 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8600,6 +8600,7 @@ virDriver NAME(Driver) = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ nodeGetFreeMemory, /* getFreeMemory */ #if VBOX_API_VERSION == 2002 || VBOX_API_VERSION == 4000 diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index b5e416b..635aa59 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -970,6 +970,7 @@ static virDriver vmwareDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ NULL, /* nodeGetCellsFreeMemory */ NULL, /* getFreeMemory */ NULL, /* domainEventRegister */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 9f47722..af18baa 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2104,6 +2104,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedDomainBlockPeek, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ xenUnifiedNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ xenUnifiedNodeGetFreeMemory, /* getFreeMemory */ xenUnifiedDomainEventRegister, /* domainEventRegister */ diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 60b23c7..6371d03 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1852,6 +1852,7 @@ static virDriver xenapiDriver = { NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ + NULL, /* nodeGetCpuTime */ xenapiNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ xenapiNodeGetFreeMemory, /* getFreeMemory */ NULL, /* domainEventRegister */ -- 1.7.1 -- Minoru Usui From usui at mxm.nes.nec.co.jp Fri Apr 8 11:35:12 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 8 Apr 2011 20:35:12 +0900 Subject: [libvirt] [PATCHv2 3/6] virNodeGetCPUTime: Implement public API In-Reply-To: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> Message-ID: <20110408203512.44ba817c.usui@mxm.nes.nec.co.jp> virNodeGetCPUTime: Implement public API Signed-off-by: Minoru Usui --- src/libvirt.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 70 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 8be18d4..a65bfc6 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -4260,6 +4260,76 @@ error: } /** + * virNodeGetCpuTime: + * @stats: nr_stats-sized array of stat structures (returned) + * @nr_stats: number of cpu time statistics requested of the node. + * @flags: unused, always pass 0 + * + * This function provides cpu time statistics of the node. + * + * Up to 'nr_stats' elements of 'stats' will be populated with cpu time statistics + * of the node. Only statistics supported by the driver, and this version of + * libvirt will be returned. + * + * Cpu time Statistics: + * + * VIR_NODE_CPU_TIME_KERNEL: + * The cumulative CPU time which spends by kernel, + * when the node booting up.(nanoseconds) + * VIR_NODE_CPU_TIME_USER: + * The cumulative CPU time which spends by user processes, + * when the node booting up.(nanoseconds) + * VIR_NODE_CPU_TIME_IDLE: + * The cumulative idle CPU time, when the node booting up.(nanoseconds) + * VIR_NODE_CPU_TIME_IOWAIT: + * The cumulative I/O wait CPU time, when the node booting up.(nanoseconds) + * VIR_NODE_CPU_TIME_UTILIZATION: + * The CPU utilization. The usage value is in percent and 100% + * represents all CPUs on the server. + * + * Returns: The number of stats provided or -1 in case of failure. + */ +int virNodeGetCpuTime (virConnectPtr conn, virNodeCpuTimePtr stats, + unsigned int nr_stats, unsigned int flags) +{ + unsigned long nr_stats_ret = 0; + + VIR_DEBUG("conn=%p, stats=%p, nr_stats=%u", conn, stats, nr_stats); + + virResetLastError(); + + if (!VIR_IS_CONNECT (conn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return 0; + } + + if (flags != 0) { + virLibConnError(VIR_ERR_INVALID_ARG, _("flags must be zero")); + goto error; + } + + if (!stats || nr_stats == 0) + return 0; + + if (nr_stats > VIR_NODE_CPU_TIME_NR) + nr_stats = VIR_NODE_CPU_TIME_NR; + + if (conn->driver->nodeGetCpuTime) { + nr_stats_ret = conn->driver->nodeGetCpuTime (conn, stats, nr_stats, flags); + if (nr_stats_ret == -1) + goto error; + return nr_stats_ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return -1; +} + +/** * virNodeGetFreeMemory: * @conn: pointer to the hypervisor connection * -- 1.7.1 -- Minoru Usui From usui at mxm.nes.nec.co.jp Fri Apr 8 11:36:02 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 8 Apr 2011 20:36:02 +0900 Subject: [libvirt] [PATCHv2 4/6] virNodeGetCPUTime: Implement remote protocol In-Reply-To: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> Message-ID: <20110408203602.7765f701.usui@mxm.nes.nec.co.jp> virNodeGetCPUTime: Implement remote protocol Signed-off-by: Minoru Usui --- daemon/remote.c | 48 +++++++++++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++++ daemon/remote_dispatch_ret.h | 1 + daemon/remote_dispatch_table.h | 5 +++ src/remote/remote_driver.c | 37 +++++++++++++++++++++++++++ src/remote/remote_protocol.c | 33 ++++++++++++++++++++++++ src/remote/remote_protocol.h | 28 ++++++++++++++++++++ src/remote/remote_protocol.x | 20 ++++++++++++++- src/remote_protocol-structs | 14 ++++++++++ 10 files changed, 194 insertions(+), 1 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 1700c2d..a6c21eb 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -679,6 +679,54 @@ remoteDispatchGetCapabilities (struct qemud_server *server ATTRIBUTE_UNUSED, } static int +remoteDispatchNodeGetCpuTime (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_get_cpu_time_args *args, + remote_node_get_cpu_time_ret *ret) +{ + struct _virNodeCpuTime *stats; + unsigned int nr_stats, i; + + if (args->maxStats > REMOTE_NODE_CPU_TIME_MAX) { + remoteDispatchFormatError (rerr, "%s", + _("maxStats > REMOTE_NODE_CPU_TIME_MAX")); + return -1; + } + + /* Allocate stats array for making dispatch call */ + if (VIR_ALLOC_N(stats, args->maxStats) < 0) { + remoteDispatchOOMError(rerr); + return -1; + } + + nr_stats = virNodeGetCpuTime (conn, stats, args->maxStats, 0); + if (nr_stats == -1) { + VIR_FREE(stats); + remoteDispatchConnError(rerr, conn); + return -1; + } + + /* Allocate return buffer */ + if (VIR_ALLOC_N(ret->stats.stats_val, args->maxStats) < 0) { + VIR_FREE(stats); + remoteDispatchOOMError(rerr); + return -1; + } + + /* Copy the stats into the xdr return structure */ + for (i = 0; i < nr_stats; i++) { + ret->stats.stats_val[i].tag = stats[i].tag; + ret->stats.stats_val[i].val = stats[i].val; + } + ret->stats.stats_len = nr_stats; + VIR_FREE(stats); + return 0; +} + +static int remoteDispatchNodeGetCellsFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index f9537d7..a757899 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -178,3 +178,4 @@ remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; remote_storage_vol_upload_args val_remote_storage_vol_upload_args; remote_storage_vol_download_args val_remote_storage_vol_download_args; + remote_node_get_cpu_time_args val_remote_node_get_cpu_time_args; diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 18bf41d..936ba23 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -1138,6 +1138,14 @@ static int remoteDispatchNodeGetCellsFreeMemory( remote_error *err, remote_node_get_cells_free_memory_args *args, remote_node_get_cells_free_memory_ret *ret); +static int remoteDispatchNodeGetCpuTime( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_node_get_cpu_time_args *args, + remote_node_get_cpu_time_ret *ret); static int remoteDispatchNodeGetFreeMemory( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_ret.h b/daemon/remote_dispatch_ret.h index 114e832..dfed98b 100644 --- a/daemon/remote_dispatch_ret.h +++ b/daemon/remote_dispatch_ret.h @@ -140,3 +140,4 @@ remote_domain_is_updated_ret val_remote_domain_is_updated_ret; remote_get_sysinfo_ret val_remote_get_sysinfo_ret; remote_domain_get_blkio_parameters_ret val_remote_domain_get_blkio_parameters_ret; + remote_node_get_cpu_time_ret val_remote_node_get_cpu_time_ret; diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index b39f7c2..5922d56 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1052,3 +1052,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* NodeGetCpuTime => 210 */ + .fn = (dispatch_fn) remoteDispatchNodeGetCpuTime, + .args_filter = (xdrproc_t) xdr_remote_node_get_cpu_time_args, + .ret_filter = (xdrproc_t) xdr_remote_node_get_cpu_time_ret, +}, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 8bac0cc..20c6e75 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1936,6 +1936,43 @@ done: } static int +remoteNodeGetCpuTime (virConnectPtr conn, + virNodeCpuTimePtr stats, + unsigned int nr_stats, + unsigned int flags) +{ + int rv = -1; + remote_node_get_cpu_time_args args; + remote_node_get_cpu_time_ret ret; + struct private_data *priv = conn->privateData; + unsigned int i; + + remoteDriverLock(priv); + + args.maxStats = nr_stats; + args.flags = flags; + memset (&ret, 0, sizeof ret); + + if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_CPU_TIME, + (xdrproc_t) xdr_remote_node_get_cpu_time_args, + (char *) &args, + (xdrproc_t) xdr_remote_node_get_cpu_time_ret, + (char *) &ret) == -1) + goto done; + + for (i = 0; i < ret.stats.stats_len; i++) { + stats[i].tag = ret.stats.stats_val[i].tag; + stats[i].val = ret.stats.stats_val[i].val; + } + rv = ret.stats.stats_len; + xdr_free((xdrproc_t) xdr_remote_node_get_cpu_time_ret, (char *) &ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int remoteNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems, int startCell, diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 5604371..e7bb93d 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -607,6 +607,39 @@ xdr_remote_get_capabilities_ret (XDR *xdrs, remote_get_capabilities_ret *objp) } bool_t +xdr_remote_node_get_cpu_time_args (XDR *xdrs, remote_node_get_cpu_time_args *objp) +{ + + if (!xdr_u_int (xdrs, &objp->maxStats)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_node_cpu_time (XDR *xdrs, remote_node_cpu_time *objp) +{ + + if (!xdr_int (xdrs, &objp->tag)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->val)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_node_get_cpu_time_ret (XDR *xdrs, remote_node_get_cpu_time_ret *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->stats.stats_val; + + if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->stats.stats_len, REMOTE_NODE_CPU_TIME_MAX, + sizeof (remote_node_cpu_time), (xdrproc_t) xdr_remote_node_cpu_time)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_node_get_cells_free_memory_args (XDR *xdrs, remote_node_get_cells_free_memory_args *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index d9bf151..42ad76b 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -55,6 +55,7 @@ typedef remote_nonnull_string *remote_string; #define REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX 16 #define REMOTE_DOMAIN_BLKIO_PARAMETERS_MAX 16 #define REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX 16 +#define REMOTE_NODE_CPU_TIME_MAX 8 #define REMOTE_NODE_MAX_CELLS 1024 #define REMOTE_AUTH_SASL_DATA_MAX 65536 #define REMOTE_AUTH_TYPE_LIST_MAX 20 @@ -304,6 +305,26 @@ struct remote_get_capabilities_ret { }; typedef struct remote_get_capabilities_ret remote_get_capabilities_ret; +struct remote_node_get_cpu_time_args { + u_int maxStats; + u_int flags; +}; +typedef struct remote_node_get_cpu_time_args remote_node_get_cpu_time_args; + +struct remote_node_cpu_time { + int tag; + uint64_t val; +}; +typedef struct remote_node_cpu_time remote_node_cpu_time; + +struct remote_node_get_cpu_time_ret { + struct { + u_int stats_len; + remote_node_cpu_time *stats_val; + } stats; +}; +typedef struct remote_node_get_cpu_time_ret remote_node_get_cpu_time_ret; + struct remote_node_get_cells_free_memory_args { int startCell; int maxCells; @@ -2413,6 +2434,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_NODE_GET_CPU_TIME = 210, }; typedef enum remote_procedure remote_procedure; @@ -2486,6 +2508,9 @@ extern bool_t xdr_remote_get_max_vcpus_args (XDR *, remote_get_max_vcpus_args*) extern bool_t xdr_remote_get_max_vcpus_ret (XDR *, remote_get_max_vcpus_ret*); extern bool_t xdr_remote_node_get_info_ret (XDR *, remote_node_get_info_ret*); extern bool_t xdr_remote_get_capabilities_ret (XDR *, remote_get_capabilities_ret*); +extern bool_t xdr_remote_node_get_cpu_time_args (XDR *, remote_node_get_cpu_time_args*); +extern bool_t xdr_remote_node_cpu_time (XDR *, remote_node_cpu_time*); +extern bool_t xdr_remote_node_get_cpu_time_ret (XDR *, remote_node_get_cpu_time_ret*); extern bool_t xdr_remote_node_get_cells_free_memory_args (XDR *, remote_node_get_cells_free_memory_args*); extern bool_t xdr_remote_node_get_cells_free_memory_ret (XDR *, remote_node_get_cells_free_memory_ret*); extern bool_t xdr_remote_node_get_free_memory_ret (XDR *, remote_node_get_free_memory_ret*); @@ -2843,6 +2868,9 @@ extern bool_t xdr_remote_get_max_vcpus_args (); extern bool_t xdr_remote_get_max_vcpus_ret (); extern bool_t xdr_remote_node_get_info_ret (); extern bool_t xdr_remote_get_capabilities_ret (); +extern bool_t xdr_remote_node_get_cpu_time_args (); +extern bool_t xdr_remote_node_cpu_time (); +extern bool_t xdr_remote_node_get_cpu_time_ret (); extern bool_t xdr_remote_node_get_cells_free_memory_args (); extern bool_t xdr_remote_node_get_cells_free_memory_ret (); extern bool_t xdr_remote_node_get_free_memory_ret (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 675eccd..46e789c 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -134,6 +134,9 @@ const REMOTE_DOMAIN_BLKIO_PARAMETERS_MAX = 16; /* Upper limit on list of memory parameters. */ const REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX = 16; +/* Upper limit on list of cpu time stats. */ +const REMOTE_NODE_CPU_TIME_MAX = 8; + /* Upper limit on number of NUMA cells */ const REMOTE_NODE_MAX_CELLS = 1024; @@ -440,6 +443,20 @@ struct remote_get_capabilities_ret { remote_nonnull_string capabilities; }; +struct remote_node_get_cpu_time_args { + u_int maxStats; + u_int flags; +}; + +struct remote_node_cpu_time { + int tag; + unsigned hyper val; +}; + +struct remote_node_get_cpu_time_ret { + remote_node_cpu_time stats; +}; + struct remote_node_get_cells_free_memory_args { int startCell; int maxCells; @@ -2176,7 +2193,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_NODE_GET_CPU_TIME = 210 /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 944553c..adf1fb5 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -151,6 +151,20 @@ struct remote_node_get_info_ret { struct remote_get_capabilities_ret { remote_nonnull_string capabilities; }; +struct remote_node_get_cpu_time_args { + u_int maxStats; + u_int flags; +}; +struct remote_node_cpu_time { + int tag; + uint64_t val; +}; +struct remote_node_get_cpu_time_ret { + struct { + u_int stats_len; + remote_node_cpu_time *stats_val; + } stats; +}; struct remote_node_get_cells_free_memory_args { int startCell; int maxCells; -- 1.7.1 -- Minoru Usui From usui at mxm.nes.nec.co.jp Fri Apr 8 11:36:52 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 8 Apr 2011 20:36:52 +0900 Subject: [libvirt] [PATCHv2 5/6] virNodeGetCPUTime: Implement virsh support In-Reply-To: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> Message-ID: <20110408203652.eb88d49c.usui@mxm.nes.nec.co.jp> virNodeGetCPUTime: Implement virsh support Add nodecputime subcommand to virsh. This subcommand prints below output. [Linux] # build/tools/virsh nodecputime usage: 2.8% user : 0.8% system: 1.9% idle : 97.2% iowait: 0.0% [can get cpu utilization directly(ESX?)] # build/tools/virsh nodecputime usage: 2.8% Signed-off-by: Minoru Usui --- tools/virsh.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 4 ++ 2 files changed, 100 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 19e3449..93288ba 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -3388,6 +3388,101 @@ cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } /* + * "nodecputime" command + */ +static const vshCmdInfo info_nodecputime[] = { + {"help", N_("Prints cpu utilizatoin of the node.")}, + {"desc", N_("Returns cpu utilizatoin of the node.(%)")}, + {NULL, NULL} +}; + +static int +cmdNodeCpuTime(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) +{ + int i, j; + int flag_utilization = FALSE; + virNodeCpuTime stats[VIR_NODE_CPU_TIME_NR]; + int nr_stats; + struct cpu_time { + unsigned long long user; + unsigned long long sys; + unsigned long long idle; + unsigned long long iowait; + unsigned long long util; + } cpu_time[2]; + double user_time, sys_time, idle_time, iowait_time, total_time; + double usage; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return FALSE; + + memset(cpu_time, 0, sizeof(struct cpu_time) * 2); + + for (i = 0; i < 2; i++) { + memset(stats, 0, sizeof(virNodeCpuTime) * VIR_NODE_CPU_TIME_NR); + nr_stats = virNodeGetCpuTime(ctl->conn, &stats[0], + VIR_NODE_CPU_TIME_NR, 0); + if (nr_stats < 0) { + vshError(ctl, "%s", _("failed to get cpu time of the node.")); + return FALSE; + } + + for (j = 0; j < nr_stats; j++) { + switch (stats[j].tag) { + case VIR_NODE_CPU_TIME_KERNEL: + cpu_time[i].sys = stats[j].val; + break; + case VIR_NODE_CPU_TIME_USER: + cpu_time[i].user = stats[j].val; + break; + case VIR_NODE_CPU_TIME_IDLE: + cpu_time[i].idle = stats[j].val; + break; + case VIR_NODE_CPU_TIME_IOWAIT: + cpu_time[i].iowait = stats[j].val; + break; + case VIR_NODE_CPU_TIME_UTILIZATION: + flag_utilization = TRUE; + cpu_time[i].util = stats[j].val; + break; + case VIR_NODE_CPU_TIME_NR: + default: + break; + } + } + + sleep(1); + } + + if (flag_utilization == TRUE) { + usage = cpu_time[0].util; + } else { + user_time = cpu_time[1].user - cpu_time[0].user; + sys_time = cpu_time[1].sys - cpu_time[0].sys; + idle_time = cpu_time[1].idle - cpu_time[0].idle; + iowait_time = cpu_time[1].iowait - cpu_time[0].iowait; + total_time = user_time + sys_time + idle_time + iowait_time; + + usage = (user_time + sys_time) / total_time * 100; + } + + vshPrint(ctl, "%-15s %5.1lf%%\n", _("usage:"), usage); + + if (flag_utilization != TRUE) { + vshPrint(ctl, "%-15s %5.1lf%%\n", + _(" user :"), user_time / total_time * 100); + vshPrint(ctl, "%-15s %5.1lf%%\n", + _(" system:"), sys_time / total_time * 100); + vshPrint(ctl, "%-15s %5.1lf%%\n", + _(" idle :"), idle_time / total_time * 100); + vshPrint(ctl, "%-15s %5.1lf%%\n", + _(" iowait:"), iowait_time / total_time * 100); + } + + return TRUE; +} + +/* * "capabilities" command */ static const vshCmdInfo info_capabilities[] = { @@ -10852,6 +10947,7 @@ static const vshCmdDef hostAndHypervisorCmds[] = { {"freecell", cmdFreecell, opts_freecell, info_freecell}, {"hostname", cmdHostname, NULL, info_hostname}, {"nodeinfo", cmdNodeinfo, NULL, info_nodeinfo}, + {"nodecputime", cmdNodeCpuTime, NULL, info_nodecputime}, {"qemu-monitor-command", cmdQemuMonitorCommand, opts_qemu_monitor_command, info_qemu_monitor_command}, {"sysinfo", cmdSysinfo, NULL, info_sysinfo}, {"uri", cmdURI, NULL, info_uri}, diff --git a/tools/virsh.pod b/tools/virsh.pod index f4bd294..d3e7eab 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -237,6 +237,10 @@ Print the XML representation of the hypervisor sysinfo, if available. Returns basic information about the node, like number and type of CPU, and size of the physical memory. +=item B + +Returns cpu utilization of the node. + =item B Print an XML document describing the capabilities of the hypervisor -- 1.7.1 -- Minoru Usui From usui at mxm.nes.nec.co.jp Fri Apr 8 11:37:45 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Fri, 8 Apr 2011 20:37:45 +0900 Subject: [libvirt] [PATCHv2 6/6] virNodeGetCPUTime: Implement linux support In-Reply-To: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> Message-ID: <20110408203745.02689fb3.usui@mxm.nes.nec.co.jp> virNodeGetCPUTime: Implement linux support Signed-off-by: Minoru Usui --- src/libvirt_private.syms | 1 + src/nodeinfo.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++ src/nodeinfo.h | 5 ++- 3 files changed, 83 insertions(+), 1 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 65a86d3..b879454 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -651,6 +651,7 @@ virNodeDeviceObjUnlock; # nodeinfo.h nodeCapsInitNUMA; +nodeGetCpuTime; nodeGetCellsFreeMemory; nodeGetFreeMemory; nodeGetInfo; diff --git a/src/nodeinfo.c b/src/nodeinfo.c index 5d40aca..4dd1d00 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -57,12 +57,17 @@ #ifdef __linux__ # define CPUINFO_PATH "/proc/cpuinfo" # define CPU_SYS_PATH "/sys/devices/system/cpu" +# define PROCSTAT_PATH "/proc/stat" /* NB, this is not static as we need to call it from the testsuite */ int linuxNodeInfoCPUPopulate(FILE *cpuinfo, virNodeInfoPtr nodeinfo, bool need_hyperthreads); +int linuxNodeCpuTime(FILE *procstat, + virNodeCpuTimePtr cpu_time, + unsigned int nr_stats); + /* Return the positive decimal contents of the given * CPU_SYS_PATH/cpu%u/FILE, or -1 on error. If MISSING_OK and the * file could not be found, return 1 instead of an error; this is @@ -322,6 +327,52 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo, return 0; } +#define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK)) + +int linuxNodeCpuTime(FILE *procstat, virNodeCpuTimePtr stats, + unsigned int nr_stats) +{ + char line[1024]; + unsigned long long usr, ni, sys, idle, iowait; + unsigned long long irq, softirq, steal, guest, guest_nice; + + if (nr_stats < 4) { + nodeReportError(VIR_ERR_INVALID_ARG, "%s", + _("Invalid parameter count")); + return -1; + } + + while (fgets(line, sizeof(line), procstat) != NULL) { + char *buf = line; + + if (STRPREFIX(buf, "cpu ")) { /* aka total logical CPU time */ + if (sscanf(buf, + "%*s %llu %llu %llu %llu %llu" // user ~ iowait + "%llu %llu %llu %llu %llu", // irq ~ guest_nice + &usr, &ni, &sys, &idle, &iowait, + &irq, &softirq, &steal, &guest, &guest_nice) < 4) { + continue; + } + + stats[0].tag = VIR_NODE_CPU_TIME_KERNEL; + stats[0].val = (sys + irq + softirq) * TICK_TO_NSEC; + + stats[1].tag = VIR_NODE_CPU_TIME_USER; + stats[1].val = (usr + ni) * TICK_TO_NSEC; + + stats[2].tag = VIR_NODE_CPU_TIME_IDLE; + stats[2].val = idle * TICK_TO_NSEC; + + stats[3].tag = VIR_NODE_CPU_TIME_IOWAIT; + stats[3].val = iowait * TICK_TO_NSEC; + + return 4; + } + } + + nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no \'cpu \' line found")); + return -1; +} #endif int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) { @@ -360,6 +411,33 @@ int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) { #endif } +int nodeGetCpuTime(virConnectPtr conn ATTRIBUTE_UNUSED, + virNodeCpuTimePtr stats, + unsigned int nr_stats, + unsigned int flags ATTRIBUTE_UNUSED) +{ + +#ifdef __linux__ + { + int ret; + FILE *procstat = fopen(PROCSTAT_PATH, "r"); + if (!procstat) { + virReportSystemError(errno, + _("cannot open %s"), PROCSTAT_PATH); + return -1; + } + ret = linuxNodeCpuTime(procstat, stats, nr_stats); + VIR_FORCE_FCLOSE(procstat); + + return ret; + } +#else + nodeReportError(VIR_ERR_NO_SUPPORT, "%s", + _("node CPU time not implemented on this platform")); + return -1; +#endif +} + #if HAVE_NUMACTL # if LIBNUMA_API_VERSION <= 1 # define NUMA_MAX_N_CPUS 4096 diff --git a/src/nodeinfo.h b/src/nodeinfo.h index 88bac6c..b024758 100644 --- a/src/nodeinfo.h +++ b/src/nodeinfo.h @@ -30,7 +30,10 @@ int nodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo); int nodeCapsInitNUMA(virCapsPtr caps); - +int nodeGetCpuTime(virConnectPtr conn ATTRIBUTE_UNUSED, + virNodeCpuTimePtr stats, + unsigned int nr_stats, + unsigned int flags ATTRIBUTE_UNUSED); int nodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems, int startCell, -- 1.7.1 -- Minoru Usui From berrange at redhat.com Fri Apr 8 13:06:17 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 8 Apr 2011 14:06:17 +0100 Subject: [libvirt] [PATCH 0/6] Add disk streaming API to libvirt In-Reply-To: <1302211924-28517-1-git-send-email-agl@us.ibm.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> Message-ID: <20110408130617.GA27561@redhat.com> On Thu, Apr 07, 2011 at 04:31:58PM -0500, Adam Litke wrote: > I've been working with Anthony Liguori and Stefan Hajnoczi to enable data > streaming to copy-on-read disk images in qemu. This work is working its way > through review and I expect it to be upstream soon as part of the support for > the new QED disk image format. > > Disk streaming is extremely useful when provisioning domains from a central > repository of template images. Currently the domain must be provisioned by > either: 1) copying the template image to local storage before the VM can be > started or, 2) creating a qcow2 image that backs to a base image in the remote > repository. Option 1 can introduce a significant delay when provisioning large > disks. Option 2 introduces a permanent dependency on a remote service and > increased network load to satisfy disk reads. So the scenario we have is a thin-provisioned disk image, with a backstore of some kind (whether local image, or a NBD server doesn't matter). The goal is to allocate blocks in the disk image, to change it from being thin-provisioned, to less-thin, or even fully-allocated. QEMU may be running while this is done (requiring online copy by QEMU process via the monitor) or shutoff (requiring offline copy with qemu-img commands). What strikes me, is that from an API design POV, there is really no compelling reason to restrict this to disk images with backing stores. Any disk volume which is thin-provisioned can benefit from this. ie, instead of copying blocks of data from the backing store, just write blocks of zeros into unallocated regions of the disk. So a mgmt app can start a VM with a sparse raw file, with host storage overcommit across all VMs, and if they later need to provide a strong guarantee for storage allocatio to a particular VM, this API can used, regardless of whether a backingstore is present. > Qemu will support two streaming modes: full device and single sector. Full > device streaming is the easiest to use because one command will cause the whole > device to be streamed as fast as possible. Single sector mode can be used if > one wants to throttle streaming to reduce I/O pressure. In this mode, a > management tool issues individual commands to stream single sectors. This design is needlessly restrictive IMHO - special casing the two extremes, and not providing any intermediate capabilities. The API should just take an offset and a length. This trivially allows for a single sector, multiple sectors, or all sectors. The API should also be using bytes, not sectors. Sectors are a very ill-defined unit of measurement, with lots of potential meanings. It could be the sector size of the underlying block device, filesystem block size, the cluster size of the virtual disk file format, or sector size of the virtual block device. Using bytes, specifying the logical offset + length of the virtual disk image is clear. In addition, all the other libvirt storage APIs use bytes, and we want this to be consistent with them. If the internal implementation wants to convert from bytes to sectors & round up/down to nearest sector boundary, then that is fine - just don't expose it in the API. Finally, while requesting allocation of the entire disk is pretty trivial, to be able to sensibly do allocation of partial regions or individual sectors, applications need to be able to find out just what regions are currently allocated/missing. This will require some kind of API to query disk allocation regions (cf the FIEMAP/FIBMAP ioctls). > To enable this support in libvirt, I propose the following API... > > virDomainStreamDisk() will start or stop a full device stream or stream a > single sector of a device. The behavior is controlled by setting > virDomainStreamDiskFlags. When either starting or stopping a full device > stream, the return value is either 0 or -1 to indicate whether the operation > succeeded. For a single sector stream, a device offset is returned (or -1 on > failure). This value can be used to continue streaming with a subsequent call > to virDomainStreamDisk(). > > virDomainStreamDiskInfo() returns information about active full device streams > (the device alias, current streaming position, and total size). I'm finding the term 'Streaming' to be quite mis-leading. This is really about allocating blocks in the disk image. Thus I would use the word 'Allocate' in the API naming. I'll followup about API design in the next patch. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Fri Apr 8 13:31:35 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 8 Apr 2011 14:31:35 +0100 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: <1302211924-28517-2-git-send-email-agl@us.ibm.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> Message-ID: <20110408133135.GB27561@redhat.com> On Thu, Apr 07, 2011 at 04:31:59PM -0500, Adam Litke wrote: > /* > + * Disk Streaming > + */ > +typedef enum { > + VIR_STREAM_DISK_ONE = 1, /* Stream a single disk unit */ > + VIR_STREAM_DISK_START = 2, /* Stream the entire disk */ > + VIR_STREAM_DISK_STOP = 4, /* Stop streaming a disk */ > +} virDomainStreamDiskFlags; Using flags to combine two separate tasks into one single API is rather unpleasant. As raised in the previous patch, the API should also be taking a offset+length in bytes, then there is no need for a special case transfer of an individual sector. > + > +#define VIR_STREAM_PATH_BUFLEN 1024 > +#define VIR_STREAM_DISK_MAX_STREAMS 10 > + > +typedef struct _virStreamDiskState virStreamDiskState; > +struct _virStreamDiskState { > + char path[VIR_STREAM_PATH_BUFLEN]; > + /* > + * The unit of measure for size and offset is unspecified. These fields > + * are meant to indicate the progress of a continuous streaming operation. > + */ > + unsigned long long offset; /* Current offset of active streaming */ > + unsigned long long size; /* Disk size */ > +}; > +typedef virStreamDiskState *virStreamDiskStatePtr; > + > +unsigned long long virDomainStreamDisk(virDomainPtr dom, > + const char *path, > + unsigned long long offset, > + unsigned int flags); > + > +int virDomainStreamDiskInfo(virDomainPtr dom, > + virStreamDiskStatePtr states, > + unsigned int nr_states, > + unsigned int flags); I would have liked it if we could use the existing JobInfo APIs for getting progress information, but if we need to allow concurrent usage for multiple disks per-VM, we can't. I think we should still use a similar style of API though. There also doesn't appear to be a precise way to determine if the copying of an entire disk failed part way through, and if so, how much was actually copied. Taking all the previous points together, I think the API needs to look like this: typedef enum { /* If set, virDomainBlockAllocate() will return immediately * allowing polling for operation completion & status */ VIR_DOMAIN_DISK_ALLOCATE_NONBLOCK, } virDomainBlockAllocateFlags; /* * @path: fully qualified filename of the virtual disk * @offset: logical position in bytes, within the virtual disk * @length: amount of data to copy, in bytes starting from @offset * @flags: One of virDomainBlockAllocateFlags, or zero * * Ensure the virtual disk @path is fully allocated * between @offset and @offset+ at length. If a backing * store is present, data will be filled from the * backing store, otherwise data will be fileld with * zeros * * If @flags contains VIR_DOMAIN_DISK_ALLOCATE_NONBLOCK, * this API will return immediately after initiating the * copy, otherwise it will block until copying is complete * */ int virDomainBlockAllocate(virDomainPtr dom, const char *path, unsigned long long offset, unsigned long long length, unsigned int flags); /* * @path: fully qualified filename of the virtual disk * @info: allocated struct to return progress info * * Query the progress of a disk allocation job. This * API must be used when virDomainBlockAllocate() was * invoked with the VIR_DOMAIN_DISK_ALLOCATE_NONBLOCK * flag set. * * The @info.type field will indicate whether the job * was completed successfully, or failed part way * through. * * The @info data progress fields will contain current * progress information. * * The hypervisor driver may optionally chose to also * fillin a time estimate for completion. */ int virDomainBlockGetJobInfo(virDomainPtr dom, const char *path, virDomainJobInfoPtr info); /* * @path: fully qualified filename of the virtual disk * * Request that a disk allocation job be aborted at * the soonest opportunity. This API can only be used * when virDomainBlockAllocate() was invoked with the * VIR_DOMAIN_DISK_ALLOCATE_NONBLOCK flag set. */ int virDomainBlockAbortJob(virDomainPtr dom, const char *path); typedef struct _virDomainBlockRegion virDomainBlockRegion; typedef virDomainBlockRegion *virDomainBlockRegionPtr; struct _virDomainBlockRegion { /* The logical offset within the file of the allocated region */ unsigned long long offset; /* The length of the allocated region */ unsigned long long length; }; /* * @path: fully qualified filename of the virtual disk * @nregions: filled in the number of @region structs * @regions: filled with a list of allocated regions * * Query the extents of allocated regions within the * virtual disk file. The offsets in the list of regions * are not guarenteed to be sorted in any explicit order. */ int virDomainBlockGetAllocationMap(virDomainPtr dom, const char *path, unsigned int *nregions, virDomainBlockRegionPtr *regions); NB, I've used 'Block' rather than 'Disk' in the API names, since all the other APIs we have dealing with disks in a guest, use 'Block' in their name. An unfortunate naming convention, but now we have it, we should stick with it consistently. This takes care of things for running guests. It would be desirable to have the same functionality available when a guest is not running, via the virStorageVol APIs. Indeed, this would allow access to the allocation functionality for disks not explicitly associated with any VM yet. Basically the API design would be identical, but instead of using virDomainBlockXXXX(virDomainPtr dom, const char *path, ....); we'd have virStorageVolXXXX(virStorageVolPtr vol, ....); Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From wencongyang at gmail.com Fri Apr 8 13:55:23 2011 From: wencongyang at gmail.com (Wen Congyang) Date: Fri, 08 Apr 2011 21:55:23 +0800 Subject: [libvirt] [PATCH] do not build libvirt_iohelper when building without libvirtd In-Reply-To: <20110408104834.GF24838@redhat.com> References: <4D9E8077.1080003@cn.fujitsu.com> <20110408104834.GF24838@redhat.com> Message-ID: <4D9F13CB.1020900@gmail.com> ? 2011-4-8 18:48, Daniel Veillard ??: > On Fri, Apr 08, 2011 at 11:26:47AM +0800, Wen Congyang wrote: >> The libexec program libvirt_iohelper is only for libvirtd. If we build rpm >> without libvirtd, we will receive the following messages: >> >> Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/wency/rpmbuild/BUILDROOT/libvirt-0.9.0-1.el6.x86_64 >> error: Installed (but unpackaged) file(s) found: >> /usr/libexec/libvirt_iohelper >> >> --- >> src/Makefile.am | 2 ++ >> 1 files changed, 2 insertions(+), 0 deletions(-) >> >> diff --git a/src/Makefile.am b/src/Makefile.am >> index 3649106..dce866e 100644 >> --- a/src/Makefile.am >> +++ b/src/Makefile.am >> @@ -1183,6 +1183,7 @@ EXTRA_DIST += $(LIBVIRT_QEMU_SYMBOL_FILE) >> >> libexec_PROGRAMS = >> >> +if WITH_LIBVIRTD >> libexec_PROGRAMS += libvirt_iohelper >> libvirt_iohelper_SOURCES = $(UTIL_IO_HELPER_SOURCES) >> libvirt_iohelper_LDFLAGS = $(WARN_LDFLAGS) $(AM_LDFLAGS) >> @@ -1191,6 +1192,7 @@ libvirt_iohelper_LDADD = \ >> ../gnulib/lib/libgnu.la >> >> libvirt_iohelper_CFLAGS = $(AM_CFLAGS) >> +endif >> >> if WITH_STORAGE_DISK >> if WITH_LIBVIRTD > > sounds right, ACK Thanks, pushed. > > Daniel > From eblake at redhat.com Fri Apr 8 14:18:05 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 08 Apr 2011 08:18:05 -0600 Subject: [libvirt] patch review tool for libvirt patches? In-Reply-To: <4D9DD714.8060105@laine.org> References: <4D9DD714.8060105@laine.org> Message-ID: <4D9F191D.7000109@redhat.com> On 04/07/2011 09:24 AM, Laine Stump wrote: > I'm sending this message 1) to see if others are feeling the pressure of > the extra traffic too (or is my brain just processing more slowly :-/), No, you're not alone - I feel that my inbox is growing faster than I can respond, and I have in the past committed the wrong version of a patch when I missed that a followup was posted later. > > Ideally, a person wanting to use this system should be able to setup > their email to filter all libvir-list traffic containing "PATCH" in the > subject line, then create an account on the patch review system and > handle all patch review via the tool's interface Agreed - the tool must be able to interact well with the mailing list, with the list as the primary archive of all patch action. I don't know if periodic summary mails of all pending patch series helps or just adds to the list traffic, but I've seen it work for other lists to have the periodic reminders of all pending patch series work out well as a way to see what still needs reviewing. Unfortunately, I don't have enough experience with any of the tools that you listed to recommend (or reject) any of them, but I'm willing to give a new tool a shot if it can help my productivity. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 8 14:20:53 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 08 Apr 2011 08:20:53 -0600 Subject: [libvirt] [PATCH v5] qemu: Remove the managed state file only if restoring succeeded In-Reply-To: <4D9E604F.5080404@redhat.com> References: <1302143512-23422-1-git-send-email-jyang@redhat.com> <4D9DD0AB.8030202@redhat.com> <4D9E604F.5080404@redhat.com> Message-ID: <4D9F19C5.9090805@redhat.com> On 04/07/2011 07:09 PM, Osier Yang wrote: > ? 2011?04?07? 22:56, Eric Blake ??: >> Sorry for not noticing sooner, but we could do some grammar cleanups. >> >> Does this look like a reasonable followup? >> >> diff --git i/src/qemu/qemu_driver.c w/src/qemu/qemu_driver.c >> index a84780b..0734a76 100644 >> --- i/src/qemu/qemu_driver.c >> +++ w/src/qemu/qemu_driver.c >> @@ -3430,7 +3430,7 @@ static int qemudDomainObjStart(virConnectPtr conn, >> if (!managed_save) >> goto cleanup; >> >> - if ((managed_save)&& (virFileExists(managed_save))) { >> + if (virFileExists(managed_save)) { >> ret = qemuDomainObjRestore(conn, driver, vm, managed_save); >> >> +Restores a domain from a B state file. See I for >> more >> info. >> >> B: To avoid corrupting file system contents within the domain, >> you >> -should not reuse the saved state file to B unless you are >> convinced >> -with reverting the domain to the previous state. >> +should not reuse the saved state file for a second B unless >> +you have also reverted all storage volumes back to the same contents >> +as when the state file was created. > > Doesn't reuse implies the "second, third, ...." B ? :) > > But anyway, it looks more clear, good to me. Thanks; pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From laine at laine.org Fri Apr 8 14:35:05 2011 From: laine at laine.org (Laine Stump) Date: Fri, 08 Apr 2011 10:35:05 -0400 Subject: [libvirt] patch review tool for libvirt patches? In-Reply-To: <20110407182126.GA2719@redhat.com> References: <4D9DD714.8060105@laine.org> <20110407182126.GA2719@redhat.com> Message-ID: <4D9F1D19.5020002@laine.org> On 04/07/2011 02:21 PM, Daniel P. Berrange wrote: > On Thu, Apr 07, 2011 at 11:24:04AM -0400, Laine Stump wrote: >> Now that 0.9.0 is out, I'd like to ask everyone's opinions about >> patch review tools. >> >> [...] >> >> >> 1) usage must be optional, so it must be able to update itself via >> monitoring messages on the list (a minimal amount of change/addition >> to the current message flow might be acceptable, but nothing major, >> and encountering PATCH/review/ACK messages as currently sent >> shouldn't make it blow up). >> >> [...] >> >> Ideally, a person wanting to use this system should be able to setup >> their email to filter all libvir-list traffic containing "PATCH" in >> the subject line, then create an account on the patch review system >> and handle all patch review via the tool's interface >> >> [...] >> >> Patchwork (http://ozlabs.org/~jk/projects/patchwork/) (used by Linux kernel& kvm maintainers) >> > For me, any tool which requires visiting a web UI to submit or view > patch code review comments/feedback is a non-starter. All code review > feedback must be on the mailing list, and correctly threaded. Agreed. That's why I made "optional" the first requirement. I wouldn't want anything that screwed up what's already working for somebody else, or made extra work for people who weren't interested, and also agree that having the mailing list archive available is very important (although I wish it was simpler to grab a message from the archive and "git am" it, or create a properly threaded reply to a message (for those times when I've already deleted a message from my mail client, then decide later that I want to do something with it) > In other words, it would be a tool which serves a 'reporting' or > 'tracking' patch series, not a code review management system. > AFAICT, patchwork is the only one expressly designed in this > manner. Their website sums it up nicely: > > "patchwork should supplement mailing lists, not replace them Well, that narrows down the field rather quickly :-) > Patchwork isn't intended to replace a community mailing list; > that's why you can't comment on a patch in patchwork. If this > were the case, then there would be two forums of discussion > on patches, which fragments the patch review process. Developers > who don't use patchwork would get left out of the discussion." That seems a bit narrow-sighted of them. There's nothing in "all review must be on the mailing list" that would prevent a separate application from presenting the diff in some sort of UI (maybe even grabbing in the entire file so that things could be seen in context), allowing comments to be made, then generating email to the list that incorporates the comments. But that's a discussion for patchwork developers, not us... > To also add to that, public mailing lists are a very good archival > system for code review / discussions. Once in a mailing list, you > can be pretty sure it'll never disappear from the web& is always > searchable from google. The same can't be said of most web apps. Plaintext definitely has the most likelyhood of enduring, and of being usable by other applications. So since the range of selection has been narrowed to 1 (well two actually - use patchwork, or don't use patchwork). Does anybody have experience setting it up and using it? Would it be simple for me to set it up locally and try it out. From kadiryuceer at gmail.com Fri Apr 8 14:56:42 2011 From: kadiryuceer at gmail.com (=?ISO-8859-1?Q?kadir_y=FCceer?=) Date: Fri, 8 Apr 2011 17:56:42 +0300 Subject: [libvirt] Is there smt missing at Java bindings? Message-ID: Hello all, I've been posting questions about my issue to the user list but it seems nobody can answer, so I had to try this list, sorry if there is any disturbance. Here is the case: I've been trying to develop a java app that can register callbacks for domain lifecycle events(suspend,resume,etc.). Only method that I've seen is Connect.VirDomainEventRegisterAny, and there is an abstract callback method inside VirConnectDomainEventGenericCallback. I implement the callback, and register it for all the domains by passing the domain pointer as NULL. Additionally for testing, I've added a println into the suspend function in org.libvirt.Domain.java, and compiled the java bindings and used the new jar file, and I was successful, I can see the message whenever I suspend the domain either by clicking *pause* or by writing dom.suspend() in my java app. However, when I try to register a callback as I mentioned in the beginning (with eventID 0, which is life_cycle ID), after the suspend operation, I get the error that you can see at the end of the mail. But before you check it out, I have to ask, are some of the event-related features of libvirt missing in java bindings? For example; VirEventAddHandleFunc, VirEventAddHandleCallback, and their derivatives. Is this a problem or the only Connect.VirDomainEventRegisterAny method of java binding suffice for providing callbacks for domain events? Thanks in advance for your responses. The error is below. Kind Regards Kadir # # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00000000, pid=5692, tid=3077520240 # # JRE version: 6.0_20-b20 # Java VM: OpenJDK Server VM (19.0-b09 mixed mode linux-x86 ) # Derivative: IcedTea6 1.9.7 # Distribution: Ubuntu 10.10, package 6b20-1.9.7-0ubuntu1 # Problematic frame: # C 0x00000000 # # An error report file with more information is saved as: # /root/NetBeansProjects/NovaTest_v0.3/hs_err_pid5692.log # # If you would like to submit a bug report, please include # instructions how to reproduce the bug and visit: # https://bugs.launchpad.net/ubuntu/+source/openjdk-6/ # The crash happened outside the Java Virtual Machine in native code. # See problematic frame for where to report the bug. # Java Result: 134 -------------- next part -------------- An HTML attachment was scrubbed... URL: From eblake at redhat.com Fri Apr 8 15:12:20 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 8 Apr 2011 09:12:20 -0600 Subject: [libvirt] [PATCH] build: fix mingw build Message-ID: <1302275540-9388-1-git-send-email-eblake@redhat.com> Commit 02c39a2 introduced a mingw build regression, due to a regression in gnulib's areadlink module: ../../../gnulib/lib/careadlinkat.c: In function 'careadlinkat': ../../../gnulib/lib/careadlinkat.c:143:39: error: 'const struct allocator' has no member named 'malloc' * .gnulib: Update to latest, for careadlinkat fix. --- Pushing under the build-breaker rule. * .gnulib bd5d1e6...9cc9910 (1): > careadlink: fix compilation error on mingw .gnulib | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/.gnulib b/.gnulib index bd5d1e6..9cc9910 160000 --- a/.gnulib +++ b/.gnulib @@ -1 +1 @@ -Subproject commit bd5d1e621103ea3f7fbae09010348ce2df563808 +Subproject commit 9cc991025d6139a3a8f3e0f1570bf39a66f3aafa -- 1.7.4.2 From stefanha at gmail.com Fri Apr 8 16:02:57 2011 From: stefanha at gmail.com (Stefan Hajnoczi) Date: Fri, 8 Apr 2011 17:02:57 +0100 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: <20110408133135.GB27561@redhat.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> <20110408133135.GB27561@redhat.com> Message-ID: On Fri, Apr 8, 2011 at 2:31 PM, Daniel P. Berrange wrote: I have CCed Anthony and Kevin. Anthony drove the QED image streaming and Kevin will probably be interested in the idea of allocating raw images as a background activity while QEMU runs. > ? ?/* > ? ? * @path: fully qualified filename of the virtual disk > ? ? * @nregions: filled in the number of @region structs > ? ? * @regions: filled with a list of allocated regions > ? ? * > ? ? * Query the extents of allocated regions within the > ? ? * virtual disk file. The offsets in the list of regions > ? ? * are not guarenteed to be sorted in any explicit order. > ? ? */ > ? ?int virDomainBlockGetAllocationMap(virDomainPtr dom, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const char *path, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned int *nregions, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? virDomainBlockRegionPtr *regions); QEMU can provide this with its existing .bdrv_is_allocated() function. Kevin, do you have any thoughts on whether this API will work well? > This takes care of things for running guests. It would be > desirable to have the same functionality available when a > guest is not running, via the virStorageVol APIs. Indeed, > this would allow access to the allocation functionality > for disks not explicitly associated with any VM yet. Today QEMU doesn't really cover the offline case although in the future it may be possible to have a qemu-img command that preallocates images and can be aborted. Stefan From kwolf at redhat.com Fri Apr 8 16:35:16 2011 From: kwolf at redhat.com (Kevin Wolf) Date: Fri, 08 Apr 2011 18:35:16 +0200 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> <20110408133135.GB27561@redhat.com> Message-ID: <4D9F3944.3060202@redhat.com> Am 08.04.2011 18:02, schrieb Stefan Hajnoczi: > On Fri, Apr 8, 2011 at 2:31 PM, Daniel P. Berrange wrote: > > I have CCed Anthony and Kevin. Anthony drove the QED image streaming > and Kevin will probably be interested in the idea of allocating raw > images as a background activity while QEMU runs. > >> /* >> * @path: fully qualified filename of the virtual disk >> * @nregions: filled in the number of @region structs >> * @regions: filled with a list of allocated regions >> * >> * Query the extents of allocated regions within the >> * virtual disk file. The offsets in the list of regions >> * are not guarenteed to be sorted in any explicit order. >> */ >> int virDomainBlockGetAllocationMap(virDomainPtr dom, >> const char *path, >> unsigned int *nregions, >> virDomainBlockRegionPtr *regions); > > QEMU can provide this with its existing .bdrv_is_allocated() function. > Kevin, do you have any thoughts on whether this API will work well? I'm probably just lacking context here, but what would a management tool do with this information? >From this one function it looks like you want to implement the image streaming in libvirt rather than qemu? What's the reason for this? And wouldn't you need at least a second function that actually copies data from the source? >> This takes care of things for running guests. It would be >> desirable to have the same functionality available when a >> guest is not running, via the virStorageVol APIs. Indeed, >> this would allow access to the allocation functionality >> for disks not explicitly associated with any VM yet. > > Today QEMU doesn't really cover the offline case although in the > future it may be possible to have a qemu-img command that preallocates > images and can be aborted. Maybe qemu-io can be used to access the information? Again, I think I'm lacking context, so I don't really know what the use case is. Kevin From berrange at redhat.com Fri Apr 8 16:48:52 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 8 Apr 2011 17:48:52 +0100 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: <4D9F3944.3060202@redhat.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> <20110408133135.GB27561@redhat.com> <4D9F3944.3060202@redhat.com> Message-ID: <20110408164852.GH27561@redhat.com> On Fri, Apr 08, 2011 at 06:35:16PM +0200, Kevin Wolf wrote: > Am 08.04.2011 18:02, schrieb Stefan Hajnoczi: > > On Fri, Apr 8, 2011 at 2:31 PM, Daniel P. Berrange wrote: > > > > I have CCed Anthony and Kevin. Anthony drove the QED image streaming > > and Kevin will probably be interested in the idea of allocating raw > > images as a background activity while QEMU runs. > > > >> /* > >> * @path: fully qualified filename of the virtual disk > >> * @nregions: filled in the number of @region structs > >> * @regions: filled with a list of allocated regions > >> * > >> * Query the extents of allocated regions within the > >> * virtual disk file. The offsets in the list of regions > >> * are not guarenteed to be sorted in any explicit order. > >> */ > >> int virDomainBlockGetAllocationMap(virDomainPtr dom, > >> const char *path, > >> unsigned int *nregions, > >> virDomainBlockRegionPtr *regions); > > > > QEMU can provide this with its existing .bdrv_is_allocated() function. > > Kevin, do you have any thoughts on whether this API will work well? > > I'm probably just lacking context here, but what would a management tool > do with this information? > > From this one function it looks like you want to implement the image > streaming in libvirt rather than qemu? What's the reason for this? And > wouldn't you need at least a second function that actually copies data > from the source? We don't want to implement it in libvirt - we want to control it from libvirt - QEMU obviously has to be in charge of actually writing the data, since the guest may be running and using the disk concurrently, and we don't want libvirt to have to learn about the various crazy virtual disk file formats QEMU has. Having an API to request allocation of regions of virtual disk file was the first request, but to effectively use it, we also need to be able to understand what the current allocation of the file is, hence the above API (akin to ioctl(FIEMAP) for sparse files). For full context see the parent messages in the thread http://www.redhat.com/archives/libvir-list/2011-April/msg00482.html http://www.redhat.com/archives/libvir-list/2011-April/msg00483.html > >> This takes care of things for running guests. It would be > >> desirable to have the same functionality available when a > >> guest is not running, via the virStorageVol APIs. Indeed, > >> this would allow access to the allocation functionality > >> for disks not explicitly associated with any VM yet. > > > > Today QEMU doesn't really cover the offline case although in the > > future it may be possible to have a qemu-img command that preallocates > > images and can be aborted. > > Maybe qemu-io can be used to access the information? Again, I think I'm > lacking context, so I don't really know what the use case is. NB, we'd want something that is a supported interface - so for offline case, I assume this means a qemu-img command or two, since AFAIK qemu-io is just an adhoc developer debugging tool Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From kwolf at redhat.com Fri Apr 8 17:06:06 2011 From: kwolf at redhat.com (Kevin Wolf) Date: Fri, 08 Apr 2011 19:06:06 +0200 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: <20110408164852.GH27561@redhat.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> <20110408133135.GB27561@redhat.com> <4D9F3944.3060202@redhat.com> <20110408164852.GH27561@redhat.com> Message-ID: <4D9F407E.3080301@redhat.com> Am 08.04.2011 18:48, schrieb Daniel P. Berrange: > On Fri, Apr 08, 2011 at 06:35:16PM +0200, Kevin Wolf wrote: >> Am 08.04.2011 18:02, schrieb Stefan Hajnoczi: >>> On Fri, Apr 8, 2011 at 2:31 PM, Daniel P. Berrange wrote: >>> >>> I have CCed Anthony and Kevin. Anthony drove the QED image streaming >>> and Kevin will probably be interested in the idea of allocating raw >>> images as a background activity while QEMU runs. >>> >>>> /* >>>> * @path: fully qualified filename of the virtual disk >>>> * @nregions: filled in the number of @region structs >>>> * @regions: filled with a list of allocated regions >>>> * >>>> * Query the extents of allocated regions within the >>>> * virtual disk file. The offsets in the list of regions >>>> * are not guarenteed to be sorted in any explicit order. >>>> */ >>>> int virDomainBlockGetAllocationMap(virDomainPtr dom, >>>> const char *path, >>>> unsigned int *nregions, >>>> virDomainBlockRegionPtr *regions); >>> >>> QEMU can provide this with its existing .bdrv_is_allocated() function. >>> Kevin, do you have any thoughts on whether this API will work well? >> >> I'm probably just lacking context here, but what would a management tool >> do with this information? >> >> From this one function it looks like you want to implement the image >> streaming in libvirt rather than qemu? What's the reason for this? And >> wouldn't you need at least a second function that actually copies data >> from the source? > > We don't want to implement it in libvirt - we want to control it > from libvirt - QEMU obviously has to be in charge of actually > writing the data, since the guest may be running and using the > disk concurrently, and we don't want libvirt to have to learn > about the various crazy virtual disk file formats QEMU has. > > Having an API to request allocation of regions of virtual disk > file was the first request, but to effectively use it, we also > need to be able to understand what the current allocation of > the file is, hence the above API (akin to ioctl(FIEMAP) for > sparse files). > > For full context see the parent messages in the thread > > http://www.redhat.com/archives/libvir-list/2011-April/msg00482.html > http://www.redhat.com/archives/libvir-list/2011-April/msg00483.html Thanks, now it makes much more sense. I think I agree with your comments. >>>> This takes care of things for running guests. It would be >>>> desirable to have the same functionality available when a >>>> guest is not running, via the virStorageVol APIs. Indeed, >>>> this would allow access to the allocation functionality >>>> for disks not explicitly associated with any VM yet. >>> >>> Today QEMU doesn't really cover the offline case although in the >>> future it may be possible to have a qemu-img command that preallocates >>> images and can be aborted. >> >> Maybe qemu-io can be used to access the information? Again, I think I'm >> lacking context, so I don't really know what the use case is. > > NB, we'd want something that is a supported interface - so for offline > case, I assume this means a qemu-img command or two, since AFAIK qemu-io > is just an adhoc developer debugging tool Hm, never thought about that. Generally it's a command that I would have seen to be more natural for qemu-io, but if we're going to make a difference between fully supported qemu-img and debug-only qemu-io, then it needs to be qemu-img. I don't think there's an explicit statement on that yet. Kevin From eblake at redhat.com Fri Apr 8 17:13:55 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 08 Apr 2011 11:13:55 -0600 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: <20110408133135.GB27561@redhat.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> <20110408133135.GB27561@redhat.com> Message-ID: <4D9F4253.7060006@redhat.com> On 04/08/2011 07:31 AM, Daniel P. Berrange wrote: > On Thu, Apr 07, 2011 at 04:31:59PM -0500, Adam Litke wrote: >> /* >> + * Disk Streaming >> + */ >> +typedef enum { >> + VIR_STREAM_DISK_ONE = 1, /* Stream a single disk unit */ >> + VIR_STREAM_DISK_START = 2, /* Stream the entire disk */ >> + VIR_STREAM_DISK_STOP = 4, /* Stop streaming a disk */ >> +} virDomainStreamDiskFlags; > > Using flags to combine two separate tasks into one single API > is rather unpleasant. As raised in the previous patch, the API > should also be taking a offset+length in bytes, then there is > no need for a special case transfer of an individual sector. > Taking all the previous points together, I think the API needs to > look like this: > > typedef enum { > /* If set, virDomainBlockAllocate() will return immediately > * allowing polling for operation completion & status > */ > VIR_DOMAIN_DISK_ALLOCATE_NONBLOCK, > } virDomainBlockAllocateFlags; It seems like adding one more flag would also make this API useful for supporting the converse operation: if we have a disk that is currently allocated, but we either know that a block is all 0s (or don't care about the data in that block if it was not all 0s), it would be nice to request punching a hole (for file-backed images residing on a file system and kernels new enough to do that) and/or truncate back to a smaller (thinly-provisioned) allocated size (which should work for both file-backed and lvm-backed disk images). Meanwhile, I know that GNU coreutils has been working on an API for efficiently getting FIEMAP data from files; part of this effort needs to involve migrating that code into gnulib so that libvirt can indeed provide an API that enumerates sections of a disk image that are allocated vs. holes. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From agl at us.ibm.com Fri Apr 8 17:44:26 2011 From: agl at us.ibm.com (Adam Litke) Date: Fri, 08 Apr 2011 12:44:26 -0500 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: <4D9F4253.7060006@redhat.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> <20110408133135.GB27561@redhat.com> <4D9F4253.7060006@redhat.com> Message-ID: <1302284666.3453.4.camel@aglitke> On Fri, 2011-04-08 at 11:13 -0600, Eric Blake wrote: > On 04/08/2011 07:31 AM, Daniel P. Berrange wrote: > > On Thu, Apr 07, 2011 at 04:31:59PM -0500, Adam Litke wrote: > >> /* > >> + * Disk Streaming > >> + */ > >> +typedef enum { > >> + VIR_STREAM_DISK_ONE = 1, /* Stream a single disk unit */ > >> + VIR_STREAM_DISK_START = 2, /* Stream the entire disk */ > >> + VIR_STREAM_DISK_STOP = 4, /* Stop streaming a disk */ > >> +} virDomainStreamDiskFlags; > > > > Using flags to combine two separate tasks into one single API > > is rather unpleasant. As raised in the previous patch, the API > > should also be taking a offset+length in bytes, then there is > > no need for a special case transfer of an individual sector. > > > Taking all the previous points together, I think the API needs to > > look like this: > > > > typedef enum { > > /* If set, virDomainBlockAllocate() will return immediately > > * allowing polling for operation completion & status > > */ > > VIR_DOMAIN_DISK_ALLOCATE_NONBLOCK, > > } virDomainBlockAllocateFlags; > > It seems like adding one more flag would also make this API useful for > supporting the converse operation: if we have a disk that is currently > allocated, but we either know that a block is all 0s (or don't care > about the data in that block if it was not all 0s), it would be nice to > request punching a hole (for file-backed images residing on a file > system and kernels new enough to do that) and/or truncate back to a > smaller (thinly-provisioned) allocated size (which should work for both > file-backed and lvm-backed disk images). I agree that this could be a good future extension of the API and further justifies the use of offset _and_ length parameters. However, I'd prefer not to consider this part at the moment since I am not aware of a hypervisor that plans to implement it. > Meanwhile, I know that GNU coreutils has been working on an API for > efficiently getting FIEMAP data from files; part of this effort needs to > involve migrating that code into gnulib so that libvirt can indeed > provide an API that enumerates sections of a disk image that are > allocated vs. holes. Why not just ask the hypervisor? Qemu's image format code is probably the most efficient place from which to gather this information. -- Thanks, Adam From berrange at redhat.com Fri Apr 8 18:13:09 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Fri, 8 Apr 2011 19:13:09 +0100 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: <1302284666.3453.4.camel@aglitke> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> <20110408133135.GB27561@redhat.com> <4D9F4253.7060006@redhat.com> <1302284666.3453.4.camel@aglitke> Message-ID: <20110408181309.GJ27561@redhat.com> On Fri, Apr 08, 2011 at 12:44:26PM -0500, Adam Litke wrote: > On Fri, 2011-04-08 at 11:13 -0600, Eric Blake wrote: > > On 04/08/2011 07:31 AM, Daniel P. Berrange wrote: > > > On Thu, Apr 07, 2011 at 04:31:59PM -0500, Adam Litke wrote: > > >> /* > > >> + * Disk Streaming > > >> + */ > > >> +typedef enum { > > >> + VIR_STREAM_DISK_ONE = 1, /* Stream a single disk unit */ > > >> + VIR_STREAM_DISK_START = 2, /* Stream the entire disk */ > > >> + VIR_STREAM_DISK_STOP = 4, /* Stop streaming a disk */ > > >> +} virDomainStreamDiskFlags; > > > > > > Using flags to combine two separate tasks into one single API > > > is rather unpleasant. As raised in the previous patch, the API > > > should also be taking a offset+length in bytes, then there is > > > no need for a special case transfer of an individual sector. > > > > > Taking all the previous points together, I think the API needs to > > > look like this: > > > > > > typedef enum { > > > /* If set, virDomainBlockAllocate() will return immediately > > > * allowing polling for operation completion & status > > > */ > > > VIR_DOMAIN_DISK_ALLOCATE_NONBLOCK, > > > } virDomainBlockAllocateFlags; > > > > It seems like adding one more flag would also make this API useful for > > supporting the converse operation: if we have a disk that is currently > > allocated, but we either know that a block is all 0s (or don't care > > about the data in that block if it was not all 0s), it would be nice to > > request punching a hole (for file-backed images residing on a file > > system and kernels new enough to do that) and/or truncate back to a > > smaller (thinly-provisioned) allocated size (which should work for both > > file-backed and lvm-backed disk images). > > I agree that this could be a good future extension of the API and > further justifies the use of offset _and_ length parameters. However, > I'd prefer not to consider this part at the moment since I am not aware > of a hypervisor that plans to implement it. That's fine, its just useful to know the design can cope with the concept in the future. > > Meanwhile, I know that GNU coreutils has been working on an API for > > efficiently getting FIEMAP data from files; part of this effort needs to > > involve migrating that code into gnulib so that libvirt can indeed > > provide an API that enumerates sections of a disk image that are > > allocated vs. holes. > > Why not just ask the hypervisor? Qemu's image format code is probably > the most efficient place from which to gather this information. In the case of the virDomainBlock* APIs, we should always just ask QEMU since we know it has the info, and it doesn't make sense to try to duplicate it in libvirt (and it isn't even safe todo so for non-raw files anyway). If we did the equivalent virStorageVolGetAllocation APIs, then we'd likely want to have an impl for raw files natively in libvirt, for use from non-QEMU drivers (LXC, Xen, etc). I wouldn't ever wnat to support non-raw formats though, so for those we could just shell out to qemu-img eventually. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From eblake at redhat.com Fri Apr 8 19:02:33 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 8 Apr 2011 13:02:33 -0600 Subject: [libvirt] [PATCH] build: really fix mingw startup In-Reply-To: <1302119254-20506-1-git-send-email-eblake@redhat.com> References: <1302119254-20506-1-git-send-email-eblake@redhat.com> Message-ID: <1302289353-5349-1-git-send-email-eblake@redhat.com> Aargh; commit 8ae5dfd still didn't fix the mingw problem, because gnulib defined O_NONBLOCK to 0 for just mingw. I've now fixed that in gnulib, but we need the latest pipe2 for libvirt to work. * .gnulib: Update to latest, for pipe2 fixes. --- Pushing under the trivial rule (it's a one-liner, right? :) * .gnulib 9cc9910...4a1579d (5): > nonblocking: reduce dependency > pipe2: fix O_NONBLOCK support on mingw > fcntl-h: fix O_ACCMODE on cygwin > pipe-filter: drop O_NONBLOCK workarounds > nonblocking: provide O_NONBLOCK for mingw .gnulib | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/.gnulib b/.gnulib index 9cc9910..4a1579d 160000 --- a/.gnulib +++ b/.gnulib @@ -1 +1 @@ -Subproject commit 9cc991025d6139a3a8f3e0f1570bf39a66f3aafa +Subproject commit 4a1579d7560659ef5723325726eda14490a967f6 -- 1.7.4.2 From anthony at codemonkey.ws Fri Apr 8 19:26:48 2011 From: anthony at codemonkey.ws (Anthony Liguori) Date: Fri, 08 Apr 2011 14:26:48 -0500 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> <20110408133135.GB27561@redhat.com> Message-ID: <4D9F6178.3080500@codemonkey.ws> On 04/08/2011 11:02 AM, Stefan Hajnoczi wrote: > On Fri, Apr 8, 2011 at 2:31 PM, Daniel P. Berrange wrote: > > I have CCed Anthony and Kevin. Anthony drove the QED image streaming > and Kevin will probably be interested in the idea of allocating raw > images as a background activity while QEMU runs. > >> /* >> * @path: fully qualified filename of the virtual disk >> * @nregions: filled in the number of @region structs >> * @regions: filled with a list of allocated regions >> * >> * Query the extents of allocated regions within the >> * virtual disk file. The offsets in the list of regions >> * are not guarenteed to be sorted in any explicit order. >> */ >> int virDomainBlockGetAllocationMap(virDomainPtr dom, >> const char *path, >> unsigned int *nregions, >> virDomainBlockRegionPtr *regions); > QEMU can provide this with its existing .bdrv_is_allocated() function. > Kevin, do you have any thoughts on whether this API will work well? I think the trouble with this API proposal is that it's overloading concepts. Sparse is not the same thing as CoW to a backing file. For instance, when you expose streaming, the result is still a sparse file. So you'd have a rather curious API where you called to "allocate" a region in the file which resulted in having a sparse file which you then called again to make it non sparse. But AFAICT, the API doesn't really tell you these details. I think it's too much abstraction with not enough commonality. Having to related APIs to expand a copy-on-read image and then to fill in a sparse file is certainly a reasonable thing to do. I think trying to make a single API that does both without having a flag that basically makes it two APIs is going to be cumbersome. Regards, Anthony Liguori From laine at laine.org Fri Apr 8 19:31:05 2011 From: laine at laine.org (Laine Stump) Date: Fri, 08 Apr 2011 15:31:05 -0400 Subject: [libvirt] RFC: virInterface change transaction API Message-ID: <4D9F6279.6040806@laine.org> I've been asked to implement what some people have termed as a "transaction-oriented" API for host interface configuration (ie virInterface*()). The basic intent is to allow rollback to a known-good config if anything goes wrong when changing around the host network config with virInterface*() functions. The most straightforward way to achieve this is that prior to calling virInterfaceDefine/virInterfaceUndefine, the current state of the host's network configuration (ie the /etc/sysconfig/network-scripts/ifcfg-* files in the case of Fedora and RHEL) would be saved off somewhere, and kept around until we're sure the new config is good; once we know that, we can just eliminate the backup. If, however, the user of virInterface*() explicitly requests, we could copy the files back; alternately if the system is rebooted without these known-good files being erased, we would assume that something went wrong and restore the original config. As with all other virInterface functions, the details of all this will be handled by netcf (and below), but since libvirt is the main consumer of netcf, I figure this is the appropriate place to discuss how it gets done, so please let me know any opinions on any piece of this. I plan to start the implementation "soon", as I want to be finished before the end of May. I see 3 layers to this: 1) libvirt At the libvirt layer, this feature just requires 3 new APIs, which are directly passed through to netcf: virInterfaceChangeStart(virConnectPtr conn, unsigned int flags); virInterfaceChangeCommit(virConnectPtr conn, unsigned int flags); virInterfaceChangeRollback(virConnectPtr conn, unsigned int flags); For the initial implementation, these will be simple passthroughs to similarly named netcf functions. (in the future, it would be useful for the server side of libvirt to determine if client<->server connectivity was lost due to the network changes, and automatically tell netcf to do a rollback). 2) netcf The netcf api will have these same three APIs, just named slightly differently: ncf_change_start(struct netcf *ncf, unsigned int flags); There are two possibilities for this. Either: A) call the initscript described below to save all config files that might possibly be changed (snapshot_config) or B) set a flag in *ncf indicating that all future calls to netcf that would end up modifying a particular config file should save off that file *if it hasn't already been saved*. (A) is simpler, but relies on the initscript having exact/complete matching knowledge of what files netcf may change. Should we worry about that and deal with the complexities of (B), or is (A) good enough for now? ncf_change_rollback(struct netcf *ncf, unsigned int flags); Again, two possbilities: A) a) save the config of all current interfaces (in memory) b) call the initscript below to restore the config to its original state. c) compare the new config to the old, and: * bring down any interfaces that no longer exist (PROBLEM: once an interface has no config files, you can no longer operate on it with "ifdown") * bounce any interfaces that have changed * bring up any interfaces that have been re-added or B) a) ifdown all interfaces b) call initscript to restore previous config (rollback_config) c) ifup all interfaces. (A) is much simpler, but may lead to unnecessary difficulties when we bounce interfaces that didn't really need it. So, the same question oas for ncf_change_start() - is the more exact operation worth the extra complexity? ncf_change_commit(struct netcf *ncf, unsigned int flags); The simplest function - this will just call the initscript to erase the backup (commit_config). 3) initscript This initscript will at first live in (be installed by) netcf (called /etc/init.d/networking-config?), but hopefully it will eventually be accepted by the initscripts package (which includes the networking-related initscripts), as it is of general use. (Dan Kenigsberg already already took a stab at this script last year, but received no reply from the initscripts maintainers, implying they may not be too keen on the idea right now - it might take some convincing ;-) https://fedorahosted.org/pipermail/initscripts-devel/2010-February/000025.html It will have three commands, one of which will be called automatically by "start" (the command called automatically at boot time): snapshot_config This will save a copy of (what the script believes are - is this problematic?) all network-config related files. It may or may not be called by netcf (see the notes in ncf_start_change() above. If this function finds that a snapshot has already been taken, it should fail. rollback_config (automatically called from "start" at boottime) This will move back (from the saved copies) all files that were changed/removed since snapshot, *and delete any files that have been added*. Note that this command doesn't need to worry about ifup/ifdown, because it will be called prior to any other networking startup (part of the reason that netcf will need to deal with that). I notice that Dan K's version saves the modified files to a "rollback-${date}" directory. Does this seem like a good idea? It's nice to not lose anything, but there is no provision for eliminating old versions, so it could grow without bound. commit_config This will just remove all the files in the save directory. So, the two problems I have right now: 1) Do we accept the inexact method of just saving all files that match a list of patterns during *start(), then in *rollback() erasing all files matching that pattern and copying the old file back? Or do we need to keep track of what files have been changed/removed and added, and copy back / delete only those files during rollback? (A version control system would keep track of this rather nicely, but that's too complex for something that's intended to be a failsafe (and that we would also like to eventually be in the base OS install). Dan B. at one point suggested using patchfiles if I wanted the save info to keep exact track of which files would need to be replaced/deleted on rollback, but on further thought this turns out to not be workable, since we would need to run diff (to create the patchfile) after all changes had been made, and any outside changes to any of the files would leave the patchfile un-appliable, thus causing our "failsafe" to fail :-( ). Therefore, we will need to rely on the list of globs to tell us what files need to be deleted, or keep our own list in a separate file.) 2) Is it going to be okay to ifdown all interfaces prior to the rollback, and ifup all interfaces afterwards? Or must we compare the new config to the original, and ifdown only those interfaces that had been previously added/changed, then ifup only those interfaces that had been previously removed/changed? 3) If anyone has ideas on making the initscript more palatable to the initscripts people, please speak up! :-) (one comment from an initscripts person was that 1) for the general case it would be difficult to draw the line on what parts of network connectivity should be included in this rollback functionality, and 2) at some point this becomes a general system config problem, and would really be better addressed by a general system wide config management system. These are both concerns that need well qualified answers. (I tend to think that this is intended as a failsafe to prevent unreachable systems, so it should be as simple as possible, and thus shouldn't be burdened with the complexity of a full system config management system (which could also co-exist at a higher level), but better answers are welcome.) From eblake at redhat.com Fri Apr 8 22:31:38 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 08 Apr 2011 16:31:38 -0600 Subject: [libvirt] [PATCH] docs: remove "returns" word from beginning of lines In-Reply-To: <1302166064-29080-1-git-send-email-jean-baptiste.rouault@diateam.net> References: <1302166064-29080-1-git-send-email-jean-baptiste.rouault@diateam.net> Message-ID: <4D9F8CCA.5060406@redhat.com> On 04/07/2011 02:47 AM, Jean-Baptiste Rouault wrote: > Move "returns" keyword from beginning of API doc lines > when it does not describe return values. ACK, and pushed. > Maybe the API doc extractor could be changed to look for > "returns: " to avoid such confusion. Probably, but I'm no python wizard, so I'm not writing that patch. Anyone else want to help? > - * If the callback wishes to keep the domain object after the callback > - * returns, it shall take a reference to it, by calling virDomainRef. > + * If the callback wishes to keep the domain object after the callback returns, > + * it shall take a reference to it, by calling virDomainRef. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 8 23:39:36 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 08 Apr 2011 17:39:36 -0600 Subject: [libvirt] [PATCH 2/3] maxmem: implement virDomainSetMaxMemory API of the qemu driver In-Reply-To: <4D9E983D.4070100@jp.fujitsu.com> References: <4D9E953A.4070102@jp.fujitsu.com> <4D9E983D.4070100@jp.fujitsu.com> Message-ID: <4D9F9CB8.5090008@redhat.com> On 04/07/2011 11:08 PM, Taku Izumi wrote: > > This patch implements the code to support virDomainSetMaxMemory API, > and to support VIR_DOMAIN_MEM_MAXIMUM flag in qemudDomainSetMemoryFlags function. > As a result, we can change the maximum memory size of inactive QEMU guests. > > Signed-off-by: Taku Izumi > --- > src/qemu/qemu_driver.c | 81 ++++++++++++++++++++++++++++++++++--------------- > 1 file changed, 57 insertions(+), 24 deletions(-) > @@ -1593,12 +1594,6 @@ static int qemudDomainSetMemoryFlags(vir > goto cleanup; > } > > - if (newmem > vm->def->mem.max_balloon) { > - qemuReportError(VIR_ERR_INVALID_ARG, > - "%s", _("cannot set memory higher than max memory")); > - goto cleanup; > - } > - Why are you dropping this check? Oh, I should read the whole patch first... > @@ -1610,6 +1605,12 @@ static int qemudDomainSetMemoryFlags(vir > else > flags = VIR_DOMAIN_MEM_CONFIG; > } > + if (flags == VIR_DOMAIN_MEM_MAXIMUM) { > + if (isActive) > + flags = VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_MAXIMUM; qemu can't change the maximum memory allocation of an active domain. Oh, but I see you catch that later... > + else > + flags = VIR_DOMAIN_MEM_CONFIG | VIR_DOMAIN_MEM_MAXIMUM; > + } > > if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) { > qemuReportError(VIR_ERR_OPERATION_INVALID, > @@ -1627,27 +1628,54 @@ static int qemudDomainSetMemoryFlags(vir > goto endjob; > } > > - if (flags & VIR_DOMAIN_MEM_LIVE) { > - priv = vm->privateData; > - qemuDomainObjEnterMonitor(vm); > - r = qemuMonitorSetBalloon(priv->mon, newmem); > - qemuDomainObjExitMonitor(vm); > - qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", r == 1); > - if (r < 0) > - goto endjob; > + if (flags & VIR_DOMAIN_MEM_MAXIMUM) { > + /* resize the maximum memory */ > > - /* Lack of balloon support is a fatal error */ > - if (r == 0) { > + if (flags & VIR_DOMAIN_MEM_LIVE) { > qemuReportError(VIR_ERR_OPERATION_INVALID, > - "%s", _("cannot set memory of an active domain")); > + _("cannot resize the maximum memory on an active domain")); Needs a "%s" to keep compilation without gettext happy (that's the only case where gcc starts warning about a format string with no % in it). But this answers my second question. > goto endjob; > } > - } > > - if (flags& VIR_DOMAIN_MEM_CONFIG) { > - persistentDef->mem.cur_balloon = newmem; > - ret = virDomainSaveConfig(driver->configDir, persistentDef); > - goto endjob; > + if (flags & VIR_DOMAIN_MEM_CONFIG) { > + persistentDef->mem.max_balloon = newmem; > + if (persistentDef->mem.cur_balloon > newmem) > + persistentDef->mem.cur_balloon = newmem; > + ret = virDomainSaveConfig(driver->configDir, persistentDef); Good - you cap the current memory if the maximum dropped. > + goto endjob; > + } > + > + } else { > + /* resize the current memory */ > + > + if (newmem > vm->def->mem.max_balloon) { > + qemuReportError(VIR_ERR_INVALID_ARG, > + "%s", _("cannot set memory higher than max memory")); Ah, you moved it down lower, answering my first question. > + goto endjob; > + } > + > + if (flags & VIR_DOMAIN_MEM_LIVE) { > + priv = vm->privateData; > + qemuDomainObjEnterMonitor(vm); > + r = qemuMonitorSetBalloon(priv->mon, newmem); > + qemuDomainObjExitMonitor(vm); > + qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", r == 1); This indentation caused lines longer than 80 columns, so I tweaked that. > + if (r < 0) > + goto endjob; > + > + /* Lack of balloon support is a fatal error */ > + if (r == 0) { > + qemuReportError(VIR_ERR_OPERATION_INVALID, > + "%s", _("cannot set memory of an active domain")); > + goto endjob; > + } > + } > + > + if (flags & VIR_DOMAIN_MEM_CONFIG) { > + persistentDef->mem.cur_balloon = newmem; > + ret = virDomainSaveConfig(driver->configDir, persistentDef); > + goto endjob; > + } > } > > ret = 0; > @@ -1665,6 +1693,11 @@ static int qemudDomainSetMemory(virDomai > return qemudDomainSetMemoryFlags(dom, newmem, VIR_DOMAIN_MEM_LIVE); > } > > +static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) { > + return qemudDomainSetMemoryFlags(dom, memory, > + VIR_DOMAIN_MEM_MAXIMUM | VIR_DOMAIN_MEM_LIVE); Hmm. Given the above implementation, this will _always_ fail. Then again, the failure message will be nicer (the function used to fail with "not implemented", now it fails with "cannot resize memory on an active domain"), so I guess it's okay to provide this stub. And given the documentation in libvirt.c, this is accurate (that documentation explicitly stated that it only works on live domains). But the real clincher is how xen behaves. I just tested, and my RHEL 5 machine with xen:/// was able to change persistent max memory of an inactive domain, so the documentation in libvirt.c is wrong. I then tried an active domain, which (surprisingly) changed the max cap, then promptly forgot the change when the domain went inactive again proving that it behaved like _LIVE and not _LIVE|_CONFIG. Qemu can't change max mem on a live domain (it's capped at qemu startup time) even if xen can, so if we tweak the libvirt.c wording to accommodate both xen and qemu behaviors (since it was already inaccurate for xen), then we can make this function succeed some of the time by defaulting to _CURRENT|_MAXIMUM instead of _LIVE|_MAXIMUM. > +} > + > static int qemudDomainGetInfo(virDomainPtr dom, > virDomainInfoPtr info) { > struct qemud_driver *driver = dom->conn->privateData; > @@ -6849,7 +6882,7 @@ static virDriver qemuDriver = { > qemudDomainDestroy, /* domainDestroy */ > qemudDomainGetOSType, /* domainGetOSType */ > qemudDomainGetMaxMemory, /* domainGetMaxMemory */ > - NULL, /* domainSetMaxMemory */ > + qemudDomainSetMaxMemory, /* domainSetMaxMemory */ > qemudDomainSetMemory, /* domainSetMemory */ > qemudDomainSetMemoryFlags, /* domainSetMemoryFlags */ > qemuDomainSetMemoryParameters, /* domainSetMemoryParameters */ > So, here's what I squashed in before pushing: diff --git i/src/libvirt.c w/src/libvirt.c index 4a39695..0da9885 100644 --- i/src/libvirt.c +++ w/src/libvirt.c @@ -2714,8 +2714,9 @@ error: * to Domain0 i.e. the domain where the application runs. * This function requires privileged access to the hypervisor. * - * This command only changes the runtime configuration of the domain, - * so can only be called on an active domain. + * This command is hypervisor-specific for whether active, persistent, + * or both configurations are changed; for more control, use + * virDomainSetMemoryFlags(). * * Returns 0 in case of success and -1 in case of failure. */ diff --git i/src/qemu/qemu_driver.c w/src/qemu/qemu_driver.c index a547faf..8a8b55d 100644 --- i/src/qemu/qemu_driver.c +++ w/src/qemu/qemu_driver.c @@ -1632,8 +1632,9 @@ static int qemudDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, /* resize the maximum memory */ if (flags & VIR_DOMAIN_MEM_LIVE) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - _("cannot resize the maximum memory on an active domain")); + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot resize the maximum memory on an " + "active domain")); goto endjob; } @@ -1649,8 +1650,8 @@ static int qemudDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, /* resize the current memory */ if (newmem > vm->def->mem.max_balloon) { - qemuReportError(VIR_ERR_INVALID_ARG, - "%s", _("cannot set memory higher than max memory")); + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("cannot set memory higher than max memory")); goto endjob; } @@ -1659,14 +1660,15 @@ static int qemudDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, qemuDomainObjEnterMonitor(vm); r = qemuMonitorSetBalloon(priv->mon, newmem); qemuDomainObjExitMonitor(vm); - qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", r == 1); + qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", + r == 1); if (r < 0) goto endjob; /* Lack of balloon support is a fatal error */ if (r == 0) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot set memory of an active domain")); + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot set memory of an active domain")); goto endjob; } } @@ -1695,7 +1697,8 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) { return qemudDomainSetMemoryFlags(dom, memory, - VIR_DOMAIN_MEM_MAXIMUM | VIR_DOMAIN_MEM_LIVE); + (VIR_DOMAIN_MEM_MAXIMUM | + VIR_DOMAIN_MEM_CURRENT)); } static int qemudDomainGetInfo(virDomainPtr dom, -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 8 23:40:52 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 08 Apr 2011 17:40:52 -0600 Subject: [libvirt] [PATCH 1/3] maxmem: introduces VIR_DOMAIN_MEM_MAXIMUM flag In-Reply-To: <4D9E980F.5090904@jp.fujitsu.com> References: <4D9E953A.4070102@jp.fujitsu.com> <4D9E980F.5090904@jp.fujitsu.com> Message-ID: <4D9F9D04.9050304@redhat.com> On 04/07/2011 11:07 PM, Taku Izumi wrote: > > This patch introduces VIR_DOMAIN_MEM_MAXIMUM flag. > > Signed-off-by: Taku Izumi > --- > include/libvirt/libvirt.h.in | 1 + > src/libvirt.c | 2 ++ > 2 files changed, 3 insertions(+) > > Index: libvirt/include/libvirt/libvirt.h.in > =================================================================== > --- libvirt.orig/include/libvirt/libvirt.h.in > +++ libvirt/include/libvirt/libvirt.h.in > @@ -857,6 +857,7 @@ typedef enum { > VIR_DOMAIN_MEM_CURRENT = 0, /* affect current domain state */ > VIR_DOMAIN_MEM_LIVE = (1 << 0), /* affect active domain */ > VIR_DOMAIN_MEM_CONFIG = (1 << 1), /* affect next boot */ > + VIR_DOMAIN_MEM_MAXIMUM = (1 << 2), /* affect Max rather than current */ > } virDomainMemoryModFlags; ACK and pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Sat Apr 9 02:25:32 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 08 Apr 2011 20:25:32 -0600 Subject: [libvirt] [PATCH 3/3] setmaxmem: add the new options to "virsh setmaxmem" command In-Reply-To: <4D9E9864.1060805@jp.fujitsu.com> References: <4D9E953A.4070102@jp.fujitsu.com> <4D9E9864.1060805@jp.fujitsu.com> Message-ID: <4D9FC39C.2090703@redhat.com> On 04/07/2011 11:08 PM, Taku Izumi wrote: > > This patch adds the new options (--live, --config, and --current) to "virsh setmaxmem" > command. The behavior of above options is the same as that of "virsh setmem". > When the --config option is specified, a modofication is effective for the s/modofication/modification/ > persistent domain, while the --live option is specified, a modification is effective > for an active domain. The --current option is specified, it affects a current domain. Long lines - 80 columns is nice, and for commit messages, I tend to be even more conservative at 70 columns (since git log indents the text). > > + > + if (current) { > + if(live || config) { s/if(/if (/ ACK with that nit fixed, and pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Sat Apr 9 09:59:06 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 9 Apr 2011 11:59:06 +0200 Subject: [libvirt] [PATCH 0/5] phyp: Cleanups and memory leak fixes Message-ID: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> This series covers several things I came across while improving the semantic of phypVolumeGetKey. Matthias From matthias.bolte at googlemail.com Sat Apr 9 09:59:07 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 9 Apr 2011 11:59:07 +0200 Subject: [libvirt] [PATCH 1/5] phyp: Remove stack allocating a 4kb volume key and fix related memory leaks In-Reply-To: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> References: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1302343151-24133-2-git-send-email-matthias.bolte@googlemail.com> Don't pre-allocate 4kb per key, make phypVolumeGetKey allocate the memory. Make phypBuildVolume return the volume key instead of using pre-allocated memory to store it. Also fix a memory leak in phypVolumeLookupByName when phypVolumeGetKey fails. Fix another memory leak in phypVolumeLookupByPath in the success path. Fix phypVolumeGetXMLDesc leaking voldef.key. --- src/phyp/phyp_driver.c | 98 ++++++++++++++++++++++++++--------------------- src/phyp/phyp_driver.h | 1 - 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index ddbc103..bd508fb 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -2153,8 +2153,8 @@ phypAttachDevice(virDomainPtr domain, const char *xml) return -1; } -static int -phypVolumeGetKey(virConnectPtr conn, char *key, const char *name) +static char * +phypVolumeGetKey(virConnectPtr conn, const char *name) { ConnectionData *connection_data = conn->networkPrivateData; phyp_driverPtr phyp_driver = conn->privateData; @@ -2182,10 +2182,10 @@ phypVolumeGetKey(virConnectPtr conn, char *key, const char *name) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + return NULL; } - cmd = virBufferContentAndReset(&buf); + cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) @@ -2196,17 +2196,13 @@ phypVolumeGetKey(virConnectPtr conn, char *key, const char *name) if (char_ptr) *char_ptr = '\0'; - if (memcpy(key, ret, MAX_KEY_SIZE) == NULL) - goto err; - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + return ret; err: VIR_FREE(cmd); VIR_FREE(ret); - return -1; + return NULL; } static char * @@ -2313,9 +2309,9 @@ phypGetStoragePoolSize(virConnectPtr conn, char *name) return -1; } -static int +static char * phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, - unsigned int capacity, char *key) + unsigned int capacity) { ConnectionData *connection_data = conn->networkPrivateData; phyp_driverPtr phyp_driver = conn->privateData; @@ -2327,6 +2323,7 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, char *ret = NULL; int exit_status = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; + char *key; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -2340,10 +2337,10 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + return NULL; } - cmd = virBufferContentAndReset(&buf); + cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0) { @@ -2351,29 +2348,37 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, goto err; } - if (phypVolumeGetKey(conn, key, lvname) == -1) - goto err;; + key = phypVolumeGetKey(conn, lvname); + + if (key == NULL) + goto err; VIR_FREE(cmd); VIR_FREE(ret); - return 0; + return key; err: VIR_FREE(cmd); VIR_FREE(ret); - return -1; + return NULL; } static virStorageVolPtr phypVolumeLookupByName(virStoragePoolPtr pool, const char *volname) { + char *key; + virStorageVolPtr vol; - char key[MAX_KEY_SIZE]; + key = phypVolumeGetKey(pool->conn, volname); - if (phypVolumeGetKey(pool->conn, key, volname) == -1) + if (key == NULL) return NULL; - return virGetStorageVol(pool->conn, pool->name, volname, key); + vol = virGetStorageVol(pool->conn, pool->name, volname, key); + + VIR_FREE(key); + + return vol; } static virStorageVolPtr @@ -2392,11 +2397,6 @@ phypStorageVolCreateXML(virStoragePoolPtr pool, return NULL; } - if (VIR_ALLOC_N(key, MAX_KEY_SIZE) < 0) { - virReportOOMError(); - return NULL; - } - /* Filling spdef manually * */ if (pool->name != NULL) { @@ -2454,9 +2454,10 @@ phypStorageVolCreateXML(virStoragePoolPtr pool, goto err; } - if (phypBuildVolume - (pool->conn, voldef->name, spdef->name, voldef->capacity, - key) == -1) + key = phypBuildVolume(pool->conn, voldef->name, spdef->name, + voldef->capacity); + + if (key == NULL) goto err; if ((vol = @@ -2464,9 +2465,12 @@ phypStorageVolCreateXML(virStoragePoolPtr pool, key)) == NULL) goto err; + VIR_FREE(key); + return vol; err: + VIR_FREE(key); virStorageVolDefFree(voldef); virStoragePoolDefFree(spdef); if (vol) @@ -2540,8 +2544,10 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) int exit_status = 0; char *cmd = NULL; char *spname = NULL; + char *char_ptr; char *key = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; + virStorageVolPtr vol; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -2566,20 +2572,21 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) if (exit_status < 0 || spname == NULL) return NULL; - char *char_ptr = strchr(spname, '\n'); + char_ptr = strchr(spname, '\n'); if (char_ptr) *char_ptr = '\0'; - if (VIR_ALLOC_N(key, MAX_KEY_SIZE) < 0) { - virReportOOMError(); - return NULL; - } + key = phypVolumeGetKey(conn, volname); - if (phypVolumeGetKey(conn, key, volname) == -1) + if (key == NULL) return NULL; - return virGetStorageVol(conn, spname, volname, key); + vol = virGetStorageVol(conn, spname, volname, key); + + VIR_FREE(key); + + return vol; } static int @@ -2647,6 +2654,8 @@ phypStoragePoolLookupByName(virConnectPtr conn, const char *name) static char * phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags) { + char *xml; + virCheckFlags(0, NULL); virStorageVolDef voldef; @@ -2661,11 +2670,6 @@ phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags) virStoragePoolDef pool; memset(&pool, 0, sizeof(virStoragePoolDef)); - if (VIR_ALLOC_N(voldef.key, MAX_KEY_SIZE) < 0) { - virReportOOMError(); - return NULL; - } - if (sp->name != NULL) { pool.name = sp->name; } else { @@ -2702,14 +2706,20 @@ phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags) goto err; } - if (memmove(voldef.key, vol->key, PATH_MAX) == NULL) { - VIR_ERROR0(_("Unable to determine volume's key.")); + voldef.key = strdup(vol->key); + + if (voldef.key == NULL) { + virReportOOMError(); goto err; } voldef.type = VIR_STORAGE_POOL_LOGICAL; - return virStorageVolDefFormat(&pool, &voldef); + xml = virStorageVolDefFormat(&pool, &voldef); + + VIR_FREE(voldef.key); + + return xml; err: return NULL; diff --git a/src/phyp/phyp_driver.h b/src/phyp/phyp_driver.h index bc8e003..a22156c 100644 --- a/src/phyp/phyp_driver.h +++ b/src/phyp/phyp_driver.h @@ -30,7 +30,6 @@ # include # include -# define MAX_KEY_SIZE (1024*4) # define LPAR_EXEC_ERR -1 # define SSH_CONN_ERR -2 /* error while trying to connect to remote host */ # define SSH_CMD_ERR -3 /* error while trying to execute the remote cmd */ -- 1.7.0.4 From matthias.bolte at googlemail.com Sat Apr 9 09:59:08 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 9 Apr 2011 11:59:08 +0200 Subject: [libvirt] [PATCH 2/5] phyp: Reduce code duplication in error and success paths In-Reply-To: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> References: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1302343151-24133-3-git-send-email-matthias.bolte@googlemail.com> Also fix memory leaks along the way in phypCreateServerSCSIAdapter and phypAttachDevice. --- src/phyp/phyp_driver.c | 592 +++++++++++++++++++++++------------------------- 1 files changed, 289 insertions(+), 303 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index bd508fb..f441261 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -109,7 +109,7 @@ waitsocket(int socket_fd, LIBSSH2_SESSION * session) /* this function is the layer that manipulates the ssh channel itself * and executes the commands on the remote machine */ static char * -phypExec(LIBSSH2_SESSION * session, char *cmd, int *exit_status, +phypExec(LIBSSH2_SESSION *session, const char *cmd, int *exit_status, virConnectPtr conn) { LIBSSH2_CHANNEL *channel; @@ -249,19 +249,16 @@ phypGetVIOSPartitionID(virConnectPtr conn) ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &id) == -1) - goto err; + goto cleanup; + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return id; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; + return id; } static virCapsPtr @@ -324,7 +321,7 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) LIBSSH2_SESSION *session = connection_data->session; int system_type = phyp_driver->system_type; int exit_status = 0; - int ndom = 0; + int ndom = -1; char *char_ptr; char *cmd = NULL; char *ret = NULL; @@ -358,19 +355,16 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &ndom) == -1) - goto err; + goto cleanup; + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return ndom; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; + return ndom; } /* This is a generic function that won't be used directly by @@ -417,7 +411,7 @@ phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids, ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; /* I need to parse the textual return in order to get the ids */ line = ret; @@ -426,7 +420,7 @@ phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids, if (virStrToLong_i(line, &next_line, 10, &ids[got]) == -1) { VIR_ERROR(_("Cannot parse number from '%s'"), line); got = -1; - goto err; + goto cleanup; } got++; line = next_line; @@ -434,9 +428,10 @@ phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids, line++; /* skip \n */ } - err: + cleanup: VIR_FREE(cmd); VIR_FREE(ret); + return got; } @@ -1300,7 +1295,7 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; int exit_status = 0; - int lpar_id = 0; + int lpar_id = -1; char *char_ptr; char *cmd = NULL; char *ret = NULL; @@ -1320,19 +1315,16 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) - goto err; + goto cleanup; + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return lpar_id; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; + return lpar_id; } /* return the lpar name given a lpar_id and a managed system name */ @@ -1361,21 +1353,20 @@ phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system, ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0 || ret == NULL) - goto err; + if (exit_status < 0 || ret == NULL) { + VIR_FREE(ret); + goto cleanup; + } char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; + cleanup: VIR_FREE(cmd); - return ret; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return NULL; + return ret; } @@ -1442,7 +1433,7 @@ phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id, ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; char_ptr = strchr(ret, '\n'); @@ -1450,17 +1441,13 @@ phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id, *char_ptr = '\0'; if (virStrToLong_i(ret, &char_ptr, 10, &memory) == -1) - goto err; - - VIR_FREE(cmd); - VIR_FREE(ret); - return memory; + goto cleanup; - err: + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return 0; + return memory; } static unsigned long @@ -1494,7 +1481,7 @@ phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system, ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; char_ptr = strchr(ret, '\n'); @@ -1502,16 +1489,13 @@ phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system, *char_ptr = '\0'; if (virStrToLong_i(ret, &char_ptr, 10, &vcpus) == -1) - goto err; + goto cleanup; + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return (unsigned long) vcpus; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + return vcpus; } static unsigned long @@ -1552,7 +1536,7 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, char *cmd = NULL; char *ret = NULL; char *char_ptr; - int remote_slot = 0; + int remote_slot = -1; int exit_status = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -1571,7 +1555,7 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; char_ptr = strchr(ret, '\n'); @@ -1579,16 +1563,13 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, *char_ptr = '\0'; if (virStrToLong_i(ret, &char_ptr, 10, &remote_slot) == -1) - goto err; + goto cleanup; + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return remote_slot; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; + return remote_slot; } /* XXX - is this needed? */ @@ -1629,7 +1610,7 @@ phypGetBackingDevice(virConnectPtr conn, const char *managed_system, ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; /* here is a little trick to deal returns of this kind: * @@ -1645,13 +1626,13 @@ phypGetBackingDevice(virConnectPtr conn, const char *managed_system, if (char_ptr[0] == '/') char_ptr++; else - goto err; + goto cleanup; backing_device = strdup(char_ptr); if (backing_device == NULL) { virReportOOMError(); - goto err; + goto cleanup; } } else { backing_device = ret; @@ -1663,14 +1644,11 @@ phypGetBackingDevice(virConnectPtr conn, const char *managed_system, if (char_ptr) *char_ptr = '\0'; + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return backing_device; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return NULL; + return backing_device; } static char * @@ -1702,21 +1680,20 @@ phypGetLparProfile(virConnectPtr conn, int lpar_id) ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0 || ret == NULL) - goto err; + if (exit_status < 0 || ret == NULL) { + VIR_FREE(ret); + goto cleanup; + } char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; + cleanup: VIR_FREE(cmd); - return ret; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return NULL; + return ret; } static int @@ -1733,12 +1710,12 @@ phypGetVIOSNextSlotNumber(virConnectPtr conn) char *cmd = NULL; char *ret = NULL; char *profile = NULL; - int slot = 0; + int slot = -1; virBuffer buf = VIR_BUFFER_INITIALIZER; if (!(profile = phypGetLparProfile(conn, vios_id))) { VIR_ERROR0(_("Unable to get VIOS profile name.")); - goto err; + return -1; } virBufferAddLit(&buf, "lssyscfg"); @@ -1756,7 +1733,7 @@ phypGetVIOSNextSlotNumber(virConnectPtr conn) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + goto cleanup; } cmd = virBufferContentAndReset(&buf); @@ -1764,24 +1741,25 @@ phypGetVIOSNextSlotNumber(virConnectPtr conn) ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) - goto err; + goto cleanup; - VIR_FREE(cmd); - VIR_FREE(ret); - return slot + 1; + slot += 1; - err: + cleanup: + VIR_FREE(profile); VIR_FREE(cmd); VIR_FREE(ret); - return -1; + + return slot; } static int phypCreateServerSCSIAdapter(virConnectPtr conn) { + int result = -1; ConnectionData *connection_data = conn->networkPrivateData; phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; @@ -1800,17 +1778,17 @@ phypCreateServerSCSIAdapter(virConnectPtr conn) (vios_name = phypGetLparNAME(session, managed_system, vios_id, conn))) { VIR_ERROR0(_("Unable to get VIOS name")); - goto err; + goto cleanup; } if (!(profile = phypGetLparProfile(conn, vios_id))) { VIR_ERROR0(_("Unable to get VIOS profile name.")); - goto err; + goto cleanup; } if ((slot = phypGetVIOSNextSlotNumber(conn)) == -1) { VIR_ERROR0(_("Unable to get free slot number")); - goto err; + goto cleanup; } /* Listing all the virtual_scsi_adapter interfaces, the new adapter must @@ -1825,14 +1803,14 @@ phypCreateServerSCSIAdapter(virConnectPtr conn) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + goto cleanup; } cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; /* Here I change the VIOS configuration to append the new adapter * with the free slot I got with phypGetVIOSNextSlotNumber. @@ -1846,14 +1824,17 @@ phypCreateServerSCSIAdapter(virConnectPtr conn) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + goto cleanup; } - cmd = virBufferContentAndReset(&buf); + VIR_FREE(cmd); + VIR_FREE(ret); + + cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; /* Finally I add the new scsi adapter to VIOS using the same slot * I used in the VIOS configuration. @@ -1867,27 +1848,27 @@ phypCreateServerSCSIAdapter(virConnectPtr conn) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + goto cleanup; } - cmd = virBufferContentAndReset(&buf); + VIR_FREE(cmd); + VIR_FREE(ret); + + cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; - VIR_FREE(profile); - VIR_FREE(vios_name); - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + result = 0; - err: + cleanup: VIR_FREE(profile); VIR_FREE(vios_name); VIR_FREE(cmd); VIR_FREE(ret); - return -1; + + return result; } static char * @@ -1925,28 +1906,27 @@ phypGetVIOSFreeSCSIAdapter(virConnectPtr conn) ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0 || ret == NULL) - goto err; + if (exit_status < 0 || ret == NULL) { + VIR_FREE(ret); + goto cleanup; + } char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; + cleanup: VIR_FREE(cmd); - return ret; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return NULL; + return ret; } static int phypAttachDevice(virDomainPtr domain, const char *xml) { - + int result = -1; virConnectPtr conn = domain->conn; ConnectionData *connection_data = domain->conn->networkPrivateData; phyp_driverPtr phyp_driver = domain->conn->privateData; @@ -1982,21 +1962,21 @@ phypAttachDevice(virDomainPtr domain, const char *xml) if (def->os.type == NULL) { virReportOOMError(); - goto err; + goto cleanup; } dev = virDomainDeviceDefParse(phyp_driver->caps, def, xml, VIR_DOMAIN_XML_INACTIVE); if (!dev) { virReportOOMError(); - goto err; + goto cleanup; } if (! (vios_name = phypGetLparNAME(session, managed_system, vios_id, conn))) { VIR_ERROR0(_("Unable to get VIOS name")); - goto err; + goto cleanup; } /* First, let's look for a free SCSI Adapter @@ -2006,11 +1986,11 @@ phypAttachDevice(virDomainPtr domain, const char *xml) * */ if (phypCreateServerSCSIAdapter(conn) == -1) { VIR_ERROR0(_("Unable to create new virtual adapter")); - goto err; + goto cleanup; } else { if (!(scsi_adapter = phypGetVIOSFreeSCSIAdapter(conn))) { VIR_ERROR0(_("Unable to create new virtual adapter")); - goto err; + goto cleanup; } } } @@ -2028,18 +2008,21 @@ phypAttachDevice(virDomainPtr domain, const char *xml) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + goto cleanup; } - cmd = virBufferContentAndReset(&buf); + VIR_FREE(cmd); + VIR_FREE(ret); + + cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (!(profile = phypGetLparProfile(conn, domain->id))) { VIR_ERROR0(_("Unable to get VIOS profile name.")); - goto err; + goto cleanup; } /* Let's get the slot number for the adapter we just created @@ -2053,17 +2036,20 @@ phypAttachDevice(virDomainPtr domain, const char *xml) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + goto cleanup; } - cmd = virBufferContentAndReset(&buf); + VIR_FREE(cmd); + VIR_FREE(ret); + + cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) - goto err; + goto cleanup; /* Listing all the virtual_scsi_adapter interfaces, the new adapter must * be appended to this list @@ -2078,14 +2064,17 @@ phypAttachDevice(virDomainPtr domain, const char *xml) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + goto cleanup; } - cmd = virBufferContentAndReset(&buf); + VIR_FREE(cmd); + VIR_FREE(ret); + + cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; /* Here I change the LPAR configuration to append the new adapter * with the new slot we just created @@ -2101,14 +2090,17 @@ phypAttachDevice(virDomainPtr domain, const char *xml) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + goto cleanup; } - cmd = virBufferContentAndReset(&buf); + VIR_FREE(cmd); + VIR_FREE(ret); + + cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) - goto err; + goto cleanup; /* Finally I add the new scsi adapter to VIOS using the same slot * I used in the VIOS configuration. @@ -2122,35 +2114,35 @@ phypAttachDevice(virDomainPtr domain, const char *xml) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + goto cleanup; } - cmd = virBufferContentAndReset(&buf); + VIR_FREE(cmd); + VIR_FREE(ret); + + cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) { VIR_ERROR0(_ ("Possibly you don't have IBM Tools installed in your LPAR." "Contact your support to enable this feature.")); - goto err; + goto cleanup; } - VIR_FREE(cmd); - VIR_FREE(ret); - VIR_FREE(def); - VIR_FREE(dev); - VIR_FREE(vios_name); - VIR_FREE(scsi_adapter); - return 0; + result = 0; - err: + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - VIR_FREE(def); - VIR_FREE(dev); + virDomainDeviceDefFree(dev); + virDomainDefFree(def); VIR_FREE(vios_name); VIR_FREE(scsi_adapter); - return -1; + VIR_FREE(profile); + VIR_FREE(domain_name); + + return result; } static char * @@ -2188,21 +2180,20 @@ phypVolumeGetKey(virConnectPtr conn, const char *name) cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0 || ret == NULL) - goto err; + if (exit_status < 0 || ret == NULL) { + VIR_FREE(ret); + goto cleanup; + } char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; + cleanup: VIR_FREE(cmd); - return ret; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return NULL; + return ret; } static char * @@ -2240,21 +2231,20 @@ phypGetStoragePoolDevice(virConnectPtr conn, char *name) ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0 || ret == NULL) - goto err; + if (exit_status < 0 || ret == NULL) { + VIR_FREE(ret); + goto cleanup; + } char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; + cleanup: VIR_FREE(cmd); - return ret; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return NULL; + return ret; } static unsigned long int @@ -2269,7 +2259,7 @@ phypGetStoragePoolSize(virConnectPtr conn, char *name) int vios_id = phyp_driver->vios_id; char *cmd = NULL; char *ret = NULL; - int sp_size = 0; + int sp_size = -1; char *char_ptr; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -2294,19 +2284,16 @@ phypGetStoragePoolSize(virConnectPtr conn, char *name) ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &sp_size) == -1) - goto err; + goto cleanup; + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return sp_size; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; + return sp_size; } static char * @@ -2323,7 +2310,7 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, char *ret = NULL; int exit_status = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; - char *key; + char *key = NULL; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -2345,22 +2332,19 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, if (exit_status < 0) { VIR_ERROR(_("Unable to create Volume: %s"), ret); - goto err; + goto cleanup; } key = phypVolumeGetKey(conn, lvname); if (key == NULL) - goto err; + goto cleanup; + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return key; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return NULL; + return key; } static virStorageVolPtr @@ -2514,22 +2498,20 @@ phypVolumeGetPhysicalVolumeByStoragePool(virStorageVolPtr vol, char *sp) ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0 || ret == NULL) - goto err; + if (exit_status < 0 || ret == NULL) { + VIR_FREE(ret); + goto cleanup; + } char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; + cleanup: VIR_FREE(cmd); - return ret; - - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return NULL; + return ret; } static virStorageVolPtr @@ -2547,7 +2529,7 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) char *char_ptr; char *key = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; - virStorageVolPtr vol; + virStorageVolPtr vol = NULL; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -2570,7 +2552,7 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) spname = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || spname == NULL) - return NULL; + goto cleanup; char_ptr = strchr(spname, '\n'); @@ -2580,10 +2562,13 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) key = phypVolumeGetKey(conn, volname); if (key == NULL) - return NULL; + goto cleanup; vol = virGetStorageVol(conn, spname, volname, key); + cleanup: + VIR_FREE(cmd); + VIR_FREE(spname); VIR_FREE(key); return vol; @@ -2593,6 +2578,7 @@ static int phypGetStoragePoolUUID(virConnectPtr conn, unsigned char *uuid, const char *name) { + int result = -1; ConnectionData *connection_data = conn->networkPrivateData; phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; @@ -2625,19 +2611,18 @@ phypGetStoragePoolUUID(virConnectPtr conn, unsigned char *uuid, ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (memmove(uuid, ret, VIR_UUID_BUFLEN) == NULL) - goto err; + goto cleanup; - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + result = 0; - err: + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return -1; + + return result; } static virStoragePoolPtr @@ -2654,22 +2639,21 @@ phypStoragePoolLookupByName(virConnectPtr conn, const char *name) static char * phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags) { + virStorageVolDef voldef; + virStoragePoolDef pool; + virStoragePoolPtr sp; char *xml; virCheckFlags(0, NULL); - virStorageVolDef voldef; memset(&voldef, 0, sizeof(virStorageVolDef)); + memset(&pool, 0, sizeof(virStoragePoolDef)); - virStoragePoolPtr sp = - phypStoragePoolLookupByName(vol->conn, vol->pool); + sp = phypStoragePoolLookupByName(vol->conn, vol->pool); if (!sp) goto err; - virStoragePoolDef pool; - memset(&pool, 0, sizeof(virStoragePoolDef)); - if (sp->name != NULL) { pool.name = sp->name; } else { @@ -2773,7 +2757,7 @@ phypVolumeGetPath(virStorageVolPtr vol) sp = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || sp == NULL) - goto err; + goto cleanup; char_ptr = strchr(sp, '\n'); @@ -2782,23 +2766,20 @@ phypVolumeGetPath(virStorageVolPtr vol) pv = phypVolumeGetPhysicalVolumeByStoragePool(vol, sp); - if (pv) { - if (virAsprintf(&path, "/%s/%s/%s", pv, sp, vol->name) < 0) { - virReportOOMError(); - goto err; - } - } else { - goto err; - } + if (!pv) + goto cleanup; - VIR_FREE(cmd); - return path; + if (virAsprintf(&path, "/%s/%s/%s", pv, sp, vol->name) < 0) { + virReportOOMError(); + goto cleanup; + } - err: + cleanup: VIR_FREE(cmd); VIR_FREE(sp); VIR_FREE(path); - return NULL; + + return path; } @@ -2806,6 +2787,7 @@ static int phypStoragePoolListVolumes(virStoragePoolPtr pool, char **const volumes, int nvolumes) { + bool success = false; virConnectPtr conn = pool->conn; ConnectionData *connection_data = conn->networkPrivateData; phyp_driverPtr phyp_driver = conn->privateData; @@ -2844,7 +2826,7 @@ phypStoragePoolListVolumes(virStoragePoolPtr pool, char **const volumes, /* I need to parse the textual return in order to get the volumes */ if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; else { volumes_list = ret; @@ -2855,7 +2837,7 @@ phypStoragePoolListVolumes(virStoragePoolPtr pool, char **const volumes, *char_ptr2 = '\0'; if ((volumes[got++] = strdup(volumes_list)) == NULL) { virReportOOMError(); - goto err; + goto cleanup; } char_ptr2++; volumes_list = char_ptr2; @@ -2864,16 +2846,20 @@ phypStoragePoolListVolumes(virStoragePoolPtr pool, char **const volumes, } } - VIR_FREE(cmd); - VIR_FREE(ret); - return got; + success = true; + + cleanup: + if (!success) { + for (i = 0; i < got; i++) + VIR_FREE(volumes[i]); + + got = -1; + } - err: - for (i = 0; i < got; i++) - VIR_FREE(volumes[i]); VIR_FREE(cmd); VIR_FREE(ret); - return -1; + + return got; } static int @@ -2885,7 +2871,7 @@ phypStoragePoolNumOfVolumes(virStoragePoolPtr pool) LIBSSH2_SESSION *session = connection_data->session; int system_type = phyp_driver->system_type; int exit_status = 0; - int nvolumes = 0; + int nvolumes = -1; char *cmd = NULL; char *ret = NULL; char *managed_system = phyp_driver->managed_system; @@ -2911,27 +2897,25 @@ phypStoragePoolNumOfVolumes(virStoragePoolPtr pool) ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &nvolumes) == -1) - goto err; + goto cleanup; /* We need to remove 2 line from the header text output */ nvolumes -= 2; + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return nvolumes; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; + return nvolumes; } static int phypDestroyStoragePool(virStoragePoolPtr pool) { + int result = -1; virConnectPtr conn = pool->conn; ConnectionData *connection_data = conn->networkPrivateData; phyp_driverPtr phyp_driver = conn->privateData; @@ -2965,29 +2949,29 @@ phypDestroyStoragePool(virStoragePoolPtr pool) "'rmsp %s'", managed_system, vios_id, pool->name) < 0) { virReportOOMError(); - goto err; + goto cleanup; } ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0) { VIR_ERROR(_("Unable to create Storage Pool: %s"), ret); - goto err; + goto cleanup; } - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + result = 0; - err: + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return -1; + + return result; } static int phypBuildStoragePool(virConnectPtr conn, virStoragePoolDefPtr def) { + int result = -1; ConnectionData *connection_data = conn->networkPrivateData; phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; @@ -3021,17 +3005,16 @@ phypBuildStoragePool(virConnectPtr conn, virStoragePoolDefPtr def) if (exit_status < 0) { VIR_ERROR(_("Unable to create Storage Pool: %s"), ret); - goto err; + goto cleanup; } - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + result = 0; - err: + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return -1; + + return result; } @@ -3043,7 +3026,7 @@ phypNumOfStoragePools(virConnectPtr conn) LIBSSH2_SESSION *session = connection_data->session; int system_type = phyp_driver->system_type; int exit_status = 0; - int nsp = 0; + int nsp = -1; char *cmd = NULL; char *ret = NULL; char *managed_system = phyp_driver->managed_system; @@ -3072,24 +3055,22 @@ phypNumOfStoragePools(virConnectPtr conn) ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &nsp) == -1) - goto err; + goto cleanup; + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return nsp; - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; + return nsp; } static int phypListStoragePools(virConnectPtr conn, char **const pools, int npools) { + bool success = false; ConnectionData *connection_data = conn->networkPrivateData; phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; @@ -3125,7 +3106,7 @@ phypListStoragePools(virConnectPtr conn, char **const pools, int npools) /* I need to parse the textual return in order to get the storage pools */ if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; else { storage_pools = ret; @@ -3136,7 +3117,7 @@ phypListStoragePools(virConnectPtr conn, char **const pools, int npools) *char_ptr2 = '\0'; if ((pools[got++] = strdup(storage_pools)) == NULL) { virReportOOMError(); - goto err; + goto cleanup; } char_ptr2++; storage_pools = char_ptr2; @@ -3145,16 +3126,20 @@ phypListStoragePools(virConnectPtr conn, char **const pools, int npools) } } - VIR_FREE(cmd); - VIR_FREE(ret); - return got; + success = true; + + cleanup: + if (!success) { + for (i = 0; i < got; i++) + VIR_FREE(pools[i]); + + got = -1; + } - err: - for (i = 0; i < got; i++) - VIR_FREE(pools[i]); VIR_FREE(cmd); VIR_FREE(ret); - return -1; + + return got; } static virStoragePoolPtr @@ -3421,6 +3406,7 @@ phypListDomains(virConnectPtr conn, int *ids, int nids) static int phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames) { + bool success = false; ConnectionData *connection_data = conn->networkPrivateData; phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; @@ -3451,7 +3437,7 @@ phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames) /* I need to parse the textual return in order to get the domains */ if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; else { domains = ret; @@ -3462,7 +3448,7 @@ phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames) *char_ptr2 = '\0'; if ((names[got++] = strdup(domains)) == NULL) { virReportOOMError(); - goto err; + goto cleanup; } char_ptr2++; domains = char_ptr2; @@ -3471,16 +3457,20 @@ phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames) } } - VIR_FREE(cmd); - VIR_FREE(ret); - return got; + success = true; + + cleanup: + if (!success) { + for (i = 0; i < got; i++) + VIR_FREE(names[i]); + + got = -1; + } - err: - for (i = 0; i < got; i++) - VIR_FREE(names[i]); VIR_FREE(cmd); VIR_FREE(ret); - return -1; + + return got; } static virDomainPtr @@ -3524,22 +3514,20 @@ phypDomainLookupByID(virConnectPtr conn, int lpar_id) conn); if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1) - goto err; + goto cleanup; if (exit_status < 0) - goto err; + goto cleanup; dom = virGetDomain(conn, lpar_name, lpar_uuid); if (dom) dom->id = lpar_id; + cleanup: VIR_FREE(lpar_name); - return dom; - err: - VIR_FREE(lpar_name); - return NULL; + return dom; } static char * @@ -3596,6 +3584,7 @@ phypDomainDumpXML(virDomainPtr dom, int flags) static int phypDomainResume(virDomainPtr dom) { + int result = -1; ConnectionData *connection_data = dom->conn->networkPrivateData; phyp_driverPtr phyp_driver = dom->conn->privateData; LIBSSH2_SESSION *session = connection_data->session; @@ -3621,21 +3610,21 @@ phypDomainResume(virDomainPtr dom) ret = phypExec(session, cmd, &exit_status, dom->conn); if (exit_status < 0) - goto err; + goto cleanup; - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + result = 0; - err: + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return -1; + + return result; } static int phypDomainShutdown(virDomainPtr dom) { + int result = -1; ConnectionData *connection_data = dom->conn->networkPrivateData; virConnectPtr conn = dom->conn; LIBSSH2_SESSION *session = connection_data->session; @@ -3654,23 +3643,22 @@ phypDomainShutdown(virDomainPtr dom) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return 0; + return -1; } cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, dom->conn); if (exit_status < 0) - goto err; + goto cleanup; - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + result = 0; - err: + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return 0; + + return result; } static int @@ -3699,6 +3687,7 @@ phypDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) static int phypDomainDestroy(virDomainPtr dom) { + int result = -1; ConnectionData *connection_data = dom->conn->networkPrivateData; phyp_driverPtr phyp_driver = dom->conn->privateData; LIBSSH2_SESSION *session = connection_data->session; @@ -3723,27 +3712,25 @@ phypDomainDestroy(virDomainPtr dom) ret = phypExec(session, cmd, &exit_status, dom->conn); if (exit_status < 0) - goto err; + goto cleanup; if (phypUUIDTable_RemLpar(dom->conn, dom->id) == -1) - goto err; + goto cleanup; dom->id = -1; + result = 0; + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return 0; - - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; + return result; } static int phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) { + int result = -1; ConnectionData *connection_data = conn->networkPrivateData; phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; @@ -3758,27 +3745,27 @@ phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) PHYP_ERROR(VIR_ERR_XML_ERROR,"%s", _("Field \"\" on the domain XML file is missing or has " "invalid value.")); - goto err; + goto cleanup; } if (!def->mem.max_balloon) { PHYP_ERROR(VIR_ERR_XML_ERROR,"%s", _("Field \"\" on the domain XML file is missing or" " has invalid value.")); - goto err; + goto cleanup; } if (def->ndisks < 1) { PHYP_ERROR(VIR_ERR_XML_ERROR, "%s", _("Domain XML must contain at least one \"\" element.")); - goto err; + goto cleanup; } if (!def->disks[0]->src) { PHYP_ERROR(VIR_ERR_XML_ERROR,"%s", _("Field \"\" under \"\" on the domain XML file is " "missing.")); - goto err; + goto cleanup; } virBufferAddLit(&buf, "mksyscfg"); @@ -3792,7 +3779,7 @@ phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + goto cleanup; } cmd = virBufferContentAndReset(&buf); @@ -3800,22 +3787,21 @@ phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) if (exit_status < 0) { VIR_ERROR(_("Unable to create LPAR. Reason: '%s'"), ret); - goto err; + goto cleanup; } if (phypUUIDTable_AddLpar(conn, def->uuid, def->id) == -1) { VIR_ERROR0(_("Unable to add LPAR to the table")); - goto err; + goto cleanup; } - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + result = 0; - err: + cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return -1; + + return result; } static virDomainPtr -- 1.7.0.4 From matthias.bolte at googlemail.com Sat Apr 9 09:59:11 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 9 Apr 2011 11:59:11 +0200 Subject: [libvirt] [PATCH 5/5] phyp: Don't overwrite error from virDomainDeviceDefParse by OOM error In-Reply-To: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> References: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1302343151-24133-6-git-send-email-matthias.bolte@googlemail.com> --- src/phyp/phyp_driver.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 226946d..f36b357 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -2000,7 +2000,6 @@ phypAttachDevice(virDomainPtr domain, const char *xml) dev = virDomainDeviceDefParse(phyp_driver->caps, def, xml, VIR_DOMAIN_XML_INACTIVE); if (!dev) { - virReportOOMError(); goto cleanup; } -- 1.7.0.4 From matthias.bolte at googlemail.com Sat Apr 9 09:59:09 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 9 Apr 2011 11:59:09 +0200 Subject: [libvirt] [PATCH 3/5] phyp: Don't try to use a string from a failed virAsprintf In-Reply-To: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> References: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1302343151-24133-4-git-send-email-matthias.bolte@googlemail.com> --- src/phyp/phyp_driver.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index f441261..24165fb 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -210,7 +210,7 @@ phypGetSystemType(virConnectPtr conn) if (virAsprintf(&cmd, "lshmc -V") < 0) { virReportOOMError(); - exit_status = -1; + return -1; } ret = phypExec(session, cmd, &exit_status, conn); -- 1.7.0.4 From matthias.bolte at googlemail.com Sat Apr 9 09:59:10 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 9 Apr 2011 11:59:10 +0200 Subject: [libvirt] [PATCH 4/5] phyp: Fix too small buffer allocation in phypAttachDevice In-Reply-To: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> References: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1302343151-24133-5-git-send-email-matthias.bolte@googlemail.com> sizeof(domain->name) is the wrong thing. Instead of using strdup here rewrite escape_specialcharacters to allocate the buffer itself. Add a contains_specialcharacters to be used in phypOpen, as phypOpen is not interested in the escaped version. --- src/phyp/phyp_driver.c | 90 ++++++++++++++++++++++++++++++++--------------- 1 files changed, 61 insertions(+), 29 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 24165fb..226946d 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -891,14 +891,63 @@ phypUUIDTable_Free(uuid_tablePtr uuid_table) VIR_FREE(uuid_table); } -static int -escape_specialcharacters(char *src, char *dst, size_t dstlen) +static bool +contains_specialcharacters(const char *src) { size_t len = strlen(src); - char temp_buffer[len]; - unsigned int i = 0, j = 0; + size_t i = 0; + if (len == 0) - return -1; + return false; + + for (i = 0; i < len; i++) { + switch (src[i]) { + case '&': + case ';': + case '`': + case '@': + case '"': + case '|': + case '*': + case '?': + case '~': + case '<': + case '>': + case '^': + case '(': + case ')': + case '[': + case ']': + case '{': + case '}': + case '$': + case '%': + case '#': + case '\\': + case '\n': + case '\r': + case '\t': + return true; + } + } + + return false; +} + +static char * +escape_specialcharacters(const char *src) +{ + size_t len = strlen(src); + size_t i = 0, j = 0; + char *dst; + + if (len == 0) + return NULL; + + if (VIR_ALLOC_N(dst, len + 1) < 0) { + virReportOOMError(); + return NULL; + } for (i = 0; i < len; i++) { switch (src[i]) { @@ -929,16 +978,14 @@ escape_specialcharacters(char *src, char *dst, size_t dstlen) case '\t': continue; default: - temp_buffer[j] = src[i]; + dst[j] = src[i]; j++; } } - temp_buffer[j] = '\0'; - if (virStrcpy(dst, temp_buffer, dstlen) == NULL) - return -1; + dst[j] = '\0'; - return 0; + return dst; } static LIBSSH2_SESSION * @@ -1121,8 +1168,6 @@ phypOpen(virConnectPtr conn, { LIBSSH2_SESSION *session = NULL; ConnectionData *connection_data = NULL; - char *string = NULL; - size_t len = 0; int internal_socket; uuid_tablePtr uuid_table = NULL; phyp_driverPtr phyp_driver = NULL; @@ -1157,13 +1202,6 @@ phypOpen(virConnectPtr conn, } if (conn->uri->path) { - len = strlen(conn->uri->path) + 1; - - if (VIR_ALLOC_N(string, len) < 0) { - virReportOOMError(); - goto failure; - } - /* need to shift one byte in order to remove the first "/" of URI component */ if (conn->uri->path[0] == '/') managed_system = strdup(conn->uri->path + 1); @@ -1183,7 +1221,7 @@ phypOpen(virConnectPtr conn, if (char_ptr) *char_ptr = '\0'; - if (escape_specialcharacters(conn->uri->path, string, len) == -1) { + if (contains_specialcharacters(conn->uri->path)) { PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Error parsing 'path'. Invalid characters.")); @@ -1242,7 +1280,6 @@ phypOpen(virConnectPtr conn, } VIR_FREE(connection_data); - VIR_FREE(string); return VIR_DRV_OPEN_ERROR; } @@ -1947,15 +1984,10 @@ phypAttachDevice(virDomainPtr domain, const char *xml) virBuffer buf = VIR_BUFFER_INITIALIZER; char *domain_name = NULL; - if (VIR_ALLOC_N(domain_name, sizeof(domain->name)) < 0) { - virReportOOMError(); - goto err; - } + domain_name = escape_specialcharacters(domain->name); - if (escape_specialcharacters - (domain->name, domain_name, strlen(domain->name)) == -1) { - virReportOOMError(); - goto err; + if (domain_name == NULL) { + goto cleanup; } def->os.type = strdup("aix"); -- 1.7.0.4 From matthias.bolte at googlemail.com Sat Apr 9 10:05:17 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 9 Apr 2011 12:05:17 +0200 Subject: [libvirt] [PATCH v2] xen: Remove PATH_MAX sized stack allocation from block stats code Message-ID: <20110409100517.GA26695@sbox> --- src/xen/block_stats.c | 51 +++++++++++++++++++++++++------------------------ 1 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/xen/block_stats.c b/src/xen/block_stats.c index e7c80c9..1918257 100644 --- a/src/xen/block_stats.c +++ b/src/xen/block_stats.c @@ -113,34 +113,35 @@ read_stat (const char *path) } static int64_t -read_bd_stat (int device, int domid, const char *str) +read_bd_stat(int device, int domid, const char *str) { - char path[PATH_MAX]; + static const char *paths[] = { + "/sys/bus/xen-backend/devices/vbd-%d-%d/statistics/%s", + "/sys/bus/xen-backend/devices/tap-%d-%d/statistics/%s", + "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s", + "/sys/devices/xen-backend/tap-%d-%d/statistics/%s" + }; + + int i; + char *path; int64_t r; - snprintf (path, sizeof path, - "/sys/bus/xen-backend/devices/vbd-%d-%d/statistics/%s", - domid, device, str); - r = read_stat (path); - if (r >= 0) return r; - - snprintf (path, sizeof path, - "/sys/bus/xen-backend/devices/tap-%d-%d/statistics/%s", - domid, device, str); - r = read_stat (path); - if (r >= 0) return r; - - snprintf (path, sizeof path, - "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s", - domid, device, str); - r = read_stat (path); - if (r >= 0) return r; - - snprintf (path, sizeof path, - "/sys/devices/xen-backend/tap-%d-%d/statistics/%s", - domid, device, str); - r = read_stat (path); - return r; + for (i = 0; i < ARRAY_CARDINALITY(paths); ++i) { + if (virAsprintf(&path, paths[i], domid, device, str) < 0) { + virReportOOMError(); + return -1; + } + + r = read_stat(path); + + VIR_FREE(path); + + if (r >= 0) { + return r; + } + } + + return -1; } /* In Xenstore, /local/domain/0/backend/vbd///state, -- 1.7.0.4 From stefanb at linux.vnet.ibm.com Sat Apr 9 15:48:41 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Sat, 09 Apr 2011 11:48:41 -0400 Subject: [libvirt] [PATCH] migrate VMs between different-endian hosts Message-ID: <4DA07FD9.8000606@linux.vnet.ibm.com> This patch enables the migration of Qemu VMs between hosts of different endianess. I tested this by migrating a i686 VM between a x86 and ppc64 host. I am converting the 'int's in the VM's state header to uint32_t assuming this doesn't break compatibility with existing deployments other than Linux. Signed-off-by: Stefan Berger --- src/qemu/qemu_driver.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) Index: libvirt-acl/src/qemu/qemu_driver.c =================================================================== --- libvirt-acl.orig/src/qemu/qemu_driver.c +++ libvirt-acl/src/qemu/qemu_driver.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "qemu_driver.h" @@ -1881,13 +1882,22 @@ VIR_ENUM_IMPL(qemudSaveCompression, QEMU struct qemud_save_header { char magic[sizeof(QEMUD_SAVE_MAGIC)-1]; - int version; - int xml_len; - int was_running; - int compressed; - int unused[15]; + uint32_t version; + uint32_t xml_len; + uint32_t was_running; + uint32_t compressed; + uint32_t unused[15]; }; +static inline void +bswap_header(struct qemud_save_header *hdr) { + hdr->version = bswap_32(hdr->version); + hdr->xml_len = bswap_32(hdr->xml_len); + hdr->was_running = bswap_32(hdr->was_running); + hdr->compressed = bswap_32(hdr->compressed); +} + + /* return -errno on failure, or 0 on success */ static int qemuDomainSaveHeader(int fd, const char *path, char *xml, @@ -3097,6 +3107,11 @@ qemuDomainSaveImageOpen(struct qemud_dri } if (header.version > QEMUD_SAVE_VERSION) { + /* convert endianess and try again */ + bswap_header(&header); + } + + if (header.version > QEMUD_SAVE_VERSION) { qemuReportError(VIR_ERR_OPERATION_FAILED, _("image version is not supported (%d > %d)"), header.version, QEMUD_SAVE_VERSION); From veillard at redhat.com Sun Apr 10 04:58:56 2011 From: veillard at redhat.com (Daniel Veillard) Date: Sun, 10 Apr 2011 12:58:56 +0800 Subject: [libvirt] [PATCHv2 1/6] virNodeGetCPUTime: Expose new API In-Reply-To: <20110408203312.90723b75.usui@mxm.nes.nec.co.jp> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> <20110408203312.90723b75.usui@mxm.nes.nec.co.jp> Message-ID: <20110410045856.GI24838@redhat.com> On Fri, Apr 08, 2011 at 08:33:12PM +0900, Minoru Usui wrote: > virNodeGetCPUTime: Expose new API > > Signed-off-by: Minoru Usui > --- > include/libvirt/libvirt.h.in | 64 ++++++++++++++++++++++++++++++++++++++++++ > src/libvirt_public.syms | 5 +++ > 2 files changed, 69 insertions(+), 0 deletions(-) > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > index bd36015..154c138 100644 > --- a/include/libvirt/libvirt.h.in > +++ b/include/libvirt/libvirt.h.in > @@ -228,6 +228,57 @@ struct _virNodeInfo { > unsigned int threads;/* number of threads per core */ > }; > > +/** > + * virNodeCpuTime: > + * > + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing > + * the information for the cpu time of the node. > + */ > + > +/** > + * Cpu Time Statistics Tags: > + */ > +typedef enum { > + /* > + * The cumulative CPU time which spends by kernel, > + * when the node booting up.(in nanoseconds). > + */ > + VIR_NODE_CPU_TIME_KERNEL = 0, > + /* > + * The cumulative CPU time which spends by user processes, > + * when the node booting up.(in nanoseconds). > + */ > + VIR_NODE_CPU_TIME_USER = 1, > + /* > + * The cumulative idle CPU time, > + * when the node booting up.(in nanoseconds). > + */ > + VIR_NODE_CPU_TIME_IDLE = 2, > + /* > + * The cumulative I/O wait CPU time, > + * when the node booting up.(in nanoseconds). > + */ > + VIR_NODE_CPU_TIME_IOWAIT = 3, > + /* > + * The CPU utilization. > + * The usage value is in percent and 100% represents all CPUs on > + * the server. > + */ > + VIR_NODE_CPU_TIME_UTILIZATION = 4, > + > + /* > + * The number of statistics supported by this version of the interface. > + * To add new statistics, add them to the enum and increase this value. > + */ > + VIR_NODE_CPU_TIME_NR = 5, > +} virNodeCpuTimeTags; > + > +typedef struct _virNodeCpuTime virNodeCpuTime; > + > +struct _virNodeCpuTime { > + virNodeCpuTimeTags tag; > + unsigned long long val; > +}; NACK, the size of an enum is not defined by the C language and hence is compiler dependant. We cannot use it as a component of a structure in the API. > /** > * virDomainSchedParameterType: > @@ -460,6 +511,14 @@ int virDomainMigrateSetMaxSpeed(virDomainPtr domain, > typedef virNodeInfo *virNodeInfoPtr; > > /** > + * virNodeCpuTimePtr: > + * > + * a virNodeCpuTimePtr is a pointer to a virNodeCpuTime structure. > + */ > + > +typedef virNodeCpuTime *virNodeCpuTimePtr; > + > +/** > * virConnectFlags > * > * Flags when opening a connection to a hypervisor > @@ -593,6 +652,11 @@ int virNodeGetInfo (virConnectPtr conn, > virNodeInfoPtr info); > char * virConnectGetCapabilities (virConnectPtr conn); > > +int virNodeGetCpuTime (virConnectPtr conn, > + virNodeCpuTimePtr stats, > + unsigned int nr_stats, > + unsigned int flags); > + I don't understand how the API is suppoed to work. Suppose you want the cumulative CPU time, how do you ask for it ? Seems you can't ! You just ask for a big stucture hoping that on return you may find it within the results. That looks broken to me. Either you make a simple API giving back an unsigned long long and you use the virNodeCpuTimeTags as the flag value int virNodeGetCpuTime(virConnectPtr conn, unsigned long long *time, unsigned int flags); and the flags indicate the value you're interested into, but in that case you have to ask multiple times. Or you make the VIR_NODE_CPU_TIME_* values a bit field, and you pass an array int virNodeGetCpuTime(virConnectPtr conn, unsigned long long *stats, unsigned int nr_stats, unsigned int flags); where flags is the logical or of the values you are interested into, and the implementation put them in order based on the VIR_NODE_CPU_TIME_* values. But in that case you must fail if one of the statistics is not available. But an API where you "go fishing" and you don't know upfront on a successful return if you got the data you're interested into sounds broken to me Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Sun Apr 10 05:03:30 2011 From: veillard at redhat.com (Daniel Veillard) Date: Sun, 10 Apr 2011 13:03:30 +0800 Subject: [libvirt] [PATCH v2] xen: Remove PATH_MAX sized stack allocation from block stats code In-Reply-To: <20110409100517.GA26695@sbox> References: <20110409100517.GA26695@sbox> Message-ID: <20110410050330.GJ24838@redhat.com> On Sat, Apr 09, 2011 at 12:05:17PM +0200, Matthias Bolte wrote: > --- > src/xen/block_stats.c | 51 +++++++++++++++++++++++++------------------------ > 1 files changed, 26 insertions(+), 25 deletions(-) > > diff --git a/src/xen/block_stats.c b/src/xen/block_stats.c > index e7c80c9..1918257 100644 > --- a/src/xen/block_stats.c > +++ b/src/xen/block_stats.c > @@ -113,34 +113,35 @@ read_stat (const char *path) > } > > static int64_t > -read_bd_stat (int device, int domid, const char *str) > +read_bd_stat(int device, int domid, const char *str) > { > - char path[PATH_MAX]; > + static const char *paths[] = { > + "/sys/bus/xen-backend/devices/vbd-%d-%d/statistics/%s", > + "/sys/bus/xen-backend/devices/tap-%d-%d/statistics/%s", > + "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s", > + "/sys/devices/xen-backend/tap-%d-%d/statistics/%s" > + }; > + > + int i; > + char *path; > int64_t r; > > - snprintf (path, sizeof path, > - "/sys/bus/xen-backend/devices/vbd-%d-%d/statistics/%s", > - domid, device, str); > - r = read_stat (path); > - if (r >= 0) return r; > - > - snprintf (path, sizeof path, > - "/sys/bus/xen-backend/devices/tap-%d-%d/statistics/%s", > - domid, device, str); > - r = read_stat (path); > - if (r >= 0) return r; > - > - snprintf (path, sizeof path, > - "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s", > - domid, device, str); > - r = read_stat (path); > - if (r >= 0) return r; > - > - snprintf (path, sizeof path, > - "/sys/devices/xen-backend/tap-%d-%d/statistics/%s", > - domid, device, str); > - r = read_stat (path); > - return r; > + for (i = 0; i < ARRAY_CARDINALITY(paths); ++i) { > + if (virAsprintf(&path, paths[i], domid, device, str) < 0) { > + virReportOOMError(); > + return -1; > + } > + > + r = read_stat(path); > + > + VIR_FREE(path); > + > + if (r >= 0) { > + return r; > + } > + } > + > + return -1; > } > > /* In Xenstore, /local/domain/0/backend/vbd///state, ACK, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From matthias.bolte at googlemail.com Sun Apr 10 11:26:47 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 10 Apr 2011 13:26:47 +0200 Subject: [libvirt] [PATCH] esx: Cleanup VI generator code Message-ID: <20110410112647.GA13500@sbox> --- src/esx/esx_vi_generator.py | 177 +++++++++++++++++-------------------------- 1 files changed, 71 insertions(+), 106 deletions(-) diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index 3d068f3..622a34a 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -41,6 +41,11 @@ valid_occurrences = [OCCURRENCE__REQUIRED_ITEM, +def aligned(left, right): + while len(left) < 59: + left += " " + + return left + right @@ -64,9 +69,6 @@ class Parameter: def is_enum(self): - global predefined_enums - global enums_by_name - return self.type in predefined_enums or self.type in enums_by_name @@ -88,10 +90,7 @@ class Parameter: else: string += ", " - while len(string) < 59: - string += " " - - return string + self.get_occurrence_comment() + "\n" + return aligned(string, self.get_occurrence_comment() + "\n") def generate_return(self, offset = 0, end_of_line = ";"): @@ -102,10 +101,7 @@ class Parameter: string += " " * offset string += "%s%s)%s" % (self.get_type_string(True), self.name, end_of_line) - while len(string) < 59: - string += " " - - return string + self.get_occurrence_comment() + "\n" + return aligned(string, self.get_occurrence_comment() + "\n") def generate_require_code(self): @@ -274,9 +270,6 @@ class Property: def is_enum(self): - global predefined_enums - global enums_by_name - return self.type in predefined_enums or self.type in enums_by_name @@ -286,10 +279,7 @@ class Property: else: string = " %s%s; " % (self.get_type_string(), self.name) - while len(string) < 59: - string += " " - - return string + self.get_occurrence_comment() + "\n" + return aligned(string, self.get_occurrence_comment() + "\n") def generate_free_code(self): @@ -380,7 +370,37 @@ class Property: -class Object: +class Base: + def __init__(self, kind, name): + self.kind = kind + self.name = name + + + def generate_typedef(self): + return "typedef %s _esxVI_%s esxVI_%s;\n" % (self.kind, self.name, self.name) + + + def generate_typeenum(self): + return " esxVI_Type_%s,\n" % self.name + + + def generate_typetostring(self): + string = " case esxVI_Type_%s:\n" % self.name + string += " return \"%s\";\n\n" % self.name + + return string + + + def generate_typefromstring(self): + string = " else if (STREQ(type, \"%s\")) {\n" % self.name + string += " return esxVI_Type_%s;\n" % self.name + string += " }\n" + + return string + + + +class Object(Base): FEATURE__DYNAMIC_CAST = (1 << 1) FEATURE__LIST = (1 << 2) FEATURE__DEEP_COPY = (1 << 3) @@ -390,34 +410,24 @@ class Object: def __init__(self, name, extends, properties, features = 0, extended_by = None): - self.name = name + Base.__init__(self, "struct", name) self.extends = extends self.features = features | Object.FEATURE__SERIALIZE | Object.FEATURE__DESERIALIZE self.properties = properties self.extended_by = extended_by if self.extended_by is not None: - self.extended_by.sort(); + self.extended_by.sort() - def generate_struct_members(self, add_banner = False, struct_gap = False): - global objects_by_name + def generate_struct_members(self, add_banner=False, struct_gap=False): members = "" - if self.extends is None: - struct_gap = True - string = " esxVI_Type _type; " - - while len(string) < 59: - string += " " - - members += string + "/* required */\n" - - if struct_gap and self.extends is None: + if struct_gap: members += "\n" if self.extends is not None: - members += objects_by_name[self.extends].generate_struct_members(add_banner = True, struct_gap = False) + "\n" + members += objects_by_name[self.extends].generate_struct_members(add_banner=True, struct_gap=False) + "\n" if self.extends is not None or add_banner: members += " /* %s */\n" % self.name @@ -431,12 +441,11 @@ class Object: return members - def generate_free_code(self, add_banner = False): - global objects_by_name + def generate_free_code(self, add_banner=False): source = "" if self.extends is not None: - source += objects_by_name[self.extends].generate_free_code(add_banner = True) + "\n" + source += objects_by_name[self.extends].generate_free_code(add_banner=True) + "\n" if self.extends is not None or add_banner: source += " /* %s */\n" % self.name @@ -457,12 +466,11 @@ class Object: return source - def generate_validate_code(self, add_banner = False): - global objects_by_name + def generate_validate_code(self, add_banner=False): source = "" if self.extends is not None: - source += objects_by_name[self.extends].generate_validate_code(add_banner = True) + "\n" + source += objects_by_name[self.extends].generate_validate_code(add_banner=True) + "\n" if self.extends is not None or add_banner: source += " /* %s */\n" % self.name @@ -484,7 +492,6 @@ class Object: def generate_dynamic_cast_code(self, is_first = True): - global objects_by_name source = "" if self.extended_by is not None: @@ -503,7 +510,6 @@ class Object: def generate_deep_copy_code(self, add_banner = False): - global objects_by_name source = "" if self.extends is not None: @@ -529,7 +535,6 @@ class Object: def generate_serialize_code(self, add_banner = False): - global objects_by_name source = "" if self.extends is not None: @@ -548,11 +553,10 @@ class Object: def generate_deserialize_code(self, add_banner = False): - global objects_by_name source = "" if self.extends is not None: - source += objects_by_name[self.extends].generate_deserialize_code(add_banner = True) + "\n" + source += objects_by_name[self.extends].generate_deserialize_code(add_banner=True) + "\n" if self.extends is not None or add_banner: source += " /* %s */\n" % self.name @@ -566,29 +570,6 @@ class Object: return source - def generate_typedef(self): - return "typedef struct _esxVI_%s esxVI_%s;\n" % (self.name, self.name) - - - def generate_typeenum(self): - return " esxVI_Type_%s,\n" % self.name - - - def generate_typetostring(self): - string = " case esxVI_Type_%s:\n" % self.name - string += " return \"%s\";\n\n" % self.name - - return string - - - def generate_typefromstring(self): - string = " else if (STREQ(type, \"%s\")) {\n" % self.name - string += " return esxVI_Type_%s;\n" % self.name - string += " }\n" - - return string - - def generate_header(self): header = "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" header += " * VI Type: %s\n" % self.name @@ -612,17 +593,12 @@ class Object: header += "struct _esxVI_%s {\n" % self.name if self.features & Object.FEATURE__LIST: - string = " esxVI_%s *_next; " % self.name + header += aligned(" esxVI_%s *_next; " % self.name, "/* optional */\n") else: - string = " esxVI_%s *_unused; " % self.name - - while len(string) < 59: - string += " " - - header += string + "/* optional */\n" - - header += self.generate_struct_members(struct_gap = True) + header += aligned(" esxVI_%s *_unused; " % self.name, "/* optional */\n") + header += aligned(" esxVI_Type _type; ", "/* required */\n") + header += self.generate_struct_members(struct_gap=True) header += "};\n\n" # functions @@ -888,39 +864,28 @@ class Object: -class Enum: - FEATURE__ANY_TYPE = (1 << 1) - FEATURE__SERIALIZE = (1 << 2) - FEATURE__DESERIALIZE = (1 << 3) - def __init__(self, name, values, features = 0): - self.name = name - self.values = values - self.features = features | Enum.FEATURE__SERIALIZE | Enum.FEATURE__DESERIALIZE - def generate_typedef(self): - return "typedef enum _esxVI_%s esxVI_%s;\n" % (self.name, self.name) - def generate_typeenum(self): - return " esxVI_Type_%s,\n" % self.name - def generate_typetostring(self): - string = " case esxVI_Type_%s:\n" % self.name - string += " return \"%s\";\n\n" % self.name - return string - def generate_typefromstring(self): - string = " else if (STREQ(type, \"%s\")) {\n" % self.name - string += " return esxVI_Type_%s;\n" % self.name - string += " }\n" - return string +class Enum(Base): + FEATURE__ANY_TYPE = (1 << 1) + FEATURE__SERIALIZE = (1 << 2) + FEATURE__DESERIALIZE = (1 << 3) + + + def __init__(self, name, values, features=0): + Base.__init__(self, "enum", name) + self.values = values + self.features = features | Enum.FEATURE__SERIALIZE | Enum.FEATURE__DESERIALIZE def generate_header(self): @@ -1027,8 +992,8 @@ def parse_object(block): if items[2] not in valid_occurrences: report_error("line %d: invalid occurrence" % line[0]) - properties.append(Property(type = items[0], name = items[1], - occurrence = items[2])) + properties.append(Property(type=items[0], name=items[1], + occurrence=items[2])) return Object(name = name, extends = extends, properties = properties) @@ -1051,7 +1016,7 @@ def parse_enum(block): # expected format: values.append(line[1]) - return Enum(name = name, values = values) + return Enum(name=name, values=values) @@ -1071,8 +1036,8 @@ def parse_method(block): if header_items[2] != "returns": report_error("line %d: invalid block header" % (number)) else: - returns = Parameter(type = header_items[3], name = "output", - occurrence = header_items[4]) + returns = Parameter(type=header_items[3], name="output", + occurrence=header_items[4]) parameters = [] @@ -1086,10 +1051,10 @@ def parse_method(block): if items[2] not in valid_occurrences: report_error("line %d: invalid occurrence" % line[0]) - parameters.append(Parameter(type = items[0], name = items[1], - occurrence = items[2])) + parameters.append(Parameter(type=items[0], name=items[1], + occurrence=items[2])) - return Method(name = name, parameters = parameters, returns = returns) + return Method(name=name, parameters=parameters, returns=returns) -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 10 11:27:19 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 10 Apr 2011 13:27:19 +0200 Subject: [libvirt] [PATCH] esx: Cleanup and refactor CastFromAnyType macros Message-ID: <20110410112719.GA13533@sbox> Add CastFromAnyType functions for the String type. --- src/esx/esx_vi_generator.py | 5 +-- src/esx/esx_vi_types.c | 64 +++++++++++++++++++++++++++++++----------- src/esx/esx_vi_types.h | 2 + 3 files changed, 51 insertions(+), 20 deletions(-) diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index 622a34a..0fd84dd 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -773,12 +773,11 @@ class Object(Base): # cast from any type if self.features & Object.FEATURE__ANY_TYPE: source += "/* esxVI_%s_CastFromAnyType */\n" % self.name - source += "ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(%s,\n" % self.name if self.extended_by is None: - source += "{\n" - source += "})\n\n" + source += "ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(%s)\n\n" % self.name else: + source += "ESX_VI__TEMPLATE__DYNAMIC_CAST_FROM_ANY_TYPE(%s,\n" % self.name source += "{\n" for extended_by in self.extended_by: diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c index f3df2b5..f3cdf2a 100644 --- a/src/esx/esx_vi_types.c +++ b/src/esx/esx_vi_types.c @@ -183,32 +183,53 @@ -#define ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(_type, _dispatch) \ +#define ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE_EXTRA(_type, _dest_type, _extra, \ + _dest_extra) \ int \ - esxVI_##_type##_CastFromAnyType(esxVI_AnyType *anyType, \ - esxVI_##_type **ptrptr) \ + esxVI_##_type##_Cast##_dest_extra##FromAnyType(esxVI_AnyType *anyType, \ + _dest_type **ptrptr) \ { \ + _dest_type *item; \ + \ if (anyType == NULL || ptrptr == NULL || *ptrptr != NULL) { \ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", \ _("Invalid argument")); \ return -1; \ } \ \ - switch (anyType->type) { \ - _dispatch \ + item = *ptrptr; \ \ - case esxVI_Type_##_type: \ - break; \ + _extra \ \ - default: \ + return esxVI_##_type##_Deserialize##_dest_extra(anyType->node, \ + ptrptr); \ + } + + + +#define ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(_type) \ + ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE_EXTRA(_type, esxVI_##_type, \ + { \ + if (anyType->type != esxVI_Type_##_type) { \ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ _("Call to %s for unexpected type '%s'"), \ __FUNCTION__, anyType->other); \ return -1; \ } \ - \ - return esxVI_##_type##_Deserialize(anyType->node, ptrptr); \ - } + }, /* nothing */) + + + +#define ESX_VI__TEMPLATE__CAST_VALUE_FROM_ANY_TYPE(_type, _value_type) \ + ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE_EXTRA(_type, _value_type, \ + { \ + if (anyType->type != esxVI_Type_##_type) { \ + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ + _("Call to %s for unexpected type '%s'"), \ + __FUNCTION__, anyType->other); \ + return -1; \ + } \ + }, Value) @@ -591,6 +612,13 @@ +#define ESX_VI__TEMPLATE__DYNAMIC_CAST_FROM_ANY_TYPE(__type, _dispatch) \ + ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE_EXTRA(__type, esxVI_##__type, \ + ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, -1), \ + /* nothing */) + + + #define ESX_VI__TEMPLATE__DYNAMIC_SERIALIZE(__type, _dispatch, _serialize) \ ESX_VI__TEMPLATE__SERIALIZE_EXTRA(__type, \ ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, -1), \ @@ -1111,6 +1139,12 @@ esxVI_String_DeepCopyValue(char **dest, const char *src) return 0; } +/* esxVI_String_CastFromAnyType */ +ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(String) + +/* esxVI_String_CastValueFromAnyType */ +ESX_VI__TEMPLATE__CAST_VALUE_FROM_ANY_TYPE(String, char) + int esxVI_String_Serialize(esxVI_String *string, const char *element, virBufferPtr output) @@ -1240,9 +1274,7 @@ ESX_VI__TEMPLATE__VALIDATE(Long, ESX_VI__TEMPLATE__LIST__APPEND(Long) /* esxVI_Long_CastFromAnyType */ -ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(Long, -{ -}) +ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(Long) /* esxVI_Long_Serialize */ ESX_VI__TEMPLATE__SERIALIZE(Long, @@ -1522,9 +1554,7 @@ ESX_VI__TEMPLATE__DEEP_COPY(ManagedObjectReference, ESX_VI__TEMPLATE__LIST__APPEND(ManagedObjectReference) /* esxVI_ManagedObjectReference_CastFromAnyType */ -ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(ManagedObjectReference, -{ -}) +ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(ManagedObjectReference) /* esxVI_ManagedObjectReference_CastListFromAnyType */ ESX_VI__TEMPLATE__LIST__CAST_FROM_ANY_TYPE(ManagedObjectReference) diff --git a/src/esx/esx_vi_types.h b/src/esx/esx_vi_types.h index 1ab39da..e53ccda 100644 --- a/src/esx/esx_vi_types.h +++ b/src/esx/esx_vi_types.h @@ -178,6 +178,8 @@ int esxVI_String_AppendValueListToList(esxVI_String **stringList, int esxVI_String_DeepCopy(esxVI_String **dest, esxVI_String *src); int esxVI_String_DeepCopyList(esxVI_String **destList, esxVI_String *srcList); int esxVI_String_DeepCopyValue(char **dest, const char *src); +int esxVI_String_CastFromAnyType(esxVI_AnyType *anyType, esxVI_String **string); +int esxVI_String_CastValueFromAnyType(esxVI_AnyType *anyType, char **string); int esxVI_String_Serialize(esxVI_String *string, const char *element, virBufferPtr output); int esxVI_String_SerializeList(esxVI_String *stringList, const char *element, -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 10 11:27:56 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 10 Apr 2011 13:27:56 +0200 Subject: [libvirt] [PATCH] esx: Extend VI generator to cover managed object types Message-ID: <20110410112756.GA13563@sbox> Generate lookup functions for managed object types. --- src/esx/esx_vi.c | 414 +++++++++++++++++++++++----------------- src/esx/esx_vi.h | 2 + src/esx/esx_vi_generator.input | 28 +++- src/esx/esx_vi_generator.py | 411 ++++++++++++++++++++++++++++++++++++++-- src/esx/esx_vi_types.c | 349 ++++++---------------------------- src/esx/esx_vi_types.h | 102 ++--------- 6 files changed, 728 insertions(+), 578 deletions(-) diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index 7446ec5..fbab347 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -3,7 +3,7 @@ * esx_vi.c: client for the VMware VI API 2.5 to manage ESX hosts * * Copyright (C) 2010 Red Hat, Inc. - * Copyright (C) 2009-2010 Matthias Bolte + * Copyright (C) 2009-2011 Matthias Bolte * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -481,107 +481,26 @@ int esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx, esxUtil_ParsedUri *parsedUri) { - int result = -1; - esxVI_String *propertyNameList = NULL; - char *name = NULL; - esxVI_ObjectContent *datacenterList = NULL; - esxVI_ObjectContent *datacenter = NULL; - esxVI_ObjectContent *computeResourceList = NULL; - esxVI_ObjectContent *computeResource = NULL; char *hostSystemName = NULL; - esxVI_ObjectContent *hostSystemList = NULL; - esxVI_ObjectContent *hostSystem = NULL; - /* Lookup Datacenter */ - if (esxVI_String_AppendValueListToList(&propertyNameList, - "name\0" - "vmFolder\0" - "hostFolder\0") < 0 || - esxVI_LookupObjectContentByType(ctx, ctx->service->rootFolder, - "Datacenter", propertyNameList, - &datacenterList, - esxVI_Occurrence_RequiredList) < 0) { - goto cleanup; - } - - if (parsedUri->path_datacenter != NULL) { - for (datacenter = datacenterList; datacenter != NULL; - datacenter = datacenter->_next) { - name = NULL; - - if (esxVI_GetStringValue(datacenter, "name", &name, - esxVI_Occurrence_RequiredItem) < 0) { - goto cleanup; - } - - if (STREQ(name, parsedUri->path_datacenter)) { - break; - } - } - - if (datacenter == NULL) { - ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Could not find datacenter '%s'"), - parsedUri->path_datacenter); - goto cleanup; - } - } else { - datacenter = datacenterList; - } - - if (esxVI_Datacenter_CastFromObjectContent(datacenter, - &ctx->datacenter) < 0) { - goto cleanup; + if (esxVI_LookupDatacenter(ctx, parsedUri->path_datacenter, + ctx->service->rootFolder, NULL, &ctx->datacenter, + esxVI_Occurrence_RequiredItem) < 0) { + return -1; } /* Lookup (Cluster)ComputeResource */ - esxVI_String_Free(&propertyNameList); - - if (esxVI_String_AppendValueListToList(&propertyNameList, - "name\0" - "host\0" - "resourcePool\0") < 0 || - esxVI_LookupObjectContentByType(ctx, ctx->datacenter->hostFolder, - "ComputeResource", propertyNameList, - &computeResourceList, - esxVI_Occurrence_RequiredList) < 0) { - goto cleanup; - } - - if (parsedUri->path_computeResource != NULL) { - for (computeResource = computeResourceList; computeResource != NULL; - computeResource = computeResource->_next) { - name = NULL; - - if (esxVI_GetStringValue(computeResource, "name", &name, - esxVI_Occurrence_RequiredItem) < 0) { - goto cleanup; - } - - if (STREQ(name, parsedUri->path_computeResource)) { - break; - } - } - - if (computeResource == NULL) { - ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Could not find compute resource '%s'"), - parsedUri->path_computeResource); - goto cleanup; - } - } else { - computeResource = computeResourceList; - } - - if (esxVI_ComputeResource_CastFromObjectContent(computeResource, - &ctx->computeResource) < 0) { - goto cleanup; + if (esxVI_LookupComputeResource(ctx, parsedUri->path_computeResource, + ctx->datacenter->hostFolder, NULL, + &ctx->computeResource, + esxVI_Occurrence_RequiredItem) < 0) { + return -1; } if (ctx->computeResource->resourcePool == NULL) { ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not retrieve resource pool")); - goto cleanup; + return -1; } /* Lookup HostSystem */ @@ -590,19 +509,7 @@ esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx, "ClusterComputeResource")) { ESX_VI_ERROR(VIR_ERR_INVALID_ARG, "%s", _("Path has to specify the host system")); - goto cleanup; - } - - esxVI_String_Free(&propertyNameList); - - if (esxVI_String_AppendValueListToList(&propertyNameList, - "name\0" - "configManager\0") < 0 || - esxVI_LookupObjectContentByType(ctx, ctx->computeResource->_reference, - "HostSystem", propertyNameList, - &hostSystemList, - esxVI_Occurrence_RequiredList) < 0) { - goto cleanup; + return -1; } if (parsedUri->path_hostSystem != NULL || @@ -613,44 +520,16 @@ esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx, } else { hostSystemName = parsedUri->path_computeResource; } - - for (hostSystem = hostSystemList; hostSystem != NULL; - hostSystem = hostSystem->_next) { - name = NULL; - - if (esxVI_GetStringValue(hostSystem, "name", &name, - esxVI_Occurrence_RequiredItem) < 0) { - goto cleanup; - } - - if (STREQ(name, hostSystemName)) { - break; - } - } - - if (hostSystem == NULL) { - ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Could not find host system '%s'"), hostSystemName); - goto cleanup; - } - } else { - hostSystem = hostSystemList; } - if (esxVI_HostSystem_CastFromObjectContent(hostSystem, - &ctx->hostSystem) < 0) { - goto cleanup; + if (esxVI_LookupHostSystem(ctx, hostSystemName, + ctx->computeResource->_reference, NULL, + &ctx->hostSystem, + esxVI_Occurrence_RequiredItem) < 0) { + return -1; } - result = 0; - - cleanup: - esxVI_String_Free(&propertyNameList); - esxVI_ObjectContent_Free(&datacenterList); - esxVI_ObjectContent_Free(&computeResourceList); - esxVI_ObjectContent_Free(&hostSystemList); - - return result; + return 0; } int @@ -658,67 +537,41 @@ esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx, const char *hostSystemIpAddress) { int result = -1; - esxVI_String *propertyNameList = NULL; esxVI_ManagedObjectReference *managedObjectReference = NULL; - esxVI_ObjectContent *hostSystem = NULL; - esxVI_ObjectContent *computeResource = NULL; - esxVI_ObjectContent *datacenter = NULL; /* Lookup HostSystem */ - if (esxVI_String_AppendValueListToList(&propertyNameList, - "name\0" - "configManager\0") < 0 || - esxVI_FindByIp(ctx, NULL, hostSystemIpAddress, esxVI_Boolean_False, + if (esxVI_FindByIp(ctx, NULL, hostSystemIpAddress, esxVI_Boolean_False, &managedObjectReference) < 0 || - esxVI_LookupObjectContentByType(ctx, managedObjectReference, - "HostSystem", propertyNameList, - &hostSystem, - esxVI_Occurrence_RequiredItem) < 0 || - esxVI_HostSystem_CastFromObjectContent(hostSystem, - &ctx->hostSystem) < 0) { + esxVI_LookupHostSystem(ctx, NULL, managedObjectReference, NULL, + &ctx->hostSystem, + esxVI_Occurrence_RequiredItem) < 0) { goto cleanup; } /* Lookup (Cluster)ComputeResource */ - esxVI_String_Free(&propertyNameList); + if (esxVI_LookupComputeResource(ctx, NULL, ctx->hostSystem->_reference, + NULL, &ctx->computeResource, + esxVI_Occurrence_RequiredItem) < 0) { + goto cleanup; + } - if (esxVI_String_AppendValueListToList(&propertyNameList, - "name\0" - "host\0" - "resourcePool\0") < 0 || - esxVI_LookupObjectContentByType(ctx, hostSystem->obj, - "ComputeResource", propertyNameList, - &computeResource, - esxVI_Occurrence_RequiredItem) < 0 || - esxVI_ComputeResource_CastFromObjectContent(computeResource, - &ctx->computeResource) < 0) { + if (ctx->computeResource->resourcePool == NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not retrieve resource pool")); goto cleanup; } /* Lookup Datacenter */ - esxVI_String_Free(&propertyNameList); - - if (esxVI_String_AppendValueListToList(&propertyNameList, - "name\0" - "vmFolder\0" - "hostFolder\0") < 0 || - esxVI_LookupObjectContentByType(ctx, computeResource->obj, - "Datacenter", propertyNameList, - &datacenter, - esxVI_Occurrence_RequiredItem) < 0 || - esxVI_Datacenter_CastFromObjectContent(datacenter, - &ctx->datacenter) < 0) { + if (esxVI_LookupDatacenter(ctx, NULL, ctx->computeResource->_reference, + NULL, &ctx->datacenter, + esxVI_Occurrence_RequiredItem) < 0) { goto cleanup; } result = 0; cleanup: - esxVI_String_Free(&propertyNameList); esxVI_ManagedObjectReference_Free(&managedObjectReference); - esxVI_ObjectContent_Free(&hostSystem); - esxVI_ObjectContent_Free(&computeResource); - esxVI_ObjectContent_Free(&datacenter); return result; } @@ -3872,3 +3725,204 @@ esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersio return -1; } } + + + + +#define ESX_VI__TEMPLATE__PROPERTY__CAST_FROM_ANY_TYPE_IGNORE(_name) \ + if (STREQ(dynamicProperty->name, #_name)) { \ + continue; \ + } + + + +#define ESX_VI__TEMPLATE__PROPERTY__CAST_FROM_ANY_TYPE(_type, _name) \ + if (STREQ(dynamicProperty->name, #_name)) { \ + if (esxVI_##_type##_CastFromAnyType(dynamicProperty->val, \ + &(*ptrptr)->_name) < 0) { \ + goto cleanup; \ + } \ + \ + continue; \ + } + + + +#define ESX_VI__TEMPLATE__PROPERTY__CAST_LIST_FROM_ANY_TYPE(_type, _name) \ + if (STREQ(dynamicProperty->name, #_name)) { \ + if (esxVI_##_type##_CastListFromAnyType(dynamicProperty->val, \ + &(*ptrptr)->_name) < 0) { \ + goto cleanup; \ + } \ + \ + continue; \ + } + + + +#define ESX_VI__TEMPLATE__PROPERTY__CAST_VALUE_FROM_ANY_TYPE(_type, _name) \ + if (STREQ(dynamicProperty->name, #_name)) { \ + if (esxVI_##_type##_CastValueFromAnyType(dynamicProperty->val, \ + &(*ptrptr)->_name) < 0) { \ + goto cleanup; \ + } \ + \ + continue; \ + } + + + +#define ESX_VI__TEMPLATE__LOOKUP(_type, _complete_properties, \ + _cast_from_anytype) \ + int \ + esxVI_Lookup##_type(esxVI_Context *ctx, const char* name /* optional */, \ + esxVI_ManagedObjectReference *root, \ + esxVI_String *selectedPropertyNameList /* optional */,\ + esxVI_##_type **ptrptr, esxVI_Occurrence occurrence) \ + { \ + int result = -1; \ + const char *completePropertyNameValueList = _complete_properties; \ + esxVI_String *propertyNameList = NULL; \ + esxVI_ObjectContent *objectContent = NULL; \ + esxVI_ObjectContent *objectContentList = NULL; \ + esxVI_DynamicProperty *dynamicProperty = NULL; \ + \ + if (ptrptr == NULL || *ptrptr != NULL) { \ + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", \ + _("Invalid argument")); \ + return -1; \ + } \ + \ + propertyNameList = selectedPropertyNameList; \ + \ + if (propertyNameList == NULL && \ + esxVI_String_AppendValueListToList \ + (&propertyNameList, completePropertyNameValueList) < 0) { \ + goto cleanup; \ + } \ + \ + if (esxVI_LookupManagedObjectHelper(ctx, name, root, #_type, \ + propertyNameList, &objectContent, \ + &objectContentList, \ + occurrence) < 0) { \ + goto cleanup; \ + } \ + \ + if (esxVI_##_type##_Alloc(ptrptr) < 0) { \ + goto cleanup; \ + } \ + \ + if (esxVI_ManagedObjectReference_DeepCopy(&(*ptrptr)->_reference, \ + objectContent->obj) < 0) { \ + goto cleanup; \ + } \ + \ + for (dynamicProperty = objectContent->propSet; \ + dynamicProperty != NULL; \ + dynamicProperty = dynamicProperty->_next) { \ + _cast_from_anytype \ + \ + VIR_WARN("Unexpected '%s' property", dynamicProperty->name); \ + } \ + \ + if (esxVI_##_type##_Validate(*ptrptr, selectedPropertyNameList) < 0) {\ + goto cleanup; \ + } \ + \ + result = 0; \ + \ + cleanup: \ + if (result < 0) { \ + esxVI_##_type##_Free(ptrptr); \ + } \ + \ + if (propertyNameList != selectedPropertyNameList) { \ + esxVI_String_Free(&propertyNameList); \ + } \ + \ + esxVI_ObjectContent_Free(&objectContentList); \ + \ + return result; \ + } + + + +static int +esxVI_LookupManagedObjectHelper(esxVI_Context *ctx, + const char *name /* optional */, + esxVI_ManagedObjectReference *root, + const char *type, + esxVI_String *propertyNameList, + esxVI_ObjectContent **objectContent, + esxVI_ObjectContent **objectContentList, + esxVI_Occurrence occurrence) +{ + int result = -1; + esxVI_ObjectContent *candidate = NULL; + char *name_candidate; + + if (objectContent == NULL || *objectContent != NULL || + objectContentList == NULL || *objectContentList != NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + if (!esxVI_String_ListContainsValue(propertyNameList, "name")) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Missing 'name' property in %s lookup"), type); + goto cleanup; + } + + if (esxVI_LookupObjectContentByType(ctx, root, type, propertyNameList, + objectContentList, + esxVI_Occurrence_OptionalList) < 0) { + goto cleanup; + } + + /* Search for a matching item */ + if (name != NULL) { + for (candidate = *objectContentList; candidate != NULL; + candidate = candidate->_next) { + name_candidate = NULL; + + if (esxVI_GetStringValue(candidate, "name", &name_candidate, + esxVI_Occurrence_RequiredItem) < 0) { + goto cleanup; + } + + if (STREQ(name_candidate, name)) { + /* Found item with matching name */ + break; + } + } + } else { + candidate = *objectContentList; + } + + if (candidate == NULL) { + if (occurrence != esxVI_Occurrence_OptionalItem) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Could not find %s with name '%s'"), type, name); + goto cleanup; + } + + result = 0; + + goto cleanup; + } + + result = 0; + + cleanup: + if (result < 0) { + esxVI_ObjectContent_Free(objectContentList); + } else { + *objectContent = candidate; + } + + return result; +} + + + +#include "esx_vi.generated.c" diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index e150dbf..d046bf9 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -444,4 +444,6 @@ int esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedHostCpuIdInfo, int esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersion); +# include "esx_vi.generated.h" + #endif /* __ESX_VI_H__ */ diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input index 44d1d9b..98b5206 100644 --- a/src/esx/esx_vi_generator.input +++ b/src/esx/esx_vi_generator.input @@ -15,7 +15,7 @@ # # Object definition: # -# object [extends ] +# [managed] object [extends ] # # ... # end @@ -739,6 +739,32 @@ end # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Managed Objects +# + +managed object ComputeResource extends ManagedEntity + ManagedObjectReference host ol + ManagedObjectReference resourcePool o +end + + +managed object Datacenter extends ManagedEntity + ManagedObjectReference hostFolder r + ManagedObjectReference vmFolder r +end + + +managed object HostSystem extends ManagedEntity + HostConfigManager configManager r +end + + +managed object ManagedEntity + String name r +end + + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Methods # diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index 0fd84dd..ab127a3 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -3,7 +3,7 @@ # # esx_vi_generator.py: generates most of the SOAP type mapping code # -# Copyright (C) 2010 Matthias Bolte +# Copyright (C) 2010-2011 Matthias Bolte # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -297,10 +297,15 @@ class Property: return " esxVI_%s_Free(&item->%s);\n" % (self.type, self.name) - def generate_validate_code(self): + def generate_validate_code(self, managed=False): + if managed: + macro = "ESX_VI__TEMPLATE__PROPERTY__MANAGED_REQUIRE" + else: + macro = "ESX_VI__TEMPLATE__PROPERTY__REQUIRE" + if self.occurrence in [OCCURRENCE__REQUIRED_ITEM, OCCURRENCE__REQUIRED_LIST]: - return " ESX_VI__TEMPLATE__PROPERTY__REQUIRE(%s)\n" % self.name + return " %s(%s)\n" % (macro, self.name) elif self.occurrence == OCCURRENCE__IGNORED: return " /* FIXME: %s is currently ignored */\n" % self.name else: @@ -345,6 +350,18 @@ class Property: return " ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(%s, %s)\n" % (self.type, self.name) + def generate_lookup_code(self): + if self.occurrence == OCCURRENCE__IGNORED: + return " ESX_VI__TEMPLATE__PROPERTY__CAST_FROM_ANY_TYPE_IGNORE(%s) /* FIXME */\n" % self.name + elif self.occurrence in [OCCURRENCE__REQUIRED_LIST, + OCCURRENCE__OPTIONAL_LIST]: + return " ESX_VI__TEMPLATE__PROPERTY__CAST_LIST_FROM_ANY_TYPE(%s, %s)\n" % (self.type, self.name) + elif self.type == "String": + return " ESX_VI__TEMPLATE__PROPERTY__CAST_VALUE_FROM_ANY_TYPE(String, %s)\n" % self.name + else: + return " ESX_VI__TEMPLATE__PROPERTY__CAST_FROM_ANY_TYPE(%s, %s)\n" % (self.type, self.name) + + def get_type_string(self): if self.type == "String" and \ self.occurrence not in [OCCURRENCE__REQUIRED_LIST, @@ -572,20 +589,20 @@ class Object(Base): def generate_header(self): header = "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" - header += " * VI Type: %s\n" % self.name + header += " * VI Object: %s\n" % self.name if self.extends is not None: - header += " * extends %s\n" % self.extends + header += " * extends %s\n" % self.extends first = True if self.extended_by is not None: for extended_by in self.extended_by: if first: - header += " * extended by %s\n" % extended_by + header += " * extended by %s\n" % extended_by first = False else: - header += " * %s\n" % extended_by + header += " * %s\n" % extended_by header += " */\n\n" @@ -646,20 +663,20 @@ class Object(Base): def generate_source(self): source = "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" - source += " * VI Type: %s\n" % self.name + source += " * VI Object: %s\n" % self.name if self.extends is not None: - source += " * extends %s\n" % self.extends + source += " * extends %s\n" % self.extends first = True if self.extended_by is not None: for extended_by in self.extended_by: if first: - source += " * extended by %s\n" % extended_by + source += " * extended by %s\n" % extended_by first = False else: - source += " * %s\n" % extended_by + source += " * %s\n" % extended_by source += " */\n\n" @@ -863,15 +880,303 @@ class Object(Base): +class ManagedObject(Base): + FEATURE__LIST = (1 << 2) + + + def __init__(self, name, extends, properties, features=0, extended_by=None): + Base.__init__(self, "struct", name) + self.extends = extends + self.features = features + self.properties = properties + self.extended_by = extended_by + + if self.extended_by is not None: + self.extended_by.sort() + + + def generate_struct_members(self, add_banner=False, struct_gap=False): + members = "" + + if struct_gap: + members += "\n" + + if self.extends is not None: + members += managed_objects_by_name[self.extends].generate_struct_members(add_banner=True) + "\n" + + if self.extends is not None or add_banner: + members += " /* %s */\n" % self.name + + for property in self.properties: + members += property.generate_struct_member() + + if len(self.properties) < 1: + members += " /* no properties */\n" + + return members + + + def generate_free_code(self, add_banner=False): + source = "" + if self.extends is not None: + source += managed_objects_by_name[self.extends].generate_free_code(add_banner=True) + "\n" + if self.extends is not None or add_banner: + source += " /* %s */\n" % self.name + if len(self.properties) < 1: + source += " /* no properties */\n" + else: + string = "" + for property in self.properties: + string += property.generate_free_code() + if len(string) < 1: + source += " /* no properties to be freed */\n" + else: + source += string + return source + def generate_validate_code(self, add_banner=False): + source = "" + + if self.extends is not None: + source += managed_objects_by_name[self.extends].generate_validate_code(add_banner=True) + "\n" + + if self.extends is not None or add_banner: + source += " /* %s */\n" % self.name + + if len(self.properties) < 1: + source += " /* no properties */\n" + else: + string = "" + for property in self.properties: + string += property.generate_validate_code(managed=True) + + if len(string) < 1: + source += " /* no required properties */\n" + else: + source += string + + return source + + + def generate_lookup_code1(self, add_banner=False): + source = "" + + if self.extends is not None: + source += managed_objects_by_name[self.extends].generate_lookup_code1(add_banner=True) + "\n" + + if self.extends is not None or add_banner: + source += " /* %s */\n" % self.name + + if len(self.properties) < 1: + source += " /* no properties */\n" + else: + string = "" + + for property in self.properties: + string += " \"%s\\0\"\n" % property.name + + if len(string) < 1: + source += " /* no properties */\n" + else: + source += string + + return source + + + def generate_lookup_code2(self, add_banner=False): + source = "" + + if self.extends is not None: + source += managed_objects_by_name[self.extends].generate_lookup_code2(add_banner=True) + "\n" + + if self.extends is not None or add_banner: + source += " /* %s */\n" % self.name + + if len(self.properties) < 1: + source += " /* no properties */\n" + else: + string = "" + + for property in self.properties: + string += property.generate_lookup_code() + + if len(string) < 1: + source += " /* no properties */\n" + else: + source += string + + return source + + + def generate_comment(self): + comment = "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" + comment += " * VI Managed Object: %s\n" % self.name + + if self.extends is not None: + comment += " * extends %s\n" % self.extends + + first = True + + if self.extended_by is not None: + for extended_by in self.extended_by: + if first: + comment += " * extended by %s\n" % extended_by + first = False + else: + comment += " * %s\n" % extended_by + + comment += " */\n\n" + + return comment + + + def generate_header(self): + header = self.generate_comment() + + # struct + header += "struct _esxVI_%s {\n" % self.name + + if self.features & Object.FEATURE__LIST: + header += aligned(" esxVI_%s *_next; " % self.name, "/* optional */\n") + else: + header += aligned(" esxVI_%s *_unused; " % self.name, "/* optional */\n") + + header += aligned(" esxVI_Type _type; ", "/* required */\n") + header += aligned(" esxVI_ManagedObjectReference *_reference; ", "/* required */\n") + header += "\n" + header += self.generate_struct_members() + + header += "};\n\n" + + # functions + header += "int esxVI_%s_Alloc(esxVI_%s **item);\n" % (self.name, self.name) + header += "void esxVI_%s_Free(esxVI_%s **item);\n" % (self.name, self.name) + header += "int esxVI_%s_Validate(esxVI_%s *item, esxVI_String *selectedPropertyNameList);\n" % (self.name, self.name) + + if self.features & Object.FEATURE__LIST: + header += "int esxVI_%s_AppendToList(esxVI_%s **list, esxVI_%s *item);\n" % (self.name, self.name, self.name) + + header += "\n\n\n" + + return header + + + def generate_helper_header(self): + header = "" + + # functions + header += ("int esxVI_Lookup%s(esxVI_Context *ctx, " + + "const char *name, " + + "esxVI_ManagedObjectReference *root, " + + "esxVI_String *selectedPropertyNameList, " + + "esxVI_%s **item, " + + "esxVI_Occurrence occurrence);\n") % (self.name, self.name) + + header += "\n" + + return header + + + def generate_source(self): + source = self.generate_comment() + + # functions + source += "/* esxVI_%s_Alloc */\n" % self.name + source += "ESX_VI__TEMPLATE__ALLOC(%s)\n\n" % self.name + + # free + if self.extended_by is None: + source += "/* esxVI_%s_Free */\n" % self.name + source += "ESX_VI__TEMPLATE__FREE(%s,\n" % self.name + source += "{\n" + + if self.features & ManagedObject.FEATURE__LIST: + if self.extends is not None: + # avoid "dereferencing type-punned pointer will break strict-aliasing rules" warnings + source += " esxVI_%s *next = (esxVI_%s *)item->_next;\n\n" % (self.extends, self.extends) + source += " esxVI_%s_Free(&next);\n" % self.extends + source += " item->_next = (esxVI_%s *)next;\n\n" % self.name + else: + source += " esxVI_%s_Free(&item->_next);\n" % self.name + + source += " esxVI_ManagedObjectReference_Free(&item->_reference);\n\n" + + source += self.generate_free_code() + + source += "})\n\n" + else: + source += "/* esxVI_%s_Free */\n" % self.name + source += "ESX_VI__TEMPLATE__DYNAMIC_FREE(%s,\n" % self.name + source += "{\n" + + for extended_by in self.extended_by: + source += " ESX_VI__TEMPLATE__DISPATCH__FREE(%s)\n" % extended_by + + source += "},\n" + source += "{\n" + + if self.features & Object.FEATURE__LIST: + if self.extends is not None: + # avoid "dereferencing type-punned pointer will break strict-aliasing rules" warnings + source += " esxVI_%s *next = (esxVI_%s *)item->_next;\n\n" % (self.extends, self.extends) + source += " esxVI_%s_Free(&next);\n" % self.extends + source += " item->_next = (esxVI_%s *)next;\n\n" % self.name + else: + source += " esxVI_%s_Free(&item->_next);\n" % self.name + + source += " esxVI_ManagedObjectReference_Free(&item->_reference);\n\n" + + source += self.generate_free_code() + + source += "})\n\n" + + # validate + source += "/* esxVI_%s_Validate */\n" % self.name + source += "ESX_VI__TEMPLATE__MANAGED_VALIDATE(%s,\n" % self.name + source += "{\n" + + source += self.generate_validate_code() + + source += "})\n\n" + + # append to list + if self.features & ManagedObject.FEATURE__LIST: + source += "/* esxVI_%s_AppendToList */\n" % self.name + source += "ESX_VI__TEMPLATE__LIST__APPEND(%s)\n\n" % self.name + + source += "\n\n" + + return source + + + def generate_helper_source(self): + source = "" + + # lookup + source += "/* esxVI_Lookup%s */\n" % self.name + source += "ESX_VI__TEMPLATE__LOOKUP(%s,\n" % self.name + source += "{\n" + + source += self.generate_lookup_code1() + + source += "},\n" + source += "{\n" + + source += self.generate_lookup_code2() + + source += "})\n\n" + + source += "\n\n" + + return source @@ -962,8 +1267,13 @@ def capitalize_first(string): def parse_object(block): - # expected format: object [extends ] + # expected format: [managed] object [extends ] header_items = block[0][1].split() + managed = False + + if header_items[0] == "managed": + managed = True + del header_items[0] if len(header_items) < 2: report_error("line %d: invalid block header" % (number)) @@ -994,7 +1304,10 @@ def parse_object(block): properties.append(Property(type=items[0], name=items[1], occurrence=items[2])) - return Object(name = name, extends = extends, properties = properties) + if managed: + return ManagedObject(name=name, extends=extends, properties=properties) + else: + return Object(name=name, extends=extends, properties=properties) @@ -1075,6 +1388,7 @@ def is_known_type(type): return type in predefined_objects or \ type in predefined_enums or \ type in objects_by_name or \ + type in managed_objects_by_name or \ type in enums_by_name @@ -1169,11 +1483,14 @@ types_header = open_and_print(os.path.join(output_dirname, "esx_vi_types.generat types_source = open_and_print(os.path.join(output_dirname, "esx_vi_types.generated.c")) methods_header = open_and_print(os.path.join(output_dirname, "esx_vi_methods.generated.h")) methods_source = open_and_print(os.path.join(output_dirname, "esx_vi_methods.generated.c")) +helpers_header = open_and_print(os.path.join(output_dirname, "esx_vi.generated.h")) +helpers_source = open_and_print(os.path.join(output_dirname, "esx_vi.generated.c")) number = 0 objects_by_name = {} +managed_objects_by_name = {} enums_by_name = {} methods_by_name = {} block = None @@ -1191,7 +1508,8 @@ for line in file(input_filename, "rb").readlines(): if len(line) < 1: continue - if line.startswith("object") or line.startswith("enum") or line.startswith("method"): + if line.startswith("object") or line.startswith("managed object") or \ + line.startswith("enum") or line.startswith("method"): if block is not None: report_error("line %d: nested block found" % (number)) else: @@ -1202,6 +1520,9 @@ for line in file(input_filename, "rb").readlines(): if block[0][1].startswith("object"): obj = parse_object(block) objects_by_name[obj.name] = obj + elif block[0][1].startswith("managed object"): + obj = parse_object(block) + managed_objects_by_name[obj.name] = obj elif block[0][1].startswith("enum"): enum = parse_enum(block) enums_by_name[enum.name] = enum @@ -1268,6 +1589,30 @@ for obj in objects_by_name.values(): +for obj in managed_objects_by_name.values(): + for property in obj.properties: + if property.occurrence != OCCURRENCE__IGNORED and \ + not is_known_type(property.type): + report_error("object '%s' contains unknown property type '%s'" % (obj.name, property.type)) + + if obj.extends is not None: + if not is_known_type(obj.extends): + report_error("object '%s' extends unknown object '%s'" % (obj.name, obj.extends)) + + # detect extended_by relation + if obj.extends is not None: + extended_obj = managed_objects_by_name[obj.extends] + + if extended_obj.extended_by is None: + extended_obj.extended_by = [obj.name] + else: + extended_obj.extended_by.append(obj.name) + extended_obj.extended_by.sort() + + + + + for obj in objects_by_name.values(): inherit_features(obj) @@ -1283,6 +1628,8 @@ types_header.write("/* Generated by esx_vi_generator.py */\n\n\n\n") types_source.write("/* Generated by esx_vi_generator.py */\n\n\n\n") methods_header.write("/* Generated by esx_vi_generator.py */\n\n\n\n") methods_source.write("/* Generated by esx_vi_generator.py */\n\n\n\n") +helpers_header.write("/* Generated by esx_vi_generator.py */\n\n\n\n") +helpers_source.write("/* Generated by esx_vi_generator.py */\n\n\n\n") # output enums @@ -1306,7 +1653,7 @@ for name in names: # output objects types_typedef.write("\n\n\n" + "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" + - " * VI Types\n" + + " * VI Objects\n" + " */\n\n") types_typeenum.write("\n") types_typetostring.write("\n") @@ -1327,6 +1674,30 @@ for name in names: +# output managed objects +types_typedef.write("\n\n\n" + + "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" + + " * VI Managed Objects\n" + + " */\n\n") +types_typeenum.write("\n") +types_typetostring.write("\n") +types_typefromstring.write("\n") + + + +names = managed_objects_by_name.keys() +names.sort() + +for name in names: + types_typedef.write(managed_objects_by_name[name].generate_typedef()) + types_typeenum.write(managed_objects_by_name[name].generate_typeenum()) + types_typetostring.write(managed_objects_by_name[name].generate_typetostring()) + types_typefromstring.write(managed_objects_by_name[name].generate_typefromstring()) + types_header.write(managed_objects_by_name[name].generate_header()) + types_source.write(managed_objects_by_name[name].generate_source()) + + + # output methods names = methods_by_name.keys() names.sort() @@ -1334,3 +1705,13 @@ names.sort() for name in names: methods_header.write(methods_by_name[name].generate_header()) methods_source.write(methods_by_name[name].generate_source()) + + + +# output helpers +names = managed_objects_by_name.keys() +names.sort() + +for name in names: + helpers_header.write(managed_objects_by_name[name].generate_helper_header()) + helpers_source.write(managed_objects_by_name[name].generate_helper_source()) diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c index f3cdf2a..9e23030 100644 --- a/src/esx/esx_vi_types.c +++ b/src/esx/esx_vi_types.c @@ -3,7 +3,7 @@ * esx_vi_types.c: client for the VMware VI API 2.5 to manage ESX hosts * * Copyright (C) 2010 Red Hat, Inc. - * Copyright (C) 2009-2010 Matthias Bolte + * Copyright (C) 2009-2011 Matthias Bolte * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -693,6 +693,44 @@ esxVI_GetActualObjectType(xmlNodePtr node, esxVI_Type baseType, +/* + * Macros to implement managed objects + */ + +#define ESX_VI__TEMPLATE__PROPERTY__MANAGED_REQUIRE(_name) \ + /* FIXME: This results in O(n^2) runtime in case of missing required, but \ + * unselected properties. */ \ + if (item->_name == 0 && \ + esxVI_String_ListContainsValue(selectedPropertyNameList, #_name)) { \ + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ + _("%s object is missing the required '%s' property"), \ + typeName, #_name); \ + return -1; \ + } + + + +#define ESX_VI__TEMPLATE__MANAGED_VALIDATE(__type, _require) \ + int \ + esxVI_##__type##_Validate(esxVI_##__type *item, \ + esxVI_String *selectedPropertyNameList) \ + { \ + const char *typeName = esxVI_Type_ToString(esxVI_Type_##__type); \ + \ + if (item->_type <= esxVI_Type_Undefined || \ + item->_type >= esxVI_Type_Other) { \ + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ + _("%s object has invalid dynamic type"), typeName); \ + return -1; \ + } \ + \ + _require \ + \ + return 0; \ + } + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * XSI: Type */ @@ -735,15 +773,6 @@ esxVI_Type_ToString(esxVI_Type type) case esxVI_Type_ManagedObjectReference: return "ManagedObjectReference"; - case esxVI_Type_Datacenter: - return "Datacenter"; - - case esxVI_Type_ComputeResource: - return "ComputeResource"; - - case esxVI_Type_HostSystem: - return "HostSystem"; - #include "esx_vi_types.generated.typetostring" case esxVI_Type_Other: @@ -776,12 +805,6 @@ esxVI_Type_FromString(const char *type) return esxVI_Type_MethodFault; } else if (STREQ(type, "ManagedObjectReference")) { return esxVI_Type_ManagedObjectReference; - } else if (STREQ(type, "Datacenter")) { - return esxVI_Type_Datacenter; - } else if (STREQ(type, "ComputeResource")) { - return esxVI_Type_ComputeResource; - } else if (STREQ(type, "HostSystem")) { - return esxVI_Type_HostSystem; } #include "esx_vi_types.generated.typefromstring" @@ -1050,6 +1073,20 @@ ESX_VI__TEMPLATE__VALIDATE(String, ESX_VI__TEMPLATE__PROPERTY__REQUIRE(value) }) +bool +esxVI_String_ListContainsValue(esxVI_String *stringList, const char *value) +{ + esxVI_String *string; + + for (string = stringList; string != NULL; string = string->_next) { + if (STREQ(string->value, value)) { + return true; + } + } + + return false; +} + /* esxVI_String_AppendToList */ ESX_VI__TEMPLATE__LIST__APPEND(String) @@ -1452,7 +1489,7 @@ esxVI_DateTime_ConvertToCalendarTime(esxVI_DateTime *dateTime, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Type: Fault + * SOAP: Fault */ /* esxVI_Fault_Alloc */ @@ -1483,7 +1520,7 @@ ESX_VI__TEMPLATE__DESERIALIZE(Fault, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Type: MethodFault + * VI Object: MethodFault */ /* esxVI_MethodFault_Alloc */ @@ -1528,7 +1565,7 @@ esxVI_MethodFault_Deserialize(xmlNodePtr node, esxVI_MethodFault **methodFault) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Type: ManagedObjectReference + * VI Object: ManagedObjectReference */ /* esxVI_ManagedObjectReference_Alloc */ @@ -1632,280 +1669,6 @@ esxVI_ManagedObjectReference_Deserialize /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Managed Object: Datacenter - * extends ManagedEntity - */ - -/* esxVI_Datacenter_Alloc */ -ESX_VI__TEMPLATE__ALLOC(Datacenter) - -/* esxVI_Datacenter_Free */ -ESX_VI__TEMPLATE__FREE(Datacenter, -{ - esxVI_Datacenter_Free(&item->_next); - esxVI_ManagedObjectReference_Free(&item->_reference); - - /* ManagedEntity */ - VIR_FREE(item->name); - - /* Datacenter */ - esxVI_ManagedObjectReference_Free(&item->hostFolder); - esxVI_ManagedObjectReference_Free(&item->vmFolder); -}) - -/* esxVI_Datacenter_Validate */ -ESX_VI__TEMPLATE__VALIDATE(Datacenter, -{ - /* ManagedEntity */ - ESX_VI__TEMPLATE__PROPERTY__REQUIRE(name); - - /* Datacenter */ - ESX_VI__TEMPLATE__PROPERTY__REQUIRE(hostFolder); - ESX_VI__TEMPLATE__PROPERTY__REQUIRE(vmFolder); -}) - -int -esxVI_Datacenter_CastFromObjectContent(esxVI_ObjectContent *objectContent, - esxVI_Datacenter **datacenter) -{ - esxVI_DynamicProperty *dynamicProperty = NULL; - - if (objectContent == NULL || datacenter == NULL || *datacenter != NULL) { - ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); - return -1; - } - - if (esxVI_Datacenter_Alloc(datacenter) < 0) { - return -1; - } - - if (esxVI_ManagedObjectReference_DeepCopy(&(*datacenter)->_reference, - objectContent->obj) < 0) { - goto failure; - } - - for (dynamicProperty = objectContent->propSet; dynamicProperty != NULL; - dynamicProperty = dynamicProperty->_next) { - if (STREQ(dynamicProperty->name, "name")) { - if (esxVI_AnyType_ExpectType(dynamicProperty->val, - esxVI_Type_String) < 0) { - goto failure; - } - - (*datacenter)->name = strdup(dynamicProperty->val->string); - - if ((*datacenter)->name == NULL) { - virReportOOMError(); - goto failure; - } - } else if (STREQ(dynamicProperty->name, "hostFolder")) { - if (esxVI_ManagedObjectReference_CastFromAnyType - (dynamicProperty->val, &(*datacenter)->hostFolder) < 0) { - goto failure; - } - } else if (STREQ(dynamicProperty->name, "vmFolder")) { - if (esxVI_ManagedObjectReference_CastFromAnyType - (dynamicProperty->val, &(*datacenter)->vmFolder) < 0) { - goto failure; - } - } - } - - if (esxVI_Datacenter_Validate(*datacenter) < 0) { - goto failure; - } - - return 0; - - failure: - esxVI_Datacenter_Free(datacenter); - - return -1; -} - - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Managed Object: ComputeResource - * extends ManagedEntity - */ - -/* esxVI_ComputeResource_Alloc */ -ESX_VI__TEMPLATE__ALLOC(ComputeResource) - -/* esxVI_ComputeResource_Free */ -ESX_VI__TEMPLATE__FREE(ComputeResource, -{ - esxVI_ComputeResource_Free(&item->_next); - esxVI_ManagedObjectReference_Free(&item->_reference); - - /* ManagedEntity */ - VIR_FREE(item->name); - - /* ComputeResource */ - esxVI_ManagedObjectReference_Free(&item->host); - esxVI_ManagedObjectReference_Free(&item->resourcePool); -}) - -/* esxVI_ComputeResource_Validate */ -ESX_VI__TEMPLATE__VALIDATE(ComputeResource, -{ - /* ManagedEntity */ - ESX_VI__TEMPLATE__PROPERTY__REQUIRE(name); - - /* ComputeResource */ -}) - -int -esxVI_ComputeResource_CastFromObjectContent - (esxVI_ObjectContent *objectContent, esxVI_ComputeResource **computeResource) -{ - esxVI_DynamicProperty *dynamicProperty = NULL; - - if (objectContent == NULL || computeResource == NULL || - *computeResource != NULL) { - ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); - return -1; - } - - if (esxVI_ComputeResource_Alloc(computeResource) < 0) { - return -1; - } - - if (esxVI_ManagedObjectReference_DeepCopy(&(*computeResource)->_reference, - objectContent->obj) < 0) { - goto failure; - } - - for (dynamicProperty = objectContent->propSet; dynamicProperty != NULL; - dynamicProperty = dynamicProperty->_next) { - if (STREQ(dynamicProperty->name, "name")) { - if (esxVI_AnyType_ExpectType(dynamicProperty->val, - esxVI_Type_String) < 0) { - goto failure; - } - - (*computeResource)->name = strdup(dynamicProperty->val->string); - - if ((*computeResource)->name == NULL) { - virReportOOMError(); - goto failure; - } - } else if (STREQ(dynamicProperty->name, "host")) { - if (esxVI_ManagedObjectReference_CastListFromAnyType - (dynamicProperty->val, &(*computeResource)->host) < 0) { - goto failure; - } - } else if (STREQ(dynamicProperty->name, "resourcePool")) { - if (esxVI_ManagedObjectReference_CastFromAnyType - (dynamicProperty->val, &(*computeResource)->resourcePool) < 0) { - goto failure; - } - } - } - - if (esxVI_ComputeResource_Validate(*computeResource) < 0) { - goto failure; - } - - return 0; - - failure: - esxVI_ComputeResource_Free(computeResource); - - return -1; -} - - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Managed Object: HostSystem - * extends ManagedEntity - */ - -/* esxVI_HostSystem_Alloc */ -ESX_VI__TEMPLATE__ALLOC(HostSystem) - -/* esxVI_HostSystem_Free */ -ESX_VI__TEMPLATE__FREE(HostSystem, -{ - esxVI_HostSystem_Free(&item->_next); - esxVI_ManagedObjectReference_Free(&item->_reference); - - /* ManagedEntity */ - VIR_FREE(item->name); - - /* HostSystem */ - esxVI_HostConfigManager_Free(&item->configManager); -}) - -/* esxVI_HostSystem_Validate */ -ESX_VI__TEMPLATE__VALIDATE(HostSystem, -{ - /* ManagedEntity */ - ESX_VI__TEMPLATE__PROPERTY__REQUIRE(name); - - /* HostSystem */ - ESX_VI__TEMPLATE__PROPERTY__REQUIRE(configManager); -}) - -int -esxVI_HostSystem_CastFromObjectContent(esxVI_ObjectContent *objectContent, - esxVI_HostSystem **hostSystem) -{ - esxVI_DynamicProperty *dynamicProperty = NULL; - - if (objectContent == NULL || hostSystem == NULL || *hostSystem != NULL) { - ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); - return -1; - } - - if (esxVI_HostSystem_Alloc(hostSystem) < 0) { - return -1; - } - - if (esxVI_ManagedObjectReference_DeepCopy(&(*hostSystem)->_reference, - objectContent->obj) < 0) { - goto failure; - } - - for (dynamicProperty = objectContent->propSet; dynamicProperty != NULL; - dynamicProperty = dynamicProperty->_next) { - if (STREQ(dynamicProperty->name, "name")) { - if (esxVI_AnyType_ExpectType(dynamicProperty->val, - esxVI_Type_String) < 0) { - goto failure; - } - - (*hostSystem)->name = strdup(dynamicProperty->val->string); - - if ((*hostSystem)->name == NULL) { - virReportOOMError(); - goto failure; - } - } else if (STREQ(dynamicProperty->name, "configManager")) { - if (esxVI_HostConfigManager_CastFromAnyType - (dynamicProperty->val, &(*hostSystem)->configManager) < 0) { - goto failure; - } - } - } - - if (esxVI_HostSystem_Validate(*hostSystem) < 0) { - goto failure; - } - - return 0; - - failure: - esxVI_HostSystem_Free(hostSystem); - - return -1; -} - - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VI Enum: VirtualMachinePowerState (Additions) */ diff --git a/src/esx/esx_vi_types.h b/src/esx/esx_vi_types.h index e53ccda..ac3741f 100644 --- a/src/esx/esx_vi_types.h +++ b/src/esx/esx_vi_types.h @@ -1,7 +1,8 @@ + /* * esx_vi_types.h: client for the VMware VI API 2.5 to manage ESX hosts * - * Copyright (C) 2009-2010 Matthias Bolte + * Copyright (C) 2009-2011 Matthias Bolte * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -44,15 +45,18 @@ typedef struct _esxVI_DateTime esxVI_DateTime; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Types + * SOAP */ typedef struct _esxVI_Fault esxVI_Fault; + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VI Objects + */ typedef struct _esxVI_MethodFault esxVI_MethodFault; typedef struct _esxVI_ManagedObjectReference esxVI_ManagedObjectReference; -typedef struct _esxVI_Datacenter esxVI_Datacenter; -typedef struct _esxVI_ComputeResource esxVI_ComputeResource; -typedef struct _esxVI_HostSystem esxVI_HostSystem; # include "esx_vi_types.generated.typedef" @@ -74,9 +78,6 @@ enum _esxVI_Type { esxVI_Type_Fault, esxVI_Type_MethodFault, esxVI_Type_ManagedObjectReference, - esxVI_Type_Datacenter, - esxVI_Type_ComputeResource, - esxVI_Type_HostSystem, # include "esx_vi_types.generated.typeenum" @@ -170,6 +171,7 @@ struct _esxVI_String { int esxVI_String_Alloc(esxVI_String **string); void esxVI_String_Free(esxVI_String **stringList); int esxVI_String_Validate(esxVI_String *string); +bool esxVI_String_ListContainsValue(esxVI_String *stringList, const char *value); int esxVI_String_AppendToList(esxVI_String **stringList, esxVI_String *string); int esxVI_String_AppendValueToList(esxVI_String **stringList, const char *value); @@ -264,7 +266,7 @@ int esxVI_DateTime_ConvertToCalendarTime(esxVI_DateTime *dateTime, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Type: Fault + * SOAP: Fault */ struct _esxVI_Fault { @@ -283,7 +285,7 @@ int esxVI_Fault_Deserialize(xmlNodePtr node, esxVI_Fault **fault); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Type: MethodFault + * VI Object: MethodFault */ /* @@ -306,7 +308,7 @@ int esxVI_MethodFault_Deserialize(xmlNodePtr node, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Type: ManagedObjectReference + * VI Object: ManagedObjectReference */ struct _esxVI_ManagedObjectReference { @@ -348,84 +350,6 @@ int esxVI_ManagedObjectReference_Deserialize /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Managed Object: Datacenter - * extends ManagedEntity - */ - -struct _esxVI_Datacenter { - esxVI_Datacenter *_next; /* optional */ - esxVI_Type _type; /* required */ - esxVI_ManagedObjectReference *_reference; /* required */ - - /* ManagedEntity */ - char *name; /* required */ - - /* Datacenter */ - esxVI_ManagedObjectReference *hostFolder; /* required */ - esxVI_ManagedObjectReference *vmFolder; /* required */ -}; - -int esxVI_Datacenter_Alloc(esxVI_Datacenter **datacenter); -void esxVI_Datacenter_Free(esxVI_Datacenter **datacenter); -int esxVI_Datacenter_Validate(esxVI_Datacenter *datacenter); -int esxVI_Datacenter_CastFromObjectContent(esxVI_ObjectContent *objectContent, - esxVI_Datacenter **datacenter); - - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Managed Object: ComputeResource - * extends ManagedEntity - */ - -struct _esxVI_ComputeResource { - esxVI_ComputeResource *_next; /* optional */ - esxVI_Type _type; /* required */ - esxVI_ManagedObjectReference *_reference; /* required */ - - /* ManagedEntity */ - char *name; /* required */ - - /* ComputeResource */ - esxVI_ManagedObjectReference *host; /* optional, list */ - esxVI_ManagedObjectReference *resourcePool; /* optional */ -}; - -int esxVI_ComputeResource_Alloc(esxVI_ComputeResource **computeResource); -void esxVI_ComputeResource_Free(esxVI_ComputeResource **computeResource); -int esxVI_ComputeResource_Validate(esxVI_ComputeResource *computeResource); -int esxVI_ComputeResource_CastFromObjectContent - (esxVI_ObjectContent *objectContent, - esxVI_ComputeResource **computeResource); - - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * VI Managed Object: HostSystem - * extends ManagedEntity - */ - -struct _esxVI_HostSystem { - esxVI_HostSystem *_next; /* optional */ - esxVI_Type _type; /* required */ - esxVI_ManagedObjectReference *_reference; /* required */ - - /* ManagedEntity */ - char *name; /* required */ - - /* HostSystem */ - esxVI_HostConfigManager *configManager; /* required */ -}; - -int esxVI_HostSystem_Alloc(esxVI_HostSystem **hostSystem); -void esxVI_HostSystem_Free(esxVI_HostSystem **hostSystem); -int esxVI_HostSystem_Validate(esxVI_HostSystem *hostSystem); -int esxVI_HostSystem_CastFromObjectContent(esxVI_ObjectContent *objectContent, - esxVI_HostSystem **hostSystem); - - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VI Enum: VirtualMachinePowerState (Additions) */ -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 10 11:28:29 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 10 Apr 2011 13:28:29 +0200 Subject: [libvirt] [PATCH] esx: Mark error message in macros for translation Message-ID: <20110410112829.GA13638@sbox> --- src/esx/esx_vi_types.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c index 9e23030..29a3c39 100644 --- a/src/esx/esx_vi_types.c +++ b/src/esx/esx_vi_types.c @@ -77,12 +77,12 @@ int \ esxVI_##__type##_Validate(esxVI_##__type *item) \ { \ - const char *type_name = esxVI_Type_ToString(esxVI_Type_##__type); \ + const char *typeName = esxVI_Type_ToString(esxVI_Type_##__type); \ \ if (item->_type <= esxVI_Type_Undefined || \ item->_type >= esxVI_Type_Other) { \ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ - "%s object has invalid dynamic type", type_name); \ + _("%s object has invalid dynamic type"), typeName); \ return -1; \ } \ \ @@ -293,7 +293,7 @@ childNode = childNode->next) { \ if (childNode->type != XML_ELEMENT_NODE) { \ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ - "Wrong XML element type %d", childNode->type); \ + _("Wrong XML element type %d"), childNode->type);\ goto failure; \ } \ \ @@ -343,22 +343,22 @@ \ if (string == NULL) { \ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ - "XML node doesn't contain text, expecting an " \ - _xsdType" value"); \ + _("XML node doesn't contain text, expecting an %s " \ + "value"), _xsdType); \ goto cleanup; \ } \ \ if (virStrToLong_ll(string, NULL, 10, &value) < 0) { \ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ - "Unknown value '%s' for "_xsdType, string); \ + _("Unknown value '%s' for %s"), string, _xsdType); \ goto cleanup; \ } \ \ if (((_min) != INT64_MIN && value < (_min)) \ || ((_max) != INT64_MAX && value > (_max))) { \ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ - "Value '%s' is not representable as "_xsdType, \ - (const char *)string); \ + _("Value '%s' is not representable as %s"), \ + string, _xsdType); \ goto cleanup; \ } \ \ @@ -482,8 +482,8 @@ #define ESX_VI__TEMPLATE__PROPERTY__REQUIRE(_name) \ if (item->_name == 0) { \ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ - "%s object is missing the required '%s' property", \ - type_name, #_name); \ + _("%s object is missing the required '%s' property"), \ + typeName, #_name); \ return -1; \ } -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 10 11:31:27 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 10 Apr 2011 13:31:27 +0200 Subject: [libvirt] [PATCH] virsh: Add --name and --description options to snapshot-create Message-ID: <20110410113127.GA13668@sbox> This options are shortcuts to set name and description of a snapshot. Suggested by Elias Probst --- I'm not sure if this is be best approach. In case of the vol-* commands there is vol-create that takes and XML file and vol-create-as that takes a set of arguments. So, should there actually be a snapshot-create-as to takes --name and --description options? Matthias tools/virsh.c | 39 ++++++++++++++++++++++++++++++++++++--- tools/virsh.pod | 6 ++++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 2e35021..2ddb2f7 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -10214,6 +10214,8 @@ static const vshCmdInfo info_snapshot_create[] = { static const vshCmdOptDef opts_snapshot_create[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, {"xmlfile", VSH_OT_DATA, 0, N_("domain snapshot XML")}, + {"name", VSH_OT_DATA, 0, N_("snapshot name")}, + {"description", VSH_OT_DATA, 0, N_("snapshot description")}, {NULL, 0, 0, NULL} }; @@ -10223,6 +10225,8 @@ cmdSnapshotCreate(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom = NULL; int ret = FALSE; const char *from = NULL; + const char *suggested_name = NULL; + const char *description = NULL; char *buffer = NULL; virDomainSnapshotPtr snapshot = NULL; xmlDocPtr xml = NULL; @@ -10237,9 +10241,38 @@ cmdSnapshotCreate(vshControl *ctl, const vshCmd *cmd) if (dom == NULL) goto cleanup; - if (vshCommandOptString(cmd, "xmlfile", &from) <= 0) - buffer = vshStrdup(ctl, ""); - else { + if (vshCommandOptString(cmd, "xmlfile", &from) <= 0) { + if (vshCommandOptString(cmd, "name", &suggested_name) < 0 || + vshCommandOptString(cmd, "description", &description) < 0) { + goto cleanup; + } + + if (suggested_name != NULL || description != NULL) { + virBuffer tmp = VIR_BUFFER_INITIALIZER; + + virBufferAddLit(&tmp, "\n"); + + if (suggested_name != NULL) + virBufferEscapeString(&tmp, " %s\n", + suggested_name); + + if (description != NULL) + virBufferEscapeString(&tmp, " %s\n", + description); + + virBufferAddLit(&tmp, ""); + + if (virBufferError(&tmp)) { + virBufferFreeAndReset(&tmp); + vshPrint(ctl, "%s", _("Failed to allocate XML buffer")); + goto cleanup; + } + + buffer = virBufferContentAndReset(&tmp); + } else { + buffer = vshStrdup(ctl, ""); + } + } else { if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) { /* we have to report the error here because during cleanup * we'll run through virDomainFree(), which loses the diff --git a/tools/virsh.pod b/tools/virsh.pod index 9c42008..aa238d9 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1223,12 +1223,14 @@ used to represent properties of snapshots. =over 4 -=item B I I +=item B I I optional I I Create a snapshot for domain I with the properties specified in I. The only properties settable for a domain snapshot are the and ; the rest of the fields are ignored, and -automatically filled in by libvirt. If I is completely omitted, +automatically filled in by libvirt. The values for and +can also be specified using I and I when I is +ommited. If I, I and I are completely omitted, then libvirt will choose a value for all fields. =item B I -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 10 11:40:15 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 10 Apr 2011 13:40:15 +0200 Subject: [libvirt] [PATCH v2] xen: Remove PATH_MAX sized stack allocation from block stats code In-Reply-To: <20110410050330.GJ24838@redhat.com> References: <20110409100517.GA26695@sbox> <20110410050330.GJ24838@redhat.com> Message-ID: 2011/4/10 Daniel Veillard : > On Sat, Apr 09, 2011 at 12:05:17PM +0200, Matthias Bolte wrote: >> --- >> ?src/xen/block_stats.c | ? 51 +++++++++++++++++++++++++------------------------ >> ?1 files changed, 26 insertions(+), 25 deletions(-) >> >> diff --git a/src/xen/block_stats.c b/src/xen/block_stats.c >> index e7c80c9..1918257 100644 >> --- a/src/xen/block_stats.c >> +++ b/src/xen/block_stats.c >> @@ -113,34 +113,35 @@ read_stat (const char *path) >> ?} >> >> ?static int64_t >> -read_bd_stat (int device, int domid, const char *str) >> +read_bd_stat(int device, int domid, const char *str) >> ?{ >> - ? ?char path[PATH_MAX]; >> + ? ?static const char *paths[] = { >> + ? ? ? ?"/sys/bus/xen-backend/devices/vbd-%d-%d/statistics/%s", >> + ? ? ? ?"/sys/bus/xen-backend/devices/tap-%d-%d/statistics/%s", >> + ? ? ? ?"/sys/devices/xen-backend/vbd-%d-%d/statistics/%s", >> + ? ? ? ?"/sys/devices/xen-backend/tap-%d-%d/statistics/%s" >> + ? ?}; >> + >> + ? ?int i; >> + ? ?char *path; >> ? ? ?int64_t r; >> >> - ? ?snprintf (path, sizeof path, >> - ? ? ? ? ? ? ?"/sys/bus/xen-backend/devices/vbd-%d-%d/statistics/%s", >> - ? ? ? ? ? ? ?domid, device, str); >> - ? ?r = read_stat (path); >> - ? ?if (r >= 0) return r; >> - >> - ? ?snprintf (path, sizeof path, >> - ? ? ? ? ? ? ?"/sys/bus/xen-backend/devices/tap-%d-%d/statistics/%s", >> - ? ? ? ? ? ? ?domid, device, str); >> - ? ?r = read_stat (path); >> - ? ?if (r >= 0) return r; >> - >> - ? ?snprintf (path, sizeof path, >> - ? ? ? ? ? ? ?"/sys/devices/xen-backend/vbd-%d-%d/statistics/%s", >> - ? ? ? ? ? ? ?domid, device, str); >> - ? ?r = read_stat (path); >> - ? ?if (r >= 0) return r; >> - >> - ? ?snprintf (path, sizeof path, >> - ? ? ? ? ? ? ?"/sys/devices/xen-backend/tap-%d-%d/statistics/%s", >> - ? ? ? ? ? ? ?domid, device, str); >> - ? ?r = read_stat (path); >> - ? ?return r; >> + ? ?for (i = 0; i < ARRAY_CARDINALITY(paths); ++i) { >> + ? ? ? ?if (virAsprintf(&path, paths[i], domid, device, str) < 0) { >> + ? ? ? ? ? ?virReportOOMError(); >> + ? ? ? ? ? ?return -1; >> + ? ? ? ?} >> + >> + ? ? ? ?r = read_stat(path); >> + >> + ? ? ? ?VIR_FREE(path); >> + >> + ? ? ? ?if (r >= 0) { >> + ? ? ? ? ? ?return r; >> + ? ? ? ?} >> + ? ?} >> + >> + ? ?return -1; >> ?} >> >> ?/* In Xenstore, /local/domain/0/backend/vbd///state, > > ?ACK, thanks ! > > Daniel > Thanks, pushed. Matthias From matthias.bolte at googlemail.com Sun Apr 10 13:03:42 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 10 Apr 2011 15:03:42 +0200 Subject: [libvirt] [PATCH] docs: Serial and parallel device target ports actually start from 0 Message-ID: <20110410130342.GA25199@sbox> Reported by Igor Gali? --- docs/formatdomain.html.in | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 574fee5..ea021e8 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1807,7 +1807,7 @@ qemu-kvm -net nic,model=? /dev/null

    target can have a port attribute, which - specifies the port number. Ports are numbered starting from 1. There are + specifies the port number. Ports are numbered starting from 0. There are usually 0, 1 or 2 parallel ports.

    @@ -1825,7 +1825,7 @@ qemu-kvm -net nic,model=? /dev/null

    target can have a port attribute, which - specifies the port number. Ports are numbered starting from 1. There are + specifies the port number. Ports are numbered starting from 0. There are usually 0, 1 or 2 serial ports.

    -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 10 13:39:29 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 10 Apr 2011 15:39:29 +0200 Subject: [libvirt] [PATCH] esx: Move CURL handling code to it's own type Message-ID: <20110410133929.GA28461@sbox> --- src/esx/esx_driver.c | 4 +- src/esx/esx_vi.c | 348 ++++++++++++++++++++++++++------------------------ src/esx/esx_vi.h | 29 +++- 3 files changed, 205 insertions(+), 176 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index deda372..ef76350 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -2642,7 +2642,7 @@ esxDomainDumpXML(virDomainPtr domain, int flags) url = virBufferContentAndReset(&buffer); - if (esxVI_Context_DownloadFile(priv->primary, url, &vmx) < 0) { + if (esxVI_CURL_Download(priv->primary->curl, url, &vmx) < 0) { goto cleanup; } @@ -3111,7 +3111,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml) /* Upload VMX file */ VIR_DEBUG("Uploading .vmx config, url='%s' vmx='%s'", url, vmx); - if (esxVI_Context_UploadFile(priv->primary, url, vmx) < 0) { + if (esxVI_CURL_Upload(priv->primary->curl, url, vmx) < 0) { goto cleanup; } diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index fbab347..2fd09cd 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -76,42 +76,25 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Context + * CURL */ -/* esxVI_Context_Alloc */ -ESX_VI__TEMPLATE__ALLOC(Context); +/* esxVI_CURL_Alloc */ +ESX_VI__TEMPLATE__ALLOC(CURL) -/* esxVI_Context_Free */ -ESX_VI__TEMPLATE__FREE(Context, +/* esxVI_CURL_Free */ +ESX_VI__TEMPLATE__FREE(CURL, { - VIR_FREE(item->url); - VIR_FREE(item->ipAddress); - - if (item->curl_handle != NULL) { - curl_easy_cleanup(item->curl_handle); + if (item->handle != NULL) { + curl_easy_cleanup(item->handle); } - if (item->curl_headers != NULL) { - curl_slist_free_all(item->curl_headers); + if (item->headers != NULL) { + curl_slist_free_all(item->headers); } - virMutexDestroy(&item->curl_lock); - - VIR_FREE(item->username); - VIR_FREE(item->password); - esxVI_ServiceContent_Free(&item->service); - esxVI_UserSession_Free(&item->session); - esxVI_Datacenter_Free(&item->datacenter); - esxVI_ComputeResource_Free(&item->computeResource); - esxVI_HostSystem_Free(&item->hostSystem); - esxVI_SelectionSpec_Free(&item->selectSet_folderToChildEntity); - esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToParent); - esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToVm); - esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToDatastore); - esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToHost); - esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToParentToParent); -}); + virMutexDestroy(&item->lock); +}) static size_t esxVI_CURL_ReadString(char *data, size_t size, size_t nmemb, void *ptrptr) @@ -218,7 +201,7 @@ esxVI_CURL_Debug(CURL *curl ATTRIBUTE_UNUSED, curl_infotype type, #endif static int -esxVI_CURL_Perform(esxVI_Context *ctx, const char *url) +esxVI_CURL_Perform(esxVI_CURL *curl, const char *url) { CURLcode errorCode; long responseCode = 0; @@ -226,23 +209,23 @@ esxVI_CURL_Perform(esxVI_Context *ctx, const char *url) const char *redirectUrl = NULL; #endif - errorCode = curl_easy_perform(ctx->curl_handle); + errorCode = curl_easy_perform(curl->handle); if (errorCode != CURLE_OK) { ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, _("curl_easy_perform() returned an error: %s (%d) : %s"), - curl_easy_strerror(errorCode), errorCode, ctx->curl_error); + curl_easy_strerror(errorCode), errorCode, curl->error); return -1; } - errorCode = curl_easy_getinfo(ctx->curl_handle, CURLINFO_RESPONSE_CODE, + errorCode = curl_easy_getinfo(curl->handle, CURLINFO_RESPONSE_CODE, &responseCode); if (errorCode != CURLE_OK) { ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, _("curl_easy_getinfo(CURLINFO_RESPONSE_CODE) returned an " "error: %s (%d) : %s"), curl_easy_strerror(errorCode), - errorCode, ctx->curl_error); + errorCode, curl->error); return -1; } @@ -255,7 +238,7 @@ esxVI_CURL_Perform(esxVI_Context *ctx, const char *url) if (responseCode == 301) { #if LIBCURL_VERSION_NUM >= 0x071202 /* 7.18.2 */ - errorCode = curl_easy_getinfo(ctx->curl_handle, CURLINFO_REDIRECT_URL, + errorCode = curl_easy_getinfo(curl->handle, CURLINFO_REDIRECT_URL, &redirectUrl); if (errorCode != CURLE_OK) { @@ -263,7 +246,7 @@ esxVI_CURL_Perform(esxVI_Context *ctx, const char *url) _("curl_easy_getinfo(CURLINFO_REDIRECT_URL) returned " "an error: %s (%d) : %s"), curl_easy_strerror(errorCode), - errorCode, ctx->curl_error); + errorCode, curl->error); } else { ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, _("The server redirects from '%s' to '%s'"), url, @@ -281,32 +264,23 @@ esxVI_CURL_Perform(esxVI_Context *ctx, const char *url) } int -esxVI_Context_Connect(esxVI_Context *ctx, const char *url, - const char *ipAddress, const char *username, - const char *password, esxUtil_ParsedUri *parsedUri) +esxVI_CURL_Connect(esxVI_CURL *curl, esxUtil_ParsedUri *parsedUri) { - if (ctx == NULL || url == NULL || ipAddress == NULL || username == NULL || - password == NULL || ctx->url != NULL || ctx->service != NULL || - ctx->curl_handle != NULL || ctx->curl_headers != NULL) { - ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); - return -1; - } - - if (esxVI_String_DeepCopyValue(&ctx->url, url) < 0 || - esxVI_String_DeepCopyValue(&ctx->ipAddress, ipAddress) < 0) { + if (curl->handle != NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid call")); return -1; } - ctx->curl_handle = curl_easy_init(); + curl->handle = curl_easy_init(); - if (ctx->curl_handle == NULL) { + if (curl->handle == NULL) { ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not initialize CURL")); return -1; } - ctx->curl_headers = curl_slist_append(ctx->curl_headers, "Content-Type: " - "text/xml; charset=UTF-8"); + curl->headers = curl_slist_append(curl->headers, + "Content-Type: text/xml; charset=UTF-8"); /* * Add a dummy expect header to stop CURL from waiting for a response code @@ -316,56 +290,179 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url, * 100 (Continue) response and the wait times out resulting in wasting * approx. 2 sec per POST operation. */ - ctx->curl_headers = curl_slist_append(ctx->curl_headers, - "Expect: nothing"); + curl->headers = curl_slist_append(curl->headers, "Expect: nothing"); - if (ctx->curl_headers == NULL) { + if (curl->headers == NULL) { ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not build CURL header list")); return -1; } - curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, ctx->url); - curl_easy_setopt(ctx->curl_handle, CURLOPT_USERAGENT, "libvirt-esx"); - curl_easy_setopt(ctx->curl_handle, CURLOPT_HEADER, 0); - curl_easy_setopt(ctx->curl_handle, CURLOPT_FOLLOWLOCATION, 0); - curl_easy_setopt(ctx->curl_handle, CURLOPT_SSL_VERIFYPEER, + curl_easy_setopt(curl->handle, CURLOPT_USERAGENT, "libvirt-esx"); + curl_easy_setopt(curl->handle, CURLOPT_HEADER, 0); + curl_easy_setopt(curl->handle, CURLOPT_FOLLOWLOCATION, 0); + curl_easy_setopt(curl->handle, CURLOPT_SSL_VERIFYPEER, parsedUri->noVerify ? 0 : 1); - curl_easy_setopt(ctx->curl_handle, CURLOPT_SSL_VERIFYHOST, + curl_easy_setopt(curl->handle, CURLOPT_SSL_VERIFYHOST, parsedUri->noVerify ? 0 : 2); - curl_easy_setopt(ctx->curl_handle, CURLOPT_COOKIEFILE, ""); - curl_easy_setopt(ctx->curl_handle, CURLOPT_HTTPHEADER, ctx->curl_headers); - curl_easy_setopt(ctx->curl_handle, CURLOPT_READFUNCTION, + curl_easy_setopt(curl->handle, CURLOPT_COOKIEFILE, ""); + curl_easy_setopt(curl->handle, CURLOPT_HTTPHEADER, curl->headers); + curl_easy_setopt(curl->handle, CURLOPT_READFUNCTION, esxVI_CURL_ReadString); - curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEFUNCTION, + curl_easy_setopt(curl->handle, CURLOPT_WRITEFUNCTION, esxVI_CURL_WriteBuffer); - curl_easy_setopt(ctx->curl_handle, CURLOPT_ERRORBUFFER, - ctx->curl_error); + curl_easy_setopt(curl->handle, CURLOPT_ERRORBUFFER, curl->error); #if ESX_VI__CURL__ENABLE_DEBUG_OUTPUT - curl_easy_setopt(ctx->curl_handle, CURLOPT_DEBUGFUNCTION, esxVI_CURL_Debug); - curl_easy_setopt(ctx->curl_handle, CURLOPT_VERBOSE, 1); + curl_easy_setopt(curl->handle, CURLOPT_DEBUGFUNCTION, esxVI_CURL_Debug); + curl_easy_setopt(curl->handle, CURLOPT_VERBOSE, 1); #endif if (parsedUri->proxy) { - curl_easy_setopt(ctx->curl_handle, CURLOPT_PROXY, + curl_easy_setopt(curl->handle, CURLOPT_PROXY, parsedUri->proxy_hostname); - curl_easy_setopt(ctx->curl_handle, CURLOPT_PROXYTYPE, + curl_easy_setopt(curl->handle, CURLOPT_PROXYTYPE, parsedUri->proxy_type); - curl_easy_setopt(ctx->curl_handle, CURLOPT_PROXYPORT, + curl_easy_setopt(curl->handle, CURLOPT_PROXYPORT, parsedUri->proxy_port); } - if (virMutexInit(&ctx->curl_lock) < 0) { + if (virMutexInit(&curl->lock) < 0) { ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not initialize CURL mutex")); return -1; } - ctx->username = strdup(username); - ctx->password = strdup(password); + return 0; +} + +int +esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content) +{ + virBuffer buffer = VIR_BUFFER_INITIALIZER; + int responseCode = 0; - if (ctx->username == NULL || ctx->password == NULL) { + if (content == NULL || *content != NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + virMutexLock(&curl->lock); + + curl_easy_setopt(curl->handle, CURLOPT_URL, url); + curl_easy_setopt(curl->handle, CURLOPT_WRITEDATA, &buffer); + curl_easy_setopt(curl->handle, CURLOPT_UPLOAD, 0); + curl_easy_setopt(curl->handle, CURLOPT_HTTPGET, 1); + + responseCode = esxVI_CURL_Perform(curl, url); + + virMutexUnlock(&curl->lock); + + if (responseCode < 0) { + goto cleanup; + } else if (responseCode != 200) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, + _("HTTP response code %d for download from '%s'"), + responseCode, url); + goto cleanup; + } + + if (virBufferError(&buffer)) { virReportOOMError(); + goto cleanup; + } + + *content = virBufferContentAndReset(&buffer); + + cleanup: + if (*content == NULL) { + virBufferFreeAndReset(&buffer); + return -1; + } + + return 0; +} + +int +esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content) +{ + int responseCode = 0; + + if (content == NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + virMutexLock(&curl->lock); + + curl_easy_setopt(curl->handle, CURLOPT_URL, url); + curl_easy_setopt(curl->handle, CURLOPT_READDATA, &content); + curl_easy_setopt(curl->handle, CURLOPT_UPLOAD, 1); + curl_easy_setopt(curl->handle, CURLOPT_INFILESIZE, strlen(content)); + + responseCode = esxVI_CURL_Perform(curl, url); + + virMutexUnlock(&curl->lock); + + if (responseCode < 0) { + return -1; + } else if (responseCode != 200 && responseCode != 201) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, + _("HTTP response code %d for upload to '%s'"), + responseCode, url); + return -1; + } + + return 0; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Context + */ + +/* esxVI_Context_Alloc */ +ESX_VI__TEMPLATE__ALLOC(Context) + +/* esxVI_Context_Free */ +ESX_VI__TEMPLATE__FREE(Context, +{ + esxVI_CURL_Free(&item->curl); + VIR_FREE(item->url); + VIR_FREE(item->ipAddress); + VIR_FREE(item->username); + VIR_FREE(item->password); + esxVI_ServiceContent_Free(&item->service); + esxVI_UserSession_Free(&item->session); + esxVI_Datacenter_Free(&item->datacenter); + esxVI_ComputeResource_Free(&item->computeResource); + esxVI_HostSystem_Free(&item->hostSystem); + esxVI_SelectionSpec_Free(&item->selectSet_folderToChildEntity); + esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToParent); + esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToVm); + esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToDatastore); + esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToHost); + esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToParentToParent); +}) + +int +esxVI_Context_Connect(esxVI_Context *ctx, const char *url, + const char *ipAddress, const char *username, + const char *password, esxUtil_ParsedUri *parsedUri) +{ + if (ctx == NULL || url == NULL || ipAddress == NULL || username == NULL || + password == NULL || ctx->url != NULL || ctx->service != NULL || + ctx->curl != NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + if (esxVI_CURL_Alloc(&ctx->curl) < 0 || + esxVI_CURL_Connect(ctx->curl, parsedUri) < 0 || + esxVI_String_DeepCopyValue(&ctx->url, url) < 0 || + esxVI_String_DeepCopyValue(&ctx->ipAddress, ipAddress) < 0 || + esxVI_String_DeepCopyValue(&ctx->username, username) < 0 || + esxVI_String_DeepCopyValue(&ctx->password, password) < 0) { return -1; } @@ -577,87 +674,6 @@ esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx, } int -esxVI_Context_DownloadFile(esxVI_Context *ctx, const char *url, char **content) -{ - virBuffer buffer = VIR_BUFFER_INITIALIZER; - int responseCode = 0; - - if (content == NULL || *content != NULL) { - ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); - return -1; - } - - virMutexLock(&ctx->curl_lock); - - curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, url); - curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEDATA, &buffer); - curl_easy_setopt(ctx->curl_handle, CURLOPT_UPLOAD, 0); - curl_easy_setopt(ctx->curl_handle, CURLOPT_HTTPGET, 1); - - responseCode = esxVI_CURL_Perform(ctx, url); - - virMutexUnlock(&ctx->curl_lock); - - if (responseCode < 0) { - goto cleanup; - } else if (responseCode != 200) { - ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, - _("HTTP response code %d for download from '%s'"), - responseCode, url); - goto cleanup; - } - - if (virBufferError(&buffer)) { - virReportOOMError(); - goto cleanup; - } - - *content = virBufferContentAndReset(&buffer); - - cleanup: - if (*content == NULL) { - virBufferFreeAndReset(&buffer); - return -1; - } - - return 0; -} - -int -esxVI_Context_UploadFile(esxVI_Context *ctx, const char *url, - const char *content) -{ - int responseCode = 0; - - if (content == NULL) { - ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); - return -1; - } - - virMutexLock(&ctx->curl_lock); - - curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, url); - curl_easy_setopt(ctx->curl_handle, CURLOPT_READDATA, &content); - curl_easy_setopt(ctx->curl_handle, CURLOPT_UPLOAD, 1); - curl_easy_setopt(ctx->curl_handle, CURLOPT_INFILESIZE, strlen(content)); - - responseCode = esxVI_CURL_Perform(ctx, url); - - virMutexUnlock(&ctx->curl_lock); - - if (responseCode < 0) { - return -1; - } else if (responseCode != 200 && responseCode != 201) { - ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, - _("HTTP response code %d for upload to '%s'"), - responseCode, url); - return -1; - } - - return 0; -} - -int esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName, const char *request, esxVI_Response **response, esxVI_Occurrence occurrence) @@ -678,17 +694,17 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName, return -1; } - virMutexLock(&ctx->curl_lock); + virMutexLock(&ctx->curl->lock); - curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, ctx->url); - curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEDATA, &buffer); - curl_easy_setopt(ctx->curl_handle, CURLOPT_UPLOAD, 0); - curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDS, request); - curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDSIZE, strlen(request)); + curl_easy_setopt(ctx->curl->handle, CURLOPT_URL, ctx->url); + curl_easy_setopt(ctx->curl->handle, CURLOPT_WRITEDATA, &buffer); + curl_easy_setopt(ctx->curl->handle, CURLOPT_UPLOAD, 0); + curl_easy_setopt(ctx->curl->handle, CURLOPT_POSTFIELDS, request); + curl_easy_setopt(ctx->curl->handle, CURLOPT_POSTFIELDSIZE, strlen(request)); - (*response)->responseCode = esxVI_CURL_Perform(ctx, ctx->url); + (*response)->responseCode = esxVI_CURL_Perform(ctx->curl, ctx->url); - virMutexUnlock(&ctx->curl_lock); + virMutexUnlock(&ctx->curl->lock); if ((*response)->responseCode < 0) { goto cleanup; @@ -869,7 +885,7 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName, */ /* esxVI_Response_Alloc */ -ESX_VI__TEMPLATE__ALLOC(Response); +ESX_VI__TEMPLATE__ALLOC(Response) /* esxVI_Response_Free */ ESX_VI__TEMPLATE__FREE(Response, @@ -879,7 +895,7 @@ ESX_VI__TEMPLATE__FREE(Response, if (item->document != NULL) { xmlFreeDoc(item->document); } -}); +}) diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index d046bf9..57788ac 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -82,6 +82,7 @@ typedef enum _esxVI_APIVersion esxVI_APIVersion; typedef enum _esxVI_ProductVersion esxVI_ProductVersion; typedef enum _esxVI_Occurrence esxVI_Occurrence; typedef struct _esxVI_ParsedHostCpuIdInfo esxVI_ParsedHostCpuIdInfo; +typedef struct _esxVI_CURL esxVI_CURL; typedef struct _esxVI_Context esxVI_Context; typedef struct _esxVI_Response esxVI_Response; typedef struct _esxVI_Enumeration esxVI_Enumeration; @@ -142,16 +143,32 @@ struct _esxVI_ParsedHostCpuIdInfo { /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * CURL + */ + +struct _esxVI_CURL { + CURL *handle; + virMutex lock; + struct curl_slist *headers; + char error[CURL_ERROR_SIZE]; +}; + +int esxVI_CURL_Alloc(esxVI_CURL **curl); +void esxVI_CURL_Free(esxVI_CURL **curl); +int esxVI_CURL_Connect(esxVI_CURL *curl, esxUtil_ParsedUri *parsedUri); +int esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content); +int esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content); + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Context */ struct _esxVI_Context { + esxVI_CURL *curl; char *url; char *ipAddress; - CURL *curl_handle; - struct curl_slist *curl_headers; - char curl_error[CURL_ERROR_SIZE]; - virMutex curl_lock; char *username; char *password; esxVI_ServiceContent *service; @@ -180,10 +197,6 @@ int esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx, esxUtil_ParsedUri *parsedUri); int esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx, const char *hostSystemIpAddress); -int esxVI_Context_DownloadFile(esxVI_Context *ctx, const char *url, - char **content); -int esxVI_Context_UploadFile(esxVI_Context *ctx, const char *url, - const char *content); int esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName, const char *request, esxVI_Response **response, esxVI_Occurrence occurrence); -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 10 15:17:24 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 10 Apr 2011 17:17:24 +0200 Subject: [libvirt] [PATCH] esx: Add a wrapper for shared CURL handles Message-ID: <20110410151724.GA29031@sbox> To be used to share a CURL handle between multiple threads in the upcoming domain event support. --- src/esx/esx_vi.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/esx/esx_vi.h | 19 ++++++ 2 files changed, 195 insertions(+), 0 deletions(-) diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index 2fd09cd..84ff2e2 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -85,6 +85,16 @@ ESX_VI__TEMPLATE__ALLOC(CURL) /* esxVI_CURL_Free */ ESX_VI__TEMPLATE__FREE(CURL, { + esxVI_SharedCURL *shared = item->shared; + + if (shared != NULL) { + esxVI_SharedCURL_Remove(shared, item); + + if (shared->count == 0) { + esxVI_SharedCURL_Free(&shared); + } + } + if (item->handle != NULL) { curl_easy_cleanup(item->handle); } @@ -418,6 +428,172 @@ esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * SharedCURL + */ + +static void +esxVI_SharedCURL_Lock(CURL *handle ATTRIBUTE_UNUSED, curl_lock_data data, + curl_lock_access access_ ATTRIBUTE_UNUSED, void *userptr) +{ + int i; + esxVI_SharedCURL *shared = userptr; + + switch (data) { + case CURL_LOCK_DATA_SHARE: + i = 0; + break; + + case CURL_LOCK_DATA_COOKIE: + i = 1; + break; + + case CURL_LOCK_DATA_DNS: + i = 2; + break; + + default: + VIR_ERROR(_("Trying to lock unknown SharedCURL lock %d"), (int)data); + return; + } + + virMutexLock(&shared->locks[i]); +} + +static void +esxVI_SharedCURL_Unlock(CURL *handle ATTRIBUTE_UNUSED, curl_lock_data data, + void *userptr) +{ + int i; + esxVI_SharedCURL *shared = userptr; + + switch (data) { + case CURL_LOCK_DATA_SHARE: + i = 0; + break; + + case CURL_LOCK_DATA_COOKIE: + i = 1; + break; + + case CURL_LOCK_DATA_DNS: + i = 2; + break; + + default: + VIR_ERROR(_("Trying to unlock unknown SharedCURL lock %d"), (int)data); + return; + } + + virMutexUnlock(&shared->locks[i]); +} + +/* esxVI_SharedCURL_Alloc */ +ESX_VI__TEMPLATE__ALLOC(SharedCURL) + +/* esxVI_SharedCURL_Free */ +ESX_VI__TEMPLATE__FREE(SharedCURL, +{ + int i; + + if (item->count > 0) { + /* Better leak than crash */ + VIR_ERROR0(_("Trying to free SharedCURL object that is still in use")); + return; + } + + if (item->handle != NULL) { + curl_share_cleanup(item->handle); + } + + for (i = 0; i < ARRAY_CARDINALITY(item->locks); ++i) { + virMutexDestroy(&item->locks[i]); + } +}) + +int +esxVI_SharedCURL_Add(esxVI_SharedCURL *shared, esxVI_CURL *curl) +{ + int i; + + if (curl->handle == NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot share uninitialized CURL handle")); + return -1; + } + + if (curl->shared != NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot share CURL handle that is already shared")); + return -1; + } + + if (shared->handle == NULL) { + shared->handle = curl_share_init(); + + if (shared->handle == NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not initialize CURL (share)")); + return -1; + } + + curl_share_setopt(shared->handle, CURLSHOPT_LOCKFUNC, + esxVI_SharedCURL_Lock); + curl_share_setopt(shared->handle, CURLSHOPT_UNLOCKFUNC, + esxVI_SharedCURL_Unlock); + curl_share_setopt(shared->handle, CURLSHOPT_USERDATA, shared); + curl_share_setopt(shared->handle, CURLSHOPT_SHARE, + CURL_LOCK_DATA_COOKIE); + curl_share_setopt(shared->handle, CURLSHOPT_SHARE, + CURL_LOCK_DATA_DNS); + + for (i = 0; i < ARRAY_CARDINALITY(shared->locks); ++i) { + if (virMutexInit(&shared->locks[i]) < 0) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not initialize a CURL (share) mutex")); + return -1; + } + } + } + + curl_easy_setopt(curl->handle, CURLOPT_SHARE, shared->handle); + + curl->shared = shared; + ++shared->count; + + return 0; +} + +int +esxVI_SharedCURL_Remove(esxVI_SharedCURL *shared, esxVI_CURL *curl) +{ + if (curl->handle == NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot unshare uninitialized CURL handle")); + return -1; + } + + if (curl->shared == NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot unshare CURL handle that is not shared")); + return -1; + } + + if (curl->shared != shared) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("CURL (share) mismatch")); + return -1; + } + + curl_easy_setopt(curl->handle, CURLOPT_SHARE, NULL); + + curl->shared = NULL; + --shared->count; + + return 0; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Context */ diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index 57788ac..560b2a6 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -83,6 +83,7 @@ typedef enum _esxVI_ProductVersion esxVI_ProductVersion; typedef enum _esxVI_Occurrence esxVI_Occurrence; typedef struct _esxVI_ParsedHostCpuIdInfo esxVI_ParsedHostCpuIdInfo; typedef struct _esxVI_CURL esxVI_CURL; +typedef struct _esxVI_SharedCURL esxVI_SharedCURL; typedef struct _esxVI_Context esxVI_Context; typedef struct _esxVI_Response esxVI_Response; typedef struct _esxVI_Enumeration esxVI_Enumeration; @@ -151,6 +152,7 @@ struct _esxVI_CURL { virMutex lock; struct curl_slist *headers; char error[CURL_ERROR_SIZE]; + esxVI_SharedCURL *shared; }; int esxVI_CURL_Alloc(esxVI_CURL **curl); @@ -162,6 +164,23 @@ int esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * SharedCURL + */ + +struct _esxVI_SharedCURL { + CURLSH *handle; + virMutex locks[3]; /* share, cookie, dns */ + size_t count; +}; + +int esxVI_SharedCURL_Alloc(esxVI_SharedCURL **shared); +void esxVI_SharedCURL_Free(esxVI_SharedCURL **shared); +int esxVI_SharedCURL_Add(esxVI_SharedCURL *shared, esxVI_CURL *curl); +int esxVI_SharedCURL_Remove(esxVI_SharedCURL *shared, esxVI_CURL *curl); + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Context */ -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 10 15:18:32 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 10 Apr 2011 17:18:32 +0200 Subject: [libvirt] [PATCH] esx: Make the parsed URI part of the private connection data Message-ID: <20110410151832.GA29175@sbox> This will be used to make esxVI_Context clonable. Also move cleanup code for esxPrivate to esxFreePrivate(). --- src/esx/esx_driver.c | 103 ++++++++++++++++++++++++------------------------- src/esx/esx_private.h | 4 +- 2 files changed, 52 insertions(+), 55 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index ef76350..bfb3c16 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -3,7 +3,7 @@ * esx_driver.c: core driver functions for managing VMware ESX hosts * * Copyright (C) 2010-2011 Red Hat, Inc. - * Copyright (C) 2009-2010 Matthias Bolte + * Copyright (C) 2009-2011 Matthias Bolte * Copyright (C) 2009 Maximilian Wilhelm * * This library is free software; you can redistribute it and/or @@ -57,6 +57,22 @@ struct _esxVMX_Data { +static void +esxFreePrivate(esxPrivate **priv) +{ + if (priv == NULL || *priv == NULL) { + return; + } + + esxVI_Context_Free(&(*priv)->host); + esxVI_Context_Free(&(*priv)->vCenter); + esxUtil_FreeParsedUri(&(*priv)->parsedUri); + virCapabilitiesFree((*priv)->caps); + VIR_FREE(*priv); +} + + + /* * Parse a file name from a .vmx file and convert it to datastore path format. * A .vmx file can contain file names in various formats: @@ -619,7 +635,6 @@ static int esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth, const char *hostname, int port, const char *predefinedUsername, - esxUtil_ParsedUri *parsedUri, esxVI_ProductVersion expectedProductVersion, char **vCenterIpAddress) { @@ -671,16 +686,16 @@ esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth, goto cleanup; } - if (virAsprintf(&url, "%s://%s:%d/sdk", priv->transport, hostname, - port) < 0) { + if (virAsprintf(&url, "%s://%s:%d/sdk", priv->parsedUri->transport, + hostname, port) < 0) { virReportOOMError(); goto cleanup; } if (esxVI_Context_Alloc(&priv->host) < 0 || esxVI_Context_Connect(priv->host, url, ipAddress, username, password, - parsedUri) < 0 || - esxVI_Context_LookupObjectsByPath(priv->host, parsedUri) < 0) { + priv->parsedUri) < 0 || + esxVI_Context_LookupObjectsByPath(priv->host, priv->parsedUri) < 0) { goto cleanup; } @@ -750,8 +765,7 @@ static int esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth, const char *hostname, int port, const char *predefinedUsername, - const char *hostSystemIpAddress, - esxUtil_ParsedUri *parsedUri) + const char *hostSystemIpAddress) { int result = -1; char ipAddress[NI_MAXHOST] = ""; @@ -761,8 +775,8 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth, char *url = NULL; if (hostSystemIpAddress == NULL && - (parsedUri->path_datacenter == NULL || - parsedUri->path_computeResource == NULL)) { + (priv->parsedUri->path_datacenter == NULL || + priv->parsedUri->path_computeResource == NULL)) { ESX_ERROR(VIR_ERR_INVALID_ARG, "%s", _("Path has to specify the datacenter and compute resource")); return -1; @@ -801,15 +815,15 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth, goto cleanup; } - if (virAsprintf(&url, "%s://%s:%d/sdk", priv->transport, hostname, - port) < 0) { + if (virAsprintf(&url, "%s://%s:%d/sdk", priv->parsedUri->transport, + hostname, port) < 0) { virReportOOMError(); goto cleanup; } if (esxVI_Context_Alloc(&priv->vCenter) < 0 || esxVI_Context_Connect(priv->vCenter, url, ipAddress, username, - password, parsedUri) < 0) { + password, priv->parsedUri) < 0) { goto cleanup; } @@ -829,7 +843,8 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth, goto cleanup; } } else { - if (esxVI_Context_LookupObjectsByPath(priv->vCenter, parsedUri) < 0) { + if (esxVI_Context_LookupObjectsByPath(priv->vCenter, + priv->parsedUri) < 0) { goto cleanup; } } @@ -896,7 +911,6 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) { virDrvOpenStatus result = VIR_DRV_OPEN_ERROR; esxPrivate *priv = NULL; - esxUtil_ParsedUri *parsedUri = NULL; char *potentialVCenterIpAddress = NULL; char vCenterIpAddress[NI_MAXHOST] = ""; @@ -919,18 +933,15 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) goto cleanup; } - if (esxUtil_ParseUri(&parsedUri, conn->uri) < 0) { + if (esxUtil_ParseUri(&priv->parsedUri, conn->uri) < 0) { goto cleanup; } - priv->transport = parsedUri->transport; - parsedUri->transport = NULL; - priv->maxVcpus = -1; priv->supportsVMotion = esxVI_Boolean_Undefined; priv->supportsLongMode = esxVI_Boolean_Undefined; - priv->autoAnswer = parsedUri->autoAnswer ? esxVI_Boolean_True - : esxVI_Boolean_False; + priv->autoAnswer = priv->parsedUri->autoAnswer ? esxVI_Boolean_True + : esxVI_Boolean_False; priv->usedCpuTimeCounterId = -1; /* @@ -942,13 +953,13 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) if (conn->uri->port == 0) { if (STRCASEEQ(conn->uri->scheme, "vpx") || STRCASEEQ(conn->uri->scheme, "esx")) { - if (STRCASEEQ(priv->transport, "https")) { + if (STRCASEEQ(priv->parsedUri->transport, "https")) { conn->uri->port = 443; } else { conn->uri->port = 80; } } else { /* GSX */ - if (STRCASEEQ(priv->transport, "https")) { + if (STRCASEEQ(priv->parsedUri->transport, "https")) { conn->uri->port = 8333; } else { conn->uri->port = 8222; @@ -960,7 +971,7 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) STRCASEEQ(conn->uri->scheme, "gsx")) { /* Connect to host */ if (esxConnectToHost(priv, auth, conn->uri->server, conn->uri->port, - conn->uri->user, parsedUri, + conn->uri->user, STRCASEEQ(conn->uri->scheme, "esx") ? esxVI_ProductVersion_ESX : esxVI_ProductVersion_GSX, @@ -969,8 +980,8 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) } /* Connect to vCenter */ - if (parsedUri->vCenter != NULL) { - if (STREQ(parsedUri->vCenter, "*")) { + if (priv->parsedUri->vCenter != NULL) { + if (STREQ(priv->parsedUri->vCenter, "*")) { if (potentialVCenterIpAddress == NULL) { ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("This host is not managed by a vCenter")); @@ -985,7 +996,7 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) goto cleanup; } } else { - if (esxUtil_ResolveHostname(parsedUri->vCenter, + if (esxUtil_ResolveHostname(priv->parsedUri->vCenter, vCenterIpAddress, NI_MAXHOST) < 0) { goto cleanup; } @@ -996,7 +1007,7 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) _("This host is managed by a vCenter with IP " "address %s, but a mismachting vCenter '%s' " "(%s) has been specified"), - potentialVCenterIpAddress, parsedUri->vCenter, + potentialVCenterIpAddress, priv->parsedUri->vCenter, vCenterIpAddress); goto cleanup; } @@ -1004,7 +1015,7 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) if (esxConnectToVCenter(priv, auth, vCenterIpAddress, conn->uri->port, NULL, - priv->host->ipAddress, parsedUri) < 0) { + priv->host->ipAddress) < 0) { goto cleanup; } } @@ -1013,15 +1024,13 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) } else { /* VPX */ /* Connect to vCenter */ if (esxConnectToVCenter(priv, auth, conn->uri->server, conn->uri->port, - conn->uri->user, NULL, parsedUri) < 0) { + conn->uri->user, NULL) < 0) { goto cleanup; } priv->primary = priv->vCenter; } - conn->privateData = priv; - /* Setup capabilities */ priv->caps = esxCapsInit(priv); @@ -1029,20 +1038,15 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED) goto cleanup; } + conn->privateData = priv; + result = VIR_DRV_OPEN_SUCCESS; cleanup: - if (result == VIR_DRV_OPEN_ERROR && priv != NULL) { - esxVI_Context_Free(&priv->host); - esxVI_Context_Free(&priv->vCenter); - - virCapabilitiesFree(priv->caps); - - VIR_FREE(priv->transport); - VIR_FREE(priv); + if (result == VIR_DRV_OPEN_ERROR) { + esxFreePrivate(&priv); } - esxUtil_FreeParsedUri(&parsedUri); VIR_FREE(potentialVCenterIpAddress); return result; @@ -1061,8 +1065,6 @@ esxClose(virConnectPtr conn) esxVI_Logout(priv->host) < 0) { result = -1; } - - esxVI_Context_Free(&priv->host); } if (priv->vCenter != NULL) { @@ -1070,14 +1072,9 @@ esxClose(virConnectPtr conn) esxVI_Logout(priv->vCenter) < 0) { result = -1; } - - esxVI_Context_Free(&priv->vCenter); } - virCapabilitiesFree(priv->caps); - - VIR_FREE(priv->transport); - VIR_FREE(priv); + esxFreePrivate(&priv); conn->privateData = NULL; @@ -2627,7 +2624,7 @@ esxDomainDumpXML(virDomainPtr domain, int flags) goto cleanup; } - virBufferVSprintf(&buffer, "%s://%s:%d/folder/", priv->transport, + virBufferVSprintf(&buffer, "%s://%s:%d/folder/", priv->parsedUri->transport, domain->conn->uri->server, domain->conn->uri->port); virBufferURIEncodeString(&buffer, directoryAndFileName); virBufferAddLit(&buffer, "?dcPath="); @@ -3078,7 +3075,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml) goto cleanup; } - virBufferVSprintf(&buffer, "%s://%s:%d/folder/", priv->transport, + virBufferVSprintf(&buffer, "%s://%s:%d/folder/", priv->parsedUri->transport, conn->uri->server, conn->uri->port); if (directoryName != NULL) { @@ -3960,7 +3957,7 @@ esxIsEncrypted(virConnectPtr conn) { esxPrivate *priv = conn->privateData; - if (STRCASEEQ(priv->transport, "https")) { + if (STRCASEEQ(priv->parsedUri->transport, "https")) { return 1; } else { return 0; @@ -3974,7 +3971,7 @@ esxIsSecure(virConnectPtr conn) { esxPrivate *priv = conn->privateData; - if (STRCASEEQ(priv->transport, "https")) { + if (STRCASEEQ(priv->parsedUri->transport, "https")) { return 1; } else { return 0; diff --git a/src/esx/esx_private.h b/src/esx/esx_private.h index 6c7edb1..1da2552 100644 --- a/src/esx/esx_private.h +++ b/src/esx/esx_private.h @@ -2,7 +2,7 @@ /* * esx_private.h: private driver struct for the VMware ESX driver * - * Copyright (C) 2009-2010 Matthias Bolte + * Copyright (C) 2009-2011 Matthias Bolte * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -36,8 +36,8 @@ typedef struct _esxPrivate { esxVI_Context *primary; /* points to host or vCenter */ esxVI_Context *host; esxVI_Context *vCenter; + esxUtil_ParsedUri *parsedUri; virCapsPtr caps; - char *transport; int32_t maxVcpus; esxVI_Boolean supportsVMotion; esxVI_Boolean supportsLongMode; /* aka x86_64 */ -- 1.7.0.4 From serge.hallyn at canonical.com Sun Apr 10 22:32:56 2011 From: serge.hallyn at canonical.com (Serge Hallyn) Date: Sun, 10 Apr 2011 17:32:56 -0500 Subject: [libvirt] Paused networking on VM up/down with NAT fwd Message-ID: <20110410223256.GA21420@hallyn.com> Hi all, some time ago bug https://bugs.launchpad.net/ubuntu/maverick/+source/qemu-kvm/+bug/584048 was fixed in libvirt. It's the one where when a VM is started or stopped which has a lower macaddr than what the bridge currently has, the bridge changes macaddr and networking pauses. The fix was to make sure that a macaddr assigned by libvirt will start with 'fe:' making it higher than the physical interface. But this doesn't help when virbr0 isn't associated with any physical nic, as in the common NAT case! Is there anything we can do to help that case? thanks, -serge From veillard at redhat.com Mon Apr 11 02:16:55 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 11 Apr 2011 10:16:55 +0800 Subject: [libvirt] [PATCH] docs: remove "returns" word from beginning of lines In-Reply-To: <4D9F8CCA.5060406@redhat.com> References: <1302166064-29080-1-git-send-email-jean-baptiste.rouault@diateam.net> <4D9F8CCA.5060406@redhat.com> Message-ID: <20110411021655.GL24838@redhat.com> On Fri, Apr 08, 2011 at 04:31:38PM -0600, Eric Blake wrote: > On 04/07/2011 02:47 AM, Jean-Baptiste Rouault wrote: > > Move "returns" keyword from beginning of API doc lines > > when it does not describe return values. > > ACK, and pushed. > > > Maybe the API doc extractor could be changed to look for > > "returns: " to avoid such confusion. > > Probably, but I'm no python wizard, so I'm not writing that patch. > Anyone else want to help? I looked at it upon receiving the patch, it's trivial from a python puoint of view, the problem is that we then need to change all function descriptions to use "Returns:" instead of "Returns" and I'm not sure it's really teh right thing to do, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Mon Apr 11 02:28:26 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 11 Apr 2011 10:28:26 +0800 Subject: [libvirt] [PATCH 2/3] maxmem: implement virDomainSetMaxMemory API of the qemu driver In-Reply-To: <4D9F9CB8.5090008@redhat.com> References: <4D9E953A.4070102@jp.fujitsu.com> <4D9E983D.4070100@jp.fujitsu.com> <4D9F9CB8.5090008@redhat.com> Message-ID: <20110411022826.GM24838@redhat.com> On Fri, Apr 08, 2011 at 05:39:36PM -0600, Eric Blake wrote: > On 04/07/2011 11:08 PM, Taku Izumi wrote: > > > > This patch implements the code to support virDomainSetMaxMemory API, > > and to support VIR_DOMAIN_MEM_MAXIMUM flag in qemudDomainSetMemoryFlags function. > > As a result, we can change the maximum memory size of inactive QEMU guests. > > [...] > > +static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) { > > + return qemudDomainSetMemoryFlags(dom, memory, > > + VIR_DOMAIN_MEM_MAXIMUM | VIR_DOMAIN_MEM_LIVE); > > Hmm. Given the above implementation, this will _always_ fail. Then > again, the failure message will be nicer (the function used to fail with > "not implemented", now it fails with "cannot resize memory on an active > domain"), so I guess it's okay to provide this stub. And given the > documentation in libvirt.c, this is accurate (that documentation > explicitly stated that it only works on live domains). > > But the real clincher is how xen behaves. I just tested, and my RHEL 5 > machine with xen:/// was able to change persistent max memory of an > inactive domain, so the documentation in libvirt.c is wrong. I then Hum, how did you test this ? This sounds weird to me, maybe the xen code really improved, but basically the max memory information was used by the hypervisor (micro) kernel to allocate things like size of page tablesetc. for the gues and well that could not be changed dynamically, once the guest was started say with a max_memory of 4G you would not be able to "live" change the max_memory to 16GB and grow the guest memory to more than 4G. > tried an active domain, which (surprisingly) changed the max cap, then > promptly forgot the change when the domain went inactive again proving > that it behaved like _LIVE and not _LIVE|_CONFIG. Qemu can't change max > mem on a live domain (it's capped at qemu startup time) even if xen can, I'm still wondering about this :-) > so if we tweak the libvirt.c wording to accommodate both xen and qemu > behaviors (since it was already inaccurate for xen), then we can make > this function succeed some of the time by defaulting to > _CURRENT|_MAXIMUM instead of _LIVE|_MAXIMUM. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Mon Apr 11 02:30:26 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 11 Apr 2011 10:30:26 +0800 Subject: [libvirt] [PATCH 1/5] phyp: Remove stack allocating a 4kb volume key and fix related memory leaks In-Reply-To: <1302343151-24133-2-git-send-email-matthias.bolte@googlemail.com> References: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> <1302343151-24133-2-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110411023026.GN24838@redhat.com> On Sat, Apr 09, 2011 at 11:59:07AM +0200, Matthias Bolte wrote: > Don't pre-allocate 4kb per key, make phypVolumeGetKey allocate the memory. > > Make phypBuildVolume return the volume key instead of using pre-allocated > memory to store it. > > Also fix a memory leak in phypVolumeLookupByName when phypVolumeGetKey > fails. Fix another memory leak in phypVolumeLookupByPath in the success > path. Fix phypVolumeGetXMLDesc leaking voldef.key. > --- > src/phyp/phyp_driver.c | 98 ++++++++++++++++++++++++++--------------------- > src/phyp/phyp_driver.h | 1 - > 2 files changed, 54 insertions(+), 45 deletions(-) > > diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c > index ddbc103..bd508fb 100644 > --- a/src/phyp/phyp_driver.c > +++ b/src/phyp/phyp_driver.c > @@ -2153,8 +2153,8 @@ phypAttachDevice(virDomainPtr domain, const char *xml) > return -1; > } > > -static int > -phypVolumeGetKey(virConnectPtr conn, char *key, const char *name) > +static char * > +phypVolumeGetKey(virConnectPtr conn, const char *name) > { > ConnectionData *connection_data = conn->networkPrivateData; > phyp_driverPtr phyp_driver = conn->privateData; > @@ -2182,10 +2182,10 @@ phypVolumeGetKey(virConnectPtr conn, char *key, const char *name) > if (virBufferError(&buf)) { > virBufferFreeAndReset(&buf); > virReportOOMError(); > - return -1; > + return NULL; > } > - cmd = virBufferContentAndReset(&buf); > > + cmd = virBufferContentAndReset(&buf); > ret = phypExec(session, cmd, &exit_status, conn); > > if (exit_status < 0 || ret == NULL) > @@ -2196,17 +2196,13 @@ phypVolumeGetKey(virConnectPtr conn, char *key, const char *name) > if (char_ptr) > *char_ptr = '\0'; > > - if (memcpy(key, ret, MAX_KEY_SIZE) == NULL) > - goto err; > - > VIR_FREE(cmd); > - VIR_FREE(ret); > - return 0; > + return ret; > > err: > VIR_FREE(cmd); > VIR_FREE(ret); > - return -1; > + return NULL; > } > > static char * > @@ -2313,9 +2309,9 @@ phypGetStoragePoolSize(virConnectPtr conn, char *name) > return -1; > } > > -static int > +static char * > phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, > - unsigned int capacity, char *key) > + unsigned int capacity) > { > ConnectionData *connection_data = conn->networkPrivateData; > phyp_driverPtr phyp_driver = conn->privateData; > @@ -2327,6 +2323,7 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, > char *ret = NULL; > int exit_status = 0; > virBuffer buf = VIR_BUFFER_INITIALIZER; > + char *key; > > if (system_type == HMC) > virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", > @@ -2340,10 +2337,10 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, > if (virBufferError(&buf)) { > virBufferFreeAndReset(&buf); > virReportOOMError(); > - return -1; > + return NULL; > } > - cmd = virBufferContentAndReset(&buf); > > + cmd = virBufferContentAndReset(&buf); > ret = phypExec(session, cmd, &exit_status, conn); > > if (exit_status < 0) { > @@ -2351,29 +2348,37 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, > goto err; > } > > - if (phypVolumeGetKey(conn, key, lvname) == -1) > - goto err;; > + key = phypVolumeGetKey(conn, lvname); > + > + if (key == NULL) > + goto err; > > VIR_FREE(cmd); > VIR_FREE(ret); > - return 0; > + return key; > > err: > VIR_FREE(cmd); > VIR_FREE(ret); > - return -1; > + return NULL; > } > > static virStorageVolPtr > phypVolumeLookupByName(virStoragePoolPtr pool, const char *volname) > { > + char *key; > + virStorageVolPtr vol; > > - char key[MAX_KEY_SIZE]; > + key = phypVolumeGetKey(pool->conn, volname); > > - if (phypVolumeGetKey(pool->conn, key, volname) == -1) > + if (key == NULL) > return NULL; > > - return virGetStorageVol(pool->conn, pool->name, volname, key); > + vol = virGetStorageVol(pool->conn, pool->name, volname, key); > + > + VIR_FREE(key); > + > + return vol; > } > > static virStorageVolPtr > @@ -2392,11 +2397,6 @@ phypStorageVolCreateXML(virStoragePoolPtr pool, > return NULL; > } > > - if (VIR_ALLOC_N(key, MAX_KEY_SIZE) < 0) { > - virReportOOMError(); > - return NULL; > - } > - > /* Filling spdef manually > * */ > if (pool->name != NULL) { > @@ -2454,9 +2454,10 @@ phypStorageVolCreateXML(virStoragePoolPtr pool, > goto err; > } > > - if (phypBuildVolume > - (pool->conn, voldef->name, spdef->name, voldef->capacity, > - key) == -1) > + key = phypBuildVolume(pool->conn, voldef->name, spdef->name, > + voldef->capacity); > + > + if (key == NULL) > goto err; > > if ((vol = > @@ -2464,9 +2465,12 @@ phypStorageVolCreateXML(virStoragePoolPtr pool, > key)) == NULL) > goto err; > > + VIR_FREE(key); > + > return vol; > > err: > + VIR_FREE(key); > virStorageVolDefFree(voldef); > virStoragePoolDefFree(spdef); > if (vol) > @@ -2540,8 +2544,10 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) > int exit_status = 0; > char *cmd = NULL; > char *spname = NULL; > + char *char_ptr; > char *key = NULL; > virBuffer buf = VIR_BUFFER_INITIALIZER; > + virStorageVolPtr vol; > > if (system_type == HMC) > virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", > @@ -2566,20 +2572,21 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) > if (exit_status < 0 || spname == NULL) > return NULL; > > - char *char_ptr = strchr(spname, '\n'); > + char_ptr = strchr(spname, '\n'); > > if (char_ptr) > *char_ptr = '\0'; > > - if (VIR_ALLOC_N(key, MAX_KEY_SIZE) < 0) { > - virReportOOMError(); > - return NULL; > - } > + key = phypVolumeGetKey(conn, volname); > > - if (phypVolumeGetKey(conn, key, volname) == -1) > + if (key == NULL) > return NULL; > > - return virGetStorageVol(conn, spname, volname, key); > + vol = virGetStorageVol(conn, spname, volname, key); > + > + VIR_FREE(key); > + > + return vol; > } > > static int > @@ -2647,6 +2654,8 @@ phypStoragePoolLookupByName(virConnectPtr conn, const char *name) > static char * > phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags) > { > + char *xml; > + > virCheckFlags(0, NULL); > > virStorageVolDef voldef; > @@ -2661,11 +2670,6 @@ phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags) > virStoragePoolDef pool; > memset(&pool, 0, sizeof(virStoragePoolDef)); > > - if (VIR_ALLOC_N(voldef.key, MAX_KEY_SIZE) < 0) { > - virReportOOMError(); > - return NULL; > - } > - > if (sp->name != NULL) { > pool.name = sp->name; > } else { > @@ -2702,14 +2706,20 @@ phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags) > goto err; > } > > - if (memmove(voldef.key, vol->key, PATH_MAX) == NULL) { > - VIR_ERROR0(_("Unable to determine volume's key.")); > + voldef.key = strdup(vol->key); > + > + if (voldef.key == NULL) { > + virReportOOMError(); > goto err; > } > > voldef.type = VIR_STORAGE_POOL_LOGICAL; > > - return virStorageVolDefFormat(&pool, &voldef); > + xml = virStorageVolDefFormat(&pool, &voldef); > + > + VIR_FREE(voldef.key); > + > + return xml; > > err: > return NULL; > diff --git a/src/phyp/phyp_driver.h b/src/phyp/phyp_driver.h > index bc8e003..a22156c 100644 > --- a/src/phyp/phyp_driver.h > +++ b/src/phyp/phyp_driver.h > @@ -30,7 +30,6 @@ > # include > # include > > -# define MAX_KEY_SIZE (1024*4) > # define LPAR_EXEC_ERR -1 > # define SSH_CONN_ERR -2 /* error while trying to connect to remote host */ > # define SSH_CMD_ERR -3 /* error while trying to execute the remote cmd */ ACK, way nicer ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Mon Apr 11 03:01:58 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 11 Apr 2011 11:01:58 +0800 Subject: [libvirt] [PATCH 2/5] phyp: Reduce code duplication in error and success paths In-Reply-To: <1302343151-24133-3-git-send-email-matthias.bolte@googlemail.com> References: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> <1302343151-24133-3-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110411030158.GO24838@redhat.com> On Sat, Apr 09, 2011 at 11:59:08AM +0200, Matthias Bolte wrote: > Also fix memory leaks along the way in phypCreateServerSCSIAdapter and > phypAttachDevice. > --- > src/phyp/phyp_driver.c | 592 +++++++++++++++++++++++------------------------- > 1 files changed, 289 insertions(+), 303 deletions(-) Long, makes for simpler and more maintainable code, ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Mon Apr 11 03:03:08 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 11 Apr 2011 11:03:08 +0800 Subject: [libvirt] [PATCH 3/5] phyp: Don't try to use a string from a failed virAsprintf In-Reply-To: <1302343151-24133-4-git-send-email-matthias.bolte@googlemail.com> References: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> <1302343151-24133-4-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110411030308.GP24838@redhat.com> On Sat, Apr 09, 2011 at 11:59:09AM +0200, Matthias Bolte wrote: > --- > src/phyp/phyp_driver.c | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c > index f441261..24165fb 100644 > --- a/src/phyp/phyp_driver.c > +++ b/src/phyp/phyp_driver.c > @@ -210,7 +210,7 @@ phypGetSystemType(virConnectPtr conn) > > if (virAsprintf(&cmd, "lshmc -V") < 0) { > virReportOOMError(); > - exit_status = -1; > + return -1; > } > ret = phypExec(session, cmd, &exit_status, conn); > ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Mon Apr 11 03:06:03 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 11 Apr 2011 11:06:03 +0800 Subject: [libvirt] [PATCH 4/5] phyp: Fix too small buffer allocation in phypAttachDevice In-Reply-To: <1302343151-24133-5-git-send-email-matthias.bolte@googlemail.com> References: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> <1302343151-24133-5-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110411030603.GQ24838@redhat.com> On Sat, Apr 09, 2011 at 11:59:10AM +0200, Matthias Bolte wrote: > sizeof(domain->name) is the wrong thing. Instead of using strdup here > rewrite escape_specialcharacters to allocate the buffer itself. > > Add a contains_specialcharacters to be used in phypOpen, as phypOpen is > not interested in the escaped version. > --- > src/phyp/phyp_driver.c | 90 ++++++++++++++++++++++++++++++++--------------- > 1 files changed, 61 insertions(+), 29 deletions(-) > > diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c > index 24165fb..226946d 100644 > --- a/src/phyp/phyp_driver.c > +++ b/src/phyp/phyp_driver.c > @@ -891,14 +891,63 @@ phypUUIDTable_Free(uuid_tablePtr uuid_table) > VIR_FREE(uuid_table); > } > > -static int > -escape_specialcharacters(char *src, char *dst, size_t dstlen) > +static bool > +contains_specialcharacters(const char *src) > { > size_t len = strlen(src); > - char temp_buffer[len]; > - unsigned int i = 0, j = 0; > + size_t i = 0; > + > if (len == 0) > - return -1; > + return false; > + > + for (i = 0; i < len; i++) { > + switch (src[i]) { > + case '&': > + case ';': > + case '`': > + case '@': > + case '"': > + case '|': > + case '*': > + case '?': > + case '~': > + case '<': > + case '>': > + case '^': > + case '(': > + case ')': > + case '[': > + case ']': > + case '{': > + case '}': > + case '$': > + case '%': > + case '#': > + case '\\': > + case '\n': > + case '\r': > + case '\t': > + return true; > + } > + } > + > + return false; > +} > + > +static char * > +escape_specialcharacters(const char *src) > +{ > + size_t len = strlen(src); > + size_t i = 0, j = 0; > + char *dst; > + > + if (len == 0) > + return NULL; > + > + if (VIR_ALLOC_N(dst, len + 1) < 0) { > + virReportOOMError(); > + return NULL; > + } > > for (i = 0; i < len; i++) { > switch (src[i]) { > @@ -929,16 +978,14 @@ escape_specialcharacters(char *src, char *dst, size_t dstlen) > case '\t': > continue; > default: > - temp_buffer[j] = src[i]; > + dst[j] = src[i]; > j++; > } > } > - temp_buffer[j] = '\0'; > > - if (virStrcpy(dst, temp_buffer, dstlen) == NULL) > - return -1; > + dst[j] = '\0'; > > - return 0; > + return dst; > } > > static LIBSSH2_SESSION * > @@ -1121,8 +1168,6 @@ phypOpen(virConnectPtr conn, > { > LIBSSH2_SESSION *session = NULL; > ConnectionData *connection_data = NULL; > - char *string = NULL; > - size_t len = 0; > int internal_socket; > uuid_tablePtr uuid_table = NULL; > phyp_driverPtr phyp_driver = NULL; > @@ -1157,13 +1202,6 @@ phypOpen(virConnectPtr conn, > } > > if (conn->uri->path) { > - len = strlen(conn->uri->path) + 1; > - > - if (VIR_ALLOC_N(string, len) < 0) { > - virReportOOMError(); > - goto failure; > - } > - > /* need to shift one byte in order to remove the first "/" of URI component */ > if (conn->uri->path[0] == '/') > managed_system = strdup(conn->uri->path + 1); > @@ -1183,7 +1221,7 @@ phypOpen(virConnectPtr conn, > if (char_ptr) > *char_ptr = '\0'; > > - if (escape_specialcharacters(conn->uri->path, string, len) == -1) { > + if (contains_specialcharacters(conn->uri->path)) { > PHYP_ERROR(VIR_ERR_INTERNAL_ERROR, > "%s", > _("Error parsing 'path'. Invalid characters.")); > @@ -1242,7 +1280,6 @@ phypOpen(virConnectPtr conn, > } > > VIR_FREE(connection_data); > - VIR_FREE(string); > > return VIR_DRV_OPEN_ERROR; > } > @@ -1947,15 +1984,10 @@ phypAttachDevice(virDomainPtr domain, const char *xml) > virBuffer buf = VIR_BUFFER_INITIALIZER; > char *domain_name = NULL; > > - if (VIR_ALLOC_N(domain_name, sizeof(domain->name)) < 0) { > - virReportOOMError(); > - goto err; > - } > + domain_name = escape_specialcharacters(domain->name); > > - if (escape_specialcharacters > - (domain->name, domain_name, strlen(domain->name)) == -1) { > - virReportOOMError(); > - goto err; > + if (domain_name == NULL) { > + goto cleanup; > } > > def->os.type = strdup("aix"); ACK, we just need to make sure contains_specialcharacters() and escape_specialcharacters() don't diverge on the charater set. Maybe add a comment in escape_specialcharacters() to this effect. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Mon Apr 11 03:06:29 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 11 Apr 2011 11:06:29 +0800 Subject: [libvirt] [PATCH 5/5] phyp: Don't overwrite error from virDomainDeviceDefParse by OOM error In-Reply-To: <1302343151-24133-6-git-send-email-matthias.bolte@googlemail.com> References: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> <1302343151-24133-6-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110411030629.GR24838@redhat.com> On Sat, Apr 09, 2011 at 11:59:11AM +0200, Matthias Bolte wrote: > --- > src/phyp/phyp_driver.c | 1 - > 1 files changed, 0 insertions(+), 1 deletions(-) > > diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c > index 226946d..f36b357 100644 > --- a/src/phyp/phyp_driver.c > +++ b/src/phyp/phyp_driver.c > @@ -2000,7 +2000,6 @@ phypAttachDevice(virDomainPtr domain, const char *xml) > dev = virDomainDeviceDefParse(phyp_driver->caps, def, xml, > VIR_DOMAIN_XML_INACTIVE); > if (!dev) { > - virReportOOMError(); > goto cleanup; > } > ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Mon Apr 11 03:09:11 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 11 Apr 2011 11:09:11 +0800 Subject: [libvirt] [PATCH] migrate VMs between different-endian hosts In-Reply-To: <4DA07FD9.8000606@linux.vnet.ibm.com> References: <4DA07FD9.8000606@linux.vnet.ibm.com> Message-ID: <20110411030911.GS24838@redhat.com> On Sat, Apr 09, 2011 at 11:48:41AM -0400, Stefan Berger wrote: > This patch enables the migration of Qemu VMs between hosts of > different endianess. I tested this by migrating a i686 VM between a > x86 and ppc64 host. OMG, there is really a use case for this :-) ? > I am converting the 'int's in the VM's state header to uint32_t > assuming this doesn't break compatibility with existing deployments > other than Linux. > > Signed-off-by: Stefan Berger > > --- > src/qemu/qemu_driver.c | 25 ++++++++++++++++++++----- > 1 file changed, 20 insertions(+), 5 deletions(-) > > Index: libvirt-acl/src/qemu/qemu_driver.c > =================================================================== > --- libvirt-acl.orig/src/qemu/qemu_driver.c > +++ libvirt-acl/src/qemu/qemu_driver.c > @@ -43,6 +43,7 @@ > #include > #include > #include > +#include > > > #include "qemu_driver.h" > @@ -1881,13 +1882,22 @@ VIR_ENUM_IMPL(qemudSaveCompression, QEMU > > struct qemud_save_header { > char magic[sizeof(QEMUD_SAVE_MAGIC)-1]; > - int version; > - int xml_len; > - int was_running; > - int compressed; > - int unused[15]; > + uint32_t version; > + uint32_t xml_len; > + uint32_t was_running; > + uint32_t compressed; > + uint32_t unused[15]; > }; > > +static inline void > +bswap_header(struct qemud_save_header *hdr) { > + hdr->version = bswap_32(hdr->version); > + hdr->xml_len = bswap_32(hdr->xml_len); > + hdr->was_running = bswap_32(hdr->was_running); > + hdr->compressed = bswap_32(hdr->compressed); > +} > + > + > /* return -errno on failure, or 0 on success */ > static int > qemuDomainSaveHeader(int fd, const char *path, char *xml, > @@ -3097,6 +3107,11 @@ qemuDomainSaveImageOpen(struct qemud_dri > } > > if (header.version > QEMUD_SAVE_VERSION) { > + /* convert endianess and try again */ > + bswap_header(&header); > + } Hum, isn't there a more reliable way to detect the change of endianness ? That's a bit fishy IMHO :-) > + if (header.version > QEMUD_SAVE_VERSION) { > qemuReportError(VIR_ERR_OPERATION_FAILED, > _("image version is not supported (%d > %d)"), > header.version, QEMUD_SAVE_VERSION); Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Mon Apr 11 03:12:30 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 11 Apr 2011 11:12:30 +0800 Subject: [libvirt] [PATCH] docs: document freecell --all In-Reply-To: <1302110917-10123-1-git-send-email-eblake@redhat.com> References: <1302110917-10123-1-git-send-email-eblake@redhat.com> Message-ID: <20110411031230.GA32376@redhat.com> On Wed, Apr 06, 2011 at 11:28:37AM -0600, Eric Blake wrote: > Based on a smaller patch developed by Moritoshi Oshiro: > https://bugzilla.redhat.com/show_bug.cgi?id=693963 > > * tools/virsh.pod (freecell): Mention all, and clarify that > optional cellno requires --cellno. > --- > > I think this is the first case where virsh.pod is trying to convey > mutually exclusive options; does the resulting layout look > reasonable? I applied and checked with man, looks fine to me, ACK, daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From wency at cn.fujitsu.com Mon Apr 11 05:41:55 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Mon, 11 Apr 2011 13:41:55 +0800 Subject: [libvirt] [RFC PATCH] check whether domain is active after qemuDomainObjExitMonitor* returns In-Reply-To: <4D94CDCA.50801@redhat.com> References: <4D91B1BF.6050106@cn.fujitsu.com> <4D938B96.8090503@redhat.com> <4D94224D.70905@cn.fujitsu.com> <4D94CDCA.50801@redhat.com> Message-ID: <4DA294A3.3090902@cn.fujitsu.com> qemu may quited unexpectedly when invoking a monitor command. And priv->mon will be NULL after qemuDomainObjExitMonitor* returns. So we must not use it. Unfortunately we still use it, and it will cause libvirtd crashed. As Eric suggested, qemuDomainObjExitMonitor* should be made to return the value of vm active after regaining lock, and marked ATTRIBUTE_RETURN_CHECK, to force all other callers to detect the case of a monitor command completing successfully but then the VM disappearing in the window between command completion and regaining the vm lock. --- src/qemu/qemu_domain.c | 24 ++++- src/qemu/qemu_domain.h | 6 +- src/qemu/qemu_driver.c | 87 +++++++++++++---- src/qemu/qemu_hotplug.c | 230 ++++++++++++++++++++++++++++----------------- src/qemu/qemu_migration.c | 93 +++++++++++++------ src/qemu/qemu_process.c | 61 +++++++++--- 6 files changed, 344 insertions(+), 157 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index c2a1f9a..0d40b7e 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -578,7 +578,7 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) * * Should be paired with an earlier qemuDomainObjEnterMonitor() call */ -void qemuDomainObjExitMonitor(virDomainObjPtr obj) +int qemuDomainObjExitMonitor(virDomainObjPtr obj) { qemuDomainObjPrivatePtr priv = obj->privateData; int refs; @@ -588,11 +588,20 @@ void qemuDomainObjExitMonitor(virDomainObjPtr obj) if (refs > 0) qemuMonitorUnlock(priv->mon); + /* Note: qemu may quited unexpectedly here, and the monitor will be freed. + * If it happened, priv->mon will be null. + */ + virDomainObjLock(obj); if (refs == 0) { priv->mon = NULL; } + + if (priv->mon == NULL) + return -1; + else + return 0; } @@ -621,8 +630,8 @@ void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, * * Should be paired with an earlier qemuDomainObjEnterMonitorWithDriver() call */ -void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, - virDomainObjPtr obj) +int qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, + virDomainObjPtr obj) { qemuDomainObjPrivatePtr priv = obj->privateData; int refs; @@ -632,12 +641,21 @@ void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, if (refs > 0) qemuMonitorUnlock(priv->mon); + /* Note: qemu may quited unexpectedly here, and the monitor will be freed. + * If it happened, priv->mon will be null. + */ + qemuDriverLock(driver); virDomainObjLock(obj); if (refs == 0) { priv->mon = NULL; } + + if (priv->mon == NULL) + return -1; + else + return 0; } void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 8258900..92fccda 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -99,11 +99,11 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; int qemuDomainObjEndJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; void qemuDomainObjEnterMonitor(virDomainObjPtr obj); -void qemuDomainObjExitMonitor(virDomainObjPtr obj); +int qemuDomainObjExitMonitor(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, virDomainObjPtr obj); -void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, - virDomainObjPtr obj); +int qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, + virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver, virDomainObjPtr obj); void qemuDomainObjExitRemoteWithDriver(struct qemud_driver *driver, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 04a5f65..2d41576 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1452,7 +1452,11 @@ static int qemudDomainShutdown(virDomainPtr dom) { priv = vm->privateData; qemuDomainObjEnterMonitor(vm); ret = qemuMonitorSystemPowerdown(priv->mon); - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } endjob: if (qemuDomainObjEndJob(vm) == 0) @@ -1659,7 +1663,11 @@ static int qemudDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, priv = vm->privateData; qemuDomainObjEnterMonitor(vm); r = qemuMonitorSetBalloon(priv->mon, newmem); - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + r = -1; + } qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", r == 1); if (r < 0) @@ -1749,7 +1757,11 @@ static int qemudDomainGetInfo(virDomainPtr dom, else { qemuDomainObjEnterMonitor(vm); err = qemuMonitorGetBalloonInfo(priv->mon, &balloon); - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + err = -1; + } } if (qemuDomainObjEndJob(vm) == 0) { vm = NULL; @@ -2524,7 +2536,11 @@ static int qemudDomainHotplugVcpus(virDomainObjPtr vm, unsigned int nvcpus) ret = 0; cleanup: - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } vm->def->vcpus = vcpus; qemuAuditVcpu(vm, oldvcpus, nvcpus, "update", rc == 1); return ret; @@ -3295,7 +3311,11 @@ static char *qemudDomainDumpXML(virDomainPtr dom, qemuDomainObjEnterMonitorWithDriver(driver, vm); err = qemuMonitorGetBalloonInfo(priv->mon, &balloon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + err = -1; + } if (qemuDomainObjEndJob(vm) == 0) { vm = NULL; goto cleanup; @@ -4843,7 +4863,11 @@ qemudDomainBlockStats (virDomainPtr dom, &stats->wr_req, &stats->wr_bytes, &stats->errs); - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } endjob: if (qemuDomainObjEndJob(vm) == 0) @@ -4944,7 +4968,11 @@ qemudDomainMemoryStats (virDomainPtr dom, qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjEnterMonitor(vm); ret = qemuMonitorGetMemoryStats(priv->mon, stats, nr_stats); - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } } else { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -5085,17 +5113,18 @@ qemudDomainMemoryPeek (virDomainPtr dom, priv = vm->privateData; qemuDomainObjEnterMonitor(vm); if (flags == VIR_MEMORY_VIRTUAL) { - if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) { - qemuDomainObjExitMonitor(vm); - goto endjob; - } + ret = qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp); } else { - if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) { - qemuDomainObjExitMonitor(vm); - goto endjob; - } + ret = qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp); } - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } + + if (ret < -1) + goto endjob; /* Read the memory file into buffer. */ if (saferead (fd, buffer, size) == (ssize_t) -1) { @@ -5259,7 +5288,11 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom, ret = qemuMonitorGetBlockExtent(priv->mon, disk->info.alias, &info->allocation); - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } } if (qemuDomainObjEndJob(vm) == 0) @@ -6101,7 +6134,11 @@ qemuDomainSnapshotCreateActive(virConnectPtr conn, qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } cleanup: if (resume && virDomainObjIsActive(vm) && @@ -6434,7 +6471,11 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, priv = vm->privateData; qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorLoadSnapshot(priv->mon, snap->def->name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + rc = -1; + } if (rc < 0) goto endjob; } @@ -6557,7 +6598,7 @@ static int qemuDomainSnapshotDiscard(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); /* we continue on even in the face of error */ qemuMonitorDeleteSnapshot(priv->mon, snap->def->name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + ignore_value(qemuDomainObjExitMonitorWithDriver(driver, vm)); } if (snap == vm->current_snapshot) { @@ -6770,7 +6811,11 @@ static int qemuDomainMonitorCommand(virDomainPtr domain, const char *cmd, goto cleanup; qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } if (qemuDomainObjEndJob(vm) == 0) { vm = NULL; goto cleanup; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index b03f774..d70e426 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -106,7 +106,11 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver, } else { ret = qemuMonitorEjectMedia(priv->mon, driveAlias, force); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } qemuAuditDisk(vm, origdisk, disk, "update", ret >= 0); @@ -201,7 +205,11 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver, memcpy(&disk->info.addr.pci, &guestAddr, sizeof(guestAddr)); } } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } qemuAuditDisk(vm, NULL, disk, "attach", ret >= 0); @@ -277,7 +285,11 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver, type, &controller->info.addr.pci); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } if (ret == 0) { controller->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; @@ -433,7 +445,11 @@ int qemuDomainAttachSCSIDisk(struct qemud_driver *driver, memcpy(&disk->info.addr.drive, &driveAddr, sizeof(driveAddr)); } } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } qemuAuditDisk(vm, NULL, disk, "attach", ret >= 0); @@ -516,7 +532,11 @@ int qemuDomainAttachUsbMassstorageDevice(struct qemud_driver *driver, } else { ret = qemuMonitorAddUSBDisk(priv->mon, disk->src); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } qemuAuditDisk(vm, NULL, disk, "attach", ret >= 0); @@ -632,21 +652,22 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) && qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorAddNetdev(priv->mon, netstr, tapfd, tapfd_name, - vhostfd, vhostfd_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, NULL, net, "attach", false); - goto cleanup; - } + ret = qemuMonitorAddNetdev(priv->mon, netstr, tapfd, tapfd_name, + vhostfd, vhostfd_name); } else { - if (qemuMonitorAddHostNetwork(priv->mon, netstr, tapfd, tapfd_name, - vhostfd, vhostfd_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, NULL, net, "attach", false); - goto cleanup; - } + ret = qemuMonitorAddHostNetwork(priv->mon, netstr, tapfd, tapfd_name, + vhostfd, vhostfd_name); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + goto cleanup; + } + + qemuAuditNet(vm, NULL, net, "attach", ret >= 0); + + if (ret < 0) + goto cleanup; VIR_FORCE_CLOSE(tapfd); VIR_FORCE_CLOSE(vhostfd); @@ -667,25 +688,26 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorAddDevice(priv->mon, nicstr) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, NULL, net, "attach", false); - goto try_remove; - } + ret = qemuMonitorAddDevice(priv->mon, nicstr); } else { - if (qemuMonitorAddPCINetwork(priv->mon, nicstr, - &guestAddr) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, NULL, net, "attach", false); - goto try_remove; + ret = qemuMonitorAddPCINetwork(priv->mon, nicstr, + &guestAddr); + if (ret == 0) { + net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; + memcpy(&net->info.addr.pci, &guestAddr, sizeof(guestAddr)); } - net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; - memcpy(&net->info.addr.pci, &guestAddr, sizeof(guestAddr)); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } qemuAuditNet(vm, NULL, net, "attach", true); + if (ret < 0) + goto try_remove; + ret = 0; vm->def->nets[vm->def->nnets++] = net; @@ -723,7 +745,9 @@ try_remove: if (qemuMonitorRemoveNetdev(priv->mon, netdev_name) < 0) VIR_WARN("Failed to remove network backend for netdev %s", netdev_name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); VIR_FREE(netdev_name); } else { VIR_WARN0("Unable to remove network backend"); @@ -736,7 +760,9 @@ try_remove: if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) VIR_WARN("Failed to remove network backend for vlan %d, net %s", vlan, hostnet_name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); VIR_FREE(hostnet_name); } goto cleanup; @@ -795,7 +821,11 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr, configfd, configfd_name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + goto error; + } } else { virDomainDevicePCIAddress guestAddr; @@ -803,7 +833,11 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, ret = qemuMonitorAddPCIHostDevice(priv->mon, &hostdev->source.subsys.u.pci, &guestAddr); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + goto error; + } hostdev->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; memcpy(&hostdev->info.addr.pci, &guestAddr, sizeof(guestAddr)); @@ -886,7 +920,11 @@ int qemuDomainAttachHostUsbDevice(struct qemud_driver *driver, ret = qemuMonitorAddUSBDeviceExact(priv->mon, hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } qemuAuditHostdev(vm, hostdev, "attach", ret == 0); if (ret < 0) goto error; @@ -1145,25 +1183,27 @@ int qemuDomainDetachPciDiskDevice(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { - qemuDomainObjExitMonitor(vm); - goto cleanup; - } + ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); } else { - if (qemuMonitorRemovePCIDevice(priv->mon, - &detach->info.addr.pci) < 0) { - qemuDomainObjExitMonitor(vm); - goto cleanup; - } + ret = qemuMonitorRemovePCIDevice(priv->mon, + &detach->info.addr.pci); } /* disconnect guest from host device */ - qemuMonitorDriveDel(priv->mon, drivestr); + if (ret == 0) + qemuMonitorDriveDel(priv->mon, drivestr); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitor(vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } qemuAuditDisk(vm, detach, NULL, "detach", ret >= 0); + if (ret < 0) + goto cleanup; + if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0) VIR_WARN("Unable to release PCI address on %s", dev->data.disk->src); @@ -1235,18 +1275,23 @@ int qemuDomainDetachDiskDevice(struct qemud_driver *driver, } qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { - qemuDomainObjExitMonitor(vm); - goto cleanup; - } + ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); /* disconnect guest from host device */ - qemuMonitorDriveDel(priv->mon, drivestr); + if (ret == 0) + qemuMonitorDriveDel(priv->mon, drivestr); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } qemuAuditDisk(vm, detach, NULL, "detach", ret >= 0); + if (ret < 0) + goto cleanup; + virDomainDiskRemove(vm->def, i); virDomainDiskDefFree(detach); @@ -1364,18 +1409,19 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) { - qemuDomainObjExitMonitor(vm); - goto cleanup; - } + ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); } else { - if (qemuMonitorRemovePCIDevice(priv->mon, - &detach->info.addr.pci) < 0) { - qemuDomainObjExitMonitor(vm); - goto cleanup; - } + ret = qemuMonitorRemovePCIDevice(priv->mon, + &detach->info.addr.pci); + } + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; } - qemuDomainObjExitMonitorWithDriver(driver, vm); + + if (ret < 0) + goto cleanup; if (vm->def->ncontrollers > 1) { memmove(vm->def->controllers + i, @@ -1452,35 +1498,31 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { - qemuDomainObjExitMonitor(vm); - qemuAuditNet(vm, detach, NULL, "detach", false); - goto cleanup; - } + ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); } else { - if (qemuMonitorRemovePCIDevice(priv->mon, - &detach->info.addr.pci) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, detach, NULL, "detach", false); - goto cleanup; - } + ret = qemuMonitorRemovePCIDevice(priv->mon, + &detach->info.addr.pci); } + if (ret < 0) + goto exitmonitor; + if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) && qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, detach, NULL, "detach", false); - goto cleanup; - } + ret = qemuMonitorRemoveNetdev(priv->mon, hostnet_name); } else { - if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, detach, NULL, "detach", false); - goto cleanup; - } + ret = qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + +exitmonitor: + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } + + if (ret < 0) + goto cleanup; qemuAuditNet(vm, detach, NULL, "detach", true); @@ -1582,7 +1624,11 @@ int qemuDomainDetachHostPciDevice(struct qemud_driver *driver, } else { ret = qemuMonitorRemovePCIDevice(priv->mon, &detach->info.addr.pci); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } qemuAuditHostdev(vm, detach, "detach", ret == 0); if (ret < 0) return -1; @@ -1681,7 +1727,11 @@ int qemuDomainDetachHostUsbDevice(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } qemuAuditHostdev(vm, detach, "detach", ret == 0); if (ret < 0) return -1; @@ -1798,7 +1848,11 @@ qemuDomainChangeGraphicsPasswords(struct qemud_driver *driver, } cleanup: - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } return ret; } diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 43741e1..cc8f428 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -125,7 +125,11 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) VIR_DEBUG0("Cancelling job at client request"); qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorMigrateCancel(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + rc = -1; + } if (rc < 0) { VIR_WARN0("Unable to cancel job"); } @@ -142,7 +146,11 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) VIR_DEBUG("Setting migration downtime to %llums", ms); qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorSetMigrationDowntime(priv->mon, ms); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + rc = -1; + } if (rc < 0) VIR_WARN0("Unable to set migration downtime"); } else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_SPEED) { @@ -153,7 +161,11 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth); qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + rc = -1; + } if (rc < 0) VIR_WARN0("Unable to set migration speed"); } @@ -173,7 +185,11 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) &memProcessed, &memRemaining, &memTotal); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + rc = -1; + } if (rc < 0) { priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; @@ -608,24 +624,31 @@ static int doNativeMigrate(struct qemud_driver *driver, } qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (resource > 0 && - qemuMonitorSetMigrationSpeed(priv->mon, resource) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cleanup; + if (resource > 0) { + ret = qemuMonitorSetMigrationSpeed(priv->mon, resource); } + if (ret < 0) + goto exitmonitor; + if (flags & VIR_MIGRATE_NON_SHARED_DISK) background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK; if (flags & VIR_MIGRATE_NON_SHARED_INC) background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_INC; - if (qemuMonitorMigrateToHost(priv->mon, background_flags, uribits->server, - uribits->port) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cleanup; + ret = qemuMonitorMigrateToHost(priv->mon, background_flags, uribits->server, + uribits->port); + +exitmonitor: + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; } - qemuDomainObjExitMonitorWithDriver(driver, vm); + + if (ret < 0) + goto cleanup; if (qemuMigrationWaitForCompletion(driver, vm) < 0) goto cleanup; @@ -824,7 +847,11 @@ static int doTunnelMigrate(struct qemud_driver *driver, } else { internalret = -1; } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + internalret = -1; + } if (internalret < 0) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("tunnelled migration monitor command failed")); @@ -844,15 +871,16 @@ static int doTunnelMigrate(struct qemud_driver *driver, * rather failed later on. Check the output of "info migrate" */ qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorGetMigrationStatus(priv->mon, - &status, - &transferred, - &remaining, - &total) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cancel; + retval = qemuMonitorGetMigrationStatus(priv->mon, + &status, + &transferred, + &remaining, + &total); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + retval = -1; } - qemuDomainObjExitMonitorWithDriver(driver, vm); if (status == QEMU_MONITOR_MIGRATION_STATUS_ERROR) { qemuReportError(VIR_ERR_OPERATION_FAILED, @@ -875,7 +903,10 @@ cancel: if (retval != 0 && virDomainObjIsActive(vm)) { qemuDomainObjEnterMonitorWithDriver(driver, vm); qemuMonitorMigrateCancel(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + } } finish: @@ -1372,12 +1403,12 @@ qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm, if (virSetCloseExec(pipeFD[1]) < 0) { virReportSystemError(errno, "%s", _("Unable to set cloexec flag")); - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cleanup; + rc = -1; + goto exitmonitor; } if (virCommandRunAsync(cmd, NULL) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cleanup; + rc = -1; + goto exitmonitor; } rc = qemuMonitorMigrateToFd(priv->mon, QEMU_MONITOR_MIGRATE_BACKGROUND, @@ -1391,7 +1422,13 @@ qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm, args, path, offset); } } - qemuDomainObjExitMonitorWithDriver(driver, vm); + +exitmonitor: + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + rc = -1; + } if (rc < 0) goto cleanup; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 9ada24d..4ca70bc 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -662,7 +662,11 @@ qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm) qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorSetCapabilities(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } error: @@ -1070,7 +1074,11 @@ qemuProcessWaitForMonitor(struct qemud_driver* driver, priv = vm->privateData; qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorGetPtyPaths(priv->mon, paths); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } VIR_DEBUG("qemuMonitorGetPtyPaths returned %i", ret); if (ret == 0) @@ -1122,11 +1130,15 @@ qemuProcessDetectVcpuPIDs(struct qemud_driver *driver, /* What follows is now all KVM specific */ qemuDomainObjEnterMonitorWithDriver(driver, vm); - if ((ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids)) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - return -1; + ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ncpupids = -1; } - qemuDomainObjExitMonitorWithDriver(driver, vm); + + if (ncpupids < 0) + return -1; /* Treat failure to get VCPU<->PID mapping as non-fatal */ if (ncpupids == 0) @@ -1322,7 +1334,11 @@ qemuProcessInitPasswords(virConnectPtr conn, qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorSetDrivePassphrase(priv->mon, alias, secret); VIR_FREE(secret); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } if (ret < 0) goto cleanup; } @@ -1713,7 +1729,12 @@ qemuProcessInitPCIAddresses(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); naddrs = qemuMonitorGetAllPCIAddresses(priv->mon, &addrs); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + VIR_FREE(addrs); + return -1; + } ret = qemuProcessDetectPCIAddresses(vm, addrs, naddrs); @@ -1890,7 +1911,11 @@ qemuProcessStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm, qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorStartCPUs(priv->mon, conn); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } if (ret == 0) { vm->state = VIR_DOMAIN_RUNNING; } @@ -1908,7 +1933,11 @@ int qemuProcessStopCPUs(struct qemud_driver *driver, virDomainObjPtr vm) vm->state = VIR_DOMAIN_PAUSED; qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorStopCPUs(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; + } if (ret < 0) { vm->state = oldState; } @@ -2389,11 +2418,15 @@ int qemuProcessStart(virConnectPtr conn, VIR_DEBUG0("Setting initial memory amount"); cur_balloon = vm->def->mem.cur_balloon; qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorSetBalloon(priv->mon, cur_balloon) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cleanup; + ret = qemuMonitorSetBalloon(priv->mon, cur_balloon); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + ret = -1; } - qemuDomainObjExitMonitorWithDriver(driver, vm); + + if (ret < 0) + goto cleanup; if (!start_paused) { VIR_DEBUG0("Starting domain CPUs"); -- 1.7.1 From izumi.taku at jp.fujitsu.com Mon Apr 11 05:56:59 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Mon, 11 Apr 2011 14:56:59 +0900 Subject: [libvirt] [PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) In-Reply-To: <4D9E9B1F.1040500@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> <4D9E9B1F.1040500@jp.fujitsu.com> Message-ID: <4DA2982B.5040406@jp.fujitsu.com> Wen-san, Hu-san, Osier-san, Thank you for reviewing. I'll update this. to Wen-san, >> + >> > + if (flags & ~(VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) { >> > + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); >> > + virDispatchError(NULL); >> > + return -1; >> > + } > Why we check the flags here? We can check it in hypervisor's implementation. > We can't use this API with flags except VIR_DOMAIN_VCPU_LIVE or VIR_DOMAIN_VCPU_CONFIG. I think validation should be done here. >> + if (conn->driver->domainPinVcpuFlags) { >> > + int ret; >> > + ret = conn->driver->domainPinVcpuFlags (domain, vcpu, cpumap, maplen, flags); > There is no need to add space between 'domainPinVcpuFlags' and '(domain', it is old coding > style. > I intentionally did because such a style is adopted in a lot of other places where drivers' function are invoked. Best regards, Taku Izumi From wency at cn.fujitsu.com Mon Apr 11 06:20:18 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Mon, 11 Apr 2011 14:20:18 +0800 Subject: [libvirt] [PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) In-Reply-To: <4DA2982B.5040406@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> <4D9E9B1F.1040500@jp.fujitsu.com> <4DA2982B.5040406@jp.fujitsu.com> Message-ID: <4DA29DA2.5000406@cn.fujitsu.com> At 04/11/2011 01:56 PM, Taku Izumi Write: > Wen-san, Hu-san, Osier-san, > > Thank you for reviewing. > I'll update this. > > to Wen-san, > >>> + >>>> + if (flags & ~(VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) { >>>> + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); >>>> + virDispatchError(NULL); >>>> + return -1; >>>> + } >> Why we check the flags here? We can check it in hypervisor's implementation. >> > > We can't use this API with flags except VIR_DOMAIN_VCPU_LIVE or VIR_DOMAIN_VCPU_CONFIG. > I think validation should be done here. The other API virDomain*Flags do not check the flags here. If we do not check it here, it will cause some problems? > >>> + if (conn->driver->domainPinVcpuFlags) { >>>> + int ret; >>>> + ret = conn->driver->domainPinVcpuFlags (domain, vcpu, cpumap, maplen, flags); >> There is no need to add space between 'domainPinVcpuFlags' and '(domain', it is old coding >> style. >> > > I intentionally did because such a style is adopted in a lot of other places > where drivers' function are invoked. > > > Best regards, > Taku Izumi > > From izumi.taku at jp.fujitsu.com Mon Apr 11 07:08:07 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Mon, 11 Apr 2011 16:08:07 +0900 Subject: [libvirt] [PATCH v2 0/4] RFC: vcpupin: configure inactive domains' CPU affinity setting In-Reply-To: <20110408073241.GB28690@localhost.localdomain> References: <4D9E999F.5070505@jp.fujitsu.com> <20110408073241.GB28690@localhost.localdomain> Message-ID: <4DA2A8D7.6040104@jp.fujitsu.com> > Two suggestions: > > - when vcpupin an inactive domain, it gives an error message like this: > > error: Requested operation is not valid: cannot pin vcpus on an inactive domain > > After applying this series, this is not true anymore. I think a > message like this is more helpful: > > Failed to pin vcpus on inactive domain, please check the --config option. I think your pointing out is reasonable, I'll change that message. > - While it can vcpupin an inactive domain, it seems reasonable to be > able to view vcpuinfo of inactive domain, so would a patch to > vcpuinfo command be included? > I shelve that work. Probably that patch should be separated. Best regards, Taku Izumi From laine at laine.org Mon Apr 11 07:10:08 2011 From: laine at laine.org (Laine Stump) Date: Mon, 11 Apr 2011 03:10:08 -0400 Subject: [libvirt] Paused networking on VM up/down with NAT fwd In-Reply-To: <20110410223256.GA21420@hallyn.com> References: <20110410223256.GA21420@hallyn.com> Message-ID: <4DA2A950.80805@laine.org> On 04/10/2011 06:32 PM, Serge Hallyn wrote: > Hi all, > > some time ago bug > https://bugs.launchpad.net/ubuntu/maverick/+source/qemu-kvm/+bug/584048 > was fixed in libvirt. It's the one where when a VM is started or stopped > which has a lower macaddr than what the bridge currently has, the bridge > changes macaddr and networking pauses. The fix was to make sure that a > macaddr assigned by libvirt will start with 'fe:' making it higher than > the physical interface. > > But this doesn't help when virbr0 isn't associated with any physical > nic, as in the common NAT case! > > Is there anything we can do to help that case? Yes, it's already been addressed, The following commit was included in 0.9.0: commit 5754dbd56d4738112a86776c09e810e32f7c3224 Author: Laine Stump Date: Wed Feb 9 03:28:12 2011 -0500 Give each virtual network bridge its own fixed MAC address This fixes https://bugzilla.redhat.com/show_bug.cgi?id=609463 The problem was that, since a bridge always acquires the MAC address of the connected interface with the numerically lowest MAC, as guests are started and stopped, it was possible for the MAC address to change over time, and this change in the network was being detected by Windows 7 (it sees the MAC of the default route change), so on each reboot it would bring up a dialog box asking about this "new network". The solution is to create a dummy tap interface with a MAC guaranteed to be lower than any guest interface's MAC, and attach that tap to the bridge as soon as it's created. Since all guest MAC addresses start with 0xFE, we can just generate a MAC with the standard "0x52, 0x54, 0" prefix, and it's guaranteed to always win (physical interfaces are never connected to these bridges, so we don't need to worry about competing numerically with them). From izumi.taku at jp.fujitsu.com Mon Apr 11 07:14:47 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Mon, 11 Apr 2011 16:14:47 +0900 Subject: [libvirt] [PATCH 1/4] vcpupin: inroduce a new libvir API (virDomainPinVcpuFlags) In-Reply-To: <4DA2982B.5040406@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> <4D9E9B1F.1040500@jp.fujitsu.com> <4DA2982B.5040406@jp.fujitsu.com> Message-ID: <4DA2AA67.2060109@jp.fujitsu.com> This patch introduces a new libvirt API (virDomainPinVcpuFlags) Signed-off-by: Taku Izumi --- include/libvirt/libvirt.h.in | 6 +++ src/driver.h | 7 +++ src/esx/esx_driver.c | 1 src/libvirt.c | 83 +++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 4 ++ src/libxl/libxl_driver.c | 1 src/lxc/lxc_driver.c | 1 src/openvz/openvz_driver.c | 1 src/phyp/phyp_driver.c | 1 src/qemu/qemu_driver.c | 1 src/remote/remote_driver.c | 1 src/test/test_driver.c | 1 src/uml/uml_driver.c | 1 src/vbox/vbox_tmpl.c | 1 src/vmware/vmware_driver.c | 1 src/xen/xen_driver.c | 1 src/xenapi/xenapi_driver.c | 1 17 files changed, 113 insertions(+) Index: libvirt/include/libvirt/libvirt.h.in =================================================================== --- libvirt.orig/include/libvirt/libvirt.h.in +++ libvirt/include/libvirt/libvirt.h.in @@ -1018,6 +1018,7 @@ typedef virVcpuInfo *virVcpuInfoPtr; /* Flags for controlling virtual CPU hot-plugging. */ typedef enum { + VIR_DOMAIN_VCPU_CURRENT = 0, /* Affect current domain state */ /* Must choose at least one of these two bits; SetVcpus can choose both */ VIR_DOMAIN_VCPU_LIVE = (1 << 0), /* Affect active domain */ VIR_DOMAIN_VCPU_CONFIG = (1 << 1), /* Affect next boot */ @@ -1038,6 +1039,11 @@ int virDomainPinVcpu unsigned int vcpu, unsigned char *cpumap, int maplen); +int virDomainPinVcpuFlags (virDomainPtr domain, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags); /** * VIR_USE_CPU: Index: libvirt/src/driver.h =================================================================== --- libvirt.orig/src/driver.h +++ libvirt/src/driver.h @@ -220,6 +220,12 @@ typedef int unsigned char *cpumap, int maplen); typedef int + (*virDrvDomainPinVcpuFlags) (virDomainPtr domain, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags); +typedef int (*virDrvDomainGetVcpus) (virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, @@ -570,6 +576,7 @@ struct _virDriver { virDrvDomainSetVcpusFlags domainSetVcpusFlags; virDrvDomainGetVcpusFlags domainGetVcpusFlags; virDrvDomainPinVcpu domainPinVcpu; + virDrvDomainPinVcpuFlags domainPinVcpuFlags; virDrvDomainGetVcpus domainGetVcpus; virDrvDomainGetMaxVcpus domainGetMaxVcpus; virDrvDomainGetSecurityLabel domainGetSecurityLabel; Index: libvirt/src/libvirt.c =================================================================== --- libvirt.orig/src/libvirt.c +++ libvirt/src/libvirt.c @@ -5464,6 +5464,89 @@ error: } /** + * virDomainPinVcpuFlags: + * @domain: pointer to domain object, or NULL for Domain0 + * @vcpu: virtual CPU number + * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN) + * Each bit set to 1 means that corresponding CPU is usable. + * Bytes are stored in little-endian order: CPU0-7, 8-15... + * In each byte, lowest CPU number is least significant bit. + * @maplen: number of bytes in cpumap, from 1 up to size of CPU map in + * underlying virtualization system (Xen...). + * If maplen < size, missing bytes are set to zero. + * If maplen > size, failure code is returned. + * @flags: an OR'ed subset of virDomainVcpuFlags + * + * Dynamically change the real CPUs which can be allocated to a virtual CPU. + * This function requires privileged access to the hypervisor. + * + * @flags may include VIR_DOMAIN_VCPU_LIVE or VIR_DOMAIN_VCPU_CONFIG. + * Both flags may be set, but VIR_DOMAIN_VCPU_MAXIMUM cannot be set. + * If VIR_DOMAIN_VCPU_LIVE is set, the change affects a running domain + * and may fail if domain is not alive. + * If VIR_DOMAIN_VCPU_CONFIG is set, the change affects persistent state, + * and will fail for transient domains. + * If neither flag is specified (that is, @flags is VIR_DOMAIN_VCPU_CURRENT), + * then an inactive domain modifies persistent setup, while an active domain + * is hypervisor-dependent on whether just live or both live and persistent + * state is changed. + * Not all hypervisors can support all flag combinations. + * + * Returns 0 in case of success, -1 in case of failure. + * + */ +int +virDomainPinVcpuFlags(virDomainPtr domain, unsigned int vcpu, + unsigned char *cpumap, int maplen, unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "vcpu=%u, cpumap=%p, maplen=%d, flags=%u", + vcpu, cpumap, maplen, flags); + + virResetLastError(); + + if (flags & ~(VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if ((vcpu > 32000) || (cpumap == NULL) || (maplen < 1)) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainPinVcpuFlags) { + int ret; + ret = conn->driver->domainPinVcpuFlags (domain, vcpu, cpumap, maplen, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; + +} + +/** * virDomainGetVcpus: * @domain: pointer to domain object, or NULL for Domain0 * @info: pointer to an array of virVcpuInfo structures (OUT) Index: libvirt/src/libvirt_public.syms =================================================================== --- libvirt.orig/src/libvirt_public.syms +++ libvirt/src/libvirt_public.syms @@ -436,4 +436,8 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8; +LIBVIRT_0.9.1 { + virDomainPinVcpuFlags; +} LIBVIRT_0.9.0; + # .... define new API here using predicted next version number .... Index: libvirt/src/lxc/lxc_driver.c =================================================================== --- libvirt.orig/src/lxc/lxc_driver.c +++ libvirt/src/lxc/lxc_driver.c @@ -2837,6 +2837,7 @@ static virDriver lxcDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/openvz/openvz_driver.c =================================================================== --- libvirt.orig/src/openvz/openvz_driver.c +++ libvirt/src/openvz/openvz_driver.c @@ -1598,6 +1598,7 @@ static virDriver openvzDriver = { openvzDomainSetVcpusFlags, /* domainSetVcpusFlags */ openvzDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/phyp/phyp_driver.c =================================================================== --- libvirt.orig/src/phyp/phyp_driver.c +++ libvirt/src/phyp/phyp_driver.c @@ -4003,6 +4003,7 @@ static virDriver phypDriver = { phypDomainSetVcpusFlags, /* domainSetVcpusFlags */ phypDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ phypGetLparCPUMAX, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -6901,6 +6901,7 @@ static virDriver qemuDriver = { qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ qemudDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ qemudDomainGetVcpus, /* domainGetVcpus */ qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */ Index: libvirt/src/remote/remote_driver.c =================================================================== --- libvirt.orig/src/remote/remote_driver.c +++ libvirt/src/remote/remote_driver.c @@ -11231,6 +11231,7 @@ static virDriver remote_driver = { remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ remoteDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ remoteDomainGetVcpus, /* domainGetVcpus */ remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */ remoteDomainGetSecurityLabel, /* domainGetSecurityLabel */ Index: libvirt/src/test/test_driver.c =================================================================== --- libvirt.orig/src/test/test_driver.c +++ libvirt/src/test/test_driver.c @@ -5378,6 +5378,7 @@ static virDriver testDriver = { testDomainSetVcpusFlags, /* domainSetVcpusFlags */ testDomainGetVcpusFlags, /* domainGetVcpusFlags */ testDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ testDomainGetVcpus, /* domainGetVcpus */ testDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/uml/uml_driver.c =================================================================== --- libvirt.orig/src/uml/uml_driver.c +++ libvirt/src/uml/uml_driver.c @@ -2184,6 +2184,7 @@ static virDriver umlDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/vbox/vbox_tmpl.c =================================================================== --- libvirt.orig/src/vbox/vbox_tmpl.c +++ libvirt/src/vbox/vbox_tmpl.c @@ -8568,6 +8568,7 @@ virDriver NAME(Driver) = { vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */ vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ vboxDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/vmware/vmware_driver.c =================================================================== --- libvirt.orig/src/vmware/vmware_driver.c +++ libvirt/src/vmware/vmware_driver.c @@ -938,6 +938,7 @@ static virDriver vmwareDriver = { NULL, /* domainSetVcpusFlags */ NULL, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/xen/xen_driver.c =================================================================== --- libvirt.orig/src/xen/xen_driver.c +++ libvirt/src/xen/xen_driver.c @@ -2072,6 +2072,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenUnifiedDomainGetVcpusFlags, /* domainGetVcpusFlags */ xenUnifiedDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ xenUnifiedDomainGetVcpus, /* domainGetVcpus */ xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/xenapi/xenapi_driver.c =================================================================== --- libvirt.orig/src/xenapi/xenapi_driver.c +++ libvirt/src/xenapi/xenapi_driver.c @@ -1820,6 +1820,7 @@ static virDriver xenapiDriver = { xenapiDomainSetVcpusFlags, /* domainSetVcpusFlags */ xenapiDomainGetVcpusFlags, /* domainGetVcpusFlags */ xenapiDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ xenapiDomainGetVcpus, /* domainGetVcpus */ xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/libxl/libxl_driver.c =================================================================== --- libvirt.orig/src/libxl/libxl_driver.c +++ libvirt/src/libxl/libxl_driver.c @@ -2594,6 +2594,7 @@ static virDriver libxlDriver = { libxlDomainSetVcpusFlags, /* domainSetVcpusFlags */ libxlDomainGetVcpusFlags, /* domainGetVcpusFlags */ libxlDomainPinVcpu, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ libxlDomainGetVcpus, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ Index: libvirt/src/esx/esx_driver.c =================================================================== --- libvirt.orig/src/esx/esx_driver.c +++ libvirt/src/esx/esx_driver.c @@ -4606,6 +4606,7 @@ static virDriver esxDriver = { esxDomainSetVcpusFlags, /* domainSetVcpusFlags */ esxDomainGetVcpusFlags, /* domainGetVcpusFlags */ NULL, /* domainPinVcpu */ + NULL, /* domainPinVcpuFlags */ NULL, /* domainGetVcpus */ esxDomainGetMaxVcpus, /* domainGetMaxVcpus */ NULL, /* domainGetSecurityLabel */ From izumi.taku at jp.fujitsu.com Mon Apr 11 07:15:50 2011 From: izumi.taku at jp.fujitsu.com (Taku Izumi) Date: Mon, 11 Apr 2011 16:15:50 +0900 Subject: [libvirt] [PATCH 2/4] vcpupin: implement the code to address the new API in the qemu driver In-Reply-To: <4D9E9B61.9090504@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> <4D9E9B61.9090504@jp.fujitsu.com> Message-ID: <4DA2AAA6.3060701@jp.fujitsu.com> This patch implements the code to address the new API (virDomainPinVcpuFlags) in the qemu driver. Signed-off-by: Taku Izumi --- src/qemu/qemu_driver.c | 100 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 24 deletions(-) Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -2667,17 +2667,24 @@ qemudDomainSetVcpus(virDomainPtr dom, un static int -qemudDomainPinVcpu(virDomainPtr dom, - unsigned int vcpu, - unsigned char *cpumap, - int maplen) { +qemudDomainPinVcpuFlags(virDomainPtr dom, + unsigned int vcpu, + unsigned char *cpumap, + int maplen, + unsigned int flags) { + struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; + virDomainDefPtr persistentDef = NULL; int maxcpu, hostcpus; virNodeInfo nodeinfo; int ret = -1; + bool isActive; qemuDomainObjPrivatePtr priv; + virCheckFlags(VIR_DOMAIN_VCPU_LIVE | + VIR_DOMAIN_VCPU_CONFIG, -1); + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); qemuDriverUnlock(driver); @@ -2690,9 +2697,18 @@ qemudDomainPinVcpu(virDomainPtr dom, goto cleanup; } - if (!virDomainObjIsActive(vm)) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s",_("cannot pin vcpus on an inactive domain")); + isActive = virDomainObjIsActive(vm); + if (flags == VIR_DOMAIN_VCPU_CURRENT) { + if (isActive) + flags = VIR_DOMAIN_VCPU_LIVE; + else + flags = VIR_DOMAIN_VCPU_CONFIG; + } + + if (!isActive && (flags & VIR_DOMAIN_VCPU_LIVE)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("a domain is inactive; can change only " + "persistent config")); goto cleanup; } @@ -2705,27 +2721,54 @@ qemudDomainPinVcpu(virDomainPtr dom, goto cleanup; } - if (nodeGetInfo(dom->conn, &nodeinfo) < 0) - goto cleanup; + if (flags & VIR_DOMAIN_VCPU_CONFIG) { + if (!vm->persistent) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot change persistent config of a transient domain")); + goto cleanup; + } + if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm))) + goto cleanup; + } - hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo); - maxcpu = maplen * 8; - if (maxcpu > hostcpus) - maxcpu = hostcpus; + if (flags & VIR_DOMAIN_VCPU_LIVE) { - if (priv->vcpupids != NULL) { - if (virProcessInfoSetAffinity(priv->vcpupids[vcpu], - cpumap, maplen, maxcpu) < 0) + if (nodeGetInfo(dom->conn, &nodeinfo) < 0) goto cleanup; - } else { - qemuReportError(VIR_ERR_NO_SUPPORT, - "%s", _("cpu affinity is not supported")); - goto cleanup; + + hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo); + maxcpu = maplen * 8; + if (maxcpu > hostcpus) + maxcpu = hostcpus; + + if (priv->vcpupids != NULL) { + if (virProcessInfoSetAffinity(priv->vcpupids[vcpu], + cpumap, maplen, maxcpu) < 0) + goto cleanup; + } else { + qemuReportError(VIR_ERR_NO_SUPPORT, + "%s", _("cpu affinity is not supported")); + goto cleanup; + } + + if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to update or add vcpupin xml of " + "a running domain")); + goto cleanup; + } + } - if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("failed to update or add vcpupin xml")); + if (flags & VIR_DOMAIN_VCPU_CONFIG) { + + if (virDomainVcpupinAdd(persistentDef, cpumap, maplen, vcpu) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to update or add vcpupin xml of " + "a persistent domain")); + goto cleanup; + } + ret = virDomainSaveConfig(driver->configDir, persistentDef); goto cleanup; } @@ -2738,6 +2781,15 @@ cleanup: } static int +qemudDomainPinVcpu(virDomainPtr dom, + unsigned int vcpu, + unsigned char *cpumap, + int maplen) { + return qemudDomainPinVcpuFlags(dom, vcpu, cpumap, maplen, + VIR_DOMAIN_VCPU_LIVE); +} + +static int qemudDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo, @@ -6901,7 +6953,7 @@ static virDriver qemuDriver = { qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ qemudDomainPinVcpu, /* domainPinVcpu */ - NULL, /* domainPinVcpuFlags */ + qemudDomainPinVcpuFlags, /* domainPinVcpuFlags */ qemudDomainGetVcpus, /* domainGetVcpus */ qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */ From stefanb at linux.vnet.ibm.com Mon Apr 11 10:32:21 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Mon, 11 Apr 2011 06:32:21 -0400 Subject: [libvirt] [PATCH] migrate VMs between different-endian hosts In-Reply-To: <20110411030911.GS24838@redhat.com> References: <4DA07FD9.8000606@linux.vnet.ibm.com> <20110411030911.GS24838@redhat.com> Message-ID: <4DA2D8B5.5000106@linux.vnet.ibm.com> On 04/10/2011 11:09 PM, Daniel Veillard wrote: > On Sat, Apr 09, 2011 at 11:48:41AM -0400, Stefan Berger wrote: >> This patch enables the migration of Qemu VMs between hosts of >> different endianess. I tested this by migrating a i686 VM between a >> x86 and ppc64 host. > OMG, there is really a use case for this :-) ? :-) There may be other architectures that run more efficiently than an x86 one. Btw, my use case is 'testing'. >> I am converting the 'int's in the VM's state header to uint32_t >> assuming this doesn't break compatibility with existing deployments >> other than Linux. >> >> Signed-off-by: Stefan Berger >> >> --- >> src/qemu/qemu_driver.c | 25 ++++++++++++++++++++----- >> 1 file changed, 20 insertions(+), 5 deletions(-) >> >> Index: libvirt-acl/src/qemu/qemu_driver.c >> =================================================================== >> --- libvirt-acl.orig/src/qemu/qemu_driver.c >> +++ libvirt-acl/src/qemu/qemu_driver.c >> @@ -43,6 +43,7 @@ >> #include >> #include >> #include >> +#include >> >> >> #include "qemu_driver.h" >> @@ -1881,13 +1882,22 @@ VIR_ENUM_IMPL(qemudSaveCompression, QEMU >> >> struct qemud_save_header { >> char magic[sizeof(QEMUD_SAVE_MAGIC)-1]; >> - int version; >> - int xml_len; >> - int was_running; >> - int compressed; >> - int unused[15]; >> + uint32_t version; >> + uint32_t xml_len; >> + uint32_t was_running; >> + uint32_t compressed; >> + uint32_t unused[15]; >> }; >> >> +static inline void >> +bswap_header(struct qemud_save_header *hdr) { >> + hdr->version = bswap_32(hdr->version); >> + hdr->xml_len = bswap_32(hdr->xml_len); >> + hdr->was_running = bswap_32(hdr->was_running); >> + hdr->compressed = bswap_32(hdr->compressed); >> +} >> + >> + >> /* return -errno on failure, or 0 on success */ >> static int >> qemuDomainSaveHeader(int fd, const char *path, char *xml, >> @@ -3097,6 +3107,11 @@ qemuDomainSaveImageOpen(struct qemud_dri >> } >> >> if (header.version> QEMUD_SAVE_VERSION) { >> + /* convert endianess and try again */ >> + bswap_header(&header); >> + } > Hum, isn't there a more reliable way to detect the change of > endianness ? That's a bit fishy IMHO :-) The problem is that the header should not have been written in a hosts' native format. So what can go wrong? QEMUD_SAVE_VERSION is '2'. Either we find 1 or 2 here and go ahead and accept it 'as-is'. Otherwise anything bigger than 3 is not accepted and swapped. 3 then becomes 0x03 00 00 00 and is discarded. 0x 02 00 00 00 would be swapped to '2' and accepted. Stefan >> + if (header.version> QEMUD_SAVE_VERSION) { >> qemuReportError(VIR_ERR_OPERATION_FAILED, >> _("image version is not supported (%d> %d)"), >> header.version, QEMUD_SAVE_VERSION); > Daniel > From veillard at redhat.com Mon Apr 11 13:36:19 2011 From: veillard at redhat.com (Daniel Veillard) Date: Mon, 11 Apr 2011 21:36:19 +0800 Subject: [libvirt] [PATCH] migrate VMs between different-endian hosts In-Reply-To: <4DA2D8B5.5000106@linux.vnet.ibm.com> References: <4DA07FD9.8000606@linux.vnet.ibm.com> <20110411030911.GS24838@redhat.com> <4DA2D8B5.5000106@linux.vnet.ibm.com> Message-ID: <20110411133619.GC30115@redhat.com> On Mon, Apr 11, 2011 at 06:32:21AM -0400, Stefan Berger wrote: > On 04/10/2011 11:09 PM, Daniel Veillard wrote: > >On Sat, Apr 09, 2011 at 11:48:41AM -0400, Stefan Berger wrote: > >>This patch enables the migration of Qemu VMs between hosts of > >>different endianess. I tested this by migrating a i686 VM between a > >>x86 and ppc64 host. > > OMG, there is really a use case for this :-) ? > :-) There may be other architectures that run more efficiently than > an x86 one. Haha, no doubt :-) > Btw, my use case is 'testing'. Okay, I was wondering, thanks ! > >>@@ -3097,6 +3107,11 @@ qemuDomainSaveImageOpen(struct qemud_dri > >> } > >> > >> if (header.version> QEMUD_SAVE_VERSION) { > >>+ /* convert endianess and try again */ > >>+ bswap_header(&header); > >>+ } > > Hum, isn't there a more reliable way to detect the change of > >endianness ? That's a bit fishy IMHO :-) > The problem is that the header should not have been written in a > hosts' native format. So what can go wrong? QEMUD_SAVE_VERSION is > '2'. Either we find 1 or 2 here and go ahead and accept it 'as-is'. > Otherwise anything bigger than 3 is not accepted and swapped. 3 then > becomes 0x03 00 00 00 and is discarded. 0x 02 00 00 00 would be > swapped to '2' and accepted. yeah, I understand, okay, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From neil at brightbox.co.uk Mon Apr 11 13:48:01 2011 From: neil at brightbox.co.uk (Neil Wilson) Date: Mon, 11 Apr 2011 14:48:01 +0100 Subject: [libvirt] IPv6 DNS and domain details Message-ID: <1302529681.6706.19.camel@lenovo-3000-n100> Hi all, I notice that the current IPv6 auto address implementation doesn't pass down any DNS details to the guest machine - which means that an 'IPv6 only' guest that works automatically is currently just out of reach. Support for handing out these details depends upon the version of 'radvd' that is installed on the host server. RHEL5's standard version has no support for DNS options. 6.0 has 1.6 installed which can hand out the DNS address, but you need 1.7 before DNS search lists from RFC6106 are supported. The data for these options is available in the network definition and it appears at first glance to be reasonably straightforward to add them. What do you think would be the best way to implement this? Is there a mechanism within libvirt already that checks versions of subsiduary programs and runs slightly different code accordingly? Or are there other plans in the pipeline? Rgs Neil Wilson From eblake at redhat.com Mon Apr 11 14:58:51 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 11 Apr 2011 08:58:51 -0600 Subject: [libvirt] [PATCH] docs: document freecell --all In-Reply-To: <20110411031230.GA32376@redhat.com> References: <1302110917-10123-1-git-send-email-eblake@redhat.com> <20110411031230.GA32376@redhat.com> Message-ID: <4DA3172B.60807@redhat.com> On 04/10/2011 09:12 PM, Daniel Veillard wrote: > On Wed, Apr 06, 2011 at 11:28:37AM -0600, Eric Blake wrote: >> Based on a smaller patch developed by Moritoshi Oshiro: >> https://bugzilla.redhat.com/show_bug.cgi?id=693963 >> >> * tools/virsh.pod (freecell): Mention all, and clarify that >> optional cellno requires --cellno. >> --- >> >> I think this is the first case where virsh.pod is trying to convey >> mutually exclusive options; does the resulting layout look >> reasonable? > > I applied and checked with man, looks fine to me, > > ACK, Thanks; pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From laine at laine.org Mon Apr 11 16:06:34 2011 From: laine at laine.org (Laine Stump) Date: Mon, 11 Apr 2011 12:06:34 -0400 Subject: [libvirt] IPv6 DNS and domain details In-Reply-To: <1302529681.6706.19.camel@lenovo-3000-n100> References: <1302529681.6706.19.camel@lenovo-3000-n100> Message-ID: <4DA3270A.9010409@laine.org> On 04/11/2011 09:48 AM, Neil Wilson wrote: > Hi all, > > I notice that the current IPv6 auto address implementation doesn't pass > down any DNS details to the guest machine - which means that an 'IPv6 > only' guest that works automatically is currently just out of reach. > > Support for handing out these details depends upon the version of > 'radvd' that is installed on the host server. RHEL5's standard version > has no support for DNS options. 6.0 has 1.6 installed which can hand out > the DNS address, but you need 1.7 before DNS search lists from RFC6106 > are supported. Interesting. Because my main development machine is still running radvd 1.6, I hadn't been aware of those options. > The data for these options is available in the network definition and it > appears at first glance to be reasonably straightforward to add them. There aren't any examples in the manpage. Do you have a working example? > What do you think would be the best way to implement this? Is there a > mechanism within libvirt already that checks versions of subsiduary > programs and runs slightly different code accordingly? We do that for qemu, but currently not for anything else that I'm aware of. Fortunately, "radvd -v" seems to reliably print out "Version x.x" on the first line (at least for 1.6 and 1.7), so we could possibly put similar logic in place for radvd, adding in DNS support when available. Of course we would want to make sure it was obvious to the admin when IPV6 DNS autconfig support wasn't available due to an old radvd (without cluttering the logs too much), otherwise we would run the risk of a lot of "bug" reports due to the radvd version being too old. > Or are there other plans in the pipeline? Not at the moment. It does sound very useful though. It would be really nice if IPv6-only worked properly. If you're not in a patch-writing mood, I could work something up, assuming someone provides a working radvd.conf file (keep in mind that we already have dnsmasq listening for DNS requests on the IPv6 address of the bridge; we just need autoconf to tell the guest to use it). From eblake at redhat.com Mon Apr 11 17:32:02 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 11 Apr 2011 11:32:02 -0600 Subject: [libvirt] [PATCH] esx: Mark error message in macros for translation In-Reply-To: <20110410112829.GA13638@sbox> References: <20110410112829.GA13638@sbox> Message-ID: <4DA33B12.3060007@redhat.com> On 04/10/2011 05:28 AM, Matthias Bolte wrote: > --- > src/esx/esx_vi_types.c | 20 ++++++++++---------- > 1 files changed, 10 insertions(+), 10 deletions(-) > > diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c > index 9e23030..29a3c39 100644 > --- a/src/esx/esx_vi_types.c > +++ b/src/esx/esx_vi_types.c > @@ -77,12 +77,12 @@ > int \ > esxVI_##__type##_Validate(esxVI_##__type *item) \ > { \ > - const char *type_name = esxVI_Type_ToString(esxVI_Type_##__type); \ > + const char *typeName = esxVI_Type_ToString(esxVI_Type_##__type); \ > \ > if (item->_type <= esxVI_Type_Undefined || \ > item->_type >= esxVI_Type_Other) { \ > ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ > - "%s object has invalid dynamic type", type_name); \ > + _("%s object has invalid dynamic type"), typeName); \ Hmm, cfg.mk already included ESX_VI_ERROR in the list of msg_gen_function that should have caught this at 'make syntax-check' time; I wonder why it was being overlooked. Oh, probably because sc_libvirt_unmarked_diagnostics states that it won't find lines where the format string is on a separate line. Same goes for sc_unmarked_diagnostics from gnulib's maint.mk; wonder if there's a way to improve the syntax checker. At any rate, ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 11 17:36:00 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 11 Apr 2011 11:36:00 -0600 Subject: [libvirt] [PATCH] virsh: Add --name and --description options to snapshot-create In-Reply-To: <20110410113127.GA13668@sbox> References: <20110410113127.GA13668@sbox> Message-ID: <4DA33C00.6050506@redhat.com> On 04/10/2011 05:31 AM, Matthias Bolte wrote: > This options are shortcuts to set name and description of a snapshot. > > Suggested by Elias Probst > --- > > I'm not sure if this is be best approach. In case of the vol-* commands there > is vol-create that takes and XML file and vol-create-as that takes a set of > arguments. > > So, should there actually be a snapshot-create-as to takes --name and > --description options? For consistency, I would argue that we don't have any other commands that modify direct xml input, and so we shouldn't be starting that now. I agree that a snapshot-create-as that takes options (and builds xml under the hood) would match with existing virsh paradigms better than making the existing snapshot-create command modify input xml on the fly. In other words, I'm afraid that your concern was unfortunately valid, and that we should NACK this patch in favor of one that adds a new command instead. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 11 17:37:19 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 11 Apr 2011 11:37:19 -0600 Subject: [libvirt] [PATCH] docs: Serial and parallel device target ports actually start from 0 In-Reply-To: <20110410130342.GA25199@sbox> References: <20110410130342.GA25199@sbox> Message-ID: <4DA33C4F.4010103@redhat.com> On 04/10/2011 07:03 AM, Matthias Bolte wrote: > Reported by Igor Gali? > --- > docs/formatdomain.html.in | 4 ++-- > 1 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in > index 574fee5..ea021e8 100644 > --- a/docs/formatdomain.html.in > +++ b/docs/formatdomain.html.in > @@ -1807,7 +1807,7 @@ qemu-kvm -net nic,model=? /dev/null > >

    > target can have a port attribute, which > - specifies the port number. Ports are numbered starting from 1. There are > + specifies the port number. Ports are numbered starting from 0. There are > usually 0, 1 or 2 parallel ports. ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 11 17:42:33 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 11 Apr 2011 11:42:33 -0600 Subject: [libvirt] [PATCH] esx: Make the parsed URI part of the private connection data In-Reply-To: <20110410151832.GA29175@sbox> References: <20110410151832.GA29175@sbox> Message-ID: <4DA33D89.40000@redhat.com> On 04/10/2011 09:18 AM, Matthias Bolte wrote: > This will be used to make esxVI_Context clonable. > > Also move cleanup code for esxPrivate to esxFreePrivate(). > --- > src/esx/esx_driver.c | 103 ++++++++++++++++++++++++------------------------- > src/esx/esx_private.h | 4 +- > 2 files changed, 52 insertions(+), 55 deletions(-) ACK; looks like a relatively straightforward refactor, followed by lots of renaming fallout. > @@ -1070,14 +1072,9 @@ esxClose(virConnectPtr conn) > esxVI_Logout(priv->vCenter) < 0) { > result = -1; > } > - > - esxVI_Context_Free(&priv->vCenter); > } > > - virCapabilitiesFree(priv->caps); > - > - VIR_FREE(priv->transport); > - VIR_FREE(priv); > + esxFreePrivate(&priv); > > conn->privateData = NULL; Is this line now redundant, since priv was initialized as conn->privateData, and esxFreePrivate(&priv) guarantees that priv will be reassigned to NULL? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 11 17:46:55 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 11 Apr 2011 11:46:55 -0600 Subject: [libvirt] [PATCH] migrate VMs between different-endian hosts In-Reply-To: <20110411133619.GC30115@redhat.com> References: <4DA07FD9.8000606@linux.vnet.ibm.com> <20110411030911.GS24838@redhat.com> <4DA2D8B5.5000106@linux.vnet.ibm.com> <20110411133619.GC30115@redhat.com> Message-ID: <4DA33E8F.209@redhat.com> On 04/11/2011 07:36 AM, Daniel Veillard wrote: >>>> @@ -3097,6 +3107,11 @@ qemuDomainSaveImageOpen(struct qemud_dri >>>> } >>>> >>>> if (header.version> QEMUD_SAVE_VERSION) { >>>> + /* convert endianess and try again */ >>>> + bswap_header(&header); >>>> + } >>> Hum, isn't there a more reliable way to detect the change of >>> endianness ? That's a bit fishy IMHO :-) >> The problem is that the header should not have been written in a >> hosts' native format. So what can go wrong? QEMUD_SAVE_VERSION is >> '2'. Either we find 1 or 2 here and go ahead and accept it 'as-is'. >> Otherwise anything bigger than 3 is not accepted and swapped. 3 then >> becomes 0x03 00 00 00 and is discarded. 0x 02 00 00 00 would be >> swapped to '2' and accepted. > > yeah, I understand, okay, Should we be writing the header in a particular byte order, regardless of host endianness? Or does that require bumping the header version to 3 anyways? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From stefanb at linux.vnet.ibm.com Mon Apr 11 17:56:14 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Mon, 11 Apr 2011 13:56:14 -0400 Subject: [libvirt] [PATCH] migrate VMs between different-endian hosts In-Reply-To: <4DA33E8F.209@redhat.com> References: <4DA07FD9.8000606@linux.vnet.ibm.com> <20110411030911.GS24838@redhat.com> <4DA2D8B5.5000106@linux.vnet.ibm.com> <20110411133619.GC30115@redhat.com> <4DA33E8F.209@redhat.com> Message-ID: <4DA340BE.9070006@linux.vnet.ibm.com> On 04/11/2011 01:46 PM, Eric Blake wrote: > On 04/11/2011 07:36 AM, Daniel Veillard wrote: >>>>> @@ -3097,6 +3107,11 @@ qemuDomainSaveImageOpen(struct qemud_dri >>>>> } >>>>> >>>>> if (header.version> QEMUD_SAVE_VERSION) { >>>>> + /* convert endianess and try again */ >>>>> + bswap_header(&header); >>>>> + } >>>> Hum, isn't there a more reliable way to detect the change of >>>> endianness ? That's a bit fishy IMHO :-) >>> The problem is that the header should not have been written in a >>> hosts' native format. So what can go wrong? QEMUD_SAVE_VERSION is >>> '2'. Either we find 1 or 2 here and go ahead and accept it 'as-is'. >>> Otherwise anything bigger than 3 is not accepted and swapped. 3 then >>> becomes 0x03 00 00 00 and is discarded. 0x 02 00 00 00 would be >>> swapped to '2' and accepted. >> yeah, I understand, okay, > Should we be writing the header in a particular byte order, regardless > of host endianness? Or does that require bumping the header version to > 3 anyways? > Would version 3 then simply mean to convert to version-3-standard-header-endianess and anything below just would fail if the hosts had different endianess ? No matter what, we'll have to have code to convert the version indicator alone. Stefan From eblake at redhat.com Mon Apr 11 19:25:32 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 11 Apr 2011 13:25:32 -0600 Subject: [libvirt] [PATCH 2/3] maxmem: implement virDomainSetMaxMemory API of the qemu driver In-Reply-To: <20110411022826.GM24838@redhat.com> References: <4D9E953A.4070102@jp.fujitsu.com> <4D9E983D.4070100@jp.fujitsu.com> <4D9F9CB8.5090008@redhat.com> <20110411022826.GM24838@redhat.com> Message-ID: <4DA355AC.9000101@redhat.com> >>> +static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) { >>> + return qemudDomainSetMemoryFlags(dom, memory, >>> + VIR_DOMAIN_MEM_MAXIMUM | VIR_DOMAIN_MEM_LIVE); >> >> Hmm. Given the above implementation, this will _always_ fail. Then >> again, the failure message will be nicer (the function used to fail with >> "not implemented", now it fails with "cannot resize memory on an active >> domain"), so I guess it's okay to provide this stub. And given the >> documentation in libvirt.c, this is accurate (that documentation >> explicitly stated that it only works on live domains). >> >> But the real clincher is how xen behaves. I just tested, and my RHEL 5 >> machine with xen:/// was able to change persistent max memory of an >> inactive domain, so the documentation in libvirt.c is wrong. I then > > Hum, how did you test this ? This sounds weird to me, maybe the xen > code really improved, but basically the max memory information was used > by the hypervisor (micro) kernel to allocate things like size of page > tablesetc. for the gues and well that could not be changed dynamically, > once the guest was started say with a max_memory of 4G you would not > be able to "live" change the max_memory to 16GB and grow the guest > memory to more than 4G. I tested as follows. Note that libvirt was able to see that xen "claimed" to have a larger max memory, but that I did not actually try to balloon the guest to the larger memory, so it could be that the balloon attempt would still fail, in which case we could argue that xen has a bug for allowing the setmaxmem to "succeed" on an active domain. I tested with libvirt 0.8.2 built for RHEL 5.6: # virsh list --all Id Name State ------------------------- 0 Domain-0 running - dom shut off # virsh dumpxml dom | grep emory 524288 524288 # virsh setmaxmem dom 600000 && echo $? 0 # virsh dumpxml dom | grep emory 599040 524288 # virsh start dom Domain dom started # virsh setmaxmem dom 580000 && echo $? # virsh dumpxml dom | grep emory 579584 524288 # virsh shutdown dom # # wait for shutdown to complete # virsh dumpxml dom | grep emory 599040 524288 Thus, setmaxmem was able to affect config-only and live-only (at least in reported numbers), but not config|live, and certainly did not match the former documentation of being a live-only operation. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 11 21:39:05 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 11 Apr 2011 15:39:05 -0600 Subject: [libvirt] snapshots += domain description? In-Reply-To: <201012071700.32747.hahn@univention.de> References: <201012071700.32747.hahn@univention.de> Message-ID: <4DA374F9.8070603@redhat.com> On 12/07/2010 09:00 AM, Philipp Hahn wrote: > Hello, > > I just encountered a problem with the current snapshot implementation for > qemu/kvm: To revert back to a snapshot, the domain description must closely > match the domain description when the snapshot was created. If the ram-size > doesn't match or the VM now contains fewer CPUs or contains additional disks, > kvm will either not load the snapshot or the machine will be broken > afterwarts. > Is this a known problem? Are you referring to a disk snapshot, created via 'virsh snapshot' on a qcow2 image, or a memory snapshot, created via 'virsh save'? The latter _does_ save the guest XML as part of the snapshot, and 'virsh restore' uses that saved XML rather than the current domain definition to resume the guest. > > Without looking into the implementation details I think saving the full domain > description instead of just a reference to the domain uuid as part of the > snapshot description would work better. So it sounds like you are talking about the 'virsh snapshot' family of commands. Indeed, there's probably quite a bit of work to do in that code to make it more reliable. > Or am I supposed to save the domain > description myself in addition the the data saved > in /var/lib/libvirt/qemu/snapshot/$DOMAIN_NAME/$SNAPSHOT_NAME.xml. I think > this is very important feature, because when you - for example - notice that > you need additional disk space and would like to include an additional block > device, this is your ideal time to take a snapshot you can revert to when you > do something wrong. I think we are hitting on more fundamental issues. Right now, the 'virsh snapshot' family of commands is geared towards qcow2 images, and relies heavily on the qcow2 internal snapshotting feature. It would be nice to enhance that to support other means of snapshotting (such as raw disk images stored on an lvm partition or using btrfs file cloning), as well as making live snapshots possible (by capturing memory as well as disk images, or even coordinating with the guest to quiesce its file systems so that restoring from a snapshot is less likely to restore a file system in an inconsistent state). > > Looking at VMware I see that reverting a VM there will not only revert the > disks and ram back to the saved state, but also the description including > name, ram size, etc. > > Any comment or advise is appreciated. Likewise - I'm hoping to look into this more myself, and any thoughts or requirements that people can think of that should drive a decent snapshot design should be brought up sooner rather than later. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 11 21:42:16 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 11 Apr 2011 15:42:16 -0600 Subject: [libvirt] [BUG] qemu: snapshots no longer shown after migration^2 In-Reply-To: <201104040808.32278.hahn@univention.de> References: <201104040808.32278.hahn@univention.de> Message-ID: <4DA375B8.2040605@redhat.com> On 04/04/2011 12:08 AM, Philipp Hahn wrote: > Hello, > > when a domain is migrated to another host and than back again, snapshots of > this domain are no longer shown. > I think that is because qemuDomainSnapshotLoad() is only called once from > qemudStartup() during startup, but not after migration (or re-definition of a > previously deleted domain, e.g. offline-migration) > > No patch yet, but this is tracked at our German bugzilla at > Thanks for the report. I'm wondering whether defining a new domain should automatically inherit all existing snapshot files that were already left in the file system, or even if undefining a domain should fail if snapshots are still present, and/or add a flag to state whether to discard snapshot files as part of undefining a domain. It makes me wonder if migration should also be able to (optionally) move snapshots along with with guest itself. Certainly plenty of work to do to make snapshot handling saner. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From berrange at redhat.com Mon Apr 11 21:45:18 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 11 Apr 2011 22:45:18 +0100 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: <4D9F6178.3080500@codemonkey.ws> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> <20110408133135.GB27561@redhat.com> <4D9F6178.3080500@codemonkey.ws> Message-ID: <20110411214518.GA7750@redhat.com> On Fri, Apr 08, 2011 at 02:26:48PM -0500, Anthony Liguori wrote: > On 04/08/2011 11:02 AM, Stefan Hajnoczi wrote: > >On Fri, Apr 8, 2011 at 2:31 PM, Daniel P. Berrange wrote: > > > >I have CCed Anthony and Kevin. Anthony drove the QED image streaming > >and Kevin will probably be interested in the idea of allocating raw > >images as a background activity while QEMU runs. > > > >> /* > >> * @path: fully qualified filename of the virtual disk > >> * @nregions: filled in the number of @region structs > >> * @regions: filled with a list of allocated regions > >> * > >> * Query the extents of allocated regions within the > >> * virtual disk file. The offsets in the list of regions > >> * are not guarenteed to be sorted in any explicit order. > >> */ > >> int virDomainBlockGetAllocationMap(virDomainPtr dom, > >> const char *path, > >> unsigned int *nregions, > >> virDomainBlockRegionPtr *regions); > >QEMU can provide this with its existing .bdrv_is_allocated() function. > > Kevin, do you have any thoughts on whether this API will work well? > > I think the trouble with this API proposal is that it's overloading > concepts. > > Sparse is not the same thing as CoW to a backing file. I don't like to use the term "sparse", since that implies a specific disk format (raw file with holes). Rather I use the term 'thin provisioned' to refer to any disk format, where the not all physical sectors have yet been allocated. A thin-provisioned disk, can trivially be thought of as a disk, with a backing file whose sectors are all filled with zeros. > For instance, when you expose streaming, the result is still a > sparse file. So you'd have a rather curious API where you called to > "allocate" a region in the file which resulted in having a sparse > file which you then called again to make it non sparse. But AFAICT, > the API doesn't really tell you these details. Copy-on-read streaming does not imply that the result is still thin-provisioned. That is a policy decision by the management application. Given information about the allocation pattern of the original master image, the mgmt app can decide whether to make a series of Allocate() calls to preserve sparseness, or make a series of Allocate() calls which result in a fully allocated image. > Having to related APIs to expand a copy-on-read image and then to > fill in a sparse file is certainly a reasonable thing to do. I > think trying to make a single API that does both without having a > flag that basically makes it two APIs is going to be cumbersome. On the contrary, having a single API makes life *simpler*. It doesn't require any special flag to distinguish the two use cases, since they are fundamentally the same thing. Some examples, which include the implicit "all zeros" backing file that every disk has, should illustrate this - Make a brand new thin-provisioned disk, no backing store, fully allocated |0|0|0|0|0|0|0|0|0| | | | | | | | | | | -> |0|0|0|0|0|0|0|0|0| - Make a brand new thin-provisioned disk, no backing store, 1/2 allocated |0|0|0|0|0|0|0|0|0| |0|0|0|0|0|0|0|0|0| | | | | | | | | | | -> |0|0|0|0|0| | | | | - Make a existing, thin-provisioned disk, no backing store, fully allocated |0|0|0|0|0|0|0|0|0| |X| |X|X| | |X| |X| -> |X|0|X|X|0|0|X|0|X| - Make a existing, thin-provisioned disk, no backing store, 1/2 allocated |0|0|0|0|0|0|0|0|0| |0|0|0|0|0|0|0|0|0| |X| |X|X| | |X| |X| -> |X|0|X|X|0| |X| |X| - Make a brand new thin-provisioned disk, with backing store, independant of backing store, but still thin: |0|0|0|0|0|0|0|0|0| |X| |X|X| | |X| |X| |0|0|0|0|0|0|0|0|0| | | | | | | | | | | -> |X| |X|X| | |X| |X| - Make a existing thin-provisioned disk, with backing store, independant of backing store, but still thin |0|0|0|0|0|0|0|0|0| |X| |X|X| | |X| |X| |0|0|0|0|0|0|0|0|0| |Y|Y|Y| | | | | | | -> |X| |X|X| | |X| |X| - Make a existing thin-provisioned disk, with backing store, independant of backing store, fully allocated |0|0|0|0|0|0|0|0|0| |X| |X|X| | |X| |X| |Y|Y|Y| | | | | | | -> |X|0|X|X|0|0|X|0|X| - Make a brand new thin-provisioned disk, with 2 backing stores, independant of backing stores & fully allocated: |0|0|0|0|0|0|0|0|0| | | |Z|Z| | | |Z| | |X| |X| | | |X| |X| |Y|Y| |Y| | | | | | -> |Y|Y|X|Y|0|0|X|Z|X| etc, etc for many more example scenarios. Cow-on-read streaming is really not a special case - it is just one of many example scenarios, all of which can be managed via the pair of APIs mentioned earlier. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From anthony at codemonkey.ws Mon Apr 11 22:06:54 2011 From: anthony at codemonkey.ws (Anthony Liguori) Date: Mon, 11 Apr 2011 17:06:54 -0500 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: <20110411214518.GA7750@redhat.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> <20110408133135.GB27561@redhat.com> <4D9F6178.3080500@codemonkey.ws> <20110411214518.GA7750@redhat.com> Message-ID: <4DA37B7E.60101@codemonkey.ws> On 04/11/2011 04:45 PM, Daniel P. Berrange wrote: > On Fri, Apr 08, 2011 at 02:26:48PM -0500, Anthony Liguori wrote: >> On 04/08/2011 11:02 AM, Stefan Hajnoczi wrote: >>> On Fri, Apr 8, 2011 at 2:31 PM, Daniel P. Berrange wrote: >>> >>> I have CCed Anthony and Kevin. Anthony drove the QED image streaming >>> and Kevin will probably be interested in the idea of allocating raw >>> images as a background activity while QEMU runs. >>> >>>> /* >>>> * @path: fully qualified filename of the virtual disk >>>> * @nregions: filled in the number of @region structs >>>> * @regions: filled with a list of allocated regions >>>> * >>>> * Query the extents of allocated regions within the >>>> * virtual disk file. The offsets in the list of regions >>>> * are not guarenteed to be sorted in any explicit order. >>>> */ >>>> int virDomainBlockGetAllocationMap(virDomainPtr dom, >>>> const char *path, >>>> unsigned int *nregions, >>>> virDomainBlockRegionPtr *regions); >>> QEMU can provide this with its existing .bdrv_is_allocated() function. >>> Kevin, do you have any thoughts on whether this API will work well? >> I think the trouble with this API proposal is that it's overloading >> concepts. >> >> Sparse is not the same thing as CoW to a backing file. > I don't like to use the term "sparse", since that implies a specific disk > format (raw file with holes). Rather I use the term 'thin provisioned' > to refer to any disk format, where the not all physical sectors have > yet been allocated. A thin-provisioned disk, can trivially be thought > of as a disk, with a backing file whose sectors are all filled with > zeros. It's not so black and white today. Imagine that you had a qcow2 file, and you "streamed" it such that it was no longer "thin provisioned", as soon as the guest starts issuing trim/discards, QEMU could conceivably start defragmenting the image and truncating resulting in a sparse file. The only time the concept of "fully allocated" really makes sense is for a raw image on a simple file system. Once you start dealing with things like btrfs and deduplication, and of those useful guarantees are thrown out the window. I think the real question is, why do you care about what physical sectors reside where? What problem are you trying to solve? >> For instance, when you expose streaming, the result is still a >> sparse file. So you'd have a rather curious API where you called to >> "allocate" a region in the file which resulted in having a sparse >> file which you then called again to make it non sparse. But AFAICT, >> the API doesn't really tell you these details. > Copy-on-read streaming does not imply that the result is still > thin-provisioned. That is a policy decision by the management > application. I think your notion of thin-provision doesn't quite map to how things work today. Unless you're in a very constrained environment, you're always thin provisioned. >> Having to related APIs to expand a copy-on-read image and then to >> fill in a sparse file is certainly a reasonable thing to do. I >> think trying to make a single API that does both without having a >> flag that basically makes it two APIs is going to be cumbersome. > On the contrary, having a single API makes life *simpler*. It doesn't > require any special flag to distinguish the two use cases, since they > are fundamentally the same thing. Some examples, which include the > implicit "all zeros" backing file that every disk has, should illustrate > this > > - Make a brand new thin-provisioned disk, no backing store, > fully allocated > > |0|0|0|0|0|0|0|0|0| > | | | | | | | | | | -> |0|0|0|0|0|0|0|0|0| > > - Make a brand new thin-provisioned disk, no backing store, > 1/2 allocated > > |0|0|0|0|0|0|0|0|0| |0|0|0|0|0|0|0|0|0| > | | | | | | | | | | -> |0|0|0|0|0| | | | | > > - Make a existing, thin-provisioned disk, no backing store, > fully allocated > > |0|0|0|0|0|0|0|0|0| > |X| |X|X| | |X| |X| -> |X|0|X|X|0|0|X|0|X| > > - Make a existing, thin-provisioned disk, no backing store, > 1/2 allocated > > |0|0|0|0|0|0|0|0|0| |0|0|0|0|0|0|0|0|0| > |X| |X|X| | |X| |X| -> |X|0|X|X|0| |X| |X| > > - Make a brand new thin-provisioned disk, with backing store, > independant of backing store, but still thin: > > |0|0|0|0|0|0|0|0|0| > |X| |X|X| | |X| |X| |0|0|0|0|0|0|0|0|0| > | | | | | | | | | | -> |X| |X|X| | |X| |X| > > - Make a existing thin-provisioned disk, with backing store, > independant of backing store, but still thin > > |0|0|0|0|0|0|0|0|0| > |X| |X|X| | |X| |X| |0|0|0|0|0|0|0|0|0| > |Y|Y|Y| | | | | | | -> |X| |X|X| | |X| |X| > > - Make a existing thin-provisioned disk, with backing store, > independant of backing store, fully allocated > > |0|0|0|0|0|0|0|0|0| > |X| |X|X| | |X| |X| > |Y|Y|Y| | | | | | | -> |X|0|X|X|0|0|X|0|X| > > - Make a brand new thin-provisioned disk, with 2 backing stores, > independant of backing stores& fully allocated: > > |0|0|0|0|0|0|0|0|0| > | | |Z|Z| | | |Z| | > |X| |X| | | |X| |X| > |Y|Y| |Y| | | | | | -> |Y|Y|X|Y|0|0|X|Z|X| > > > etc, etc for many more example scenarios. Cow-on-read streaming is really > not a special case - it is just one of many example scenarios, all of > which can be managed via the pair of APIs mentioned earlier. It's just not this simple with modern file systems unfortunately. The problem is your mixing a filesystem concept (sparseness) with a purely QEMU concept (backing file). Streaming is the process of merging a backing file into the current image without disrupting the backing file. When it is completed and the two are fully merged, the current image no longer has a dependency on the backing file. It's essentially a reverse snapshot merge and is probably close to snapshot merging conceptually than image sparseness. Regards, Anthony Liguori > Regards, > Daniel From eblake at redhat.com Mon Apr 11 22:27:19 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 11 Apr 2011 16:27:19 -0600 Subject: [libvirt] [PATCH] maint: fix grammar errors Message-ID: <1302560839-23381-1-git-send-email-eblake@redhat.com> Jim recently improved gnulib to catch various grammar errors during 'make syntax-check'. * .gnulib: Update to latest, for syntax-check improvements. * include/libvirt/libvirt.h.in (virConnectAuthCallbackPtr): Use cannot rather than two words. * src/driver.c: Likewise. * src/driver.h (VIR_SECRET_GET_VALUE_INTERNAL_CALL): Likewise. * src/remote/remote_driver.c (initialize_gnutls): Likewise. * src/util/pci.c (pciBindDeviceToStub): Likewise. * src/storage/storage_backend.c (virStorageBackendCreateQemuImg): Likewise. (virStorageBackendUpdateVolTargetInfoFD): Avoid doubled word. * docs/formatdomain.html.in: Likewise. * src/qemu/qemu_process.c (qemuProcessStart): Likewise. * cfg.mk (exclude_file_name_regexp--sc_prohibit_can_not) (exclude_file_name_regexp--sc_prohibit_doubled_word): Exclude existing translation problems. --- * .gnulib 4a1579d...ca6143b (40): > autoupdate > maint.mk: prohibit doubled words > maint: fix doubled-word typo in comments > maint: remove doubled word: s/it it/it/ > maint.mk: remove useless semicolon and backslash > stdint test: Fix compilation failure on OSF/1 with DTK compiler. > autoupdate > maint: remove doubled words in comments, e.g., s/a a/a/ > test-chown.h: correct a cast > fix typo in ChangeLog entry > getaddrinfo: Fix test for sa_len member. > maint: change "can not" to "cannot" > maint: change "a a" to "a" > maint.mk: prohibit \ > maint: fix "the the" in comment > maint: change "can not" to "cannot" > maint.mk: prohibit use of "can not" > careadlinkat: Guard against misuse of careadlinkatcwd. > careadlinkat: Use common coding style. > careadlinkat: Clarify specification. > areadlinkat: Avoid link error on many platforms. > allocator, careadlinkat: Fix double-inclusion guard. > relocatable-prog-wrapper: Update after module 'areadlink' changed. > relocatable-prog-wrapper: Update after module 'areadlink' changed. > strftime: silence gnulib-tool warning > verify: Fix syntax error with GCC 4.6 in C++ mode. > autoupdate > allocator: New module. > * lib/stdlib.in.h (malloc, realloc): Limit this change to a smaller scope. > * lib/realloc.c (_GL_USE_STDLIB_ALLOC, malloc, realloc): Likewise. > * lib/malloc.c (_GL_USE_STDLIB_ALLOC, malloc): Likewise. > * lib/relocwrapper.c (_GL_USE_STDLIB_ALLOC, malloc): Likewise. > * lib/relocatable.c (_GL_USE_STDLIB_ALLOC, malloc): Likewise. > * lib/canonicalize-lgpl.c (_GL_USE_STDLIB_ALLOC, malloc): Likewise. > * lib/setenv.c (_GL_USE_STDLIB_ALLOC, malloc, realloc): Likewise. > * lib/progreloc.c (_GL_USE_STDLIB_ALLOC, malloc): Likewise. > * lib/malloca.c (_GL_USE_STDLIB_ALLOC, malloc): Likewise. > * lib/careadlinkat.c (_GL_USE_STDLIB_ALLOC): Define. > stdlib: let modules use system malloc, realloc > careadlinkat: rename members to avoid problem .gnulib | 2 +- cfg.mk | 4 ++++ docs/formatdomain.html.in | 2 +- include/libvirt/libvirt.h.in | 2 +- src/driver.c | 4 ++-- src/driver.h | 2 +- src/qemu/qemu_process.c | 2 +- src/remote/remote_driver.c | 2 +- src/storage/storage_backend.c | 4 ++-- src/util/pci.c | 6 +++--- 10 files changed, 17 insertions(+), 13 deletions(-) diff --git a/.gnulib b/.gnulib index 4a1579d..ca6143b 160000 --- a/.gnulib +++ b/.gnulib @@ -1 +1 @@ -Subproject commit 4a1579d7560659ef5723325726eda14490a967f6 +Subproject commit ca6143b425589c3a64bd28efd7af14463f96d576 diff --git a/cfg.mk b/cfg.mk index 4ed0d96..94db937 100644 --- a/cfg.mk +++ b/cfg.mk @@ -573,9 +573,13 @@ exclude_file_name_regexp--sc_prohibit_always_true_header_tests = \ exclude_file_name_regexp--sc_prohibit_asprintf = \ ^(bootstrap.conf$$|po/|src/util/util\.c$$|examples/domain-events/events-c/event-test\.c$$) +exclude_file_name_regexp--sc_prohibit_can_not = ^po/ + exclude_file_name_regexp--sc_prohibit_close = \ (\.py$$|^docs/|(src/util/files\.c|src/libvirt\.c)$$) +exclude_file_name_regexp--sc_prohibit_doubled_word = ^po/ + exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \ (^docs/api_extension/|^tests/qemuhelpdata/|\.(gif|ico|png)$$) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 574fee5..3c4c656 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -774,7 +774,7 @@ Since 0.0.3; "device" attribute since 0.1.4; "network" attribute since 0.8.7

    source
    -
    If the disk type is "file", then the +
    If the disk type is "file", then the file attribute specifies the fully-qualified path to the file holding the disk. If the disk type is "block", then the dev diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 04b7fbf..5783303 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -505,7 +505,7 @@ typedef virConnectCredential *virConnectCredentialPtr; * When authentication requires one or more interactions, this callback * is invoked. For each interaction supplied, data must be gathered * from the user and filled in to the 'result' and 'resultlen' fields. - * If an interaction can not be filled, fill in NULL and 0. + * If an interaction cannot be filled, fill in NULL and 0. * * Returns 0 if all interactions were filled, or -1 upon error */ diff --git a/src/driver.c b/src/driver.c index f882ea1..579c2b3 100644 --- a/src/driver.c +++ b/src/driver.c @@ -1,7 +1,7 @@ /* * driver.c: Helpers for loading drivers * - * Copyright (C) 2006-2010 Red Hat, Inc. + * Copyright (C) 2006-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -32,7 +32,7 @@ #define DEFAULT_DRIVER_DIR LIBDIR "/libvirt/connection-driver" -/* Make sure ... INTERNAL_CALL can not be set by the caller */ +/* Make sure ... INTERNAL_CALL cannot be set by the caller */ verify((VIR_SECRET_GET_VALUE_INTERNAL_CALL & VIR_SECRET_GET_VALUE_FLAGS_MASK) == 0); diff --git a/src/driver.h b/src/driver.h index e5f91ca..a8b79e6 100644 --- a/src/driver.h +++ b/src/driver.h @@ -1063,7 +1063,7 @@ struct _virDeviceMonitor { enum { /* This getValue call is inside libvirt, override the "private" flag. - This flag can not be set by outside callers. */ + This flag cannot be set by outside callers. */ VIR_SECRET_GET_VALUE_INTERNAL_CALL = 1 << 16 }; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 9ada24d..7295f9e 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2326,7 +2326,7 @@ int qemuProcessStart(virConnectPtr conn, ret = virCommandRun(cmd, NULL); VIR_FREE(pidfile); - /* wait for qemu process to to show up */ + /* wait for qemu process to show up */ if (ret == 0) { if (virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) { qemuReportError(VIR_ERR_INTERNAL_ERROR, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 9310ddf..5cb4f4c 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1223,7 +1223,7 @@ initialize_gnutls(char *pkipath, int flags) goto out_of_memory; /* Use default location as long as one of CA certificate, - * client key, and client certificate can not be found in + * client key, and client certificate cannot be found in * $HOME/.pki/libvirt, we don't want to make user confused * with one file is here, the other is there. */ diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index 8af2878..97a7e4b 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -703,7 +703,7 @@ virStorageBackendCreateQemuImg(virConnectPtr conn, (!inputBackingPath || STRNEQ(inputBackingPath, vol->backingStore.path))) { virStorageReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("a different backing store can not " + "%s", _("a different backing store cannot " "be specified.")); return -1; } @@ -1188,7 +1188,7 @@ virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target, *capacity = sb.st_size; } else { off_t end; - /* XXX this is POSIX compliant, but doesn't work for for CHAR files, + /* XXX this is POSIX compliant, but doesn't work for CHAR files, * only BLOCK. There is a Linux specific ioctl() for getting * size of both CHAR / BLOCK devices we should check for in * configure diff --git a/src/util/pci.c b/src/util/pci.c index 248afd3..ff950d1 100644 --- a/src/util/pci.c +++ b/src/util/pci.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 Red Hat, Inc. + * Copyright (C) 2009-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1073,7 +1073,7 @@ remove_id: * ID table so that 'drivers_probe' works below. */ if (pciDriverFile(&path, driver, "remove_id") < 0) { - /* We do not remove PCI ID from pci-stub, and we can not reprobe it */ + /* We do not remove PCI ID from pci-stub, and we cannot reprobe it */ if (dev->reprobe) { VIR_WARN("Could not remove PCI ID '%s' from %s, and the device " "cannot be probed again.", dev->id, driver); @@ -1087,7 +1087,7 @@ remove_id: _("Failed to remove PCI ID '%s' from %s"), dev->id, driver); - /* remove PCI ID from pci-stub failed, and we can not reprobe it */ + /* remove PCI ID from pci-stub failed, and we cannot reprobe it */ if (dev->reprobe) { VIR_WARN("Failed to remove PCI ID '%s' from %s, and the device " "cannot be probed again.", dev->id, driver); -- 1.7.4.2 From wency at cn.fujitsu.com Tue Apr 12 01:39:04 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Tue, 12 Apr 2011 09:39:04 +0800 Subject: [libvirt] [PATCH] maint: fix grammar errors In-Reply-To: <1302560839-23381-1-git-send-email-eblake@redhat.com> References: <1302560839-23381-1-git-send-email-eblake@redhat.com> Message-ID: <4DA3AD38.2000607@cn.fujitsu.com> At 04/12/2011 06:27 AM, Eric Blake Write: > Jim recently improved gnulib to catch various grammar errors > during 'make syntax-check'. > > * .gnulib: Update to latest, for syntax-check improvements. > * include/libvirt/libvirt.h.in (virConnectAuthCallbackPtr): Use > cannot rather than two words. > * src/driver.c: Likewise. > * src/driver.h (VIR_SECRET_GET_VALUE_INTERNAL_CALL): Likewise. > * src/remote/remote_driver.c (initialize_gnutls): Likewise. > * src/util/pci.c (pciBindDeviceToStub): Likewise. > * src/storage/storage_backend.c (virStorageBackendCreateQemuImg): > Likewise. > (virStorageBackendUpdateVolTargetInfoFD): Avoid doubled word. > * docs/formatdomain.html.in: Likewise. > * src/qemu/qemu_process.c (qemuProcessStart): Likewise. > * cfg.mk (exclude_file_name_regexp--sc_prohibit_can_not) > (exclude_file_name_regexp--sc_prohibit_doubled_word): Exclude > existing translation problems. > --- > > * .gnulib 4a1579d...ca6143b (40): > > autoupdate > > maint.mk: prohibit doubled words > > maint: fix doubled-word typo in comments > > maint: remove doubled word: s/it it/it/ > > maint.mk: remove useless semicolon and backslash > > stdint test: Fix compilation failure on OSF/1 with DTK compiler. > > autoupdate > > maint: remove doubled words in comments, e.g., s/a a/a/ > > test-chown.h: correct a cast > > fix typo in ChangeLog entry > > getaddrinfo: Fix test for sa_len member. > > maint: change "can not" to "cannot" > > maint: change "a a" to "a" > > maint.mk: prohibit \ > > maint: fix "the the" in comment > > maint: change "can not" to "cannot" > > maint.mk: prohibit use of "can not" > > careadlinkat: Guard against misuse of careadlinkatcwd. > > careadlinkat: Use common coding style. > > careadlinkat: Clarify specification. > > areadlinkat: Avoid link error on many platforms. > > allocator, careadlinkat: Fix double-inclusion guard. > > relocatable-prog-wrapper: Update after module 'areadlink' changed. > > relocatable-prog-wrapper: Update after module 'areadlink' changed. > > strftime: silence gnulib-tool warning > > verify: Fix syntax error with GCC 4.6 in C++ mode. > > autoupdate > > allocator: New module. > > * lib/stdlib.in.h (malloc, realloc): Limit this change to a smaller scope. > > * lib/realloc.c (_GL_USE_STDLIB_ALLOC, malloc, realloc): Likewise. > > * lib/malloc.c (_GL_USE_STDLIB_ALLOC, malloc): Likewise. > > * lib/relocwrapper.c (_GL_USE_STDLIB_ALLOC, malloc): Likewise. > > * lib/relocatable.c (_GL_USE_STDLIB_ALLOC, malloc): Likewise. > > * lib/canonicalize-lgpl.c (_GL_USE_STDLIB_ALLOC, malloc): Likewise. > > * lib/setenv.c (_GL_USE_STDLIB_ALLOC, malloc, realloc): Likewise. > > * lib/progreloc.c (_GL_USE_STDLIB_ALLOC, malloc): Likewise. > > * lib/malloca.c (_GL_USE_STDLIB_ALLOC, malloc): Likewise. > > * lib/careadlinkat.c (_GL_USE_STDLIB_ALLOC): Define. > > stdlib: let modules use system malloc, realloc > > careadlinkat: rename members to avoid problem > > .gnulib | 2 +- > cfg.mk | 4 ++++ > docs/formatdomain.html.in | 2 +- > include/libvirt/libvirt.h.in | 2 +- > src/driver.c | 4 ++-- > src/driver.h | 2 +- > src/qemu/qemu_process.c | 2 +- > src/remote/remote_driver.c | 2 +- > src/storage/storage_backend.c | 4 ++-- > src/util/pci.c | 6 +++--- > 10 files changed, 17 insertions(+), 13 deletions(-) > > diff --git a/.gnulib b/.gnulib > index 4a1579d..ca6143b 160000 > --- a/.gnulib > +++ b/.gnulib > @@ -1 +1 @@ > -Subproject commit 4a1579d7560659ef5723325726eda14490a967f6 > +Subproject commit ca6143b425589c3a64bd28efd7af14463f96d576 > diff --git a/cfg.mk b/cfg.mk > index 4ed0d96..94db937 100644 > --- a/cfg.mk > +++ b/cfg.mk > @@ -573,9 +573,13 @@ exclude_file_name_regexp--sc_prohibit_always_true_header_tests = \ > exclude_file_name_regexp--sc_prohibit_asprintf = \ > ^(bootstrap.conf$$|po/|src/util/util\.c$$|examples/domain-events/events-c/event-test\.c$$) > > +exclude_file_name_regexp--sc_prohibit_can_not = ^po/ > + > exclude_file_name_regexp--sc_prohibit_close = \ > (\.py$$|^docs/|(src/util/files\.c|src/libvirt\.c)$$) > > +exclude_file_name_regexp--sc_prohibit_doubled_word = ^po/ > + > exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \ > (^docs/api_extension/|^tests/qemuhelpdata/|\.(gif|ico|png)$$) > > diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in > index 574fee5..3c4c656 100644 > --- a/docs/formatdomain.html.in > +++ b/docs/formatdomain.html.in > @@ -774,7 +774,7 @@ > Since 0.0.3; "device" attribute since 0.1.4; > "network" attribute since 0.8.7
    >
    source
    > -
    If the disk type is "file", then the > +
    If the disk type is "file", then > the file attribute specifies the fully-qualified > path to the file holding the disk. If the disk > type is "block", then the dev > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > index 04b7fbf..5783303 100644 > --- a/include/libvirt/libvirt.h.in > +++ b/include/libvirt/libvirt.h.in > @@ -505,7 +505,7 @@ typedef virConnectCredential *virConnectCredentialPtr; > * When authentication requires one or more interactions, this callback > * is invoked. For each interaction supplied, data must be gathered > * from the user and filled in to the 'result' and 'resultlen' fields. > - * If an interaction can not be filled, fill in NULL and 0. > + * If an interaction cannot be filled, fill in NULL and 0. > * > * Returns 0 if all interactions were filled, or -1 upon error > */ > diff --git a/src/driver.c b/src/driver.c > index f882ea1..579c2b3 100644 > --- a/src/driver.c > +++ b/src/driver.c > @@ -1,7 +1,7 @@ > /* > * driver.c: Helpers for loading drivers > * > - * Copyright (C) 2006-2010 Red Hat, Inc. > + * Copyright (C) 2006-2011 Red Hat, Inc. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public > @@ -32,7 +32,7 @@ > > #define DEFAULT_DRIVER_DIR LIBDIR "/libvirt/connection-driver" > > -/* Make sure ... INTERNAL_CALL can not be set by the caller */ > +/* Make sure ... INTERNAL_CALL cannot be set by the caller */ > verify((VIR_SECRET_GET_VALUE_INTERNAL_CALL & > VIR_SECRET_GET_VALUE_FLAGS_MASK) == 0); > > diff --git a/src/driver.h b/src/driver.h > index e5f91ca..a8b79e6 100644 > --- a/src/driver.h > +++ b/src/driver.h > @@ -1063,7 +1063,7 @@ struct _virDeviceMonitor { > > enum { > /* This getValue call is inside libvirt, override the "private" flag. > - This flag can not be set by outside callers. */ > + This flag cannot be set by outside callers. */ > VIR_SECRET_GET_VALUE_INTERNAL_CALL = 1 << 16 > }; > > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > index 9ada24d..7295f9e 100644 > --- a/src/qemu/qemu_process.c > +++ b/src/qemu/qemu_process.c > @@ -2326,7 +2326,7 @@ int qemuProcessStart(virConnectPtr conn, > ret = virCommandRun(cmd, NULL); > VIR_FREE(pidfile); > > - /* wait for qemu process to to show up */ > + /* wait for qemu process to show up */ > if (ret == 0) { > if (virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) { > qemuReportError(VIR_ERR_INTERNAL_ERROR, > diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c > index 9310ddf..5cb4f4c 100644 > --- a/src/remote/remote_driver.c > +++ b/src/remote/remote_driver.c > @@ -1223,7 +1223,7 @@ initialize_gnutls(char *pkipath, int flags) > goto out_of_memory; > > /* Use default location as long as one of CA certificate, > - * client key, and client certificate can not be found in > + * client key, and client certificate cannot be found in > * $HOME/.pki/libvirt, we don't want to make user confused > * with one file is here, the other is there. > */ > diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c > index 8af2878..97a7e4b 100644 > --- a/src/storage/storage_backend.c > +++ b/src/storage/storage_backend.c > @@ -703,7 +703,7 @@ virStorageBackendCreateQemuImg(virConnectPtr conn, > (!inputBackingPath || > STRNEQ(inputBackingPath, vol->backingStore.path))) { > virStorageReportError(VIR_ERR_INTERNAL_ERROR, > - "%s", _("a different backing store can not " > + "%s", _("a different backing store cannot " > "be specified.")); > return -1; > } > @@ -1188,7 +1188,7 @@ virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target, > *capacity = sb.st_size; > } else { > off_t end; > - /* XXX this is POSIX compliant, but doesn't work for for CHAR files, > + /* XXX this is POSIX compliant, but doesn't work for CHAR files, > * only BLOCK. There is a Linux specific ioctl() for getting > * size of both CHAR / BLOCK devices we should check for in > * configure > diff --git a/src/util/pci.c b/src/util/pci.c > index 248afd3..ff950d1 100644 > --- a/src/util/pci.c > +++ b/src/util/pci.c > @@ -1,5 +1,5 @@ > /* > - * Copyright (C) 2009-2010 Red Hat, Inc. > + * Copyright (C) 2009-2011 Red Hat, Inc. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public > @@ -1073,7 +1073,7 @@ remove_id: > * ID table so that 'drivers_probe' works below. > */ > if (pciDriverFile(&path, driver, "remove_id") < 0) { > - /* We do not remove PCI ID from pci-stub, and we can not reprobe it */ > + /* We do not remove PCI ID from pci-stub, and we cannot reprobe it */ Sorry for my bad english. I only modify the grammar errors in error messages, and do not notice the comment. > if (dev->reprobe) { > VIR_WARN("Could not remove PCI ID '%s' from %s, and the device " > "cannot be probed again.", dev->id, driver); > @@ -1087,7 +1087,7 @@ remove_id: > _("Failed to remove PCI ID '%s' from %s"), > dev->id, driver); > > - /* remove PCI ID from pci-stub failed, and we can not reprobe it */ > + /* remove PCI ID from pci-stub failed, and we cannot reprobe it */ > if (dev->reprobe) { > VIR_WARN("Failed to remove PCI ID '%s' from %s, and the device " > "cannot be probed again.", dev->id, driver); I modify cfg.mk and update gnulib, use 'make syntax-check' and found the same grammar errors. ACK. From usui at mxm.nes.nec.co.jp Tue Apr 12 02:43:32 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Tue, 12 Apr 2011 11:43:32 +0900 Subject: [libvirt] [PATCHv2 1/6] virNodeGetCPUTime: Expose new API In-Reply-To: <20110410045856.GI24838@redhat.com> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> <20110408203312.90723b75.usui@mxm.nes.nec.co.jp> <20110410045856.GI24838@redhat.com> Message-ID: <20110412114332.8376455b.usui@mxm.nes.nec.co.jp> Hi, Daniel. Thank you for your review. On Sun, 10 Apr 2011 12:58:56 +0800 Daniel Veillard wrote: > On Fri, Apr 08, 2011 at 08:33:12PM +0900, Minoru Usui wrote: > > virNodeGetCPUTime: Expose new API > > > > Signed-off-by: Minoru Usui > > --- > > include/libvirt/libvirt.h.in | 64 ++++++++++++++++++++++++++++++++++++++++++ > > src/libvirt_public.syms | 5 +++ > > 2 files changed, 69 insertions(+), 0 deletions(-) > > > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > > index bd36015..154c138 100644 > > --- a/include/libvirt/libvirt.h.in > > +++ b/include/libvirt/libvirt.h.in > > @@ -228,6 +228,57 @@ struct _virNodeInfo { > > unsigned int threads;/* number of threads per core */ > > }; > > > > +/** > > + * virNodeCpuTime: > > + * > > + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing > > + * the information for the cpu time of the node. > > + */ > > + > > +/** > > + * Cpu Time Statistics Tags: > > + */ > > +typedef enum { > > + /* > > + * The cumulative CPU time which spends by kernel, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_KERNEL = 0, > > + /* > > + * The cumulative CPU time which spends by user processes, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_USER = 1, > > + /* > > + * The cumulative idle CPU time, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_IDLE = 2, > > + /* > > + * The cumulative I/O wait CPU time, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_IOWAIT = 3, > > + /* > > + * The CPU utilization. > > + * The usage value is in percent and 100% represents all CPUs on > > + * the server. > > + */ > > + VIR_NODE_CPU_TIME_UTILIZATION = 4, > > + > > + /* > > + * The number of statistics supported by this version of the interface. > > + * To add new statistics, add them to the enum and increase this value. > > + */ > > + VIR_NODE_CPU_TIME_NR = 5, > > +} virNodeCpuTimeTags; > > + > > +typedef struct _virNodeCpuTime virNodeCpuTime; > > + > > +struct _virNodeCpuTime { > > + virNodeCpuTimeTags tag; > > + unsigned long long val; > > +}; > > NACK, the size of an enum is not defined by the C language and > hence is compiler dependant. We cannot use it as a component of a > structure in the API. OK. I'll change the enum to int. > > /** > > * virDomainSchedParameterType: > > @@ -460,6 +511,14 @@ int virDomainMigrateSetMaxSpeed(virDomainPtr domain, > > typedef virNodeInfo *virNodeInfoPtr; > > > > /** > > + * virNodeCpuTimePtr: > > + * > > + * a virNodeCpuTimePtr is a pointer to a virNodeCpuTime structure. > > + */ > > + > > +typedef virNodeCpuTime *virNodeCpuTimePtr; > > + > > +/** > > * virConnectFlags > > * > > * Flags when opening a connection to a hypervisor > > @@ -593,6 +652,11 @@ int virNodeGetInfo (virConnectPtr conn, > > virNodeInfoPtr info); > > char * virConnectGetCapabilities (virConnectPtr conn); > > > > +int virNodeGetCpuTime (virConnectPtr conn, > > + virNodeCpuTimePtr stats, > > + unsigned int nr_stats, > > + unsigned int flags); > > + > > I don't understand how the API is suppoed to work. Suppose you want > the cumulative CPU time, how do you ask for it ? Seems you can't ! You > just ask for a big stucture hoping that on return you may find it within > the results. That looks broken to me. > > Either you make a simple API giving back an unsigned long long and > you use the virNodeCpuTimeTags as the flag value > > int virNodeGetCpuTime(virConnectPtr conn, unsigned long long *time, > unsigned int flags); > > and the flags indicate the value you're interested into, but in that > case you have to ask multiple times. Or you make the VIR_NODE_CPU_TIME_* > values a bit field, and you pass an array > > int virNodeGetCpuTime(virConnectPtr conn, > unsigned long long *stats, > unsigned int nr_stats, > unsigned int flags); > > where flags is the logical or of the values you are interested into, and > the implementation put them in order based on the VIR_NODE_CPU_TIME_* > values. But in that case you must fail if one of the statistics is not > available. > > But an API where you "go fishing" and you don't know upfront on a > successful return if you got the data you're interested into sounds > broken to me Thank you for your useful advice. I think the API user would be better to request which values return, too. I'll change the I/F to above 2nd style. > > Daniel > > -- > Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ > daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ > http://veillard.com/ | virtualization library http://libvirt.org/ -- Minoru Usui From hutao at cn.fujitsu.com Tue Apr 12 03:34:07 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Tue, 12 Apr 2011 11:34:07 +0800 Subject: [libvirt] [PATCH 3/6] use virObject to manage reference-count of virDomainObj In-Reply-To: <4D9CEA54.6000402@redhat.com> References: <4D9CEA54.6000402@redhat.com> Message-ID: <20110412033407.GA32561@localhost.localdomain> Caught Segmentation violation dumping internal log buffer: ====== start of log ===== e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=191 w=202, f=208 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=192 w=203, f=209 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=193 w=204, f=210 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=194 w=205, f=211 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=195 w=206, f=212 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=196 w=207, f=213 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=197 w=208, f=214 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=198 w=209, f=215 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=199 w=210, f=32 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=200 w=211, f=36 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=201 w=212, f=18 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=202 w=213, f=38 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=203 w=214, f=14 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=204 w=215, f=40 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=205 w=216, f=19 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=206 w=217, f=25 e=1 d=0 09:56:30.559: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=207 w=218, f=21 e=1 d=0 09:56:30.559: 21798: debug : virEventPollCalculateTimeout:310 : Calculate expiry of 2 timers 09:56:30.559: 21798: debug : virEventPollCalculateTimeout:342 : Timeout at 0 due in -1 ms 09:56:30.559: 21798: debug : virEventPollRunOnce:605 : Poll on 207 handles 0x7f6ce2520bd0 timeout -1 09:56:32.000: 21799: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=21 09:56:32.000: 21799: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.000: 21799: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=20 09:56:32.000: 21799: debug : virDomainFree:2083 : dom=0x7f6d18000d00, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), 09:56:32.000: 21799: debug : virUnrefDomain:276 : unref domain 0x7f6d18000d00 hut-vm1 1 09:56:32.000: 21799: debug : virReleaseDomain:238 : release domain 0x7f6d18000d00 hut-vm1 68698441-bf5f-4f16-b277-dc22258875ec 09:56:32.000: 21799: debug : virReleaseDomain:246 : unref connection 0x7f6d10002cc0 2 09:56:32.000: 21799: debug : remoteSerializeError:141 : prog=536903814 ver=1 proc=53 type=1 serial=4, msg=Timed out during operation: cannot acquire state change lock 09:56:32.001: 21799: debug : virEventPollUpdateHandle:144 : Update handle w=10 e=3 09:56:32.001: 21799: debug : virEventPollInterruptLocked:690 : Interrupting 09:56:32.001: 21799: debug : remoteDispatchClientRequest:372 : prog=536903814 ver=1 type=0 status=0 serial=5 proc=2 09:56:32.001: 21799: debug : virEventPollUpdateHandle:144 : Update handle w=17 e=3 09:56:32.001: 21799: debug : virEventPollInterruptLocked:690 : Interrupting 09:56:32.001: 21799: debug : remoteDispatchClientRequest:372 : prog=536903814 ver=1 type=0 status=0 serial=4 proc=53 09:56:32.001: 21799: debug : virDomainCoreDump:2363 : dom=0x7f6d18000d00, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), to=/mnt/data/dumps/dump-hut-vm1.1, flags=0 09:56:32.001: 21799: debug : virDomainObjRef:988 : obj=0x12deff0 refs=21 09:56:32.001: 21801: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=20 09:56:32.001: 21801: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.001: 21801: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=19 09:56:32.001: 21801: debug : virDomainFree:2083 : dom=0x7f6d14000f70, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), 09:56:32.001: 21801: debug : virUnrefDomain:276 : unref domain 0x7f6d14000f70 hut-vm1 1 09:56:32.001: 21801: debug : virReleaseDomain:238 : release domain 0x7f6d14000f70 hut-vm1 68698441-bf5f-4f16-b277-dc22258875ec 09:56:32.001: 21801: debug : virReleaseDomain:246 : unref connection 0x7f6d10002460 2 09:56:32.001: 21801: debug : remoteSerializeError:141 : prog=536903814 ver=1 proc=53 type=1 serial=4, msg=Timed out during operation: cannot acquire state change lock 09:56:32.001: 21798: debug : virEventPollRunOnce:616 : Poll got 1 event(s) 09:56:32.001: 21798: debug : virEventPollDispatchTimeouts:406 : Dispatch 2 09:56:32.001: 21798: debug : virEventPollDispatchHandles:453 : Dispatch 207 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=0 w=1 09:56:32.001: 21798: debug : virEventPollDispatchHandles:480 : Dispatch n=0 f=3 w=1 e=1 (nil) 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=1 w=2 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=3 w=4 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=4 w=5 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=5 w=6 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=6 w=7 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=7 w=9 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=8 w=10 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=9 w=12 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=10 w=15 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=11 w=17 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=12 w=18 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=13 w=19 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=14 w=21 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=15 w=22 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=16 w=23 09:56:32.001: 21801: debug : virEventPollUpdateHandle:144 : Update handle w=19 e=3 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=17 w=24 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=18 w=25 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=19 w=26 09:56:32.001: 21803: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=18 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=20 w=27 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=21 w=28 09:56:32.001: 21803: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=22 w=29 09:56:32.001: 21803: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=17 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=23 w=31 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=24 w=33 09:56:32.001: 21803: debug : virDomainFree:2083 : dom=0x7f6d10002660, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=25 w=35 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=26 w=37 09:56:32.001: 21803: debug : virUnrefDomain:276 : unref domain 0x7f6d10002660 hut-vm1 1 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=27 w=38 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=28 w=39 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=29 w=40 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=30 w=41 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=31 w=42 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=32 w=43 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=33 w=44 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=34 w=45 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=35 w=46 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=36 w=47 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=37 w=48 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=38 w=49 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=39 w=50 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=40 w=51 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=41 w=52 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=42 w=53 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=43 w=54 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=44 w=55 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=45 w=56 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=46 w=57 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=47 w=58 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=48 w=59 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=49 w=60 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=50 w=61 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=51 w=62 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=52 w=63 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=53 w=64 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=54 w=65 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=55 w=66 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=56 w=67 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=57 w=68 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=58 w=69 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=59 w=70 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=60 w=71 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=61 w=72 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=62 w=73 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=63 w=74 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=64 w=75 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=65 w=76 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=66 w=77 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=67 w=78 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=68 w=79 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=69 w=80 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=70 w=81 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=71 w=82 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=72 w=83 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=73 w=84 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=74 w=85 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=75 w=86 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=76 w=87 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=77 w=88 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=78 w=89 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=79 w=90 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=80 w=91 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=81 w=92 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=82 w=93 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=83 w=94 09:56:32.001:09:56:32.006: 21798: debug : virConnectClose:1319 : conn=0x7f6cfc000a10 09:56:32.006: 21798: debug : virUnrefConnect:145 : unref connection 0x7f6cfc000a10 1 09:56:32.006: 21798: debug : virReleaseConnect:94 : release connection 0x7f6cfc000a10 ollDispatchHandles:467 : i=87 w=98 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=88 w=99 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=89 w=100 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=90 w=101 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=91 w=102 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=92 w=103 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=93 w=104 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=94 w=105 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=95 w=106 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=96 w=107 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=97 w=108 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=98 w=109 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=99 w=110 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=100 w=111 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=101 w=112 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=102 w=113 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=103 w=114 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=104 w=115 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=105 w=116 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=106 w=117 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=107 w=118 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=108 w=119 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=109 w=120 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=110 w=121 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=111 w=122 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=112 w=123 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=113 w=124 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=114 w=125 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=115 w=126 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=116 w=127 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=117 w=128 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=118 w=129 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=119 w=130 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=120 w=131 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=121 w=132 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=122 w=133 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=123 w=134 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=124 w=135 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=125 w=136 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=126 w=137 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=127 w=138 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=128 w=139 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=129 w=140 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=130 w=141 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=131 w=142 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=132 w=143 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=133 w=144 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=134 w=145 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=135 w=146 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=136 w=147 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=137 w=148 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=138 w=149 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=139 w=150 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=140 w=151 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=141 w=152 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=142 w=153 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=143 w=154 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=144 w=155 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=145 w=156 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=146 w=157 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=147 w=158 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=148 w=159 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=149 w=160 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=150 w=161 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=151 w=162 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=152 w=163 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=153 w=164 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=154 w=165 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=155 w=166 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=156 w=167 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=157 w=168 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=158 w=169 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=159 w=170 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=160 w=171 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=161 w=172 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=162 w=173 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=163 w=174 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=164 w=175 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=165 w=176 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=166 w=177 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=167 w=178 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=168 w=179 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=169 w=180 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=170 w=181 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=171 w=182 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=172 w=183 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=173 w=184 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=174 w=185 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=175 w=186 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=176 w=187 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=177 w=188 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=178 w=189 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=179 w=190 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=180 w=191 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=181 w=192 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=182 w=193 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=183 w=194 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=184 w=195 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=185 w=196 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=186 w=197 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=187 w=198 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=188 w=199 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=189 w=200 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=190 w=201 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=191 w=202 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=192 w=203 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=193 w=204 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=194 w=205 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=195 w=206 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=196 w=207 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=197 w=208 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=198 w=209 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=199 w=210 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=200 w=211 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=201 w=212 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=202 w=213 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=203 w=214 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=204 w=215 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=205 w=216 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=206 w=217 09:56:32.001: 21798: debug : virEventPollDispatchHandles:467 : i=207 w=218 09:56:32.001: 21798: debug : virEventPollCleanupTimeouts:498 : Cleanup 2 09:56:32.001: 21798: debug : virEventPollCleanupHandles:545 : Cleanup 208 09:56:32.001: 22033: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=16 09:56:32.001: 21801: debug : virEventPollInterruptLocked:686 : Skip interrupt, 0 701839104 09:56:32.001: 22033: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.001: 22033: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=15 09:56:32.001: 22033: debug : virDomainFree:2083 : dom=0x7f6d000009f0, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), 09:56:32.001: 22033: debug : virUnrefDomain:276 : unref domain 0x7f6d000009f0 hut-vm1 1 09:56:32.001: 22033: debug : virReleaseDomain:238 : release domain 0x7f6d000009f0 hut-vm1 68698441-bf5f-4f16-b277-dc22258875ec 09:56:32.001: 22033: debug : virReleaseDomain:246 : unref connection 0x7f6d18000b00 2 09:56:32.001: 21803: debug : virReleaseDomain:238 : release domain 0x7f6d10002660 hut-vm1 68698441-bf5f-4f16-b277-dc22258875ec 09:56:32.001: 21803: debug : virReleaseDomain:246 : unref connection 0x7f6d10002740 2 09:56:32.001: 21798: debug : virEventRunDefaultImpl:188 : 09:56:32.001: 21798: debug : virEventPollCleanupTimeouts:498 : Cleanup 2 09:56:32.001: 21798: debug : virEventPollCleanupHandles:545 : Cleanup 208 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=0 w=1, f=3 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=1 w=2, f=5 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=2 w=3, f=11 e=0 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=3 w=4, f=11 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=4 w=5, f=12 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=5 w=6, f=8 e=25 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=6 w=7, f=7 e=25 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=7 w=9, f=17 e=25 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=8 w=10, f=13 e=5 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=9 w=12, f=16 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=10 w=15, f=20 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=11 w=17, f=22 e=5 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=12 w=18, f=23 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=13 w=19, f=24 e=5 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=14 w=21, f=26 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=15 w=22, f=27 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=16 w=23, f=28 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=17 w=24, f=29 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=18 w=25, f=30 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=19 w=26, f=31 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=20 w=27, f=33 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=21 w=28, f=34 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=22 w=29, f=35 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=23 w=31, f=37 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=24 w=33, f=39 e=1 d=0 09:56:32.001: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=25 w=35, f=41 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=26 w=37, f=43 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=27 w=38, f=44 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=28 w=39, f=45 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=29 w=40, f=46 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=30 w=41, f=47 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=31 w=42, f=48 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=32 w=43, f=49 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=33 w=44, f=50 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=34 w=45, f=51 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=35 w=46, f=52 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=36 w=47, f=53 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=37 w=48, f=54 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=38 w=49, f=55 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=39 w=50, f=56 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=40 w=51, f=57 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=41 w=52, f=58 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=42 w=53, f=59 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=43 w=54, f=60 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=44 w=55, f=61 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=45 w=56, f=62 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=46 w=57, f=63 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=47 w=58, f=64 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=48 w=59, f=65 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=49 w=60, f=66 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=50 w=61, f=67 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=51 w=62, f=68 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=52 w=63, f=69 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=53 w=64, f=70 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=54 w=65, f=71 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=55 w=66, f=72 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=56 w=67, f=73 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=57 w=68, f=74 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=58 w=69, f=75 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=59 w=70, f=76 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=60 w=71, f=77 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=61 w=72, f=78 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=62 w=73, f=79 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=63 w=74, f=80 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=64 w=75, f=81 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=65 w=76, f=82 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=66 w=77, f=83 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=67 w=78, f=84 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=68 w=79, f=85 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=69 w=80, f=86 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=70 w=81, f=87 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=71 w=82, f=88 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=72 w=83, f=89 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=73 w=84, f=90 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=74 w=85, f=91 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=75 w=86, f=92 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=76 w=87, f=93 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=77 w=88, f=94 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=78 w=89, f=95 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=79 w=90, f=96 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=80 w=91, f=97 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=81 w=92, f=98 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=82 w=93, f=99 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=83 w=94, f=100 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=84 w=95, f=101 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=85 w=96, f=102 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=86 w=97, f=103 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=87 w=98, f=104 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=88 w=99, f=105 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=89 w=100, f=106 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=90 w=101, f=107 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=91 w=102, f=108 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=92 w=103, f=109 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=93 w=104, f=110 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=94 w=105, f=111 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=95 w=106, f=112 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=96 w=107, f=113 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=97 w=108, f=114 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=98 w=109, f=115 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=99 w=110, f=116 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=100 w=111, f=117 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=101 w=112, f=118 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=102 w=113, f=119 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=103 w=114, f=120 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=104 w=115, f=121 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=105 w=116, f=122 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=106 w=117, f=123 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=107 w=118, f=124 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=108 w=119, f=125 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=109 w=120, f=126 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=110 w=121, f=127 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=111 w=122, f=128 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=112 w=123, f=129 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=113 w=124, f=130 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=114 w=125, f=131 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=115 w=126, f=132 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=116 w=127, f=133 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=117 w=128, f=134 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=118 w=129, f=135 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=119 w=130, f=136 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=120 w=131, f=137 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=121 w=132, f=138 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=122 w=133, f=139 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=123 w=134, f=140 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=124 w=135, f=141 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=125 w=136, f=142 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=126 w=137, f=143 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=127 w=138, f=144 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=128 w=139, f=145 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=129 w=140, f=146 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=130 w=141, f=147 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=131 w=142, f=148 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=132 w=143, f=149 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=133 w=144, f=150 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=134 w=145, f=151 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=135 w=146, f=152 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=136 w=147, f=153 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=137 w=148, f=154 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=138 w=149, f=155 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=139 w=150, f=156 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=140 w=151, f=157 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=141 w=152, f=158 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=142 w=153, f=159 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=143 w=154, f=160 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=144 w=155, f=161 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=145 w=156, f=162 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=146 w=157, f=163 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=147 w=158, f=164 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=148 w=159, f=165 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=149 w=160, f=166 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=150 w=161, f=167 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=151 w=162, f=168 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=152 w=163, f=169 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=153 w=164, f=170 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=154 w=165, f=171 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=155 w=166, f=172 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=156 w=167, f=173 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=157 w=168, f=174 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=158 w=169, f=175 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=159 w=170, f=176 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=160 w=171, f=177 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=161 w=172, f=178 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=162 w=173, f=179 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=163 w=174, f=180 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=164 w=175, f=181 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=165 w=176, f=182 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=166 w=177, f=183 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=167 w=178, f=184 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=168 w=179, f=185 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=169 w=180, f=186 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=170 w=181, f=187 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=171 w=182, f=188 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=172 w=183, f=189 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=173 w=184, f=190 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=174 w=185, f=191 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=175 w=186, f=192 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=176 w=187, f=193 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=177 w=188, f=194 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=178 w=189, f=195 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=179 w=190, f=196 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=180 w=191, f=197 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=181 w=192, f=198 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=182 w=193, f=199 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=183 w=194, f=200 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=184 w=195, f=201 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=185 w=196, f=202 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=186 w=197, f=203 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=187 w=198, f=204 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=188 w=199, f=205 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=189 w=200, f=206 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=190 w=201, f=207 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=191 w=202, f=208 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=192 w=203, f=209 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=193 w=204, f=210 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=194 w=205, f=211 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=195 w=206, f=212 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=196 w=207, f=213 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=197 w=208, f=214 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=198 w=209, f=215 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=199 w=210, f=32 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=200 w=211, f=36 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=201 w=212, f=18 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=202 w=213, f=38 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=203 w=214, f=14 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=204 w=215, f=40 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=205 w=216, f=19 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=206 w=217, f=25 e=1 d=0 09:56:32.002: 21798: debug : virEventPollMakePollFDs:374 : Prepare n=207 w=218, f=21 e=1 d=0 09:56:32.002: 21798: debug : virEventPollCalculateTimeout:310 : Calculate expiry of 2 timers 09:56:32.002: 21798: debug : virEventPollCalculateTimeout:342 : Timeout at 0 due in -1 ms 09:56:32.002: 21798: debug : virEventPollRunOnce:605 : Poll on 207 handles 0x7f6ce2520bd0 timeout -1 09:56:32.002: 21798: debug : virEventPollRunOnce:616 : Poll got 4 event(s) 09:56:32.002: 21798: debug : virEventPollDispatchTimeouts:406 : Dispatch 2 09:56:32.002: 21798: debug : virEventPollDispatchHandles:453 : Dispatch 207 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=0 w=1 09:56:32.002: 21798: debug : virEventPollDispatchHandles:480 : Dispatch n=0 f=3 w=1 e=1 (nil) 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=1 w=2 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=3 w=4 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=4 w=5 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=5 w=6 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=6 w=7 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=7 w=9 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=8 w=10 09:56:32.002: 21798: debug : virEventPollDispatchHandles:480 : Dispatch n=8 f=13 w=10 e=4 0x12b20d0 09:56:32.002: 21798: debug : virEventPollUpdateHandle:144 : Update handle w=10 e=1 09:56:32.002: 21798: debug : virEventPollInterruptLocked:686 : Skip interrupt, 1 701839104 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=9 w=12 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=10 w=15 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=11 w=17 09:56:32.002: 21798: debug : virEventPollDispatchHandles:480 : Dispatch n=11 f=22 w=17 e=4 0x12b20d0 09:56:32.002: 21798: debug : virEventPollUpdateHandle:144 : Update handle w=17 e=1 09:56:32.002: 21798: debug : virEventPollInterruptLocked:686 : Skip interrupt, 1 701839104 09:56:32.002: 21798: debug : virEventPollRemoveHandle:171 : Remove handle w=17 09:56:32.002: 21798: debug : virEventPollRemoveHandle:184 : mark delete 11 22 09:56:32.002: 21798: debug : virEventPollInterruptLocked:686 : Skip interrupt, 1 701839104 09:56:32.002: 21798: debug : qemudDispatchClientFailure:1567 : CLIENT_DISCONNECT: fd=22 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=12 w=18 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=13 w=19 09:56:32.002: 21798: debug : virEventPollDispatchHandles:480 : Dispatch n=13 f=24 w=19 e=4 0x12b20d0 09:56:32.002: 21798: debug : virEventPollUpdateHandle:144 : Update handle w=19 e=1 09:56:32.002: 21798: debug : virEventPollInterruptLocked:686 : Skip interrupt, 1 701839104 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=14 w=21 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=15 w=22 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=16 w=23 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=17 w=24 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=18 w=25 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=19 w=26 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=20 w=27 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=21 w=28 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=22 w=29 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=23 w=31 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=24 w=33 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=25 w=35 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=26 w=37 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=27 w=38 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=28 w=39 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=29 w=40 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=30 w=41 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=31 w=42 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=32 w=43 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=33 w=44 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=34 w=45 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=35 w=46 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=36 w=47 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=37 w=48 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=38 w=49 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=39 w=50 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=40 w=51 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=41 w=52 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=42 w=53 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=43 w=54 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=44 w=55 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=45 w=56 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=46 w=57 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=47 w=58 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=48 w=59 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=49 w=60 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=50 w=61 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=51 w=62 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=52 w=63 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=53 w=64 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=54 w=65 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=55 w=66 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=56 w=67 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=57 w=68 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=58 w=69 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=59 w=70 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=60 w=71 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=61 w=72 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=62 w=73 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=63 w=74 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=64 w=75 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=65 w=76 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=66 w=77 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=67 w=78 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=68 w=79 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=69 w=80 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=70 w=81 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=71 w=82 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=72 w=83 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=73 w=84 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=74 w=85 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=75 w=86 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=76 w=87 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=77 w=88 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=78 w=89 09:56:32.002: 21798: debug : virEventPollDispatchHandles:467 : i=79 w=90 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=80 w=91 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=81 w=92 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=82 w=93 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=83 w=94 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=84 w=95 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=85 w=96 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=86 w=97 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=87 w=98 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=88 w=99 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=89 w=100 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=90 w=101 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=91 w=102 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=92 w=103 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=93 w=104 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=94 w=105 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=95 w=106 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=96 w=107 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=97 w=108 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=98 w=109 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=99 w=110 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=100 w=111 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=101 w=112 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=102 w=113 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=103 w=114 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=104 w=115 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=105 w=116 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=106 w=117 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=107 w=118 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=108 w=119 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=109 w=120 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=110 w=121 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=111 w=122 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=112 w=123 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=113 w=124 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=114 w=125 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=115 w=126 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=116 w=127 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=117 w=128 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=118 w=129 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=119 w=130 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=120 w=131 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=121 w=132 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=122 w=133 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=123 w=134 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=124 w=135 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=125 w=136 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=126 w=137 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=127 w=138 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=128 w=139 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=129 w=140 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=130 w=141 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=131 w=142 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=132 w=143 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=133 w=144 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=134 w=145 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=135 w=146 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=136 w=147 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=137 w=148 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=138 w=149 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=139 w=150 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=140 w=151 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=141 w=152 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=142 w=153 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=143 w=154 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=144 w=155 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=145 w=156 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=146 w=157 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=147 w=158 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=148 w=159 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=149 w=160 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=150 w=161 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=151 w=162 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=152 w=163 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=153 w=164 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=154 w=165 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=155 w=166 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=156 w=167 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=157 w=168 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=158 w=169 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=159 w=170 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=160 w=171 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=161 w=172 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=162 w=173 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=163 w=174 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=164 w=175 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=165 w=176 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=166 w=177 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=167 w=178 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=168 w=179 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=169 w=180 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=170 w=181 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=171 w=182 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=172 w=183 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=173 w=184 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=174 w=185 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=175 w=186 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=176 w=187 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=177 w=188 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=178 w=189 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=179 w=190 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=180 w=191 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=181 w=192 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=182 w=193 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=183 w=194 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=184 w=195 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=185 w=196 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=186 w=197 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=187 w=198 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=188 w=199 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=189 w=200 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=190 w=201 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=191 w=202 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=192 w=203 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=193 w=204 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=194 w=205 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=195 w=206 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=196 w=207 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=197 w=208 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=198 w=209 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=199 w=210 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=200 w=211 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=201 w=212 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=202 w=213 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=203 w=214 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=204 w=215 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=205 w=216 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=206 w=217 09:56:32.003: 21798: debug : virEventPollDispatchHandles:467 : i=207 w=218 09:56:32.005: 22033: debug : remoteSerializeError:141 : prog=536903814 ver=1 proc=53 type=1 serial=4, msg=Timed out during operation: cannot acquire state change lock 09:56:32.005: 21801: debug : remoteDispatchClientRequest:372 : prog=536903814 ver=1 type=0 status=0 serial=4 proc=53 09:56:32.005: 21801: debug : virDomainCoreDump:2363 : dom=0x7f6d14000960, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), to=/mnt/data/dumps/dump-hut-vm1.1, flags=0 09:56:32.003: 21798: debug : virEventPollCleanupTimeouts:498 : Cleanup 2 09:56:32.005: 21798: debug : virEventPollCleanupHandles:545 : Cleanup 208 09:56:32.005: 22033: debug : virEventPollUpdateHandle:144 : Update handle w=15 e=3 09:56:32.005: 22033: debug : virEventPollInterruptLocked:686 : Skip interrupt, 0 701839104 09:56:32.005: 21803: debug : remoteSerializeError:141 : prog=536903814 ver=1 proc=53 type=1 serial=4, msg=Timed out during operation: cannot acquire state change lock 09:56:32.003: 22032: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=14 09:56:32.005: 22032: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.005: 21803: debug : virEventPollUpdateHandle:144 : Update handle w=12 e=3 09:56:32.005: 22019: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=13 09:56:32.005: 21803: debug : virEventPollInterruptLocked:686 : Skip interrupt, 0 701839104 09:56:32.005: 22019: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.005: 22030: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=12 09:56:32.005: 22030: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.005: 22077: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=11 09:56:32.005: 22077: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.005: 22082: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=10 09:56:32.005: 22082: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.005: 21802: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=9 09:56:32.005: 21802: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.005: 22029: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=8 09:56:32.005: 22029: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.005: 22058: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=7 09:56:32.005: 22058: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.005: 22057: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=6 09:56:32.005: 22057: error : qemuDomainObjBeginJobWithDriver:513 : Timed out during operation: cannot acquire state change lock 09:56:32.005: 21801: debug : virDomainObjRef:988 : obj=0x12deff0 refs=7 09:56:32.005: 22032: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=6 09:56:32.005: 22032: debug : virDomainFree:2083 : dom=0x7f6cf0000c70, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), 09:56:32.005: 22032: debug : virUnrefDomain:276 : unref domain 0x7f6cf0000c70 hut-vm1 1 09:56:32.005: 22032: debug : virReleaseDomain:238 : release domain 0x7f6cf0000c70 hut-vm1 68698441-bf5f-4f16-b277-dc22258875ec 09:56:32.005: 22032: debug : virReleaseDomain:246 : unref connection 0x7f6cf4000a10 2 09:56:32.005: 22019: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=5 09:56:32.005: 22019: debug : virDomainFree:2083 : dom=0x7f6d04000990, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), 09:56:32.005: 22019: debug : virUnrefDomain:276 : unref domain 0x7f6d04000990 hut-vm1 1 09:56:32.005: 22019: debug : virReleaseDomain:238 : release domain 0x7f6d04000990 hut-vm1 68698441-bf5f-4f16-b277-dc22258875ec 09:56:32.005: 22019: debug : virReleaseDomain:246 : unref connection 0x7f6d04000b50 2 09:56:32.005: 22030: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=4 09:56:32.005: 22030: debug : virDomainFree:2083 : dom=0x7f6cf4000df0, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), 09:56:32.005: 22030: debug : virUnrefDomain:276 : unref domain 0x7f6cf4000df0 hut-vm1 1 09:56:32.006: 22030: debug : virReleaseDomain:238 : release domain 0x7f6cf4000df0 hut-vm1 68698441-bf5f-4f16-b277-dc22258875ec 09:56:32.006: 22030: debug : virReleaseDomain:246 : unref connection 0x7f6d04000dd0 2 09:56:32.006: 22077: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=3 09:56:32.006: 22077: debug : virDomainFree:2083 : dom=0x7f6ce8000b10, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), 09:56:32.006: 22077: debug : virUnrefDomain:276 : unref domain 0x7f6ce8000b10 hut-vm1 1 09:56:32.006: 22077: debug : virReleaseDomain:238 : release domain 0x7f6ce8000b10 hut-vm1 68698441-bf5f-4f16-b277-dc22258875ec 09:56:32.006: 22077: debug : virReleaseDomain:246 : unref connection 0x7f6d14000d70 2 09:56:32.006: 22082: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=2 09:56:32.006: 22082: debug : virDomainFree:2083 : dom=0x7f6ce4000ec0, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), 09:56:32.006: 22082: debug : virUnrefDomain:276 : unref domain 0x7f6ce4000ec0 hut-vm1 1 09:56:32.006: 22082: debug : virReleaseDomain:238 : release domain 0x7f6ce4000ec0 hut-vm1 68698441-bf5f-4f16-b277-dc22258875ec 09:56:32.006: 22082: debug : virReleaseDomain:246 : unref connection 0x7f6cdc000a10 2 09:56:32.006: 21802: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=1 09:56:32.006: 21802: debug : virDomainFree:2083 : dom=0x7f6d0c000b90, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), 09:56:32.006: 21802: debug : virUnrefDomain:276 : unref domain 0x7f6d0c000b90 hut-vm1 1 09:56:32.006: 21802: debug : virReleaseDomain:238 : release domain 0x7f6d0c000b90 hut-vm1 68698441-bf5f-4f16-b277-dc22258875ec 09:56:32.006: 21802: debug : virReleaseDomain:246 : unref connection 0x7f6cf0000b50 2 09:56:32.006: 22029: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=0 09:56:32.006: 22029: debug : virDomainObjFree:971 : obj=0x12deff0 09:56:32.006: 22029: error : qemuDomainObjPrivateFree:122 : Unexpected QEMU monitor still active during domain deletion 09:56:32.006: 22029: debug : qemuMonitorClose:717 : mon=0x7f6d10002c10 09:56:32.006: 22029: debug : virEventPollRemoveHandle:171 : Remove handle w=9 09:56:32.006: 22029: debug : virEventPollRemoveHandle:184 : mark delete 7 17 09:56:32.006: 22029: debug : virEventPollInterruptLocked:686 : Skip interrupt, 0 701839104 09:56:32.006: 22029: debug : virDomainFree:2083 : dom=0x7f6cfc000df0, (VM: name=hut-vm1, uuid=68698441-bf5f-4f16-b277-dc22258875ec), 09:56:32.006: 22029: debug : virUnrefDomain:276 : unref domain 0x7f6cfc000df0 hut-vm1 1 09:56:32.006: 22029: debug : virReleaseDomain:238 : release domain 0x7f6cfc000df0 hut-vm1 68698441-bf5f-4f16-b277-dc22258875ec 09:56:32.006: 22029: debug : virReleaseDomain:246 : unref connection 0x12c61e0 2 09:56:32.006: 22058: debug : virDomainObjUnref:995 : obj=0x12deff0 refs=-1 ====== end of log ===== Segmentation fault (core dumped) -------------- next part -------------- A non-text attachment was scrubbed... Name: libvirt-test.sh Type: application/x-sh Size: 532 bytes Desc: not available URL: From jyang at redhat.com Tue Apr 12 05:27:01 2011 From: jyang at redhat.com (Osier Yang) Date: Tue, 12 Apr 2011 13:27:01 +0800 Subject: [libvirt] [PATCH v2] Storage: Add fs pool formatting In-Reply-To: <1302252716-31890-3-git-send-email-jyang@redhat.com> References: <1302252716-31890-3-git-send-email-jyang@redhat.com> Message-ID: <1302586021-9194-1-git-send-email-jyang@redhat.com> Previous description from Dave Allan. This patch adds the ability to make the filesystem for a filesystem pool during a pool build. The patch adds two new flags, no overwrite and overwrite, to control when mkfs gets executed. By default, the patch preserves the current behavior, i.e., if no flags are specified, pool build on a filesystem pool only makes the directory on which the filesystem will be mounted. If the no overwrite flag is specified, the target device is checked to determine if a filesystem of the type specified in the pool is present. If a filesystem of that type is already present, mkfs is not executed and the build call returns an error. Otherwise, mkfs is executed and any data present on the device is overwritten. If the overwrite flag is specified, mkfs is always executed, and any existing data on the target device is overwritten unconditionally. Changes per feedback from eblake: * Made probe & overwrite flags exclusive * Changed LDFLAGS to LIBADD in Makefile.am * Added missing virCheckFlags() * Fixed copyright dates * Removed cast of char * passed to libblkid and replaced it with a strdup'd copy * Changed flags to an unsigned int in virsh.c Changes per feedback from Dan B. * Changed probe flag to no-overwrite * Moved libblkid probe code into storage_backend_fs.c New changes: (per last feedback from Eric) * s/VIR_STORAGE_POOL_PROBE_BUILT/VIR_STORAGE_POOL_BUILT/ * Add virsh document * Remove the internal function exporting in libvirt_private.syms * Correct wonky spacing * use virCommand instead of array for the command. --- include/libvirt/libvirt.h.in | 6 +- include/libvirt/virterror.h | 2 + src/libvirt.c | 5 +- src/storage/storage_backend_fs.c | 194 +++++++++++++++++++++++++++++++++++++- src/storage/storage_backend_fs.h | 7 ++ src/util/virterror.c | 64 ++++++++----- 6 files changed, 245 insertions(+), 33 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index d765412..e43c98a 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1335,8 +1335,10 @@ typedef enum { typedef enum { VIR_STORAGE_POOL_BUILD_NEW = 0, /* Regular build from scratch */ - VIR_STORAGE_POOL_BUILD_REPAIR = 1, /* Repair / reinitialize */ - VIR_STORAGE_POOL_BUILD_RESIZE = 2 /* Extend existing pool */ + VIR_STORAGE_POOL_BUILD_REPAIR = (1 << 0), /* Repair / reinitialize */ + VIR_STORAGE_POOL_BUILD_RESIZE = (1 << 1), /* Extend existing pool */ + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE = (1 << 2), /* Do not overwrite existing pool */ + VIR_STORAGE_POOL_BUILD_OVERWRITE = (1 << 3), /* Overwrite data */ } virStoragePoolBuildFlags; typedef enum { diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 0708e02..33fbe9a 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -231,6 +231,8 @@ typedef enum { VIR_ERR_INVALID_DOMAIN_SNAPSHOT = 71,/* invalid domain snapshot */ VIR_ERR_NO_DOMAIN_SNAPSHOT = 72, /* domain snapshot not found */ VIR_ERR_INVALID_STREAM = 73, /* stream pointer not valid */ + VIR_ERR_STORAGE_PROBE_FAILED = 74, /* storage pool proble failed */ + VIR_ERR_STORAGE_POOL_BUILT = 75, /* storage pool already built */ } virErrorNumber; /** diff --git a/src/libvirt.c b/src/libvirt.c index dde4bd4..03d870b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -8001,7 +8001,10 @@ error: /** * virStoragePoolBuild: * @pool: pointer to storage pool - * @flags: future flags, use 0 for now + * @flags: flags to control pool build behaviour + * + * Currently only filesystem pool accepts flags VIR_STORAGE_POOL_BUILD_OVERWRITE + * and VIR_STORAGE_POOL_BUILD_NO_OVERWRITE. * * Build the underlying storage pool * diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index 0a6b074..d1c8794 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -33,6 +33,10 @@ #include #include +#if HAVE_LIBBLKID +# include +#endif + #include #include #include @@ -45,6 +49,8 @@ #include "memory.h" #include "xml.h" #include "files.h" +#include "logging.h" +#include "command.h" #define VIR_FROM_THIS VIR_FROM_STORAGE @@ -533,13 +539,175 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED, } #endif /* WITH_STORAGE_FS */ +#if HAVE_LIBBLKID +static virStoragePoolProbeResult +virStorageBackendFileSystemProbe(const char *device, + const char *format) { + + virStoragePoolProbeResult ret = FILESYSTEM_PROBE_ERROR; + blkid_probe probe = NULL; + const char *fstype = NULL; + char *names[2], *libblkid_format = NULL; + + VIR_DEBUG("Probing for existing filesystem of type %s on device %s", + format, device); + + if (blkid_known_fstype(format) == 0) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Not capable of probing for " + "filesystem of type %s"), + format); + goto error; + } + + probe = blkid_new_probe_from_filename(device); + if (probe == NULL) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Failed to create filesystem probe " + "for device %s"), + device); + goto error; + } + + if ((libblkid_format = strdup(format)) == NULL) { + virReportOOMError(); + goto error; + } + + names[0] = libblkid_format; + names[1] = NULL; + + blkid_probe_filter_superblocks_type(probe, + BLKID_FLTR_ONLYIN, + names); + + if (blkid_do_probe(probe) != 0) { + VIR_INFO("No filesystem of type '%s' found on device '%s'", + format, device); + ret = FILESYSTEM_PROBE_NOT_FOUND; + } else if (blkid_probe_lookup_value(probe, "TYPE", &fstype, NULL) == 0) { + virStorageReportError(VIR_ERR_STORAGE_POOL_BUILT, + _("Existing filesystem of type '%s' found on " + "device '%s'"), + fstype, device); + ret = FILESYSTEM_PROBE_FOUND; + } + + if (blkid_do_probe(probe) != 1) { + virStorageReportError(VIR_ERR_STORAGE_PROBE_FAILED, + _("Found additional probes to run, " + "filesystem probing may be incorrect")); + ret = FILESYSTEM_PROBE_ERROR; + } + +error: + VIR_FREE(libblkid_format); + + if (probe != NULL) { + blkid_free_probe(probe); + } + + return ret; +} + +#else /* #if HAVE_LIBBLKID */ + +static virStoragePoolProbeResult +virStorageBackendFileSystemProbe(const char *device ATTRIBUTE_UNUSED, + const char *format ATTRIBUTE_UNUSED) +{ + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("probing for filesystems is unsupported " + "by this build")); + + return FILESYSTEM_PROBE_ERROR; +} + +#endif /* #if HAVE_LIBBLKID */ + +static int +virStorageBackendExecuteMKFS(const char *device, + const char *format) +{ + int ret = 0; + virCommandPtr cmd = NULL; + + cmd = virCommandNewArgList(MKFS, + "-t", + format, + device, + NULL); + + if (virCommandRun(cmd, NULL) < 0) { + virReportSystemError(errno, + _("Failed to make filesystem of " + "type '%s' on device '%s'"), + format, device); + ret = -1; + } + + return ret; +} + + +static int +virStorageBackendMakeFileSystem(virStoragePoolObjPtr pool, + unsigned int flags) +{ + const char *device = NULL, *format = NULL; + bool ok_to_mkfs = false; + int ret = -1; + + if (pool->def->source.devices == NULL) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("No source device specified when formatting pool '%s'"), + pool->def->name); + goto error; + } + + device = pool->def->source.devices[0].path; + format = virStoragePoolFormatFileSystemTypeToString(pool->def->source.format); + VIR_DEBUG("source device: '%s' format: '%s'", device, format); + + if (!virFileExists(device)) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("Source device does not exist when formatting pool '%s'"), + pool->def->name); + goto error; + } + + if (flags & VIR_STORAGE_POOL_BUILD_OVERWRITE) { + ok_to_mkfs = true; + } else if (flags & VIR_STORAGE_POOL_BUILD_NO_OVERWRITE && + virStorageBackendFileSystemProbe(device, format) == + FILESYSTEM_PROBE_NOT_FOUND) { + ok_to_mkfs = true; + } + + if (ok_to_mkfs) { + ret = virStorageBackendExecuteMKFS(device, format); + } + +error: + return ret; +} + + /** * @conn connection to report errors against * @pool storage pool to build + * @flags controls the pool formating behaviour * * Build a directory or FS based storage pool. * + * If no flag is set, it only makes the directory; If + * VIR_STORAGE_POOL_BUILD_NO_OVERWRITE set, it probes to determine if + * a filesystem already exists on the target device, returning an error + * if exists, or using mkfs to format the target device if not; If + * VIR_STORAGE_POOL_BUILD_OVERWRITE is set, mkfs is always executed, + * any existed data on the target device is overwritten unconditionally. + * * - If it is a FS based pool, mounts the unlying source device on the pool * * Returns 0 on success, -1 on error @@ -547,11 +715,23 @@ virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED, static int virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, - unsigned int flags ATTRIBUTE_UNUSED) + unsigned int flags) { int err, ret = -1; - char *parent; - char *p; + char *parent = NULL; + char *p = NULL; + + virCheckFlags(VIR_STORAGE_POOL_BUILD_OVERWRITE | + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, ret); + + if (flags == (VIR_STORAGE_POOL_BUILD_OVERWRITE | + VIR_STORAGE_POOL_BUILD_NO_OVERWRITE)) { + virStorageReportError(VIR_ERR_OPERATION_INVALID, + _("Overwrite and no overwrite flags" + " are mutually exclusive")); + goto error; + } if ((parent = strdup(pool->def->target.path)) == NULL) { virReportOOMError(); @@ -601,7 +781,13 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, goto error; } } - ret = 0; + + if (flags != 0) { + ret = virStorageBackendMakeFileSystem(pool, flags); + } else { + ret = 0; + } + error: VIR_FREE(parent); return ret; diff --git a/src/storage/storage_backend_fs.h b/src/storage/storage_backend_fs.h index 7def53e..394e552 100644 --- a/src/storage/storage_backend_fs.h +++ b/src/storage/storage_backend_fs.h @@ -29,6 +29,13 @@ # if WITH_STORAGE_FS extern virStorageBackend virStorageBackendFileSystem; extern virStorageBackend virStorageBackendNetFileSystem; + +typedef enum { + FILESYSTEM_PROBE_FOUND, + FILESYSTEM_PROBE_NOT_FOUND, + FILESYSTEM_PROBE_ERROR, +} virStoragePoolProbeResult; + # endif extern virStorageBackend virStorageBackendDirectory; diff --git a/src/util/virterror.c b/src/util/virterror.c index b7d8924..4450a43 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -1041,63 +1041,75 @@ virErrorMsg(virErrorNumber error, const char *info) break; case VIR_ERR_NO_STORAGE_POOL: if (info == NULL) - errmsg = _("Storage pool not found"); + errmsg = _("Storage pool not found"); else - errmsg = _("Storage pool not found: %s"); + errmsg = _("Storage pool not found: %s"); break; case VIR_ERR_NO_STORAGE_VOL: if (info == NULL) - errmsg = _("Storage volume not found"); + errmsg = _("Storage volume not found"); else - errmsg = _("Storage volume not found: %s"); + errmsg = _("Storage volume not found: %s"); + break; + case VIR_ERR_STORAGE_PROBE_FAILED: + if (info == NULL) + errmsg = _("Storage pool probe failed"); + else + errmsg = _("Storage pool probe failed: %s"); + break; + case VIR_ERR_STORAGE_POOL_BUILT: + if (info == NULL) + errmsg = _("Storage pool already built"); + else + errmsg = _("Storage pool already built: %s"); break; case VIR_ERR_INVALID_STORAGE_POOL: if (info == NULL) - errmsg = _("invalid storage pool pointer in"); + errmsg = _("invalid storage pool pointer in"); else - errmsg = _("invalid storage pool pointer in %s"); + errmsg = _("invalid storage pool pointer in %s"); break; case VIR_ERR_INVALID_STORAGE_VOL: if (info == NULL) - errmsg = _("invalid storage volume pointer in"); + errmsg = _("invalid storage volume pointer in"); else - errmsg = _("invalid storage volume pointer in %s"); + errmsg = _("invalid storage volume pointer in %s"); break; case VIR_WAR_NO_STORAGE: if (info == NULL) - errmsg = _("Failed to find a storage driver"); + errmsg = _("Failed to find a storage driver"); else - errmsg = _("Failed to find a storage driver: %s"); + errmsg = _("Failed to find a storage driver: %s"); break; case VIR_WAR_NO_NODE: if (info == NULL) - errmsg = _("Failed to find a node driver"); + errmsg = _("Failed to find a node driver"); else - errmsg = _("Failed to find a node driver: %s"); + errmsg = _("Failed to find a node driver: %s"); break; case VIR_ERR_INVALID_NODE_DEVICE: if (info == NULL) - errmsg = _("invalid node device pointer"); + errmsg = _("invalid node device pointer"); else - errmsg = _("invalid node device pointer in %s"); + errmsg = _("invalid node device pointer in %s"); break; case VIR_ERR_NO_NODE_DEVICE: if (info == NULL) - errmsg = _("Node device not found"); + errmsg = _("Node device not found"); else - errmsg = _("Node device not found: %s"); + errmsg = _("Node device not found: %s"); break; case VIR_ERR_NO_SECURITY_MODEL: if (info == NULL) - errmsg = _("Security model not found"); + errmsg = _("Security model not found"); else - errmsg = _("Security model not found: %s"); + errmsg = _("Security model not found: %s"); break; case VIR_ERR_OPERATION_INVALID: if (info == NULL) - errmsg = _("Requested operation is not valid"); + errmsg = _("Requested operation is not valid"); else - errmsg = _("Requested operation is not valid: %s"); + errmsg = _("Requested operation is not valid: %s"); break; case VIR_WAR_NO_INTERFACE: if (info == NULL) @@ -1149,21 +1161,21 @@ virErrorMsg(virErrorNumber error, const char *info) break; case VIR_ERR_INVALID_NWFILTER: if (info == NULL) - errmsg = _("Invalid network filter"); + errmsg = _("Invalid network filter"); else - errmsg = _("Invalid network filter: %s"); + errmsg = _("Invalid network filter: %s"); break; case VIR_ERR_NO_NWFILTER: if (info == NULL) - errmsg = _("Network filter not found"); + errmsg = _("Network filter not found"); else - errmsg = _("Network filter not found: %s"); + errmsg = _("Network filter not found: %s"); break; case VIR_ERR_BUILD_FIREWALL: if (info == NULL) - errmsg = _("Error while building firewall"); + errmsg = _("Error while building firewall"); else - errmsg = _("Error while building firewall: %s"); + errmsg = _("Error while building firewall: %s"); break; case VIR_ERR_CONFIG_UNSUPPORTED: if (info == NULL) -- 1.7.4 From hutao at cn.fujitsu.com Tue Apr 12 05:51:33 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Tue, 12 Apr 2011 13:51:33 +0800 Subject: [libvirt] [PATCH 3/6] use virObject to manage reference-count of virDomainObj In-Reply-To: <20110412033407.GA32561@localhost.localdomain> References: <4D9CEA54.6000402@redhat.com> <20110412033407.GA32561@localhost.localdomain> Message-ID: <20110412055133.GA4164@localhost.localdomain> Sorry, I unexpectedly deleted text body. I changed the code like this: diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index c2a1f9a..8aad0b3 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -514,7 +514,10 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, else virReportSystemError(errno, "%s", _("cannot acquire job mutex")); + virDomainObjUnlock(obj); qemuDriverLock(driver); + virDomainObjLock(obj); + virDomainObjUnref(obj); return -1; } } but still have problem. (see log in previous mail.) The reference count of virDomainObj becomes 0 while there are still threads accessing it. This causes two results: one is segmentation fault as shown in the log; the other is the qemu monitor fd is closed two early, and threads are polling a closed fd. Steps of my test: 1. change the value of max_clients in /etc/libvirt/libvirtd.conf to big enough value: max_clients = 2000000 2. run libvirtd 3. run libvirt-test.sh hut-vm1 (hut-vm1 is my vm name) (warning: this script forks many processes you have to kill by hand) (again, the log and script libvirt-test.sh are in my previous mail) From veillard at redhat.com Tue Apr 12 06:05:08 2011 From: veillard at redhat.com (Daniel Veillard) Date: Tue, 12 Apr 2011 14:05:08 +0800 Subject: [libvirt] [PATCH] migrate VMs between different-endian hosts In-Reply-To: <4DA33E8F.209@redhat.com> References: <4DA07FD9.8000606@linux.vnet.ibm.com> <20110411030911.GS24838@redhat.com> <4DA2D8B5.5000106@linux.vnet.ibm.com> <20110411133619.GC30115@redhat.com> <4DA33E8F.209@redhat.com> Message-ID: <20110412060508.GA1149@redhat.com> On Mon, Apr 11, 2011 at 11:46:55AM -0600, Eric Blake wrote: > On 04/11/2011 07:36 AM, Daniel Veillard wrote: > >>>> @@ -3097,6 +3107,11 @@ qemuDomainSaveImageOpen(struct qemud_dri > >>>> } > >>>> > >>>> if (header.version> QEMUD_SAVE_VERSION) { > >>>> + /* convert endianess and try again */ > >>>> + bswap_header(&header); > >>>> + } > >>> Hum, isn't there a more reliable way to detect the change of > >>> endianness ? That's a bit fishy IMHO :-) > >> The problem is that the header should not have been written in a > >> hosts' native format. So what can go wrong? QEMUD_SAVE_VERSION is > >> '2'. Either we find 1 or 2 here and go ahead and accept it 'as-is'. > >> Otherwise anything bigger than 3 is not accepted and swapped. 3 then > >> becomes 0x03 00 00 00 and is discarded. 0x 02 00 00 00 would be > >> swapped to '2' and accepted. > > > > yeah, I understand, okay, > > Should we be writing the header in a particular byte order, regardless > of host endianness? Or does that require bumping the header version to > 3 anyways? The thing I'm worried about is that by bumping older versions won't be able to restore the new dumps, and that could be a serious issue on shared storage. We are not introducing a new feature, so I thin we need to preserve forward compatibility. The patch as is is minimal but achieves it. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From hahn at univention.de Tue Apr 12 06:27:47 2011 From: hahn at univention.de (Philipp Hahn) Date: Tue, 12 Apr 2011 08:27:47 +0200 Subject: [libvirt] [PATCH 0/3] [PoC] snapshot += xml In-Reply-To: <4DA374F9.8070603@redhat.com> References: <4DA374F9.8070603@redhat.com> Message-ID: Hello, this is just a proof-of-concept implementation for storing the domain xml description with the xml snapshot data. This is needed for Qemu, since restoring a Qemu domain after changing the "virtual hardware" (like changing RAM size, number of CPUs, controllers) is not possible: The "loadvm" command will fail to restore the saved state. My idea was to save the domain XML data with the snapshot XML data, which currently just contains a reference to the domain UUID. On snapshot-restore that domain description is restored to overwrites the current domain description. I descided to store a reference to the parsed domainObj with the domainSnapshotObj, since my goal was to detect on revert, if resuing the currently running Qemu process is possible, or the the process needs to be restartet with different arguments to revert changes to the "virtual hardware". I hadn't had time to implement this yet, so currently the Qemu process is restarted on every revert, which disconnects any VNC session and is also a lot slower then simply calling "loadvm". For this implementation I needed to pass "virCapsPtr" down to virDomainSnapshotDefParseString(). I only implemented that correctly for Qemu, so vbox and esx might be broken currently. An alternative (and simpler) implementation would be to just store the unparsed XML description with the runtime domainSnapshotObj. This would simplify copying the domain description, but would complicate detecting if "loadvm" is possible or Qemu must be restarted. The implementation currently works very well for me, but I noticed some memory leak, which might be related to this patch (or some other, since my version of libvirt contains several other patches as well). Philipp Hahn (3): Swap virDomain / virFomainSnapshot declaration snapshot: save domain description with snapshot Snapshot: restore domain description from snapshot src/conf/domain_conf.c | 27 +++++++++++-- src/conf/domain_conf.h | 102 ++++++++++++++++++++++++----------------------- src/esx/esx_driver.c | 2 +- src/qemu/qemu_driver.c | 43 +++++++++++++++++++- src/vbox/vbox_tmpl.c | 2 +- 5 files changed, 117 insertions(+), 59 deletions(-) From hahn at univention.de Tue Apr 12 06:21:47 2011 From: hahn at univention.de (Philipp Hahn) Date: Tue, 12 Apr 2011 08:21:47 +0200 Subject: [libvirt] [PATCH 3/3] Snapshot: restore domain description from snapshot In-Reply-To: References: <4DA374F9.8070603@redhat.com> Message-ID: Restore the domain description from the snapshot information. TODOs: - Only restart the KVM process when the snapshot is incompatible with "loadvm". This would have the benefir of being able to switch saved states very fast and also doesn't disconnect any VNC viewer. Signed-off-by: Philipp Hahn --- src/qemu/qemu_driver.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 files changed, 38 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5041d32..5610961 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6282,6 +6282,7 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain, { struct qemud_driver *driver = domain->conn->privateData; virDomainObjPtr vm = NULL; + virDomainDefPtr newDef = NULL; virDomainSnapshotObjPtr snap = NULL; virDomainSnapshotPtr snapshot = NULL; char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -6311,6 +6312,18 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain, if (!(def = virDomainSnapshotDefParseString(xmlDesc, 1, qemu_driver->caps))) goto cleanup; + /* create copy */ + if (!def->dom) { + char *xml = NULL; + if (!(xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE))) + goto cleanup; + newDef = virDomainDefParseString(driver->caps, xml, VIR_DOMAIN_XML_INACTIVE); + VIR_FREE(xml); + if (!newDef) + goto cleanup; + def->dom = newDef; + } + if (!(snap = virDomainSnapshotAssignDef(&vm->snapshots, def))) goto cleanup; @@ -6561,6 +6574,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, virDomainEventPtr event = NULL; qemuDomainObjPrivatePtr priv; int rc; + virDomainDefPtr newDef = NULL; virCheckFlags(0, -1); @@ -6586,10 +6600,23 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; + /* create copy */ + if (snap->def->dom) { + char *xml = NULL; + /* TODO:Compare old definition to new definition to decide, if KVM must be restarted or existing KVM can be reused. */ + if (!(xml = virDomainDefFormat(snap->def->dom, VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE))) + goto cleanup; + newDef = virDomainDefParseString(driver->caps, xml, VIR_DOMAIN_XML_INACTIVE); + VIR_FREE(xml); + if (!newDef) + goto cleanup; + virDomainObjAssignDef(vm, newDef, false); + } + if (snap->def->state == VIR_DOMAIN_RUNNING || snap->def->state == VIR_DOMAIN_PAUSED) { - if (virDomainObjIsActive(vm)) { + if (virDomainObjIsActive(vm) && !newDef) { priv = vm->privateData; qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorLoadSnapshot(priv->mon, snap->def->name); @@ -6598,6 +6625,16 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, goto endjob; } else { + if (virDomainObjIsActive(vm)) { + //qemudShutdownVMDaemon(driver, vm, 0); // <= 0.12.4 + qemuProcessStop(driver, vm, 0); // >= 14 + if (!vm->persistent) { + if (qemuDomainObjEndJob(vm) > 0) + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + goto cleanup; + } + } if (qemuDomainSnapshotSetCurrentActive(vm, driver->snapshotDir) < 0) goto endjob; -- 1.7.1 From hahn at univention.de Tue Apr 12 06:06:18 2011 From: hahn at univention.de (Philipp Hahn) Date: Tue, 12 Apr 2011 08:06:18 +0200 Subject: [libvirt] [PATCH 1/3] Swap virDomain / virFomainSnapshot declaration In-Reply-To: References: <4DA374F9.8070603@redhat.com> Message-ID: In preparation for storing the domain description with the snapshot, swap the order of declaration. Signed-off-by: Philipp Hahn --- src/conf/domain_conf.h | 100 ++++++++++++++++++++++++------------------------ 1 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 30aeccc..9e7e1ee 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -982,56 +982,6 @@ struct _virDomainClockDef { # define VIR_DOMAIN_CPUMASK_LEN 1024 -/* Snapshot state */ -typedef struct _virDomainSnapshotDef virDomainSnapshotDef; -typedef virDomainSnapshotDef *virDomainSnapshotDefPtr; -struct _virDomainSnapshotDef { - char *name; - char *description; - char *parent; - time_t creationTime; - int state; - - long active; -}; - -typedef struct _virDomainSnapshotObj virDomainSnapshotObj; -typedef virDomainSnapshotObj *virDomainSnapshotObjPtr; -struct _virDomainSnapshotObj { - int refs; - - virDomainSnapshotDefPtr def; -}; - -typedef struct _virDomainSnapshotObjList virDomainSnapshotObjList; -typedef virDomainSnapshotObjList *virDomainSnapshotObjListPtr; -struct _virDomainSnapshotObjList { - /* name string -> virDomainSnapshotObj mapping - * for O(1), lockless lookup-by-name */ - virHashTable *objs; -}; - -virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, - int newSnapshot); -void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def); -char *virDomainSnapshotDefFormat(char *domain_uuid, - virDomainSnapshotDefPtr def, - int internal); -virDomainSnapshotObjPtr virDomainSnapshotAssignDef(virDomainSnapshotObjListPtr snapshots, - const virDomainSnapshotDefPtr def); - -int virDomainSnapshotObjListInit(virDomainSnapshotObjListPtr objs); -int virDomainSnapshotObjListGetNames(virDomainSnapshotObjListPtr snapshots, - char **const names, int maxnames); -int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots); -virDomainSnapshotObjPtr virDomainSnapshotFindByName(const virDomainSnapshotObjListPtr snapshots, - const char *name); -void virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots, - virDomainSnapshotObjPtr snapshot); -int virDomainSnapshotObjUnref(virDomainSnapshotObjPtr snapshot); -int virDomainSnapshotHasChildren(virDomainSnapshotObjPtr snap, - virDomainSnapshotObjListPtr snapshots); - /* Guest VM main configuration */ typedef struct _virDomainDef virDomainDef; typedef virDomainDef *virDomainDefPtr; @@ -1122,6 +1072,56 @@ struct _virDomainDef { virDomainXMLNamespace ns; }; +/* Snapshot state */ +typedef struct _virDomainSnapshotDef virDomainSnapshotDef; +typedef virDomainSnapshotDef *virDomainSnapshotDefPtr; +struct _virDomainSnapshotDef { + char *name; + char *description; + char *parent; + time_t creationTime; + int state; + + long active; +}; + +typedef struct _virDomainSnapshotObj virDomainSnapshotObj; +typedef virDomainSnapshotObj *virDomainSnapshotObjPtr; +struct _virDomainSnapshotObj { + int refs; + + virDomainSnapshotDefPtr def; +}; + +typedef struct _virDomainSnapshotObjList virDomainSnapshotObjList; +typedef virDomainSnapshotObjList *virDomainSnapshotObjListPtr; +struct _virDomainSnapshotObjList { + /* name string -> virDomainSnapshotObj mapping + * for O(1), lockless lookup-by-name */ + virHashTable *objs; +}; + +virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, + int newSnapshot); +void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def); +char *virDomainSnapshotDefFormat(char *domain_uuid, + virDomainSnapshotDefPtr def, + int internal); +virDomainSnapshotObjPtr virDomainSnapshotAssignDef(virDomainSnapshotObjListPtr snapshots, + const virDomainSnapshotDefPtr def); + +int virDomainSnapshotObjListInit(virDomainSnapshotObjListPtr objs); +int virDomainSnapshotObjListGetNames(virDomainSnapshotObjListPtr snapshots, + char **const names, int maxnames); +int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots); +virDomainSnapshotObjPtr virDomainSnapshotFindByName(const virDomainSnapshotObjListPtr snapshots, + const char *name); +void virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots, + virDomainSnapshotObjPtr snapshot); +int virDomainSnapshotObjUnref(virDomainSnapshotObjPtr snapshot); +int virDomainSnapshotHasChildren(virDomainSnapshotObjPtr snap, + virDomainSnapshotObjListPtr snapshots); + /* Guest VM runtime state */ typedef struct _virDomainObj virDomainObj; typedef virDomainObj *virDomainObjPtr; -- 1.7.1 From hahn at univention.de Tue Apr 12 06:16:42 2011 From: hahn at univention.de (Philipp Hahn) Date: Tue, 12 Apr 2011 08:16:42 +0200 Subject: [libvirt] [PATCH 2/3] snapshot: save domain description with snapshot In-Reply-To: References: <4DA374F9.8070603@redhat.com> Message-ID: <47b2fe6c95355ab275774f950a78daa7a10850b7.1302589667.git.hahn@univention.de> Save the domain description with the XML snapshot data. TODOs: - XML file is no longer nicely indented - Fix esx driver - Fix vbox driver Signed-off-by: Philipp Hahn --- src/conf/domain_conf.c | 27 +++++++++++++++++++++++---- src/conf/domain_conf.h | 4 +++- src/esx/esx_driver.c | 2 +- src/qemu/qemu_driver.c | 4 ++-- src/vbox/vbox_tmpl.c | 2 +- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 16e1291..d568c43 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -8564,6 +8564,7 @@ void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def) if (!def) return; + virDomainDefFree(def->dom); VIR_FREE(def->name); VIR_FREE(def->description); VIR_FREE(def->parent); @@ -8571,7 +8572,8 @@ void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def) } virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, - int newSnapshot) + int newSnapshot, + virCapsPtr caps) { xmlXPathContextPtr ctxt = NULL; xmlDocPtr xml = NULL; @@ -8661,6 +8663,14 @@ virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, else def->creationTime = tv.tv_sec; + xmlNodePtr domainNode = virXPathNode("./domain", ctxt); + if (domainNode == NULL) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing domain from existing snapshot")); + def->dom = NULL; + } else + def->dom = virDomainDefParseNode(caps, xml, domainNode, VIR_DOMAIN_XML_INACTIVE); + ret = def; cleanup: @@ -8678,6 +8688,7 @@ char *virDomainSnapshotDefFormat(char *domain_uuid, virDomainSnapshotDefPtr def, int internal) { + char *xml = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; virBufferAddLit(&buf, "\n"); @@ -8694,9 +8705,17 @@ char *virDomainSnapshotDefFormat(char *domain_uuid, } virBufferVSprintf(&buf, " %ld\n", def->creationTime); - virBufferAddLit(&buf, " \n"); - virBufferVSprintf(&buf, " %s\n", domain_uuid); - virBufferAddLit(&buf, " \n"); + if (def->dom != NULL) { + xml = virDomainDefFormat(def->dom, VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE); + } + if (xml != NULL) { + virBufferVSprintf(&buf, " %s", xml); + VIR_FREE(xml); + } else { + virBufferAddLit(&buf, " \n"); + virBufferVSprintf(&buf, " %s\n", domain_uuid); + virBufferAddLit(&buf, " \n"); + } if (internal) virBufferVSprintf(&buf, " %ld\n", def->active); virBufferAddLit(&buf, "\n"); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9e7e1ee..c8c64ed 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1083,6 +1083,7 @@ struct _virDomainSnapshotDef { int state; long active; + virDomainDefPtr dom; }; typedef struct _virDomainSnapshotObj virDomainSnapshotObj; @@ -1102,7 +1103,8 @@ struct _virDomainSnapshotObjList { }; virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, - int newSnapshot); + int newSnapshot, + virCapsPtr caps); void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def); char *virDomainSnapshotDefFormat(char *domain_uuid, virDomainSnapshotDefPtr def, diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 4f013e8..25c95c9 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4058,7 +4058,7 @@ esxDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc, return NULL; } - def = virDomainSnapshotDefParseString(xmlDesc, 1); + def = virDomainSnapshotDefParseString(xmlDesc, 1, NULL); /* TODO:caps */ if (def == NULL) { return NULL; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 4481261..5041d32 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -330,7 +330,7 @@ static void qemuDomainSnapshotLoad(void *payload, continue; } - def = virDomainSnapshotDefParseString(xmlStr, 0); + def = virDomainSnapshotDefParseString(xmlStr, 0, qemu_driver->caps); if (def == NULL) { /* Nothing we can do here, skip this one */ VIR_ERROR(_("Failed to parse snapshot XML from file '%s'"), fullpath); @@ -6308,7 +6308,7 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain, if (!qemuDomainSnapshotIsAllowed(vm)) goto cleanup; - if (!(def = virDomainSnapshotDefParseString(xmlDesc, 1))) + if (!(def = virDomainSnapshotDefParseString(xmlDesc, 1, qemu_driver->caps))) goto cleanup; if (!(snap = virDomainSnapshotAssignDef(&vm->snapshots, def))) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index e8ac48f..a8c8570 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -5547,7 +5547,7 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom, virCheckFlags(0, NULL); - if (!(def = virDomainSnapshotDefParseString(xmlDesc, 1))) + if (!(def = virDomainSnapshotDefParseString(xmlDesc, 1, NULL))) /* TODO:caps */ goto cleanup; vboxIIDFromUUID(&domiid, dom->uuid); -- 1.7.1 From veillard at redhat.com Tue Apr 12 06:58:49 2011 From: veillard at redhat.com (Daniel Veillard) Date: Tue, 12 Apr 2011 14:58:49 +0800 Subject: [libvirt] [PATCH] esx: Cleanup VI generator code In-Reply-To: <20110410112647.GA13500@sbox> References: <20110410112647.GA13500@sbox> Message-ID: <20110412065849.GB1149@redhat.com> On Sun, Apr 10, 2011 at 01:26:47PM +0200, Matthias Bolte wrote: > --- > src/esx/esx_vi_generator.py | 177 +++++++++++++++++-------------------------- > 1 files changed, 71 insertions(+), 106 deletions(-) > > diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py > index 3d068f3..622a34a 100755 > --- a/src/esx/esx_vi_generator.py > +++ b/src/esx/esx_vi_generator.py > @@ -41,6 +41,11 @@ valid_occurrences = [OCCURRENCE__REQUIRED_ITEM, > > > > +def aligned(left, right): > + while len(left) < 59: > + left += " " > + > + return left + right crude but that works :-) for the generator it's fine, overall I'm not sure many understand that code beside you, ACK Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Tue Apr 12 07:00:44 2011 From: veillard at redhat.com (Daniel Veillard) Date: Tue, 12 Apr 2011 15:00:44 +0800 Subject: [libvirt] [PATCH] esx: Cleanup and refactor CastFromAnyType macros In-Reply-To: <20110410112719.GA13533@sbox> References: <20110410112719.GA13533@sbox> Message-ID: <20110412070044.GC1149@redhat.com> On Sun, Apr 10, 2011 at 01:27:19PM +0200, Matthias Bolte wrote: > Add CastFromAnyType functions for the String type. > --- > src/esx/esx_vi_generator.py | 5 +-- > src/esx/esx_vi_types.c | 64 +++++++++++++++++++++++++++++++----------- > src/esx/esx_vi_types.h | 2 + > 3 files changed, 51 insertions(+), 20 deletions(-) ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From hahn at univention.de Tue Apr 12 07:10:06 2011 From: hahn at univention.de (Philipp Hahn) Date: Tue, 12 Apr 2011 09:10:06 +0200 Subject: [libvirt] snapshots += domain description? In-Reply-To: <4DA374F9.8070603@redhat.com> References: <201012071700.32747.hahn@univention.de> <4DA374F9.8070603@redhat.com> Message-ID: <201104120910.11165.hahn@univention.de> Hello Eric, On Monday April, 11th 2011 23:39:05 Eric Blake wrote: > Are you referring to a disk snapshot, created via 'virsh snapshot' on a > qcow2 image, or a memory snapshot, created via 'virsh save'? The first one (snapshot). > So it sounds like you are talking about the 'virsh snapshot' family of > commands. Indeed, there's probably quite a bit of work to do in that > code to make it more reliable. See my proof-of-concept implementation, which I just posted for comments. BYtE Philipp -- Philipp Hahn Open Source Software Engineer hahn at univention.de Univention GmbH Linux for Your Business fon: +49 421 22 232- 0 Mary-Somerville-Str.1 D-28359 Bremen fax: +49 421 22 232-99 http://www.univention.de/ -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 197 bytes Desc: This is a digitally signed message part. URL: From hahn at univention.de Tue Apr 12 07:29:15 2011 From: hahn at univention.de (Philipp Hahn) Date: Tue, 12 Apr 2011 09:29:15 +0200 Subject: [libvirt] qemu-namespace handling? Message-ID: <201104120929.15619.hahn@univention.de> Hello, some time ago I hand to manipulate the domain XML description using Pythons Elemtree XML implementation, which had problems generating the right format for libvirt: elemtree just supports adding Qname elements (that is "{http://libvirt.org/schemas/domain/qemu/1.0}commandline") which internally would create a temporary binding of this namespace to the "ns0" Prefix. My work-around for Elemtree was the add the name-space mapping for "qemu" to "http://libvirt.org/schemas/domain/qemu/1.0" to ETs internal mapping table and add an "xmlns:qemu" attribute by hand: ET._namespace_map[QEMU_URI] = 'qemu' domain.attrib['xmlns:qemu'] = QEMU_URI libvirt on the other hand expects the prefix to be "qemu" and only checks, that this prefix is bound to the URI mentioned above at the root node). The following examples would be XML valid, but are not accepted by libvirt: ... ... ... ... The following (esoteric) example might be wrongly accepted by libvirt (untested): ... I don't know if this is worth fixing, but I still encountered the first two problems myself and had to spend some time to detecting what I did wrong. So at least I want to share my finding with others, so they don't do the same mistake. Sincerely Philipp Hahn -- Philipp Hahn Open Source Software Engineer hahn at univention.de Univention GmbH Linux for Your Business fon: +49 421 22 232- 0 Mary-Somerville-Str.1 D-28359 Bremen fax: +49 421 22 232-99 http://www.univention.de/ -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 197 bytes Desc: This is a digitally signed message part. URL: From berrange at redhat.com Tue Apr 12 08:14:11 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 12 Apr 2011 09:14:11 +0100 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: <4DA37B7E.60101@codemonkey.ws> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> <20110408133135.GB27561@redhat.com> <4D9F6178.3080500@codemonkey.ws> <20110411214518.GA7750@redhat.com> <4DA37B7E.60101@codemonkey.ws> Message-ID: <20110412081411.GB10071@redhat.com> On Mon, Apr 11, 2011 at 05:06:54PM -0500, Anthony Liguori wrote: > On 04/11/2011 04:45 PM, Daniel P. Berrange wrote: > >On Fri, Apr 08, 2011 at 02:26:48PM -0500, Anthony Liguori wrote: > >>On 04/08/2011 11:02 AM, Stefan Hajnoczi wrote: > >>>On Fri, Apr 8, 2011 at 2:31 PM, Daniel P. Berrange wrote: > >>> > >>>I have CCed Anthony and Kevin. Anthony drove the QED image streaming > >>>and Kevin will probably be interested in the idea of allocating raw > >>>images as a background activity while QEMU runs. > >>> > >>>> /* > >>>> * @path: fully qualified filename of the virtual disk > >>>> * @nregions: filled in the number of @region structs > >>>> * @regions: filled with a list of allocated regions > >>>> * > >>>> * Query the extents of allocated regions within the > >>>> * virtual disk file. The offsets in the list of regions > >>>> * are not guarenteed to be sorted in any explicit order. > >>>> */ > >>>> int virDomainBlockGetAllocationMap(virDomainPtr dom, > >>>> const char *path, > >>>> unsigned int *nregions, > >>>> virDomainBlockRegionPtr *regions); > >>>QEMU can provide this with its existing .bdrv_is_allocated() function. > >>> Kevin, do you have any thoughts on whether this API will work well? > >>I think the trouble with this API proposal is that it's overloading > >>concepts. > >> > >>Sparse is not the same thing as CoW to a backing file. > >I don't like to use the term "sparse", since that implies a specific disk > >format (raw file with holes). Rather I use the term 'thin provisioned' > >to refer to any disk format, where the not all physical sectors have > >yet been allocated. A thin-provisioned disk, can trivially be thought > >of as a disk, with a backing file whose sectors are all filled with > >zeros. > > It's not so black and white today. > > Imagine that you had a qcow2 file, and you "streamed" it such that > it was no longer "thin provisioned", as soon as the guest starts > issuing trim/discards, QEMU could conceivably start defragmenting > the image and truncating resulting in a sparse file. > > The only time the concept of "fully allocated" really makes sense is > for a raw image on a simple file system. Once you start dealing > with things like btrfs and deduplication, and of those useful > guarantees are thrown out the window. I would expect any behaviour where QEMU would defrag/truncate the file to release host storage blocks to be configurable. It must be possible for a mgmt app to ensure that a guest runs with fully allocated storage at all times, to provide protection against allocation failure due to overcommit. > I think the real question is, why do you care about what physical > sectors reside where? What problem are you trying to solve? Err, I don't care where the physical sectors reside. The API is providing info about the logical allocation information. The primary motivation is the image streaming use case, in the sector-at-a-time mode, rather than single-shot entire image. The other example is making an image fully allocated. There may be other use cases, hence the proposal to provide a general purpose API instead of something that only considers the narrow use case of image streaming, which we then have to later replace with something more general. > >>For instance, when you expose streaming, the result is still a > >>sparse file. So you'd have a rather curious API where you called to > >>"allocate" a region in the file which resulted in having a sparse > >>file which you then called again to make it non sparse. But AFAICT, > >>the API doesn't really tell you these details. > >Copy-on-read streaming does not imply that the result is still > >thin-provisioned. That is a policy decision by the management > >application. > > I think your notion of thin-provision doesn't quite map to how > things work today. Unless you're in a very constrained environment, > you're always thin provisioned. I don't agree with that. Use of thin-provisioning is a policy decision that an application can make, not a mandatory requirement Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From kwolf at redhat.com Tue Apr 12 08:31:54 2011 From: kwolf at redhat.com (Kevin Wolf) Date: Tue, 12 Apr 2011 10:31:54 +0200 Subject: [libvirt] [PATCH 1/6] Add new API virDomainStreamDisk[Info] to header and drivers In-Reply-To: <20110412081411.GB10071@redhat.com> References: <1302211924-28517-1-git-send-email-agl@us.ibm.com> <1302211924-28517-2-git-send-email-agl@us.ibm.com> <20110408133135.GB27561@redhat.com> <4D9F6178.3080500@codemonkey.ws> <20110411214518.GA7750@redhat.com> <4DA37B7E.60101@codemonkey.ws> <20110412081411.GB10071@redhat.com> Message-ID: <4DA40DFA.2010309@redhat.com> Am 12.04.2011 10:14, schrieb Daniel P. Berrange: > On Mon, Apr 11, 2011 at 05:06:54PM -0500, Anthony Liguori wrote: >> On 04/11/2011 04:45 PM, Daniel P. Berrange wrote: >>> On Fri, Apr 08, 2011 at 02:26:48PM -0500, Anthony Liguori wrote: >>>> On 04/08/2011 11:02 AM, Stefan Hajnoczi wrote: >>>>> On Fri, Apr 8, 2011 at 2:31 PM, Daniel P. Berrange wrote: >>>>> >>>>> I have CCed Anthony and Kevin. Anthony drove the QED image streaming >>>>> and Kevin will probably be interested in the idea of allocating raw >>>>> images as a background activity while QEMU runs. >>>>> >>>>>> /* >>>>>> * @path: fully qualified filename of the virtual disk >>>>>> * @nregions: filled in the number of @region structs >>>>>> * @regions: filled with a list of allocated regions >>>>>> * >>>>>> * Query the extents of allocated regions within the >>>>>> * virtual disk file. The offsets in the list of regions >>>>>> * are not guarenteed to be sorted in any explicit order. >>>>>> */ >>>>>> int virDomainBlockGetAllocationMap(virDomainPtr dom, >>>>>> const char *path, >>>>>> unsigned int *nregions, >>>>>> virDomainBlockRegionPtr *regions); >>>>> QEMU can provide this with its existing .bdrv_is_allocated() function. >>>>> Kevin, do you have any thoughts on whether this API will work well? >>>> I think the trouble with this API proposal is that it's overloading >>>> concepts. >>>> >>>> Sparse is not the same thing as CoW to a backing file. >>> I don't like to use the term "sparse", since that implies a specific disk >>> format (raw file with holes). Rather I use the term 'thin provisioned' >>> to refer to any disk format, where the not all physical sectors have >>> yet been allocated. A thin-provisioned disk, can trivially be thought >>> of as a disk, with a backing file whose sectors are all filled with >>> zeros. >> >> It's not so black and white today. >> >> Imagine that you had a qcow2 file, and you "streamed" it such that >> it was no longer "thin provisioned", as soon as the guest starts >> issuing trim/discards, QEMU could conceivably start defragmenting >> the image and truncating resulting in a sparse file. >> >> The only time the concept of "fully allocated" really makes sense is >> for a raw image on a simple file system. Once you start dealing >> with things like btrfs and deduplication, and of those useful >> guarantees are thrown out the window. > > I would expect any behaviour where QEMU would defrag/truncate the > file to release host storage blocks to be configurable. While I agree that we should have this option, it isn't true today. So I'm afraid qemu doesn't meet your expectations. > It must be > possible for a mgmt app to ensure that a guest runs with fully > allocated storage at all times, to provide protection against > allocation failure due to overcommit. > >> I think the real question is, why do you care about what physical >> sectors reside where? What problem are you trying to solve? > > Err, I don't care where the physical sectors reside. The API > is providing info about the logical allocation information. > The primary motivation is the image streaming use case, in > the sector-at-a-time mode, rather than single-shot entire > image. The other example is making an image fully allocated. > There may be other use cases, hence the proposal to provide > a general purpose API instead of something that only considers > the narrow use case of image streaming, which we then have to > later replace with something more general. But Anthony is right that the allocation status is more than just a boolean: 1. Allocated 2. Not allocated, but known to be zero (without backing file access) 3. Not allocated in the overlay, but allocated in the backing file 4. Not allocated in both the overlay and the backing file For our problem cases 3 and 4 are almost the same, and they are the interesting ones: You can turn them into case 2 by setting a flag in the overlay image, or you can fully allocate them and turn them into case 1. Streaming is mostly about the former, while preallocation is about the latter. So I think what Anthony wants to know is how this maps to your API. Kevin From minovotn at redhat.com Tue Apr 12 09:05:10 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 12 Apr 2011 11:05:10 +0200 Subject: [libvirt] Libvirt and IPSec (was: What about Trusted Virtual Domains???) In-Reply-To: <4D9C6663.3030504@polito.it> References: <4D9C6663.3030504@polito.it> Message-ID: <4DA415C6.6070602@redhat.com> On 04/06/2011 03:10 PM, Paolo Smiraglia wrote: > Hi to everyone! First of all, sorry for the thread subject change. > > Due to the several issues of the Libvirt implementation of the Trusted > Virtual Domains (TVD), I decided to approach the topic in a modular manner. Hi Paolo, so basically this is about IPSec driver implementation to the libvirt ? I don't think the idea is bad however I'm not working on libvirt too much so you should ask libvirt guys about they opinion. Since I think implementing this may be a good idea I'm putting DV to the CC list for his opinion on this matter. Daniel, if you are not the right person to ask, please tell me however I see Paolo's thread is not having any reply and I think the idea is not bad so I'd like to ask about your opinion on this matter. Thanks, Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From liyong at skybility.com Tue Apr 12 09:35:20 2011 From: liyong at skybility.com (Lyre) Date: Tue, 12 Apr 2011 17:35:20 +0800 Subject: [libvirt] [libvirt-php 0/2] Fixed some memory leaks Message-ID: <1302600922-26817-1-git-send-email-liyong@skybility.com> Hi all: This patch fixed some memory leaks Lyre (2): Fix memory leak when connection failed Fix memory leak when releasing connection & domain src/libvirt-php.c | 36 +++++++++++++++++++++++++++--------- 1 files changed, 27 insertions(+), 9 deletions(-) -- 1.7.3.4 C From liyong at skybility.com Tue Apr 12 09:35:21 2011 From: liyong at skybility.com (Lyre) Date: Tue, 12 Apr 2011 17:35:21 +0800 Subject: [libvirt] [libvirt-php 1/2] Fix memory leak when connection failed In-Reply-To: <1302600922-26817-1-git-send-email-liyong@skybility.com> References: <1302600922-26817-1-git-send-email-liyong@skybility.com> Message-ID: <1302600922-26817-2-git-send-email-liyong@skybility.com> --- src/libvirt-php.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/src/libvirt-php.c b/src/libvirt-php.c index 9998fc8..e6a780a 100644 --- a/src/libvirt-php.c +++ b/src/libvirt-php.c @@ -788,7 +788,11 @@ PHP_FUNCTION(libvirt_connect) efree(creds); } - if (conn->conn == NULL) RETURN_FALSE; + if (conn->conn == NULL) + { + efree (conn); + RETURN_FALSE; + } ZEND_REGISTER_RESOURCE(return_value, conn, le_libvirt_connection); conn->resource_id=Z_LVAL_P(return_value); } -- 1.7.3.4 + From liyong at skybility.com Tue Apr 12 09:35:22 2011 From: liyong at skybility.com (Lyre) Date: Tue, 12 Apr 2011 17:35:22 +0800 Subject: [libvirt] [libvirt-php 2/2] Fix memory leak when releasing connection & domain In-Reply-To: <1302600922-26817-1-git-send-email-liyong@skybility.com> References: <1302600922-26817-1-git-send-email-liyong@skybility.com> Message-ID: <1302600922-26817-3-git-send-email-liyong@skybility.com> --- src/libvirt-php.c | 30 ++++++++++++++++++++++-------- 1 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/libvirt-php.c b/src/libvirt-php.c index e6a780a..ce9d0b9 100644 --- a/src/libvirt-php.c +++ b/src/libvirt-php.c @@ -291,10 +291,17 @@ static void php_libvirt_connection_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) php_libvirt_connection *conn = (php_libvirt_connection*)rsrc->ptr; int rv; - rv = virConnectClose(conn->conn); - if (rv!=0) - php_error_docref(NULL TSRMLS_CC, E_WARNING,"virConnectClose failed with %i on destructor: %s", rv, LIBVIRT_G (last_error)); - conn->conn=NULL; + if (conn != NULL) + { + if (conn->conn != NULL) + { + rv = virConnectClose(conn->conn); + if (rv!=0) + php_error_docref(NULL TSRMLS_CC, E_WARNING,"virConnectClose failed with %i on destructor: %s", rv, LIBVIRT_G (last_error)); + conn->conn=NULL; + } + efree (conn); + } } /* Destructor for domain resource */ @@ -303,10 +310,17 @@ static void php_libvirt_domain_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) php_libvirt_domain *domain = (php_libvirt_domain*)rsrc->ptr; int rv; - rv = virDomainFree (domain->domain); - if (rv != 0) - php_error_docref(NULL TSRMLS_CC, E_WARNING,"virDomainFree failed with %i on destructor: %s", rv, LIBVIRT_G (last_error)); - domain->domain=NULL; + if (domain != NULL) + { + if (domain->domain != NULL) + { + rv = virDomainFree (domain->domain); + if (rv != 0) + php_error_docref(NULL TSRMLS_CC, E_WARNING,"virDomainFree failed with %i on destructor: %s", rv, LIBVIRT_G (last_error)); + domain->domain=NULL; + } + efree (domain); + } } /* Destructor for storagepool resource */ -- 1.7.3.4 ? From minovotn at redhat.com Tue Apr 12 09:40:40 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 12 Apr 2011 11:40:40 +0200 Subject: [libvirt] [libvirt-php 0/2] Fixed some memory leaks In-Reply-To: <1302600922-26817-1-git-send-email-liyong@skybility.com> References: <1302600922-26817-1-git-send-email-liyong@skybility.com> Message-ID: <4DA41E18.3090000@redhat.com> On 04/12/2011 11:35 AM, Lyre wrote: > Hi all: > > This patch fixed some memory leaks > > Lyre (2): > Fix memory leak when connection failed > Fix memory leak when releasing connection & domain > > src/libvirt-php.c | 36 +++++++++++++++++++++++++++--------- > 1 files changed, 27 insertions(+), 9 deletions(-) > Good thing to fix those memory leaks, ACKed and pushed series. Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From berrange at redhat.com Tue Apr 12 10:19:11 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 12 Apr 2011 11:19:11 +0100 Subject: [libvirt] qemu-namespace handling? In-Reply-To: <201104120929.15619.hahn@univention.de> References: <201104120929.15619.hahn@univention.de> Message-ID: <20110412101911.GD10071@redhat.com> On Tue, Apr 12, 2011 at 09:29:15AM +0200, Philipp Hahn wrote: > Hello, > > some time ago I hand to manipulate the domain XML description using Pythons > Elemtree XML implementation, which had problems generating the right format > for libvirt: elemtree just supports adding Qname elements (that > is "{http://libvirt.org/schemas/domain/qemu/1.0}commandline") which > internally would create a temporary binding of this namespace to the "ns0" > Prefix. > > My work-around for Elemtree was the add the name-space mapping for "qemu" > to "http://libvirt.org/schemas/domain/qemu/1.0" to ETs internal mapping table > and add an "xmlns:qemu" attribute by hand: > ET._namespace_map[QEMU_URI] = 'qemu' > domain.attrib['xmlns:qemu'] = QEMU_URI > > libvirt on the other hand expects the prefix to be "qemu" and only checks, > that this prefix is bound to the URI mentioned above at the root node). This is definitely a libvirt bug we should fix. The namespace prefix should not be used as anything other than a key to match to a corresponding namespace URI. So libvirt should not look for "qemu", it should allow anything which ultimately maps to "http://libvirt.org/schemas/domain/qemu/1.0" > The following examples would be XML valid, but are not accepted by libvirt: > > ... > > ... > > > ... > > ... > Yes, we should fix our code to accept both of those. > The following (esoteric) example might be wrongly accepted by libvirt > (untested): > > > > ... > Eww, nasty. > I don't know if this is worth fixing, but I still encountered the first two > problems myself and had to spend some time to detecting what I did wrong. So > at least I want to share my finding with others, so they don't do the same > mistake. Thanks for pointing this out. We really want to fix this, because when building up an XML doc via an API, it is all too easy to skip over the addition of the fixed prefix<->URI mapping, and just let your XML API auto-generate a prefix. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From wency at cn.fujitsu.com Tue Apr 12 10:22:12 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Tue, 12 Apr 2011 18:22:12 +0800 Subject: [libvirt] [PATCH 3/6] use virObject to manage reference-count of virDomainObj In-Reply-To: <20110412055133.GA4164@localhost.localdomain> References: <4D9CEA54.6000402@redhat.com> <20110412033407.GA32561@localhost.localdomain> <20110412055133.GA4164@localhost.localdomain> Message-ID: <4DA427D4.2090502@cn.fujitsu.com> At 04/12/2011 01:51 PM, Hu Tao Write: > Sorry, I unexpectedly deleted text body. > > I changed the code like this: > > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > index c2a1f9a..8aad0b3 100644 > --- a/src/qemu/qemu_domain.c > +++ b/src/qemu/qemu_domain.c > @@ -514,7 +514,10 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, > else > virReportSystemError(errno, > "%s", _("cannot acquire job mutex")); > + virDomainObjUnlock(obj); > qemuDriverLock(driver); > + virDomainObjLock(obj); We lock qemu_driver and vm as the folling steps: 1. lock qemu_driver 2. lock vm We try to lock qemu_driver while holding the vm's lock. OOps, it will cause the libvirtd deadlock.(I can reproduce this bug by your script) > + virDomainObjUnref(obj); We have unref it, so do not unref it again. > return -1; > } > } > > but still have problem. (see log in previous mail.) The reference count > of virDomainObj becomes 0 while there are still threads accessing it. > This causes two results: one is segmentation fault as shown in the log; > the other is the qemu monitor fd is closed two early, and threads are > polling a closed fd. > > Steps of my test: > > 1. change the value of max_clients in /etc/libvirt/libvirtd.conf to > big enough value: > > max_clients = 2000000 > > 2. run libvirtd > > 3. run libvirt-test.sh hut-vm1 (hut-vm1 is my vm name) (warning: this > script forks many processes you have to kill by hand) > > (again, the log and script libvirt-test.sh are in my previous mail) > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list > From hutao at cn.fujitsu.com Tue Apr 12 10:33:21 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Tue, 12 Apr 2011 18:33:21 +0800 Subject: [libvirt] [PATCH 3/6] use virObject to manage reference-count of virDomainObj In-Reply-To: <4DA427D4.2090502@cn.fujitsu.com> References: <4D9CEA54.6000402@redhat.com> <20110412033407.GA32561@localhost.localdomain> <20110412055133.GA4164@localhost.localdomain> <4DA427D4.2090502@cn.fujitsu.com> Message-ID: <20110412103321.GC4164@localhost.localdomain> On Tue, Apr 12, 2011 at 06:22:12PM +0800, Wen Congyang wrote: > At 04/12/2011 01:51 PM, Hu Tao Write: > > Sorry, I unexpectedly deleted text body. > > > > I changed the code like this: > > > > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > > index c2a1f9a..8aad0b3 100644 > > --- a/src/qemu/qemu_domain.c > > +++ b/src/qemu/qemu_domain.c > > @@ -514,7 +514,10 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, > > else > > virReportSystemError(errno, > > "%s", _("cannot acquire job mutex")); > > + virDomainObjUnlock(obj); > > qemuDriverLock(driver); > > + virDomainObjLock(obj); > > We lock qemu_driver and vm as the folling steps: > 1. lock qemu_driver > 2. lock vm > > We try to lock qemu_driver while holding the vm's lock. > OOps, it will cause the libvirtd deadlock.(I can reproduce this bug by your script) > > > + virDomainObjUnref(obj); > > We have unref it, so do not unref it again. Didn't see there is already a call to virDomainObjUnref. the patch should be: >From 712883d0151222a276f777f473d96aa23ad5d9d6 Mon Sep 17 00:00:00 2001 From: Hu Tao Date: Tue, 12 Apr 2011 18:29:27 +0800 Subject: [PATCH] qemu: fix a dead-lock problem In qemuDomainObjBeginJobWithDriver, when virCondWaitUntil timeouts, the function tries to call qemuDriverLock with virDomainObj locked, this causes the dead-lock problem. This patch fixes this. --- src/qemu/qemu_domain.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index c2a1f9a..a947b4e 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -506,15 +506,17 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, while (priv->jobActive) { if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) { - /* Safe to ignore value since ref count was incremented above */ - ignore_value(virDomainObjUnref(obj)); if (errno == ETIMEDOUT) qemuReportError(VIR_ERR_OPERATION_TIMEOUT, "%s", _("cannot acquire state change lock")); else virReportSystemError(errno, "%s", _("cannot acquire job mutex")); + virDomainObjUnlock(obj); qemuDriverLock(driver); + virDomainObjLock(obj); + /* Safe to ignore value since ref count was incremented above */ + ignore_value(virDomainObjUnref(obj)); return -1; } } -- 1.7.3.1 From berrange at redhat.com Tue Apr 12 10:40:13 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 12 Apr 2011 11:40:13 +0100 Subject: [libvirt] [PATCH 3/6] use virObject to manage reference-count of virDomainObj In-Reply-To: <20110412103321.GC4164@localhost.localdomain> References: <4D9CEA54.6000402@redhat.com> <20110412033407.GA32561@localhost.localdomain> <20110412055133.GA4164@localhost.localdomain> <4DA427D4.2090502@cn.fujitsu.com> <20110412103321.GC4164@localhost.localdomain> Message-ID: <20110412104013.GE10071@redhat.com> On Tue, Apr 12, 2011 at 06:33:21PM +0800, Hu Tao wrote: > On Tue, Apr 12, 2011 at 06:22:12PM +0800, Wen Congyang wrote: > > At 04/12/2011 01:51 PM, Hu Tao Write: > > > Sorry, I unexpectedly deleted text body. > > > > > > I changed the code like this: > > > > > > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > > > index c2a1f9a..8aad0b3 100644 > > > --- a/src/qemu/qemu_domain.c > > > +++ b/src/qemu/qemu_domain.c > > > @@ -514,7 +514,10 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, > > > else > > > virReportSystemError(errno, > > > "%s", _("cannot acquire job mutex")); > > > + virDomainObjUnlock(obj); > > > qemuDriverLock(driver); > > > + virDomainObjLock(obj); > > > > We lock qemu_driver and vm as the folling steps: > > 1. lock qemu_driver > > 2. lock vm > > > > We try to lock qemu_driver while holding the vm's lock. > > OOps, it will cause the libvirtd deadlock.(I can reproduce this bug by your script) > > > > > + virDomainObjUnref(obj); > > > > We have unref it, so do not unref it again. > > Didn't see there is already a call to virDomainObjUnref. the patch > should be: > > >From 712883d0151222a276f777f473d96aa23ad5d9d6 Mon Sep 17 00:00:00 2001 > From: Hu Tao > Date: Tue, 12 Apr 2011 18:29:27 +0800 > Subject: [PATCH] qemu: fix a dead-lock problem > > In qemuDomainObjBeginJobWithDriver, when virCondWaitUntil timeouts, > the function tries to call qemuDriverLock with virDomainObj locked, > this causes the dead-lock problem. This patch fixes this. > --- > src/qemu/qemu_domain.c | 6 ++++-- > 1 files changed, 4 insertions(+), 2 deletions(-) > > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > index c2a1f9a..a947b4e 100644 > --- a/src/qemu/qemu_domain.c > +++ b/src/qemu/qemu_domain.c > @@ -506,15 +506,17 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, > > while (priv->jobActive) { > if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) { > - /* Safe to ignore value since ref count was incremented above */ > - ignore_value(virDomainObjUnref(obj)); > if (errno == ETIMEDOUT) > qemuReportError(VIR_ERR_OPERATION_TIMEOUT, > "%s", _("cannot acquire state change lock")); > else > virReportSystemError(errno, > "%s", _("cannot acquire job mutex")); > + virDomainObjUnlock(obj); > qemuDriverLock(driver); > + virDomainObjLock(obj); > + /* Safe to ignore value since ref count was incremented above */ > + ignore_value(virDomainObjUnref(obj)); > return -1; > } > } > -- ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From paolo.smiraglia at polito.it Tue Apr 12 11:23:51 2011 From: paolo.smiraglia at polito.it (Paolo Smiraglia) Date: Tue, 12 Apr 2011 13:23:51 +0200 Subject: [libvirt] Libvirt and IPSec (was: What about Trusted Virtual Domains???) In-Reply-To: <4DA415C6.6070602@redhat.com> References: <4D9C6663.3030504@polito.it> <4DA415C6.6070602@redhat.com> Message-ID: <4DA43647.5040602@polito.it> Hi Michael! Thanks for the reply. Comments are inline. > Hi Paolo, > so basically this is about IPSec driver implementation to the libvirt ? Exactly... > I don't think the idea is bad however I'm not working on libvirt too > much so you should ask libvirt guys about they opinion. > > Since I think implementing this may be a good idea I'm putting DV to the > CC list for his opinion on this matter. Thanks for the "support of the cause". ;-) See you, Paolo -- PAOLO SMIRAGLIA Department of Control and Computer Engineering Polytechnic University of Turin Email: paolo.smiraglia at polito.it -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 6095 bytes Desc: S/MIME Cryptographic Signature URL: From minovotn at redhat.com Tue Apr 12 11:34:18 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 12 Apr 2011 13:34:18 +0200 Subject: [libvirt] Libvirt and IPSec In-Reply-To: <4DA43647.5040602@polito.it> References: <4D9C6663.3030504@polito.it> <4DA415C6.6070602@redhat.com> <4DA43647.5040602@polito.it> Message-ID: <4DA438BA.3050401@redhat.com> On 04/12/2011 01:23 PM, Paolo Smiraglia wrote: > Hi Michael! > Thanks for the reply. Comments are inline. > >> Hi Paolo, >> so basically this is about IPSec driver implementation to the libvirt ? > Exactly... > Ok, right. I don't know much about IPSec itself so some study on the matter would be necessary to provide some better understanding however from what I know the implementation to the Linux kernel directly is possible for the software stack however implementing this in the virtual hardware stack (emulation) is certainly a good thing since you don't need to patch the kernel at all. The only thing I'm not sure about is the technical point of view since I don't know how hard would the implementation be. >> I don't think the idea is bad however I'm not working on libvirt too >> much so you should ask libvirt guys about they opinion. >> >> Since I think implementing this may be a good idea I'm putting DV to the >> CC list for his opinion on this matter. > Thanks for the "support of the cause". ;-) No problem since I think the idea is good and therefore I support the idea at least :) Have a great time, Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From james.barkley at gmail.com Tue Apr 12 12:13:43 2011 From: james.barkley at gmail.com (jbarkley) Date: Tue, 12 Apr 2011 08:13:43 -0400 Subject: [libvirt] [PATCH] - added mapping to Network object - added implementation of select networking functions - virsh net-list and net-info commands now work for esx Message-ID: <1302610423-19095-1-git-send-email-james.barkley@gmail.com> From: jbarkely --- src/esx/esx_network_driver.c | 181 +++++++++++++++++++++++++++++++++++++++- src/esx/esx_vi.c | 104 ++++++++++++++++++++++- src/esx/esx_vi.h | 9 ++ src/esx/esx_vi_generator.input | 78 +++++++++++++++++ 4 files changed, 366 insertions(+), 6 deletions(-) diff --git a/src/esx/esx_network_driver.c b/src/esx/esx_network_driver.c index a64bb8e..c4cc7b4 100644 --- a/src/esx/esx_network_driver.c +++ b/src/esx/esx_network_driver.c @@ -34,6 +34,7 @@ #include "esx_vi.h" #include "esx_vi_methods.h" #include "esx_util.h" +#include "md5.h" #define VIR_FROM_THIS VIR_FROM_ESX @@ -63,18 +64,190 @@ esxNetworkClose(virConnectPtr conn) return 0; } +static virNetworkPtr +esxNetworkLookupByName(virConnectPtr conn, const char *name) { + //esxPrivate *priv = conn->networkPrivateData; + esxPrivate *priv = conn->networkPrivateData; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *network = NULL; + virNetworkPtr virNetwork = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; + unsigned char md5[MD5_DIGEST_SIZE]; /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */ + + if (esxVI_EnsureSession(priv->primary) < 0) { + return NULL; + } + + if (esxVI_LookupNetworkByName(priv->primary, name, propertyNameList, + &network, + esxVI_Occurrence_OptionalItem) < 0) { + goto cleanup; + } + + if (NULL==network) { + // raise error + ESX_ERROR(VIR_ERR_NO_NETWORK, _("No network with name '%s'"), name); + goto cleanup; + + } + + char *name_candidate = NULL; + esxVI_GetStringValue(network, "name", &name_candidate, esxVI_Occurrence_OptionalItem); + + md5_buffer(name, strlen(name), md5); + virNetwork = virGetNetwork(conn, name, md5); + + cleanup: + esxVI_String_Free(&propertyNameList); + //esxVI_ObjectContent_Free(&network); +// printf("virNetwork=%s\n", virNetwork->name); + return virNetwork; +} + +static int +esxListNetworks(virConnectPtr conn, char **const names, int nnames) +{ + //setup + bool success = false; + esxPrivate *priv = conn->networkPrivateData; + esxVI_String *propertyNameList = NULL; + esxVI_DynamicProperty *dynamicProperty = NULL; + esxVI_ObjectContent *networkList = NULL; + esxVI_ObjectContent *network = NULL; + int count = 0; + int i; + + //check args + if (names == NULL || nnames < 0) { + ESX_ERROR(VIR_ERR_INVALID_ARG, "%s", _("Invalid argument")); + return -1; + } + + if (nnames == 0) { + return 0; + } + + //check connection + if (esxVI_EnsureSession(priv->primary) < 0) { + return -1; + } + + //get network(s) + if (esxVI_String_AppendValueToList(&propertyNameList, + "summary.name") < 0 || + esxVI_LookupNetworkList(priv->primary, propertyNameList, + &networkList) < 0) { + goto cleanup; + } + + for (network = networkList; network != NULL; + network = network->_next) { + for (dynamicProperty = network->propSet; dynamicProperty != NULL; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, "summary.name")) { + if (esxVI_AnyType_ExpectType(dynamicProperty->val, + esxVI_Type_String) < 0) { + goto cleanup; + } + + names[count] = strdup(dynamicProperty->val->string); + + if (names[count] == NULL) { + virReportOOMError(); + goto cleanup; + } + + ++count; + break; + } else { + VIR_WARN("Unexpected '%s' property", dynamicProperty->name); + } + } + } + + success = true; + + //cleanup + cleanup: + if (! success) { + for (i = 0; i < count; ++i) { + VIR_FREE(names[i]); + } + + count = -1; + } + + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&networkList); + + return count; +} + +static int +esxNumOfNetworks(virConnectPtr conn) +{ + //setup + esxPrivate *priv = conn->networkPrivateData; + esxVI_String *propertyNameList = NULL; + esxVI_DynamicProperty *dynamicProperty = NULL; + esxVI_ObjectContent *networkList = NULL; + esxVI_ObjectContent *network = NULL; + int count = 0; + int i; + + //check connection + if (esxVI_EnsureSession(priv->primary) < 0) { + return -1; + } + + //get network(s) + if (esxVI_String_AppendValueToList(&propertyNameList, + "summary.name") < 0 || + esxVI_LookupNetworkList(priv->primary, propertyNameList, + &networkList) < 0) { + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&networkList); + + return -1; + } + + for (network = networkList; network != NULL; + network = network->_next) { + for (dynamicProperty = network->propSet; dynamicProperty != NULL; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, "summary.name")) { + ++count; + break; + } else { + VIR_WARN("Unexpected '%s' property", dynamicProperty->name); + } + } + } + + + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&networkList); + + return count; +} + +static int esxNumOfDefinedNetworks(virConnectPtr conn) +{ + printf("JB-BUG C\n"); + return 8; +} static virNetworkDriver esxNetworkDriver = { "ESX", /* name */ esxNetworkOpen, /* open */ esxNetworkClose, /* close */ - NULL, /* numOfNetworks */ - NULL, /* listNetworks */ - NULL, /* numOfDefinedNetworks */ + esxNumOfNetworks, /* numOfNetworks */ + esxListNetworks, /* listNetworks */ + esxNumOfDefinedNetworks, /* numOfDefinedNetworks */ NULL, /* listDefinedNetworks */ NULL, /* networkLookupByUUID */ - NULL, /* networkLookupByName */ + esxNetworkLookupByName, /* networkLookupByName */ NULL, /* networkCreateXML */ NULL, /* networkDefineXML */ NULL, /* networkUndefine */ diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index 7446ec5..509cf07 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -109,6 +109,7 @@ ESX_VI__TEMPLATE__FREE(Context, esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToParent); esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToVm); esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToDatastore); + esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToNetwork); esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToHost); esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToParentToParent); }); @@ -1483,6 +1484,13 @@ esxVI_BuildSelectSetCollection(esxVI_Context *ctx) return -1; } + /* HostSystem -> network (Network) */ + if (esxVI_BuildSelectSet(&ctx->selectSet_hostSystemToNetwork, + "hostSystemToNetwork", + "HostSystem", "network", NULL) < 0) { + return -1; + } + /* Folder -> parent (Folder, Datacenter) */ if (esxVI_BuildSelectSet(&ctx->selectSet_computeResourceToParentToParent, "managedEntityToParent", @@ -1543,9 +1551,13 @@ esxVI_EnsureSession(esxVI_Context *ctx) * Query the session manager for the current session of this connection * and re-login if there is no current session for this connection. */ + if (esxVI_String_AppendValueToList(&propertyNameList, - "currentSession") < 0 || - esxVI_LookupObjectContentByType(ctx, ctx->service->sessionManager, + "currentSession") < 0) { + goto cleanup; + } + + if (esxVI_LookupObjectContentByType(ctx, ctx->service->sessionManager, "SessionManager", propertyNameList, &sessionManager, esxVI_Occurrence_RequiredItem) < 0) { @@ -1649,6 +1661,8 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx, objectSpec->selectSet = ctx->selectSet_hostSystemToVm; } else if (STREQ(type, "Datastore")) { objectSpec->selectSet = ctx->selectSet_hostSystemToDatastore; + } else if (STREQ(type, "Network")) { + objectSpec->selectSet = ctx->selectSet_hostSystemToNetwork; } else { ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, _("Invalid lookup of '%s' from '%s'"), @@ -2474,6 +2488,92 @@ esxVI_LookupDatastoreList(esxVI_Context *ctx, esxVI_String *propertyNameList, esxVI_Occurrence_OptionalList); } +int +esxVI_LookupNetworkList(esxVI_Context *ctx, + esxVI_String *propertyNameList, + esxVI_ObjectContent **networkList) +{ + return esxVI_LookupObjectContentByType(ctx, ctx->hostSystem->_reference, + "Network", propertyNameList, + networkList, + esxVI_Occurrence_OptionalList); +} + +int +esxVI_LookupNetworkByName(esxVI_Context *ctx, const char *name, + esxVI_String *propertyNameList, + esxVI_ObjectContent **network, + esxVI_Occurrence occurrence) +{ + int result = -1; + esxVI_String *completePropertyNameList = NULL; + esxVI_ObjectContent *networkList = NULL; + esxVI_ObjectContent *candidate = NULL; + char *name_candidate = NULL; + + if (network == NULL || *network != NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + + if (esxVI_String_DeepCopyList(&completePropertyNameList, + propertyNameList) < 0 || + esxVI_String_AppendValueToList(&completePropertyNameList, "name") < 0 || + esxVI_LookupNetworkList(ctx, completePropertyNameList, + &networkList) < 0) { + goto cleanup; + } + + for (candidate = networkList; candidate != NULL; + candidate = candidate->_next) { + VIR_FREE(name_candidate); + + /* + if (esxVI_GetVirtualMachineIdentity(candidate, NULL, &name_candidate, + NULL) < 0) { + goto cleanup; + } + */ + if (esxVI_GetStringValue(candidate, "name", &name_candidate, + esxVI_Occurrence_OptionalItem) < 0) { + goto cleanup; + } + + if (STRNEQ(name, name_candidate)) { + continue; + } + + if (esxVI_ObjectContent_DeepCopy(network, candidate) < 0) { + goto cleanup; + } + + break; + } + + /* + if (*network == NULL) { + if (occurrence == esxVI_Occurrence_OptionalItem) { + result = 0; + + goto cleanup; + } else { + ESX_VI_ERROR(VIR_ERR_NO_NETWORK, + _("Could not find network with name '%s'"), name); + goto cleanup; + } + } + */ + + result = 0; + + cleanup: + esxVI_String_Free(&completePropertyNameList); + esxVI_ObjectContent_Free(&networkList); + //VIR_FREE(name_candidate); + + return result; +} int diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index e150dbf..cbd6068 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -165,6 +165,7 @@ struct _esxVI_Context { esxVI_SelectionSpec *selectSet_hostSystemToParent; esxVI_SelectionSpec *selectSet_hostSystemToVm; esxVI_SelectionSpec *selectSet_hostSystemToDatastore; + esxVI_SelectionSpec *selectSet_hostSystemToNetwork; esxVI_SelectionSpec *selectSet_computeResourceToHost; esxVI_SelectionSpec *selectSet_computeResourceToParentToParent; bool hasQueryVirtualDiskUuid; @@ -367,11 +368,19 @@ int esxVI_LookupVirtualMachineByUuidAndPrepareForTask int esxVI_LookupDatastoreList(esxVI_Context *ctx, esxVI_String *propertyNameList, esxVI_ObjectContent **datastoreList); +int esxVI_LookupNetworkList(esxVI_Context *ctx, esxVI_String *propertyNameList, + esxVI_ObjectContent **networkList); + int esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name, esxVI_String *propertyNameList, esxVI_ObjectContent **datastore, esxVI_Occurrence occurrence); +int esxVI_LookupNetworkByName(esxVI_Context *ctx, const char *name, + esxVI_String *propertyNameList, + esxVI_ObjectContent **network, + esxVI_Occurrence occurrence); + int esxVI_LookupDatastoreByAbsolutePath(esxVI_Context *ctx, const char *absolutePath, esxVI_String *propertyNameList, diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input index 44d1d9b..86c4b12 100644 --- a/src/esx/esx_vi_generator.input +++ b/src/esx/esx_vi_generator.input @@ -334,6 +334,84 @@ object HostNasVolume extends HostFileSystemVolume String userName o end +object HostNetCapabilities +end + +object HostIpRouteConfig +end + +object HostDnsConfig +end + +object HostIpRouteConfig +end + +object HostNetworkConfig +end + +object HostNetworkInfo +end + +object HostNetworkSystem + HostNetCapabilities capabilities rl + HostIpRouteConfig consoleIpRuteConfig r + HostDnsConfig dnsConfig r + HostIpRouteConfig ipRouteConfig r + HostNetworkConfig networkConfig r + HostNetworkInfo networkInfo r +end + + +object HostIpRouteConfig +end + +object HostVirtualNic +end + +object HostDhcpService +end + +object HostDnsConfig +end + +object HostNatService +end + +object PhysicalNic +end + +object HostPortGroup +end + +object HostProxySwitch +end + +object HostIpRouteTableInfo +end + +object HostVirtualNic +end + +object HostVirtualSwitch +end + +object HostNetworkInfo + Boolean atBootIpV6Enabled r + HostIpRouteConfig consoleIpRouteConfig r + HostVirtualNic consoleVnic rl + HostDhcpService dhcp rl + HostDnsConfig dnsConfig r + HostIpRouteConfig ipRouteConfig r + Boolean ipV6Enabled r + HostNatService nat rl + PhysicalNic pnic rl + HostPortGroup portgroup rl + HostProxySwitch proxySwitch rl + HostIpRouteTableInfo routeTableInfo r + HostVirtualNic vnic rl + HostVirtualSwitch vswitch rl +end + object HostScsiDiskPartition String diskName r -- 1.7.4.1 From mprivozn at redhat.com Tue Apr 12 14:58:48 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Tue, 12 Apr 2011 16:58:48 +0200 Subject: [libvirt] [PATCH] Fix possible infinite loop in remote driver Message-ID: <1302620328-10231-1-git-send-email-mprivozn@redhat.com> When we take out completed calls from queue we might end up in circular pointer. We don't want pointer to previous item point to element taken out. --- src/remote/remote_driver.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 9310ddf..ec10010 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -10672,8 +10672,9 @@ remoteIOEventLoop(virConnectPtr conn, */ VIR_DEBUG("Waking up sleep %d %p %p", tmp->proc_nr, tmp, priv->waitDispatch); virCondSignal(&tmp->cond); + } else { + prev = tmp; } - prev = tmp; tmp = tmp->next; } -- 1.7.4.2 From eblake at redhat.com Tue Apr 12 15:07:23 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 12 Apr 2011 09:07:23 -0600 Subject: [libvirt] [PATCH] maint: fix grammar errors In-Reply-To: <4DA3AD38.2000607@cn.fujitsu.com> References: <1302560839-23381-1-git-send-email-eblake@redhat.com> <4DA3AD38.2000607@cn.fujitsu.com> Message-ID: <4DA46AAB.3050004@redhat.com> On 04/11/2011 07:39 PM, Wen Congyang wrote: > At 04/12/2011 06:27 AM, Eric Blake Write: >> Jim recently improved gnulib to catch various grammar errors >> during 'make syntax-check'. >> >> * .gnulib: Update to latest, for syntax-check improvements. >> * include/libvirt/libvirt.h.in (virConnectAuthCallbackPtr): Use >> cannot rather than two words. > > I modify cfg.mk and update gnulib, use 'make syntax-check' and found the same grammar > errors. > ACK. Thanks; pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From berrange at redhat.com Tue Apr 12 15:12:08 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 12 Apr 2011 16:12:08 +0100 Subject: [libvirt] [PATCH] Fix possible infinite loop in remote driver In-Reply-To: <1302620328-10231-1-git-send-email-mprivozn@redhat.com> References: <1302620328-10231-1-git-send-email-mprivozn@redhat.com> Message-ID: <20110412151208.GJ10071@redhat.com> On Tue, Apr 12, 2011 at 04:58:48PM +0200, Michal Privoznik wrote: > When we take out completed calls from queue we might end up > in circular pointer. We don't want pointer to previous item > point to element taken out. > --- > src/remote/remote_driver.c | 3 ++- > 1 files changed, 2 insertions(+), 1 deletions(-) > > diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c > index 9310ddf..ec10010 100644 > --- a/src/remote/remote_driver.c > +++ b/src/remote/remote_driver.c > @@ -10672,8 +10672,9 @@ remoteIOEventLoop(virConnectPtr conn, > */ > VIR_DEBUG("Waking up sleep %d %p %p", tmp->proc_nr, tmp, priv->waitDispatch); > virCondSignal(&tmp->cond); > + } else { > + prev = tmp; > } > - prev = tmp; > tmp = tmp->next; > } ACK The diff context doesn't really show enough, but this is correct fix for the logic flaw Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From laine at laine.org Tue Apr 12 15:23:48 2011 From: laine at laine.org (Laine Stump) Date: Tue, 12 Apr 2011 11:23:48 -0400 Subject: [libvirt] Libvirt and IPSec (was: What about Trusted Virtual Domains???) In-Reply-To: <4D9C6663.3030504@polito.it> References: <4D9C6663.3030504@polito.it> Message-ID: <4DA46E84.4010908@laine.org> On 04/06/2011 09:10 AM, Paolo Smiraglia wrote: > Hi to everyone! First of all, sorry for the thread subject change. > > Due to the several issues of the Libvirt implementation of the Trusted > Virtual Domains (TVD), I decided to approach the topic in a modular > manner. > > I think that the first step should be to define the IPSec support or, > more in general, the secure tunnel support for Libvirt. I see the > implementation divided in two step: > > 1. define a new driver called 'sectunnel' which describes a generic > secure tunnel that will be established using several > technologies (for now using only ipsec) Would this tunnel be necessarily brought up / torn down by libvirt, or could it be (maybe preferable? I don't have an opinion, just asking) that it be part of the host config, populating files in /etc. If the latter, maybe the right thing to do would be to enhance the XML of virInterfaceDefine (as described by netcf) to also configure ipsec tunnels (and openvpn tunnels, and whatever other tunnels) (I mention this both as a possible way to avoid the need for a new libvirt API, as well as to enhance the functionality of virInterface*() and netcf) Currently all traffic from the virtual networks is simply sent to the host's IP stack for forwarding. Are the decisions about which IPSec association to use for traffic based solely on routing, and is there necessarily a single routing domain on a host? Or can the decision be based on ipfilter rules and/or multiple routing domains on a single host (we had experimented with both of these at a former employer, but I don't recall which parts of it were local modifications and which were part of the stock kernel). If all decisions are based on routing, and there is a single routing domain, then the tunnel will necessarily be system-wide on the host, and may just as well be configured as any other interface (the only difference being that interfaces configured with virInterfaceDefine() persist even if libvirt is stopped and never started again, while something defined with virNetworkDefine (and probably a virSecTunnelDefine) may persist beyond stopping libvirt, but would not survive a reboot if libvirt wasn't started. A fine distinction actually, and maybe one that doesn't need to be made in general, but that's a different discussion) > 2. modify the existing 'network' driver by adding the possibility to > specify the 'sectunnel' that > the network have to use in the virtual network definition Will *all* traffic leaving/entering the virtual network travel via the tunnel, and will there be a single tunnel? If so, this could be given as a part of the element (similar to the way "dev='eth0'" is used now - it specifies that all traffic entering/leaving must go via eth0). It would look something like this: (of course all this really does is to set an ipfilter rule that disallows forwarding traffic to/from any other interface from/to the virtual network). Beyond that, if there will an exact 1:1 correspondence between secure tunnel and virtual network (half of which is implied by the "tunnel='sec-net'"), perhaps the config for the tunnel could just be included in the xml (probably as sub-elements of ) rather than creating yet another API (and also the need to involve virInterface*()/netcf) > As an example, you can see below a possible XML definition of the > network which use a secure tunnel and the corresponding 'sectunnel' > XML definition: > > NETWORK DEFINITION > ================== > > sec-net > 3e3fce45-4f53-4fa7-bb32-11f34168b82b > > > ... > <--(specify the 'sectunnel' to use) > > > SECTUNNEL DEFINITION > ==================== > > sec-tun > 8b7fd1b0-4463-43b7-8b6e-8006344aeb66 > > > > > <--(specify the 'secret' which > contains the pre-shared key) > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > As you can see in the 'sectunnel' XML definition, I use a 'secret' > element. This element is a Libvirt secret [1] and it stores the > pre-shared key used by IPSec to establish the Security Associations > (SA). Obviously this feature requires to define a new usage category > in the 'secret' driver definition. > > Another possible way to establish the SA is to use the X.509 > certificates. To this purpose, I think that the certificates already > used by Libvirt to setup SSL/TLS remote connections, might be used. > > That's all! :-) > > What do you think about this possible IPSec implementation? > > Thanks in advance for the replies! > > Best regards, > > PAOLO > > > > LINK LIST > --------- > [1] http://libvirt.org/formatsecret.html > > > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list From eblake at redhat.com Tue Apr 12 15:51:50 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 12 Apr 2011 09:51:50 -0600 Subject: [libvirt] [PATCH] Fix possible infinite loop in remote driver In-Reply-To: <20110412151208.GJ10071@redhat.com> References: <1302620328-10231-1-git-send-email-mprivozn@redhat.com> <20110412151208.GJ10071@redhat.com> Message-ID: <4DA47516.9020003@redhat.com> On 04/12/2011 09:12 AM, Daniel P. Berrange wrote: > On Tue, Apr 12, 2011 at 04:58:48PM +0200, Michal Privoznik wrote: >> When we take out completed calls from queue we might end up >> in circular pointer. We don't want pointer to previous item >> point to element taken out. >> --- >> src/remote/remote_driver.c | 3 ++- >> 1 files changed, 2 insertions(+), 1 deletions(-) >> >> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c >> index 9310ddf..ec10010 100644 >> --- a/src/remote/remote_driver.c >> +++ b/src/remote/remote_driver.c >> @@ -10672,8 +10672,9 @@ remoteIOEventLoop(virConnectPtr conn, >> */ >> VIR_DEBUG("Waking up sleep %d %p %p", tmp->proc_nr, tmp, priv->waitDispatch); >> virCondSignal(&tmp->cond); >> + } else { >> + prev = tmp; >> } >> - prev = tmp; >> tmp = tmp->next; >> } > > ACK > > The diff context doesn't really show enough, but this is correct fix > for the logic flaw I've pushed this. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From laine at laine.org Tue Apr 12 16:13:56 2011 From: laine at laine.org (Laine Stump) Date: Tue, 12 Apr 2011 12:13:56 -0400 Subject: [libvirt] RFC: disconnecting guest/domain interface config from host config (aka migration with macvtap) Message-ID: <4DA47A44.8040307@laine.org> Abstraction of guest <--> host network connection in libvirt ===================================== The element of a guest's domain config in libvirt has a element that describes what resources on a host will be used to connect the guest's network interface to the rest of the world. This is very flexible, allowing several different types of connection (virtual network, host bridge, direct macvtap connection to physical interface, qemu usermode, user-defined via an external script), but currently has the problem that unnecessary details of the host config are embedded into the guest's config; if the guest is migrated to a different host, and that host has a different hardware or network config (or possibly the same hardware, but that hardware is currently in use by a different guest), the migration will fail. I am proposing a change to libvirt's network XML that will allow us to (optionally - old configs will remain valid) remove the host details from the guest's domain XML (which can move around from host to host) and place them in the network XML (which remains with the host); the domain XML will then use existing config elements to associate each guest interface with a "network". The motivating use case for this change is the "direct" connection type (which uses macvtap for vepa and vnlink connections directly between a guest and a physical interface, rather than through a bridge), but it is applicable for all types of connection. (Another hopeful side effect of this change will be to make libvirt's network connection model easier to realize on non-Linux hypervisors (eg, VMWare ESX), so Mathias - please chime in!) Background -------------------- libvirt currently has 3 major types of guest interface connection (there are also "type='user'" and "type='ethernet'", but they probably wouldn't be used in a multi-host environment, so I'm not considering them here): 1) type='network' The guest's network interface is connected to a libvirt-created "virtual network", which is in reality (in the case of KVM or Xen) a Linux bridge device that isn't connected to any physical host interface - any connection to the outside goes through the host's IP routing stack. The network to use is indicated in the element of the guest's interface xml: . Because the name 'mynetwork' is controlled by libvirt, it's perfectly reasonable to assume that the same network name could be available on another host that is accepting a migrated guest. 2) type='bridge' The guest's network interface is connected to a bridge device (eg "br0") that has already been configured in the host's network config files (eg, in /etc/sysconfig/network-scripts). This bridge is itself connected to the outside via a physical host interface, eg "eth0", *NOT* through the hosts IP routing stack. The bridge to use is indicated in the source with . Although the naming of the bridge is outside the scope of libvirt, it is at least possible to setup all hosts to have the same bridge name (so that a guest could be migrated from one host to another). 3) type='direct' The guest's network interface is connected directly to a physical interface (eg "eth0") with macvtap, or sometimes to a virtual function ("VF") of a physical interface (which is also really just another interface, from the software point of view). The interface to use is indicated with In this case, the interface name is determined by the host OS and cannot be arbitrarily changed. Also a host will have multiple interfaces / VFs available to guests, and in some modes may allow only a single guest to connect to a given interface (implying that the interface used by a guest when on one host will probably not be available when migrating to another). So in order to have flexible migration from one host to another, an abstraction to allow the guest XML to use the same name on all hosts must be introduced. Three possible methods for providing this abstraction come to mind: Option 1 ----------- (Be forewarned that Option 1 & 2 are shown here mainly to illustrate my thought process while arriving at my preferred Option - 3 :-) In a manner similar to the way the vnet%d tap devices are created, name the interface with an embedded variable (eg "eth%d") (plus attributes for min and max %d) and let the underlying code in libvirt search for/reserve an appropriate device> This is the simplest to code/configure, but does not allow a) more complex names (eg, interface names as determined by biosdevname can be of the form "pci%dp%d_%d"), b) multiple ranges, c) oversubscribing of interfaces (it is possible, although sub-optimal, to connect multiple guest interfaces to a single host interface with macvtap). VERDICT: looks ugly, not flexible enough. Option 2 ----------- create a new class of libvirt XML config to describe a pool of network interfaces, and reference this pool in the guest interface element: ... The problem with this is that it requires a new API for defining/undefining/etc management of "interface pools". Also, it wouldn't allow (for example) one host to use a pool of macvtap addresses to connect guests, and another host to use a host bridge for the same connection (obviously, such a non-uniform setup wouldn't be desirable in a large host farm, but may be encountered in some smaller setup) VERDICT: creates more API clutter (ie extra work *and* confusion for users). Is "flexible enough" for current motivation, but unnecessarily limiting, eg doesn't help the model to be more easily adapted to VMWare etc. Option 3 ----------- Up to now we've only discussed the need for separating the host-specific config ( element) in the case of type='direct' interfaces (well, in reality I've gone back and edited this document so many times that is no longer true, but play along with me! :-). But it really is a problem for all interface types - all of the information currently in the guest's interface element really is tied to the host, and shouldn't be defined in detail in the guest XML; it should instead be defined once for each host, and only referenced by some name in the guest XML; that way as a guest moves from host to host, it will automatically adjust its connection to match the new environmant. As a more general solution, instead of having the special new "interfacePool" object in the config, what if the XML for "network was expanded to mean "any type of guest network connection" (with a new "type='xxx'" attribute at the toplevel to indicate which type), not just "a private bridge optionally connected to the real world via routing/NAT"? If this was the case, the guest interface XML could always be, eg: ... and depending on the network config of the host the guest was migrated to, this could be either a direct (macvtap) connection via an interface allocated from a pool (the pool being defined in the definition of 'red-network'), a bridge (again, pointed to by the definition of 'red-network', or a virtual network (using the current network definition syntax). This way the same guest could be migrated not only between macvtap-enabled hosts, but from there to a host using a bridge, or maybe a host in a remote location that used a virtual network with a secure tunnel to connect back to the rest of the red-network. (Part of the migration process would of course check that the destination host had a network of the proper name, and fail if it didn't; management software at a level above libvirt would probably filter a list of candidate migration destinations based on available networks, and only attempt migration to one that had the matching network available). Examples of 'red-network' for different types of connections (all of these would work with the interface XML given above): red-network ... red-network red-network I know there may be some resistance to this expansion of the usage of , but I think it does fit in with the current usage properly, and is preferable to adding an entire new class of API just to define a pool of interfaces. Open questions: 1) What should the element inside network/source look like. Making each interface in the pool a separate element, with possible attributed, would be the simplest to code, but would get tedious on a system with, for example, an ethernet card with 64 VFs. On the other hand, just parameterizing a string (eth%d) is inadequate, eg, when there are multiple non-contiguous ranges. 2) do we need a "max connections" for each interface in a pool of macvtap interfaces? Or should we just overload them in a round-robin fashion unless mode='passthru' (a new mode which requires only one guest per interface). 3) What about the parameters in the element that are currently used by vepa/vnlink. Do those belong with the host, or with the guest? 4) Are there other types that we want? Perhaps the recent proposal for IPSec / secure tunnels could be incorporated as a new network type (or maybe it could just be the standard "virtual" type, with a tunnel as the forward device). From jdenemar at redhat.com Tue Apr 12 16:54:33 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 12 Apr 2011 18:54:33 +0200 Subject: [libvirt] [PATCH] util: Simplify hash implementation Message-ID: So far first entries for each hash key are stored directly in the hash table while other entries mapped to the same key are linked through pointers. As a result of that, the code is cluttered with special handling for the first items. Commit 9677cd33eea4c65d78ba463b46b8b45ed2da1709 made it possible to remove current entry when iterating through all hash entries. However, it didn't add the special first item handling which could cause libvirtd crash or hang. Instead of adding more clutter, this patch fixes the crash by linking all entries (even the first ones) through pointers which significantly simplifies the code and makes it more maintainable. --- src/util/hash.c | 290 ++++++++++++++++++------------------------------------- 1 files changed, 94 insertions(+), 196 deletions(-) diff --git a/src/util/hash.c b/src/util/hash.c index 48a94ad..dbb34ec 100644 --- a/src/util/hash.c +++ b/src/util/hash.c @@ -50,14 +50,13 @@ struct _virHashEntry { struct _virHashEntry *next; void *name; void *payload; - int valid; }; /* * The entire hash table */ struct _virHashTable { - struct _virHashEntry *table; + virHashEntryPtr *table; int size; int nbElems; /* True iff we are iterating over hash entries. */ @@ -165,7 +164,7 @@ virHashTablePtr virHashCreateFull(int size, * * Create a new virHashTablePtr. * - * Returns the newly created object, or NULL if an error occured. + * Returns the newly created object, or NULL if an error occurred. */ virHashTablePtr virHashCreate(int size, virHashDataFree dataFree) { @@ -189,10 +188,8 @@ virHashTablePtr virHashCreate(int size, virHashDataFree dataFree) static int virHashGrow(virHashTablePtr table, int size) { - unsigned long key; int oldsize, i; - virHashEntryPtr iter, next; - struct _virHashEntry *oldtable; + virHashEntryPtr *oldtable; #ifdef DEBUG_GROW unsigned long nbElem = 0; @@ -217,43 +214,18 @@ virHashGrow(virHashTablePtr table, int size) } table->size = size; - /* If the two loops are merged, there would be situations where - * a new entry needs to allocated and data copied into it from - * the main table. So instead, we run through the array twice, first - * copying all the elements in the main array (where we can't get - * conflicts) and then the rest, so we only free (and don't allocate) - */ - for (i = 0; i < oldsize; i++) { - if (oldtable[i].valid == 0) - continue; - key = virHashComputeKey(table, oldtable[i].name); - memcpy(&(table->table[key]), &(oldtable[i]), sizeof(virHashEntry)); - table->table[key].next = NULL; - } - for (i = 0; i < oldsize; i++) { - iter = oldtable[i].next; + virHashEntryPtr iter = oldtable[i]; while (iter) { - next = iter->next; + virHashEntryPtr next = iter->next; + unsigned long key = virHashComputeKey(table, iter->name); - /* - * put back the entry in the new table - */ - - key = virHashComputeKey(table, iter->name); - if (table->table[key].valid == 0) { - memcpy(&(table->table[key]), iter, sizeof(virHashEntry)); - table->table[key].next = NULL; - VIR_FREE(iter); - } else { - iter->next = table->table[key].next; - table->table[key].next = iter; - } + iter->next = table->table[key]; + table->table[key] = iter; #ifdef DEBUG_GROW nbElem++; #endif - iter = next; } } @@ -279,36 +251,24 @@ void virHashFree(virHashTablePtr table) { int i; - virHashEntryPtr iter; - virHashEntryPtr next; - int inside_table = 0; - int nbElems; if (table == NULL) return; - if (table->table) { - nbElems = table->nbElems; - for (i = 0; (i < table->size) && (nbElems > 0); i++) { - iter = &(table->table[i]); - if (iter->valid == 0) - continue; - inside_table = 1; - while (iter) { - next = iter->next; - if ((table->dataFree != NULL) && (iter->payload != NULL)) - table->dataFree(iter->payload, iter->name); - if (table->keyFree) - table->keyFree(iter->name); - iter->payload = NULL; - if (!inside_table) - VIR_FREE(iter); - nbElems--; - inside_table = 0; - iter = next; - } + + for (i = 0; i < table->size; i++) { + virHashEntryPtr iter = table->table[i]; + while (iter) { + virHashEntryPtr next = iter->next; + + if (table->dataFree) + table->dataFree(iter->payload, iter->name); + if (table->keyFree) + table->keyFree(iter->name); + VIR_FREE(iter); + iter = next; } - VIR_FREE(table->table); } + VIR_FREE(table); } @@ -319,9 +279,7 @@ virHashAddOrUpdateEntry(virHashTablePtr table, const void *name, { unsigned long key, len = 0; virHashEntryPtr entry; - virHashEntryPtr insert; char *new_name; - bool found; if ((table == NULL) || (name == NULL)) return (-1); @@ -329,67 +287,40 @@ virHashAddOrUpdateEntry(virHashTablePtr table, const void *name, if (table->iterating) virHashIterationError(-1); - /* - * Check for duplicate and insertion location. - */ - found = false; key = virHashComputeKey(table, name); - if (table->table[key].valid == 0) { - insert = NULL; - } else { - for (insert = &(table->table[key]); insert->next != NULL; - insert = insert->next) { - if (table->keyEqual(insert->name, name)) { - found = true; - break; - } - len++; - } - if (table->keyEqual(insert->name, name)) - found = true; - } - - if (found) { - if (is_update) { - if (table->dataFree) - table->dataFree(insert->payload, insert->name); - insert->payload = userdata; - return (0); - } else { - return (-1); - } - } - if (insert == NULL) { - entry = &(table->table[key]); - } else { - if (VIR_ALLOC(entry) < 0) { - virReportOOMError(); - return (-1); + /* Check for duplicate entry */ + for (entry = table->table[key]; entry; entry = entry->next) { + if (table->keyEqual(entry->name, name)) { + if (is_update) { + if (table->dataFree) + table->dataFree(entry->payload, entry->name); + entry->payload = userdata; + return 0; + } else { + return -1; + } } + len++; } - new_name = table->keyCopy(name); - if (new_name == NULL) { + if (VIR_ALLOC(entry) < 0 || !(new_name = table->keyCopy(name))) { virReportOOMError(); - if (insert != NULL) - VIR_FREE(entry); - return (-1); + VIR_FREE(entry); + return -1; } + entry->name = new_name; entry->payload = userdata; - entry->next = NULL; - entry->valid = 1; - - if (insert != NULL) - insert->next = entry; + entry->next = table->table[key]; + table->table[key] = entry; table->nbElems++; if (len > MAX_HASH_LEN) virHashGrow(table, MAX_HASH_LEN * table->size); - return (0); + return 0; } /** @@ -443,18 +374,15 @@ virHashLookup(virHashTablePtr table, const void *name) unsigned long key; virHashEntryPtr entry; - if (table == NULL) - return (NULL); - if (name == NULL) - return (NULL); + if (!table || !name) + return NULL; + key = virHashComputeKey(table, name); - if (table->table[key].valid == 0) - return (NULL); - for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { + for (entry = table->table[key]; entry; entry = entry->next) { if (table->keyEqual(entry->name, name)) - return (entry->payload); + return entry->payload; } - return (NULL); + return NULL; } @@ -512,47 +440,31 @@ virHashSize(virHashTablePtr table) int virHashRemoveEntry(virHashTablePtr table, const void *name) { - unsigned long key; virHashEntryPtr entry; - virHashEntryPtr prev = NULL; + virHashEntryPtr *nextptr; if (table == NULL || name == NULL) return (-1); - key = virHashComputeKey(table, name); - if (table->table[key].valid == 0) { - return (-1); - } else { - for (entry = &(table->table[key]); entry != NULL; - entry = entry->next) { - if (table->keyEqual(entry->name, name)) { - if (table->iterating && table->current != entry) - virHashIterationError(-1); - if (table->dataFree && (entry->payload != NULL)) - table->dataFree(entry->payload, entry->name); - entry->payload = NULL; - if (table->keyFree) - table->keyFree(entry->name); - if (prev) { - prev->next = entry->next; - VIR_FREE(entry); - } else { - if (entry->next == NULL) { - entry->valid = 0; - } else { - entry = entry->next; - memcpy(&(table->table[key]), entry, - sizeof(virHashEntry)); - VIR_FREE(entry); - } - } - table->nbElems--; - return (0); - } - prev = entry; + nextptr = table->table + virHashComputeKey(table, name); + for (entry = *nextptr; entry; entry = entry->next) { + if (table->keyEqual(entry->name, name)) { + if (table->iterating && table->current != entry) + virHashIterationError(-1); + + if (table->dataFree) + table->dataFree(entry->payload, entry->name); + if (table->keyFree) + table->keyFree(entry->name); + *nextptr = entry->next; + VIR_FREE(entry); + table->nbElems--; + return 0; } - return (-1); + nextptr = &entry->next; } + + return -1; } @@ -581,15 +493,15 @@ int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data) table->iterating = true; table->current = NULL; for (i = 0 ; i < table->size ; i++) { - virHashEntryPtr entry = table->table + i; + virHashEntryPtr entry = table->table[i]; while (entry) { virHashEntryPtr next = entry->next; - if (entry->valid) { - table->current = entry; - iter(entry->payload, entry->name, data); - table->current = NULL; - count++; - } + + table->current = entry; + iter(entry->payload, entry->name, data); + table->current = NULL; + + count++; entry = next; } } @@ -612,7 +524,10 @@ int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data) * * Returns number of items removed on success, -1 on failure */ -int virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, const void *data) { +int virHashRemoveSet(virHashTablePtr table, + virHashSearcher iter, + const void *data) +{ int i, count = 0; if (table == NULL || iter == NULL) @@ -624,44 +539,27 @@ int virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, const void *da table->iterating = true; table->current = NULL; for (i = 0 ; i < table->size ; i++) { - virHashEntryPtr prev = NULL; - virHashEntryPtr entry = &(table->table[i]); + virHashEntryPtr *nextptr = table->table + i; - while (entry && entry->valid) { - if (iter(entry->payload, entry->name, data)) { + while (*nextptr) { + virHashEntryPtr entry = *nextptr; + if (!iter(entry->payload, entry->name, data)) { + *nextptr = entry->next; + } else { count++; if (table->dataFree) table->dataFree(entry->payload, entry->name); if (table->keyFree) table->keyFree(entry->name); + *nextptr = entry->next; + VIR_FREE(entry); table->nbElems--; - if (prev) { - prev->next = entry->next; - VIR_FREE(entry); - entry = prev; - } else { - if (entry->next == NULL) { - entry->valid = 0; - entry->name = NULL; - } else { - entry = entry->next; - memcpy(&(table->table[i]), entry, - sizeof(virHashEntry)); - VIR_FREE(entry); - entry = &(table->table[i]); - continue; - } - } - } - prev = entry; - if (entry) { - entry = entry->next; } } } table->iterating = false; - return (count); + return count; } /** @@ -675,7 +573,10 @@ int virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, const void *da * returns non-zero will be returned by this function. * The elements are processed in a undefined order */ -void *virHashSearch(virHashTablePtr table, virHashSearcher iter, const void *data) { +void *virHashSearch(virHashTablePtr table, + virHashSearcher iter, + const void *data) +{ int i; if (table == NULL || iter == NULL) @@ -687,18 +588,15 @@ void *virHashSearch(virHashTablePtr table, virHashSearcher iter, const void *dat table->iterating = true; table->current = NULL; for (i = 0 ; i < table->size ; i++) { - virHashEntryPtr entry = table->table + i; - while (entry) { - if (entry->valid) { - if (iter(entry->payload, entry->name, data)) { - table->iterating = false; - return entry->payload; - } + virHashEntryPtr entry; + for (entry = table->table[i]; entry; entry = entry->next) { + if (iter(entry->payload, entry->name, data)) { + table->iterating = false; + return entry->payload; } - entry = entry->next; } } table->iterating = false; - return (NULL); + return NULL; } -- 1.7.5.rc1 From jdenemar at redhat.com Tue Apr 12 16:54:53 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 12 Apr 2011 18:54:53 +0200 Subject: [libvirt] [PATCH] util: Fix crash when removing entries during hash iteration In-Reply-To: References: Message-ID: Commit 9677cd33eea4c65d78ba463b46b8b45ed2da1709 made it possible to remove current entry when iterating through all hash entries. However, it didn't properly handle a special case of removing first entry assigned to a given key which contains several entries in its collision list. --- This is an alternate less invasive fix to "util: Simplify hash implementation". I prefer the more invasive fix for upstream but I'm sending this alternative here for completeness. src/util/hash.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/src/util/hash.c b/src/util/hash.c index 48a94ad..fc7652d 100644 --- a/src/util/hash.c +++ b/src/util/hash.c @@ -585,10 +585,18 @@ int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data) while (entry) { virHashEntryPtr next = entry->next; if (entry->valid) { + void *name = (entry == table->table + i) ? entry->name : NULL; + table->current = entry; iter(entry->payload, entry->name, data); table->current = NULL; count++; + + /* revisit current entry if it was the first one in collision + * list and its content changed, i.e. it was deleted by iter() + */ + if (name && name != entry->name) + continue; } entry = next; } -- 1.7.5.rc1 From eblake at redhat.com Tue Apr 12 17:06:17 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 12 Apr 2011 11:06:17 -0600 Subject: [libvirt] [PATCH] util: Fix crash when removing entries during hash iteration In-Reply-To: References: Message-ID: <4DA48689.9080702@redhat.com> On 04/12/2011 10:54 AM, Jiri Denemark wrote: > Commit 9677cd33eea4c65d78ba463b46b8b45ed2da1709 made it possible to > remove current entry when iterating through all hash entries. However, > it didn't properly handle a special case of removing first entry > assigned to a given key which contains several entries in its collision > list. > --- > This is an alternate less invasive fix to "util: Simplify hash implementation". > I prefer the more invasive fix for upstream but I'm sending this alternative > here for completeness. For backporting purposes, would it make sense to apply this patch first, then apply the other one which undoes this patch as part of its simplifications? Then, anyone trying to pick and choose patches to backport can feel justified going with the smaller patch in isolation. As for this patch itself, ACK, but whether to apply it depends on the answer to the bigger question above. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From jdenemar at redhat.com Tue Apr 12 17:24:16 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 12 Apr 2011 19:24:16 +0200 Subject: [libvirt] [PATCH] util: Fix crash when removing entries during hash iteration In-Reply-To: <4DA48689.9080702@redhat.com> References: <4DA48689.9080702@redhat.com> Message-ID: <20110412172416.GM7195@orkuz.home> On Tue, Apr 12, 2011 at 11:06:17 -0600, Eric Blake wrote: > On 04/12/2011 10:54 AM, Jiri Denemark wrote: > > Commit 9677cd33eea4c65d78ba463b46b8b45ed2da1709 made it possible to > > remove current entry when iterating through all hash entries. However, > > it didn't properly handle a special case of removing first entry > > assigned to a given key which contains several entries in its collision > > list. > > --- > > This is an alternate less invasive fix to "util: Simplify hash implementation". > > I prefer the more invasive fix for upstream but I'm sending this alternative > > here for completeness. > > For backporting purposes, would it make sense to apply this patch first, > then apply the other one which undoes this patch as part of its > simplifications? Then, anyone trying to pick and choose patches to > backport can feel justified going with the smaller patch in isolation. That sounds like a good idea. I'll send a v2 for the simplification patch soon. > As for this patch itself, ACK, but whether to apply it depends on the > answer to the bigger question above. Thanks and I pushed it. Jirka From jdenemar at redhat.com Tue Apr 12 17:25:31 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 12 Apr 2011 19:25:31 +0200 Subject: [libvirt] [PATCH v2] util: Simplify hash implementation Message-ID: <0ebc29ed7078c909b92f692d28c572f0c05ff9b9.1302629114.git.jdenemar@redhat.com> So far first entries for each hash key are stored directly in the hash table while other entries mapped to the same key are linked through pointers. As a result of that, the code is cluttered with special handling for the first items. This patch makes all entries (even the first ones) linked through pointers, which significantly simplifies the code and makes it more maintainable. --- src/util/hash.c | 294 +++++++++++++++++-------------------------------------- 1 files changed, 92 insertions(+), 202 deletions(-) diff --git a/src/util/hash.c b/src/util/hash.c index fc7652d..dbb34ec 100644 --- a/src/util/hash.c +++ b/src/util/hash.c @@ -50,14 +50,13 @@ struct _virHashEntry { struct _virHashEntry *next; void *name; void *payload; - int valid; }; /* * The entire hash table */ struct _virHashTable { - struct _virHashEntry *table; + virHashEntryPtr *table; int size; int nbElems; /* True iff we are iterating over hash entries. */ @@ -165,7 +164,7 @@ virHashTablePtr virHashCreateFull(int size, * * Create a new virHashTablePtr. * - * Returns the newly created object, or NULL if an error occured. + * Returns the newly created object, or NULL if an error occurred. */ virHashTablePtr virHashCreate(int size, virHashDataFree dataFree) { @@ -189,10 +188,8 @@ virHashTablePtr virHashCreate(int size, virHashDataFree dataFree) static int virHashGrow(virHashTablePtr table, int size) { - unsigned long key; int oldsize, i; - virHashEntryPtr iter, next; - struct _virHashEntry *oldtable; + virHashEntryPtr *oldtable; #ifdef DEBUG_GROW unsigned long nbElem = 0; @@ -217,43 +214,18 @@ virHashGrow(virHashTablePtr table, int size) } table->size = size; - /* If the two loops are merged, there would be situations where - * a new entry needs to allocated and data copied into it from - * the main table. So instead, we run through the array twice, first - * copying all the elements in the main array (where we can't get - * conflicts) and then the rest, so we only free (and don't allocate) - */ - for (i = 0; i < oldsize; i++) { - if (oldtable[i].valid == 0) - continue; - key = virHashComputeKey(table, oldtable[i].name); - memcpy(&(table->table[key]), &(oldtable[i]), sizeof(virHashEntry)); - table->table[key].next = NULL; - } - for (i = 0; i < oldsize; i++) { - iter = oldtable[i].next; + virHashEntryPtr iter = oldtable[i]; while (iter) { - next = iter->next; - - /* - * put back the entry in the new table - */ + virHashEntryPtr next = iter->next; + unsigned long key = virHashComputeKey(table, iter->name); - key = virHashComputeKey(table, iter->name); - if (table->table[key].valid == 0) { - memcpy(&(table->table[key]), iter, sizeof(virHashEntry)); - table->table[key].next = NULL; - VIR_FREE(iter); - } else { - iter->next = table->table[key].next; - table->table[key].next = iter; - } + iter->next = table->table[key]; + table->table[key] = iter; #ifdef DEBUG_GROW nbElem++; #endif - iter = next; } } @@ -279,36 +251,24 @@ void virHashFree(virHashTablePtr table) { int i; - virHashEntryPtr iter; - virHashEntryPtr next; - int inside_table = 0; - int nbElems; if (table == NULL) return; - if (table->table) { - nbElems = table->nbElems; - for (i = 0; (i < table->size) && (nbElems > 0); i++) { - iter = &(table->table[i]); - if (iter->valid == 0) - continue; - inside_table = 1; - while (iter) { - next = iter->next; - if ((table->dataFree != NULL) && (iter->payload != NULL)) - table->dataFree(iter->payload, iter->name); - if (table->keyFree) - table->keyFree(iter->name); - iter->payload = NULL; - if (!inside_table) - VIR_FREE(iter); - nbElems--; - inside_table = 0; - iter = next; - } + + for (i = 0; i < table->size; i++) { + virHashEntryPtr iter = table->table[i]; + while (iter) { + virHashEntryPtr next = iter->next; + + if (table->dataFree) + table->dataFree(iter->payload, iter->name); + if (table->keyFree) + table->keyFree(iter->name); + VIR_FREE(iter); + iter = next; } - VIR_FREE(table->table); } + VIR_FREE(table); } @@ -319,9 +279,7 @@ virHashAddOrUpdateEntry(virHashTablePtr table, const void *name, { unsigned long key, len = 0; virHashEntryPtr entry; - virHashEntryPtr insert; char *new_name; - bool found; if ((table == NULL) || (name == NULL)) return (-1); @@ -329,67 +287,40 @@ virHashAddOrUpdateEntry(virHashTablePtr table, const void *name, if (table->iterating) virHashIterationError(-1); - /* - * Check for duplicate and insertion location. - */ - found = false; key = virHashComputeKey(table, name); - if (table->table[key].valid == 0) { - insert = NULL; - } else { - for (insert = &(table->table[key]); insert->next != NULL; - insert = insert->next) { - if (table->keyEqual(insert->name, name)) { - found = true; - break; - } - len++; - } - if (table->keyEqual(insert->name, name)) - found = true; - } - - if (found) { - if (is_update) { - if (table->dataFree) - table->dataFree(insert->payload, insert->name); - insert->payload = userdata; - return (0); - } else { - return (-1); - } - } - if (insert == NULL) { - entry = &(table->table[key]); - } else { - if (VIR_ALLOC(entry) < 0) { - virReportOOMError(); - return (-1); + /* Check for duplicate entry */ + for (entry = table->table[key]; entry; entry = entry->next) { + if (table->keyEqual(entry->name, name)) { + if (is_update) { + if (table->dataFree) + table->dataFree(entry->payload, entry->name); + entry->payload = userdata; + return 0; + } else { + return -1; + } } + len++; } - new_name = table->keyCopy(name); - if (new_name == NULL) { + if (VIR_ALLOC(entry) < 0 || !(new_name = table->keyCopy(name))) { virReportOOMError(); - if (insert != NULL) - VIR_FREE(entry); - return (-1); + VIR_FREE(entry); + return -1; } + entry->name = new_name; entry->payload = userdata; - entry->next = NULL; - entry->valid = 1; - - if (insert != NULL) - insert->next = entry; + entry->next = table->table[key]; + table->table[key] = entry; table->nbElems++; if (len > MAX_HASH_LEN) virHashGrow(table, MAX_HASH_LEN * table->size); - return (0); + return 0; } /** @@ -443,18 +374,15 @@ virHashLookup(virHashTablePtr table, const void *name) unsigned long key; virHashEntryPtr entry; - if (table == NULL) - return (NULL); - if (name == NULL) - return (NULL); + if (!table || !name) + return NULL; + key = virHashComputeKey(table, name); - if (table->table[key].valid == 0) - return (NULL); - for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { + for (entry = table->table[key]; entry; entry = entry->next) { if (table->keyEqual(entry->name, name)) - return (entry->payload); + return entry->payload; } - return (NULL); + return NULL; } @@ -512,47 +440,31 @@ virHashSize(virHashTablePtr table) int virHashRemoveEntry(virHashTablePtr table, const void *name) { - unsigned long key; virHashEntryPtr entry; - virHashEntryPtr prev = NULL; + virHashEntryPtr *nextptr; if (table == NULL || name == NULL) return (-1); - key = virHashComputeKey(table, name); - if (table->table[key].valid == 0) { - return (-1); - } else { - for (entry = &(table->table[key]); entry != NULL; - entry = entry->next) { - if (table->keyEqual(entry->name, name)) { - if (table->iterating && table->current != entry) - virHashIterationError(-1); - if (table->dataFree && (entry->payload != NULL)) - table->dataFree(entry->payload, entry->name); - entry->payload = NULL; - if (table->keyFree) - table->keyFree(entry->name); - if (prev) { - prev->next = entry->next; - VIR_FREE(entry); - } else { - if (entry->next == NULL) { - entry->valid = 0; - } else { - entry = entry->next; - memcpy(&(table->table[key]), entry, - sizeof(virHashEntry)); - VIR_FREE(entry); - } - } - table->nbElems--; - return (0); - } - prev = entry; + nextptr = table->table + virHashComputeKey(table, name); + for (entry = *nextptr; entry; entry = entry->next) { + if (table->keyEqual(entry->name, name)) { + if (table->iterating && table->current != entry) + virHashIterationError(-1); + + if (table->dataFree) + table->dataFree(entry->payload, entry->name); + if (table->keyFree) + table->keyFree(entry->name); + *nextptr = entry->next; + VIR_FREE(entry); + table->nbElems--; + return 0; } - return (-1); + nextptr = &entry->next; } + + return -1; } @@ -581,23 +493,15 @@ int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data) table->iterating = true; table->current = NULL; for (i = 0 ; i < table->size ; i++) { - virHashEntryPtr entry = table->table + i; + virHashEntryPtr entry = table->table[i]; while (entry) { virHashEntryPtr next = entry->next; - if (entry->valid) { - void *name = (entry == table->table + i) ? entry->name : NULL; - table->current = entry; - iter(entry->payload, entry->name, data); - table->current = NULL; - count++; + table->current = entry; + iter(entry->payload, entry->name, data); + table->current = NULL; - /* revisit current entry if it was the first one in collision - * list and its content changed, i.e. it was deleted by iter() - */ - if (name && name != entry->name) - continue; - } + count++; entry = next; } } @@ -620,7 +524,10 @@ int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data) * * Returns number of items removed on success, -1 on failure */ -int virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, const void *data) { +int virHashRemoveSet(virHashTablePtr table, + virHashSearcher iter, + const void *data) +{ int i, count = 0; if (table == NULL || iter == NULL) @@ -632,44 +539,27 @@ int virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, const void *da table->iterating = true; table->current = NULL; for (i = 0 ; i < table->size ; i++) { - virHashEntryPtr prev = NULL; - virHashEntryPtr entry = &(table->table[i]); + virHashEntryPtr *nextptr = table->table + i; - while (entry && entry->valid) { - if (iter(entry->payload, entry->name, data)) { + while (*nextptr) { + virHashEntryPtr entry = *nextptr; + if (!iter(entry->payload, entry->name, data)) { + *nextptr = entry->next; + } else { count++; if (table->dataFree) table->dataFree(entry->payload, entry->name); if (table->keyFree) table->keyFree(entry->name); + *nextptr = entry->next; + VIR_FREE(entry); table->nbElems--; - if (prev) { - prev->next = entry->next; - VIR_FREE(entry); - entry = prev; - } else { - if (entry->next == NULL) { - entry->valid = 0; - entry->name = NULL; - } else { - entry = entry->next; - memcpy(&(table->table[i]), entry, - sizeof(virHashEntry)); - VIR_FREE(entry); - entry = &(table->table[i]); - continue; - } - } - } - prev = entry; - if (entry) { - entry = entry->next; } } } table->iterating = false; - return (count); + return count; } /** @@ -683,7 +573,10 @@ int virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, const void *da * returns non-zero will be returned by this function. * The elements are processed in a undefined order */ -void *virHashSearch(virHashTablePtr table, virHashSearcher iter, const void *data) { +void *virHashSearch(virHashTablePtr table, + virHashSearcher iter, + const void *data) +{ int i; if (table == NULL || iter == NULL) @@ -695,18 +588,15 @@ void *virHashSearch(virHashTablePtr table, virHashSearcher iter, const void *dat table->iterating = true; table->current = NULL; for (i = 0 ; i < table->size ; i++) { - virHashEntryPtr entry = table->table + i; - while (entry) { - if (entry->valid) { - if (iter(entry->payload, entry->name, data)) { - table->iterating = false; - return entry->payload; - } + virHashEntryPtr entry; + for (entry = table->table[i]; entry; entry = entry->next) { + if (iter(entry->payload, entry->name, data)) { + table->iterating = false; + return entry->payload; } - entry = entry->next; } } table->iterating = false; - return (NULL); + return NULL; } -- 1.7.5.rc1 From eblake at redhat.com Tue Apr 12 19:10:15 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 12 Apr 2011 13:10:15 -0600 Subject: [libvirt] [PATCH v2] util: Simplify hash implementation In-Reply-To: <0ebc29ed7078c909b92f692d28c572f0c05ff9b9.1302629114.git.jdenemar@redhat.com> References: <0ebc29ed7078c909b92f692d28c572f0c05ff9b9.1302629114.git.jdenemar@redhat.com> Message-ID: <4DA4A397.9080002@redhat.com> On 04/12/2011 11:25 AM, Jiri Denemark wrote: > So far first entries for each hash key are stored directly in the hash > table while other entries mapped to the same key are linked through > pointers. As a result of that, the code is cluttered with special > handling for the first items. > > This patch makes all entries (even the first ones) linked through > pointers, which significantly simplifies the code and makes it more > maintainable. > --- > src/util/hash.c | 294 +++++++++++++++++-------------------------------------- > 1 files changed, 92 insertions(+), 202 deletions(-) The diffstat proves the maintainability aspect, even if the code is (slightly) less efficient now by doing more malloc calls. Gnulib has some hash modules, which might further offload some of our maintenance burden, except that they are GPL rather than LGPLv2+, so I doubt we'll ever be able to use them. > > diff --git a/src/util/hash.c b/src/util/hash.c > index fc7652d..dbb34ec 100644 > --- a/src/util/hash.c > +++ b/src/util/hash.c > @@ -50,14 +50,13 @@ struct _virHashEntry { > struct _virHashEntry *next; > void *name; > void *payload; > - int valid; > }; > > /* > * The entire hash table > */ > struct _virHashTable { > - struct _virHashEntry *table; > + virHashEntryPtr *table; Makes sense - an array of pointers, rather than an array of first entries with pointers to the rest of the chain. > @@ -217,43 +214,18 @@ virHashGrow(virHashTablePtr table, int size) > } > table->size = size; > > - /* If the two loops are merged, there would be situations where > - * a new entry needs to allocated and data copied into it from > - * the main table. So instead, we run through the array twice, first > - * copying all the elements in the main array (where we can't get > - * conflicts) and then the rest, so we only free (and don't allocate) Oh my. That statement is only true if growth is always by a power-of-two multiple (which happened to be the case, but could easily be broken had we changed MAX_HASH_LEN to something other than 8). Another good reason for this patch. ACK - all the changes look correct, and certainly simpler. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Tue Apr 12 21:30:27 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 12 Apr 2011 15:30:27 -0600 Subject: [libvirt] [PATCH] virsh: Fix a problem of argv parsing In-Reply-To: <1302007127-16185-1-git-send-email-jyang@redhat.com> References: <1302007127-16185-1-git-send-email-jyang@redhat.com> Message-ID: <4DA4C473.9000908@redhat.com> On 04/05/2011 06:38 AM, Osier Yang wrote: > Problem example: > # virsh -d 5 vol-create --pool default col.xml > vol-create: pool(optdata): default > vol-create: pool(optdata): col.xml > error: command 'vol-create' requires option > > It gets same "vshCmdOptDef" for both "--pool default" > and "col.xml". > > This patch fixes it by increase "data_ct" when things like > "--pool default" is successfully parsed, so that could > get right "vshCmdOptDef" for the other arguments which > are not with option name together. > --- > tools/virsh.c | 2 ++ > 1 files changed, 2 insertions(+), 0 deletions(-) NAK to this patch. It still doesn't detect other issues with argument parsing, such as 'virsh vol-create --pool default --pool other col.xml'. Typically, option parsing should favor the last instance of a given option, rather than the first, or error out that the option is given too many times, but your patch doesn't change the status quo of going with the first instance of the option. Instead, I've prepared a better patch that not only fixes this issue, but also addresses a regression I introduced in 0.8.5, where 'virsh freecell 0' no longer parses correctly. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Tue Apr 12 21:35:05 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 12 Apr 2011 15:35:05 -0600 Subject: [libvirt] [PATCH 0/2] virsh: improve option parsing, including a regression fix In-Reply-To: <4DA4C473.9000908@redhat.com> References: <4DA4C473.9000908@redhat.com> Message-ID: <1302644107-22840-1-git-send-email-eblake@redhat.com> I wish I could have come up with something with fewer lines of code changed; but I'm at least happy that the end result only touched vshCommandParse and its helper functions rather than having to touch lots of existing commands. This fixes multiple bugs: a regression in 'virsh freecell 0' parsing, as well as an infelicity in 'virsh vol-create --pool default vol.xml' handling. It also makes it so that 'virsh vol-info vol-name pool-name' works without having to specify an explicit --pool argument. Eric Blake (2): virsh: list required options first virsh: fix regression in parsing optional integer tools/virsh.c | 169 ++++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 114 insertions(+), 55 deletions(-) From eblake at redhat.com Tue Apr 12 21:35:06 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 12 Apr 2011 15:35:06 -0600 Subject: [libvirt] [PATCH 1/2] virsh: list required options first In-Reply-To: <4DA4C473.9000908@redhat.com> References: <4DA4C473.9000908@redhat.com> Message-ID: <1302644107-22840-2-git-send-email-eblake@redhat.com> The current state of virsh parsing is that: all lookup the volume by path (technically, the last two also attempt a name lookup within a pool, whereas the first skips that step, but the end result is the same); meanwhile: complains about unexpected data. Why? Because the --pool option is optional, so default was parsed as the --vol argument, and /path/to/image.img doesn't match up with any remaining options that require an argument. Therefore, the only way to specify pool is with an explicit "--pool" argument (you can't specify it positionally). However, named arguments can appear in any order, so: have also always worked. Therefore, this patch has no functional change on vol-info option parsing, but only on 'virsh help vol-info' synopsis layout. However, it also allows the next patch to 1) enforce that required options are always first (without this patch, the next patch would fail the testsuite), and 2) allow the user to omit the "--pool" argument. That is, the next patch makes it possible to do: instead of the longer * tools/virsh.c (opts_vol_create_from, opts_vol_clone) (opts_vol_upload, opts_vol_download, opts_vol_delete) (opts_vol_wipe, opts_vol_info, opts_vol_dumpxml, opts_vol_key) (opts_vol_path): List optional pool parameter after required arguments. --- tools/virsh.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 2e35021..cd1d246 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -6963,8 +6963,8 @@ static const vshCmdInfo info_vol_create_from[] = { static const vshCmdOptDef opts_vol_create_from[] = { {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name")}, {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML vol description")}, - {"inputpool", VSH_OT_STRING, 0, N_("pool name or uuid of the input volume's pool")}, {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("input vol name or key")}, + {"inputpool", VSH_OT_STRING, 0, N_("pool name or uuid of the input volume's pool")}, {NULL, 0, 0, NULL} }; @@ -7059,9 +7059,9 @@ static const vshCmdInfo info_vol_clone[] = { }; static const vshCmdOptDef opts_vol_clone[] = { - {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("orig vol name or key")}, {"newname", VSH_OT_DATA, VSH_OFLAG_REQ, N_("clone name")}, + {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {NULL, 0, 0, NULL} }; @@ -7136,9 +7136,9 @@ static const vshCmdInfo info_vol_upload[] = { }; static const vshCmdOptDef opts_vol_upload[] = { - {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")}, {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file")}, + {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {"offset", VSH_OT_INT, 0, N_("volume offset to upload to") }, {"length", VSH_OT_INT, 0, N_("amount of data to upload") }, {NULL, 0, 0, NULL} @@ -7236,9 +7236,9 @@ static const vshCmdInfo info_vol_download[] = { }; static const vshCmdOptDef opts_vol_download[] = { - {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")}, {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file")}, + {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {"offset", VSH_OT_INT, 0, N_("volume offset to download from") }, {"length", VSH_OT_INT, 0, N_("amount of data to download") }, {NULL, 0, 0, NULL} @@ -7342,8 +7342,8 @@ static const vshCmdInfo info_vol_delete[] = { }; static const vshCmdOptDef opts_vol_delete[] = { - {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")}, + {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {NULL, 0, 0, NULL} }; @@ -7383,8 +7383,8 @@ static const vshCmdInfo info_vol_wipe[] = { }; static const vshCmdOptDef opts_vol_wipe[] = { - {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")}, + {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {NULL, 0, 0, NULL} }; @@ -7424,8 +7424,8 @@ static const vshCmdInfo info_vol_info[] = { }; static const vshCmdOptDef opts_vol_info[] = { - {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")}, + {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {NULL, 0, 0, NULL} }; @@ -7475,8 +7475,8 @@ static const vshCmdInfo info_vol_dumpxml[] = { }; static const vshCmdOptDef opts_vol_dumpxml[] = { - {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")}, + {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {NULL, 0, 0, NULL} }; @@ -7888,8 +7888,8 @@ static const vshCmdInfo info_vol_key[] = { }; static const vshCmdOptDef opts_vol_key[] = { - {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("volume name or path")}, + {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {NULL, 0, 0, NULL} }; @@ -7921,8 +7921,8 @@ static const vshCmdInfo info_vol_path[] = { }; static const vshCmdOptDef opts_vol_path[] = { - {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("volume name or key")}, + {"pool", VSH_OT_STRING, 0, N_("pool name or uuid")}, {NULL, 0, 0, NULL} }; -- 1.7.1 From eblake at redhat.com Tue Apr 12 21:35:07 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 12 Apr 2011 15:35:07 -0600 Subject: [libvirt] [PATCH 2/2] virsh: fix regression in parsing optional integer In-Reply-To: <4DA4C473.9000908@redhat.com> References: <4DA4C473.9000908@redhat.com> Message-ID: <1302644107-22840-3-git-send-email-eblake@redhat.com> Regression introduced in 0.8.5, commit c1564268. The command 'virsh freecell 0' quit working when it changed from an optional string to an optional integer. This patch introduces a slight change that specifying an option twice is now detected as an error. * tools/virsh.c (vshCmddefGetData, vshCmddefGetOption) (vshCommandCheckOpts): Alter parameters to use bitmaps. (vshCmddefOptParse): New function. (vshCommandParse): Update for better handling of positional arguments. (vshCmddefHelp): Allow unit tests to validate options. --- tools/virsh.c | 149 +++++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 104 insertions(+), 45 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index cd1d246..486442e 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -57,6 +57,7 @@ #include "configmake.h" #include "threads.h" #include "command.h" +#include "count-one-bits.h" static char *progname; @@ -10930,66 +10931,107 @@ vshCmddefGetInfo(const vshCmdDef * cmd, const char *name) return NULL; } +static int +vshCmddefOptParse(const vshCmdDef *cmd, uint32_t* opts_need_arg, + uint32_t *opts_required) +{ + int i; + bool optional = false; + + if (!cmd->opts) + return 0; + + for (i = 0; cmd->opts[i].name; i++) { + const vshCmdOptDef *opt = &cmd->opts[i]; + + if (i > 31) + return -1; /* too many options */ + if (opt->type == VSH_OT_BOOL) { + if (opt->flag & VSH_OFLAG_REQ) + return -1; /* bool options can't be mandatory */ + continue; + } + *opts_need_arg |= 1 << i; + if (opt->flag & VSH_OFLAG_REQ) { + if (optional) + return -1; /* mandatory options must be listed first */ + *opts_required |= 1 << i; + } else { + optional = true; + } + } + return 0; +} + static const vshCmdOptDef * -vshCmddefGetOption(const vshCmdDef * cmd, const char *name) +vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name, + uint32_t *opts_seen) { - const vshCmdOptDef *opt; + int i; - for (opt = cmd->opts; opt && opt->name; opt++) - if (STREQ(opt->name, name)) + for (i = 0; cmd->opts && cmd->opts[i].name; i++) { + const vshCmdOptDef *opt = &cmd->opts[i]; + + if (STREQ(opt->name, name)) { + if (*opts_seen & (1 << i)) { + vshError(ctl, _("option --%s already seen"), name); + return NULL; + } + *opts_seen |= 1 << i; return opt; + } + } + + vshError(ctl, _("command '%s' doesn't support option --%s"), + cmd->name, name); return NULL; } static const vshCmdOptDef * -vshCmddefGetData(const vshCmdDef * cmd, int data_ct) +vshCmddefGetData(const vshCmdDef *cmd, uint32_t *opts_need_arg, + uint32_t *opts_seen) { + int i; const vshCmdOptDef *opt; - for (opt = cmd->opts; opt && opt->name; opt++) { - if (opt->type >= VSH_OT_DATA || - (opt->type == VSH_OT_INT && (opt->flag & VSH_OFLAG_REQ))) { - if (data_ct == 0 || opt->type == VSH_OT_ARGV) - return opt; - else - data_ct--; - } - } - return NULL; + if (!*opts_need_arg) + return NULL; + + /* Grab least-significant set bit */ + i = count_one_bits(*opts_need_arg ^ (*opts_need_arg - 1)) - 1; + opt = &cmd->opts[i]; + if (opt->type != VSH_OT_ARGV) + *opts_need_arg &= ~(1 << i); + *opts_seen |= 1 << i; + return opt; } /* * Checks for required options */ static int -vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd) +vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd, uint32_t opts_required, + uint32_t opts_seen) { const vshCmdDef *def = cmd->def; - const vshCmdOptDef *d; - int err = 0; - - for (d = def->opts; d && d->name; d++) { - if (d->flag & VSH_OFLAG_REQ) { - vshCmdOpt *o = cmd->opts; - int ok = 0; - - while (o && ok == 0) { - if (o->def == d) - ok = 1; - o = o->next; - } - if (!ok) { - vshError(ctl, - d->type == VSH_OT_DATA ? - _("command '%s' requires <%s> option") : - _("command '%s' requires --%s option"), - def->name, d->name); - err = 1; - } + int i; + + opts_required &= ~opts_seen; + if (!opts_required) + return 0; + for (i = 0; def->opts[i].name; i++) { + if (opts_required & (1 << i)) { + const vshCmdOptDef *opt = &def->opts[i]; + + vshError(ctl, + opt->type == VSH_OT_DATA ? + _("command '%s' requires <%s> option") : + _("command '%s' requires --%s option"), + def->name, opt->name); } } - return !err; + return -1; } static const vshCmdDef * @@ -11055,6 +11097,14 @@ vshCmddefHelp(vshControl *ctl, const char *cmdname) const char *desc = _(vshCmddefGetInfo(def, "desc")); const char *help = _(vshCmddefGetInfo(def, "help")); char buf[256]; + uint32_t opts_need_arg; + uint32_t opts_required; + + if (vshCmddefOptParse(def, &opts_need_arg, &opts_required)) { + vshError(ctl, _("internal error: bad options in command: '%s'"), + def->name); + return FALSE; + } fputs(_(" NAME\n"), stdout); fprintf(stdout, " %s - %s\n", def->name, help); @@ -11731,7 +11781,9 @@ vshCommandParse(vshControl *ctl, vshCommandParser *parser) const vshCmdDef *cmd = NULL; vshCommandToken tk; bool data_only = false; - int data_ct = 0; + uint32_t opts_need_arg = 0; + uint32_t opts_required = 0; + uint32_t opts_seen = 0; first = NULL; @@ -11754,6 +11806,13 @@ vshCommandParse(vshControl *ctl, vshCommandParser *parser) vshError(ctl, _("unknown command: '%s'"), tkdata); goto syntaxError; /* ... or ignore this command only? */ } + if (vshCmddefOptParse(cmd, &opts_need_arg, + &opts_required) < 0) { + vshError(ctl, + _("internal error: bad options in command: '%s'"), + tkdata); + goto syntaxError; + } VIR_FREE(tkdata); } else if (data_only) { goto get_data; @@ -11764,10 +11823,8 @@ vshCommandParse(vshControl *ctl, vshCommandParser *parser) *optstr = '\0'; /* convert the '=' to '\0' */ optstr = vshStrdup(ctl, optstr + 1); } - if (!(opt = vshCmddefGetOption(cmd, tkdata + 2))) { - vshError(ctl, - _("command '%s' doesn't support option --%s"), - cmd->name, tkdata + 2); + if (!(opt = vshCmddefGetOption(ctl, cmd, tkdata + 2, + &opts_seen))) { VIR_FREE(optstr); goto syntaxError; } @@ -11789,6 +11846,7 @@ vshCommandParse(vshControl *ctl, vshCommandParser *parser) VSH_OT_INT ? _("number") : _("string")); goto syntaxError; } + opts_need_arg &= ~opts_seen; } else { tkdata = NULL; if (optstr) { @@ -11804,7 +11862,8 @@ vshCommandParse(vshControl *ctl, vshCommandParser *parser) continue; } else { get_data: - if (!(opt = vshCmddefGetData(cmd, data_ct++))) { + if (!(opt = vshCmddefGetData(cmd, &opts_need_arg, + &opts_seen))) { vshError(ctl, _("unexpected data '%s'"), tkdata); goto syntaxError; } @@ -11840,7 +11899,7 @@ get_data: c->def = cmd; c->next = NULL; - if (!vshCommandCheckOpts(ctl, c)) { + if (vshCommandCheckOpts(ctl, c, opts_required, opts_seen) < 0) { VIR_FREE(c); goto syntaxError; } -- 1.7.1 From eblake at redhat.com Tue Apr 12 22:01:00 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 12 Apr 2011 16:01:00 -0600 Subject: [libvirt] [PATCH 3/2] tests: test recent virsh option parsing changes In-Reply-To: <1302644107-22840-1-git-send-email-eblake@redhat.com> References: <1302644107-22840-1-git-send-email-eblake@redhat.com> Message-ID: <1302645660-26625-1-git-send-email-eblake@redhat.com> * tests/virsh-optparse: New file. * tests/Makefile.am (test_scripts): Use it. --- Hmm, I'd better take my own advice and test this stuff :) tests/Makefile.am | 1 + tests/virsh-optparse | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 0 deletions(-) create mode 100755 tests/virsh-optparse diff --git a/tests/Makefile.am b/tests/Makefile.am index 5896442..3fa708c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -140,6 +140,7 @@ test_scripts += \ undefine \ vcpupin \ virsh-all \ + virsh-optparse \ virsh-schedinfo \ virsh-synopsis endif diff --git a/tests/virsh-optparse b/tests/virsh-optparse new file mode 100755 index 0000000..5fe5097 --- /dev/null +++ b/tests/virsh-optparse @@ -0,0 +1,70 @@ +#!/bin/sh +# Ensure that virsh option parsing doesn't regress + +# Copyright (C) 2011 Red Hat, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +: ${srcdir=$(pwd)} +: ${abs_top_srcdir=$(pwd)/..} +: ${abs_top_builddir=$(pwd)/..} + +# If $abs_top_builddir/tools is not early in $PATH, put it there, +# so that we can safely invoke "virsh" simply with its name. +case $PATH in + $abs_top_builddir/tools/src:$abs_top_builddir/tools:*) ;; + $abs_top_builddir/tools:*) ;; + *) PATH=$abs_top_builddir/tools:$PATH; export PATH ;; +esac + +if test "$VERBOSE" = yes; then + set -x + virsh --version +fi + +. "$srcdir/test-lib.sh" + +cat <<\EOF > exp-out || framework_failure + +setvcpus: trying as domain NAME +setvcpus: count(optdata): 2 +setvcpus: domain(optdata): test +setvcpus: found option : test +EOF + +fail=0 + +test_url=test:///default + +for args in \ + 'test 2' \ + '--domain test 2' \ + '--domain=test 2' \ + 'test --count 2' \ + 'test --count=2' \ + '--domain test --count 2' \ + '--domain=test --count 2' \ + '--domain test --count=2' \ + '--domain=test --count=2' \ + '--count 2 --domain test' \ + '--count 2 --domain=test' \ + '--count=2 --domain test' \ + '--count=2 --domain=test' \ +; do + virsh -d5 -c $test_url setvcpus $args >out 2>>err || fail=1 + LC_ALL=C sort out | compare - exp-out || fail=1 +done +test -s err && fail=1 + +(exit $fail); exit $fail -- 1.7.1 From eblake at redhat.com Tue Apr 12 23:12:18 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 12 Apr 2011 17:12:18 -0600 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <1297270705-8709-4-git-send-email-berrange@redhat.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com> <1297270705-8709-4-git-send-email-berrange@redhat.com> Message-ID: <4DA4DC52.8010509@redhat.com> On 02/09/2011 09:58 AM, Daniel P. Berrange wrote: > This patch attempts to introduce a version 3 that uses the > improved 5 step sequence > > * Src: Begin > - Generate XML to pass to dst > - Generate optional cookie to pass to dst > > * Dst: Prepare > - Get ready to accept incoming VM > - Generate optional cookie to pass to src > > * Src: Perform > - Start migration and wait for send completion > - Generate optional cookie to pass to dst > > * Dst: Finish > - Wait for recv completion and check status > - Kill off VM if failed, resume if success > - Generate optional cookie to pass to src > > * Src: Confirm > - Kill off VM if success, resume if failed I've been thinking about this a bit more, and have a question. What happens when the source side decides to abort the migration? For example, if libvirtd on the source gets a SIGHUP or SIGINT, it would be nice to have the cleanup code abort any in-flight migrations so that when libvirtd is restarted, the guest is still operational on the source, and the guest does not have to wait for a full TCP timeout cycle to realize that the source is not going to complete the migration. Does this call for additional internal points in the RPC implementation of v3 migration? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From wency at cn.fujitsu.com Wed Apr 13 01:46:11 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 13 Apr 2011 09:46:11 +0800 Subject: [libvirt] [PATCH 3/6] use virObject to manage reference-count of virDomainObj In-Reply-To: <20110412104013.GE10071@redhat.com> References: <4D9CEA54.6000402@redhat.com> <20110412033407.GA32561@localhost.localdomain> <20110412055133.GA4164@localhost.localdomain> <4DA427D4.2090502@cn.fujitsu.com> <20110412103321.GC4164@localhost.localdomain> <20110412104013.GE10071@redhat.com> Message-ID: <4DA50063.2090700@cn.fujitsu.com> At 04/12/2011 06:40 PM, Daniel P. Berrange Write: > On Tue, Apr 12, 2011 at 06:33:21PM +0800, Hu Tao wrote: >> On Tue, Apr 12, 2011 at 06:22:12PM +0800, Wen Congyang wrote: >>> At 04/12/2011 01:51 PM, Hu Tao Write: >>>> Sorry, I unexpectedly deleted text body. >>>> >>>> I changed the code like this: >>>> >>>> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c >>>> index c2a1f9a..8aad0b3 100644 >>>> --- a/src/qemu/qemu_domain.c >>>> +++ b/src/qemu/qemu_domain.c >>>> @@ -514,7 +514,10 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, >>>> else >>>> virReportSystemError(errno, >>>> "%s", _("cannot acquire job mutex")); >>>> + virDomainObjUnlock(obj); >>>> qemuDriverLock(driver); >>>> + virDomainObjLock(obj); >>> >>> We lock qemu_driver and vm as the folling steps: >>> 1. lock qemu_driver >>> 2. lock vm >>> >>> We try to lock qemu_driver while holding the vm's lock. >>> OOps, it will cause the libvirtd deadlock.(I can reproduce this bug by your script) >>> >>>> + virDomainObjUnref(obj); >>> >>> We have unref it, so do not unref it again. >> >> Didn't see there is already a call to virDomainObjUnref. the patch >> should be: >> >> >From 712883d0151222a276f777f473d96aa23ad5d9d6 Mon Sep 17 00:00:00 2001 >> From: Hu Tao >> Date: Tue, 12 Apr 2011 18:29:27 +0800 >> Subject: [PATCH] qemu: fix a dead-lock problem >> >> In qemuDomainObjBeginJobWithDriver, when virCondWaitUntil timeouts, >> the function tries to call qemuDriverLock with virDomainObj locked, >> this causes the dead-lock problem. This patch fixes this. >> --- >> src/qemu/qemu_domain.c | 6 ++++-- >> 1 files changed, 4 insertions(+), 2 deletions(-) >> >> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c >> index c2a1f9a..a947b4e 100644 >> --- a/src/qemu/qemu_domain.c >> +++ b/src/qemu/qemu_domain.c >> @@ -506,15 +506,17 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, >> >> while (priv->jobActive) { >> if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) { >> - /* Safe to ignore value since ref count was incremented above */ >> - ignore_value(virDomainObjUnref(obj)); >> if (errno == ETIMEDOUT) >> qemuReportError(VIR_ERR_OPERATION_TIMEOUT, >> "%s", _("cannot acquire state change lock")); >> else >> virReportSystemError(errno, >> "%s", _("cannot acquire job mutex")); >> + virDomainObjUnlock(obj); >> qemuDriverLock(driver); >> + virDomainObjLock(obj); >> + /* Safe to ignore value since ref count was incremented above */ >> + ignore_value(virDomainObjUnref(obj)); >> return -1; >> } >> } >> -- > > ACK Thanks. Applied. > > Daniel From kamezawa.hiroyu at jp.fujitsu.com Wed Apr 13 02:47:17 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Wed, 13 Apr 2011 11:47:17 +0900 Subject: [libvirt] [PATCHv9 0/4] persistent device modification for qemu Message-ID: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> Updated against the latest git tree, no major changes since a week ago. Thank you for reviews in previous ones. Purpose of patches: Now, virsh at(de)tach-device/disk/...etc.. doesn't support to update inactive domain's definition even with the --persistent flag. To update persistent modification of inactive domains, we have to use virsh edit. So, if we want to update inactive domain definition with scripts, we need to use other command/libs than libvirt. I'd like to use libvirt/virsh in scripts. This patches adds to support for updating domain definition via virsh with scripts. This series just includes 'disk' updates but I'll add more. Thanks, -Kame From kamezawa.hiroyu at jp.fujitsu.com Wed Apr 13 02:49:31 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Wed, 13 Apr 2011 11:49:31 +0900 Subject: [libvirt] [PATCHv9 1/4] libvirt/qemu - persistent modification of devices. In-Reply-To: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> References: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110413114931.a3357044.kamezawa.hiroyu@jp.fujitsu.com> Now, qemudDomainAttachDeviceFlags() and qemudDomainDetachDeviceFlags() doesn't support VIR_DOMAIN_DEVICE_MODIFY_CONFIG. By this, virsh's at(de)tatch-device --persistent cannot modify qemu config. (Xen allows it.) This patch is a base patch for adding support of devices in step by step manner. Following patches will add some device support. Signed-off-by: KAMEZAWA Hiroyuki Changelog: v8->v9 - removed unnecessary comments. --- src/qemu/qemu_driver.c | 134 +++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 120 insertions(+), 14 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 04a5f65..49af487 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3918,16 +3918,117 @@ cleanup: return ret; } -static int qemudDomainAttachDeviceFlags(virDomainPtr dom, - const char *xml, - unsigned int flags) { - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); +static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef, + virDomainDeviceDefPtr newdev) +{ + + switch(newdev->type) { + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("the device is not supported for now")); return -1; } - return qemudDomainAttachDevice(dom, xml); + return 0; +} + +static int qemuDomainDetachDevicePersistent(virDomainDefPtr vmdef, + virDomainDeviceDefPtr device) +{ + switch(device->type) { + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("the device is not supported for now")); + return -1; + } + return 0; +} + +static int qemuDomainModifyDevicePersistent(virDomainPtr dom, + const char *xml, + unsigned int attach, + unsigned int flags) +{ + struct qemud_driver *driver; + virDomainDeviceDefPtr device; + virDomainDefPtr vmdef; + virDomainObjPtr vm; + int ret = -1; + + /* + * When both of MODIFY_CONFIG and MODIFY_LIVE are passed at the same time, + * return error for now. We should support this later. + */ + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify active domain and its definition " + "at the same time.")); + return -1; + } + + driver = dom->conn->privateData; + qemuDriverLock(driver); + vm = virDomainFindByName(&driver->domains, dom->name); + if (!vm) { + qemuReportError(VIR_ERR_NO_DOMAIN, _("no domain with name : '%s'"), + dom->name); + goto unlock_out; + } + + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + goto unlock_out; + + if (virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify active domain's definition")); + goto endjob; + } + + vmdef = virDomainObjGetPersistentDef(driver->caps, vm); + + if (!vmdef) + goto endjob; + + device = virDomainDeviceDefParse(driver->caps, + vmdef, xml, VIR_DOMAIN_XML_INACTIVE); + if (!device) + goto endjob; + + if (attach) + ret = qemuDomainAttachDevicePersistent(vmdef, device); + else + ret = qemuDomainDetachDevicePersistent(vmdef, device); + + if (!ret) + ret = virDomainSaveConfig(driver->configDir, vmdef); + + virDomainDeviceDefFree(device); + +endjob: + if (qemuDomainObjEndJob(vm) == 0) + vm = NULL; +unlock_out: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); + return ret; +} + +static int qemudDomainAttachDeviceFlags(virDomainPtr dom, + const char *xml, + unsigned int flags) +{ + int ret = -1; + + virCheckFlags((VIR_DOMAIN_DEVICE_MODIFY_CONFIG | + VIR_DOMAIN_DEVICE_MODIFY_LIVE), -1); + + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) + ret = qemuDomainModifyDevicePersistent(dom, xml, 1, flags); + else if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) + ret = qemudDomainAttachDevice(dom, xml); + + return ret; } @@ -4141,14 +4242,19 @@ cleanup: static int qemudDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) { - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } + unsigned int flags) +{ + int ret = -1; + + virCheckFlags((VIR_DOMAIN_DEVICE_MODIFY_CONFIG | + VIR_DOMAIN_DEVICE_MODIFY_LIVE), -1); - return qemudDomainDetachDevice(dom, xml); + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) + ret = qemuDomainModifyDevicePersistent(dom, xml, 0, flags); + else if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) + ret = qemudDomainDetachDevice(dom, xml); + + return ret; } static int qemudDomainGetAutostart(virDomainPtr dom, -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Wed Apr 13 02:50:55 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Wed, 13 Apr 2011 11:50:55 +0900 Subject: [libvirt] [PATCHv9 2/4] libvirt/qemu - keep consistency at persistent modification. In-Reply-To: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> References: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110413115055.42f13f69.kamezawa.hiroyu@jp.fujitsu.com> At persistent modification of inactive domains, we go several steps as - insert disk to vmdef - assign controller if necessary - assign pci address if necessary - save it to file If failure happens in above sequence, we need to keep consistency between vmdef on cache and XML in the file. This patch adds support for consistent modification of vmdef. This patch adds virDomainObjCopyPersistentDef(). This will create a copy of persistent def. The caller can update this and later replace current one as: copy = virDomainObjCopyPersistentDef() .....update.... if (error) virDomainObjAssignDef(dom, copy); else virDomainDefFree(copy). Signed-off-by: KAMEZAWA Hiroyuki --- src/conf/domain_conf.c | 18 ++++++++++++++++++ src/conf/domain_conf.h | 3 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 13 +++++++++++-- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 90a1317..e644af0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9370,3 +9370,21 @@ cleanup: return ret; } + +virDomainDefPtr +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom) +{ + char *xml; + virDomainDefPtr cur, ret; + + cur = virDomainObjGetPersistentDef(caps, dom); + + xml = virDomainDefFormat(cur, VIR_DOMAIN_XML_WRITE_FLAGS); + if (!xml) + return NULL; + + ret = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS); + + VIR_FREE(xml); + return ret; +} diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 95bd11e..9b97f26 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1377,6 +1377,9 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk, virDomainDiskDefPathIterator iter, void *opaque); +virDomainDefPtr +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom); + typedef const char* (*virLifecycleToStringFunc)(int type); typedef int (*virLifecycleFromStringFunc)(const char *type); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 54e4482..f464951 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -278,6 +278,7 @@ virDomainMemballoonModelTypeToString; virDomainNetDefFree; virDomainNetTypeToString; virDomainObjAssignDef; +virDomainObjCopyPersistentDef; virDomainObjSetDefTransient; virDomainObjGetPersistentDef; virDomainObjIsDuplicate; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 49af487..b568382 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3983,8 +3983,11 @@ static int qemuDomainModifyDevicePersistent(virDomainPtr dom, _("cannot modify active domain's definition")); goto endjob; } - - vmdef = virDomainObjGetPersistentDef(driver->caps, vm); + /* + * Here, create a copy of the current definition and update it. + * We'll finally replace the definition at success. + */ + vmdef = virDomainObjCopyPersistentDef(driver->caps, vm); if (!vmdef) goto endjob; @@ -4002,6 +4005,12 @@ static int qemuDomainModifyDevicePersistent(virDomainPtr dom, if (!ret) ret = virDomainSaveConfig(driver->configDir, vmdef); + /* At success, replace it. this never fails. */ + if (!ret) + virDomainObjAssignDef(vm, vmdef, false); + else /* At failure, discard copy. */ + virDomainDefFree(vmdef); + virDomainDeviceDefFree(device); endjob: -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Wed Apr 13 02:51:49 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Wed, 13 Apr 2011 11:51:49 +0900 Subject: [libvirt] [PATCHv9 3/4] libvirt/qemu - support persistent disk modification In-Reply-To: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> References: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110413115149.71c80289.kamezawa.hiroyu@jp.fujitsu.com> support changes of disks by VIR_DOMAIN_DEVICE_MODIFY_CONFIG for qemu. Signed-off-by: KAMEZAWA Hiroyuki Changelog: v8->v9 updated comments --- src/conf/domain_conf.c | 22 ++++++++++++++++++++++ src/conf/domain_conf.h | 2 ++ src/libvirt_private.syms | 2 ++ src/qemu/qemu_driver.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 0 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e644af0..a39da7e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4879,6 +4879,19 @@ virVirtualPortProfileFormat(virBufferPtr buf, virBufferVSprintf(buf, "%s\n", indent); } +int virDomainDiskIndexByName(virDomainDefPtr def, const char *name) +{ + virDomainDiskDefPtr vdisk; + int i; + + for (i = 0; i < def->ndisks; i++) { + vdisk = def->disks[i]; + if (STREQ(vdisk->dst, name)) + return i; + } + return -1; +} + int virDomainDiskInsert(virDomainDefPtr def, virDomainDiskDefPtr disk) { @@ -4950,6 +4963,15 @@ void virDomainDiskRemove(virDomainDefPtr def, size_t i) } } +int virDomainDiskRemoveByName(virDomainDefPtr def, const char *name) +{ + int i = virDomainDiskIndexByName(def, name); + if (i < 0) + return -1; + virDomainDiskRemove(def, i); + return 0; +} + int virDomainControllerInsert(virDomainDefPtr def, virDomainControllerDefPtr controller) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9b97f26..6b7cfe7 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1282,6 +1282,7 @@ int virDomainVcpupinAdd(virDomainDefPtr def, int maplen, int vcpu); +int virDomainDiskIndexByName(virDomainDefPtr def, const char *name); int virDomainDiskInsert(virDomainDefPtr def, virDomainDiskDefPtr disk); void virDomainDiskInsertPreAlloced(virDomainDefPtr def, @@ -1289,6 +1290,7 @@ void virDomainDiskInsertPreAlloced(virDomainDefPtr def, int virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def); void virDomainDiskRemove(virDomainDefPtr def, size_t i); +int virDomainDiskRemoveByName(virDomainDefPtr def, const char *name); int virDomainControllerInsert(virDomainDefPtr def, virDomainControllerDefPtr controller); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f464951..5c241aa 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -245,11 +245,13 @@ virDomainDiskDefFree; virDomainDiskDeviceTypeToString; virDomainDiskErrorPolicyTypeFromString; virDomainDiskErrorPolicyTypeToString; +virDomainDiskIndexByName; virDomainDiskInsert; virDomainDiskInsertPreAlloced; virDomainDiskIoTypeFromString; virDomainDiskIoTypeToString; virDomainDiskRemove; +virDomainDiskRemoveByName; virDomainDiskTypeFromString; virDomainDiskTypeToString; virDomainFSDefFree; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b568382..9c4f290 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3921,8 +3921,28 @@ cleanup: static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef, virDomainDeviceDefPtr newdev) { + virDomainDiskDefPtr disk; switch(newdev->type) { + case VIR_DOMAIN_DEVICE_DISK: + disk = newdev->data.disk; + if (virDomainDiskIndexByName(vmdef, disk->dst) >= 0) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("target %s already exists."), disk->dst); + return -1; + } + if (virDomainDiskInsert(vmdef, disk)) { + virReportOOMError(); + return -1; + } + /* vmdef has the pointer. Generic codes for vmdef will do all jobs */ + newdev->data.disk = NULL; + if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO) + if (virDomainDefAddImplicitControllers(vmdef) < 0) + return -1; + if (qemuDomainAssignPCIAddresses(vmdef) < 0) + return -1; + break; default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the device is not supported for now")); @@ -3935,7 +3955,17 @@ static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef, static int qemuDomainDetachDevicePersistent(virDomainDefPtr vmdef, virDomainDeviceDefPtr device) { + virDomainDiskDefPtr disk; + switch(device->type) { + case VIR_DOMAIN_DEVICE_DISK: + disk = device->data.disk; + if (virDomainDiskRemoveByName(vmdef, disk->dst)) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("no target device %s"), disk->dst); + return -1; + } + break; default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("the device is not supported for now")); -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Wed Apr 13 02:53:24 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Wed, 13 Apr 2011 11:53:24 +0900 Subject: [libvirt] [PATCHv9 4/4] libvirt/qemu - check address confliction before addition. In-Reply-To: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> References: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110413115324.a4ba4868.kamezawa.hiroyu@jp.fujitsu.com> qemuDomainAttachDevicePersistent() calls qemuDomainAssignPCIAddresses() and virDomainDefAddImplicitControllers() at the end of its call. But PCI/Drive address confliction checks are PCI - confliction will be found but error report is not verbose. Drive - never done. For example, when adding a device which has already used address. error: Failed to attach device from /home/kamezawa/testc.xml error: An error occurred, but the cause is unknown After patch, the message will be error: Failed to attach device from /home/kamezawa/testc.xml error: invalid argument in device address conflict This error report is better. And new code aslo checks devices other than PCI devices. Signed-off-by: KAMEZAWA Hiroyuki Changelog: - typo fix. --- src/conf/domain_conf.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 2 + src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 3 ++ 4 files changed, 71 insertions(+), 0 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a39da7e..1de4c7a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1305,6 +1305,71 @@ void virDomainDefClearDeviceAliases(virDomainDefPtr def) virDomainDeviceInfoIterate(def, virDomainDeviceInfoClearAlias, NULL); } +static int virDomainDeviceAddressMatch(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, + void *opaque) +{ + virDomainDeviceInfoPtr checked = opaque; + /* skip to check confliction of alias */ + if (info->type != checked->type) + return 0; + if (info->alias && checked->alias && STREQ(info->alias, checked->alias)) + return -1; + /* addr is zero cleared before filled */ + if (!memcmp(&info->addr, &checked->addr, sizeof(info->addr))) + return -1; + return 0; +} + +int virDomainDefFindDeviceAddressConflict(virDomainDefPtr def, + virDomainDeviceDefPtr dev) +{ + virDomainDeviceInfoPtr checked; + int ret; + + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + checked = &dev->data.disk->info; + break; + case VIR_DOMAIN_DEVICE_FS: + checked = &dev->data.fs->info; + break; + case VIR_DOMAIN_DEVICE_NET: + checked = &dev->data.net->info; + break; + case VIR_DOMAIN_DEVICE_INPUT: + checked = &dev->data.input->info; + break; + case VIR_DOMAIN_DEVICE_SOUND: + checked = &dev->data.sound->info; + break; + case VIR_DOMAIN_DEVICE_VIDEO: + checked = &dev->data.video->info; + break; + case VIR_DOMAIN_DEVICE_HOSTDEV: + checked = &dev->data.hostdev->info; + break; + case VIR_DOMAIN_DEVICE_WATCHDOG: + checked = &dev->data.watchdog->info; + break; + case VIR_DOMAIN_DEVICE_CONTROLLER: + checked = &dev->data.controller->info; + break; + case VIR_DOMAIN_DEVICE_GRAPHICS: /* has no address info */ + return 0; + default: /* internal error */ + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Unknown device type")); + return -1; + } + if (checked->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) + return 0; + ret = virDomainDeviceInfoIterate(def, virDomainDeviceAddressMatch, checked); + if (ret) + virDomainReportError(VIR_ERR_INVALID_ARG, + "%s", _("device address conflict")); + return ret; +} /* Generate a string representation of a device address * @param address Device address to stringify diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6b7cfe7..a33c60f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1215,6 +1215,8 @@ int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info); void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info); void virDomainDefClearPCIAddresses(virDomainDefPtr def); void virDomainDefClearDeviceAliases(virDomainDefPtr def); +int virDomainDefFindDeviceAddressConflict(virDomainDefPtr def, + virDomainDeviceDefPtr dev); typedef int (*virDomainDeviceInfoCallback)(virDomainDefPtr def, virDomainDeviceInfoPtr dev, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5c241aa..9eb0d59 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -222,6 +222,7 @@ virDomainCpuSetParse; virDomainDefAddImplicitControllers; virDomainDefClearDeviceAliases; virDomainDefClearPCIAddresses; +virDomainDefFindDeviceAddressConflict; virDomainDefFormat; virDomainDefFree; virDomainDefParseFile; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 9c4f290..aada6be 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3923,6 +3923,9 @@ static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef, { virDomainDiskDefPtr disk; + if (virDomainDefFindDeviceAddressConflict(vmdef, newdev)) + return -1; + switch(newdev->type) { case VIR_DOMAIN_DEVICE_DISK: disk = newdev->data.disk; -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Wed Apr 13 02:54:35 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Wed, 13 Apr 2011 11:54:35 +0900 Subject: [libvirt] [PATCHv9 0/4] persistent device modification for qemu In-Reply-To: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> References: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110413115435.50c465d2.kamezawa.hiroyu@jp.fujitsu.com> Sorry, CC list was wrong. remove "hugh.dickins at tiscali.co.uk" from CC if you reply.. Thanks, -Kame From liyong at skybility.com Wed Apr 13 04:10:39 2011 From: liyong at skybility.com (Lyre) Date: Wed, 13 Apr 2011 12:10:39 +0800 Subject: [libvirt] [libvirt-php] Fix get_xml when xpath is null Message-ID: <1302667839-13712-1-git-send-email-liyong@skybility.com> Hi all: To my surprise, it seems that passing null to php as a string parameter, will set the pointer which retrive it to an empty string "" , but not NULL. get_xml_from_xpath() doesn't work correctly since an empty string is passed as the xpath argument, and libxml will complain "Invalid expression" I know seldom about xpath, I'm not sure if it is the correct way to fix it. BTW, what xpath shall I pass to get the entire xml? --- src/libvirt-php.c | 25 +++++++++++++++++++++++++ 1 files changed, 25 insertions(+), 0 deletions(-) diff --git a/src/libvirt-php.c b/src/libvirt-php.c index ce9d0b9..2a77423 100644 --- a/src/libvirt-php.c +++ b/src/libvirt-php.c @@ -1205,6 +1205,11 @@ char *get_string_from_xpath(char *xml, char *xpath, zval **val, int *retVal) int ret = 0, i; char *value, key[8] = { 0 }; + if ((xpath == NULL) || (xml == NULL)) + { + return NULL; + } + xp = xmlCreateDocParserCtxt( (xmlChar *)xml ); if (!xp) { if (retVal) @@ -1691,6 +1696,10 @@ PHP_FUNCTION(libvirt_domain_get_xml_desc) int retval = -1; GET_DOMAIN_FROM_ARGS("rs|l",&zdomain,&xpath,&xpath_len,&flags); + if (xpath_len < 1) + { + xpath = NULL; + } xml=virDomainGetXMLDesc(domain->domain,flags); if (xml==NULL) { @@ -3123,6 +3132,10 @@ PHP_FUNCTION(libvirt_storagevolume_get_xml_desc) int retval = -1; GET_VOLUME_FROM_ARGS("rs|l",&zvolume,&xpath,&xpath_len,&flags); + if (xpath_len < 1) + { + xpath = NULL; + } xml=virStorageVolGetXMLDesc(volume->volume,flags); if (xml==NULL) { @@ -3338,6 +3351,10 @@ PHP_FUNCTION(libvirt_storagepool_get_xml_desc) int retval = -1; GET_STORAGEPOOL_FROM_ARGS("rs|l", &zpool, &xpath, &xpath_len, &flags); + if (xpath_len < 1) + { + xpath = NULL; + } xml = virStoragePoolGetXMLDesc (pool->pool, flags); if (xml == NULL) @@ -4136,6 +4153,10 @@ PHP_FUNCTION(libvirt_nodedev_get_xml_desc) int retval = -1; GET_NODEDEV_FROM_ARGS("r|s",&znodedev,&xpath,&xpath_len); + if (xpath_len < 1) + { + xpath = NULL; + } xml=virNodeDeviceGetXMLDesc(nodedev->device, 0); if ( xml == NULL ) { @@ -4576,6 +4597,10 @@ PHP_FUNCTION(libvirt_network_get_xml_desc) int retval = -1; GET_NETWORK_FROM_ARGS("r|s",&znetwork,&xpath,&xpath_len); + if (xpath_len < 1) + { + xpath = NULL; + } xml=virNetworkGetXMLDesc(network->network, 0); -- 1.7.3.4 From laijs at cn.fujitsu.com Wed Apr 13 04:56:58 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Wed, 13 Apr 2011 12:56:58 +0800 Subject: [libvirt] [PATCH 0/6] Add support for injecting NMI to guest Message-ID: <4DA52D1A.1000307@cn.fujitsu.com> This patch series implements a feature of injecting NMI to guest, which is accessible via new virDomainInjectNMI API and 'inject-nmi' command in virsh. Lai Jiangshan (6): inject-nmi: Defining the public API inject-nmi: Defining the internal API inject-nmi: Implementing the public API inject-nmi: Implementing the remote protocol inject-nmi: Expose the new API in virsh qemu,inject-nmi: Implement the driver methods daemon/remote.c | 26 ++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++++ daemon/remote_dispatch_table.h | 5 ++++ include/libvirt/libvirt.h.in | 2 + src/driver.h | 4 +++ src/esx/esx_driver.c | 1 + src/libvirt.c | 44 +++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 ++++ src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 3 +- src/qemu/qemu_driver.c | 43 ++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 14 +++++++++++ src/qemu/qemu_monitor.h | 2 + src/qemu/qemu_monitor_json.c | 29 +++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 1 + src/qemu/qemu_monitor_text.c | 20 ++++++++++++++++ src/qemu/qemu_monitor_text.h | 1 + src/remote/remote_driver.c | 25 +++++++++++++++++++ src/remote/remote_protocol.c | 11 ++++++++ src/remote/remote_protocol.h | 10 ++++++++ src/remote/remote_protocol.x | 8 +++++- src/remote_protocol-structs | 4 +++ src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xen/xen_driver.h | 1 + src/xen/xen_hypervisor.c | 1 + src/xen/xen_inotify.c | 1 + src/xen/xend_internal.c | 1 + src/xen/xm_internal.c | 1 + src/xen/xs_internal.c | 1 + src/xenapi/xenapi_driver.c | 1 + tools/virsh.c | 36 ++++++++++++++++++++++++++++ tools/virsh.pod | 4 +++ 39 files changed, 320 insertions(+), 2 deletions(-) -- 1.7.4 From laijs at cn.fujitsu.com Wed Apr 13 04:59:51 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Wed, 13 Apr 2011 12:59:51 +0800 Subject: [libvirt] [PATCH 1/6] inject-nmi: Defining the public API In-Reply-To: <4DA52D1A.1000307@cn.fujitsu.com> References: <4DA52D1A.1000307@cn.fujitsu.com> Message-ID: <4DA52DC7.5050007@cn.fujitsu.com> --- include/libvirt/libvirt.h.in | 2 ++ src/libvirt_public.syms | 5 +++++ 2 files changed, 7 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 5783303..0e1e27a 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2519,6 +2519,8 @@ int virDomainOpenConsole(virDomainPtr dom, virStreamPtr st, unsigned int flags); +int virDomainInjectNMI(virDomainPtr domain, unsigned int flags); + #ifdef __cplusplus } #endif diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b4aed41..f5bbc01 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -436,4 +436,9 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8; +LIBVIRT_0.9.1 { + global: + virDomainInjectNMI; +} LIBVIRT_0.9.0; + # .... define new API here using predicted next version number .... -- 1.7.4 From laijs at cn.fujitsu.com Wed Apr 13 05:00:12 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Wed, 13 Apr 2011 13:00:12 +0800 Subject: [libvirt] [PATCH 2/6] inject-nmi: Defining the internal API In-Reply-To: <4DA52D1A.1000307@cn.fujitsu.com> References: <4DA52D1A.1000307@cn.fujitsu.com> Message-ID: <4DA52DDC.9010803@cn.fujitsu.com> --- src/driver.h | 4 ++++ src/esx/esx_driver.c | 1 + src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 3 ++- src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 1 + src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xen/xen_driver.h | 1 + src/xen/xen_hypervisor.c | 1 + src/xen/xen_inotify.c | 1 + src/xen/xend_internal.c | 1 + src/xen/xm_internal.c | 1 + src/xen/xs_internal.c | 1 + src/xenapi/xenapi_driver.c | 1 + 20 files changed, 24 insertions(+), 1 deletions(-) diff --git a/src/driver.h b/src/driver.h index a8b79e6..94cc37d 100644 --- a/src/driver.h +++ b/src/driver.h @@ -515,6 +515,9 @@ typedef int virStreamPtr st, unsigned int flags); +typedef int + (*virDrvDomainInjectNMI)(virDomainPtr dom, unsigned int flags); + /** * _virDriver: @@ -639,6 +642,7 @@ struct _virDriver { virDrvDomainSnapshotDelete domainSnapshotDelete; virDrvQemuDomainMonitorCommand qemuDomainMonitorCommand; virDrvDomainOpenConsole domainOpenConsole; + virDrvDomainInjectNMI domainInjectNMI; }; typedef int diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index deda372..061a562 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4675,6 +4675,7 @@ static virDriver esxDriver = { esxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 3040914..35e8104 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2663,6 +2663,7 @@ static virDriver libxlDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; static virStateDriver libxlStateDriver = { diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e905302..fbbe803 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2906,6 +2906,7 @@ static virDriver lxcDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ lxcDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; static virStateDriver lxcStateDriver = { diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 4af28e9..96f82bb 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1667,6 +1667,7 @@ static virDriver openvzDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; int openvzRegister(void) { diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index ddbc103..dfd0463 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -4071,7 +4071,8 @@ static virDriver phypDriver = { NULL, /* domainRevertToSnapshot */ NULL, /* domainSnapshotDelete */ NULL, /* qemuMonitorCommand */ - NULL, /* domainOpenConsole */ + NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; static virStorageDriver phypStorageDriver = { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 04a5f65..c3ec07e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6970,6 +6970,7 @@ static virDriver qemuDriver = { qemuDomainSnapshotDelete, /* domainSnapshotDelete */ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ qemuDomainOpenConsole, /* domainOpenConsole */ + qemuDomainInjectNMI, /* domainInjectNMI */ }; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index b979f71..795bea9 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -11301,6 +11301,7 @@ static virDriver remote_driver = { remoteDomainSnapshotDelete, /* domainSnapshotDelete */ remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ remoteDomainOpenConsole, /* domainOpenConsole */ + remoteDomainInjectNMI, /* domainInjectNMI */ }; static virNetworkDriver network_driver = { diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 17f5ad9..b4dcc5b 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5447,6 +5447,7 @@ static virDriver testDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; static virNetworkDriver testNetworkDriver = { diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 33849a0..73a5415 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2253,6 +2253,7 @@ static virDriver umlDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ umlDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; static int diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 0fbfba5..4bcc192 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8647,6 +8647,7 @@ virDriver NAME(Driver) = { vboxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; virNetworkDriver NAME(NetworkDriver) = { diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index b5e416b..d6fc9e8 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -1007,6 +1007,7 @@ static virDriver vmwareDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; int diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 9f47722..c9e6115 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2141,6 +2141,7 @@ static virDriver xenUnifiedDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ xenUnifiedDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; /** diff --git a/src/xen/xen_driver.h b/src/xen/xen_driver.h index 58b8561..7cc363c 100644 --- a/src/xen/xen_driver.h +++ b/src/xen/xen_driver.h @@ -108,6 +108,7 @@ struct xenUnifiedDriver { virDrvDomainGetSchedulerType domainGetSchedulerType; virDrvDomainGetSchedulerParameters domainGetSchedulerParameters; virDrvDomainSetSchedulerParameters domainSetSchedulerParameters; + virDrvDomainInjectNMI domainInjectNMI; }; typedef struct xenXMConfCache *xenXMConfCachePtr; diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c index 8a9dae5..9b0bfcc 100644 --- a/src/xen/xen_hypervisor.c +++ b/src/xen/xen_hypervisor.c @@ -839,6 +839,7 @@ struct xenUnifiedDriver xenHypervisorDriver = { xenHypervisorGetSchedulerType, /* domainGetSchedulerType */ xenHypervisorGetSchedulerParameters, /* domainGetSchedulerParameters */ xenHypervisorSetSchedulerParameters, /* domainSetSchedulerParameters */ + NULL, /* domainInjectNMI */ }; #define virXenError(code, ...) \ diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c index 5a997e6..9a68e6b 100644 --- a/src/xen/xen_inotify.c +++ b/src/xen/xen_inotify.c @@ -87,6 +87,7 @@ struct xenUnifiedDriver xenInotifyDriver = { NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ + NULL, /* domainInjectNMI */ }; static int diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 04122ba..783d2d1 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -3881,6 +3881,7 @@ struct xenUnifiedDriver xenDaemonDriver = { xenDaemonGetSchedulerType, /* domainGetSchedulerType */ xenDaemonGetSchedulerParameters, /* domainGetSchedulerParameters */ xenDaemonSetSchedulerParameters, /* domainSetSchedulerParameters */ + NULL, /* domainInjectNMI */ }; diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 9225808..72bd863 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -118,6 +118,7 @@ struct xenUnifiedDriver xenXMDriver = { NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ + NULL, /* domainInjectNMI */ }; #define xenXMError(code, ...) \ diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c index d9aad1f..0118a9e 100644 --- a/src/xen/xs_internal.c +++ b/src/xen/xs_internal.c @@ -80,6 +80,7 @@ struct xenUnifiedDriver xenStoreDriver = { NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ + NULL, /* domainInjectNMI */ }; #define virXenStoreError(code, ...) \ diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 60b23c7..7069b52 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1889,6 +1889,7 @@ static virDriver xenapiDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; /** -- 1.7.4 From laijs at cn.fujitsu.com Wed Apr 13 05:00:36 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Wed, 13 Apr 2011 13:00:36 +0800 Subject: [libvirt] [PATCH 3/6] inject-nmi: Implementing the public API In-Reply-To: <4DA52D1A.1000307@cn.fujitsu.com> References: <4DA52D1A.1000307@cn.fujitsu.com> Message-ID: <4DA52DF4.9000901@cn.fujitsu.com> --- src/libvirt.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 44 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 0da9885..56996f9 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -5214,6 +5214,50 @@ error: } /** + * virDomainInjectNMI: + * @domain: pointer to domain object, or NULL for Domain0 + * @flags: the flags for controlling behaviours + * + * Send NMI to the guest + * + * Returns 0 in case of success, -1 in case of failure. + */ + +int virDomainInjectNMI(virDomainPtr domain, unsigned int flags) +{ + virConnectPtr conn; + VIR_DOMAIN_DEBUG(domain, "flags=%u", flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainInjectNMI) { + int ret; + ret = conn->driver->domainInjectNMI(domain, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} + +/** * virDomainSetVcpus: * @domain: pointer to domain object, or NULL for Domain0 * @nvcpus: the new number of virtual CPUs for this domain -- 1.7.4 From laijs at cn.fujitsu.com Wed Apr 13 05:01:02 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Wed, 13 Apr 2011 13:01:02 +0800 Subject: [libvirt] [PATCH 4/6] inject-nmi: Implementing the remote protocol In-Reply-To: <4DA52D1A.1000307@cn.fujitsu.com> References: <4DA52D1A.1000307@cn.fujitsu.com> Message-ID: <4DA52E0E.3050408@cn.fujitsu.com> --- daemon/remote.c | 26 ++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++++++ daemon/remote_dispatch_table.h | 5 +++++ src/remote/remote_driver.c | 24 ++++++++++++++++++++++++ src/remote/remote_protocol.c | 11 +++++++++++ src/remote/remote_protocol.h | 10 ++++++++++ src/remote/remote_protocol.x | 8 +++++++- src/remote_protocol-structs | 4 ++++ 9 files changed, 96 insertions(+), 1 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index dd85ef1..a539d03 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -2844,6 +2844,32 @@ remoteDispatchDomainGetBlkioParameters(struct qemud_server *server } static int +remoteDispatchDomainInjectNMI(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_inject_nmi_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virDomainPtr dom; + + dom = get_nonnull_domain(conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + if (virDomainInjectNMI(dom, args->flags) == -1) { + virDomainFree(dom); + remoteDispatchConnError(rerr, conn); + return -1; + } + virDomainFree(dom); + return 0; +} + +static int remoteDispatchDomainSetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index f9537d7..4887d7c 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -178,3 +178,4 @@ remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; remote_storage_vol_upload_args val_remote_storage_vol_upload_args; remote_storage_vol_download_args val_remote_storage_vol_download_args; + remote_domain_inject_nmi_args val_remote_domain_inject_nmi_args; diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 18bf41d..4e12cb0 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -338,6 +338,14 @@ static int remoteDispatchDomainHasManagedSaveImage( remote_error *err, remote_domain_has_managed_save_image_args *args, remote_domain_has_managed_save_image_ret *ret); +static int remoteDispatchDomainInjectNMI( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_inject_nmi_args *args, + void *ret); static int remoteDispatchDomainInterfaceStats( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index b39f7c2..b911acf 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1052,3 +1052,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* DomainInjectNMI => 210 */ + .fn = (dispatch_fn) remoteDispatchDomainInjectNMI, + .args_filter = (xdrproc_t) xdr_remote_domain_inject_nmi_args, + .ret_filter = (xdrproc_t) xdr_void, +}, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 795bea9..40deb52 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2933,6 +2933,30 @@ done: } static int +remoteDomainInjectNMI(virDomainPtr domain, unsigned int flags) +{ + int rv = -1; + remote_domain_inject_nmi_args args; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + make_nonnull_domain (&args.dom, domain); + args.flags = flags; + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_INJECT_NMI, + (xdrproc_t) xdr_remote_domain_inject_nmi_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int remoteDomainSetVcpus (virDomainPtr domain, unsigned int nvcpus) { int rv = -1; diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 5604371..3ff0b1f 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -1463,6 +1463,17 @@ xdr_remote_domain_undefine_args (XDR *xdrs, remote_domain_undefine_args *objp) } bool_t +xdr_remote_domain_inject_nmi_args (XDR *xdrs, remote_domain_inject_nmi_args *objp) +{ + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_domain_set_vcpus_args (XDR *xdrs, remote_domain_set_vcpus_args *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index d9bf151..4da003e 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -2200,6 +2200,13 @@ struct remote_storage_vol_download_args { u_int flags; }; typedef struct remote_storage_vol_download_args remote_storage_vol_download_args; + +struct remote_domain_inject_nmi_args { + remote_nonnull_domain dom; + u_int flags; +}; +typedef struct remote_domain_inject_nmi_args remote_domain_inject_nmi_args; + #define REMOTE_PROGRAM 0x20008086 #define REMOTE_PROTOCOL_VERSION 1 @@ -2413,6 +2420,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_INJECT_NMI = 210, }; typedef enum remote_procedure remote_procedure; @@ -2561,6 +2569,7 @@ extern bool_t xdr_remote_domain_create_with_flags_ret (XDR *, remote_domain_cre extern bool_t xdr_remote_domain_define_xml_args (XDR *, remote_domain_define_xml_args*); extern bool_t xdr_remote_domain_define_xml_ret (XDR *, remote_domain_define_xml_ret*); extern bool_t xdr_remote_domain_undefine_args (XDR *, remote_domain_undefine_args*); +extern bool_t xdr_remote_domain_inject_nmi_args (XDR *, remote_domain_inject_nmi_args*); extern bool_t xdr_remote_domain_set_vcpus_args (XDR *, remote_domain_set_vcpus_args*); extern bool_t xdr_remote_domain_set_vcpus_flags_args (XDR *, remote_domain_set_vcpus_flags_args*); extern bool_t xdr_remote_domain_get_vcpus_flags_args (XDR *, remote_domain_get_vcpus_flags_args*); @@ -2918,6 +2927,7 @@ extern bool_t xdr_remote_domain_create_with_flags_ret (); extern bool_t xdr_remote_domain_define_xml_args (); extern bool_t xdr_remote_domain_define_xml_ret (); extern bool_t xdr_remote_domain_undefine_args (); +extern bool_t xdr_remote_domain_inject_nmi_args (); extern bool_t xdr_remote_domain_set_vcpus_args (); extern bool_t xdr_remote_domain_set_vcpus_flags_args (); extern bool_t xdr_remote_domain_get_vcpus_flags_args (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 675eccd..1aacf99 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -817,6 +817,11 @@ struct remote_domain_undefine_args { remote_nonnull_domain dom; }; +struct remote_domain_inject_nmi_args { + remote_nonnull_domain dom; + unsigned int flags; +}; + struct remote_domain_set_vcpus_args { remote_nonnull_domain dom; int nvcpus; @@ -2176,8 +2181,9 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_INJECT_NMI = 210, /* * Notice how the entries are grouped in sets of 10 ? * Nice isn't it. Please keep it this way when adding more. diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 944553c..4b75e33 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1435,3 +1435,7 @@ struct remote_message_header { u_int serial; remote_message_status status; }; +struct remote_domain_inject_nmi_args { + remote_nonnull_domain dom; + unsigned int flags; +}; -- 1.7.4 From laijs at cn.fujitsu.com Wed Apr 13 05:01:27 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Wed, 13 Apr 2011 13:01:27 +0800 Subject: [libvirt] [PATCH 5/6] inject-nmi: Expose the new API in virsh In-Reply-To: <4DA52D1A.1000307@cn.fujitsu.com> References: <4DA52D1A.1000307@cn.fujitsu.com> Message-ID: <4DA52E27.4020605@cn.fujitsu.com> --- tools/virsh.c | 36 ++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 4 ++++ 2 files changed, 40 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 2e35021..5e3df8a 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2919,6 +2919,41 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) } /* + * "inject-nmi" command + */ +static const vshCmdInfo info_inject_nmi[] = { + {"help", N_("Inject NMI to the guest")}, + {"desc", N_("Inject NMI to the guest domain.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_inject_nmi[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {NULL, 0, 0, NULL} +}; + + +static int +cmdInjectNMI(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + const char *type; + int ret = TRUE; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return FALSE; + + if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + return FALSE; + + if (virDomainInjectNMI(dom, 0) < 0) + ret = FALSE; + + virDomainFree(dom); + return ret; +} + +/* * "setmemory" command */ static const vshCmdInfo info_setmem[] = { @@ -10733,6 +10768,7 @@ static const vshCmdDef domManagementCmds[] = { {"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem}, {"setmem", cmdSetmem, opts_setmem, info_setmem}, {"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus}, + {"inject-nmi", cmdInjectNMI, opts_inject_nmi, info_inject_nmi}, {"shutdown", cmdShutdown, opts_shutdown, info_shutdown}, {"start", cmdStart, opts_start, info_start}, {"suspend", cmdSuspend, opts_suspend, info_suspend}, diff --git a/tools/virsh.pod b/tools/virsh.pod index 2a708f6..f317c57 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -290,6 +290,10 @@ running B. When in a paused state the domain will still consume allocated resources like memory, but will not be eligible for scheduling by the hypervisor. +=item B I + +Inject NMI to the guest + =item B The domain is in the process of shutting down, i.e. the guest operating system -- 1.7.4 From laijs at cn.fujitsu.com Wed Apr 13 05:01:50 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Wed, 13 Apr 2011 13:01:50 +0800 Subject: [libvirt] [PATCH 6/6] qemu, inject-nmi: Implement the driver methods In-Reply-To: <4DA52D1A.1000307@cn.fujitsu.com> References: <4DA52D1A.1000307@cn.fujitsu.com> Message-ID: <4DA52E3E.10402@cn.fujitsu.com> --- src/qemu/qemu_driver.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 14 ++++++++++++++ src/qemu/qemu_monitor.h | 2 ++ src/qemu/qemu_monitor_json.c | 29 +++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 1 + src/qemu/qemu_monitor_text.c | 20 ++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 1 + 7 files changed, 109 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c3ec07e..274d605 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1701,6 +1701,48 @@ static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) return qemudDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM); } +static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags) +{ + struct qemud_driver *driver = domain->conn->privateData; + virDomainObjPtr vm = NULL; + int ret = -1; + qemuDomainObjPrivatePtr priv; + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, domain->uuid); + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(domain->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; + } + + priv = vm->privateData; + + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + goto cleanup; + qemuDomainObjEnterMonitorWithDriver(driver, vm); + ret = qemuMonitorInjectNMI(priv->mon, flags); + qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjEndJob(vm) == 0) { + vm = NULL; + goto cleanup; + } + +cleanup: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); + return ret; +} + static int qemudDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 2d28f8d..de48156 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2228,3 +2228,17 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, ret = qemuMonitorTextArbitraryCommand(mon, cmd, reply); return ret; } + + +int qemuMonitorInjectNMI(qemuMonitorPtr mon, unsigned int flags) +{ + int ret; + + VIR_DEBUG("mon=%p, flags=%u", mon, flags); + + if (mon->json) + ret = qemuMonitorJSONInjectNMI(mon, flags); + else + ret = qemuMonitorTextInjectNMI(mon, flags); + return ret; +} diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c90219b..7acec43 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -423,6 +423,8 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, char **reply, bool hmp); +int qemuMonitorInjectNMI(qemuMonitorPtr mon, unsigned int flags); + /** * When running two dd process and using <> redirection, we need a * shell that will not truncate files. These two strings serve that diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 20a78e1..e980db2 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2513,3 +2513,32 @@ cleanup: return ret; } + +int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon, unsigned int flags ATTRIBUTE_UNUSED) +{ + int ret; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + + /* + * FIXME: qmp nmi is not supported until qemu-0.16.0, + * use human-monitor-command instead temporary. + * + * FIXME: qemu's nmi command just injects NMI to a specified CPU, + * use "nmi 0" instead temporary. + */ + cmd = qemuMonitorJSONMakeCommand("human-monitor-command", + "s:command-line", "nmi 0", + NULL); + if (!cmd) + return -1; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 086f0e1..7488100 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -204,4 +204,5 @@ int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon, char **reply_str, bool hmp); +int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon, unsigned int flags); #endif /* QEMU_MONITOR_JSON_H */ diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 53781c8..e28f211 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -2628,3 +2628,23 @@ int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, return ret; } + +int qemuMonitorTextInjectNMI(qemuMonitorPtr mon, unsigned int flags ATTRIBUTE_UNUSED) +{ + const char *cmd = "nmi 0"; + char *reply = NULL; + + /* + * FIXME: qemu's nmi command just injects NMI to a specified CPU, + * use "nmi 0" instead temporary. + */ + if (!qemuMonitorTextArbitraryCommand(mon, cmd, &reply)) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("failed to inject NMI using command '%s'"), + cmd); + return -1; + } + + VIR_FREE(reply); + return 0; +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 0838a2b..0f6afb9 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -198,4 +198,5 @@ int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name); int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply); +int qemuMonitorTextInjectNMI(qemuMonitorPtr mon, unsigned int flags); #endif /* QEMU_MONITOR_TEXT_H */ -- 1.7.4 From veillard at redhat.com Wed Apr 13 05:37:04 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 13 Apr 2011 13:37:04 +0800 Subject: [libvirt] Time to think about the next release 0.9.1 Message-ID: <20110413053704.GK1149@redhat.com> I think keeping with the monthly schedule for new release is a good thing considering the current amount of changes and patches being pushed. So if we plan 0.9.1 by the month end, this means entering freeze around the week-end of the 23rd, i.e. in 10 days, a rough estimate is that the new release would embed 200-250 commits which is plenty enough :-) Opinions ? Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Wed Apr 13 05:41:12 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 13 Apr 2011 13:41:12 +0800 Subject: [libvirt] [PATCH] esx: Extend VI generator to cover managed object types In-Reply-To: <20110410112756.GA13563@sbox> References: <20110410112756.GA13563@sbox> Message-ID: <20110413054112.GL1149@redhat.com> On Sun, Apr 10, 2011 at 01:27:56PM +0200, Matthias Bolte wrote: > Generate lookup functions for managed object types. > --- > src/esx/esx_vi.c | 414 +++++++++++++++++++++++----------------- > src/esx/esx_vi.h | 2 + > src/esx/esx_vi_generator.input | 28 +++- > src/esx/esx_vi_generator.py | 411 ++++++++++++++++++++++++++++++++++++++-- > src/esx/esx_vi_types.c | 349 ++++++---------------------------- > src/esx/esx_vi_types.h | 102 ++--------- > 6 files changed, 728 insertions(+), 578 deletions(-) Hum, it's a fairly big patch, and I won't pretend to fully understand it. A cursory look didn't raised any issue to me, and since you're the one managing that code, the best is for you to push it and others to make sure everything still works well, so the earlier the better :-) ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Wed Apr 13 05:43:12 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 13 Apr 2011 13:43:12 +0800 Subject: [libvirt] [PATCH] virsh: Add --name and --description options to snapshot-create In-Reply-To: <4DA33C00.6050506@redhat.com> References: <20110410113127.GA13668@sbox> <4DA33C00.6050506@redhat.com> Message-ID: <20110413054312.GM1149@redhat.com> On Mon, Apr 11, 2011 at 11:36:00AM -0600, Eric Blake wrote: > On 04/10/2011 05:31 AM, Matthias Bolte wrote: > > This options are shortcuts to set name and description of a snapshot. > > > > Suggested by Elias Probst > > --- > > > > I'm not sure if this is be best approach. In case of the vol-* commands there > > is vol-create that takes and XML file and vol-create-as that takes a set of > > arguments. > > > > So, should there actually be a snapshot-create-as to takes --name and > > --description options? > > For consistency, I would argue that we don't have any other commands > that modify direct xml input, and so we shouldn't be starting that now. > I agree that a snapshot-create-as that takes options (and builds xml > under the hood) would match with existing virsh paradigms better than > making the existing snapshot-create command modify input xml on the fly. > In other words, I'm afraid that your concern was unfortunately valid, > and that we should NACK this patch in favor of one that adds a new > command instead. Agreed ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From kadiryuceer at gmail.com Wed Apr 13 06:43:09 2011 From: kadiryuceer at gmail.com (=?ISO-8859-1?Q?kadir_y=FCceer?=) Date: Wed, 13 Apr 2011 09:43:09 +0300 Subject: [libvirt] Is there smt missing at Java bindings? In-Reply-To: References: Message-ID: Hello all, I've been posting questions about my issue to the user list but it seems nobody can answer, so I had to try this list, sorry if there is any disturbance. Here is the case: I've been trying to develop a java app that can register callbacks for domain lifecycle events(suspend,resume,etc.). Only method that I've seen is Connect.VirDomainEventRegisterAny, and there is an abstract callback method inside VirConnectDomainEventGenericCallback. I implement the callback, and register it for all the domains by passing the domain pointer as NULL. Additionally for testing, I've added a println into the suspend function in org.libvirt.Domain.java, and compiled the java bindings and used the new jar file, and I was successful, I can see the message whenever I suspend the domain either by clicking *pause* or by writing dom.suspend() in my java app. However, when I try to register a callback as I mentioned in the beginning (with eventID 0, which is life_cycle ID), after the suspend operation, I get the error that you can see at the end of the mail. But before you check it out, I have to ask, are some of the event-related features of libvirt missing in java bindings? For example; VirEventAddHandleFunc, VirEventAddHandleCallback, and their derivatives. Is this a problem or the only Connect.VirDomainEventRegisterAny method of java binding suffice for providing callbacks for domain events? Thanks in advance for your responses. The error is below. Kind Regards Kadir # # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00000000, pid=5692, tid=3077520240 # # JRE version: 6.0_20-b20 # Java VM: OpenJDK Server VM (19.0-b09 mixed mode linux-x86 ) # Derivative: IcedTea6 1.9.7 # Distribution: Ubuntu 10.10, package 6b20-1.9.7-0ubuntu1 # Problematic frame: # C 0x00000000 # # An error report file with more information is saved as: # /root/NetBeansProjects/NovaTest_v0.3/hs_err_pid5692.log # # If you would like to submit a bug report, please include # instructions how to reproduce the bug and visit: # https://bugs.launchpad.net/ubuntu/+source/openjdk-6/ # The crash happened outside the Java Virtual Machine in native code. # See problematic frame for where to report the bug. # Java Result: 134 -------------- next part -------------- An HTML attachment was scrubbed... URL: From matthias.bolte at googlemail.com Wed Apr 13 06:51:18 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Wed, 13 Apr 2011 08:51:18 +0200 Subject: [libvirt] [PATCH] - added mapping to Network object - added implementation of select networking functions - virsh net-list and net-info commands now work for esx In-Reply-To: <1302610423-19095-1-git-send-email-james.barkley@gmail.com> References: <1302610423-19095-1-git-send-email-james.barkley@gmail.com> Message-ID: Long summary line. You could reformat it like this: esx: Support virsh net-list and net-info Add mapping of Network object and implementation of select networking functions. This makes virsh net-list and net-info commands work for ESX. 2011/4/12 jbarkley : > From: jbarkely You should tell git your name and email address to get it properly recorded in a patch. See git config for this: git config --global user.name "your name" git config --global user.email "your email" > --- > ?src/esx/esx_network_driver.c ? | ?181 +++++++++++++++++++++++++++++++++++++++- > ?src/esx/esx_vi.c ? ? ? ? ? ? ? | ?104 ++++++++++++++++++++++- > ?src/esx/esx_vi.h ? ? ? ? ? ? ? | ? ?9 ++ > ?src/esx/esx_vi_generator.input | ? 78 +++++++++++++++++ > ?4 files changed, 366 insertions(+), 6 deletions(-) As I'm a bit short of time right now just some general comments. - C style comments (/* */) are preferred over C++ style ones (//). - Remove code that you have commented out. - I'm not sure if using the MD5 sum of the name of a network it's UUID is the stablest possible source. I'd like to find a better option for this, but I'm not sure that it exists. - Instead of adding many empty objects for the members of HostNetworkSystem and HostNetworkInfo that aren't used yet you could mark them as ignored (i) instead in the .input file. Overall the patch looks okay. I'll give it a detailed review and test it over the weekend. In the meantime I'd like to delay the inclusion of this patch into the codebase until we are confident that this approach is the correct one. Matthias From DUBI at il.ibm.com Wed Apr 13 06:56:04 2011 From: DUBI at il.ibm.com (Zvi Dubitzky) Date: Wed, 13 Apr 2011 09:56:04 +0300 Subject: [libvirt] virsh shutdown Message-ID: Hi For some reason recent libvirt code (0.8.3 and even before) the 'virsh shutdown ' is not effective . It issues an ok message by the domians remains in a runnning state . Only th e destroy works fine. Any idea ? Zvi Dubitzky Email:dubi at il.ibm.com From minovotn at redhat.com Wed Apr 13 07:32:32 2011 From: minovotn at redhat.com (Michal Novotny) Date: Wed, 13 Apr 2011 09:32:32 +0200 Subject: [libvirt] [libvirt-php] Fix get_xml when xpath is null In-Reply-To: <1302667839-13712-1-git-send-email-liyong@skybility.com> References: <1302667839-13712-1-git-send-email-liyong@skybility.com> Message-ID: <4DA55190.2020203@redhat.com> On 04/13/2011 06:10 AM, Lyre wrote: > Hi all: > > To my surprise, it seems that passing null to php as a string parameter, > will set the pointer which retrive it to an empty string "" , but not NULL. > get_xml_from_xpath() doesn't work correctly since an empty string is > passed as the xpath argument, and libxml will complain "Invalid expression" > > I know seldom about xpath, I'm not sure if it is the correct way to fix it. > > BTW, what xpath shall I pass to get the entire xml? > Hi Lyre, thanks for the information however I was always using the NULL value as second argument for the get_xml_desc(), like e.g.: $entire_xml = libvirt_domain_get_xml_desc($dom, NULL); My development and testing is done on Fedora 14 and php-5.3.6-1.fc14.i686 version of the package and it's working fine for me. However the patch you sent to the list seems better and it's working fine so I've pushed it to the repository right now. Just for the record, what did you mean by passing NULL to php as a string parameter? To pass as 'null' ? I'm using it the way described above and 'null' is required only for libvirt_connect() since there are some issues with passing NULL to libvirt_connect(). We still may need to fix the libvirt_connect() function, that's true. Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From minovotn at redhat.com Wed Apr 13 07:53:02 2011 From: minovotn at redhat.com (Michal Novotny) Date: Wed, 13 Apr 2011 09:53:02 +0200 Subject: [libvirt] [PATCH v2 0/5] Add TXT record and hosts support for DNS service and dnsmasq command-line regression testing In-Reply-To: <1301654756-3920-1-git-send-email-minovotn@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> Message-ID: <4DA5565E.1070401@redhat.com> Any review on this? Just found there is no reply yet. Michal On 04/01/2011 12:45 PM, Michal Novotny wrote: > Hi, > this is the patch to introduce the TXT record and DNS hosts support > for the DNS service on the virtual network. This can be defined using > the txt-record subelement in the dns element of the network XML > description. The definition of TXT record names containing spaces > is rejected with the error message that TXT record names in DNS > doesn't support spaces. > > Also, regression testing for the dnsmasq command line has been > added to test whether the dnsmasq command-line is correct or not. > > The new XML definition syntax is: > > > > > gateway > host > > > > Where multiple host elements can be defined to put the aliases > for specified IP addresses. > > The patch series has been tested for the configuration and it > was working fine and also RelaxNG schema with the tests have > been both altered to add test cases to test those patches. > > All of the patches passed the make, make check and make > syntax-check commands and it has been tested for the definition > described above and it was working fine (tested using dig for > DNS TXT record and nslookup in the guest for the DNS hosts). > > Michal > > Signed-off-by: Michal Novotny > > Michal Novotny (5): > Network: Add TXT record support for virtual DNS service > Network: Add regression tests for the command line arguments > Network: Move dnsmasqContext creation to > networkSaveDnsmasqHostsfile() and pass to dnsmasq only if > applicable > Network: Add additional hosts internal infrastructure > Network: Add support for DNS hosts definition in the network XML > > docs/formatnetwork.html.in | 31 +++- > docs/schemas/network.rng | 20 ++ > src/conf/network_conf.c | 183 ++++++++++++++ > src/conf/network_conf.h | 25 ++ > src/libvirt_private.syms | 1 + > src/network/bridge_driver.c | 103 ++++++-- > src/network/bridge_driver.h | 3 + > src/util/dnsmasq.c | 266 +++++++++++++++++++- > src/util/dnsmasq.h | 22 ++- > tests/Makefile.am | 11 + > tests/networkxml2argvdata/isolated-network.argv | 1 + > tests/networkxml2argvdata/isolated-network.xml | 11 + > .../networkxml2argvdata/nat-network-dns-hosts.argv | 1 + > .../networkxml2argvdata/nat-network-dns-hosts.xml | 19 ++ > .../nat-network-dns-txt-record.argv | 1 + > .../nat-network-dns-txt-record.xml | 24 ++ > tests/networkxml2argvdata/nat-network.argv | 1 + > tests/networkxml2argvdata/nat-network.xml | 21 ++ > tests/networkxml2argvdata/netboot-network.argv | 1 + > tests/networkxml2argvdata/netboot-network.xml | 14 + > .../networkxml2argvdata/netboot-proxy-network.argv | 1 + > .../networkxml2argvdata/netboot-proxy-network.xml | 13 + > tests/networkxml2argvdata/routed-network.argv | 1 + > tests/networkxml2argvdata/routed-network.xml | 9 + > tests/networkxml2argvtest.c | 120 +++++++++ > tests/networkxml2xmlin/nat-network-dns-hosts.xml | 27 ++ > .../nat-network-dns-txt-record.xml | 24 ++ > tests/networkxml2xmlout/nat-network-dns-hosts.xml | 27 ++ > .../nat-network-dns-txt-record.xml | 24 ++ > tests/networkxml2xmltest.c | 2 + > 30 files changed, 974 insertions(+), 33 deletions(-) > create mode 100644 tests/networkxml2argvdata/isolated-network.argv > create mode 100644 tests/networkxml2argvdata/isolated-network.xml > create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.argv > create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.xml > create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.argv > create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.xml > create mode 100644 tests/networkxml2argvdata/nat-network.argv > create mode 100644 tests/networkxml2argvdata/nat-network.xml > create mode 100644 tests/networkxml2argvdata/netboot-network.argv > create mode 100644 tests/networkxml2argvdata/netboot-network.xml > create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.argv > create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.xml > create mode 100644 tests/networkxml2argvdata/routed-network.argv > create mode 100644 tests/networkxml2argvdata/routed-network.xml > create mode 100644 tests/networkxml2argvtest.c > create mode 100644 tests/networkxml2xmlin/nat-network-dns-hosts.xml > create mode 100644 tests/networkxml2xmlin/nat-network-dns-txt-record.xml > create mode 100644 tests/networkxml2xmlout/nat-network-dns-hosts.xml > create mode 100644 tests/networkxml2xmlout/nat-network-dns-txt-record.xml > -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From liyong at skybility.com Wed Apr 13 07:50:24 2011 From: liyong at skybility.com (Lyre) Date: Wed, 13 Apr 2011 15:50:24 +0800 Subject: [libvirt] [libvirt-php] Fix get_xml when xpath is null In-Reply-To: <4DA55190.2020203@redhat.com> References: <1302667839-13712-1-git-send-email-liyong@skybility.com> <4DA55190.2020203@redhat.com> Message-ID: <4DA555C0.9020904@skybility.com> ? 2011?04?13? 15:32, Michal Novotny ??: > On 04/13/2011 06:10 AM, Lyre wrote: >> Hi all: >> >> To my surprise, it seems that passing null to php as a string parameter, >> will set the pointer which retrive it to an empty string "" , but not NULL. >> get_xml_from_xpath() doesn't work correctly since an empty string is >> passed as the xpath argument, and libxml will complain "Invalid expression" >> >> I know seldom about xpath, I'm not sure if it is the correct way to fix it. >> >> BTW, what xpath shall I pass to get the entire xml? >> > Hi Lyre, > thanks for the information however I was always using the NULL value as > second argument for the get_xml_desc(), like e.g.: > > $entire_xml = libvirt_domain_get_xml_desc($dom, NULL); > > My development and testing is done on Fedora 14 and > php-5.3.6-1.fc14.i686 version of the package and it's working fine for > me. However the patch you sent to the list seems better and it's working > fine so I've pushed it to the repository right now. > > Just for the record, what did you mean by passing NULL to php as a > string parameter? To pass as 'null' ? I'm using it the way described > above and 'null' is required only for libvirt_connect() since there are > some issues with passing NULL to libvirt_connect(). We still may need to > fix the libvirt_connect() function, that's true. > > Michal > Hi Michal: I'm testing it on sles 11 sp1 with php 5.2.6. Let's take libvirt_domains_get_xml_desc as an example: when I called $entire_xml = libvirt_domain_get_xml_desc($dom, NULL); In the C code: PHP_FUNCTION(libvirt_domain_get_xml_desc) { char *xpath = NULL; int xpath_len; /* ... */ GET_DOMAIN_FROM_ARGS("rs|l",&zdomain,&xpath,&xpath_len,&flags); /* other stuff */ } After fetching arguments, xpath point to an empty string "". So that it was not NULL anymore. That's strange, or maybe I have misunderstood the argument passing mechanism. From minovotn at redhat.com Wed Apr 13 08:00:04 2011 From: minovotn at redhat.com (Michal Novotny) Date: Wed, 13 Apr 2011 10:00:04 +0200 Subject: [libvirt] [libvirt-php] Fix get_xml when xpath is null In-Reply-To: <4DA555C0.9020904@skybility.com> References: <1302667839-13712-1-git-send-email-liyong@skybility.com> <4DA55190.2020203@redhat.com> <4DA555C0.9020904@skybility.com> Message-ID: <4DA55804.6020409@redhat.com> On 04/13/2011 09:50 AM, Lyre wrote: > ? 2011?04?13? 15:32, Michal Novotny ??: >> On 04/13/2011 06:10 AM, Lyre wrote: >>> Hi all: >>> >>> To my surprise, it seems that passing null to php as a string parameter, >>> will set the pointer which retrive it to an empty string "" , but not NULL. >>> get_xml_from_xpath() doesn't work correctly since an empty string is >>> passed as the xpath argument, and libxml will complain "Invalid expression" >>> >>> I know seldom about xpath, I'm not sure if it is the correct way to fix it. >>> >>> BTW, what xpath shall I pass to get the entire xml? >>> >> Hi Lyre, >> thanks for the information however I was always using the NULL value as >> second argument for the get_xml_desc(), like e.g.: >> >> $entire_xml = libvirt_domain_get_xml_desc($dom, NULL); >> >> My development and testing is done on Fedora 14 and >> php-5.3.6-1.fc14.i686 version of the package and it's working fine for >> me. However the patch you sent to the list seems better and it's working >> fine so I've pushed it to the repository right now. >> >> Just for the record, what did you mean by passing NULL to php as a >> string parameter? To pass as 'null' ? I'm using it the way described >> above and 'null' is required only for libvirt_connect() since there are >> some issues with passing NULL to libvirt_connect(). We still may need to >> fix the libvirt_connect() function, that's true. >> >> Michal >> > Hi Michal: > > I'm testing it on sles 11 sp1 with php 5.2.6. > > Let's take libvirt_domains_get_xml_desc as an example: > > when I called $entire_xml = libvirt_domain_get_xml_desc($dom, NULL); > > In the C code: > > PHP_FUNCTION(libvirt_domain_get_xml_desc) > { > char *xpath = NULL; > int xpath_len; > /* ... */ > > GET_DOMAIN_FROM_ARGS("rs|l",&zdomain,&xpath,&xpath_len,&flags); > > /* other stuff */ > } > > After fetching arguments, xpath point to an empty string "". So that it > was not NULL anymore. > > That's strange, or maybe I have misunderstood the argument passing > mechanism. > > Hi Lyre, I can see your point and since you're having different version of php it's possible the version I'm having had a bug that xpath was not empty string. I guess passing mechanism could change in next versions of PHP so I'm not saying that it's bad or anything. I'm just saying I didn't run into those issues myself but since your patch fixes the issue for you and it didn't break anything on my setup, then I guess it's good and I pushed it to the repository already. Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From atodorov at otb.bg Wed Apr 13 08:15:02 2011 From: atodorov at otb.bg (Alexander Todorov) Date: Wed, 13 Apr 2011 11:15:02 +0300 Subject: [libvirt] [PATCH] implement BOOT_TIMEOUT Message-ID: <1302682502-4967-1-git-send-email-atodorov@otb.bg> --- tools/libvirt-guests.init.sh | 2 ++ tools/libvirt-guests.sysconf | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) diff --git a/tools/libvirt-guests.init.sh b/tools/libvirt-guests.init.sh index f247e5e..b462ea8 100644 --- a/tools/libvirt-guests.init.sh +++ b/tools/libvirt-guests.init.sh @@ -42,6 +42,7 @@ URIS=default ON_BOOT=start ON_SHUTDOWN=suspend SHUTDOWN_TIMEOUT=0 +BOOT_TIMEOUT=0 test -f "$sysconfdir"/sysconfig/libvirt-guests && . "$sysconfdir"/sysconfig/libvirt-guests @@ -166,6 +167,7 @@ start() { gettext "already active"; echo else retval run_virsh "$uri" start "$name" >/dev/null && \ + sleep $BOOT_TIMEOUT && \ gettext "done"; echo fi fi diff --git a/tools/libvirt-guests.sysconf b/tools/libvirt-guests.sysconf index cd58728..e970a00 100644 --- a/tools/libvirt-guests.sysconf +++ b/tools/libvirt-guests.sysconf @@ -10,6 +10,9 @@ # libvirtd #ON_BOOT=start +# number of seconds to wait before starting the next guest +#BOOT_TIMEOUT=0 + # action taken on host shutdown # - suspend all running guests are suspended using virsh managedsave # - shutdown all running guests are asked to shutdown. Please be careful with -- 1.7.1 From atodorov at otb.bg Wed Apr 13 08:16:19 2011 From: atodorov at otb.bg (Alexander Todorov) Date: Wed, 13 Apr 2011 11:16:19 +0300 Subject: [libvirt] [PATCH] implement BOOT_TIMEOUT In-Reply-To: <1302682502-4967-1-git-send-email-atodorov@otb.bg> References: <1302682502-4967-1-git-send-email-atodorov@otb.bg> Message-ID: <4DA55BD3.6080908@otb.bg> Sorry for top posing. This is https://bugzilla.redhat.com/show_bug.cgi?id=695653. Was filed first in Bugzilla because the mailing list wasn't accessible yesterday. ?? 13.04.2011 11:15, Alexander Todorov ??????: > --- > tools/libvirt-guests.init.sh | 2 ++ > tools/libvirt-guests.sysconf | 3 +++ > 2 files changed, 5 insertions(+), 0 deletions(-) > > diff --git a/tools/libvirt-guests.init.sh b/tools/libvirt-guests.init.sh > index f247e5e..b462ea8 100644 > --- a/tools/libvirt-guests.init.sh > +++ b/tools/libvirt-guests.init.sh > @@ -42,6 +42,7 @@ URIS=default > ON_BOOT=start > ON_SHUTDOWN=suspend > SHUTDOWN_TIMEOUT=0 > +BOOT_TIMEOUT=0 > > test -f "$sysconfdir"/sysconfig/libvirt-guests&& > . "$sysconfdir"/sysconfig/libvirt-guests > @@ -166,6 +167,7 @@ start() { > gettext "already active"; echo > else > retval run_virsh "$uri" start "$name">/dev/null&& \ > + sleep $BOOT_TIMEOUT&& \ > gettext "done"; echo > fi > fi > diff --git a/tools/libvirt-guests.sysconf b/tools/libvirt-guests.sysconf > index cd58728..e970a00 100644 > --- a/tools/libvirt-guests.sysconf > +++ b/tools/libvirt-guests.sysconf > @@ -10,6 +10,9 @@ > # libvirtd > #ON_BOOT=start > > +# number of seconds to wait before starting the next guest > +#BOOT_TIMEOUT=0 > + > # action taken on host shutdown > # - suspend all running guests are suspended using virsh managedsave > # - shutdown all running guests are asked to shutdown. Please be careful with -- ???. ?????????? ??????? - RHCE, RHCVA, RHCI ???????? ?????????? ???????? ???? - Red Hat Ready Business Partner www.otb.bg/sumu From minovotn at redhat.com Wed Apr 13 08:36:24 2011 From: minovotn at redhat.com (Michal Novotny) Date: Wed, 13 Apr 2011 10:36:24 +0200 Subject: [libvirt] Regression in allocating ports for serial/parallel devs In-Reply-To: <4D9B43C0.6060003@redhat.com> References: <4D9B3FAB.8090205@redhat.com> <4D9B40A5.60407@redhat.com> <4D9B43C0.6060003@redhat.com> Message-ID: <4DA56088.5030906@redhat.com> On 04/05/2011 06:30 PM, Cole Robinson wrote: > On 04/05/2011 12:17 PM, Michal Novotny wrote: >> On 04/05/2011 06:13 PM, Cole Robinson wrote: >>> Hi Michal, >>> >>> The following commit introduced a regression: >>> >>> http://libvirt.org/git/?p=libvirt.git;a=commit;h=79c3fe4d1681cd94598d2bd42e38a98f51cb645d >>> >>> Now, defining a guest with XML like >>> >>> >>> >>> >>> >>> Will allocate to all 3. The reason is that >>> target.port is never set to -1 unless the user specified some >>> XML. A simple fix is: >>> >>> --- a/src/conf/domain_conf.c >>> +++ b/src/conf/domain_conf.c >>> @@ -3265,6 +3265,8 @@ virDomainChrDefParseXML(virCapsPtr caps, >>> return NULL; >>> } >>> >>> + def->target.port = -1; >>> + >>> type = virXMLPropString(node, "type"); >>> if (type == NULL) { >>> def->source.type = VIR_DOMAIN_CHR_TYPE_PTY; >>> >>> But that doesn't solve the problem for users who are building ChrDef's >>> by hand, like when converting between formats as xen and vmware drivers >>> do. I didn't look at those users so they may be safe, but the interface >>> should be improved. Maybe add a ChrDefNew function that sets the -1 default. >>> >>> Additionally we should add a qemuxml2xml test for this to prevent >>> against future regressions. >>> >>> Thanks, >>> Cole >> Hi Cole, >> do you think it's worth implementing the ChrDefNew besides the ChrDef >> which we already have? >> > ChrDefNew would be a constructor function, that would return an > allocated ChrDefPtr. In fact I'd argue we should have these constructors > for every device type, some others definitely need it at the moment > (like controller which uses a similar -1 default). > >> There's a regression testing but maybe it's not for qemuxml2xml test. >> > Not sure I understand this sentence, but qemuxml2xml test is for round > trip XML testing, which is what is needed here. There is already a > couple examples where the round trip XML is expected to change, see for > example > > tests/qemuxml2xmltest.c > tests/qemuxml2argvdata/qemuxml2argv-console-compat-auto.xml > tests/qemuxml2xmloutdata/qemuxml2xmlout-console-compat-auto.xml > > Thanks, > Cole I'm sorry for the delay to get to this and I've been thinking about what you wrote and I'm still not sure how exactly it should work. Based on the virDomainChrDefParseXML() function there's: if (VIR_ALLOC(def) < 0) { virReportOOMError(); return NULL; } used for the allocation of the virDomainChrDefPtr (since it's declared as "virDomainChrDefPtr def") so basically just adding: def->target.port = -1; below those lines would be sufficient, won't it ? Or do you prefer having some function like virChrDefNew declared as: static virDomainChrDefPtr virChrDefNew() { virDomainChrDefPtr def; if (VIR_ALLOC(def) < 0) { virReportOOMError(); return NULL; } def->target.port = -1; return def; } or something similar to this ? Thanks, Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From wency at cn.fujitsu.com Wed Apr 13 09:22:27 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 13 Apr 2011 17:22:27 +0800 Subject: [libvirt] [PATCHv9 0/4] persistent device modification for qemu In-Reply-To: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> References: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4DA56B53.8000607@cn.fujitsu.com> At 04/13/2011 10:47 AM, KAMEZAWA Hiroyuki Write: > > Updated against the latest git tree, no major changes since a week ago. > Thank you for reviews in previous ones. > > Purpose of patches: > Now, virsh at(de)tach-device/disk/...etc.. doesn't support to update > inactive domain's definition even with the --persistent flag. > To update persistent modification of inactive domains, we have to use > virsh edit. > > So, if we want to update inactive domain definition with scripts, we need to > use other command/libs than libvirt. I'd like to use libvirt/virsh in scripts. > This patches adds to support for updating domain definition via virsh with > scripts. This series just includes 'disk' updates but I'll add more. This series patches look good to me. Eric, will you have some time to have a review on this? > > Thanks, > -Kame > > From james.barkley at gmail.com Wed Apr 13 10:45:41 2011 From: james.barkley at gmail.com (James Barkley) Date: Wed, 13 Apr 2011 06:45:41 -0400 Subject: [libvirt] [PATCH] - added mapping to Network object - added implementation of select networking functions - virsh net-list and net-info commands now work for esx In-Reply-To: References: <1302610423-19095-1-git-send-email-james.barkley@gmail.com> Message-ID: On Wed, Apr 13, 2011 at 2:51 AM, Matthias Bolte < matthias.bolte at googlemail.com> wrote: > Long summary line. You could reformat it like this: > > > esx: Support virsh net-list and net-info > > Add mapping of Network object and implementation of select > networking functions. > > This makes virsh net-list and net-info commands work for ESX. > > Right, can do. I didn't realize it was just taking the commit message and stuffing it into the subject line. > > 2011/4/12 jbarkley : > > From: jbarkely > > You should tell git your name and email address to get it properly > recorded in a patch. See git config for this: > > git config --global user.name "your name" > git config --global user.email "your email" > whoops - thought I had done that. > > > --- > > src/esx/esx_network_driver.c | 181 > +++++++++++++++++++++++++++++++++++++++- > > src/esx/esx_vi.c | 104 ++++++++++++++++++++++- > > src/esx/esx_vi.h | 9 ++ > > src/esx/esx_vi_generator.input | 78 +++++++++++++++++ > > 4 files changed, 366 insertions(+), 6 deletions(-) > > As I'm a bit short of time right now just some general comments. > > - C style comments (/* */) are preferred over C++ style ones (//). > Noted > - Remove code that you have commented out. > Got it > - I'm not sure if using the MD5 sum of the name of a network it's UUID is the stablest possible source. I'd like to find a better option for > this, but I'm not sure that it exists. > Agreed - this was a hack placeholder to get *something* in place for the UUID. But a hash of the network name won't be UU, but just U since different hosts can have networks with the same name (and in fact do by default with ESX - the "VM Network"). Not sure if there is a better alternative, but I'll keep looking. > - Instead of adding many empty objects for the members of > HostNetworkSystem and HostNetworkInfo that aren't used yet you could > mark them as ignored (i) instead in the .input file. > Cool - didn't realize I could do this. > > Overall the patch looks okay. I'll give it a detailed review and test > it over the weekend. > > In the meantime I'd like to delay the inclusion of this patch into the > codebase until we are confident that this approach is the correct one. > > Sure - whenever you're comfortable. I needed the functionality for some software we're building so we're using the added functionality now. I just thought it'd be nice to give you a chance to add it back in. Let me know how your in-depth review turns out - in the meantime I may clean up the other things you mentioned (comments, ignore marks, etc.). I doubt I'll get to the functionality for adding a network for another week or even two, but I'll let you know how that goes. > Matthias > Thanks for taking the time -jb -------------- next part -------------- An HTML attachment was scrubbed... URL: From berrange at redhat.com Wed Apr 13 11:15:32 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 13 Apr 2011 12:15:32 +0100 Subject: [libvirt] [PATCH] util: Simplify hash implementation In-Reply-To: References: Message-ID: <20110413111532.GB18468@redhat.com> On Tue, Apr 12, 2011 at 06:54:33PM +0200, Jiri Denemark wrote: > So far first entries for each hash key are stored directly in the hash > table while other entries mapped to the same key are linked through > pointers. As a result of that, the code is cluttered with special > handling for the first items. > > Commit 9677cd33eea4c65d78ba463b46b8b45ed2da1709 made it possible to > remove current entry when iterating through all hash entries. However, > it didn't add the special first item handling which could cause libvirtd > crash or hang. This highlights what should be an obvious problem.... we have near zero test coverage of the hash table class. The code is totally standalone and it should be easy to write a test case to exercise all its methods, and many of the edge cases. IMHO we should fix the lack of a test suite before refactoring it again, so that we know we're actually get it right this time :-) Both the existing code & your new patch are complex enough, that I'm not confident in code review alone identifying all the bugs. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Wed Apr 13 11:28:49 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 13 Apr 2011 12:28:49 +0100 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <4DA4DC52.8010509@redhat.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com> <1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> Message-ID: <20110413112849.GE18468@redhat.com> On Tue, Apr 12, 2011 at 05:12:18PM -0600, Eric Blake wrote: > On 02/09/2011 09:58 AM, Daniel P. Berrange wrote: > > This patch attempts to introduce a version 3 that uses the > > improved 5 step sequence > > > > * Src: Begin > > - Generate XML to pass to dst > > - Generate optional cookie to pass to dst > > > > * Dst: Prepare > > - Get ready to accept incoming VM > > - Generate optional cookie to pass to src > > > > * Src: Perform > > - Start migration and wait for send completion > > - Generate optional cookie to pass to dst > > > > * Dst: Finish > > - Wait for recv completion and check status > > - Kill off VM if failed, resume if success > > - Generate optional cookie to pass to src > > > > * Src: Confirm > > - Kill off VM if success, resume if failed > > I've been thinking about this a bit more, and have a question. What > happens when the source side decides to abort the migration? For > example, if libvirtd on the source gets a SIGHUP or SIGINT, it would be > nice to have the cleanup code abort any in-flight migrations so that > when libvirtd is restarted, the guest is still operational on the > source, and the guest does not have to wait for a full TCP timeout cycle > to realize that the source is not going to complete the migration. > > Does this call for additional internal points in the RPC implementation > of v3 migration? The source can already abort migration, even in the v2 protocol, using the virDomainJobAbort() API (or virsh domjobabort). This issues a 'migrate_cancel' monitor command to QEMU, which in turns causes the 'perform' step to return failure, which is passed to the 'finish' step which tears down the destination VM Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From crobinso at redhat.com Wed Apr 13 12:21:59 2011 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 13 Apr 2011 08:21:59 -0400 Subject: [libvirt] Regression in allocating ports for serial/parallel devs In-Reply-To: <4DA56088.5030906@redhat.com> References: <4D9B3FAB.8090205@redhat.com> <4D9B40A5.60407@redhat.com> <4D9B43C0.6060003@redhat.com> <4DA56088.5030906@redhat.com> Message-ID: <4DA59567.60302@redhat.com> On 04/13/2011 04:36 AM, Michal Novotny wrote: > On 04/05/2011 06:30 PM, Cole Robinson wrote: >> On 04/05/2011 12:17 PM, Michal Novotny wrote: >>> On 04/05/2011 06:13 PM, Cole Robinson wrote: >>>> Hi Michal, >>>> >>>> The following commit introduced a regression: >>>> >>>> http://libvirt.org/git/?p=libvirt.git;a=commit;h=79c3fe4d1681cd94598d2bd42e38a98f51cb645d >>>> >>>> Now, defining a guest with XML like >>>> >>>> >>>> >>>> >>>> >>>> Will allocate to all 3. The reason is that >>>> target.port is never set to -1 unless the user specified some >>>> XML. A simple fix is: >>>> >>>> --- a/src/conf/domain_conf.c >>>> +++ b/src/conf/domain_conf.c >>>> @@ -3265,6 +3265,8 @@ virDomainChrDefParseXML(virCapsPtr caps, >>>> return NULL; >>>> } >>>> >>>> + def->target.port = -1; >>>> + >>>> type = virXMLPropString(node, "type"); >>>> if (type == NULL) { >>>> def->source.type = VIR_DOMAIN_CHR_TYPE_PTY; >>>> >>>> But that doesn't solve the problem for users who are building ChrDef's >>>> by hand, like when converting between formats as xen and vmware drivers >>>> do. I didn't look at those users so they may be safe, but the interface >>>> should be improved. Maybe add a ChrDefNew function that sets the -1 default. >>>> >>>> Additionally we should add a qemuxml2xml test for this to prevent >>>> against future regressions. >>>> >>>> Thanks, >>>> Cole >>> Hi Cole, >>> do you think it's worth implementing the ChrDefNew besides the ChrDef >>> which we already have? >>> >> ChrDefNew would be a constructor function, that would return an >> allocated ChrDefPtr. In fact I'd argue we should have these constructors >> for every device type, some others definitely need it at the moment >> (like controller which uses a similar -1 default). >> >>> There's a regression testing but maybe it's not for qemuxml2xml test. >>> >> Not sure I understand this sentence, but qemuxml2xml test is for round >> trip XML testing, which is what is needed here. There is already a >> couple examples where the round trip XML is expected to change, see for >> example >> >> tests/qemuxml2xmltest.c >> tests/qemuxml2argvdata/qemuxml2argv-console-compat-auto.xml >> tests/qemuxml2xmloutdata/qemuxml2xmlout-console-compat-auto.xml >> >> Thanks, >> Cole > I'm sorry for the delay to get to this and I've been thinking about what > you wrote and I'm still not sure how exactly it should work. Based on > the virDomainChrDefParseXML() function there's: > > if (VIR_ALLOC(def) < 0) { > virReportOOMError(); > return NULL; > } > > used for the allocation of the virDomainChrDefPtr (since it's declared > as "virDomainChrDefPtr def") so basically just adding: > > def->target.port = -1; > > below those lines would be sufficient, won't it ? Or do you prefer > having some function like virChrDefNew declared as: > > static virDomainChrDefPtr > virChrDefNew() { > virDomainChrDefPtr def; > > if (VIR_ALLOC(def) < 0) { > virReportOOMError(); > return NULL; > } > > def->target.port = -1; > return def; > } > That is basically the function I was envisioning, but I don't think it should be static, since there are users outside domain_conf who populate ChrDefPtr (xen and vmware at least). - Cole From minovotn at redhat.com Wed Apr 13 12:44:20 2011 From: minovotn at redhat.com (Michal Novotny) Date: Wed, 13 Apr 2011 14:44:20 +0200 Subject: [libvirt] Regression in allocating ports for serial/parallel devs In-Reply-To: <4DA59567.60302@redhat.com> References: <4D9B3FAB.8090205@redhat.com> <4D9B40A5.60407@redhat.com> <4D9B43C0.6060003@redhat.com> <4DA56088.5030906@redhat.com> <4DA59567.60302@redhat.com> Message-ID: <4DA59AA4.4050804@redhat.com> On 04/13/2011 02:21 PM, Cole Robinson wrote: > On 04/13/2011 04:36 AM, Michal Novotny wrote: >> On 04/05/2011 06:30 PM, Cole Robinson wrote: >>> On 04/05/2011 12:17 PM, Michal Novotny wrote: >>>> On 04/05/2011 06:13 PM, Cole Robinson wrote: >>>>> Hi Michal, >>>>> >>>>> The following commit introduced a regression: >>>>> >>>>> http://libvirt.org/git/?p=libvirt.git;a=commit;h=79c3fe4d1681cd94598d2bd42e38a98f51cb645d >>>>> >>>>> Now, defining a guest with XML like >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> Will allocate to all 3. The reason is that >>>>> target.port is never set to -1 unless the user specified some >>>>> XML. A simple fix is: >>>>> >>>>> --- a/src/conf/domain_conf.c >>>>> +++ b/src/conf/domain_conf.c >>>>> @@ -3265,6 +3265,8 @@ virDomainChrDefParseXML(virCapsPtr caps, >>>>> return NULL; >>>>> } >>>>> >>>>> + def->target.port = -1; >>>>> + >>>>> type = virXMLPropString(node, "type"); >>>>> if (type == NULL) { >>>>> def->source.type = VIR_DOMAIN_CHR_TYPE_PTY; >>>>> >>>>> But that doesn't solve the problem for users who are building ChrDef's >>>>> by hand, like when converting between formats as xen and vmware drivers >>>>> do. I didn't look at those users so they may be safe, but the interface >>>>> should be improved. Maybe add a ChrDefNew function that sets the -1 default. >>>>> >>>>> Additionally we should add a qemuxml2xml test for this to prevent >>>>> against future regressions. >>>>> >>>>> Thanks, >>>>> Cole >>>> Hi Cole, >>>> do you think it's worth implementing the ChrDefNew besides the ChrDef >>>> which we already have? >>>> >>> ChrDefNew would be a constructor function, that would return an >>> allocated ChrDefPtr. In fact I'd argue we should have these constructors >>> for every device type, some others definitely need it at the moment >>> (like controller which uses a similar -1 default). >>> >>>> There's a regression testing but maybe it's not for qemuxml2xml test. >>>> >>> Not sure I understand this sentence, but qemuxml2xml test is for round >>> trip XML testing, which is what is needed here. There is already a >>> couple examples where the round trip XML is expected to change, see for >>> example >>> >>> tests/qemuxml2xmltest.c >>> tests/qemuxml2argvdata/qemuxml2argv-console-compat-auto.xml >>> tests/qemuxml2xmloutdata/qemuxml2xmlout-console-compat-auto.xml >>> >>> Thanks, >>> Cole >> I'm sorry for the delay to get to this and I've been thinking about what >> you wrote and I'm still not sure how exactly it should work. Based on >> the virDomainChrDefParseXML() function there's: >> >> if (VIR_ALLOC(def) < 0) { >> virReportOOMError(); >> return NULL; >> } >> >> used for the allocation of the virDomainChrDefPtr (since it's declared >> as "virDomainChrDefPtr def") so basically just adding: >> >> def->target.port = -1; >> >> below those lines would be sufficient, won't it ? Or do you prefer >> having some function like virChrDefNew declared as: >> >> static virDomainChrDefPtr >> virChrDefNew() { >> virDomainChrDefPtr def; >> >> if (VIR_ALLOC(def) < 0) { >> virReportOOMError(); >> return NULL; >> } >> >> def->target.port = -1; >> return def; >> } >> > That is basically the function I was envisioning, but I don't think it should > be static, since there are users outside domain_conf who populate ChrDefPtr > (xen and vmware at least). > > - Cole So do you think I should introduce the function I mentioned and use it instead of VIR_ALLOC(def) calls? Thanks, Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From crobinso at redhat.com Wed Apr 13 12:46:37 2011 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 13 Apr 2011 08:46:37 -0400 Subject: [libvirt] Regression in allocating ports for serial/parallel devs In-Reply-To: <4DA59AA4.4050804@redhat.com> References: <4D9B3FAB.8090205@redhat.com> <4D9B40A5.60407@redhat.com> <4D9B43C0.6060003@redhat.com> <4DA56088.5030906@redhat.com> <4DA59567.60302@redhat.com> <4DA59AA4.4050804@redhat.com> Message-ID: <4DA59B2D.9050606@redhat.com> On 04/13/2011 08:44 AM, Michal Novotny wrote: > On 04/13/2011 02:21 PM, Cole Robinson wrote: >> On 04/13/2011 04:36 AM, Michal Novotny wrote: >>> On 04/05/2011 06:30 PM, Cole Robinson wrote: >>>> On 04/05/2011 12:17 PM, Michal Novotny wrote: >>>>> On 04/05/2011 06:13 PM, Cole Robinson wrote: >>>>>> Hi Michal, >>>>>> >>>>>> The following commit introduced a regression: >>>>>> >>>>>> http://libvirt.org/git/?p=libvirt.git;a=commit;h=79c3fe4d1681cd94598d2bd42e38a98f51cb645d >>>>>> >>>>>> Now, defining a guest with XML like >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> Will allocate to all 3. The reason is that >>>>>> target.port is never set to -1 unless the user specified some >>>>>> XML. A simple fix is: >>>>>> >>>>>> --- a/src/conf/domain_conf.c >>>>>> +++ b/src/conf/domain_conf.c >>>>>> @@ -3265,6 +3265,8 @@ virDomainChrDefParseXML(virCapsPtr caps, >>>>>> return NULL; >>>>>> } >>>>>> >>>>>> + def->target.port = -1; >>>>>> + >>>>>> type = virXMLPropString(node, "type"); >>>>>> if (type == NULL) { >>>>>> def->source.type = VIR_DOMAIN_CHR_TYPE_PTY; >>>>>> >>>>>> But that doesn't solve the problem for users who are building ChrDef's >>>>>> by hand, like when converting between formats as xen and vmware drivers >>>>>> do. I didn't look at those users so they may be safe, but the interface >>>>>> should be improved. Maybe add a ChrDefNew function that sets the -1 default. >>>>>> >>>>>> Additionally we should add a qemuxml2xml test for this to prevent >>>>>> against future regressions. >>>>>> >>>>>> Thanks, >>>>>> Cole >>>>> Hi Cole, >>>>> do you think it's worth implementing the ChrDefNew besides the ChrDef >>>>> which we already have? >>>>> >>>> ChrDefNew would be a constructor function, that would return an >>>> allocated ChrDefPtr. In fact I'd argue we should have these constructors >>>> for every device type, some others definitely need it at the moment >>>> (like controller which uses a similar -1 default). >>>> >>>>> There's a regression testing but maybe it's not for qemuxml2xml test. >>>>> >>>> Not sure I understand this sentence, but qemuxml2xml test is for round >>>> trip XML testing, which is what is needed here. There is already a >>>> couple examples where the round trip XML is expected to change, see for >>>> example >>>> >>>> tests/qemuxml2xmltest.c >>>> tests/qemuxml2argvdata/qemuxml2argv-console-compat-auto.xml >>>> tests/qemuxml2xmloutdata/qemuxml2xmlout-console-compat-auto.xml >>>> >>>> Thanks, >>>> Cole >>> I'm sorry for the delay to get to this and I've been thinking about what >>> you wrote and I'm still not sure how exactly it should work. Based on >>> the virDomainChrDefParseXML() function there's: >>> >>> if (VIR_ALLOC(def) < 0) { >>> virReportOOMError(); >>> return NULL; >>> } >>> >>> used for the allocation of the virDomainChrDefPtr (since it's declared >>> as "virDomainChrDefPtr def") so basically just adding: >>> >>> def->target.port = -1; >>> >>> below those lines would be sufficient, won't it ? Or do you prefer >>> having some function like virChrDefNew declared as: >>> >>> static virDomainChrDefPtr >>> virChrDefNew() { >>> virDomainChrDefPtr def; >>> >>> if (VIR_ALLOC(def) < 0) { >>> virReportOOMError(); >>> return NULL; >>> } >>> >>> def->target.port = -1; >>> return def; >>> } >>> >> That is basically the function I was envisioning, but I don't think it should >> be static, since there are users outside domain_conf who populate ChrDefPtr >> (xen and vmware at least). >> >> - Cole > So do you think I should introduce the function I mentioned and use it > instead of VIR_ALLOC(def) calls? > Yes, that's correct. Thanks, Cole From minovotn at redhat.com Wed Apr 13 12:47:24 2011 From: minovotn at redhat.com (Michal Novotny) Date: Wed, 13 Apr 2011 14:47:24 +0200 Subject: [libvirt] Regression in allocating ports for serial/parallel devs In-Reply-To: <4DA59B2D.9050606@redhat.com> References: <4D9B3FAB.8090205@redhat.com> <4D9B40A5.60407@redhat.com> <4D9B43C0.6060003@redhat.com> <4DA56088.5030906@redhat.com> <4DA59567.60302@redhat.com> <4DA59AA4.4050804@redhat.com> <4DA59B2D.9050606@redhat.com> Message-ID: <4DA59B5C.7090906@redhat.com> On 04/13/2011 02:46 PM, Cole Robinson wrote: > On 04/13/2011 08:44 AM, Michal Novotny wrote: >> On 04/13/2011 02:21 PM, Cole Robinson wrote: >>> On 04/13/2011 04:36 AM, Michal Novotny wrote: >>>> On 04/05/2011 06:30 PM, Cole Robinson wrote: >>>>> On 04/05/2011 12:17 PM, Michal Novotny wrote: >>>>>> On 04/05/2011 06:13 PM, Cole Robinson wrote: >>>>>>> Hi Michal, >>>>>>> >>>>>>> The following commit introduced a regression: >>>>>>> >>>>>>> http://libvirt.org/git/?p=libvirt.git;a=commit;h=79c3fe4d1681cd94598d2bd42e38a98f51cb645d >>>>>>> >>>>>>> Now, defining a guest with XML like >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> Will allocate to all 3. The reason is that >>>>>>> target.port is never set to -1 unless the user specified some >>>>>>> XML. A simple fix is: >>>>>>> >>>>>>> --- a/src/conf/domain_conf.c >>>>>>> +++ b/src/conf/domain_conf.c >>>>>>> @@ -3265,6 +3265,8 @@ virDomainChrDefParseXML(virCapsPtr caps, >>>>>>> return NULL; >>>>>>> } >>>>>>> >>>>>>> + def->target.port = -1; >>>>>>> + >>>>>>> type = virXMLPropString(node, "type"); >>>>>>> if (type == NULL) { >>>>>>> def->source.type = VIR_DOMAIN_CHR_TYPE_PTY; >>>>>>> >>>>>>> But that doesn't solve the problem for users who are building ChrDef's >>>>>>> by hand, like when converting between formats as xen and vmware drivers >>>>>>> do. I didn't look at those users so they may be safe, but the interface >>>>>>> should be improved. Maybe add a ChrDefNew function that sets the -1 default. >>>>>>> >>>>>>> Additionally we should add a qemuxml2xml test for this to prevent >>>>>>> against future regressions. >>>>>>> >>>>>>> Thanks, >>>>>>> Cole >>>>>> Hi Cole, >>>>>> do you think it's worth implementing the ChrDefNew besides the ChrDef >>>>>> which we already have? >>>>>> >>>>> ChrDefNew would be a constructor function, that would return an >>>>> allocated ChrDefPtr. In fact I'd argue we should have these constructors >>>>> for every device type, some others definitely need it at the moment >>>>> (like controller which uses a similar -1 default). >>>>> >>>>>> There's a regression testing but maybe it's not for qemuxml2xml test. >>>>>> >>>>> Not sure I understand this sentence, but qemuxml2xml test is for round >>>>> trip XML testing, which is what is needed here. There is already a >>>>> couple examples where the round trip XML is expected to change, see for >>>>> example >>>>> >>>>> tests/qemuxml2xmltest.c >>>>> tests/qemuxml2argvdata/qemuxml2argv-console-compat-auto.xml >>>>> tests/qemuxml2xmloutdata/qemuxml2xmlout-console-compat-auto.xml >>>>> >>>>> Thanks, >>>>> Cole >>>> I'm sorry for the delay to get to this and I've been thinking about what >>>> you wrote and I'm still not sure how exactly it should work. Based on >>>> the virDomainChrDefParseXML() function there's: >>>> >>>> if (VIR_ALLOC(def) < 0) { >>>> virReportOOMError(); >>>> return NULL; >>>> } >>>> >>>> used for the allocation of the virDomainChrDefPtr (since it's declared >>>> as "virDomainChrDefPtr def") so basically just adding: >>>> >>>> def->target.port = -1; >>>> >>>> below those lines would be sufficient, won't it ? Or do you prefer >>>> having some function like virChrDefNew declared as: >>>> >>>> static virDomainChrDefPtr >>>> virChrDefNew() { >>>> virDomainChrDefPtr def; >>>> >>>> if (VIR_ALLOC(def) < 0) { >>>> virReportOOMError(); >>>> return NULL; >>>> } >>>> >>>> def->target.port = -1; >>>> return def; >>>> } >>>> >>> That is basically the function I was envisioning, but I don't think it should >>> be static, since there are users outside domain_conf who populate ChrDefPtr >>> (xen and vmware at least). >>> >>> - Cole >> So do you think I should introduce the function I mentioned and use it >> instead of VIR_ALLOC(def) calls? >> > Yes, that's correct. > > Thanks, > Cole Ok, I understand. I'll write the patch for this today. Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From laine at laine.org Wed Apr 13 14:19:56 2011 From: laine at laine.org (Laine Stump) Date: Wed, 13 Apr 2011 10:19:56 -0400 Subject: [libvirt] RFC: disconnecting guest/domain interface config from host config (aka migration with macvtap) In-Reply-To: <4DA47A44.8040307@laine.org> References: <4DA47A44.8040307@laine.org> Message-ID: <4DA5B10C.8070400@laine.org> On 04/12/2011 12:13 PM, Laine Stump wrote: > Abstraction of guest <--> host network connection in libvirt > ===================================== Here is a response that was posted in the tracking bug report (https://bugzilla.redhat.com/show_bug.cgi?id=643947). I'm transferring it to here and replying to keep the discussion in one place: Martin Wilck writes: > I notice that this RFE doesn't mention openvswitch at all. Wouldn't that offer > all you need, and even more, if there was a plugin for configuring openvswitch > in libvirt? Perhaps having "vSwitch" in the title of this bug is confusing things... openvswitch is an alternative to using a 1) linux host bridge, 2) a libvirt virtual network (which is also a host bridge in disguise) or 3) a direct connection to an interface. It is *not*, as far as I understand, something that could/should be used together with any of those, but *instead of* them. There are libvirt users who are using macvtap for direct connection between guests and the host network interface device 1) for performance reasons, and 2) because libvirt's macvtap support also has support for physical switches that have vepa and vnlink - in these modes all traffic to/from a guest is mandated to travel through the physical switch, even if it ends up hairpinning back to the same host. This allows the admin of the physical switch to enforce rules about type of traffic, QoS, etc. openvswitch would not be interesting in this scenario, because it adds extra overhead on the host, and also allows bypassing the mandatory trip to the physical switch. The main purpose of the proposal here is to allow guests using this type of direct connection to migrate successfully among hosts. A nice side effect is that it will make it easier to add in support for things like openvsitch (which, as I understand it, can just become another type of libvirt ). So while openvswitch may benefit from this code (see below), it is not a viable alternative to it. > > Option 3 > ----------- > > Up to now we've only discussed the need for separating the > host-specific config ( element) in the case of type='direct' > interfaces (well, in reality I've gone back and edited this document > so many times that is no longer true, but play along with me! :-). But > it really is a problem for all interface types - all of the > information currently in the guest's interface element really > is tied to the host, and shouldn't be defined in detail in the guest > XML; it should instead be defined once for each host, and only > referenced by some name in the guest XML; that way as a guest moves > from host to host, it will automatically adjust its connection to > match the new environmant. > > As a more general solution, instead of having the special new > "interfacePool" object in the config, what if the XML for "network was > expanded to mean "any type of guest network connection" (with a new > "type='xxx'" attribute at the toplevel to indicate which type), not > just "a private bridge optionally connected to the real world via > routing/NAT"? > > If this was the case, the guest interface XML could always be, eg: > > > > ... > > > and depending on the network config of the host the guest was migrated > to, this could be either a direct (macvtap) connection via an > interface allocated from a pool (the pool being defined in the > definition of 'red-network'), a bridge (again, pointed to by the > definition of 'red-network', or a virtual network (using the current > network definition syntax). This way the same guest could be migrated > not only between macvtap-enabled hosts, but from there to a host using > a bridge, or maybe a host in a remote location that used a virtual > network with a secure tunnel to connect back to the rest of the > red-network. (Part of the migration process would of course check that > the destination host had a network of the proper name, and fail if it > didn't; management software at a level above libvirt would probably > filter a list of candidate migration destinations based on available > networks, and only attempt migration to one that had the matching > network available). > > > Examples of 'red-network' for different types of connections (all of > these would work with the interface XML given above): > > > > red-network > > > ... > > > > > red-network > > > > > red-network > > > > > > > > In other words, to support openvswitch, we would add: red-network Then at guest boot startup time, libvirt would do all the setup to connect the qemu process' network interface to the openvswitch. From mprivozn at redhat.com Wed Apr 13 14:37:00 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Wed, 13 Apr 2011 16:37:00 +0200 Subject: [libvirt] [PATCH] Spice: support auid, images and stream compression Message-ID: <1302705420-15402-1-git-send-email-mprivozn@redhat.com> This extends the SPICE XML to allow variable compression settings for audio, images and streaming: All new element are optional. --- docs/formatdomain.html.in | 12 ++ docs/schemas/domain.rng | 50 ++++++++ src/conf/domain_conf.c | 130 ++++++++++++++++++++ src/conf/domain_conf.h | 42 +++++++ src/libvirt_private.syms | 8 ++ src/qemu/qemu_command.c | 16 +++ .../qemuxml2argv-graphics-spice.args | 4 +- .../qemuxml2argv-graphics-spice.xml | 4 + 8 files changed, 265 insertions(+), 1 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 3c4c656..c5edf53 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1664,6 +1664,18 @@ qemu-kvm -net nic,model=? /dev/null <channel name='main' mode='secure'/> <channel name='record' mode='insecure'/> </graphics> +

    +Spice supports variable compression settings for audio, images and streaming. +This setting are accessible via compression attribute in all +following elements: image to set image compression (accept +auto_glz, auto_lz, quic, +glz, lz, off), jpeg for +JPEG compression for images over wan (accept auto, +never, always), zlib for configuring +wan image compression (accept auto, never, +always) and playback for enabling audio stream +compression (accept on or off) +

    "rdp"
    diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 0fbf326..f0578f8 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1283,6 +1283,56 @@ + + + + + auto_glz + auto_lz + quic + glz + lz + off + + + + + + + + + + auto + never + always + + + + + + + + + + auto + never + always + + + + + + + + + + on + off + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 90a1317..f215e7d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -322,6 +322,32 @@ VIR_ENUM_IMPL(virDomainGraphicsSpiceChannelMode, "secure", "insecure"); +VIR_ENUM_IMPL(virDomainGraphicsSpiceImageCompression, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST, + "auto_glz", + "auto_lz", + "quic", + "glz", + "lz", + "off"); + +VIR_ENUM_IMPL(virDomainGraphicsSpiceJpegCompression, + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST, + "auto", + "never", + "always"); + +VIR_ENUM_IMPL(virDomainGraphicsSpiceZlibCompression, + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST, + "auto", + "never", + "always"); + +VIR_ENUM_IMPL(virDomainGraphicsSpicePlaybackCompression, + VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST, + "on", + "off"); + VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST, "subsystem", "capabilities") @@ -3917,6 +3943,11 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { if (virDomainGraphicsAuthDefParseXML(node, &def->data.spice.auth) < 0) goto error; + def->data.spice.image = VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST; + def->data.spice.jpeg = VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST; + def->data.spice.zlib = VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST; + def->data.spice.playback = VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST; + cur = node->children; while (cur != NULL) { if (cur->type == XML_ELEMENT_NODE) { @@ -3954,6 +3985,89 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { VIR_FREE(mode); def->data.spice.channels[nameval] = modeval; + } else if (xmlStrEqual(cur->name, BAD_CAST "image")) { + const char *compression = virXMLPropString(cur, "compression"); + int compressionVal; + + if (!compression) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("spice image missing compression")); + goto error; + } + + if ((compressionVal = + virDomainGraphicsSpiceImageCompressionTypeFromString(compression)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown spice image compression %s"), + compression); + VIR_FREE(compression); + goto error; + } + VIR_FREE(compression); + + def->data.spice.image = compressionVal; + } else if (xmlStrEqual(cur->name, BAD_CAST "jpeg")) { + const char *compression = virXMLPropString(cur, "compression"); + int compressionVal; + + if (!compression) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("spice jpeg missing compression")); + goto error; + } + + if ((compressionVal = + virDomainGraphicsSpiceJpegCompressionTypeFromString(compression)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown spice jpeg compression %s"), + compression); + VIR_FREE(compression); + goto error; + } + VIR_FREE(compression); + + def->data.spice.jpeg = compressionVal; + } else if (xmlStrEqual(cur->name, BAD_CAST "zlib")) { + const char *compression = virXMLPropString(cur, "compression"); + int compressionVal; + + if (!compression) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("spice zlib missing compression")); + goto error; + } + + if ((compressionVal = + virDomainGraphicsSpiceZlibCompressionTypeFromString(compression)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown spice zlib compression %s"), + compression); + VIR_FREE(compression); + goto error; + } + + def->data.spice.zlib = compressionVal; + } else if (xmlStrEqual(cur->name, BAD_CAST "playback")) { + const char *compression = virXMLPropString(cur, "compression"); + int compressionVal; + + if (!compression) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("spice playback missing compression")); + goto error; + } + + if ((compressionVal = + virDomainGraphicsSpicePlaybackCompressionTypeFromString(compression)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown spice playback compression")); + VIR_FREE(compression); + goto error; + + } + VIR_FREE(compression); + + def->data.spice.playback = compressionVal; } } cur = cur->next; @@ -7817,6 +7931,22 @@ virDomainGraphicsDefFormat(virBufferPtr buf, virDomainGraphicsSpiceChannelNameTypeToString(i), virDomainGraphicsSpiceChannelModeTypeToString(mode)); } + if (def->data.spice.image != + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST) + virBufferVSprintf(buf, " \n", + virDomainGraphicsSpiceImageCompressionTypeToString(def->data.spice.image)); + if (def->data.spice.jpeg != + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST) + virBufferVSprintf(buf, " \n", + virDomainGraphicsSpiceJpegCompressionTypeToString(def->data.spice.jpeg)); + if (def->data.spice.zlib != + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST) + virBufferVSprintf(buf, " \n", + virDomainGraphicsSpiceZlibCompressionTypeToString(def->data.spice.zlib)); + if (def->data.spice.playback != + VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST) + virBufferVSprintf(buf, " \n", + virDomainGraphicsSpicePlaybackCompressionTypeToString(def->data.spice.playback)); } if (children) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 95bd11e..e36f0ed 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -658,6 +658,40 @@ enum virDomainGraphicsSpiceChannelMode { VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_LAST }; +enum virDomainGraphicsSpiceImageCompression { + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_AUTO_GLZ, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_AUTO_LZ, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_QUIC, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_GLZ, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LZ, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_OFF, + + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST +}; + +enum virDomainGraphicsSpiceJpegCompression { + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_AUTO, + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_NEVER, + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_ALWAYS, + + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST +}; + +enum virDomainGraphicsSpiceZlibCompression { + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_AUTO, + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_NEVER, + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_ALWAYS, + + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST +}; + +enum virDomainGraphicsSpicePlaybackCompression { + VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_ON, + VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_OFF, + + VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST +}; + typedef struct _virDomainGraphicsDef virDomainGraphicsDef; typedef virDomainGraphicsDef *virDomainGraphicsDefPtr; struct _virDomainGraphicsDef { @@ -695,6 +729,10 @@ struct _virDomainGraphicsDef { virDomainGraphicsAuthDef auth; unsigned int autoport :1; int channels[VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST]; + int image; + int jpeg; + int zlib; + int playback; } spice; } data; }; @@ -1423,6 +1461,10 @@ VIR_ENUM_DECL(virDomainInputBus) VIR_ENUM_DECL(virDomainGraphics) VIR_ENUM_DECL(virDomainGraphicsSpiceChannelName) VIR_ENUM_DECL(virDomainGraphicsSpiceChannelMode) +VIR_ENUM_DECL(virDomainGraphicsSpiceImageCompression) +VIR_ENUM_DECL(virDomainGraphicsSpiceJpegCompression) +VIR_ENUM_DECL(virDomainGraphicsSpiceZlibCompression) +VIR_ENUM_DECL(virDomainGraphicsSpicePlaybackCompression) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) VIR_ENUM_DECL(virDomainSeclabel) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 54e4482..d2aa077 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -262,6 +262,14 @@ virDomainGraphicsSpiceChannelModeTypeFromString; virDomainGraphicsSpiceChannelModeTypeToString; virDomainGraphicsSpiceChannelNameTypeFromString; virDomainGraphicsSpiceChannelNameTypeToString; +virDomainGraphicsSpiceImageCompressionTypeToString; +virDomainGraphicsSpiceImageCompressionTypeFromString; +virDomainGraphicsSpiceJpegCompressionTypeFromString; +virDomainGraphicsSpiceJpegCompressionTypeToString; +virDomainGraphicsSpicePlaybackCompressionTypeFromString; +virDomainGraphicsSpicePlaybackCompressionTypeToString; +virDomainGraphicsSpiceZlibCompressionTypeFromString; +virDomainGraphicsSpiceZlibCompressionTypeToString; virDomainGraphicsTypeFromString; virDomainGraphicsTypeToString; virDomainHostdevDefFree; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index fea0068..6272910 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4032,6 +4032,22 @@ qemuBuildCommandLine(virConnectPtr conn, break; } } + if (def->graphics[0]->data.spice.image != + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST) + virBufferVSprintf(&opt, ",image-compression=%s", + virDomainGraphicsSpiceImageCompressionTypeToString(def->graphics[0]->data.spice.image)); + if (def->graphics[0]->data.spice.jpeg != + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST) + virBufferVSprintf(&opt, ",jpeg-wan-compression=%s", + virDomainGraphicsSpiceJpegCompressionTypeToString(def->graphics[0]->data.spice.jpeg)); + if (def->graphics[0]->data.spice.zlib != + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST) + virBufferVSprintf(&opt, ",zlib-glz-wan-compression=%s", + virDomainGraphicsSpiceZlibCompressionTypeToString(def->graphics[0]->data.spice.zlib)); + if (def->graphics[0]->data.spice.playback != + VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST) + virBufferVSprintf(&opt, ",playback-compression=%s", + virDomainGraphicsSpicePlaybackCompressionTypeToString(def->graphics[0]->data.spice.playback)); virCommandAddArg(cmd, "-spice"); virCommandAddArgBuffer(cmd, &opt); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args index c788bb6..70cd35b 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args @@ -2,6 +2,8 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=spice \ /usr/bin/qemu -S -M pc -m 214 -smp 1 -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ /dev/HostVG/QEMUGuest1 -usb -spice port=5903,tls-port=5904,addr=127.0.0.1,\ -x509-dir=/etc/pki/libvirt-spice,tls-channel=main,plaintext-channel=inputs -vga \ +x509-dir=/etc/pki/libvirt-spice,tls-channel=main,plaintext-channel=inputs,\ +image-compression=auto_glz,jpeg-wan-compression=auto,zlib-glz-wan-compression=auto,\ +playback-compression=on -vga \ qxl -global qxl.vram_size=18874368 -device qxl,id=video1,vram_size=33554432,bus=pci.0,addr=0x4 \ -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml index 5d46509..a29f50d 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml @@ -24,6 +24,10 @@ + + + +
    "rdp"
    diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 0fbf326..f0578f8 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1283,6 +1283,56 @@ + + + + + auto_glz + auto_lz + quic + glz + lz + off + + + + + + + + + + auto + never + always + + + + + + + + + + auto + never + always + + + + + + + + + + on + off + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 90a1317..a380db3 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -322,6 +322,36 @@ VIR_ENUM_IMPL(virDomainGraphicsSpiceChannelMode, "secure", "insecure"); +VIR_ENUM_IMPL(virDomainGraphicsSpiceImageCompression, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST, + "default", + "auto_glz", + "auto_lz", + "quic", + "glz", + "lz", + "off"); + +VIR_ENUM_IMPL(virDomainGraphicsSpiceJpegCompression, + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST, + "default", + "auto", + "never", + "always"); + +VIR_ENUM_IMPL(virDomainGraphicsSpiceZlibCompression, + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST, + "default", + "auto", + "never", + "always"); + +VIR_ENUM_IMPL(virDomainGraphicsSpicePlaybackCompression, + VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST, + "default", + "on", + "off"); + VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST, "subsystem", "capabilities") @@ -3954,6 +3984,89 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { VIR_FREE(mode); def->data.spice.channels[nameval] = modeval; + } else if (xmlStrEqual(cur->name, BAD_CAST "image")) { + const char *compression = virXMLPropString(cur, "compression"); + int compressionVal; + + if (!compression) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("spice image missing compression")); + goto error; + } + + if ((compressionVal = + virDomainGraphicsSpiceImageCompressionTypeFromString(compression)) < 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown spice image compression %s"), + compression); + VIR_FREE(compression); + goto error; + } + VIR_FREE(compression); + + def->data.spice.image = compressionVal; + } else if (xmlStrEqual(cur->name, BAD_CAST "jpeg")) { + const char *compression = virXMLPropString(cur, "compression"); + int compressionVal; + + if (!compression) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("spice jpeg missing compression")); + goto error; + } + + if ((compressionVal = + virDomainGraphicsSpiceJpegCompressionTypeFromString(compression)) < 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown spice jpeg compression %s"), + compression); + VIR_FREE(compression); + goto error; + } + VIR_FREE(compression); + + def->data.spice.jpeg = compressionVal; + } else if (xmlStrEqual(cur->name, BAD_CAST "zlib")) { + const char *compression = virXMLPropString(cur, "compression"); + int compressionVal; + + if (!compression) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("spice zlib missing compression")); + goto error; + } + + if ((compressionVal = + virDomainGraphicsSpiceZlibCompressionTypeFromString(compression)) < 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown spice zlib compression %s"), + compression); + VIR_FREE(compression); + goto error; + } + + def->data.spice.zlib = compressionVal; + } else if (xmlStrEqual(cur->name, BAD_CAST "playback")) { + const char *compression = virXMLPropString(cur, "compression"); + int compressionVal; + + if (!compression) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("spice playback missing compression")); + goto error; + } + + if ((compressionVal = + virDomainGraphicsSpicePlaybackCompressionTypeFromString(compression)) < 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown spice playback compression")); + VIR_FREE(compression); + goto error; + + } + VIR_FREE(compression); + + def->data.spice.playback = compressionVal; } } cur = cur->next; @@ -7817,6 +7930,18 @@ virDomainGraphicsDefFormat(virBufferPtr buf, virDomainGraphicsSpiceChannelNameTypeToString(i), virDomainGraphicsSpiceChannelModeTypeToString(mode)); } + if (def->data.spice.image) + virBufferVSprintf(buf, " \n", + virDomainGraphicsSpiceImageCompressionTypeToString(def->data.spice.image)); + if (def->data.spice.jpeg) + virBufferVSprintf(buf, " \n", + virDomainGraphicsSpiceJpegCompressionTypeToString(def->data.spice.jpeg)); + if (def->data.spice.zlib) + virBufferVSprintf(buf, " \n", + virDomainGraphicsSpiceZlibCompressionTypeToString(def->data.spice.zlib)); + if (def->data.spice.playback) + virBufferVSprintf(buf, " \n", + virDomainGraphicsSpicePlaybackCompressionTypeToString(def->data.spice.playback)); } if (children) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 95bd11e..60a33ce 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -658,6 +658,44 @@ enum virDomainGraphicsSpiceChannelMode { VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_LAST }; +enum virDomainGraphicsSpiceImageCompression { + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_DEFAULT = 0, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_AUTO_GLZ, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_AUTO_LZ, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_QUIC, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_GLZ, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LZ, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_OFF, + + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST +}; + +enum virDomainGraphicsSpiceJpegCompression { + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_DEFAULT = 0, + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_AUTO, + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_NEVER, + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_ALWAYS, + + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST +}; + +enum virDomainGraphicsSpiceZlibCompression { + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_DEFAULT = 0, + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_AUTO, + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_NEVER, + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_ALWAYS, + + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST +}; + +enum virDomainGraphicsSpicePlaybackCompression { + VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_DEFAULT = 0, + VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_ON, + VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_OFF, + + VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST +}; + typedef struct _virDomainGraphicsDef virDomainGraphicsDef; typedef virDomainGraphicsDef *virDomainGraphicsDefPtr; struct _virDomainGraphicsDef { @@ -695,6 +733,10 @@ struct _virDomainGraphicsDef { virDomainGraphicsAuthDef auth; unsigned int autoport :1; int channels[VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST]; + int image; + int jpeg; + int zlib; + int playback; } spice; } data; }; @@ -1423,6 +1465,10 @@ VIR_ENUM_DECL(virDomainInputBus) VIR_ENUM_DECL(virDomainGraphics) VIR_ENUM_DECL(virDomainGraphicsSpiceChannelName) VIR_ENUM_DECL(virDomainGraphicsSpiceChannelMode) +VIR_ENUM_DECL(virDomainGraphicsSpiceImageCompression) +VIR_ENUM_DECL(virDomainGraphicsSpiceJpegCompression) +VIR_ENUM_DECL(virDomainGraphicsSpiceZlibCompression) +VIR_ENUM_DECL(virDomainGraphicsSpicePlaybackCompression) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) VIR_ENUM_DECL(virDomainSeclabel) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 54e4482..d2aa077 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -262,6 +262,14 @@ virDomainGraphicsSpiceChannelModeTypeFromString; virDomainGraphicsSpiceChannelModeTypeToString; virDomainGraphicsSpiceChannelNameTypeFromString; virDomainGraphicsSpiceChannelNameTypeToString; +virDomainGraphicsSpiceImageCompressionTypeToString; +virDomainGraphicsSpiceImageCompressionTypeFromString; +virDomainGraphicsSpiceJpegCompressionTypeFromString; +virDomainGraphicsSpiceJpegCompressionTypeToString; +virDomainGraphicsSpicePlaybackCompressionTypeFromString; +virDomainGraphicsSpicePlaybackCompressionTypeToString; +virDomainGraphicsSpiceZlibCompressionTypeFromString; +virDomainGraphicsSpiceZlibCompressionTypeToString; virDomainGraphicsTypeFromString; virDomainGraphicsTypeToString; virDomainHostdevDefFree; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index fea0068..89668d4 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4032,6 +4032,18 @@ qemuBuildCommandLine(virConnectPtr conn, break; } } + if (def->graphics[0]->data.spice.image) + virBufferVSprintf(&opt, ",image-compression=%s", + virDomainGraphicsSpiceImageCompressionTypeToString(def->graphics[0]->data.spice.image)); + if (def->graphics[0]->data.spice.jpeg) + virBufferVSprintf(&opt, ",jpeg-wan-compression=%s", + virDomainGraphicsSpiceJpegCompressionTypeToString(def->graphics[0]->data.spice.jpeg)); + if (def->graphics[0]->data.spice.zlib) + virBufferVSprintf(&opt, ",zlib-glz-wan-compression=%s", + virDomainGraphicsSpiceZlibCompressionTypeToString(def->graphics[0]->data.spice.zlib)); + if (def->graphics[0]->data.spice.playback) + virBufferVSprintf(&opt, ",playback-compression=%s", + virDomainGraphicsSpicePlaybackCompressionTypeToString(def->graphics[0]->data.spice.playback)); virCommandAddArg(cmd, "-spice"); virCommandAddArgBuffer(cmd, &opt); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args index c788bb6..70cd35b 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args @@ -2,6 +2,8 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=spice \ /usr/bin/qemu -S -M pc -m 214 -smp 1 -nodefaults -monitor \ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ /dev/HostVG/QEMUGuest1 -usb -spice port=5903,tls-port=5904,addr=127.0.0.1,\ -x509-dir=/etc/pki/libvirt-spice,tls-channel=main,plaintext-channel=inputs -vga \ +x509-dir=/etc/pki/libvirt-spice,tls-channel=main,plaintext-channel=inputs,\ +image-compression=auto_glz,jpeg-wan-compression=auto,zlib-glz-wan-compression=auto,\ +playback-compression=on -vga \ qxl -global qxl.vram_size=18874368 -device qxl,id=video1,vram_size=33554432,bus=pci.0,addr=0x4 \ -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml index 5d46509..a29f50d 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml @@ -24,6 +24,10 @@ + + + +
    "rdp"
    diff --git i/docs/schemas/domain.rng w/docs/schemas/domain.rng index f0578f8..7163c6e 100644 --- i/docs/schemas/domain.rng +++ w/docs/schemas/domain.rng @@ -1260,6 +1260,7 @@ + @@ -1333,6 +1334,7 @@ + diff --git i/src/conf/domain_conf.c w/src/conf/domain_conf.c index cadaa0b..4afc489 100644 --- i/src/conf/domain_conf.c +++ w/src/conf/domain_conf.c @@ -3996,7 +3996,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { } if ((compressionVal = - virDomainGraphicsSpiceImageCompressionTypeFromString(compression)) < 0) { + virDomainGraphicsSpiceImageCompressionTypeFromString(compression)) <= 0) { virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown spice image compression %s"), compression); @@ -4017,7 +4017,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { } if ((compressionVal = - virDomainGraphicsSpiceJpegCompressionTypeFromString(compression)) < 0) { + virDomainGraphicsSpiceJpegCompressionTypeFromString(compression)) <= 0) { virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown spice jpeg compression %s"), compression); @@ -4038,7 +4038,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { } if ((compressionVal = - virDomainGraphicsSpiceZlibCompressionTypeFromString(compression)) < 0) { + virDomainGraphicsSpiceZlibCompressionTypeFromString(compression)) <= 0) { virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown spice zlib compression %s"), compression); @@ -4058,7 +4058,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { } if ((compressionVal = - virDomainGraphicsSpicePlaybackCompressionTypeFromString(compression)) < 0) { + virDomainGraphicsSpicePlaybackCompressionTypeFromString(compression)) <= 0) { virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown spice playback compression")); VIR_FREE(compression); -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 14 16:30:15 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 10:30:15 -0600 Subject: [libvirt] [libvirt PATCH v3] Introduce virDomainChrDefNew() In-Reply-To: <4DA71D5F.50103@redhat.com> References: <1302797114-13909-1-git-send-email-minovotn@redhat.com> <4DA71D5F.50103@redhat.com> Message-ID: <4DA72117.6000200@redhat.com> On 04/14/2011 10:14 AM, Cole Robinson wrote: > On 04/14/2011 12:05 PM, Michal Novotny wrote: >> Make: passed >> Make check: passed >> Make syntax-check: passed >> >> Hi, >> this is the commit to introduce the function to create new character >> device definition for the domain as advised by Cole Robinson >> . >> >> The function is used on the relevant places and also new tests has >> been added. >> >> Michal >> > > ACK, looks good now. Pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Thu Apr 14 16:44:25 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Thu, 14 Apr 2011 18:44:25 +0200 Subject: [libvirt] [PATCH] Fix gcc 4.6 warnings In-Reply-To: <1302772955-6711-1-git-send-email-cfergeau@redhat.com> References: <1302772955-6711-1-git-send-email-cfergeau@redhat.com> Message-ID: 2011/4/14 Christophe Fergeau : > gcc 4.6 warns when a variable is initialized but isn't used afterwards: > > vmware/vmware_driver.c:449:18: warning: variable 'vmxPath' set but not used [-Wunused-but-set-variable] > > This patch fixes these warnings. There are still 2 offending files: > > - vbox_tmpl.c: the variable is used inside an #ifdef and is assigned several > ?times outside of #ifdef. Fixing the warning would have required wrapping > ?all the assignment inside #ifdef which hurts readability. > > vbox/vbox_tmpl.c: In function 'vboxAttachDrives': > vbox/vbox_tmpl.c:3918:22: warning: variable 'accessMode' set but not used [-Wunused-but-set-variable] > > - esx_vi_types.generated.c: the name implies it's generated code and I > ?didn't want to dive into the code generator > > esx/esx_vi_types.generated.c: In function 'esxVI_FileQueryFlags_Free': > esx/esx_vi_types.generated.c:1203:3: warning: variable 'item' set but not used [-Wunused-but-set-variable] I can take care of that and I'll post a speculative patch for it as I don't have a gcc 4.6 at hand right now to test it my self. > --- > ?src/nwfilter/nwfilter_ebiptables_driver.c | ? ?7 +++---- > ?src/util/logging.c ? ? ? ? ? ? ? ? ? ? ? ?| ? ?3 +-- > ?src/vmware/vmware_driver.c ? ? ? ? ? ? ? ?| ? ?2 +- > ?3 files changed, 5 insertions(+), 7 deletions(-) > ACK. Before I can apply this patch we need to solve an issue with email address. You used a RedHat one for this patch, but you are listed with a Gnome one in the AUTHORS. This makes the syntax-check unhappy. We can solve this by adding your RedHat address as an alias to the Gnome on to the .mailmap file or use your RedHat as the mail one in the AUTHORS files and add and alias the other way around to the .mailmap file. What way do you prefer? Matthias From eblake at redhat.com Thu Apr 14 16:49:49 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 10:49:49 -0600 Subject: [libvirt] [PATCH 4/5] phyp: Fix too small buffer allocation in phypAttachDevice In-Reply-To: References: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> <1302343151-24133-5-git-send-email-matthias.bolte@googlemail.com> <20110411030603.GQ24838@redhat.com> Message-ID: <4DA725AD.4050000@redhat.com> On 04/14/2011 06:00 AM, Matthias Bolte wrote: >> ACK, we just need to make sure contains_specialcharacters() and >> escape_specialcharacters() don't diverge on the charater set. Maybe >> add a comment in escape_specialcharacters() to this effect. >> >> Daniel >> > > I just moved the character set to a define, like this and pushed the result. > > @@ -905,32 +911,10 @@ contains_specialcharacters(const char *src) > > for (i = 0; i < len; i++) { > switch (src[i]) { > + SPECIALCHARACTER_CASES > + return true; > + default: > + continue; > } Fair enough - continue the loop until we find a special character. > } > > @@ -954,35 +938,11 @@ escape_specialcharacters(const char *src) > > for (i = 0; i < len; i++) { > switch (src[i]) { > + SPECIALCHARACTER_CASES > + continue; > + default: > + dst[j] = src[i]; > + j++; Huh? That is not escaping characters, but omitting them! This code seems rather broken; was the intent to add \ escaping before special characters? I _really_ want to add something to src/util/util.h that outputs shell-escaped strings automatically (virCommandToString needs to use it, and the current 'virsh echo --shell' could share it), so that all clients that are doing shell escaping use a single entry point rather than re-coding ad-hoc methods. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From cfergeau at redhat.com Thu Apr 14 16:52:50 2011 From: cfergeau at redhat.com (Christophe Fergeau) Date: Thu, 14 Apr 2011 18:52:50 +0200 Subject: [libvirt] [PATCH] Fix gcc 4.6 warnings In-Reply-To: References: <1302772955-6711-1-git-send-email-cfergeau@redhat.com> Message-ID: <20110414165249.GC26310@teriyaki.redhat.com> On Thu, Apr 14, 2011 at 06:44:25PM +0200, Matthias Bolte wrote: > I can take care of that and I'll post a speculative patch for it as I > don't have a gcc 4.6 at hand right now to test it my self. I can easily test it, I'll let you know how it goes. > Before I can apply this patch we need to solve an issue with email > address. You used a RedHat one for this patch, but you are listed with > a Gnome one in the AUTHORS. This makes the syntax-check unhappy. We > can solve this by adding your RedHat address as an alias to the Gnome > on to the .mailmap file or use your RedHat as the mail one in the > AUTHORS files and add and alias the other way around to the .mailmap > file. > > What way do you prefer? I prefer the latter (@redhat.com in AUTHORS, and @gnome.org addy in .mailmap). Thanks! Christophe -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 198 bytes Desc: not available URL: From eblake at redhat.com Thu Apr 14 16:53:37 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 10:53:37 -0600 Subject: [libvirt] [PATCH] migrate VMs between different-endian hosts In-Reply-To: <4DA07FD9.8000606@linux.vnet.ibm.com> References: <4DA07FD9.8000606@linux.vnet.ibm.com> Message-ID: <4DA72691.3050106@redhat.com> On 04/09/2011 09:48 AM, Stefan Berger wrote: > This patch enables the migration of Qemu VMs between hosts of different > endianess. I tested this by migrating a i686 VM between a x86 and ppc64 > host. > > I am converting the 'int's in the VM's state header to uint32_t assuming > this doesn't break compatibility with existing deployments other than > Linux. > > Signed-off-by: Stefan Berger > > --- > src/qemu/qemu_driver.c | 25 ++++++++++++++++++++----- > 1 file changed, 20 insertions(+), 5 deletions(-) > > Index: libvirt-acl/src/qemu/qemu_driver.c > =================================================================== > --- libvirt-acl.orig/src/qemu/qemu_driver.c > +++ libvirt-acl/src/qemu/qemu_driver.c > @@ -43,6 +43,7 @@ > #include > #include > #include > +#include This won't work unless you also modify bootstrap.conf to include the gnulib byteswap module. ACK with that nit fixed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 14 16:54:00 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 10:54:00 -0600 Subject: [libvirt] [PATCH] migrate VMs between different-endian hosts In-Reply-To: <4DA6E85A.3020605@linux.vnet.ibm.com> References: <4DA07FD9.8000606@linux.vnet.ibm.com> <20110411030911.GS24838@redhat.com> <4DA2D8B5.5000106@linux.vnet.ibm.com> <20110411133619.GC30115@redhat.com> <4DA33E8F.209@redhat.com> <20110412060508.GA1149@redhat.com> <4DA6E85A.3020605@linux.vnet.ibm.com> Message-ID: <4DA726A8.7050307@redhat.com> On 04/14/2011 06:28 AM, Stefan Berger wrote: >> The thing I'm worried about is that by bumping older versions won't >> be able to restore the new dumps, and that could be a serious issue on >> shared storage. We are not introducing a new feature, so I thin we need >> to preserve forward compatibility. The patch as is is minimal but >> achieves it. >> > Do you want to accept the patch ? See my conditional ACK to the actual patch. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Thu Apr 14 17:06:19 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Thu, 14 Apr 2011 19:06:19 +0200 Subject: [libvirt] [PATCH 4/5] phyp: Fix too small buffer allocation in phypAttachDevice In-Reply-To: <4DA725AD.4050000@redhat.com> References: <1302343151-24133-1-git-send-email-matthias.bolte@googlemail.com> <1302343151-24133-5-git-send-email-matthias.bolte@googlemail.com> <20110411030603.GQ24838@redhat.com> <4DA725AD.4050000@redhat.com> Message-ID: 2011/4/14 Eric Blake : > On 04/14/2011 06:00 AM, Matthias Bolte wrote: >>> ?ACK, we just need to make sure contains_specialcharacters() and >>> escape_specialcharacters() don't diverge on the charater set. Maybe >>> add a comment in escape_specialcharacters() to this effect. >>> >>> Daniel >>> >> >> I just moved the character set to a define, like this and pushed the result. >> >> @@ -905,32 +911,10 @@ contains_specialcharacters(const char *src) >> >> ? ? ?for (i = 0; i < len; i++) { >> ? ? ? ? ?switch (src[i]) { >> + ? ? ? ?SPECIALCHARACTER_CASES >> + ? ? ? ? ? ?return true; >> + ? ? ? ?default: >> + ? ? ? ? ? ?continue; >> ? ? ? ? ?} > > Fair enough - continue the loop until we find a special character. > >> ? ? ?} >> >> @@ -954,35 +938,11 @@ escape_specialcharacters(const char *src) >> >> ? ? ?for (i = 0; i < len; i++) { >> ? ? ? ? ?switch (src[i]) { >> + ? ? ? ?SPECIALCHARACTER_CASES >> + ? ? ? ? ? ?continue; >> + ? ? ? ?default: >> + ? ? ? ? ? ?dst[j] = src[i]; >> + ? ? ? ? ? ?j++; > > Huh? ?That is not escaping characters, but omitting them! ?This code > seems rather broken; was the intent to add \ escaping before special > characters? Well, The code was this way from the beginning, we'll have to ask Eduardo about its intention here. Matthias From matthias.bolte at googlemail.com Thu Apr 14 17:10:47 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Thu, 14 Apr 2011 19:10:47 +0200 Subject: [libvirt] [PATCH] Fix gcc 4.6 warnings In-Reply-To: <20110414165249.GC26310@teriyaki.redhat.com> References: <1302772955-6711-1-git-send-email-cfergeau@redhat.com> <20110414165249.GC26310@teriyaki.redhat.com> Message-ID: 2011/4/14 Christophe Fergeau : > On Thu, Apr 14, 2011 at 06:44:25PM +0200, Matthias Bolte wrote: >> I can take care of that and I'll post a speculative patch for it as I >> don't have a gcc 4.6 at hand right now to test it my self. > > I can easily test it, I'll let you know how it goes. > >> Before I can apply this patch we need to solve an issue with email >> address. You used a RedHat one for this patch, but you are listed with >> a Gnome one in the AUTHORS. This makes the syntax-check unhappy. We >> can solve this by adding your RedHat address as an alias to the Gnome >> on to the .mailmap file or use your RedHat as the mail one in the >> AUTHORS files and add and alias the other way around to the .mailmap >> file. >> >> What way do you prefer? > > I prefer the latter (@redhat.com in AUTHORS, and @gnome.org addy in > .mailmap). > > Thanks! > > Christophe > Okay, I change the addresses accordingly and pushed the result. Matthias From matthias.bolte at googlemail.com Thu Apr 14 17:18:27 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Thu, 14 Apr 2011 19:18:27 +0200 Subject: [libvirt] [PATCH] esx: Fix gcc 4.6 warning about initialized but unused variables Message-ID: This is a speculative patch as I don't have gcc 4.6 at hand to test it. Matthias -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-esx-Fix-gcc-4.6-warning-about-initialized-but-unused.patch Type: text/x-patch Size: 2886 bytes Desc: not available URL: From matthias.bolte at googlemail.com Thu Apr 14 17:28:30 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Thu, 14 Apr 2011 19:28:30 +0200 Subject: [libvirt] [PATCH] Fix gcc 4.6 warnings in vbox_tmpl.c In-Reply-To: <1302783036-24592-1-git-send-email-cfergeau@redhat.com> References: <20110414120721.GB26310@teriyaki.redhat.com> <1302783036-24592-1-git-send-email-cfergeau@redhat.com> Message-ID: 2011/4/14 Christophe Fergeau : > --- > ?src/vbox/vbox_tmpl.c | ? 11 ++++++++--- > ?1 files changed, 8 insertions(+), 3 deletions(-) > > diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c > index 0fbfba5..a7d78df 100644 > --- a/src/vbox/vbox_tmpl.c > +++ b/src/vbox/vbox_tmpl.c > @@ -3915,7 +3915,9 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) > ? ? ? ? ? ? PRUnichar *mediumFileUtf16 = NULL; > ? ? ? ? ? ? PRUint32 ? storageBus ? ? ?= StorageBus_Null; > ? ? ? ? ? ? PRUint32 ? deviceType ? ? ?= DeviceType_Null; > +# if VBOX_API_VERSION >= 4000 > ? ? ? ? ? ? PRUint32 ? accessMode ? ? ?= AccessMode_ReadOnly; > +#endif > ? ? ? ? ? ? PRInt32 ? ?deviceInst ? ? ?= 0; > ? ? ? ? ? ? PRInt32 ? ?devicePort ? ? ?= 0; > ? ? ? ? ? ? PRInt32 ? ?deviceSlot ? ? ?= 0; > @@ -3924,24 +3926,27 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) > > ? ? ? ? ? ? if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) { > ? ? ? ? ? ? ? ? deviceType = DeviceType_HardDisk; > - ? ? ? ? ? ? ? ?accessMode = AccessMode_ReadWrite; > ?# if VBOX_API_VERSION < 4000 > ? ? ? ? ? ? ? ? data->vboxObj->vtbl->FindHardDisk(data->vboxObj, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mediumFileUtf16, &medium); > +#else This else is not indented properly. make syntax-check should have caught that if you have cppi installed. > + ? ? ? ? ? ? ? ?accessMode = AccessMode_ReadWrite; > ?# endif ACK. If fixed the minor indentation errors and pushed the result. Matthias From eblake at redhat.com Thu Apr 14 17:36:50 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 11:36:50 -0600 Subject: [libvirt] [PATCH 0/4] more phyp refactoring In-Reply-To: References: <1302732432-1129-1-git-send-email-eblake@redhat.com> <4DA71540.5090204@redhat.com> Message-ID: <4DA730B2.60409@redhat.com> On 04/14/2011 09:51 AM, Matthias Bolte wrote: >>> src/phyp/phyp_driver.c | 1128 +++++++----------------------------------------- >>> 1 files changed, 163 insertions(+), 965 deletions(-) >> >> Serves me right for thinking Matthias' cleanups had already been >> applied. Now I get to rebase, with lots of conflicts :) > > Sorry for that :( No problem. The fault is mostly mine for seeing your series and its review, and assuming it was in without verifying it myself. :) > > I'm currently quite busy with my studies and can only spent some time > on weekends for libvirt development to get some distraction. This > results in longer delays between libvirt related things I do. Today, I > successfully took an exam and am relaxing with libvirt stuff right > now. > > You probably want to post a rebased v2 before I review your phyp > patches, don't you? Yep, and v2 will be larger because I've found more leaks in the meantime. Plus, your 2/5 missed cleaning up the error paths for all the new interface functions that I just pushed in between when you submitted your patches for review vs. actually pushing them, so I'm fixing those to be consistent, as well. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From stefanb at linux.vnet.ibm.com Thu Apr 14 17:45:26 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Thu, 14 Apr 2011 13:45:26 -0400 Subject: [libvirt] [PATCH] ppc: Enable starting of VMs on ppc host Message-ID: <4DA732B6.20503@linux.vnet.ibm.com> Subject: ppc: Enable starting of VMs on ppc host Due to differences in /proc/cpuinfo the parsing of the cpu data is different between architectures. On PPC /proc/cpuinfo looks like this: [original formatting with tabs] processor : 0 cpu : PPC970MP, altivec supported clock : 2297.700000MHz revision : 1.1 (pvr 0044 0101) processor : 1 cpu : PPC970MP, altivec supported clock : 2297.700000MHz revision : 1.1 (pvr 0044 0101) [..] timebase : 14318000 platform : pSeries model : IBM,8844-AC1 machine : CHRP IBM,8844-AC1 The patch adapts the parsing of the data found in /proc/cpuinfo. /sys/devices/system/cpu/cpuX/topology/physical_package_id also always returns -1. Check for it on ppc and make it '0' if found negative. Signed-off-by: Stefan Berger --- src/nodeinfo.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) Index: libvirt/src/nodeinfo.c =================================================================== --- libvirt.orig/src/nodeinfo.c +++ libvirt/src/nodeinfo.c @@ -163,7 +163,14 @@ cleanup: static int parse_socket(unsigned int cpu) { - return get_cpu_value(cpu, "topology/physical_package_id", false); + int ret = get_cpu_value(cpu, "topology/physical_package_id", false); +#if defined(__powerpc__) || \ + defined(__powerpc64__) + /* ppc has -1 */ + if (ret < 0) + ret = 0; +#endif + return ret; } int linuxNodeInfoCPUPopulate(FILE *cpuinfo, @@ -206,6 +213,9 @@ int linuxNodeInfoCPUPopulate(FILE *cpuin return -1; } nodeinfo->cpus++; +#if defined(__x86_64__) || \ + defined(__amd64__) || \ + defined(__i386__) } else if (STRPREFIX(buf, "cpu MHz")) { char *p; unsigned int ui; @@ -237,6 +247,27 @@ int linuxNodeInfoCPUPopulate(FILE *cpuin && id > nodeinfo->cores) nodeinfo->cores = id; } +#elif defined(__powerpc__) || \ + defined(__powerpc64__) + } else if (STRPREFIX(buf, "clock")) { + char *p; + unsigned int ui; + buf += 5; + while (*buf && c_isspace(*buf)) + buf++; + if (*buf != ':' || !buf[1]) { + nodeReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("parsing cpuinfo cpu MHz")); + return -1; + } + if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 + /* Accept trailing fractional part. */ + && (*p == '\0' || *p == '.' || c_isspace(*p))) + nodeinfo->mhz = ui; + } +#else +# warning Parser for /proc/cpuinfo needs to be adapted for your architecture +#endif } if (!nodeinfo->cpus) { From stefanb at linux.vnet.ibm.com Thu Apr 14 17:50:45 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Thu, 14 Apr 2011 13:50:45 -0400 Subject: [libvirt] [PATCH] migrate VMs between different-endian hosts In-Reply-To: <4DA72691.3050106@redhat.com> References: <4DA07FD9.8000606@linux.vnet.ibm.com> <4DA72691.3050106@redhat.com> Message-ID: <4DA733F5.1030306@linux.vnet.ibm.com> On 04/14/2011 12:53 PM, Eric Blake wrote: > On 04/09/2011 09:48 AM, Stefan Berger wrote: >> This patch enables the migration of Qemu VMs between hosts of different >> endianess. I tested this by migrating a i686 VM between a x86 and ppc64 >> host. >> >> I am converting the 'int's in the VM's state header to uint32_t assuming >> this doesn't break compatibility with existing deployments other than >> Linux. >> >> Signed-off-by: Stefan Berger >> >> --- >> src/qemu/qemu_driver.c | 25 ++++++++++++++++++++----- >> 1 file changed, 20 insertions(+), 5 deletions(-) >> >> Index: libvirt-acl/src/qemu/qemu_driver.c >> =================================================================== >> --- libvirt-acl.orig/src/qemu/qemu_driver.c >> +++ libvirt-acl/src/qemu/qemu_driver.c >> @@ -43,6 +43,7 @@ >> #include >> #include >> #include >> +#include > This won't work unless you also modify bootstrap.conf to include the > gnulib byteswap module. > > ACK with that nit fixed. > I don't think it's necessary to include it there: # rpm -q --whatprovides /usr/include/byteswap.h glibc-headers-2.12.90-21.x86_64 Stefan From eblake at redhat.com Thu Apr 14 18:18:32 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 12:18:32 -0600 Subject: [libvirt] [PATCH] ppc: Enable starting of VMs on ppc host In-Reply-To: <4DA732B6.20503@linux.vnet.ibm.com> References: <4DA732B6.20503@linux.vnet.ibm.com> Message-ID: <4DA73A78.3090201@redhat.com> On 04/14/2011 11:45 AM, Stefan Berger wrote: > Subject: ppc: Enable starting of VMs on ppc host > > The patch adapts the parsing of the data found in /proc/cpuinfo. > > /sys/devices/system/cpu/cpuX/topology/physical_package_id also > always returns -1. Check for it on ppc and make it '0' if found negative. > > Signed-off-by: Stefan Berger > > --- > src/nodeinfo.c | 33 ++++++++++++++++++++++++++++++++- > 1 file changed, 32 insertions(+), 1 deletion(-) > ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 14 18:20:43 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 12:20:43 -0600 Subject: [libvirt] [PATCH] migrate VMs between different-endian hosts In-Reply-To: <4DA733F5.1030306@linux.vnet.ibm.com> References: <4DA07FD9.8000606@linux.vnet.ibm.com> <4DA72691.3050106@redhat.com> <4DA733F5.1030306@linux.vnet.ibm.com> Message-ID: <4DA73AFB.2050707@redhat.com> On 04/14/2011 11:50 AM, Stefan Berger wrote: >>> +++ libvirt-acl/src/qemu/qemu_driver.c >>> @@ -43,6 +43,7 @@ >>> #include >>> #include >>> #include >>> +#include >> This won't work unless you also modify bootstrap.conf to include the >> gnulib byteswap module. >> >> ACK with that nit fixed. >> > I don't think it's necessary to include it there: > > # rpm -q --whatprovides /usr/include/byteswap.h > glibc-headers-2.12.90-21.x86_64 Not all the world is glibc. BSD and mingw lack byteswap.h, and qemu compiles on more than just Linux. While I'm not sure if any non-Linux hosts default to compiling the qemu driver at the current moment, that does not mean that we should not be thinking about the portability aspects. Adding a one-liner inclusion of the byteswap module to bootstrap.conf will avoid any questions of portability pitfalls. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From stefanb at linux.vnet.ibm.com Thu Apr 14 18:53:58 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Thu, 14 Apr 2011 14:53:58 -0400 Subject: [libvirt] [PATCH] migrate VMs between different-endian hosts In-Reply-To: <4DA73AFB.2050707@redhat.com> References: <4DA07FD9.8000606@linux.vnet.ibm.com> <4DA72691.3050106@redhat.com> <4DA733F5.1030306@linux.vnet.ibm.com> <4DA73AFB.2050707@redhat.com> Message-ID: <4DA742C6.3040401@linux.vnet.ibm.com> On 04/14/2011 02:20 PM, Eric Blake wrote: > On 04/14/2011 11:50 AM, Stefan Berger wrote: >>>> +++ libvirt-acl/src/qemu/qemu_driver.c >>>> @@ -43,6 +43,7 @@ >>>> #include >>>> #include >>>> #include >>>> +#include >>> This won't work unless you also modify bootstrap.conf to include the >>> gnulib byteswap module. >>> >>> ACK with that nit fixed. >>> >> I don't think it's necessary to include it there: >> >> # rpm -q --whatprovides /usr/include/byteswap.h >> glibc-headers-2.12.90-21.x86_64 > Not all the world is glibc. BSD and mingw lack byteswap.h, and qemu > compiles on more than just Linux. While I'm not sure if any non-Linux > hosts default to compiling the qemu driver at the current moment, that > does not mean that we should not be thinking about the portability > aspects. Adding a one-liner inclusion of the byteswap module to > bootstrap.conf will avoid any questions of portability pitfalls. > Push with that nit fixed. Stefan From stefanb at linux.vnet.ibm.com Thu Apr 14 18:56:44 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Thu, 14 Apr 2011 14:56:44 -0400 Subject: [libvirt] [PATCH] ppc: Enable starting of VMs on ppc host In-Reply-To: <4DA73A78.3090201@redhat.com> References: <4DA732B6.20503@linux.vnet.ibm.com> <4DA73A78.3090201@redhat.com> Message-ID: <4DA7436C.6040001@linux.vnet.ibm.com> On 04/14/2011 02:18 PM, Eric Blake wrote: > On 04/14/2011 11:45 AM, Stefan Berger wrote: >> Subject: ppc: Enable starting of VMs on ppc host >> >> The patch adapts the parsing of the data found in /proc/cpuinfo. >> >> /sys/devices/system/cpu/cpuX/topology/physical_package_id also >> always returns -1. Check for it on ppc and make it '0' if found negative. >> >> Signed-off-by: Stefan Berger >> >> --- >> src/nodeinfo.c | 33 ++++++++++++++++++++++++++++++++- >> 1 file changed, 32 insertions(+), 1 deletion(-) >> > ACK. > Pushed. I unfortunately didn't pay attention to syntax-check and the indentation of the #if's is wrong. Gee. Stefan Stefan From laine at laine.org Thu Apr 14 19:06:55 2011 From: laine at laine.org (Laine Stump) Date: Thu, 14 Apr 2011 15:06:55 -0400 Subject: [libvirt] [PATCHv2] network: truncate bridges' dummy tap device names to IFNAMSIZ (15) chars In-Reply-To: <1302717340-26901-1-git-send-email-laine@laine.org> References: <1302717340-26901-1-git-send-email-laine@laine.org> Message-ID: <1302808015-11280-1-git-send-email-laine@laine.org> (Change from V1 - define a static char[] containing the desired prefix, and use its size to figure out how much to truncate, rather than having a bunch of magic numbers. This also makes it simpler and less error-prone to change the suffix if we decide to.) This patch addresses: https://bugzilla.redhat.com/show_bug.cgi?id=694382 In order to give each libvirt-created bridge a fixed MAC address, commit 5754dbd56d4738112a86776c09e810e32f7c3224, added code to create a dummy tap device with guaranteed lowest MAC address and attach it to the bridge. This tap device was given the name "${bridgename}-nic". However, an interface device name must be IFNAMSIZ (15) characters or less, so a valid ${bridgename} such as "verylongname123" (15 characters) would lead to an invalid tap device name ("verylongname123-nic" - 19 characters), and that in turn led to a failure to bring up the network. The solution is to shorten the part of the original name used to generate the tap device name. However, simply truncating it is insufficient, because the last few characters of an interface name are often a number used to indicate one of a list of several similar devices (for example, "verylongname123", "verylongname124", etc) and simple truncation would lead to duplicate names (eg "verlongnam-nic" and "verylongnam-nic"). So instead we take the first 8 characters of $bridgename ("verylong" in the example), add on the final 3 bytes ("123"), then add "-nic" (so "verylong123-nic"). Not pretty, but it is much more likely to generate a unique name, and is reproducible (unlike, say, a random number). --- src/network/bridge_driver.c | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index ea2bfd4..b108bb9 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -141,9 +141,23 @@ networkRadvdConfigFileName(const char *netname) static char * networkBridgeDummyNicName(const char *brname) { + static const char dummyNicSuffix[] = "-nic"; char *nicname; - virAsprintf(&nicname, "%s-nic", brname); + if (strlen(brname) + sizeof(dummyNicSuffix) > IFNAMSIZ) { + /* because the length of an ifname is limited to IFNAMSIZ-1 + * (usually 15), and we're adding 4 more characters, we must + * truncate the original name to 11 to fit. In order to catch + * a possible numeric ending (eg virbr0, virbr1, etc), we grab + * the first 8 and last 3 characters of the string. + */ + virAsprintf(&nicname, "%.*s%s%s", + /* space for last 3 chars + "-nic" + NULL */ + (int)(IFNAMSIZ - (3 + sizeof(dummyNicSuffix))), + brname, brname + strlen(brname) - 3, dummyNicSuffix); + } else { + virAsprintf(&nicname, "%s%s", brname, dummyNicSuffix); + } return nicname; } -- 1.7.3.4 From eblake at redhat.com Thu Apr 14 19:19:15 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 13:19:15 -0600 Subject: [libvirt] [PATCHv2] network: truncate bridges' dummy tap device names to IFNAMSIZ (15) chars In-Reply-To: <1302808015-11280-1-git-send-email-laine@laine.org> References: <1302717340-26901-1-git-send-email-laine@laine.org> <1302808015-11280-1-git-send-email-laine@laine.org> Message-ID: <4DA748B3.3050709@redhat.com> On 04/14/2011 01:06 PM, Laine Stump wrote: > > (Change from V1 - define a static char[] containing the desired > prefix, and use its size to figure out how much to truncate, rather > than having a bunch of magic numbers. This also makes it simpler and > less error-prone to change the suffix if we decide to.) Indeed :) > The solution is to shorten the part of the original name used to > generate the tap device name. However, simply truncating it is > insufficient, because the last few characters of an interface name are > often a number used to indicate one of a list of several similar > devices (for example, "verylongname123", "verylongname124", etc) and > simple truncation would lead to duplicate names (eg "verlongnam-nic" > and "verylongnam-nic"). So instead we take the first 8 characters of > $bridgename ("verylong" in the example), add on the final 3 bytes > ("123"), then add "-nic" (so "verylong123-nic"). Not pretty, but it > is much more likely to generate a unique name, and is reproducible > (unlike, say, a random number). > --- > src/network/bridge_driver.c | 16 +++++++++++++++- > 1 files changed, 15 insertions(+), 1 deletions(-) Here's making my IRC review official: ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 14 19:34:53 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 13:34:53 -0600 Subject: [libvirt] [PATCH] ppc: Enable starting of VMs on ppc host In-Reply-To: <4DA7436C.6040001@linux.vnet.ibm.com> References: <4DA732B6.20503@linux.vnet.ibm.com> <4DA73A78.3090201@redhat.com> <4DA7436C.6040001@linux.vnet.ibm.com> Message-ID: <4DA74C5D.9020702@redhat.com> On 04/14/2011 12:56 PM, Stefan Berger wrote: > On 04/14/2011 02:18 PM, Eric Blake wrote: >> On 04/14/2011 11:45 AM, Stefan Berger wrote: >>> Subject: ppc: Enable starting of VMs on ppc host >>> >>> The patch adapts the parsing of the data found in /proc/cpuinfo. >>> >>> /sys/devices/system/cpu/cpuX/topology/physical_package_id also >>> always returns -1. Check for it on ppc and make it '0' if found >>> negative. >>> >>> Signed-off-by: Stefan Berger >>> >>> --- >>> src/nodeinfo.c | 33 ++++++++++++++++++++++++++++++++- >>> 1 file changed, 32 insertions(+), 1 deletion(-) >>> >> ACK. >> > Pushed. > > I unfortunately didn't pay attention to syntax-check and the indentation > of the #if's is wrong. Gee. Oh well. I've pushed the obvious fixup as trivial. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 14 19:56:35 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 13:56:35 -0600 Subject: [libvirt] [PATCH] Merge all returns paths from dispatcher into single path In-Reply-To: <20110414124304.GH6009@redhat.com> References: <1302718366-32246-1-git-send-email-berrange@redhat.com> <4DA6307D.1030402@redhat.com> <20110414124304.GH6009@redhat.com> Message-ID: <4DA75173.8020709@redhat.com> On 04/14/2011 06:43 AM, Daniel P. Berrange wrote: >>> + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); >> >> Is virNetError really the best name for the new helper macro, especially >> since VIR_FROM_THIS is VIR_FROM_REMOTE? Should it instead be named >> virRemoteError()? > > virNetError() is what my RPC series of patches uses throughout. > Also it will change VIR_FROM_REMOTE to VIR_FROM_RPC Fair enough. >>> +cleanup: >>> + if (rv < 0) >>> + remoteDispatchError(rerr); >> >> That works. I wonder if we can completely get rid of >> remoteDispatchOOMError? > > Other files still use it, but it will be gone with the > RPC rewrite. What other files? daemon/dispatch.h declares it and daemon/dispatch.c implements it, but no one but daemon/remote.c uses it. >>> if (virDomainBlockPeek(dom, path, offset, size, >>> ret->buffer.buffer_val, flags) == -1) { >>> - /* free(ret->buffer.buffer_val); - caller frees */ >>> - remoteDispatchConnError(rerr, conn); >>> - virDomainFree(dom); >>> - return -1; >>> + goto cleanup; >>> } >>> - virDomainFree(dom); >>> >>> - return 0; >>> + rv = 0; >>> + >>> +cleanup: >>> + if (rv < 0) { >>> + remoteDispatchError(rerr); >>> + VIR_FREE(ret->buffer.buffer_val); >> >> Can we also clean up the caller to quit freeing (as a separate patch), >> now that we guarantee the cleanup here? Should we have a 'make >> syntax-check' rule that catches unadorned use of free() instead of VIR_FREE? > > I'm not sure what you mean here ? If rv == 0, then 'ret' is expected > to have the data present, and the caller will use xdr_free() to release > it. If rv == -1, then 'ret' is expected to have not been initialized, > hence this code must free that buffer. My question was about the commented-out /* free() - caller frees */ above. But if you're correct, the function caller does _not_ free ret->buffer.buffer_val on a -1 return, so there's nothing to fix in the caller and this really does plug a leak. On the other hand, calling VIR_FREE on the error path is perfectly fine, even if the caller did free that variable, because the caller will see NULL and be a no-op - so my question was whether the caller is doing the free even for a -1 return which can now be cleaned up. At any rate, I don't think you need to make any changes to this hunk, and if you're right, we are plugging a leak rather than leaving a no-op free in some caller. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 14 20:01:02 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:01:02 -0600 Subject: [libvirt] [PATCH] Merge all returns paths from dispatcher into single path In-Reply-To: <20110414132946.GI6009@redhat.com> References: <1302718366-32246-1-git-send-email-berrange@redhat.com> <4DA6307D.1030402@redhat.com> <20110414132946.GI6009@redhat.com> Message-ID: <4DA7527E.5050501@redhat.com> On 04/14/2011 07:29 AM, Daniel P. Berrange wrote: >>> >>> parent = virNodeDeviceGetParent(dev); >> >> ...and malloc'd on this path. > > It isn't malloc'd here actually. This is returning > a 'const char *'... Umm - libvirt.c declares it as 'const char *', but defers to the deviceMonitor->deviceGetParent callback. And that callback returns 'char *', not 'const char *'. In turn, in node_device_driver.c:nodeDeviceGetParent, the callback that actually implements things is actually setting ret to at strdup() value. Ouch - our API inherently leaks. >> >> ...and add unconditional VIR_FREE(parent) here. I'm surprised we >> haven't noticed that leak before. > > ..meaning it isn't actually a leak here :-) Yes it is, by design :( -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 14 20:04:01 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:04:01 -0600 Subject: [libvirt] [PATCH] Merge all returns paths from dispatcher into single path In-Reply-To: <4DA7527E.5050501@redhat.com> References: <1302718366-32246-1-git-send-email-berrange@redhat.com> <4DA6307D.1030402@redhat.com> <20110414132946.GI6009@redhat.com> <4DA7527E.5050501@redhat.com> Message-ID: <4DA75331.3060408@redhat.com> On 04/14/2011 02:01 PM, Eric Blake wrote: > On 04/14/2011 07:29 AM, Daniel P. Berrange wrote: >>>> >>>> parent = virNodeDeviceGetParent(dev); >>> >>> ...and malloc'd on this path. >> >> It isn't malloc'd here actually. This is returning >> a 'const char *'... > > Umm - libvirt.c declares it as 'const char *', but defers to the > deviceMonitor->deviceGetParent callback. And that callback returns > 'char *', not 'const char *'. In turn, in > node_device_driver.c:nodeDeviceGetParent, the callback that actually > implements things is actually setting ret to at strdup() value. > > Ouch - our API inherently leaks. > >>> >>> ...and add unconditional VIR_FREE(parent) here. I'm surprised we >>> haven't noticed that leak before. >> >> ..meaning it isn't actually a leak here :-) > > Yes it is, by design :( Now I'm waffling. It looks like libvirt.c is caching the result from the callback. So even though the callback exposes strdup()'d memory, libvirt.c is caching that in the virNodeDevicePtr, and only ever calling the callback once. So it's not a leak after all. Sorry for my confusion. /me goes and crawls back in my hole ... -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 14 20:22:26 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:22:26 -0600 Subject: [libvirt] [PATCHv2 0/9] round 2 of phyp cleanups Message-ID: <1302812555-3418-1-git-send-email-eblake@redhat.com> Smaller code and fewer bugs. Rebase of earlier version at: https://www.redhat.com/archives/libvir-list/2011-April/msg00677.html Eric Blake (9): maint: use lighter-weight function for straight appends phyp: avoid a logic bug phyp: avoid memory leak on failure phyp: more return handling cleanup phyp: use consistent style for labels phyp: prefer memcpy over memmove when legal phyp: use consistent return string handling phyp: avoid memory leaks in command values phyp: another simplification src/conf/nwfilter_conf.c | 16 +- src/phyp/phyp_driver.c | 1355 ++++++++--------------------------------- src/qemu/qemu_command.c | 30 +- src/security/virt-aa-helper.c | 2 +- src/util/sexpr.c | 4 +- src/xen/xend_internal.c | 6 +- src/xenxs/xen_sxpr.c | 2 +- src/xenxs/xen_xm.c | 4 +- 8 files changed, 290 insertions(+), 1129 deletions(-) -- 1.7.4.2 From eblake at redhat.com Thu Apr 14 20:22:29 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:22:29 -0600 Subject: [libvirt] [PATCHv2 3/9] phyp: avoid memory leak on failure In-Reply-To: <1302812555-3418-1-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> Message-ID: <1302812555-3418-4-git-send-email-eblake@redhat.com> * src/phyp/phyp_driver.c (phypUUIDTable_Init): Avoid memory leak on error. --- src/phyp/phyp_driver.c | 46 +++++++++++++++++++++++++++------------------- 1 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 7aa494d..0c69d4f 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -807,31 +807,35 @@ phypUUIDTable_Pull(virConnectPtr conn) static int phypUUIDTable_Init(virConnectPtr conn) { - uuid_tablePtr uuid_table; + uuid_tablePtr uuid_table = NULL; phyp_driverPtr phyp_driver; int nids_numdomains = 0; int nids_listdomains = 0; int *ids = NULL; unsigned int i = 0; + int ret = -1; + bool table_created = false; if ((nids_numdomains = phypNumDomainsGeneric(conn, 2)) < 0) - goto err; + goto cleanup; if (VIR_ALLOC_N(ids, nids_numdomains) < 0) { virReportOOMError(); - goto err; + goto cleanup; } if ((nids_listdomains = phypListDomainsGeneric(conn, ids, nids_numdomains, 1)) < 0) - goto err; + goto cleanup; /* exit early if there are no domains */ - if (nids_numdomains == 0 && nids_listdomains == 0) - goto exit; - else if (nids_numdomains != nids_listdomains) { + if (nids_numdomains == 0 && nids_listdomains == 0) { + ret = 0; + goto cleanup; + } + if (nids_numdomains != nids_listdomains) { VIR_ERROR0(_("Unable to determine number of domains.")); - goto err; + goto cleanup; } phyp_driver = conn->privateData; @@ -841,11 +845,12 @@ phypUUIDTable_Init(virConnectPtr conn) /* try to get the table from server */ if (phypUUIDTable_Pull(conn) == -1) { /* file not found in the server, creating a new one */ + table_created = true; if (VIR_ALLOC_N(uuid_table->lpars, uuid_table->nlpars) >= 0) { for (i = 0; i < uuid_table->nlpars; i++) { if (VIR_ALLOC(uuid_table->lpars[i]) < 0) { virReportOOMError(); - goto err; + goto cleanup; } uuid_table->lpars[i]->id = ids[i]; @@ -855,27 +860,30 @@ phypUUIDTable_Init(virConnectPtr conn) } } else { virReportOOMError(); - goto err; + goto cleanup; } if (phypUUIDTable_WriteFile(conn) == -1) - goto err; + goto cleanup; if (phypUUIDTable_Push(conn) == -1) - goto err; + goto cleanup; } else { if (phypUUIDTable_ReadFile(conn) == -1) - goto err; - goto exit; + goto cleanup; } - exit: - VIR_FREE(ids); - return 0; + ret = 0; - err: +cleanup: + if (ret < 0 && table_created) { + for (i = 0; i < uuid_table->nlpars; i++) { + VIR_FREE(uuid_table->lpars[i]); + } + VIR_FREE(uuid_table->lpars); + } VIR_FREE(ids); - return -1; + return ret; } static void -- 1.7.4.2 From eblake at redhat.com Thu Apr 14 20:22:27 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:22:27 -0600 Subject: [libvirt] [PATCHv2 1/9] maint: use lighter-weight function for straight appends In-Reply-To: <1302812555-3418-1-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> Message-ID: <1302812555-3418-2-git-send-email-eblake@redhat.com> It costs quite a few processor cycles to go through printf parsing just to determine that we only meant to append. * src/xen/xend_internal.c (xend_op_ext): Consolidate multiple printfs into one. * src/qemu/qemu_command.c (qemuBuildWatchdogDevStr) (qemuBuildUSBInputDevStr, qemuBuildSoundDevStr) (qemuBuildSoundCodecStr, qemuBuildVideoDevStr): Likewise. (qemuBuildCpuArgStr, qemuBuildCommandLine): Prefer virBufferAdd over virBufferVsprintf for trivial appends. * src/phyp/phyp_driver.c (phypExec, phypUUIDTable_Push) (phypUUIDTable_Pull): Likewise. * src/conf/nwfilter_conf.c (macProtocolIDFormatter) (arpOpcodeFormatter, formatIPProtocolID, printStringItems) (virNWFilterPrintStateMatchFlags, virNWIPAddressFormat) (virNWFilterDefFormat): Likewise. * src/security/virt-aa-helper.c (main): Likewise. * src/util/sexpr.c (sexpr2string): Likewise. * src/xenxs/xen_sxpr.c (xenFormatSxprChr): Likewise. * src/xenxs/xen_xm.c (xenFormatXMDisk): Likewise. --- src/conf/nwfilter_conf.c | 16 ++++++++-------- src/phyp/phyp_driver.c | 7 +++---- src/qemu/qemu_command.c | 30 +++++++++++------------------- src/security/virt-aa-helper.c | 2 +- src/util/sexpr.c | 4 ++-- src/xen/xend_internal.c | 6 ++---- src/xenxs/xen_sxpr.c | 2 +- src/xenxs/xen_xm.c | 4 ++-- 8 files changed, 30 insertions(+), 41 deletions(-) diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 0732322..327fab3 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -488,7 +488,7 @@ macProtocolIDFormatter(virBufferPtr buf, if (intMapGetByInt(macProtoMap, nwf->p.ethHdrFilter.dataProtocolID.u.u16, &str)) { - virBufferVSprintf(buf, "%s", str); + virBufferAdd(buf, str, -1); } else { if (nwf->p.ethHdrFilter.dataProtocolID.datatype == DATATYPE_UINT16) asHex = false; @@ -591,7 +591,7 @@ arpOpcodeFormatter(virBufferPtr buf, if (intMapGetByInt(arpOpcodeMap, nwf->p.arpHdrFilter.dataOpcode.u.u16, &str)) { - virBufferVSprintf(buf, "%s", str); + virBufferAdd(buf, str, -1); } else { virBufferVSprintf(buf, "%d", nwf->p.arpHdrFilter.dataOpcode.u.u16); } @@ -653,7 +653,7 @@ formatIPProtocolID(virBufferPtr buf, if (intMapGetByInt(ipProtoMap, nwf->p.ipHdrFilter.ipHdr.dataProtocolID.u.u8, &str)) { - virBufferVSprintf(buf, "%s", str); + virBufferAdd(buf, str, -1); } else { if (nwf->p.ipHdrFilter.ipHdr.dataProtocolID.datatype == DATATYPE_UINT8) asHex = false; @@ -734,8 +734,8 @@ printStringItems(virBufferPtr buf, const struct int_map *int_map, for (i = 0; int_map[i].val; i++) { if (mask == int_map[i].attr) { if (c >= 1) - virBufferVSprintf(buf, "%s", sep); - virBufferVSprintf(buf, "%s", int_map[i].val); + virBufferAdd(buf, sep, -1); + virBufferAdd(buf, int_map[i].val, -1); c++; } } @@ -769,7 +769,7 @@ virNWFilterPrintStateMatchFlags(virBufferPtr buf, const char *prefix, if (!disp_none && (flags & RULE_FLAG_STATE_NONE)) return; - virBufferVSprintf(buf, "%s", prefix); + virBufferAdd(buf, prefix, -1); printStringItems(buf, stateMatchMap, flags, ","); } @@ -2699,7 +2699,7 @@ virNWIPAddressFormat(virBufferPtr buf, virSocketAddrPtr ipaddr) char *output = virSocketFormatAddr(ipaddr); if (output) { - virBufferVSprintf(buf, "%s", output); + virBufferAdd(buf, output, -1); VIR_FREE(output); } } @@ -2936,7 +2936,7 @@ virNWFilterDefFormat(virNWFilterDefPtr def) xml = virNWFilterEntryFormat(def->filterEntries[i]); if (!xml) goto err_exit; - virBufferVSprintf(&buf, "%s", xml); + virBufferAdd(&buf, xml, -1); VIR_FREE(xml); } diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 3862c9c..5742d95 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -1,4 +1,3 @@ - /* * Copyright (C) 2010-2011 Red Hat, Inc. * Copyright IBM Corp. 2009 @@ -156,7 +155,7 @@ phypExec(LIBSSH2_SESSION *session, const char *cmd, int *exit_status, rc = libssh2_channel_read(channel, buffer, buffer_size); if (rc > 0) { bytecount += rc; - virBufferVSprintf(&tex_ret, "%s", buffer); + virBufferAdd(&tex_ret, buffer, -1); } } while (rc > 0); @@ -494,7 +493,7 @@ phypUUIDTable_Push(virConnectPtr conn) char *remote_file = NULL; if (conn->uri->user != NULL) { - virBufferVSprintf(&username, "%s", conn->uri->user); + virBufferAdd(&username, conn->uri->user, -1); if (virBufferError(&username)) { virBufferFreeAndReset(&username); @@ -711,7 +710,7 @@ phypUUIDTable_Pull(virConnectPtr conn) char *remote_file = NULL; if (conn->uri->user != NULL) { - virBufferVSprintf(&username, "%s", conn->uri->user); + virBufferAdd(&username, conn->uri->user, -1); if (virBufferError(&username)) { virBufferFreeAndReset(&username); diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 71e5062..2205ed1 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1798,8 +1798,7 @@ qemuBuildWatchdogDevStr(virDomainWatchdogDefPtr dev, goto error; } - virBufferVSprintf(&buf, "%s", model); - virBufferVSprintf(&buf, ",id=%s", dev->info.alias); + virBufferVSprintf(&buf, "%s,id=%s", model, dev->info.alias); if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0) goto error; @@ -1845,10 +1844,9 @@ qemuBuildUSBInputDevStr(virDomainInputDefPtr dev) { virBuffer buf = VIR_BUFFER_INITIALIZER; - virBufferVSprintf(&buf, "%s", + virBufferVSprintf(&buf, "%s,id=%s", dev->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ? - "usb-mouse" : "usb-tablet"); - virBufferVSprintf(&buf, ",id=%s", dev->info.alias); + "usb-mouse" : "usb-tablet", dev->info.alias); if (virBufferError(&buf)) { virReportOOMError(); @@ -1884,8 +1882,7 @@ qemuBuildSoundDevStr(virDomainSoundDefPtr sound, else if (STREQ(model, "ich6")) model = "intel-hda"; - virBufferVSprintf(&buf, "%s", model); - virBufferVSprintf(&buf, ",id=%s", sound->info.alias); + virBufferVSprintf(&buf, "%s,id=%s", model, sound->info.alias); if (qemuBuildDeviceAddressStr(&buf, &sound->info, qemuCaps) < 0) goto error; @@ -1908,10 +1905,8 @@ qemuBuildSoundCodecStr(virDomainSoundDefPtr sound, virBuffer buf = VIR_BUFFER_INITIALIZER; int cad = 0; - virBufferVSprintf(&buf, "%s", codec); - virBufferVSprintf(&buf, ",id=%s-codec%d", sound->info.alias, cad); - virBufferVSprintf(&buf, ",bus=%s.0", sound->info.alias); - virBufferVSprintf(&buf, ",cad=%d", cad); + virBufferVSprintf(&buf, "%s,id=%s-codec%d,bus=%s.0,cad=%d", + codec, sound->info.alias, cad, sound->info.alias, cad); if (virBufferError(&buf)) { virReportOOMError(); @@ -1938,8 +1933,7 @@ qemuBuildVideoDevStr(virDomainVideoDefPtr video, goto error; } - virBufferVSprintf(&buf, "%s", model); - virBufferVSprintf(&buf, ",id=%s", video->info.alias); + virBufferVSprintf(&buf, "%s,id=%s", model, video->info.alias); if (video->type == VIR_DOMAIN_VIDEO_TYPE_QXL) { if (video->vram > (UINT_MAX / 1024)) { @@ -2572,7 +2566,7 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver, goto cleanup; *hasHwVirt = hasSVM > 0 ? true : false; - virBufferVSprintf(&buf, "%s", guest->model); + virBufferAdd(&buf, guest->model, -1); for (i = 0; i < guest->nfeatures; i++) { char sign; if (guest->features[i].policy == VIR_CPU_FEATURE_DISABLE) @@ -3128,7 +3122,7 @@ qemuBuildCommandLine(virConnectPtr conn, else if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_DISABLED) virBufferVSprintf(&boot_buf, "order=%s,menu=off", boot); } else { - virBufferVSprintf(&boot_buf, "%s", boot); + virBufferAdd(&boot_buf, boot, -1); } virCommandAddArgBuffer(cmd, &boot_buf); @@ -3291,8 +3285,7 @@ qemuBuildCommandLine(virConnectPtr conn, host->name, host->port); } else { - virBufferVSprintf(&rbd_hosts, "%s", - host->name); + virBufferAdd(&rbd_hosts, host->name, -1); } } } @@ -3414,8 +3407,7 @@ qemuBuildCommandLine(virConnectPtr conn, host->name, host->port); } else { - virBufferVSprintf(&rbd_hosts, "%s", - host->name); + virBufferAdd(&rbd_hosts, host->name, -1); } } break; diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index bb716e6..08ff53c 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1204,7 +1204,7 @@ main(int argc, char **argv) virBufferVSprintf(&buf, " \"%s/run/libvirt/**/%s.pid\" rwk,\n", LOCALSTATEDIR, ctl->def->name); if (ctl->files) - virBufferVSprintf(&buf, "%s", ctl->files); + virBufferAdd(&buf, ctl->files, -1); } if (virBufferError(&buf)) { diff --git a/src/util/sexpr.c b/src/util/sexpr.c index ae1692a..da3d4b3 100644 --- a/src/util/sexpr.c +++ b/src/util/sexpr.c @@ -1,7 +1,7 @@ /* * sexpr.c : S-Expression routines to communicate with the Xen Daemon * - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 Red Hat, Inc. * Copyright (C) 2005 Anthony Liguori * * This file is subject to the terms and conditions of the GNU Lesser General @@ -234,7 +234,7 @@ sexpr2string(const struct sexpr *sexpr, virBufferPtr buffer) strchr(sexpr->u.value, '(')) virBufferVSprintf(buffer, "'%s'", sexpr->u.value); else - virBufferVSprintf(buffer, "%s", sexpr->u.value); + virBufferAdd(buffer, sexpr->u.value, -1); break; case SEXPR_NIL: diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 04122ba..57422d3 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -487,13 +487,11 @@ xend_op_ext(virConnectPtr xend, const char *path, const char *key, va_list ap) while (k) { v = va_arg(ap, const char *); - virBufferVSprintf(&buf, "%s", k); - virBufferVSprintf(&buf, "%s", "="); - virBufferVSprintf(&buf, "%s", v); + virBufferVSprintf(&buf, "%s=%s", k, v); k = va_arg(ap, const char *); if (k) - virBufferVSprintf(&buf, "%s", "&"); + virBufferAddChar(&buf, '&'); } if (virBufferError(&buf)) { diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c index b590517..d2ec370 100644 --- a/src/xenxs/xen_sxpr.c +++ b/src/xenxs/xen_sxpr.c @@ -1514,7 +1514,7 @@ xenFormatSxprChr(virDomainChrDefPtr def, case VIR_DOMAIN_CHR_TYPE_STDIO: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_PTY: - virBufferVSprintf(buf, "%s", type); + virBufferAdd(buf, type, -1); break; case VIR_DOMAIN_CHR_TYPE_FILE: diff --git a/src/xenxs/xen_xm.c b/src/xenxs/xen_xm.c index 89f75a5..dbcaf15 100644 --- a/src/xenxs/xen_xm.c +++ b/src/xenxs/xen_xm.c @@ -1115,13 +1115,13 @@ static int xenFormatXMDisk(virConfValuePtr list, goto cleanup; } } - virBufferVSprintf(&buf, "%s", disk->src); + virBufferAdd(&buf, disk->src, -1); } virBufferAddLit(&buf, ","); if (hvm && xendConfigVersion == 1) virBufferAddLit(&buf, "ioemu:"); - virBufferVSprintf(&buf, "%s", disk->dst); + virBufferAdd(&buf, disk->dst, -1); if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) virBufferAddLit(&buf, ":cdrom"); -- 1.7.4.2 From eblake at redhat.com Thu Apr 14 20:22:32 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:22:32 -0600 Subject: [libvirt] [PATCHv2 6/9] phyp: prefer memcpy over memmove when legal In-Reply-To: <1302812555-3418-1-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> Message-ID: <1302812555-3418-7-git-send-email-eblake@redhat.com> * src/phyp/phyp_driver.c (phypUUIDTable_AddLpar) (phypGetLparUUID, phypGetStoragePoolUUID, phypVolumeGetXMLDesc) (phypGetStoragePoolXMLDesc): Use faster method. --- src/phyp/phyp_driver.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index a952875..27536eb 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -624,7 +624,7 @@ phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id) } uuid_table->lpars[i]->id = id; - memmove(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN); + memcpy(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN); if (phypUUIDTable_WriteFile(conn) == -1) goto err; @@ -1388,7 +1388,7 @@ phypGetLparUUID(unsigned char *uuid, int lpar_id, virConnectPtr conn) for (i = 0; i < uuid_table->nlpars; i++) { if (lpars[i]->id == lpar_id) { - memmove(uuid, lpars[i]->uuid, VIR_UUID_BUFLEN); + memcpy(uuid, lpars[i]->uuid, VIR_UUID_BUFLEN); return 0; } } @@ -2609,7 +2609,7 @@ phypGetStoragePoolUUID(virConnectPtr conn, unsigned char *uuid, if (exit_status < 0 || ret == NULL) goto cleanup; - if (memmove(uuid, ret, VIR_UUID_BUFLEN) == NULL) + if (memcpy(uuid, ret, VIR_UUID_BUFLEN) == NULL) goto cleanup; result = 0; @@ -2657,7 +2657,7 @@ phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags) goto err; } - if (memmove(pool.uuid, sp->uuid, VIR_UUID_BUFLEN) == NULL) { + if (memcpy(pool.uuid, sp->uuid, VIR_UUID_BUFLEN) == NULL) { VIR_ERROR0(_("Unable to determine storage sp's uuid.")); goto err; } @@ -3241,7 +3241,7 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags) goto err; } - if (memmove(def.uuid, pool->uuid, VIR_UUID_BUFLEN) == NULL) { + if (memcpy(def.uuid, pool->uuid, VIR_UUID_BUFLEN) == NULL) { VIR_ERROR0(_("Unable to determine storage pool's uuid.")); goto err; } -- 1.7.4.2 From eblake at redhat.com Thu Apr 14 20:22:31 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:22:31 -0600 Subject: [libvirt] [PATCHv2 5/9] phyp: use consistent style for labels In-Reply-To: <1302812555-3418-1-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> Message-ID: <1302812555-3418-6-git-send-email-eblake@redhat.com> * src/phyp/phyp_driver.c: Match label style of rest of project. (phypExec, phypUUIDTable_Pull): Drop an extra label. --- src/phyp/phyp_driver.c | 129 +++++++++++++++++++++++------------------------- 1 files changed, 62 insertions(+), 67 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 37395c6..a952875 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -182,15 +182,6 @@ phypExec(LIBSSH2_SESSION *session, const char *cmd, int *exit_status, (*exit_status) = exitcode; libssh2_channel_free(channel); channel = NULL; - goto exit; - - err: - (*exit_status) = SSH_CMD_ERR; - virBufferFreeAndReset(&tex_ret); - VIR_FREE(buffer); - return NULL; - - exit: VIR_FREE(buffer); if (virBufferError(&tex_ret)) { @@ -199,6 +190,12 @@ phypExec(LIBSSH2_SESSION *session, const char *cmd, int *exit_status, return NULL; } return virBufferContentAndReset(&tex_ret); + +err: + (*exit_status) = SSH_CMD_ERR; + virBufferFreeAndReset(&tex_ret); + VIR_FREE(buffer); + return NULL; } static int @@ -256,7 +253,7 @@ phypGetVIOSPartitionID(virConnectPtr conn) if (virStrToLong_i(ret, &char_ptr, 10, &id) == -1) goto cleanup; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -302,7 +299,7 @@ phypCapsInit(void) return caps; - no_memory: +no_memory: virCapabilitiesFree(caps); return NULL; } @@ -362,7 +359,7 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) if (virStrToLong_i(ret, &char_ptr, 10, &ndom) == -1) goto cleanup; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -430,7 +427,7 @@ phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids, line++; /* skip \n */ } - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -471,7 +468,7 @@ phypUUIDTable_WriteFile(virConnectPtr conn) } return 0; - err: +err: VIR_FORCE_CLOSE(fd); return -1; } @@ -569,7 +566,7 @@ phypUUIDTable_Push(virConnectPtr conn) virBufferFreeAndReset(&username); return 0; - err: +err: if (channel) { libssh2_channel_send_eof(channel); libssh2_channel_wait_eof(channel); @@ -602,7 +599,7 @@ phypUUIDTable_RemLpar(virConnectPtr conn, int id) return 0; - err: +err: return -1; } @@ -637,7 +634,7 @@ phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id) return 0; - err: +err: return -1; } @@ -686,7 +683,7 @@ phypUUIDTable_ReadFile(virConnectPtr conn) VIR_FORCE_CLOSE(fd); return 0; - err: +err: VIR_FORCE_CLOSE(fd); return -1; } @@ -780,9 +777,7 @@ phypUUIDTable_Pull(virConnectPtr conn) local_file); goto err; } - goto exit; - exit: if (channel) { libssh2_channel_send_eof(channel); libssh2_channel_wait_eof(channel); @@ -793,7 +788,7 @@ phypUUIDTable_Pull(virConnectPtr conn) virBufferFreeAndReset(&username); return 0; - err: +err: if (channel) { libssh2_channel_send_eof(channel); libssh2_channel_wait_eof(channel); @@ -1041,7 +1036,7 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth, freeaddrinfo(ai); goto err; - connected: +connected: (*internal_socket) = sock; @@ -1074,7 +1069,7 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth, NULL)) == LIBSSH2_ERROR_EAGAIN) ; - keyboard_interactive: +keyboard_interactive: if (rc == LIBSSH2_ERROR_SOCKET_NONE || rc == LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED || rc == LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED) { @@ -1112,10 +1107,10 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth, goto err; } - disconnect: +disconnect: libssh2_session_disconnect(session, "Disconnecting..."); libssh2_session_free(session); - err: +err: VIR_FREE(userhome); VIR_FREE(pubkey); VIR_FREE(pvtkey); @@ -1123,7 +1118,7 @@ openSSHSession(virConnectPtr conn, virConnectAuthPtr auth, VIR_FREE(password); return NULL; - exit: +exit: VIR_FREE(userhome); VIR_FREE(pubkey); VIR_FREE(pvtkey); @@ -1235,7 +1230,7 @@ phypOpen(virConnectPtr conn, return VIR_DRV_OPEN_SUCCESS; - failure: +failure: if (phyp_driver != NULL) { virCapabilitiesFree(phyp_driver->caps); VIR_FREE(phyp_driver->managed_system); @@ -1327,7 +1322,7 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) goto cleanup; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -1370,7 +1365,7 @@ phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system, if (char_ptr) *char_ptr = '\0'; - cleanup: +cleanup: VIR_FREE(cmd); return ret; @@ -1450,7 +1445,7 @@ phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id, if (virStrToLong_i(ret, &char_ptr, 10, &memory) == -1) goto cleanup; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -1498,7 +1493,7 @@ phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system, if (virStrToLong_i(ret, &char_ptr, 10, &vcpus) == -1) goto cleanup; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -1572,7 +1567,7 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, if (virStrToLong_i(ret, &char_ptr, 10, &remote_slot) == -1) goto cleanup; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -1651,7 +1646,7 @@ phypGetBackingDevice(virConnectPtr conn, const char *managed_system, if (char_ptr) *char_ptr = '\0'; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -1697,7 +1692,7 @@ phypGetLparProfile(virConnectPtr conn, int lpar_id) if (char_ptr) *char_ptr = '\0'; - cleanup: +cleanup: VIR_FREE(cmd); return ret; @@ -1755,7 +1750,7 @@ phypGetVIOSNextSlotNumber(virConnectPtr conn) slot += 1; - cleanup: +cleanup: VIR_FREE(profile); VIR_FREE(cmd); VIR_FREE(ret); @@ -1869,7 +1864,7 @@ phypCreateServerSCSIAdapter(virConnectPtr conn) result = 0; - cleanup: +cleanup: VIR_FREE(profile); VIR_FREE(vios_name); VIR_FREE(cmd); @@ -1923,7 +1918,7 @@ phypGetVIOSFreeSCSIAdapter(virConnectPtr conn) if (char_ptr) *char_ptr = '\0'; - cleanup: +cleanup: VIR_FREE(cmd); return ret; @@ -2133,7 +2128,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) result = 0; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); virDomainDeviceDefFree(dev); @@ -2191,7 +2186,7 @@ phypVolumeGetKey(virConnectPtr conn, const char *name) if (char_ptr) *char_ptr = '\0'; - cleanup: +cleanup: VIR_FREE(cmd); return ret; @@ -2242,7 +2237,7 @@ phypGetStoragePoolDevice(virConnectPtr conn, char *name) if (char_ptr) *char_ptr = '\0'; - cleanup: +cleanup: VIR_FREE(cmd); return ret; @@ -2290,7 +2285,7 @@ phypGetStoragePoolSize(virConnectPtr conn, char *name) if (virStrToLong_i(ret, &char_ptr, 10, &sp_size) == -1) goto cleanup; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -2341,7 +2336,7 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, if (key == NULL) goto cleanup; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -2454,7 +2449,7 @@ phypStorageVolCreateXML(virStoragePoolPtr pool, return vol; - err: +err: VIR_FREE(key); virStorageVolDefFree(voldef); virStoragePoolDefFree(spdef); @@ -2509,7 +2504,7 @@ phypVolumeGetPhysicalVolumeByStoragePool(virStorageVolPtr vol, char *sp) if (char_ptr) *char_ptr = '\0'; - cleanup: +cleanup: VIR_FREE(cmd); return ret; @@ -2567,7 +2562,7 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) vol = virGetStorageVol(conn, spname, volname, key); - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(spname); VIR_FREE(key); @@ -2619,7 +2614,7 @@ phypGetStoragePoolUUID(virConnectPtr conn, unsigned char *uuid, result = 0; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -2706,7 +2701,7 @@ phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags) return xml; - err: +err: return NULL; } @@ -2775,7 +2770,7 @@ phypVolumeGetPath(virStorageVolPtr vol) goto cleanup; } - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(sp); VIR_FREE(path); @@ -2849,7 +2844,7 @@ phypStoragePoolListVolumes(virStoragePoolPtr pool, char **const volumes, success = true; - cleanup: +cleanup: if (!success) { for (i = 0; i < got; i++) VIR_FREE(volumes[i]); @@ -2906,7 +2901,7 @@ phypStoragePoolNumOfVolumes(virStoragePoolPtr pool) /* We need to remove 2 line from the header text output */ nvolumes -= 2; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -2953,7 +2948,7 @@ phypDestroyStoragePool(virStoragePoolPtr pool) result = 0; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -3002,7 +2997,7 @@ phypBuildStoragePool(virConnectPtr conn, virStoragePoolDefPtr def) result = 0; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -3052,7 +3047,7 @@ phypNumOfStoragePools(virConnectPtr conn) if (virStrToLong_i(ret, &char_ptr, 10, &nsp) == -1) goto cleanup; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -3120,7 +3115,7 @@ phypListStoragePools(virConnectPtr conn, char **const pools, int npools) success = true; - cleanup: +cleanup: if (!success) { for (i = 0; i < got; i++) VIR_FREE(pools[i]); @@ -3186,7 +3181,7 @@ phypGetStoragePoolLookUpByUUID(virConnectPtr conn, } } - err: +err: VIR_FREE(local_uuid); VIR_FREE(pools); return NULL; @@ -3224,7 +3219,7 @@ phypStoragePoolCreateXML(virConnectPtr conn, return sp; - err: +err: virStoragePoolDefFree(def); if (sp) virUnrefStoragePool(sp); @@ -3272,7 +3267,7 @@ phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags) return virStoragePoolDefFormat(&def); - err: +err: return NULL; } @@ -3857,7 +3852,7 @@ phypGetLparState(virConnectPtr conn, unsigned int lpar_id) else if (STREQ(ret, "Shutting Down")) state = VIR_DOMAIN_SHUTDOWN; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); return state; @@ -3909,7 +3904,7 @@ phypDiskType(virConnectPtr conn, char *backing_device) else if (STREQ(ret, "FBPOOL")) disk_type = VIR_DOMAIN_DISK_TYPE_FILE; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); return disk_type; @@ -3989,7 +3984,7 @@ phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames) success = true; - cleanup: +cleanup: if (!success) { for (i = 0; i < got; i++) VIR_FREE(names[i]); @@ -4054,7 +4049,7 @@ phypDomainLookupByID(virConnectPtr conn, int lpar_id) if (dom) dom->id = lpar_id; - cleanup: +cleanup: VIR_FREE(lpar_name); return dom; @@ -4107,7 +4102,7 @@ phypDomainDumpXML(virDomainPtr dom, int flags) return virDomainDefFormat(&def, flags); - err: +err: return NULL; } @@ -4144,7 +4139,7 @@ phypDomainResume(virDomainPtr dom) result = 0; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -4184,7 +4179,7 @@ phypDomainShutdown(virDomainPtr dom) result = 0; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -4250,7 +4245,7 @@ phypDomainDestroy(virDomainPtr dom) dom->id = -1; result = 0; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -4327,7 +4322,7 @@ phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) result = 0; - cleanup: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); @@ -4381,7 +4376,7 @@ phypDomainCreateAndStart(virConnectPtr conn, return dom; - err: +err: virDomainDefFree(def); if (dom) virUnrefDomain(dom); -- 1.7.4.2 From eblake at redhat.com Thu Apr 14 20:22:33 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:22:33 -0600 Subject: [libvirt] [PATCHv2 7/9] phyp: use consistent return string handling In-Reply-To: <1302812555-3418-1-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> Message-ID: <1302812555-3418-8-git-send-email-eblake@redhat.com> Use the name 'ret' for all phypExec results, to make it easier to wrap phypExec. Don't allow a possibly NULL ret through printf. * src/phyp/phyp_driver.c (phypBuildVolume, phypDestroyStoragePool) (phypBuildStoragePool, phypBuildLpar): Avoid NULL dereference. (phypInterfaceDestroy): Avoid redundant free. (phypVolumeLookupByPath, phypVolumeGetPath): Use consistent naming. --- src/phyp/phyp_driver.c | 37 +++++++++++++++++-------------------- 1 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 27536eb..56909af 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -2327,7 +2327,7 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0) { - VIR_ERROR(_("Unable to create Volume: %s"), ret); + VIR_ERROR(_("Unable to create Volume: %s"), NULLSTR(ret)); goto cleanup; } @@ -2521,7 +2521,7 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) int vios_id = phyp_driver->vios_id; int exit_status = 0; char *cmd = NULL; - char *spname = NULL; + char *ret = NULL; char *char_ptr; char *key = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -2545,12 +2545,12 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) } cmd = virBufferContentAndReset(&buf); - spname = phypExec(session, cmd, &exit_status, conn); + ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0 || spname == NULL) + if (exit_status < 0 || ret == NULL) goto cleanup; - char_ptr = strchr(spname, '\n'); + char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; @@ -2560,11 +2560,11 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) if (key == NULL) goto cleanup; - vol = virGetStorageVol(conn, spname, volname, key); + vol = virGetStorageVol(conn, ret, volname, key); cleanup: VIR_FREE(cmd); - VIR_FREE(spname); + VIR_FREE(ret); VIR_FREE(key); return vol; @@ -2725,7 +2725,7 @@ phypVolumeGetPath(virStorageVolPtr vol) int vios_id = phyp_driver->vios_id; int exit_status = 0; char *cmd = NULL; - char *sp = NULL; + char *ret = NULL; char *path = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; char *char_ptr; @@ -2750,33 +2750,32 @@ phypVolumeGetPath(virStorageVolPtr vol) } cmd = virBufferContentAndReset(&buf); - sp = phypExec(session, cmd, &exit_status, conn); + ret = phypExec(session, cmd, &exit_status, conn); - if (exit_status < 0 || sp == NULL) + if (exit_status < 0 || ret == NULL) goto cleanup; - char_ptr = strchr(sp, '\n'); + char_ptr = strchr(ret, '\n'); if (char_ptr) *char_ptr = '\0'; - pv = phypVolumeGetPhysicalVolumeByStoragePool(vol, sp); + pv = phypVolumeGetPhysicalVolumeByStoragePool(vol, ret); if (!pv) goto cleanup; - if (virAsprintf(&path, "/%s/%s/%s", pv, sp, vol->name) < 0) { + if (virAsprintf(&path, "/%s/%s/%s", pv, ret, vol->name) < 0) { virReportOOMError(); goto cleanup; } cleanup: VIR_FREE(cmd); - VIR_FREE(sp); + VIR_FREE(ret); VIR_FREE(path); return path; - } static int @@ -2942,7 +2941,7 @@ phypDestroyStoragePool(virStoragePoolPtr pool) ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0) { - VIR_ERROR(_("Unable to destroy Storage Pool: %s"), ret); + VIR_ERROR(_("Unable to destroy Storage Pool: %s"), NULLSTR(ret)); goto cleanup; } @@ -2991,7 +2990,7 @@ phypBuildStoragePool(virConnectPtr conn, virStoragePoolDefPtr def) ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0) { - VIR_ERROR(_("Unable to create Storage Pool: %s"), ret); + VIR_ERROR(_("Unable to create Storage Pool: %s"), NULLSTR(ret)); goto cleanup; } @@ -3337,8 +3336,6 @@ phypInterfaceDestroy(virInterfacePtr iface, } cmd = virBufferContentAndReset(&buf); - VIR_FREE(ret); - ret = phypExec(session, cmd, &exit_status, iface->conn); if (exit_status < 0 || ret == NULL) @@ -4311,7 +4308,7 @@ phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0) { - VIR_ERROR(_("Unable to create LPAR. Reason: '%s'"), ret); + VIR_ERROR(_("Unable to create LPAR. Reason: '%s'"), NULLSTR(ret)); goto cleanup; } -- 1.7.4.2 From eblake at redhat.com Thu Apr 14 20:22:35 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:22:35 -0600 Subject: [libvirt] [PATCHv2 9/9] phyp: another simplification In-Reply-To: <1302812555-3418-1-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> Message-ID: <1302812555-3418-10-git-send-email-eblake@redhat.com> Rather than copying and pasting lots of code, factor it into a single helper function. * src/phyp/phyp_driver.c (phypExecInt): New function. (phypGetVIOSPartitionID, phypNumDomainsGeneric, phypGetLparID) (phypGetLparMem, phypGetLparCPUGeneric, phypGetRemoteSlot) (phypGetVIOSNextSlotNumber, phypAttachDevice) (phypGetStoragePoolSize, phypStoragePoolNumOfVolumes) (phypNumOfStoragePools, phypInterfaceDestroy) (phypInterfaceDefineXML, phypInterfaceLookupByName) (phypInterfaceIsActive, phypNumOfInterfaces): Use it. --- src/phyp/phyp_driver.c | 316 ++++++++++-------------------------------------- 1 files changed, 67 insertions(+), 249 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index bc24b76..98d5cd6 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -228,6 +228,26 @@ phypExecBuffer(LIBSSH2_SESSION *session, virBufferPtr buf, int *exit_status, return ret; } +/* Convenience wrapper function */ +static int phypExecInt(LIBSSH2_SESSION *, virBufferPtr, virConnectPtr, int *) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); +static int +phypExecInt(LIBSSH2_SESSION *session, virBufferPtr buf, virConnectPtr conn, + int *result) +{ + char *str; + int ret; + + str = phypExecBuffer(session, buf, &ret, conn, true); + if (!str || ret) { + VIR_FREE(str); + return -1; + } + ret = virStrToLong_i(str, NULL, 10, result); + VIR_FREE(str); + return ret; +} + static int phypGetSystemType(virConnectPtr conn) { @@ -255,10 +275,7 @@ phypGetVIOSPartitionID(virConnectPtr conn) phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; int system_type = phyp_driver->system_type; - char *ret = NULL; - int exit_status = 0; int id = -1; - char *char_ptr; char *managed_system = phyp_driver->managed_system; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -267,17 +284,7 @@ phypGetVIOSPartitionID(virConnectPtr conn) virBufferVSprintf(&buf, " -m %s", managed_system); virBufferAddLit(&buf, " -r lpar -F lpar_id,lpar_env" "|sed -n '/vioserver/ {\n s/,.*$//\n p\n}'"); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &id) == -1) - goto cleanup; - -cleanup: - VIR_FREE(ret); - + phypExecInt(session, &buf, conn, &id); return id; } @@ -340,10 +347,7 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; int system_type = phyp_driver->system_type; - int exit_status = 0; int ndom = -1; - char *char_ptr; - char *ret = NULL; char *managed_system = phyp_driver->managed_system; const char *state; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -364,17 +368,7 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9]*'", state); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &ndom) == -1) - goto cleanup; - -cleanup: - VIR_FREE(ret); - + phypExecInt(session, &buf, conn, &ndom); return ndom; } @@ -1298,27 +1292,14 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, { phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; - int exit_status = 0; int lpar_id = -1; - char *char_ptr; - char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; virBufferAddLit(&buf, "lssyscfg -r lpar"); if (system_type == HMC) virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " --filter lpar_names=%s -F lpar_id", name); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) - goto cleanup; - -cleanup: - VIR_FREE(ret); - + phypExecInt(session, &buf, conn, &lpar_id); return lpar_id; } @@ -1382,10 +1363,7 @@ phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id, LIBSSH2_SESSION *session = connection_data->session; phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; - char *ret = NULL; - char *char_ptr; int memory = 0; - int exit_status = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; if (type != 1 && type != 0) @@ -1397,17 +1375,7 @@ phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id, virBufferVSprintf(&buf, " -r mem --level lpar -F %s --filter lpar_ids=%d", type ? "curr_mem" : "curr_max_mem", lpar_id); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &memory) == -1) - goto cleanup; - -cleanup: - VIR_FREE(ret); - + phypExecInt(session, &buf, conn, &memory); return memory; } @@ -1419,9 +1387,6 @@ phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system, LIBSSH2_SESSION *session = connection_data->session; phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; - char *ret = NULL; - char *char_ptr; - int exit_status = 0; int vcpus = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -1431,17 +1396,7 @@ phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system, virBufferVSprintf(&buf, " -r proc --level lpar -F %s --filter lpar_ids=%d", type ? "curr_max_procs" : "curr_procs", lpar_id); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &vcpus) == -1) - goto cleanup; - -cleanup: - VIR_FREE(ret); - + phypExecInt(session, &buf, conn, &vcpus); return vcpus; } @@ -1480,10 +1435,7 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, LIBSSH2_SESSION *session = connection_data->session; phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; - char *ret = NULL; - char *char_ptr; int remote_slot = -1; - int exit_status = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; virBufferAddLit(&buf, "lshwres"); @@ -1491,17 +1443,7 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -r virtualio --rsubtype scsi -F " "remote_slot_num --filter lpar_names=%s", lpar_name); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &remote_slot) == -1) - goto cleanup; - -cleanup: - VIR_FREE(ret); - + phypExecInt(session, &buf, conn, &remote_slot); return remote_slot; } @@ -1609,9 +1551,6 @@ phypGetVIOSNextSlotNumber(virConnectPtr conn) char *managed_system = phyp_driver->managed_system; int system_type = phyp_driver->system_type; int vios_id = phyp_driver->vios_id; - int exit_status = 0; - char *char_ptr; - char *ret = NULL; char *profile = NULL; int slot = -1; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -1632,21 +1571,9 @@ phypGetVIOSNextSlotNumber(virConnectPtr conn) "virtual_serial_adapters|sed -e 's/\"//g' -e " "'s/,/\\n/g'|sed -e 's/\\(^[0-9][0-9]\\*\\).*$/\\1/'" "|sort|tail -n 1", profile); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) - goto cleanup; - - slot += 1; - -cleanup: - VIR_FREE(profile); - VIR_FREE(ret); - - return slot; + if (phypExecInt(session, &buf, conn, &slot) < 0) + return -1; + return slot + 1; } static int @@ -1779,7 +1706,6 @@ phypAttachDevice(virDomainPtr domain, const char *xml) int system_type = phyp_driver->system_type; int vios_id = phyp_driver->vios_id; int exit_status = 0; - char *char_ptr = NULL; char *ret = NULL; char *scsi_adapter = NULL; int slot = 0; @@ -1859,12 +1785,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) virBufferVSprintf(&buf, " slot_num,backing_device|grep %s|cut -d, -f1", dev->data.disk->src); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) + if (phypExecInt(session, &buf, conn, &slot) < 0) goto cleanup; /* Listing all the virtual_scsi_adapter interfaces, the new adapter must @@ -1893,10 +1814,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) "\"virtual_scsi_adapters=%s,%d/client/%d/%s/0\"'", domain_name, domain->id, ret, slot, vios_id, vios_name); - VIR_FREE(ret); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) + if (phypExecInt(session, &buf, conn, &slot) < 0) goto cleanup; /* Finally I add the new scsi adapter to VIOS using the same slot @@ -1999,11 +1917,8 @@ phypGetStoragePoolSize(virConnectPtr conn, char *name) LIBSSH2_SESSION *session = connection_data->session; char *managed_system = phyp_driver->managed_system; int system_type = phyp_driver->system_type; - int exit_status = 0; int vios_id = phyp_driver->vios_id; - char *ret = NULL; int sp_size = -1; - char *char_ptr; virBuffer buf = VIR_BUFFER_INITIALIZER; if (system_type == HMC) @@ -2016,17 +1931,7 @@ phypGetStoragePoolSize(virConnectPtr conn, char *name) virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|sed '1d; s/ //g'"); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &sp_size) == -1) - goto cleanup; - -cleanup: - VIR_FREE(ret); - + phypExecInt(session, &buf, conn, &sp_size); return sp_size; } @@ -2457,7 +2362,7 @@ phypStoragePoolListVolumes(virStoragePoolPtr pool, char **const volumes, int i; char *ret = NULL; char *volumes_list = NULL; - char *char_ptr2 = NULL; + char *char_ptr = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; if (system_type == HMC) @@ -2479,16 +2384,16 @@ phypStoragePoolListVolumes(virStoragePoolPtr pool, char **const volumes, volumes_list = ret; while (got < nvolumes) { - char_ptr2 = strchr(volumes_list, '\n'); + char_ptr = strchr(volumes_list, '\n'); - if (char_ptr2) { - *char_ptr2 = '\0'; + if (char_ptr) { + *char_ptr = '\0'; if ((volumes[got++] = strdup(volumes_list)) == NULL) { virReportOOMError(); goto cleanup; } - char_ptr2++; - volumes_list = char_ptr2; + char_ptr++; + volumes_list = char_ptr; } else break; } @@ -2515,12 +2420,9 @@ phypStoragePoolNumOfVolumes(virStoragePoolPtr pool) phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; int system_type = phyp_driver->system_type; - int exit_status = 0; int nvolumes = -1; - char *ret = NULL; char *managed_system = phyp_driver->managed_system; int vios_id = phyp_driver->vios_id; - char *char_ptr; virBuffer buf = VIR_BUFFER_INITIALIZER; if (system_type == HMC) @@ -2530,21 +2432,11 @@ phypStoragePoolNumOfVolumes(virStoragePoolPtr pool) if (system_type == HMC) virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|grep -c '^.*$'"); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &nvolumes) == -1) - goto cleanup; + if (phypExecInt(session, &buf, conn, &nvolumes) < 0) + return -1; /* We need to remove 2 line from the header text output */ - nvolumes -= 2; - -cleanup: - VIR_FREE(ret); - - return nvolumes; + return nvolumes - 2; } static int @@ -2632,12 +2524,9 @@ phypNumOfStoragePools(virConnectPtr conn) phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; int system_type = phyp_driver->system_type; - int exit_status = 0; int nsp = -1; - char *ret = NULL; char *managed_system = phyp_driver->managed_system; int vios_id = phyp_driver->vios_id; - char *char_ptr; virBuffer buf = VIR_BUFFER_INITIALIZER; if (system_type == HMC) @@ -2650,17 +2539,7 @@ phypNumOfStoragePools(virConnectPtr conn) virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|grep -c '^.*$'"); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &nsp) == -1) - goto cleanup; - -cleanup: - VIR_FREE(ret); - + phypExecInt(session, &buf, conn, &nsp); return nsp; } @@ -2679,7 +2558,7 @@ phypListStoragePools(virConnectPtr conn, char **const pools, int npools) int i; char *ret = NULL; char *storage_pools = NULL; - char *char_ptr2 = NULL; + char *char_ptr = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; if (system_type == HMC) @@ -2699,16 +2578,16 @@ phypListStoragePools(virConnectPtr conn, char **const pools, int npools) storage_pools = ret; while (got < npools) { - char_ptr2 = strchr(storage_pools, '\n'); + char_ptr = strchr(storage_pools, '\n'); - if (char_ptr2) { - *char_ptr2 = '\0'; + if (char_ptr) { + *char_ptr = '\0'; if ((pools[got++] = strdup(storage_pools)) == NULL) { virReportOOMError(); goto cleanup; } - char_ptr2++; - storage_pools = char_ptr2; + char_ptr++; + storage_pools = char_ptr; } else break; } @@ -2884,7 +2763,6 @@ phypInterfaceDestroy(virInterfacePtr iface, int exit_status = 0; int slot_num = 0; int lpar_id = 0; - char *char_ptr; char *ret = NULL; int rv = -1; @@ -2898,17 +2776,10 @@ phypInterfaceDestroy(virInterfacePtr iface, " -r virtualio --rsubtype eth --level lpar " " -F mac_addr,slot_num|" " sed -n '/%s/ s/^.*,//p'", iface->mac); - ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &slot_num) == -1) + if (phypExecInt(session, &buf, iface->conn, &slot_num) < 0) goto cleanup; /* Getting the remote slot number */ - VIR_FREE(ret); - virBufferAddLit(&buf, "lshwres "); if (system_type == HMC) virBufferVSprintf(&buf, "-m %s ", managed_system); @@ -2917,17 +2788,10 @@ phypInterfaceDestroy(virInterfacePtr iface, " -r virtualio --rsubtype eth --level lpar " " -F mac_addr,lpar_id|" " sed -n '/%s/ s/^.*,//p'", iface->mac); - ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) + if (phypExecInt(session, &buf, iface->conn, &lpar_id) < 0) goto cleanup; /* excluding interface */ - VIR_FREE(ret); - virBufferAddLit(&buf, "chhwres "); if (system_type == HMC) virBufferVSprintf(&buf, "-m %s ", managed_system); @@ -2960,7 +2824,6 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, char *managed_system = phyp_driver->managed_system; int system_type = phyp_driver->system_type; int exit_status = 0; - char *char_ptr; int slot = 0; char *ret = NULL; char name[PHYP_IFACENAME_SIZE]; @@ -2980,20 +2843,13 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, " -r virtualio --rsubtype slot --level slot" " -Fslot_num --filter lpar_names=%s" " |sort|tail -n 1", def->name); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) + if (phypExecInt(session, &buf, conn, &slot) < 0) goto cleanup; /* The next free slot itself: */ slot++; /* Now adding the new network interface */ - VIR_FREE(ret); - virBufferAddLit(&buf, "chhwres "); if (system_type == HMC) virBufferVSprintf(&buf, "-m %s ", managed_system); @@ -3078,7 +2934,6 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) char *managed_system = phyp_driver->managed_system; int system_type = phyp_driver->system_type; int exit_status = 0; - char *char_ptr; char *ret = NULL; int slot = 0; int lpar_id = 0; @@ -3094,17 +2949,10 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) " -r virtualio --rsubtype slot --level slot " " -F drc_name,slot_num |" " sed -n '/%s/ s/^.*,//p'", name); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) + if (phypExecInt(session, &buf, conn, &slot) < 0) goto cleanup; /*Getting the lpar_id for the interface */ - VIR_FREE(ret); - virBufferAddLit(&buf, "lshwres "); if (system_type == HMC) virBufferVSprintf(&buf, "-m %s ", managed_system); @@ -3113,12 +2961,7 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) " -r virtualio --rsubtype slot --level slot " " -F drc_name,lpar_id |" " sed -n '/%s/ s/^.*,//p'", name); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) + if (phypExecInt(session, &buf, conn, &lpar_id) < 0) goto cleanup; /*Getting the interface mac */ @@ -3130,7 +2973,6 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) " -r virtualio --rsubtype eth --level lpar " " -F lpar_id,slot_num,mac_addr|" " sed -n '/%d,%d/ s/^.*,//p'", lpar_id, slot); - VIR_FREE(ret); ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) @@ -3154,10 +2996,7 @@ phypInterfaceIsActive(virInterfacePtr iface) virBuffer buf = VIR_BUFFER_INITIALIZER; char *managed_system = phyp_driver->managed_system; int system_type = phyp_driver->system_type; - int exit_status = 0; int state = -1; - char *char_ptr; - char *ret = NULL; virBufferAddLit(&buf, "lshwres "); if (system_type == HMC) @@ -3167,16 +3006,7 @@ phypInterfaceIsActive(virInterfacePtr iface) " -r virtualio --rsubtype eth --level lpar " " -F mac_addr,state |" " sed -n '/%s/ s/^.*,//p'", iface->mac); - ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &state) == -1) - goto cleanup; - -cleanup: - VIR_FREE(ret); + phypExecInt(session, &buf, iface->conn, &state); return state; } @@ -3194,7 +3024,7 @@ phypListInterfaces(virConnectPtr conn, char **const names, int nnames) int i; char *ret = NULL; char *networks = NULL; - char *char_ptr2 = NULL; + char *char_ptr = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; bool success = false; @@ -3214,16 +3044,16 @@ phypListInterfaces(virConnectPtr conn, char **const names, int nnames) networks = ret; while (got < nnames) { - char_ptr2 = strchr(networks, '\n'); + char_ptr = strchr(networks, '\n'); - if (char_ptr2) { - *char_ptr2 = '\0'; + if (char_ptr) { + *char_ptr = '\0'; if ((names[got++] = strdup(networks)) == NULL) { virReportOOMError(); goto cleanup; } - char_ptr2++; - networks = char_ptr2; + char_ptr++; + networks = char_ptr; } else { break; } @@ -3247,10 +3077,7 @@ phypNumOfInterfaces(virConnectPtr conn) char *managed_system = phyp_driver->managed_system; int system_type = phyp_driver->system_type; int vios_id = phyp_driver->vios_id; - int exit_status = 0; int nnets = -1; - char *char_ptr; - char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; virBufferAddLit(&buf, "lshwres "); @@ -3260,16 +3087,7 @@ phypNumOfInterfaces(virConnectPtr conn) virBufferVSprintf(&buf, "-r virtualio --rsubtype eth --level lpar|" "grep -v lpar_id=%d|grep -c lpar_name", vios_id); - ret = phypExecBuffer(session, &buf, &exit_status, conn, false); - - if (exit_status < 0 || ret == NULL) - goto cleanup; - - if (virStrToLong_i(ret, &char_ptr, 10, &nnets) == -1) - goto cleanup; - -cleanup: - VIR_FREE(ret); + phypExecInt(session, &buf, conn, &nnets); return nnets; } @@ -3376,7 +3194,7 @@ phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames) int i; char *ret = NULL; char *domains = NULL; - char *char_ptr2 = NULL; + char *char_ptr = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; virBufferAddLit(&buf, "lssyscfg -r lpar"); @@ -3393,16 +3211,16 @@ phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames) domains = ret; while (got < nnames) { - char_ptr2 = strchr(domains, '\n'); + char_ptr = strchr(domains, '\n'); - if (char_ptr2) { - *char_ptr2 = '\0'; + if (char_ptr) { + *char_ptr = '\0'; if ((names[got++] = strdup(domains)) == NULL) { virReportOOMError(); goto cleanup; } - char_ptr2++; - domains = char_ptr2; + char_ptr++; + domains = char_ptr; } else break; } -- 1.7.4.2 From eblake at redhat.com Thu Apr 14 20:22:28 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:22:28 -0600 Subject: [libvirt] [PATCHv2 2/9] phyp: avoid a logic bug In-Reply-To: <1302812555-3418-1-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> Message-ID: <1302812555-3418-3-git-send-email-eblake@redhat.com> Ever since commit ebc46f, the destroy function built two command variants but only used one. I went with the variant that matches the idiom used in the counterpart of phypBuildStoragePool. * src/phyp/phyp_driver.c (phypDestroyStoragePool): Avoid clobbering cmd. Fix error message typo. --- src/phyp/phyp_driver.c | 11 +---------- 1 files changed, 1 insertions(+), 10 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 5742d95..7aa494d 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -2936,19 +2936,10 @@ phypDestroyStoragePool(virStoragePoolPtr pool) return -1; } cmd = virBufferContentAndReset(&buf); - - if (virAsprintf(&cmd, - "viosvrcmd -m %s --id %d -c " - "'rmsp %s'", managed_system, vios_id, - pool->name) < 0) { - virReportOOMError(); - goto cleanup; - } - ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0) { - VIR_ERROR(_("Unable to create Storage Pool: %s"), ret); + VIR_ERROR(_("Unable to destroy Storage Pool: %s"), ret); goto cleanup; } -- 1.7.4.2 From eblake at redhat.com Thu Apr 14 20:22:34 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:22:34 -0600 Subject: [libvirt] [PATCHv2 8/9] phyp: avoid memory leaks in command values In-Reply-To: <1302812555-3418-1-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> Message-ID: <1302812555-3418-9-git-send-email-eblake@redhat.com> * src/phyp/phyp_driver.c (phypExecBuffer): New function. Use it throughout file for less code, and for plugging a few leaks. --- Amazing how much copy-and-paste code this consolidated. src/phyp/phyp_driver.c | 803 ++++++------------------------------------------ 1 files changed, 92 insertions(+), 711 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 56909af..bc24b76 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -110,6 +110,9 @@ waitsocket(int socket_fd, LIBSSH2_SESSION * session) /* this function is the layer that manipulates the ssh channel itself * and executes the commands on the remote machine */ +static char *phypExec(LIBSSH2_SESSION *, const char *, int *, virConnectPtr) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_NONNULL(4); static char * phypExec(LIBSSH2_SESSION *session, const char *cmd, int *exit_status, virConnectPtr conn) @@ -198,6 +201,33 @@ err: return NULL; } +/* Convenience wrapper function */ +static char *phypExecBuffer(LIBSSH2_SESSION *, virBufferPtr buf, int *, + virConnectPtr, bool) ATTRIBUTE_NONNULL(1) + ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); +static char * +phypExecBuffer(LIBSSH2_SESSION *session, virBufferPtr buf, int *exit_status, + virConnectPtr conn, bool strip_newline) +{ + char *cmd; + char *ret; + + if (virBufferError(buf)) { + virBufferFreeAndReset(buf); + virReportOOMError(); + return NULL; + } + cmd = virBufferContentAndReset(buf); + ret = phypExec(session, cmd, exit_status, conn); + VIR_FREE(cmd); + if (ret && *exit_status == 0 && strip_newline) { + char *nl = strchr(ret, '\n'); + if (nl) + *nl = '\0'; + } + return ret; +} + static int phypGetSystemType(virConnectPtr conn) { @@ -225,7 +255,6 @@ phypGetVIOSPartitionID(virConnectPtr conn) phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; int system_type = phyp_driver->system_type; - char *cmd = NULL; char *ret = NULL; int exit_status = 0; int id = -1; @@ -238,14 +267,7 @@ phypGetVIOSPartitionID(virConnectPtr conn) virBufferVSprintf(&buf, " -m %s", managed_system); virBufferAddLit(&buf, " -r lpar -F lpar_id,lpar_env" "|sed -n '/vioserver/ {\n s/,.*$//\n p\n}'"); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -254,7 +276,6 @@ phypGetVIOSPartitionID(virConnectPtr conn) goto cleanup; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return id; @@ -322,7 +343,6 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) int exit_status = 0; int ndom = -1; char *char_ptr; - char *cmd = NULL; char *ret = NULL; char *managed_system = phyp_driver->managed_system; const char *state; @@ -344,14 +364,7 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9]*'", state); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -360,7 +373,6 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) goto cleanup; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return ndom; @@ -384,7 +396,6 @@ phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids, char *managed_system = phyp_driver->managed_system; int exit_status = 0; int got = -1; - char *cmd = NULL; char *ret = NULL; char *line, *next_line; const char *state; @@ -400,14 +411,7 @@ phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids, virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -F lpar_id,state %s | sed -e 's/,.*$//'", state); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -428,9 +432,7 @@ phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids, } cleanup: - VIR_FREE(cmd); VIR_FREE(ret); - return got; } @@ -1299,7 +1301,6 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, int exit_status = 0; int lpar_id = -1; char *char_ptr; - char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -1307,14 +1308,7 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, if (system_type == HMC) virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " --filter lpar_names=%s -F lpar_id", name); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -1323,7 +1317,6 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, goto cleanup; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return lpar_id; @@ -1336,38 +1329,18 @@ phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system, { phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; - char *cmd = NULL; char *ret = NULL; int exit_status = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; - char *char_ptr; virBufferAddLit(&buf, "lssyscfg -r lpar"); if (system_type == HMC) virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " --filter lpar_ids=%d -F name", lpar_id); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return NULL; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, true); - if (exit_status < 0 || ret == NULL) { + if (exit_status < 0) VIR_FREE(ret); - goto cleanup; - } - - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - -cleanup: - VIR_FREE(cmd); - return ret; } @@ -1409,7 +1382,6 @@ phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id, LIBSSH2_SESSION *session = connection_data->session; phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; - char *cmd = NULL; char *ret = NULL; char *char_ptr; int memory = 0; @@ -1425,28 +1397,15 @@ phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id, virBufferVSprintf(&buf, " -r mem --level lpar -F %s --filter lpar_ids=%d", type ? "curr_mem" : "curr_max_mem", lpar_id); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return 0; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - if (virStrToLong_i(ret, &char_ptr, 10, &memory) == -1) goto cleanup; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return memory; @@ -1460,7 +1419,6 @@ phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system, LIBSSH2_SESSION *session = connection_data->session; phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; - char *cmd = NULL; char *ret = NULL; char *char_ptr; int exit_status = 0; @@ -1473,28 +1431,15 @@ phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system, virBufferVSprintf(&buf, " -r proc --level lpar -F %s --filter lpar_ids=%d", type ? "curr_max_procs" : "curr_procs", lpar_id); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return 0; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - if (virStrToLong_i(ret, &char_ptr, 10, &vcpus) == -1) goto cleanup; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return vcpus; @@ -1535,7 +1480,6 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, LIBSSH2_SESSION *session = connection_data->session; phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; - char *cmd = NULL; char *ret = NULL; char *char_ptr; int remote_slot = -1; @@ -1547,28 +1491,15 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -r virtualio --rsubtype scsi -F " "remote_slot_num --filter lpar_names=%s", lpar_name); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - if (virStrToLong_i(ret, &char_ptr, 10, &remote_slot) == -1) goto cleanup; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return remote_slot; @@ -1585,7 +1516,6 @@ phypGetBackingDevice(virConnectPtr conn, const char *managed_system, LIBSSH2_SESSION *session = connection_data->session; phyp_driverPtr phyp_driver = conn->privateData; int system_type = phyp_driver->system_type; - char *cmd = NULL; char *ret = NULL; int remote_slot = 0; int exit_status = 0; @@ -1602,14 +1532,7 @@ phypGetBackingDevice(virConnectPtr conn, const char *managed_system, virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -r virtualio --rsubtype scsi -F " "backing_devices --filter slots=%d", remote_slot); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return NULL; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -1647,7 +1570,6 @@ phypGetBackingDevice(virConnectPtr conn, const char *managed_system, *char_ptr = '\0'; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return backing_device; @@ -1662,10 +1584,8 @@ phypGetLparProfile(virConnectPtr conn, int lpar_id) char *managed_system = phyp_driver->managed_system; int system_type = phyp_driver->system_type; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; - char *char_ptr; virBufferAddLit(&buf, "lssyscfg"); if (system_type == HMC) @@ -1673,28 +1593,10 @@ phypGetLparProfile(virConnectPtr conn, int lpar_id) virBufferVSprintf(&buf, " -r prof --filter lpar_ids=%d -F name|head -n 1", lpar_id); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return NULL; - } - cmd = virBufferContentAndReset(&buf); + ret = phypExecBuffer(session, &buf, &exit_status, conn, true); - ret = phypExec(session, cmd, &exit_status, conn); - - if (exit_status < 0 || ret == NULL) { + if (exit_status < 0) VIR_FREE(ret); - goto cleanup; - } - - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - -cleanup: - VIR_FREE(cmd); - return ret; } @@ -1709,7 +1611,6 @@ phypGetVIOSNextSlotNumber(virConnectPtr conn) int vios_id = phyp_driver->vios_id; int exit_status = 0; char *char_ptr; - char *cmd = NULL; char *ret = NULL; char *profile = NULL; int slot = -1; @@ -1731,16 +1632,7 @@ phypGetVIOSNextSlotNumber(virConnectPtr conn) "virtual_serial_adapters|sed -e 's/\"//g' -e " "'s/,/\\n/g'|sed -e 's/\\(^[0-9][0-9]\\*\\).*$/\\1/'" "|sort|tail -n 1", profile); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -1752,7 +1644,6 @@ phypGetVIOSNextSlotNumber(virConnectPtr conn) cleanup: VIR_FREE(profile); - VIR_FREE(cmd); VIR_FREE(ret); return slot; @@ -1769,7 +1660,6 @@ phypCreateServerSCSIAdapter(virConnectPtr conn) int system_type = phyp_driver->system_type; int vios_id = phyp_driver->vios_id; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; char *profile = NULL; int slot = 0; @@ -1802,14 +1692,7 @@ phypCreateServerSCSIAdapter(virConnectPtr conn) virBufferVSprintf(&buf, " -r prof --filter lpar_ids=%d,profile_names=%s" " -F virtual_scsi_adapters|sed -e s/\\\"//g", vios_id, profile); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -1823,17 +1706,8 @@ phypCreateServerSCSIAdapter(virConnectPtr conn) virBufferVSprintf(&buf, " -r prof -i 'name=%s,lpar_id=%d," "\"virtual_scsi_adapters=%s,%d/server/any/any/1\"'", vios_name, vios_id, ret, slot); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - - VIR_FREE(cmd); VIR_FREE(ret); - - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -1847,17 +1721,7 @@ phypCreateServerSCSIAdapter(virConnectPtr conn) virBufferVSprintf(&buf, " -p %s -o a -s %d -d 0 -a \"adapter_type=server\"", vios_name, slot); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - - VIR_FREE(cmd); - VIR_FREE(ret); - - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -1867,7 +1731,6 @@ phypCreateServerSCSIAdapter(virConnectPtr conn) cleanup: VIR_FREE(profile); VIR_FREE(vios_name); - VIR_FREE(cmd); VIR_FREE(ret); return result; @@ -1883,10 +1746,8 @@ phypGetVIOSFreeSCSIAdapter(virConnectPtr conn) int system_type = phyp_driver->system_type; int vios_id = phyp_driver->vios_id; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; - char *char_ptr; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -1898,29 +1759,10 @@ phypGetVIOSFreeSCSIAdapter(virConnectPtr conn) virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|sed '/,[^.*]/d; s/,//g; q'"); + ret = phypExecBuffer(session, &buf, &exit_status, conn, true); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return NULL; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); - - if (exit_status < 0 || ret == NULL) { + if (exit_status < 0) VIR_FREE(ret); - goto cleanup; - } - - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - -cleanup: - VIR_FREE(cmd); - return ret; } @@ -1938,7 +1780,6 @@ phypAttachDevice(virDomainPtr domain, const char *xml) int vios_id = phyp_driver->vios_id; int exit_status = 0; char *char_ptr = NULL; - char *cmd = NULL; char *ret = NULL; char *scsi_adapter = NULL; int slot = 0; @@ -2000,18 +1841,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) if (system_type == HMC) virBufferAddChar(&buf, '\''); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - - VIR_FREE(cmd); - VIR_FREE(ret); - - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -2029,17 +1859,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) virBufferVSprintf(&buf, " slot_num,backing_device|grep %s|cut -d, -f1", dev->data.disk->src); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - - VIR_FREE(cmd); - VIR_FREE(ret); - - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -2057,17 +1877,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) " -r prof --filter lpar_ids=%d,profile_names=%s" " -F virtual_scsi_adapters|sed -e 's/\"//g'", vios_id, profile); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - - VIR_FREE(cmd); - VIR_FREE(ret); - - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -2083,17 +1893,8 @@ phypAttachDevice(virDomainPtr domain, const char *xml) "\"virtual_scsi_adapters=%s,%d/client/%d/%s/0\"'", domain_name, domain->id, ret, slot, vios_id, vios_name); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - - VIR_FREE(cmd); VIR_FREE(ret); - - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) goto cleanup; @@ -2107,17 +1908,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) virBufferVSprintf(&buf, " -p %s -o a -s %d -d 0 -a \"adapter_type=server\"", domain_name, slot); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - - VIR_FREE(cmd); - VIR_FREE(ret); - - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) { VIR_ERROR0(_ @@ -2129,7 +1920,6 @@ phypAttachDevice(virDomainPtr domain, const char *xml) result = 0; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); virDomainDeviceDefFree(dev); virDomainDefFree(def); @@ -2151,10 +1941,8 @@ phypVolumeGetKey(virConnectPtr conn, const char *name) int system_type = phyp_driver->system_type; int vios_id = phyp_driver->vios_id; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; - char *char_ptr; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -2166,29 +1954,10 @@ phypVolumeGetKey(virConnectPtr conn, const char *name) virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|sed -e 's/^LV IDENTIFIER://' -e 's/ //g'"); + ret = phypExecBuffer(session, &buf, &exit_status, conn, true); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return NULL; - } - - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, conn); - - if (exit_status < 0 || ret == NULL) { + if (exit_status < 0) VIR_FREE(ret); - goto cleanup; - } - - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - -cleanup: - VIR_FREE(cmd); - return ret; } @@ -2202,10 +1971,8 @@ phypGetStoragePoolDevice(virConnectPtr conn, char *name) int system_type = phyp_driver->system_type; int vios_id = phyp_driver->vios_id; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; - char *char_ptr; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -2217,29 +1984,10 @@ phypGetStoragePoolDevice(virConnectPtr conn, char *name) virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|sed '1d; s/ //g'"); + ret = phypExecBuffer(session, &buf, &exit_status, conn, true); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return NULL; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); - - if (exit_status < 0 || ret == NULL) { + if (exit_status < 0) VIR_FREE(ret); - goto cleanup; - } - - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - -cleanup: - VIR_FREE(cmd); - return ret; } @@ -2253,7 +2001,6 @@ phypGetStoragePoolSize(virConnectPtr conn, char *name) int system_type = phyp_driver->system_type; int exit_status = 0; int vios_id = phyp_driver->vios_id; - char *cmd = NULL; char *ret = NULL; int sp_size = -1; char *char_ptr; @@ -2269,15 +2016,7 @@ phypGetStoragePoolSize(virConnectPtr conn, char *name) virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|sed '1d; s/ //g'"); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -2286,7 +2025,6 @@ phypGetStoragePoolSize(virConnectPtr conn, char *name) goto cleanup; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return sp_size; @@ -2302,7 +2040,6 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, int vios_id = phyp_driver->vios_id; int system_type = phyp_driver->system_type; char *managed_system = phyp_driver->managed_system; - char *cmd = NULL; char *ret = NULL; int exit_status = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -2316,15 +2053,7 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, if (system_type == HMC) virBufferAddChar(&buf, '\''); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return NULL; - } - - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0) { VIR_ERROR(_("Unable to create Volume: %s"), NULLSTR(ret)); @@ -2333,11 +2062,7 @@ phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname, key = phypVolumeGetKey(conn, lvname); - if (key == NULL) - goto cleanup; - cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return key; @@ -2469,10 +2194,8 @@ phypVolumeGetPhysicalVolumeByStoragePool(virStorageVolPtr vol, char *sp) int system_type = phyp_driver->system_type; int vios_id = phyp_driver->vios_id; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; - char *char_ptr; if (system_type == HMC) virBufferVSprintf(&buf, "viosvrcmd -m %s --id %d -c '", @@ -2484,29 +2207,10 @@ phypVolumeGetPhysicalVolumeByStoragePool(virStorageVolPtr vol, char *sp) virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|sed 1d"); + ret = phypExecBuffer(session, &buf, &exit_status, conn, true); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return NULL; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); - - if (exit_status < 0 || ret == NULL) { + if (exit_status < 0) VIR_FREE(ret); - goto cleanup; - } - - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - -cleanup: - VIR_FREE(cmd); - return ret; } @@ -2520,9 +2224,7 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) int system_type = phyp_driver->system_type; int vios_id = phyp_driver->vios_id; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; - char *char_ptr; char *key = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; virStorageVolPtr vol = NULL; @@ -2537,24 +2239,11 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|sed -e 's/^VOLUME GROUP://g' -e 's/ //g'"); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return NULL; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, true); if (exit_status < 0 || ret == NULL) goto cleanup; - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - key = phypVolumeGetKey(conn, volname); if (key == NULL) @@ -2563,7 +2252,6 @@ phypVolumeLookupByPath(virConnectPtr conn, const char *volname) vol = virGetStorageVol(conn, ret, volname, key); cleanup: - VIR_FREE(cmd); VIR_FREE(ret); VIR_FREE(key); @@ -2582,7 +2270,6 @@ phypGetStoragePoolUUID(virConnectPtr conn, unsigned char *uuid, int system_type = phyp_driver->system_type; int vios_id = phyp_driver->vios_id; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -2596,15 +2283,7 @@ phypGetStoragePoolUUID(virConnectPtr conn, unsigned char *uuid, virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|sed '1,2d'"); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -2615,7 +2294,6 @@ phypGetStoragePoolUUID(virConnectPtr conn, unsigned char *uuid, result = 0; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return result; @@ -2724,11 +2402,9 @@ phypVolumeGetPath(virStorageVolPtr vol) int system_type = phyp_driver->system_type; int vios_id = phyp_driver->vios_id; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; char *path = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; - char *char_ptr; char *pv; if (system_type == HMC) @@ -2742,24 +2418,11 @@ phypVolumeGetPath(virStorageVolPtr vol) virBufferVSprintf(&buf, "|sed -e 's/^VOLUME GROUP://g' -e 's/ //g'"); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return NULL; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, true); if (exit_status < 0 || ret == NULL) goto cleanup; - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - pv = phypVolumeGetPhysicalVolumeByStoragePool(vol, ret); if (!pv) @@ -2771,7 +2434,6 @@ phypVolumeGetPath(virStorageVolPtr vol) } cleanup: - VIR_FREE(cmd); VIR_FREE(ret); VIR_FREE(path); @@ -2793,7 +2455,6 @@ phypStoragePoolListVolumes(virStoragePoolPtr pool, char **const volumes, int exit_status = 0; int got = 0; int i; - char *cmd = NULL; char *ret = NULL; char *volumes_list = NULL; char *char_ptr2 = NULL; @@ -2809,15 +2470,7 @@ phypStoragePoolListVolumes(virStoragePoolPtr pool, char **const volumes, virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|sed '1,2d'"); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); /* I need to parse the textual return in order to get the volumes */ if (exit_status < 0 || ret == NULL) @@ -2850,10 +2503,7 @@ cleanup: got = -1; } - - VIR_FREE(cmd); VIR_FREE(ret); - return got; } @@ -2867,7 +2517,6 @@ phypStoragePoolNumOfVolumes(virStoragePoolPtr pool) int system_type = phyp_driver->system_type; int exit_status = 0; int nvolumes = -1; - char *cmd = NULL; char *ret = NULL; char *managed_system = phyp_driver->managed_system; int vios_id = phyp_driver->vios_id; @@ -2881,15 +2530,7 @@ phypStoragePoolNumOfVolumes(virStoragePoolPtr pool) if (system_type == HMC) virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|grep -c '^.*$'"); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -2901,7 +2542,6 @@ phypStoragePoolNumOfVolumes(virStoragePoolPtr pool) nvolumes -= 2; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return nvolumes; @@ -2918,7 +2558,6 @@ phypDestroyStoragePool(virStoragePoolPtr pool) int vios_id = phyp_driver->vios_id; char *managed_system = phyp_driver->managed_system; int system_type = phyp_driver->system_type; - char *cmd = NULL; char *ret = NULL; int exit_status = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -2931,14 +2570,7 @@ phypDestroyStoragePool(virStoragePoolPtr pool) if (system_type == HMC) virBufferAddChar(&buf, '\''); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0) { VIR_ERROR(_("Unable to destroy Storage Pool: %s"), NULLSTR(ret)); @@ -2948,7 +2580,6 @@ phypDestroyStoragePool(virStoragePoolPtr pool) result = 0; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return result; @@ -2965,7 +2596,6 @@ phypBuildStoragePool(virConnectPtr conn, virStoragePoolDefPtr def) int vios_id = phyp_driver->vios_id; int system_type = phyp_driver->system_type; char *managed_system = phyp_driver->managed_system; - char *cmd = NULL; char *ret = NULL; int exit_status = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -2979,15 +2609,7 @@ phypBuildStoragePool(virConnectPtr conn, virStoragePoolDefPtr def) if (system_type == HMC) virBufferAddChar(&buf, '\''); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0) { VIR_ERROR(_("Unable to create Storage Pool: %s"), NULLSTR(ret)); @@ -2997,7 +2619,6 @@ phypBuildStoragePool(virConnectPtr conn, virStoragePoolDefPtr def) result = 0; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return result; @@ -3013,7 +2634,6 @@ phypNumOfStoragePools(virConnectPtr conn) int system_type = phyp_driver->system_type; int exit_status = 0; int nsp = -1; - char *cmd = NULL; char *ret = NULL; char *managed_system = phyp_driver->managed_system; int vios_id = phyp_driver->vios_id; @@ -3030,15 +2650,7 @@ phypNumOfStoragePools(virConnectPtr conn) virBufferAddChar(&buf, '\''); virBufferVSprintf(&buf, "|grep -c '^.*$'"); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -3047,7 +2659,6 @@ phypNumOfStoragePools(virConnectPtr conn) goto cleanup; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return nsp; @@ -3066,7 +2677,6 @@ phypListStoragePools(virConnectPtr conn, char **const pools, int npools) int exit_status = 0; int got = 0; int i; - char *cmd = NULL; char *ret = NULL; char *storage_pools = NULL; char *char_ptr2 = NULL; @@ -3080,15 +2690,7 @@ phypListStoragePools(virConnectPtr conn, char **const pools, int npools) if (system_type == HMC) virBufferAddChar(&buf, '\''); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); /* I need to parse the textual return in order to get the storage pools */ if (exit_status < 0 || ret == NULL) @@ -3121,10 +2723,7 @@ cleanup: got = -1; } - - VIR_FREE(cmd); VIR_FREE(ret); - return got; } @@ -3286,7 +2885,6 @@ phypInterfaceDestroy(virInterfacePtr iface, int slot_num = 0; int lpar_id = 0; char *char_ptr; - char *cmd = NULL; char *ret = NULL; int rv = -1; @@ -3300,15 +2898,7 @@ phypInterfaceDestroy(virInterfacePtr iface, " -r virtualio --rsubtype eth --level lpar " " -F mac_addr,slot_num|" " sed -n '/%s/ s/^.*,//p'", iface->mac); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, iface->conn); + ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -3317,7 +2907,6 @@ phypInterfaceDestroy(virInterfacePtr iface, goto cleanup; /* Getting the remote slot number */ - VIR_FREE(cmd); VIR_FREE(ret); virBufferAddLit(&buf, "lshwres "); @@ -3328,15 +2917,7 @@ phypInterfaceDestroy(virInterfacePtr iface, " -r virtualio --rsubtype eth --level lpar " " -F mac_addr,lpar_id|" " sed -n '/%s/ s/^.*,//p'", iface->mac); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, iface->conn); + ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -3345,7 +2926,6 @@ phypInterfaceDestroy(virInterfacePtr iface, goto cleanup; /* excluding interface */ - VIR_FREE(cmd); VIR_FREE(ret); virBufferAddLit(&buf, "chhwres "); @@ -3355,15 +2935,7 @@ phypInterfaceDestroy(virInterfacePtr iface, virBufferVSprintf(&buf, " -r virtualio --rsubtype eth" " --id %d -o r -s %d", lpar_id, slot_num); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, iface->conn); + ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false); if (exit_status < 0 || ret != NULL) goto cleanup; @@ -3371,7 +2943,6 @@ phypInterfaceDestroy(virInterfacePtr iface, rv = 0; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return rv; } @@ -3390,7 +2961,6 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, int system_type = phyp_driver->system_type; int exit_status = 0; char *char_ptr; - char *cmd = NULL; int slot = 0; char *ret = NULL; char name[PHYP_IFACENAME_SIZE]; @@ -3410,15 +2980,7 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, " -r virtualio --rsubtype slot --level slot" " -Fslot_num --filter lpar_names=%s" " |sort|tail -n 1", def->name); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -3430,7 +2992,6 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, slot++; /* Now adding the new network interface */ - VIR_FREE(cmd); VIR_FREE(ret); virBufferAddLit(&buf, "chhwres "); @@ -3441,15 +3002,7 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, " -r virtualio --rsubtype eth" " -p %s -o a -s %d -a port_vlan_id=1," "ieee_virtual_eth=0", def->name, slot); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret != NULL) goto cleanup; @@ -3460,7 +3013,6 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, sleep(1); /* Getting the new interface name */ - VIR_FREE(cmd); VIR_FREE(ret); virBufferAddLit(&buf, "lshwres "); @@ -3471,19 +3023,10 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, " -r virtualio --rsubtype slot --level slot" " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " "s/^.*drc_name=//'", def->name, slot); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) { /* roll back and excluding interface if error*/ - VIR_FREE(cmd); VIR_FREE(ret); virBufferAddLit(&buf, "chhwres "); @@ -3493,23 +3036,13 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, virBufferVSprintf(&buf, " -r virtualio --rsubtype eth" " -p %s -o r -s %d", def->name, slot); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); goto cleanup; } memcpy(name, ret, PHYP_IFACENAME_SIZE-1); /* Getting the new interface mac addr */ - VIR_FREE(cmd); VIR_FREE(ret); virBufferAddLit(&buf, "lshwres "); @@ -3520,15 +3053,7 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, "-r virtualio --rsubtype eth --level lpar " " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; " "s/^.*mac_addr=//'", def->name, slot); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -3538,7 +3063,6 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, result = virGetInterface(conn, name, mac); cleanup: - VIR_FREE(cmd); VIR_FREE(ret); virInterfaceDefFree(def); return result; @@ -3555,7 +3079,6 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) int system_type = phyp_driver->system_type; int exit_status = 0; char *char_ptr; - char *cmd = NULL; char *ret = NULL; int slot = 0; int lpar_id = 0; @@ -3571,15 +3094,7 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) " -r virtualio --rsubtype slot --level slot " " -F drc_name,slot_num |" " sed -n '/%s/ s/^.*,//p'", name); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -3588,7 +3103,6 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) goto cleanup; /*Getting the lpar_id for the interface */ - VIR_FREE(cmd); VIR_FREE(ret); virBufferAddLit(&buf, "lshwres "); @@ -3599,15 +3113,7 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) " -r virtualio --rsubtype slot --level slot " " -F drc_name,lpar_id |" " sed -n '/%s/ s/^.*,//p'", name); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return NULL; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -3624,17 +3130,8 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) " -r virtualio --rsubtype eth --level lpar " " -F lpar_id,slot_num,mac_addr|" " sed -n '/%d,%d/ s/^.*,//p'", lpar_id, slot); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - VIR_FREE(ret); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -3644,7 +3141,6 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) result = virGetInterface(conn, name, ret); cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return result; } @@ -3661,7 +3157,6 @@ phypInterfaceIsActive(virInterfacePtr iface) int exit_status = 0; int state = -1; char *char_ptr; - char *cmd = NULL; char *ret = NULL; virBufferAddLit(&buf, "lshwres "); @@ -3672,15 +3167,7 @@ phypInterfaceIsActive(virInterfacePtr iface) " -r virtualio --rsubtype eth --level lpar " " -F mac_addr,state |" " sed -n '/%s/ s/^.*,//p'", iface->mac); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, iface->conn); + ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -3689,7 +3176,6 @@ phypInterfaceIsActive(virInterfacePtr iface) goto cleanup; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return state; } @@ -3706,7 +3192,6 @@ phypListInterfaces(virConnectPtr conn, char **const names, int nnames) int exit_status = 0; int got = 0; int i; - char *cmd = NULL; char *ret = NULL; char *networks = NULL; char *char_ptr2 = NULL; @@ -3719,14 +3204,7 @@ phypListInterfaces(virConnectPtr conn, char **const names, int nnames) virBufferVSprintf(&buf, " -r virtualio --rsubtype slot --level slot|" " sed '/eth/!d; /lpar_id=%d/d; s/^.*drc_name=//g'", vios_id); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); /* I need to parse the textual return in order to get the network * interfaces */ @@ -3756,7 +3234,6 @@ cleanup: for (i = 0; i < got; i++) VIR_FREE(names[i]); } - VIR_FREE(cmd); VIR_FREE(ret); return got; } @@ -3773,7 +3250,6 @@ phypNumOfInterfaces(virConnectPtr conn) int exit_status = 0; int nnets = -1; char *char_ptr; - char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -3784,15 +3260,7 @@ phypNumOfInterfaces(virConnectPtr conn) virBufferVSprintf(&buf, "-r virtualio --rsubtype eth --level lpar|" "grep -v lpar_id=%d|grep -c lpar_name", vios_id); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - goto cleanup; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0 || ret == NULL) goto cleanup; @@ -3801,7 +3269,6 @@ phypNumOfInterfaces(virConnectPtr conn) goto cleanup; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return nnets; } @@ -3813,10 +3280,8 @@ phypGetLparState(virConnectPtr conn, unsigned int lpar_id) phyp_driverPtr phyp_driver = conn->privateData; LIBSSH2_SESSION *session = connection_data->session; int system_type = phyp_driver->system_type; - char *cmd = NULL; char *ret = NULL; int exit_status = 0; - char *char_ptr = NULL; char *managed_system = phyp_driver->managed_system; int state = VIR_DOMAIN_NOSTATE; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -3825,23 +3290,11 @@ phypGetLparState(virConnectPtr conn, unsigned int lpar_id) if (system_type == HMC) virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -F state --filter lpar_ids=%d", lpar_id); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return state; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, true); if (exit_status < 0 || ret == NULL) goto cleanup; - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - if (STREQ(ret, "Running")) state = VIR_DOMAIN_RUNNING; else if (STREQ(ret, "Not Activated")) @@ -3850,7 +3303,6 @@ phypGetLparState(virConnectPtr conn, unsigned int lpar_id) state = VIR_DOMAIN_SHUTDOWN; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return state; } @@ -3864,10 +3316,8 @@ phypDiskType(virConnectPtr conn, char *backing_device) ConnectionData *connection_data = conn->networkPrivateData; LIBSSH2_SESSION *session = connection_data->session; int system_type = phyp_driver->system_type; - char *cmd = NULL; char *ret = NULL; int exit_status = 0; - char *char_ptr; char *managed_system = phyp_driver->managed_system; int vios_id = phyp_driver->vios_id; int disk_type = -1; @@ -3879,30 +3329,17 @@ phypDiskType(virConnectPtr conn, char *backing_device) virBufferVSprintf(&buf, " -p %d -c \"lssp -field name type " "-fmt , -all|sed -n '/%s/ {\n s/^.*,//\n p\n}'\"", vios_id, backing_device); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return disk_type; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, true); if (exit_status < 0 || ret == NULL) goto cleanup; - char_ptr = strchr(ret, '\n'); - - if (char_ptr) - *char_ptr = '\0'; - if (STREQ(ret, "LVPOOL")) disk_type = VIR_DOMAIN_DISK_TYPE_BLOCK; else if (STREQ(ret, "FBPOOL")) disk_type = VIR_DOMAIN_DISK_TYPE_FILE; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return disk_type; } @@ -3937,7 +3374,6 @@ phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames) int exit_status = 0; int got = 0; int i; - char *cmd = NULL; char *ret = NULL; char *domains = NULL; char *char_ptr2 = NULL; @@ -3948,14 +3384,7 @@ phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames) virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -F name,state" "|sed -n '/Not Activated/ {\n s/,.*$//\n p\n}'"); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); /* I need to parse the textual return in order to get the domains */ if (exit_status < 0 || ret == NULL) @@ -3988,10 +3417,7 @@ cleanup: got = -1; } - - VIR_FREE(cmd); VIR_FREE(ret); - return got; } @@ -4113,7 +3539,6 @@ phypDomainResume(virDomainPtr dom) int system_type = phyp_driver->system_type; char *managed_system = phyp_driver->managed_system; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -4122,14 +3547,7 @@ phypDomainResume(virDomainPtr dom) virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -r lpar -o on --id %d -f %s", dom->id, dom->name); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, dom->conn); + ret = phypExecBuffer(session, &buf, &exit_status, dom->conn, false); if (exit_status < 0) goto cleanup; @@ -4137,7 +3555,6 @@ phypDomainResume(virDomainPtr dom) result = 0; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return result; @@ -4154,7 +3571,6 @@ phypDomainShutdown(virDomainPtr dom) int system_type = phyp_driver->system_type; char *managed_system = phyp_driver->managed_system; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -4162,14 +3578,7 @@ phypDomainShutdown(virDomainPtr dom) if (system_type == HMC) virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -r lpar -o shutdown --id %d", dom->id); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, dom->conn); + ret = phypExecBuffer(session, &buf, &exit_status, dom->conn, false); if (exit_status < 0) goto cleanup; @@ -4177,7 +3586,6 @@ phypDomainShutdown(virDomainPtr dom) result = 0; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return result; @@ -4216,7 +3624,6 @@ phypDomainDestroy(virDomainPtr dom) int system_type = phyp_driver->system_type; char *managed_system = phyp_driver->managed_system; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -4224,14 +3631,7 @@ phypDomainDestroy(virDomainPtr dom) if (system_type == HMC) virBufferVSprintf(&buf, " -m %s", managed_system); virBufferVSprintf(&buf, " -r lpar --id %d", dom->id); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, dom->conn); + ret = phypExecBuffer(session, &buf, &exit_status, dom->conn, false); if (exit_status < 0) goto cleanup; @@ -4243,7 +3643,6 @@ phypDomainDestroy(virDomainPtr dom) result = 0; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return result; @@ -4258,7 +3657,6 @@ phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) LIBSSH2_SESSION *session = connection_data->session; int system_type = phyp_driver->system_type; char *managed_system = phyp_driver->managed_system; - char *cmd = NULL; char *ret = NULL; int exit_status = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -4298,14 +3696,7 @@ phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) def->name, (int) def->mem.cur_balloon, (int) def->mem.cur_balloon, (int) def->mem.max_balloon, (int) def->vcpus, def->disks[0]->src); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, conn); + ret = phypExecBuffer(session, &buf, &exit_status, conn, false); if (exit_status < 0) { VIR_ERROR(_("Unable to create LPAR. Reason: '%s'"), NULLSTR(ret)); @@ -4320,7 +3711,6 @@ phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) result = 0; cleanup: - VIR_FREE(cmd); VIR_FREE(ret); return result; @@ -4402,7 +3792,6 @@ phypDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, int system_type = phyp_driver->system_type; char *managed_system = phyp_driver->managed_system; int exit_status = 0; - char *cmd = NULL; char *ret = NULL; char operation; unsigned long ncpus = 0; @@ -4438,14 +3827,7 @@ phypDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, virBufferVSprintf(&buf, " --id %d -o %c --procunits %d 2>&1 |sed " "-e 's/^.*\\([0-9][0-9]*.[0-9][0-9]*\\).*$/\\1/'", dom->id, operation, amount); - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return 0; - } - cmd = virBufferContentAndReset(&buf); - - ret = phypExec(session, cmd, &exit_status, dom->conn); + ret = phypExecBuffer(session, &buf, &exit_status, dom->conn, false); if (exit_status < 0) { VIR_ERROR0(_ @@ -4453,7 +3835,6 @@ phypDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, " Contact your support to enable this feature.")); } - VIR_FREE(cmd); VIR_FREE(ret); return 0; -- 1.7.4.2 From eblake at redhat.com Thu Apr 14 20:22:30 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:22:30 -0600 Subject: [libvirt] [PATCHv2 4/9] phyp: more return handling cleanup In-Reply-To: <1302812555-3418-1-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> Message-ID: <1302812555-3418-5-git-send-email-eblake@redhat.com> * src/phyp/phyp_driver.c (phypInterfaceDestroy) (phypInterfaceDefineXML, phypInterfaceLookupByName) (phypInterfaceIsActive, phypListInterfaces, phypNumOfInterfaces): Clean up return handling of recent additions. --- src/phyp/phyp_driver.c | 130 +++++++++++++++++++++--------------------------- 1 files changed, 56 insertions(+), 74 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 0c69d4f..37395c6 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -3294,6 +3294,7 @@ phypInterfaceDestroy(virInterfacePtr iface, char *char_ptr; char *cmd = NULL; char *ret = NULL; + int rv = -1; /* Getting the remote slot number */ @@ -3309,17 +3310,17 @@ phypInterfaceDestroy(virInterfacePtr iface, if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - goto err; + goto cleanup; } cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, iface->conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &slot_num) == -1) - goto err; + goto cleanup; /* Getting the remote slot number */ VIR_FREE(cmd); @@ -3337,7 +3338,7 @@ phypInterfaceDestroy(virInterfacePtr iface, if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - goto err; + goto cleanup; } cmd = virBufferContentAndReset(&buf); @@ -3346,10 +3347,10 @@ phypInterfaceDestroy(virInterfacePtr iface, ret = phypExec(session, cmd, &exit_status, iface->conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) - goto err; + goto cleanup; /* excluding interface */ VIR_FREE(cmd); @@ -3366,23 +3367,21 @@ phypInterfaceDestroy(virInterfacePtr iface, if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - goto err; + goto cleanup; } cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, iface->conn); if (exit_status < 0 || ret != NULL) - goto err; + goto cleanup; - VIR_FREE(cmd); - VIR_FREE(ret); - return 0; + rv = 0; - err: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); - return -1; + return rv; } static virInterfacePtr @@ -3405,9 +3404,10 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, char name[PHYP_IFACENAME_SIZE]; char mac[PHYP_MAC_SIZE]; virInterfaceDefPtr def; + virInterfacePtr result = NULL; if (!(def = virInterfaceDefParseString(xml))) - goto err; + goto cleanup; /* Now need to get the next free slot number */ virBufferAddLit(&buf, "lshwres "); @@ -3422,17 +3422,17 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - goto err; + goto cleanup; } cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) - goto err; + goto cleanup; /* The next free slot itself: */ slot++; @@ -3453,14 +3453,14 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - goto err; + goto cleanup; } cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret != NULL) - goto err; + goto cleanup; /* Need to sleep a little while to wait for the HMC to * complete the execution of the command. @@ -3483,7 +3483,7 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - goto err; + goto cleanup; } cmd = virBufferContentAndReset(&buf); @@ -3505,13 +3505,13 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - goto err; + goto cleanup; } cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); - goto err; + goto cleanup; } memcpy(name, ret, PHYP_IFACENAME_SIZE-1); @@ -3532,27 +3532,24 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - goto err; + goto cleanup; } cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; memcpy(mac, ret, PHYP_MAC_SIZE-1); - VIR_FREE(cmd); - VIR_FREE(ret); - virInterfaceDefFree(def); - return virGetInterface(conn, name, mac); + result = virGetInterface(conn, name, mac); - err: +cleanup: VIR_FREE(cmd); VIR_FREE(ret); virInterfaceDefFree(def); - return NULL; + return result; } static virInterfacePtr @@ -3586,17 +3583,17 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - goto err; + goto cleanup; } cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) - goto err; + goto cleanup; /*Getting the lpar_id for the interface */ VIR_FREE(cmd); @@ -3621,10 +3618,10 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) - goto err; + goto cleanup; /*Getting the interface mac */ virBufferAddLit(&buf, "lshwres "); @@ -3639,7 +3636,7 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return NULL; + goto cleanup; } cmd = virBufferContentAndReset(&buf); @@ -3648,21 +3645,16 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; memcpy(mac, ret, PHYP_MAC_SIZE-1); result = virGetInterface(conn, name, ret); +cleanup: VIR_FREE(cmd); VIR_FREE(ret); return result; - - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return NULL; - } static int @@ -3675,7 +3667,7 @@ phypInterfaceIsActive(virInterfacePtr iface) char *managed_system = phyp_driver->managed_system; int system_type = phyp_driver->system_type; int exit_status = 0; - int state = 0; + int state = -1; char *char_ptr; char *cmd = NULL; char *ret = NULL; @@ -3692,27 +3684,22 @@ phypInterfaceIsActive(virInterfacePtr iface) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - return -1; + goto cleanup; } cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, iface->conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &state) == -1) - goto err; + goto cleanup; +cleanup: VIR_FREE(cmd); VIR_FREE(ret); return state; - - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; - } static int @@ -3732,6 +3719,7 @@ phypListInterfaces(virConnectPtr conn, char **const names, int nnames) char *networks = NULL; char *char_ptr2 = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; + bool success = false; virBufferAddLit(&buf, "lshwres"); if (system_type == HMC) @@ -3742,15 +3730,16 @@ phypListInterfaces(virConnectPtr conn, char **const names, int nnames) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - goto err; + goto cleanup; } cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); - /* I need to parse the textual return in order to get the network interfaces */ + /* I need to parse the textual return in order to get the network + * interfaces */ if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; networks = ret; @@ -3761,7 +3750,7 @@ phypListInterfaces(virConnectPtr conn, char **const names, int nnames) *char_ptr2 = '\0'; if ((names[got++] = strdup(networks)) == NULL) { virReportOOMError(); - goto err; + goto cleanup; } char_ptr2++; networks = char_ptr2; @@ -3770,16 +3759,14 @@ phypListInterfaces(virConnectPtr conn, char **const names, int nnames) } } +cleanup: + if (!success) { + for (i = 0; i < got; i++) + VIR_FREE(names[i]); + } VIR_FREE(cmd); VIR_FREE(ret); return got; - - err: - for (i = 0; i < got; i++) - VIR_FREE(names[i]); - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; } static int @@ -3792,7 +3779,7 @@ phypNumOfInterfaces(virConnectPtr conn) int system_type = phyp_driver->system_type; int vios_id = phyp_driver->vios_id; int exit_status = 0; - int nnets = 0; + int nnets = -1; char *char_ptr; char *cmd = NULL; char *ret = NULL; @@ -3809,27 +3796,22 @@ phypNumOfInterfaces(virConnectPtr conn) if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); virReportOOMError(); - goto err; + goto cleanup; } cmd = virBufferContentAndReset(&buf); ret = phypExec(session, cmd, &exit_status, conn); if (exit_status < 0 || ret == NULL) - goto err; + goto cleanup; if (virStrToLong_i(ret, &char_ptr, 10, &nnets) == -1) - goto err; + goto cleanup; +cleanup: VIR_FREE(cmd); VIR_FREE(ret); return nnets; - - err: - VIR_FREE(cmd); - VIR_FREE(ret); - return -1; - } static int -- 1.7.4.2 From eblake at redhat.com Thu Apr 14 20:32:36 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:32:36 -0600 Subject: [libvirt] [PATCH] implement BOOT_TIMEOUT In-Reply-To: <4DA6CAC2.5080409@otb.bg> References: <1302682502-4967-1-git-send-email-atodorov@otb.bg> <4DA5DE06.6070507@redhat.com> <4DA6CAC2.5080409@otb.bg> Message-ID: <4DA759E4.7080401@redhat.com> On 04/14/2011 04:21 AM, Alexander Todorov wrote: > I will rework the patch with your comments and post it again but was > wondering about something more advanced. > > Is it possible to specify the order(and timeouts) in which individual > guests are started? As it seems currently this is not possible. I'm not sure of any way to do this short of naming your guests so that their names are sorted in the order you want them started. Hmm, thinking back to an earlier proposal, this might be a good fit for the idea of VM groups: https://www.redhat.com/archives/libvir-list/2011-March/msg01546.html That is, if you can teach libvirt to manage the notion of groups of related VMs, then you can also express ordering contraints within each group. > I've come across a situation where one of the guests needs to start > first (provides a database) and then another guests needs to start > second (an app server). The reason is that this is a proprietary app > which is badly written and fails to connect/re-connect to the database > if it is not online in the first place. Without more code on the libvirt front, I think you're stuck renaming the guests to enforce naming order (assuming that libvirt even goes by sorted name order, as opposed to readdir() order where you have no control). -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 14 20:34:47 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:34:47 -0600 Subject: [libvirt] [PATCH 2/3] qemu: unlock qemu driver and vm before returning from processWatchdogEvent() In-Reply-To: <4D9C1CED.20202@cn.fujitsu.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1CED.20202@cn.fujitsu.com> Message-ID: <4DA75A67.7050704@redhat.com> On 04/06/2011 01:57 AM, Wen Congyang wrote: > When the function processWatchdogEvent() failed, we only free wdEvent, but > forget to unlock qemu driver and vm, free dumpfile. > > --- > src/qemu/qemu_driver.c | 28 +++++++++++++++++++--------- > 1 files changed, 19 insertions(+), 9 deletions(-) ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 14 20:43:00 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:43:00 -0600 Subject: [libvirt] [PATCH V2 3/3] hold an extra reference while handling watchdog event In-Reply-To: <4D9C1D38.8090004@cn.fujitsu.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1D38.8090004@cn.fujitsu.com> Message-ID: <4DA75C54.5000509@redhat.com> On 04/06/2011 01:58 AM, Wen Congyang wrote: > If the domain is not persistent, and qemu quited unexpectedly before s/quited/quits/ > calling processWatchdogEvent(), vm will be freed and the function > processWatchdogEvent() will be dangerous. > > --- > src/qemu/qemu_driver.c | 12 ++++++++---- > src/qemu/qemu_process.c | 4 ++++ > 2 files changed, 12 insertions(+), 4 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 628cfe3..d02891c 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -2436,15 +2436,19 @@ static void processWatchdogEvent(void *data, void *opaque) > } > break; > default: > - goto cleanup; > + qemuDriverLock(driver); > + virDomainObjLock(wdEvent->vm); > + goto unlock; > } > > endjob: > - if (qemuDomainObjEndJob(wdEvent->vm) == 0) > - wdEvent->vm = NULL; > + /* Safe to ignore value since ref count was incremented in > + * qemuProcessHandleWatchdog(). > + */ > + ignore_value(qemuDomainObjEndJob(wdEvent->vm)); > > unlock: > - if (wdEvent->vm) > + if (virDomainObjUnref(wdEvent->vm) > 0) > virDomainObjUnlock(wdEvent->vm); > qemuDriverUnlock(driver); > > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > index 48ecd5c..321374c 100644 > --- a/src/qemu/qemu_process.c > +++ b/src/qemu/qemu_process.c > @@ -426,6 +426,10 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > if (VIR_ALLOC(wdEvent) == 0) { > wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP; > wdEvent->vm = vm; > + /* Hold an extra reference because we can't allow 'vm' to be > + * deleted before handling watchdog event is finished. > + */ > + virDomainObjRef(vm); > ignore_value(virThreadPoolSendJob(driver->workerPool, wdEvent)); ACK to the need to do this. Hmm, maybe we should just squash 2 and 3 together into one patch. Also, I found a flaw in 2 while reviewing this one. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From laine at laine.org Thu Apr 14 20:43:53 2011 From: laine at laine.org (Laine Stump) Date: Thu, 14 Apr 2011 16:43:53 -0400 Subject: [libvirt] [PATCHv2] network: truncate bridges' dummy tap device names to IFNAMSIZ (15) chars In-Reply-To: <4DA748B3.3050709@redhat.com> References: <1302717340-26901-1-git-send-email-laine@laine.org> <1302808015-11280-1-git-send-email-laine@laine.org> <4DA748B3.3050709@redhat.com> Message-ID: <4DA75C89.8080102@laine.org> On 04/14/2011 03:19 PM, Eric Blake wrote: > --- >> src/network/bridge_driver.c | 16 +++++++++++++++- >> 1 files changed, 15 insertions(+), 1 deletions(-) > Here's making my IRC review official: > > ACK. Pushed. Thanks! From eblake at redhat.com Thu Apr 14 20:45:11 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 14 Apr 2011 14:45:11 -0600 Subject: [libvirt] [PATCH 2/3] qemu: unlock qemu driver and vm before returning from processWatchdogEvent() In-Reply-To: <4D9C1CED.20202@cn.fujitsu.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1CED.20202@cn.fujitsu.com> Message-ID: <4DA75CD7.9080908@redhat.com> On 04/06/2011 01:57 AM, Wen Congyang wrote: > When the function processWatchdogEvent() failed, we only free wdEvent, but > forget to unlock qemu driver and vm, free dumpfile. > > --- > src/qemu/qemu_driver.c | 28 +++++++++++++++++++--------- > 1 files changed, 19 insertions(+), 9 deletions(-) I spoke too soon. > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index dd84f65..628cfe3 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -2400,19 +2400,22 @@ static void processWatchdogEvent(void *data, void *opaque) > wdEvent->vm->def->name, Oops - this is reading from wdEvent->vm contents... > (unsigned int)time(NULL)) < 0) { > virReportOOMError(); > - break; > + goto cleanup; > } > > qemuDriverLock(driver); > virDomainObjLock(wdEvent->vm); ...prior to obtaining the lock. I think we need to swap that order. > + default: > + goto cleanup; > } > > +endjob: > + if (qemuDomainObjEndJob(wdEvent->vm) == 0) > + wdEvent->vm = NULL; > + > +unlock: > + if (wdEvent->vm) > + virDomainObjUnlock(wdEvent->vm); > + qemuDriverUnlock(driver); > + > +cleanup: > VIR_FREE(wdEvent); If you do that, then nothing in the VIR_DOMAIN_WATCHDOG_ACTION_DUMP case jumps to cleanup, and after patch 3, the default case also unlocks the vm rather than jumping to cleanup. I think you need to send a v2 patch with 2 and 3 squashed into a single fix. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From igor47 at moomers.org Thu Apr 14 20:52:27 2011 From: igor47 at moomers.org (Igor Serebryany) Date: Thu, 14 Apr 2011 15:52:27 -0500 Subject: [libvirt] [PATCH] implement BOOT_TIMEOUT In-Reply-To: <4DA759E4.7080401@redhat.com> References: <1302682502-4967-1-git-send-email-atodorov@otb.bg> <4DA5DE06.6070507@redhat.com> <4DA6CAC2.5080409@otb.bg> <4DA759E4.7080401@redhat.com> Message-ID: <20110414205227.GC23639@moomers.org> On Thu, Apr 14, 2011 at 02:32:36PM -0600, Eric Blake wrote: > Without more code on the libvirt front, I think you're stuck renaming > the guests to enforce naming order (assuming that libvirt even goes by > sorted name order, as opposed to readdir() order where you have no control). I solved this problem in my own application, a layer above libvirt. I simply make all of my domains non-persistent. When the node reboots, nothing starts up. My application detects that domains that should be running aren't and defines/starts them. It's easy at that point to start them up in whatever order I want and give whatever delay between startups. Even if you don't have some overarching managing application (like, if you're managing one node instead of hundreds), you could easily do something similar with a cron job. --Igor -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 198 bytes Desc: Digital signature URL: From laine at laine.org Thu Apr 14 23:18:31 2011 From: laine at laine.org (Laine Stump) Date: Thu, 14 Apr 2011 19:18:31 -0400 Subject: [libvirt] [PATCH] implement BOOT_TIMEOUT In-Reply-To: <4DA759E4.7080401@redhat.com> References: <1302682502-4967-1-git-send-email-atodorov@otb.bg> <4DA5DE06.6070507@redhat.com> <4DA6CAC2.5080409@otb.bg> <4DA759E4.7080401@redhat.com> Message-ID: <4DA780C7.4040602@laine.org> On 04/14/2011 04:32 PM, Eric Blake wrote: > On 04/14/2011 04:21 AM, Alexander Todorov wrote: >> I've come across a situation where one of the guests needs to start >> first (provides a database) and then another guests needs to start >> second (an app server). The reason is that this is a proprietary app >> which is badly written and fails to connect/re-connect to the database >> if it is not online in the first place. > Without more code on the libvirt front, I think you're stuck renaming > the guests to enforce naming order (assuming that libvirt even goes by > sorted name order, as opposed to readdir() order where you have no control). Of course that does no good if guest A which happens to startup on Host 1 has a prerequisite of guest B which may already be running on Host 2, or may not be running at all. So should libvirt try to solve the problem for the special case of all guests on one host, or defer it to higher level management, which may know about more than one host? Maybe libvirt could just make space for the information about dependencies in the domain XML, but not do anything to try and enforce it (or maybe that could be something optionally enabled in system config for installations with a single host). From wency at cn.fujitsu.com Fri Apr 15 03:00:35 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Fri, 15 Apr 2011 11:00:35 +0800 Subject: [libvirt] [PATCH] build: include esx_vi.generated.* into dist file Message-ID: <4DA7B4D3.4060308@cn.fujitsu.com> commit d4601696 introduces two more generated files: esx_vi.generated.h and esx_vi.generated.h. But we do not include them into dist file. It will break building if using dist file to build. --- src/Makefile.am | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index dce866e..1eaa7d1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -332,7 +332,9 @@ ESX_DRIVER_GENERATED = \ esx/esx_vi_types.generated.typedef \ esx/esx_vi_types.generated.typeenum \ esx/esx_vi_types.generated.typetostring \ - esx/esx_vi_types.generated.typefromstring + esx/esx_vi_types.generated.typefromstring \ + esx/esx_vi.generated.c \ + esx/esx_vi.generated.h ESX_DRIVER_EXTRA_DIST = \ esx/README \ -- 1.7.1 From wency at cn.fujitsu.com Fri Apr 15 03:11:39 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Fri, 15 Apr 2011 11:11:39 +0800 Subject: [libvirt] [PATCH V3 2/2] enhance processWatchdogEvent() In-Reply-To: <4DA75CD7.9080908@redhat.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1CED.20202@cn.fujitsu.com> <4DA75CD7.9080908@redhat.com> Message-ID: <4DA7B76B.3010308@cn.fujitsu.com> This patch do the following two things: 1. hold an extra reference while handling watchdog event If the domain is not persistent, and qemu quits unexpectedly before calling processWatchdogEvent(), vm will be freed and the function processWatchdogEvent() will be dangerous. 2. unlock qemu driver and vm before returning from processWatchdogEvent() When the function processWatchdogEvent() failed, we only free wdEvent, but forget to unlock qemu driver and vm, free dumpfile. --- src/qemu/qemu_driver.c | 34 ++++++++++++++++++++++------------ src/qemu/qemu_process.c | 4 ++++ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d5c1274..f6e503a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2442,6 +2442,9 @@ static void processWatchdogEvent(void *data, void *opaque) struct qemuDomainWatchdogEvent *wdEvent = data; struct qemud_driver *driver = opaque; + qemuDriverLock(driver); + virDomainObjLock(wdEvent->vm); + switch (wdEvent->action) { case VIR_DOMAIN_WATCHDOG_ACTION_DUMP: { @@ -2452,19 +2455,19 @@ static void processWatchdogEvent(void *data, void *opaque) wdEvent->vm->def->name, (unsigned int)time(NULL)) < 0) { virReportOOMError(); - break; + goto unlock; } - qemuDriverLock(driver); - virDomainObjLock(wdEvent->vm); - - if (qemuDomainObjBeginJobWithDriver(driver, wdEvent->vm) < 0) - break; + if (qemuDomainObjBeginJobWithDriver(driver, wdEvent->vm) < 0) { + VIR_FREE(dumpfile); + goto unlock; + } if (!virDomainObjIsActive(wdEvent->vm)) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); - break; + VIR_FREE(dumpfile); + goto endjob; } ret = doCoreDump(driver, @@ -2481,16 +2484,23 @@ static void processWatchdogEvent(void *data, void *opaque) qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Resuming after dump failed")); - if (qemuDomainObjEndJob(wdEvent->vm) > 0) - virDomainObjUnlock(wdEvent->vm); - - qemuDriverUnlock(driver); - VIR_FREE(dumpfile); } break; + default: + goto unlock; } +endjob: + /* Safe to ignore value since ref count was incremented in + * qemuProcessHandleWatchdog(). + */ + ignore_value(qemuDomainObjEndJob(wdEvent->vm)); + +unlock: + if (virDomainObjUnref(wdEvent->vm) > 0) + virDomainObjUnlock(wdEvent->vm); + qemuDriverUnlock(driver); VIR_FREE(wdEvent); } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 7295f9e..b6bec46 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -428,6 +428,10 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, if (VIR_ALLOC(wdEvent) == 0) { wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP; wdEvent->vm = vm; + /* Hold an extra reference because we can't allow 'vm' to be + * deleted before handling watchdog event is finished. + */ + virDomainObjRef(vm); ignore_value(virThreadPoolSendJob(driver->workerPool, wdEvent)); } else virReportOOMError(); -- 1.7.1 From matthias.bolte at googlemail.com Fri Apr 15 06:03:41 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 15 Apr 2011 08:03:41 +0200 Subject: [libvirt] [PATCH] build: include esx_vi.generated.* into dist file In-Reply-To: <4DA7B4D3.4060308@cn.fujitsu.com> References: <4DA7B4D3.4060308@cn.fujitsu.com> Message-ID: 2011/4/15 Wen Congyang : > commit d4601696 introduces two more generated files: esx_vi.generated.h > and esx_vi.generated.h. But we do not include them into dist file. > It will break building if using dist file to build. > > --- > ?src/Makefile.am | ? ?4 +++- > ?1 files changed, 3 insertions(+), 1 deletions(-) > > diff --git a/src/Makefile.am b/src/Makefile.am > index dce866e..1eaa7d1 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -332,7 +332,9 @@ ESX_DRIVER_GENERATED = ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ > ? ? ? ? ? ? ? ?esx/esx_vi_types.generated.typedef ? ? ? ? ? ? ? ? ? ? ?\ > ? ? ? ? ? ? ? ?esx/esx_vi_types.generated.typeenum ? ? ? ? ? ? ? ? ? ? \ > ? ? ? ? ? ? ? ?esx/esx_vi_types.generated.typetostring ? ? ? ? ? ? ? ? \ > - ? ? ? ? ? ? ? esx/esx_vi_types.generated.typefromstring > + ? ? ? ? ? ? ? esx/esx_vi_types.generated.typefromstring ? ? ? ? ? ? ? \ > + ? ? ? ? ? ? ? esx/esx_vi.generated.c ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ > + ? ? ? ? ? ? ? esx/esx_vi.generated.h > > ?ESX_DRIVER_EXTRA_DIST = ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ > ? ? ? ? ? ? ? ?esx/README ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ > -- > 1.7.1 > ACK. Matthias From minovotn at redhat.com Fri Apr 15 06:45:20 2011 From: minovotn at redhat.com (Michal Novotny) Date: Fri, 15 Apr 2011 08:45:20 +0200 Subject: [libvirt] [PATCH 0/2] Network: Add TXT record and hosts support for DNS on virtual network In-Reply-To: <20110330134648.GF16213@redhat.com> References: <1301489832-32475-1-git-send-email-minovotn@redhat.com> <20110330134648.GF16213@redhat.com> Message-ID: <4DA7E980.8000905@redhat.com> Any followup on v2 of the patch? Just because Daniel (Veillard) wrote something after 0.9.0 and I read already something about 0.9.1 so I would like to remind about v2 of the patch because I don't want it to go to the /dev/null :) Michal On 03/30/2011 03:46 PM, Daniel Veillard wrote: > On Wed, Mar 30, 2011 at 02:57:10PM +0200, Michal Novotny wrote: >> Hi, >> this is the patch to introduce the TXT record support for the DNS >> service on the virtual network. This can be defined using the >> txt-record subelement in the dns element of the network XML >> description. >> >> First patch is adding TXT record support to the DNS service on >> the virtual network and the second patch is adding support for >> defining hosts for the DNS service. >> >> The new definition syntax is: >> >> >> >> >> gateway >> host >> >> >> >> Where multiple host elements can be defined to put the aliases >> for specified IP addresses. >> >> The patch series has been tested for the configuration and it >> was working fine and also RelaxNG schema with the tests have >> been both altered to add test cases to test those patches. >> >> Both of the patches passed make, syntax checking and all the >> tests. > Principle sounds fine but let's defer this to after 0.9.0, :) > > Daniel > -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 15 07:02:17 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 15 Apr 2011 16:02:17 +0900 Subject: [libvirt] [RFC][PATCHv1 0/5] libvirt - show per cpu accounting information Message-ID: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> When running 'virt-top -1' , "show percpu statistics mode", virt-top shows a fake value. When running 'while true; do echo hello;done' on a 4vcpu guest, == 0 0.0 1 0.0 2 0.0 3 0.0 4 25.0 25.0= 5 25.0 25.0=# 6 25.0 25.0= 7 25.0 25.0= == All cpus just used equally ;) This is because there is no interface to get per-cpu usage of domain. This patch adds an interface virDomainPcpuStats() to get per-cpu statistics, cpuTime in nanoseconds. Here is a test result with a python script using new interface. == [root at bluextal python]# ./virt-cpuacct.py ({'cpuTime': 0L}, {'cpuTime': 0L}, {'cpuTime': 0L}, {'cpuTime': 0L}, {'cpuTime': 4679204346L}, {'cpuTime': 2103820380L}, {'cpuTime': 8904513019L}, {'cpuTime': 7424701195L}) [root at bluextal python]# ./virt-cpuacct.py ({'cpuTime': 0L}, {'cpuTime': 0L}, {'cpuTime': 0L}, {'cpuTime': 0L}, {'cpuTime': 57010689139L}, {'cpuTime': 26152907202L}, {'cpuTime': 53759693931L}, {'cpuTime': 43074348218L}) == Although I added a new interface, I still wonder what interface is better... any comments are welcome. Thanks, -Kame From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 15 07:03:46 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 15 Apr 2011 16:03:46 +0900 Subject: [libvirt] [RFC][PATCHv1 1/5] libvirt - show cpuacct cgroup's percpu statistics. In-Reply-To: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110415160346.0dc31fb0.kamezawa.hiroyu@jp.fujitsu.com> cpuacct cgroup provides per cpu cputime. Add an interface for that. Signed-off-by: KAMEZAWA Hiroyuki --- src/libvirt_private.syms | 1 + src/util/cgroup.c | 27 +++++++++++++++++++++++++++ src/util/cgroup.h | 2 ++ 3 files changed, 30 insertions(+), 0 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ba7739d..f7a1ee7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -70,6 +70,7 @@ virCgroupFree; virCgroupGetBlkioWeight; virCgroupGetCpuShares; virCgroupGetCpuacctUsage; +virCgroupGetCpuacctUsagePercpu; virCgroupGetFreezerState; virCgroupGetMemoryHardLimit; virCgroupGetMemorySoftLimit; diff --git a/src/util/cgroup.c b/src/util/cgroup.c index afe8731..58ea805 100644 --- a/src/util/cgroup.c +++ b/src/util/cgroup.c @@ -1329,6 +1329,33 @@ int virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long *usage) "cpuacct.usage", usage); } +int virCgroupGetCpuacctUsagePercpu(virCgroupPtr group, + int nr, unsigned long long *usage) +{ + int i, rc; + char *strval = NULL; + char *startp, *endp; + unsigned long long int value; + + memset(usage, 0, sizeof(unsigned long long) * nr); + + rc = virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPUACCT, + "cpuacct.usage_percpu", &strval); + if (rc) + goto out; + + for (i = 0, startp = strval; i < nr; i++) { + if (virStrToLong_ull(startp, &endp, 10, &value)) + break; + startp = endp; + usage[i] = value; + } + rc = i; +out: + VIR_FREE(strval); + return rc; +} + int virCgroupSetFreezerState(virCgroupPtr group, const char *state) { return virCgroupSetValueStr(group, diff --git a/src/util/cgroup.h b/src/util/cgroup.h index 8ae756d..31cbcba 100644 --- a/src/util/cgroup.h +++ b/src/util/cgroup.h @@ -100,6 +100,8 @@ int virCgroupSetCpuShares(virCgroupPtr group, unsigned long long shares); int virCgroupGetCpuShares(virCgroupPtr group, unsigned long long *shares); int virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long *usage); +int virCgroupGetCpuacctUsagePercpu(virCgroupPtr group, + int nr, unsigned long long *usage); int virCgroupSetFreezerState(virCgroupPtr group, const char *state); int virCgroupGetFreezerState(virCgroupPtr group, char **state); -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 15 07:04:52 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 15 Apr 2011 16:04:52 +0900 Subject: [libvirt] [RFC][PATCHv1 2/5] libvirt - new API for getting percpu statistics of VM In-Reply-To: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110415160452.63bd9216.kamezawa.hiroyu@jp.fujitsu.com> Per (host) cpu activity of VMs are very insterested numbers when running VMs on large SMPs. virt-top -1 mode tries to provide the information. (But it's not implemented.) This patch adds a libvirt interface to get per cpu statistics of each nodes. This patch just adds an interface and driver entry points. So, - doesn't include patches for python. - doesn't include any driver. Following patches will add some drivers and codes for python. Signed-off-by: KAMEZAWA Hiroyuki --- include/libvirt/libvirt.h.in | 13 ++++++++++ src/driver.h | 6 ++++ src/esx/esx_driver.c | 1 + src/libvirt.c | 55 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 4 +++ src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 1 + src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xenapi/xenapi_driver.c | 1 + 17 files changed, 91 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 5783303..6b9292c 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -400,6 +400,13 @@ struct _virDomainMemoryStat { typedef virDomainMemoryStatStruct *virDomainMemoryStatPtr; +typedef struct _virDomainPcpuStat virDomainPcpuStatStruct; + +struct _virDomainPcpuStat { + unsigned long long cpuTime; +}; + +typedef virDomainPcpuStatStruct *virDomainPcpuStatPtr; /* Domain core dump flags. */ typedef enum { @@ -923,6 +930,12 @@ int virDomainMemoryStats (virDomainPtr dom, virDomainMemoryStatPtr stats, unsigned int nr_stats, unsigned int flags); + +int virDomainPcpuStats (virDomainPtr dom, + virDomainPcpuStatPtr stats, + unsigned int nr_stats, + unsigned int flags); + int virDomainBlockPeek (virDomainPtr dom, const char *path, unsigned long long offset, diff --git a/src/driver.h b/src/driver.h index a8b79e6..ee1dac7 100644 --- a/src/driver.h +++ b/src/driver.h @@ -291,6 +291,11 @@ typedef int (virDomainPtr domain, struct _virDomainMemoryStat *stats, unsigned int nr_stats); +typedef int + (*virDrvDomainPcpuStats) + (virDomainPtr domain, + struct _virDomainPcpuStat *stats, + unsigned int nr_stats); typedef int (*virDrvDomainBlockPeek) @@ -599,6 +604,7 @@ struct _virDriver { virDrvDomainBlockStats domainBlockStats; virDrvDomainInterfaceStats domainInterfaceStats; virDrvDomainMemoryStats domainMemoryStats; + virDrvDomainPcpuStats domainPcpuStats; virDrvDomainBlockPeek domainBlockPeek; virDrvDomainMemoryPeek domainMemoryPeek; virDrvDomainGetBlockInfo domainGetBlockInfo; diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 50c631b..34a31f0 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4632,6 +4632,7 @@ static virDriver esxDriver = { NULL, /* domainBlockStats */ NULL, /* domainInterfaceStats */ NULL, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ diff --git a/src/libvirt.c b/src/libvirt.c index 0da9885..24ef621 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -4595,6 +4595,61 @@ error: } /** + * virDomainPcpuStats: + * @dom: pointer to the domain object + * @stats: nr_stats-sized array of stat structures (returned) + * @nr_stats: number of cpu statistics requested + * @flags: unused, always pass 0 + * + * This function provides per-cpu statistics for the domain. 'cpu' here means + * not vcpu. + * + * Up to 'nr_stats' elements of 'stats' will be populated with cpu statistics + * from the domain. Only statistics supported by the domain, the driver, and + * this version of libvirt will be returned. + * + * Now, only cpuTime per cpu is reported in nanoseconds. + * + * Returns: The number of stats provided or -1 in case of failure. + */ +int virDomainPcpuStats (virDomainPtr dom, virDomainPcpuStatPtr stats, + unsigned int nr_stats, unsigned int flags) +{ + virConnectPtr conn; + unsigned long nr_stats_ret = 0; + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN (dom)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + if (flags != 0) { + virLibDomainError(VIR_ERR_INVALID_ARG, + _("flags must be zero")); + goto error; + } + + if (!stats || nr_stats == 0) + return 0; + + conn = dom->conn; + if (conn->driver->domainPcpuStats) { + nr_stats_ret = conn->driver->domainPcpuStats (dom, stats, nr_stats); + if (nr_stats_ret == -1) + goto error; + return nr_stats_ret; + } + + virLibDomainError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(dom->conn); + return -1; +} + +/** * virDomainBlockPeek: * @dom: pointer to the domain object * @path: path to the block device diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b4aed41..312ba66 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -436,4 +436,8 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8; +LIBVIRT_0.9.1 { + global: + virDomainPcpuStats; +} LIBVIRT_0.9.0; # .... define new API here using predicted next version number .... diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 3040914..285dcaa 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2623,6 +2623,7 @@ static virDriver libxlDriver = { NULL, /* domainBlockStats */ NULL, /* domainInterfaceStats */ NULL, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e905302..9046a58 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2866,6 +2866,7 @@ static virDriver lxcDriver = { NULL, /* domainBlockStats */ lxcDomainInterfaceStats, /* domainInterfaceStats */ NULL, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 4af28e9..0c0004d 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1627,6 +1627,7 @@ static virDriver openvzDriver = { NULL, /* domainBlockStats */ NULL, /* domainInterfaceStats */ NULL, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 3862c9c..ac62d62 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -4579,6 +4579,7 @@ static virDriver phypDriver = { NULL, /* domainBlockStats */ NULL, /* domainInterfaceStats */ NULL, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c1a44c9..0a78a70 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6981,6 +6981,7 @@ static virDriver qemuDriver = { qemudDomainBlockStats, /* domainBlockStats */ qemudDomainInterfaceStats, /* domainInterfaceStats */ qemudDomainMemoryStats, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ qemudDomainBlockPeek, /* domainBlockPeek */ qemudDomainMemoryPeek, /* domainMemoryPeek */ qemuDomainGetBlockInfo, /* domainGetBlockInfo */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index b979f71..d00b9ee 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -11261,6 +11261,7 @@ static virDriver remote_driver = { remoteDomainBlockStats, /* domainBlockStats */ remoteDomainInterfaceStats, /* domainInterfaceStats */ remoteDomainMemoryStats, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ remoteDomainBlockPeek, /* domainBlockPeek */ remoteDomainMemoryPeek, /* domainMemoryPeek */ remoteDomainGetBlockInfo, /* domainGetBlockInfo */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 17f5ad9..0489492 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5407,6 +5407,7 @@ static virDriver testDriver = { testDomainBlockStats, /* domainBlockStats */ testDomainInterfaceStats, /* domainInterfaceStats */ NULL, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 33849a0..f3372fa 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2213,6 +2213,7 @@ static virDriver umlDriver = { NULL, /* domainBlockStats */ NULL, /* domainInterfaceStats */ NULL, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ umlDomainBlockPeek, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 3ca34dd..4467866 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8602,6 +8602,7 @@ virDriver NAME(Driver) = { NULL, /* domainBlockStats */ NULL, /* domainInterfaceStats */ NULL, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index bbfb1a4..d98ea45 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -967,6 +967,7 @@ static virDriver vmwareDriver = { NULL, /* domainBlockStats */ NULL, /* domainInterfaceStats */ NULL, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 9f47722..1a76623 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2101,6 +2101,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedDomainBlockStats, /* domainBlockStats */ xenUnifiedDomainInterfaceStats, /* domainInterfaceStats */ NULL, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ xenUnifiedDomainBlockPeek, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 60b23c7..62d83d8 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1849,6 +1849,7 @@ static virDriver xenapiDriver = { NULL, /* domainBlockStats */ NULL, /* domainInterfaceStats */ NULL, /* domainMemoryStats */ + NULL, /* domainPcpuStats */ NULL, /* domainBlockPeek */ NULL, /* domainMemoryPeek */ NULL, /* domainGetBlockInfo */ -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 15 07:05:56 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 15 Apr 2011 16:05:56 +0900 Subject: [libvirt] [RFC][PATCHv1 3/5] Add a remote driver for virDomainPcpuStats() In-Reply-To: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110415160556.d0ce7e3a.kamezawa.hiroyu@jp.fujitsu.com> Signed-off-by: KAMEZAWA Hiroyuki --- daemon/remote.c | 61 +++++++++++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++ daemon/remote_dispatch_ret.h | 1 + daemon/remote_dispatch_table.h | 5 +++ src/remote/remote_driver.c | 39 +++++++++++++++++++++- src/remote/remote_protocol.c | 31 ++++++++++++++++++ src/remote/remote_protocol.h | 27 +++++++++++++++ src/remote/remote_protocol.x | 18 ++++++++++- 9 files changed, 189 insertions(+), 2 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 5de1055..9757f13 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1138,6 +1138,67 @@ remoteDispatchDomainMemoryStats(struct qemud_server *server ATTRIBUTE_UNUSED, } static int +remoteDispatchDomainPcpuStats(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_pcpu_stats_args *args, + remote_domain_pcpu_stats_ret *ret) +{ + virDomainPtr dom; + struct _virDomainPcpuStat *stats; + unsigned int nr_stats, i; + + if (!conn) { + remoteDispatchFormatError(rerr, "%s", _("connection not open")); + return -1; + } + + if (args->nr_stats > REMOTE_DOMAIN_PCPU_STATS_MAX) { + remoteDispatchFormatError(rerr, "%s", + _("nr_stats > REMOTE_DOMAIN_PCPU_STATS_MAX")); + return -1; + } + + dom = get_nonnull_domain(conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + /* Allocate stats array for making dispatch call */ + if (VIR_ALLOC_N(stats, args->nr_stats) < 0) { + virDomainFree(dom); + remoteDispatchOOMError(rerr); + return -1; + } + + nr_stats = virDomainPcpuStats(dom, stats, args->nr_stats, 0); + if (nr_stats == -1) { + VIR_FREE(stats); + remoteDispatchConnError(rerr, conn); + virDomainFree(dom); + return -1; + } + virDomainFree(dom); + + /* Allocate return buffer */ + if (VIR_ALLOC_N(ret->stats.stats_val, nr_stats) < 0) { + VIR_FREE(stats); + remoteDispatchOOMError(rerr); + return -1; + } + + /* Copy the stats into the xdr return structure */ + for (i = 0; i < nr_stats; i++) + ret->stats.stats_val[i].val = stats[i].cpuTime; + ret->stats.stats_len = nr_stats; + VIR_FREE(stats); + return 0; +} + +static int remoteDispatchDomainBlockPeek(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index f9537d7..42fc7b2 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -178,3 +178,4 @@ remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; remote_storage_vol_upload_args val_remote_storage_vol_upload_args; remote_storage_vol_download_args val_remote_storage_vol_download_args; + remote_domain_pcpu_stats_args val_remote_domain_pcpu_stats_args; diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 18bf41d..5dece04 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -498,6 +498,14 @@ static int remoteDispatchDomainOpenConsole( remote_error *err, remote_domain_open_console_args *args, void *ret); +static int remoteDispatchDomainPcpuStats( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_pcpu_stats_args *args, + remote_domain_pcpu_stats_ret *ret); static int remoteDispatchDomainPinVcpu( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_ret.h b/daemon/remote_dispatch_ret.h index 114e832..4c0b66d 100644 --- a/daemon/remote_dispatch_ret.h +++ b/daemon/remote_dispatch_ret.h @@ -140,3 +140,4 @@ remote_domain_is_updated_ret val_remote_domain_is_updated_ret; remote_get_sysinfo_ret val_remote_get_sysinfo_ret; remote_domain_get_blkio_parameters_ret val_remote_domain_get_blkio_parameters_ret; + remote_domain_pcpu_stats_ret val_remote_domain_pcpu_stats_ret; diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index b39f7c2..cb1fa05 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1052,3 +1052,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* DomainPcpuStats => 210 */ + .fn = (dispatch_fn) remoteDispatchDomainPcpuStats, + .args_filter = (xdrproc_t) xdr_remote_domain_pcpu_stats_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_pcpu_stats_ret, +}, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index d00b9ee..6f7c2e7 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -4172,6 +4172,43 @@ done: return rv; } + +static int +remoteDomainPcpuStats (virDomainPtr domain, + struct _virDomainPcpuStat *stats, + unsigned int nr_stats) +{ + int rv = -1; + remote_domain_pcpu_stats_args args; + remote_domain_pcpu_stats_ret ret; + struct private_data *priv = domain->conn->privateData; + unsigned int i; + + remoteDriverLock(priv); + + make_nonnull_domain (&args.dom, domain); + args.nr_stats = nr_stats; + + memset (&ret, 0, sizeof ret); + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_PCPU_STATS, + (xdrproc_t) xdr_remote_domain_pcpu_stats_args, + (char *) &args, + (xdrproc_t) xdr_remote_domain_pcpu_stats_ret, + (char *) &ret) == -1) + goto done; + + for (i = 0; i < ret.stats.stats_len; i++) + stats[i].cpuTime = ret.stats.stats_val[i].val; + rv = ret.stats.stats_len; + xdr_free((xdrproc_t) xdr_remote_domain_pcpu_stats_ret, (char *) &ret); + + done: + remoteDriverUnlock(priv); + return rv; +} + + static int remoteDomainBlockPeek (virDomainPtr domain, const char *path, @@ -11261,7 +11298,7 @@ static virDriver remote_driver = { remoteDomainBlockStats, /* domainBlockStats */ remoteDomainInterfaceStats, /* domainInterfaceStats */ remoteDomainMemoryStats, /* domainMemoryStats */ - NULL, /* domainPcpuStats */ + remoteDomainPcpuStats, /* domainPcpuStats */ remoteDomainBlockPeek, /* domainBlockPeek */ remoteDomainMemoryPeek, /* domainMemoryPeek */ remoteDomainGetBlockInfo, /* domainGetBlockInfo */ diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 5604371..53825ea 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -872,6 +872,37 @@ xdr_remote_domain_memory_stats_ret (XDR *xdrs, remote_domain_memory_stats_ret *o } bool_t +xdr_remote_domain_pcpu_stats_args (XDR *xdrs, remote_domain_pcpu_stats_args *objp) +{ + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->nr_stats)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_pcpu_stat (XDR *xdrs, remote_domain_pcpu_stat *objp) +{ + + if (!xdr_uint64_t (xdrs, &objp->val)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_pcpu_stats_ret (XDR *xdrs, remote_domain_pcpu_stats_ret *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->stats.stats_val; + + if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->stats.stats_len, REMOTE_DOMAIN_PCPU_STATS_MAX, + sizeof (remote_domain_pcpu_stat), (xdrproc_t) xdr_remote_domain_pcpu_stat)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_domain_block_peek_args (XDR *xdrs, remote_domain_block_peek_args *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index d9bf151..f220de9 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -59,6 +59,7 @@ typedef remote_nonnull_string *remote_string; #define REMOTE_AUTH_SASL_DATA_MAX 65536 #define REMOTE_AUTH_TYPE_LIST_MAX 20 #define REMOTE_DOMAIN_MEMORY_STATS_MAX 1024 +#define REMOTE_DOMAIN_PCPU_STATS_MAX 1024 #define REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX 1024 #define REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX 65536 #define REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX 65536 @@ -463,6 +464,25 @@ struct remote_domain_memory_stats_ret { }; typedef struct remote_domain_memory_stats_ret remote_domain_memory_stats_ret; +struct remote_domain_pcpu_stats_args { + remote_nonnull_domain dom; + u_int nr_stats; +}; +typedef struct remote_domain_pcpu_stats_args remote_domain_pcpu_stats_args; + +struct remote_domain_pcpu_stat { + uint64_t val; +}; +typedef struct remote_domain_pcpu_stat remote_domain_pcpu_stat; + +struct remote_domain_pcpu_stats_ret { + struct { + u_int stats_len; + remote_domain_pcpu_stat *stats_val; + } stats; +}; +typedef struct remote_domain_pcpu_stats_ret remote_domain_pcpu_stats_ret; + struct remote_domain_block_peek_args { remote_nonnull_domain dom; remote_nonnull_string path; @@ -2413,6 +2433,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_PCPU_STATS = 210, }; typedef enum remote_procedure remote_procedure; @@ -2507,6 +2528,9 @@ extern bool_t xdr_remote_domain_interface_stats_ret (XDR *, remote_domain_inter extern bool_t xdr_remote_domain_memory_stats_args (XDR *, remote_domain_memory_stats_args*); extern bool_t xdr_remote_domain_memory_stat (XDR *, remote_domain_memory_stat*); extern bool_t xdr_remote_domain_memory_stats_ret (XDR *, remote_domain_memory_stats_ret*); +extern bool_t xdr_remote_domain_pcpu_stats_args (XDR *, remote_domain_pcpu_stats_args*); +extern bool_t xdr_remote_domain_pcpu_stat (XDR *, remote_domain_pcpu_stat*); +extern bool_t xdr_remote_domain_pcpu_stats_ret (XDR *, remote_domain_pcpu_stats_ret*); extern bool_t xdr_remote_domain_block_peek_args (XDR *, remote_domain_block_peek_args*); extern bool_t xdr_remote_domain_block_peek_ret (XDR *, remote_domain_block_peek_ret*); extern bool_t xdr_remote_domain_memory_peek_args (XDR *, remote_domain_memory_peek_args*); @@ -2864,6 +2888,9 @@ extern bool_t xdr_remote_domain_interface_stats_ret (); extern bool_t xdr_remote_domain_memory_stats_args (); extern bool_t xdr_remote_domain_memory_stat (); extern bool_t xdr_remote_domain_memory_stats_ret (); +extern bool_t xdr_remote_domain_pcpu_stats_args (); +extern bool_t xdr_remote_domain_pcpu_stat (); +extern bool_t xdr_remote_domain_pcpu_stats_ret (); extern bool_t xdr_remote_domain_block_peek_args (); extern bool_t xdr_remote_domain_block_peek_ret (); extern bool_t xdr_remote_domain_memory_peek_args (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 675eccd..7ab7704 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -146,6 +146,9 @@ const REMOTE_AUTH_TYPE_LIST_MAX = 20; /* Upper limit on list of memory stats */ const REMOTE_DOMAIN_MEMORY_STATS_MAX = 1024; +/* Upper limit on list of pcpu stats */ +const REMOTE_DOMAIN_PCPU_STATS_MAX = 1024; + /* Upper limit on lists of domain snapshots. */ const REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX = 1024; @@ -554,6 +557,18 @@ struct remote_domain_memory_stats_ret { remote_domain_memory_stat stats; }; +struct remote_domain_pcpu_stats_args { + remote_nonnull_domain dom; + u_int nr_stats; +}; + +struct remote_domain_pcpu_stat { + unsigned hyper val; +}; +struct remote_domain_pcpu_stats_ret { + remote_domain_pcpu_stat stats; +}; + struct remote_domain_block_peek_args { remote_nonnull_domain dom; remote_nonnull_string path; @@ -2176,7 +2191,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_PCPU_STATS = 210 /* * Notice how the entries are grouped in sets of 10 ? -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 15 07:06:56 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 15 Apr 2011 16:06:56 +0900 Subject: [libvirt] [RFC][PATCHv1 4/5] Add a python interface for virDomainPcpuStats. In-Reply-To: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110415160656.62e8a43c.kamezawa.hiroyu@jp.fujitsu.com> Values of all cpus are returned by a tuple of Dict as: [{cpuTime: xxxx}, {cpuTime: yyyy}} # when the number of cpu is 2. Signed-off-by: KAMEZAWA Hiroyuki --- python/generator.py | 1 + python/libvirt-override-api.xml | 5 ++++ python/libvirt-override.c | 42 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 0 deletions(-) diff --git a/python/generator.py b/python/generator.py index 4fa4f65..d2695bb 100755 --- a/python/generator.py +++ b/python/generator.py @@ -307,6 +307,7 @@ skip_impl = ( 'virDomainBlockStats', 'virDomainInterfaceStats', 'virDomainMemoryStats', + 'virDomainPcpuStats', 'virNodeGetCellsFreeMemory', 'virDomainGetSchedulerType', 'virDomainGetSchedulerParameters', diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml index 54deeb5..5ee3881 100644 --- a/python/libvirt-override-api.xml +++ b/python/libvirt-override-api.xml @@ -127,6 +127,11 @@ + + Extracts per cpu statistics for a domain + + + Returns the available memory for a list of cells diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 4a9b432..c2ff0aa 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -164,6 +164,47 @@ libvirt_virDomainMemoryStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { return info; } +static PyObject* +libvirt_virDomainPcpuStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { + virDomainPtr domain; + virNodeInfo nodeinfo; + PyObject *pyobj_domain; + PyObject *info, *info2; + int nr_stats, i_retval, i; + virDomainPcpuStatPtr stats; + + if (!PyArg_ParseTuple(args, (char *)"O:virDomainPcpuStats", &pyobj_domain)) + return (NULL); + + domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virNodeGetInfo(virDomainGetConnect(domain), &nodeinfo); + LIBVIRT_END_ALLOW_THREADS; + if (i_retval < 0) + return VIR_PY_NONE; + + stats = malloc(sizeof(struct _virDomainPcpuStat) * nodeinfo.cpus); + + nr_stats = virDomainPcpuStats(domain, stats, nodeinfo.cpus, 0); + + if (nr_stats == -1) + return VIR_PY_NONE; + + if ((info = PyTuple_New(nodeinfo.cpus)) == NULL) + return VIR_PY_NONE; + + for (i = 0; i < nr_stats; i++) { + if ((info2 = PyDict_New()) == NULL) + return VIR_PY_NONE; + PyDict_SetItem(info2, libvirt_constcharPtrWrap("cpuTime"), + PyLong_FromLongLong(stats[i].cpuTime)); + PyTuple_SetItem(info, i, info2); + } + return (info); +} + + static PyObject * libvirt_virDomainGetSchedulerType(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { @@ -3545,6 +3586,7 @@ static PyMethodDef libvirtMethods[] = { {(char *) "virDomainBlockStats", libvirt_virDomainBlockStats, METH_VARARGS, NULL}, {(char *) "virDomainInterfaceStats", libvirt_virDomainInterfaceStats, METH_VARARGS, NULL}, {(char *) "virDomainMemoryStats", libvirt_virDomainMemoryStats, METH_VARARGS, NULL}, + {(char *) "virDomainPcpuStats", libvirt_virDomainPcpuStats, METH_VARARGS, NULL}, {(char *) "virNodeGetCellsFreeMemory", libvirt_virNodeGetCellsFreeMemory, METH_VARARGS, NULL}, {(char *) "virDomainGetSchedulerType", libvirt_virDomainGetSchedulerType, METH_VARARGS, NULL}, {(char *) "virDomainGetSchedulerParameters", libvirt_virDomainGetSchedulerParameters, METH_VARARGS, NULL}, -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 15 07:07:49 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 15 Apr 2011 16:07:49 +0900 Subject: [libvirt] [RFC][PATCHv1 5/5] Add a qemu driver for virDomainPcpuStats() In-Reply-To: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110415160749.c0648aaf.kamezawa.hiroyu@jp.fujitsu.com> Signed-off-by: KAMEZAWA Hiroyuki --- src/qemu/qemu_conf.c | 1 + src/qemu/qemu_driver.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index bb5421b..89c5b4c 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -302,6 +302,7 @@ int qemudLoadDriverConfig(struct qemud_driver *driver, } else { driver->cgroupControllers = (1 << VIR_CGROUP_CONTROLLER_CPU) | + (1 << VIR_CGROUP_CONTROLLER_CPUACCT) | (1 << VIR_CGROUP_CONTROLLER_DEVICES) | (1 << VIR_CGROUP_CONTROLLER_MEMORY) | (1 << VIR_CGROUP_CONTROLLER_BLKIO); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0a78a70..6db4f8a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5011,6 +5011,75 @@ cleanup: } static int +qemuDomainPcpuStats (virDomainPtr dom, + struct _virDomainPcpuStat *stats, + unsigned int nr_stats) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm = NULL; + virCgroupPtr group = NULL; + int ret = -1; + unsigned long long *array = NULL; + int i; + + + qemuDriverLock(driver); + if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPUACCT)) { + qemuDriverUnlock(driver); + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cgroup CPUACCT controller is not mounted")); + goto cleanup; + } + + 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 (VIR_ALLOC_N(array, nr_stats) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto cleanup; + } + + if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot find cgroup for domain %s"), vm->def->name); + goto cleanup; + } + + ret = virCgroupGetCpuacctUsagePercpu(group, nr_stats, array); + if (ret <= 0) { + ret = -1; + goto cleanup; + } + + for (i = 0; i < ret; i++) + stats[i].cpuTime = array[i]; + +cleanup: + if (group) + virCgroupFree(&group); + VIR_FREE(array); + if (vm) + virDomainObjUnlock(vm); + return ret; +} + + + +static int qemudDomainBlockPeek (virDomainPtr dom, const char *path, unsigned long long offset, size_t size, @@ -6981,7 +7050,7 @@ static virDriver qemuDriver = { qemudDomainBlockStats, /* domainBlockStats */ qemudDomainInterfaceStats, /* domainInterfaceStats */ qemudDomainMemoryStats, /* domainMemoryStats */ - NULL, /* domainPcpuStats */ + qemuDomainPcpuStats, /* domainPcpuStats */ qemudDomainBlockPeek, /* domainBlockPeek */ qemudDomainMemoryPeek, /* domainMemoryPeek */ qemuDomainGetBlockInfo, /* domainGetBlockInfo */ -- 1.7.4.1 From jyang at redhat.com Fri Apr 15 07:18:42 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 15 Apr 2011 15:18:42 +0800 Subject: [libvirt] [RFC] Support changing scheduler setting persistently Message-ID: <1302851930-32654-1-git-send-email-jyang@redhat.com> This patch series introduce a new API virDomainSetSchedulerParametersFlags to change the scheduler setting persistently. The new API accepts two flags, VIR_DOMAIN_SCHED_PARAMS_LIVE and VIR_DOMAIN_SCHED_PARAMS_PERSISTENT, "LIVE" flag affects the running domain config, "PERSISTENT" affects both the running and persistent domain config, both flags require the domain is running. "LIVE" flags is used by default. It's not like "setvcpus", which accepts "--live", "--config", and "--current" flags, as scheduler setting relates with cgroup (QEMU/LXC), upper layer apps probably need to use virDomainGetSchedulerParameter and virDomainSetSchedulerParametersFlags together, such as virsh, virDomainGetSchedulerParameter looks up parameters, so support changing the scheduler setting on inactive domain probably is not good idea. Regards Osier From jyang at redhat.com Fri Apr 15 07:18:43 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 15 Apr 2011 15:18:43 +0800 Subject: [libvirt] [PATCH 1/8] schedinfo: Define new API virDomainSetSchedulerParametersFlags In-Reply-To: <1302851930-32654-1-git-send-email-jyang@redhat.com> References: <1302851930-32654-1-git-send-email-jyang@redhat.com> Message-ID: <1302851930-32654-2-git-send-email-jyang@redhat.com> Flags may include VIR_DOMAIN_SCHED_PARAMS_LIVE and VIR_DOMAIN_SCHED_PARAMS_PERSISTENT, the first one means changing the domain scheduler setting only for running domain config, and the later one means changing both the running and persistent domain config. Both flags require domain is running, VIR_DOMAIN_SCHED_PARAMS_LIVE is used by default. --- include/libvirt/libvirt.h.in | 14 ++++++++++++++ src/libvirt_public.syms | 5 +++++ 2 files changed, 19 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 04b7fbf..c87608c 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -280,6 +280,13 @@ struct _virSchedParameter { typedef virSchedParameter *virSchedParameterPtr; +/* Domain scheduler parameters setting flags. */ +typedef enum { + /* Both these two flags works on running domain. */ + VIR_DOMAIN_SCHED_PARAMS_LIVE = (1 << 0), /* Affects active domain config */ + VIR_DOMAIN_SCHED_PARAMS_PERSISTENT = (1 << 1), /* Affects both active and persistent domain config. */ +} virDomainSchedParametersFlags; + /* * Fetch scheduler parameters, caller allocates 'params' field of size 'nparams' */ @@ -293,6 +300,13 @@ int virDomainGetSchedulerParameters (virDomainPtr domain, int virDomainSetSchedulerParameters (virDomainPtr domain, virSchedParameterPtr params, int nparams); +/* + * Change scheduler parameters according to flags. + */ +int virDomainSetSchedulerParametersFlags (virDomainPtr domain, + virSchedParameterPtr params, + int nparams, + unsigned int flags); /** * virDomainBlockStats: diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b4aed41..03d08f1 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -436,4 +436,9 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8; +LIBVIRT_0.9.1 { + global: + virDomainSetSchedulerParametersFlags; +} LIBVIRT_0.9.0; + # .... define new API here using predicted next version number .... -- 1.7.4 From jyang at redhat.com Fri Apr 15 07:18:44 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 15 Apr 2011 15:18:44 +0800 Subject: [libvirt] [PATCH 2/8] schedinfo: Define the internal API In-Reply-To: <1302851930-32654-1-git-send-email-jyang@redhat.com> References: <1302851930-32654-1-git-send-email-jyang@redhat.com> Message-ID: <1302851930-32654-3-git-send-email-jyang@redhat.com> --- src/driver.h | 8 ++++++++ src/esx/esx_driver.c | 1 + src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 6 ++++-- src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xenapi/xenapi_driver.c | 1 + 14 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/driver.h b/src/driver.h index e5f91ca..55ffab2 100644 --- a/src/driver.h +++ b/src/driver.h @@ -276,6 +276,13 @@ typedef int int nparams); typedef int + (*virDrvDomainSetSchedulerParametersFlags) + (virDomainPtr domain, + virSchedParameterPtr params, + int nparams, + unsigned int flags); + +typedef int (*virDrvDomainBlockStats) (virDomainPtr domain, const char *path, @@ -593,6 +600,7 @@ struct _virDriver { virDrvDomainGetSchedulerType domainGetSchedulerType; virDrvDomainGetSchedulerParameters domainGetSchedulerParameters; virDrvDomainSetSchedulerParameters domainSetSchedulerParameters; + virDrvDomainSetSchedulerParametersFlags domainSetSchedulerParametersFlags; virDrvDomainMigratePrepare domainMigratePrepare; virDrvDomainMigratePerform domainMigratePerform; virDrvDomainMigrateFinish domainMigrateFinish; diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index deda372..5c7bd80 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4629,6 +4629,7 @@ static virDriver esxDriver = { esxDomainGetSchedulerType, /* domainGetSchedulerType */ esxDomainGetSchedulerParameters, /* domainGetSchedulerParameters */ esxDomainSetSchedulerParameters, /* domainSetSchedulerParameters */ + NULL, /* domainSetSchedulerParametersFlags */ esxDomainMigratePrepare, /* domainMigratePrepare */ esxDomainMigratePerform, /* domainMigratePerform */ esxDomainMigrateFinish, /* domainMigrateFinish */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 3040914..ef3ea46 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2617,6 +2617,7 @@ static virDriver libxlDriver = { libxlDomainGetSchedulerType,/* domainGetSchedulerType */ libxlDomainGetSchedulerParameters,/* domainGetSchedulerParameters */ libxlDomainSetSchedulerParameters,/* domainSetSchedulerParameters */ + NULL /* domainSetSchedulerParametersFlags */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e905302..72c0a0a 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2860,6 +2860,7 @@ static virDriver lxcDriver = { lxcGetSchedulerType, /* domainGetSchedulerType */ lxcGetSchedulerParameters, /* domainGetSchedulerParameters */ lxcSetSchedulerParameters, /* domainSetSchedulerParameters */ + NULL, /* domainSetSchedulerParametersFlags */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 4af28e9..d3d3365 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1621,6 +1621,7 @@ static virDriver openvzDriver = { NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ + NULL, /* domainSetSchedulerParametersFlags */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index ddbc103..dd90fca 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -4026,6 +4026,7 @@ static virDriver phypDriver = { NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ + NULL, /* domainSetSchedulerParametersFlags */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 04a5f65..f06dcea 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6924,6 +6924,7 @@ static virDriver qemuDriver = { qemuGetSchedulerType, /* domainGetSchedulerType */ qemuGetSchedulerParameters, /* domainGetSchedulerParameters */ qemuSetSchedulerParameters, /* domainSetSchedulerParameters */ + NULL, /* domainSetSchedulerParametersFlags */ NULL, /* domainMigratePrepare (v1) */ qemudDomainMigratePerform, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 9310ddf..7fe57d0 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1223,7 +1223,7 @@ initialize_gnutls(char *pkipath, int flags) goto out_of_memory; /* Use default location as long as one of CA certificate, - * client key, and client certificate can not be found in + * client key, and client certificate cannot be found in * $HOME/.pki/libvirt, we don't want to make user confused * with one file is here, the other is there. */ @@ -10672,8 +10672,9 @@ remoteIOEventLoop(virConnectPtr conn, */ VIR_DEBUG("Waking up sleep %d %p %p", tmp->proc_nr, tmp, priv->waitDispatch); virCondSignal(&tmp->cond); + } else { + prev = tmp; } - prev = tmp; tmp = tmp->next; } @@ -11254,6 +11255,7 @@ static virDriver remote_driver = { remoteDomainGetSchedulerType, /* domainGetSchedulerType */ remoteDomainGetSchedulerParameters, /* domainGetSchedulerParameters */ remoteDomainSetSchedulerParameters, /* domainSetSchedulerParameters */ + NULL, /* domainSetSchedulerParametersFlags */ remoteDomainMigratePrepare, /* domainMigratePrepare */ remoteDomainMigratePerform, /* domainMigratePerform */ remoteDomainMigrateFinish, /* domainMigrateFinish */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 17f5ad9..42ec89c 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5401,6 +5401,7 @@ static virDriver testDriver = { testDomainGetSchedulerType, /* domainGetSchedulerType */ testDomainGetSchedulerParams, /* domainGetSchedulerParameters */ testDomainSetSchedulerParams, /* domainSetSchedulerParameters */ + NULL, /* domainSetSchedulerParametersFlags */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 33849a0..852e066 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2207,6 +2207,7 @@ static virDriver umlDriver = { NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ + NULL, /* domainSetSchedulerParametersFlags */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 0fbfba5..0d9d17e 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8591,6 +8591,7 @@ virDriver NAME(Driver) = { NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ + NULL, /* domainSetSchedulerParametersFlags */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index b5e416b..1db1b0d 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -961,6 +961,7 @@ static virDriver vmwareDriver = { NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ + NULL, /* domainSetSchedulerParametersFlags */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 9f47722..48a777f 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2095,6 +2095,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedDomainGetSchedulerType, /* domainGetSchedulerType */ xenUnifiedDomainGetSchedulerParameters, /* domainGetSchedulerParameters */ xenUnifiedDomainSetSchedulerParameters, /* domainSetSchedulerParameters */ + NULL, /* domainSetSchedulerParametersFlags */ xenUnifiedDomainMigratePrepare, /* domainMigratePrepare */ xenUnifiedDomainMigratePerform, /* domainMigratePerform */ xenUnifiedDomainMigrateFinish, /* domainMigrateFinish */ diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 60b23c7..db21c1a 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1843,6 +1843,7 @@ static virDriver xenapiDriver = { xenapiDomainGetSchedulerType, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ + NULL, /* domainSetSchedulerParametersFlags */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ -- 1.7.4 From jyang at redhat.com Fri Apr 15 07:18:45 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 15 Apr 2011 15:18:45 +0800 Subject: [libvirt] [PATCH 3/8] schedinfo: Implemente the public API In-Reply-To: <1302851930-32654-1-git-send-email-jyang@redhat.com> References: <1302851930-32654-1-git-send-email-jyang@redhat.com> Message-ID: <1302851930-32654-4-git-send-email-jyang@redhat.com> --- src/libvirt.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 60 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 0da9885..fae83fe 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -4401,6 +4401,66 @@ error: return -1; } +/** + * virDomainSetSchedulerParameters: + * @domain: pointer to domain object + * @params: pointer to scheduler parameter objects + * @nparams: number of scheduler parameter + * (this value should be same or less than the returned value + * nparams of virDomainGetSchedulerType) + * @flags: an OR'ed set of virDomainMemoryModFlags + * + * Change the scheduler parameters according to the specified flags + * + * @flags may include VIR_DOMAIN_SCHED_PARAMS_LIVE or + * VIR_DOMAIN_SCHED_PARAMS_CONFIG, both flags may be set, and both flags + * requires the domain is running. + * If VIR_DOMAIN_SCHED_PARAMS_LIVE is set, the change affects a running + * domain and will fail if the domain is not active. + * If VIR_DOMAIN_SCHED_PARAMS_CONFIG is set, the change affects both the + * running and persistent domain config, and will fail for transient + * domains or the domain is not active. + + * Returns -1 in case of error, 0 in case of success. + */ +int +virDomainSetSchedulerParametersFlags(virDomainPtr domain, + virSchedParameterPtr params, + int nparams, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "params=%p, nparams=%d", params, nparams); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + conn = domain->conn; + + if (conn->driver->domainSetSchedulerParametersFlags) { + int ret; + ret = conn->driver->domainSetSchedulerParametersFlags (domain, params, nparams, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} + /** * virDomainBlockStats: -- 1.7.4 From jyang at redhat.com Fri Apr 15 07:18:46 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 15 Apr 2011 15:18:46 +0800 Subject: [libvirt] [PATCH 4/8] schedinfo: Expose the new public API for Python binding In-Reply-To: <1302851930-32654-1-git-send-email-jyang@redhat.com> References: <1302851930-32654-1-git-send-email-jyang@redhat.com> Message-ID: <1302851930-32654-5-git-send-email-jyang@redhat.com> --- python/generator.py | 1 + python/libvirt-override-api.xml | 7 +++ python/libvirt-override.c | 95 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 0 deletions(-) diff --git a/python/generator.py b/python/generator.py index 4fa4f65..a44a4d0 100755 --- a/python/generator.py +++ b/python/generator.py @@ -311,6 +311,7 @@ skip_impl = ( 'virDomainGetSchedulerType', 'virDomainGetSchedulerParameters', 'virDomainSetSchedulerParameters', + 'virDomainSetSchedulerParametersFlags', 'virDomainSetBlkioParameters', 'virDomainGetBlkioParameters', 'virDomainSetMemoryParameters', diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml index 54deeb5..490217b 100644 --- a/python/libvirt-override-api.xml +++ b/python/libvirt-override-api.xml @@ -162,6 +162,13 @@ + + Change the scheduler parameters according to flags + + + + + Change the blkio tunables diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 4a9b432..35e823c 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -371,7 +371,101 @@ libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_INT_SUCCESS; } +static PyObject * +libvirt_virDomainSetSchedulerParametersFlags(PyObject *self ATTRIBUTE_UNUSED, + PyObject *args) { + virDomainPtr domain; + PyObject *pyobj_domain, *info; + char *c_retval; + int i_retval; + int nparams, i; + virSchedParameterPtr params; + unsigned int flags; + + if (!PyArg_ParseTuple(args, (char *)"OO:virDomainSetScedulerParameters", + &pyobj_domain, &info, &flags)) + return(NULL); + domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + + LIBVIRT_BEGIN_ALLOW_THREADS; + c_retval = virDomainGetSchedulerType(domain, &nparams); + LIBVIRT_END_ALLOW_THREADS; + + if (c_retval == NULL) + return VIR_PY_INT_FAIL; + free(c_retval); + + if ((params = malloc(sizeof(*params)*nparams)) == NULL) + return VIR_PY_INT_FAIL; + + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainGetSchedulerParameters(domain, params, &nparams); + LIBVIRT_END_ALLOW_THREADS; + + if (i_retval < 0) { + free(params); + return VIR_PY_INT_FAIL; + } + + /* convert to a Python tuple of long objects */ + for (i = 0 ; i < nparams ; i++) { + PyObject *key, *val; + key = libvirt_constcharPtrWrap(params[i].field); + val = PyDict_GetItem(info, key); + Py_DECREF(key); + + if (val == NULL) + continue; + + switch (params[i].type) { + case VIR_DOMAIN_SCHED_FIELD_INT: + params[i].value.i = (int)PyInt_AS_LONG(val); + break; + + case VIR_DOMAIN_SCHED_FIELD_UINT: + params[i].value.ui = (unsigned int)PyInt_AS_LONG(val); + break; + case VIR_DOMAIN_SCHED_FIELD_LLONG: + params[i].value.l = (long long)PyLong_AsLongLong(val); + break; + + case VIR_DOMAIN_SCHED_FIELD_ULLONG: + params[i].value.ul = (unsigned long long)PyLong_AsLongLong(val); + break; + + case VIR_DOMAIN_SCHED_FIELD_DOUBLE: + params[i].value.d = (double)PyFloat_AsDouble(val); + break; + + case VIR_DOMAIN_SCHED_FIELD_BOOLEAN: + { + /* Hack - Python's definition of Py_True breaks strict + * aliasing rules, so can't directly compare :-( + */ + PyObject *hacktrue = PyBool_FromLong(1); + params[i].value.b = hacktrue == val ? 1 : 0; + Py_DECREF(hacktrue); + } + break; + + default: + free(params); + return VIR_PY_INT_FAIL; + } + } + + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainSetSchedulerParametersFlags(domain, params, nparams, flags); + LIBVIRT_END_ALLOW_THREADS; + if (i_retval < 0) { + free(params); + return VIR_PY_INT_FAIL; + } + + free(params); + return VIR_PY_INT_SUCCESS; +} /* FIXME: This is a place holder for the implementation. */ @@ -3549,6 +3643,7 @@ static PyMethodDef libvirtMethods[] = { {(char *) "virDomainGetSchedulerType", libvirt_virDomainGetSchedulerType, METH_VARARGS, NULL}, {(char *) "virDomainGetSchedulerParameters", libvirt_virDomainGetSchedulerParameters, METH_VARARGS, NULL}, {(char *) "virDomainSetSchedulerParameters", libvirt_virDomainSetSchedulerParameters, METH_VARARGS, NULL}, + {(char *) "virDomainSetSchedulerParametersFlags", libvirt_virDomainSetSchedulerParametersFlags, METH_VARARGS, NULL}, {(char *) "virDomainSetBlkioParameters", libvirt_virDomainSetBlkioParameters, METH_VARARGS, NULL}, {(char *) "virDomainGetBlkioParameters", libvirt_virDomainGetBlkioParameters, METH_VARARGS, NULL}, {(char *) "virDomainSetMemoryParameters", libvirt_virDomainSetMemoryParameters, METH_VARARGS, NULL}, -- 1.7.4 From jyang at redhat.com Fri Apr 15 07:18:47 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 15 Apr 2011 15:18:47 +0800 Subject: [libvirt] [PATCH 5/8] schedinfo: Implemente the remote protocol In-Reply-To: <1302851930-32654-1-git-send-email-jyang@redhat.com> References: <1302851930-32654-1-git-send-email-jyang@redhat.com> Message-ID: <1302851930-32654-6-git-send-email-jyang@redhat.com> --- daemon/remote.c | 71 ++++++++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++ daemon/remote_dispatch_table.h | 5 ++ src/remote/remote_driver.c | 77 +++++++++++++++++++++++++++++++++-- src/remote/remote_protocol.c | 15 +++++++ src/remote/remote_protocol.h | 13 ++++++ src/remote/remote_protocol.x | 9 ++++- 8 files changed, 194 insertions(+), 5 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index dd85ef1..3ad116b 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -921,6 +921,77 @@ remoteDispatchDomainSetSchedulerParameters (struct qemud_server *server ATTRIBUT } static int +remoteDispatchDomainSetSchedulerParametersFlags (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_set_scheduler_parameters_flags_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virDomainPtr dom; + int i, r, nparams; + virSchedParameterPtr params; + unsigned int flags; + + nparams = args->params.params_len; + + if (nparams > REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX) { + remoteDispatchFormatError (rerr, "%s", _("nparams too large")); + return -1; + } + if (VIR_ALLOC_N(params, nparams) < 0) { + remoteDispatchOOMError(rerr); + return -1; + } + + /* Deserialise parameters. */ + for (i = 0; i < nparams; ++i) { + if (virStrcpyStatic(params[i].field, args->params.params_val[i].field) == NULL) { + remoteDispatchFormatError(rerr, _("Field %s too big for destination"), + args->params.params_val[i].field); + return -1; + } + params[i].type = args->params.params_val[i].value.type; + switch (params[i].type) { + case VIR_DOMAIN_SCHED_FIELD_INT: + params[i].value.i = args->params.params_val[i].value.remote_sched_param_value_u.i; break; + case VIR_DOMAIN_SCHED_FIELD_UINT: + params[i].value.ui = args->params.params_val[i].value.remote_sched_param_value_u.ui; break; + case VIR_DOMAIN_SCHED_FIELD_LLONG: + params[i].value.l = args->params.params_val[i].value.remote_sched_param_value_u.l; break; + case VIR_DOMAIN_SCHED_FIELD_ULLONG: + params[i].value.ul = args->params.params_val[i].value.remote_sched_param_value_u.ul; break; + case VIR_DOMAIN_SCHED_FIELD_DOUBLE: + params[i].value.d = args->params.params_val[i].value.remote_sched_param_value_u.d; break; + case VIR_DOMAIN_SCHED_FIELD_BOOLEAN: + params[i].value.b = args->params.params_val[i].value.remote_sched_param_value_u.b; break; + } + } + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + VIR_FREE(params); + remoteDispatchConnError(rerr, conn); + return -1; + } + + flags = args->flags; + + r = virDomainSetSchedulerParametersFlags (dom, params, nparams, flags); + VIR_FREE(params); + if (r == -1) { + remoteDispatchConnError(rerr, conn); + virDomainFree(dom); + return -1; + } + virDomainFree(dom); + + return 0; +} + + +static int remoteDispatchDomainBlockStats (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index f9537d7..5cb2572 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -178,3 +178,4 @@ remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; remote_storage_vol_upload_args val_remote_storage_vol_upload_args; remote_storage_vol_download_args val_remote_storage_vol_download_args; + remote_domain_set_scheduler_parameters_flags_args val_remote_domain_set_scheduler_parameters_flags_args; diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 18bf41d..8b249ad 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -602,6 +602,14 @@ static int remoteDispatchDomainSetSchedulerParameters( remote_error *err, remote_domain_set_scheduler_parameters_args *args, void *ret); +static int remoteDispatchDomainSetSchedulerParametersFlags( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_set_scheduler_parameters_flags_args *args, + void *ret); static int remoteDispatchDomainSetVcpus( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index b39f7c2..96485eb 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1052,3 +1052,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* DomainSetSchedulerParametersFlags => 210 */ + .fn = (dispatch_fn) remoteDispatchDomainSetSchedulerParametersFlags, + .args_filter = (xdrproc_t) xdr_remote_domain_set_scheduler_parameters_flags_args, + .ret_filter = (xdrproc_t) xdr_void, +}, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 7fe57d0..c89cef5 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1223,7 +1223,7 @@ initialize_gnutls(char *pkipath, int flags) goto out_of_memory; /* Use default location as long as one of CA certificate, - * client key, and client certificate cannot be found in + * client key, and client certificate can not be found in * $HOME/.pki/libvirt, we don't want to make user confused * with one file is here, the other is there. */ @@ -4058,6 +4058,76 @@ done: } static int +remoteDomainSetSchedulerParametersFlags (virDomainPtr domain, + virSchedParameterPtr params, + int nparams, + unsigned int flags) +{ + int rv = -1; + remote_domain_set_scheduler_parameters_flags_args args; + int i, do_error; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + make_nonnull_domain (&args.dom, domain); + + /* Serialise the scheduler parameters. */ + args.params.params_len = nparams; + if (VIR_ALLOC_N(args.params.params_val, nparams) < 0) { + virReportOOMError(); + goto done; + } + + do_error = 0; + for (i = 0; i < nparams; ++i) { + /* call() will free this: */ + args.params.params_val[i].field = strdup (params[i].field); + if (args.params.params_val[i].field == NULL) { + virReportOOMError(); + do_error = 1; + } + args.params.params_val[i].value.type = params[i].type; + switch (params[i].type) { + case VIR_DOMAIN_SCHED_FIELD_INT: + args.params.params_val[i].value.remote_sched_param_value_u.i = params[i].value.i; break; + case VIR_DOMAIN_SCHED_FIELD_UINT: + args.params.params_val[i].value.remote_sched_param_value_u.ui = params[i].value.ui; break; + case VIR_DOMAIN_SCHED_FIELD_LLONG: + args.params.params_val[i].value.remote_sched_param_value_u.l = params[i].value.l; break; + case VIR_DOMAIN_SCHED_FIELD_ULLONG: + args.params.params_val[i].value.remote_sched_param_value_u.ul = params[i].value.ul; break; + case VIR_DOMAIN_SCHED_FIELD_DOUBLE: + args.params.params_val[i].value.remote_sched_param_value_u.d = params[i].value.d; break; + case VIR_DOMAIN_SCHED_FIELD_BOOLEAN: + args.params.params_val[i].value.remote_sched_param_value_u.b = params[i].value.b; break; + default: + remoteError(VIR_ERR_RPC, "%s", _("unknown parameter type")); + do_error = 1; + } + } + + args.flags = flags; + + if (do_error) { + xdr_free ((xdrproc_t) xdr_remote_domain_set_scheduler_parameters_flags_args, (char *) &args); + goto done; + } + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS_FLAGS, + (xdrproc_t) xdr_remote_domain_set_scheduler_parameters_flags_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + + +static int remoteDomainBlockStats (virDomainPtr domain, const char *path, struct _virDomainBlockStats *stats) { @@ -10672,9 +10742,8 @@ remoteIOEventLoop(virConnectPtr conn, */ VIR_DEBUG("Waking up sleep %d %p %p", tmp->proc_nr, tmp, priv->waitDispatch); virCondSignal(&tmp->cond); - } else { - prev = tmp; } + prev = tmp; tmp = tmp->next; } @@ -11255,7 +11324,7 @@ static virDriver remote_driver = { remoteDomainGetSchedulerType, /* domainGetSchedulerType */ remoteDomainGetSchedulerParameters, /* domainGetSchedulerParameters */ remoteDomainSetSchedulerParameters, /* domainSetSchedulerParameters */ - NULL, /* domainSetSchedulerParametersFlags */ + remoteDomainSetSchedulerParametersFlags, /* domainSetSchedulerParametersFlags */ remoteDomainMigratePrepare, /* domainMigratePrepare */ remoteDomainMigratePerform, /* domainMigratePerform */ remoteDomainMigrateFinish, /* domainMigrateFinish */ diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 5604371..5036cac 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -693,6 +693,21 @@ xdr_remote_domain_set_scheduler_parameters_args (XDR *xdrs, remote_domain_set_sc } bool_t +xdr_remote_domain_set_scheduler_parameters_flags_args (XDR *xdrs, remote_domain_set_scheduler_parameters_flags_args *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->params.params_val; + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->params.params_len, REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX, + sizeof (remote_sched_param), (xdrproc_t) xdr_remote_sched_param)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_domain_set_blkio_parameters_args (XDR *xdrs, remote_domain_set_blkio_parameters_args *objp) { char **objp_cpp0 = (char **) (void *) &objp->params.params_val; diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index d9bf151..ec576a0 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -357,6 +357,16 @@ struct remote_domain_set_scheduler_parameters_args { }; typedef struct remote_domain_set_scheduler_parameters_args remote_domain_set_scheduler_parameters_args; +struct remote_domain_set_scheduler_parameters_flags_args { + remote_nonnull_domain dom; + struct { + u_int params_len; + remote_sched_param *params_val; + } params; + u_int flags; +}; +typedef struct remote_domain_set_scheduler_parameters_flags_args remote_domain_set_scheduler_parameters_flags_args; + struct remote_domain_set_blkio_parameters_args { remote_nonnull_domain dom; struct { @@ -2413,6 +2423,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS_FLAGS = 210, }; typedef enum remote_procedure remote_procedure; @@ -2494,6 +2505,7 @@ extern bool_t xdr_remote_domain_get_scheduler_type_ret (XDR *, remote_domain_ge extern bool_t xdr_remote_domain_get_scheduler_parameters_args (XDR *, remote_domain_get_scheduler_parameters_args*); extern bool_t xdr_remote_domain_get_scheduler_parameters_ret (XDR *, remote_domain_get_scheduler_parameters_ret*); extern bool_t xdr_remote_domain_set_scheduler_parameters_args (XDR *, remote_domain_set_scheduler_parameters_args*); +extern bool_t xdr_remote_domain_set_scheduler_parameters_flags_args (XDR *, remote_domain_set_scheduler_parameters_flags_args*); extern bool_t xdr_remote_domain_set_blkio_parameters_args (XDR *, remote_domain_set_blkio_parameters_args*); extern bool_t xdr_remote_domain_get_blkio_parameters_args (XDR *, remote_domain_get_blkio_parameters_args*); extern bool_t xdr_remote_domain_get_blkio_parameters_ret (XDR *, remote_domain_get_blkio_parameters_ret*); @@ -2851,6 +2863,7 @@ extern bool_t xdr_remote_domain_get_scheduler_type_ret (); extern bool_t xdr_remote_domain_get_scheduler_parameters_args (); extern bool_t xdr_remote_domain_get_scheduler_parameters_ret (); extern bool_t xdr_remote_domain_set_scheduler_parameters_args (); +extern bool_t xdr_remote_domain_set_scheduler_parameters_flags_args (); extern bool_t xdr_remote_domain_set_blkio_parameters_args (); extern bool_t xdr_remote_domain_get_blkio_parameters_args (); extern bool_t xdr_remote_domain_get_blkio_parameters_ret (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 675eccd..a320fe0 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -476,6 +476,12 @@ struct remote_domain_set_scheduler_parameters_args { remote_sched_param params; }; +struct remote_domain_set_scheduler_parameters_flags_args { + remote_nonnull_domain dom; + remote_sched_param params; + unsigned int flags; +}; + struct remote_domain_set_blkio_parameters_args { remote_nonnull_domain dom; remote_blkio_param params; @@ -2176,7 +2182,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS_FLAGS = 210 /* * Notice how the entries are grouped in sets of 10 ? -- 1.7.4 From jyang at redhat.com Fri Apr 15 07:18:48 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 15 Apr 2011 15:18:48 +0800 Subject: [libvirt] [PATCH 6/8] schedinfo: Support new API for qemu driver In-Reply-To: <1302851930-32654-1-git-send-email-jyang@redhat.com> References: <1302851930-32654-1-git-send-email-jyang@redhat.com> Message-ID: <1302851930-32654-7-git-send-email-jyang@redhat.com> --- src/qemu/qemu_driver.c | 64 +++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f06dcea..1c71962 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4651,37 +4651,59 @@ cleanup: return ret; } -static int qemuSetSchedulerParameters(virDomainPtr dom, - virSchedParameterPtr params, - int nparams) +static int qemuSetSchedulerParametersFlags(virDomainPtr dom, + virSchedParameterPtr params, + int nparams, + unsigned int flags) { struct qemud_driver *driver = dom->conn->privateData; int i; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; + virDomainDefPtr persistentDef = NULL; int ret = -1; - qemuDriverLock(driver); + virCheckFlags(VIR_DOMAIN_SCHED_PARAMS_LIVE | + VIR_DOMAIN_SCHED_PARAMS_PERSISTENT, -1); + if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cgroup CPU controller is not mounted")); goto cleanup; } + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); if (vm == NULL) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - _("No such domain %s"), dom->uuid); + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + qemuReportError(VIR_ERR_NO_DOMAIN, + _("No domain with uuid: %s"), uuidstr); goto cleanup; } + /* Could find the cgroup for domain implies the domain is running. */ if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) { qemuReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot find cgroup for domain %s"), vm->def->name); + _("cannot find cgroup for domain %s"), vm->def->name); goto cleanup; } + if (qemuDomainObjBeginJob(vm) < 0) + goto cleanup; + + if (flags & VIR_DOMAIN_SCHED_PARAMS_PERSISTENT) { + if (!vm->persistent) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot change persistent config of a transient domain")); + goto endjob; + } + if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm))) + goto endjob; + } + for (i = 0; i < nparams; i++) { virSchedParameterPtr param = ¶ms[i]; @@ -4690,25 +4712,35 @@ static int qemuSetSchedulerParameters(virDomainPtr dom, if (param->type != VIR_DOMAIN_SCHED_FIELD_ULLONG) { qemuReportError(VIR_ERR_INVALID_ARG, "%s", _("invalid type for cpu_shares tunable, expected a 'ullong'")); - goto cleanup; + goto endjob; } rc = virCgroupSetCpuShares(group, params[i].value.ul); if (rc != 0) { virReportSystemError(-rc, "%s", - _("unable to set cpu shares tunable")); - goto cleanup; + _("unable to set cpu shares tunable")); + goto endjob; } vm->def->cputune.shares = params[i].value.ul; + + if (flags & VIR_DOMAIN_SCHED_PARAMS_PERSISTENT) { + persistentDef->cputune.shares = params[i].value.ul; + ret = virDomainSaveConfig(driver->configDir, persistentDef); + goto endjob; + } } else { qemuReportError(VIR_ERR_INVALID_ARG, _("Invalid parameter `%s'"), param->field); - goto cleanup; + goto endjob; } } ret = 0; +endjob: + if (qemuDomainObjEndJob(vm) == 0) + vm = NULL; + cleanup: virCgroupFree(&group); if (vm) @@ -4717,6 +4749,14 @@ cleanup: return ret; } +static int qemuSetSchedulerParameters(virDomainPtr dom, + virSchedParameterPtr params, + int nparams) +{ + return qemuSetSchedulerParametersFlags(dom, params, nparams, + VIR_DOMAIN_SCHED_PARAMS_LIVE); +} + static int qemuGetSchedulerParameters(virDomainPtr dom, virSchedParameterPtr params, int *nparams) @@ -6924,7 +6964,7 @@ static virDriver qemuDriver = { qemuGetSchedulerType, /* domainGetSchedulerType */ qemuGetSchedulerParameters, /* domainGetSchedulerParameters */ qemuSetSchedulerParameters, /* domainSetSchedulerParameters */ - NULL, /* domainSetSchedulerParametersFlags */ + qemuSetSchedulerParametersFlags, /* domainSetSchedulerParametersFlags */ NULL, /* domainMigratePrepare (v1) */ qemudDomainMigratePerform, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ -- 1.7.4 From jyang at redhat.com Fri Apr 15 07:18:49 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 15 Apr 2011 15:18:49 +0800 Subject: [libvirt] [PATCH 7/8] schedinfo: Support new API for lxc driver In-Reply-To: <1302851930-32654-1-git-send-email-jyang@redhat.com> References: <1302851930-32654-1-git-send-email-jyang@redhat.com> Message-ID: <1302851930-32654-8-git-send-email-jyang@redhat.com> --- src/lxc/lxc_driver.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 72c0a0a..5db1035 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2244,21 +2244,28 @@ static char *lxcGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED, return schedulerType; } -static int lxcSetSchedulerParameters(virDomainPtr domain, - virSchedParameterPtr params, - int nparams) +static int lxcSetSchedulerParametersFlags(virDomainPtr domain, + virSchedParameterPtr params, + int nparams, + unsigned int flags) { lxc_driver_t *driver = domain->conn->privateData; int i; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; + virDomainDefPtr persistentDef = NULL; int ret = -1; + bool isActive; + + virCheckFlags(VIR_DOMAIN_SCHED_PARAMS_LIVE | + VIR_DOMAIN_SCHED_PARAMS_PERSISTENT, -1); if (driver->cgroup == NULL) return -1; lxcDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, domain->uuid); + lxcDriverUnlock(driver); if (vm == NULL) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -2268,9 +2275,20 @@ static int lxcSetSchedulerParameters(virDomainPtr domain, goto cleanup; } + /* Could find cgroup for domain implies the domain is running. */ if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) goto cleanup; + if (flags & VIR_DOMAIN_SCHED_PARAMS_PERSISTENT) { + if (!vm->persistent) { + lxcError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot change persistent config of a transient domain")); + goto cleanup; + } + if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm))) + goto cleanup; + } + for (i = 0; i < nparams; i++) { virSchedParameterPtr param = ¶ms[i]; @@ -2294,17 +2312,30 @@ static int lxcSetSchedulerParameters(virDomainPtr domain, } vm->def->cputune.shares = params[i].value.ul; + + if (flags & VIR_DOMAIN_SCHED_PARAMS_PERSISTENT) { + persistentDef->cputune.shares = params[i].value.ul; + ret = virDomainSaveConfig(driver->configDir, persistentDef); + goto cleanup; + } } ret = 0; cleanup: - lxcDriverUnlock(driver); virCgroupFree(&group); if (vm) virDomainObjUnlock(vm); return ret; } +static int lxcSetSchedulerParameters(virDomainPtr domain, + virSchedParameterPtr params, + int nparams) +{ + return lxcSetSchedulerParametersFlags(domain, params, nparams, + VIR_DOMAIN_SCHED_PARAMS_LIVE); +} + static int lxcGetSchedulerParameters(virDomainPtr domain, virSchedParameterPtr params, int *nparams) @@ -2860,7 +2891,7 @@ static virDriver lxcDriver = { lxcGetSchedulerType, /* domainGetSchedulerType */ lxcGetSchedulerParameters, /* domainGetSchedulerParameters */ lxcSetSchedulerParameters, /* domainSetSchedulerParameters */ - NULL, /* domainSetSchedulerParametersFlags */ + lxcSetSchedulerParametersFlags, /* domainSetSchedulerParametersFlags */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ -- 1.7.4 From jyang at redhat.com Fri Apr 15 07:18:50 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 15 Apr 2011 15:18:50 +0800 Subject: [libvirt] [PATCH 8/8] schedinfo: Modify schedinfo command to accepts flags In-Reply-To: <1302851930-32654-1-git-send-email-jyang@redhat.com> References: <1302851930-32654-1-git-send-email-jyang@redhat.com> Message-ID: <1302851930-32654-9-git-send-email-jyang@redhat.com> --- tools/virsh.c | 26 +++++++++++++++++++++++--- tools/virsh.pod | 8 +++++++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 2e35021..e6e80b5 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1598,6 +1598,8 @@ static const vshCmdOptDef opts_schedinfo[] = { {"set", VSH_OT_STRING, VSH_OFLAG_NONE, N_("parameter=value")}, {"weight", VSH_OT_INT, VSH_OFLAG_NONE, N_("weight for XEN_CREDIT")}, {"cap", VSH_OT_INT, VSH_OFLAG_NONE, N_("cap for XEN_CREDIT")}, + {"live", VSH_OT_BOOL, 0, N_("affect running domain")}, + {"persistent", VSH_OT_BOOL, 0, N_("affect both running domain and next boot")}, {NULL, 0, 0, NULL} }; @@ -1705,6 +1707,18 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) int update = 0; int i, ret; int ret_val = FALSE; + int live = vshCommandOptBool(cmd, "live"); + int persistent = vshCommandOptBool(cmd, "persistent"); + int flags = 0; + + if (live) + flags |= VIR_DOMAIN_SCHED_PARAMS_LIVE; + if (persistent) + flags |= VIR_DOMAIN_SCHED_PARAMS_PERSISTENT; + + /* neither option is specified */ + if (!live && !persistent) + flags = -1; if (!vshConnectionUsability(ctl, ctl->conn)) return FALSE; @@ -1714,9 +1728,10 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) /* Print SchedulerType */ schedulertype = virDomainGetSchedulerType(dom, &nparams); - if (schedulertype!= NULL){ + + if (schedulertype != NULL){ vshPrint(ctl, "%-15s: %s\n", _("Scheduler"), - schedulertype); + schedulertype); VIR_FREE(schedulertype); } else { vshPrint(ctl, "%-15s: %s\n", _("Scheduler"), _("Unknown")); @@ -1743,7 +1758,12 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) /* Update parameters & refresh data */ if (update) { - ret = virDomainSetSchedulerParameters(dom, params, nparams); + if (flags == -1) + ret = virDomainSetSchedulerParameters(dom, params, nparams); + else { + ret = virDomainSetSchedulerParametersFlags(dom, params, nparams, flags); + } + if (ret == -1) goto cleanup; diff --git a/tools/virsh.pod b/tools/virsh.pod index 2a708f6..8c1005b 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -567,7 +567,8 @@ severed upon restore, as TCP timeouts may have expired. =item B optional I<--set> B I -=item B optional I<--weight> B optional I<--cap> B I +=item B optional I<--weight> B optional I<--cap> B +I I<--live> I<--persistent> Allows you to show (and set) the domain scheduler parameters. The parameters available for each hypervisor are: @@ -577,6 +578,11 @@ Xen (credit scheduler): weight, cap ESX (allocation scheduler): reservation, limit, shares +Both I<--live> and I<--persistent> may be set, and both of them requires the domain +is running, I<--live> affects the running domain and fails if the domain is not +active. I<--persistent> affects both the active and persistent domain config, and +fails if the domain is transient or not active. I<--live> is the default flag. + B: The cpu_shares parameter has a valid value range of 0-262144; Negative values are wrapped to positive, and larger values are capped at the maximum. Therefore, -1 is a useful shorthand for 262144. -- 1.7.4 From matthias.bolte at googlemail.com Fri Apr 15 07:43:15 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 15 Apr 2011 09:43:15 +0200 Subject: [libvirt] [RFC][PATCHv1 2/5] libvirt - new API for getting percpu statistics of VM In-Reply-To: <20110415160452.63bd9216.kamezawa.hiroyu@jp.fujitsu.com> References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> <20110415160452.63bd9216.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: 2011/4/15 KAMEZAWA Hiroyuki : > Per (host) cpu activity of VMs are very insterested numbers > when running VMs on large SMPs. virt-top -1 mode tries to > provide the information. (But it's not implemented.) > > This patch adds a libvirt interface to get per cpu statistics > of each nodes. This patch just adds an interface and driver > entry points. So, > ?- doesn't include patches for python. > ?- doesn't include any driver. > > Following patches will add some drivers and codes for python. > > Signed-off-by: KAMEZAWA Hiroyuki > --- > ?include/libvirt/libvirt.h.in | ? 13 ++++++++++ > ?src/driver.h ? ? ? ? ? ? ? ? | ? ?6 ++++ > ?src/esx/esx_driver.c ? ? ? ? | ? ?1 + > ?src/libvirt.c ? ? ? ? ? ? ? ?| ? 55 ++++++++++++++++++++++++++++++++++++++++++ > ?src/libvirt_public.syms ? ? ?| ? ?4 +++ > ?src/libxl/libxl_driver.c ? ? | ? ?1 + > ?src/lxc/lxc_driver.c ? ? ? ? | ? ?1 + > ?src/openvz/openvz_driver.c ? | ? ?1 + > ?src/phyp/phyp_driver.c ? ? ? | ? ?1 + > ?src/qemu/qemu_driver.c ? ? ? | ? ?1 + > ?src/remote/remote_driver.c ? | ? ?1 + > ?src/test/test_driver.c ? ? ? | ? ?1 + > ?src/uml/uml_driver.c ? ? ? ? | ? ?1 + > ?src/vbox/vbox_tmpl.c ? ? ? ? | ? ?1 + > ?src/vmware/vmware_driver.c ? | ? ?1 + > ?src/xen/xen_driver.c ? ? ? ? | ? ?1 + > ?src/xenapi/xenapi_driver.c ? | ? ?1 + > ?17 files changed, 91 insertions(+), 0 deletions(-) > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > index 5783303..6b9292c 100644 > --- a/include/libvirt/libvirt.h.in > +++ b/include/libvirt/libvirt.h.in > @@ -400,6 +400,13 @@ struct _virDomainMemoryStat { > > ?typedef virDomainMemoryStatStruct *virDomainMemoryStatPtr; > > +typedef struct _virDomainPcpuStat virDomainPcpuStatStruct; > + > +struct _virDomainPcpuStat { > + ? ?unsigned long long cpuTime; > +}; > + NACK to adding another public struct to the API. It's not expendable. As a stylistic nit pleas don't use the term PCPU as this looks like "Physical CPU". Just call it virDomainPerVcpuStat at least. Also do you really need the absolute CPU time? As noted elsewhere, this is in fact not implementable for ESX. But ESX can provide the virtual CPU utilization in MHz and percent. See the virNodeGetCpuTime series [1] for a better approach. [1] https://www.redhat.com/archives/libvir-list/2011-April/msg00702.html Matthias From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 15 07:43:03 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 15 Apr 2011 16:43:03 +0900 Subject: [libvirt] [RFC][PATCHv1 2/5] libvirt - new API for getting percpu statistics of VM In-Reply-To: References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> <20110415160452.63bd9216.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110415164303.455ab625.kamezawa.hiroyu@jp.fujitsu.com> On Fri, 15 Apr 2011 09:43:15 +0200 Matthias Bolte wrote: > 2011/4/15 KAMEZAWA Hiroyuki : > > Per (host) cpu activity of VMs are very insterested numbers > > when running VMs on large SMPs. virt-top -1 mode tries to > > provide the information. (But it's not implemented.) > > > > This patch adds a libvirt interface to get per cpu statistics > > of each nodes. This patch just adds an interface and driver > > entry points. So, > > ?- doesn't include patches for python. > > ?- doesn't include any driver. > > > > Following patches will add some drivers and codes for python. > > > > Signed-off-by: KAMEZAWA Hiroyuki > > --- > > ?include/libvirt/libvirt.h.in | ? 13 ++++++++++ > > ?src/driver.h ? ? ? ? ? ? ? ? | ? ?6 ++++ > > ?src/esx/esx_driver.c ? ? ? ? | ? ?1 + > > ?src/libvirt.c ? ? ? ? ? ? ? ?| ? 55 ++++++++++++++++++++++++++++++++++++++++++ > > ?src/libvirt_public.syms ? ? ?| ? ?4 +++ > > ?src/libxl/libxl_driver.c ? ? | ? ?1 + > > ?src/lxc/lxc_driver.c ? ? ? ? | ? ?1 + > > ?src/openvz/openvz_driver.c ? | ? ?1 + > > ?src/phyp/phyp_driver.c ? ? ? | ? ?1 + > > ?src/qemu/qemu_driver.c ? ? ? | ? ?1 + > > ?src/remote/remote_driver.c ? | ? ?1 + > > ?src/test/test_driver.c ? ? ? | ? ?1 + > > ?src/uml/uml_driver.c ? ? ? ? | ? ?1 + > > ?src/vbox/vbox_tmpl.c ? ? ? ? | ? ?1 + > > ?src/vmware/vmware_driver.c ? | ? ?1 + > > ?src/xen/xen_driver.c ? ? ? ? | ? ?1 + > > ?src/xenapi/xenapi_driver.c ? | ? ?1 + > > ?17 files changed, 91 insertions(+), 0 deletions(-) > > > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > > index 5783303..6b9292c 100644 > > --- a/include/libvirt/libvirt.h.in > > +++ b/include/libvirt/libvirt.h.in > > @@ -400,6 +400,13 @@ struct _virDomainMemoryStat { > > > > ?typedef virDomainMemoryStatStruct *virDomainMemoryStatPtr; > > > > +typedef struct _virDomainPcpuStat virDomainPcpuStatStruct; > > + > > +struct _virDomainPcpuStat { > > + ? ?unsigned long long cpuTime; > > +}; > > + > > NACK to adding another public struct to the API. Oh, yes. I searched a sutiable existing API but cannot found. Maybe adding new enum to Usui's work will be good but I need an array. Hmm, returning an array of unsigned long long is ok ? > It's not expendable. > As a stylistic nit pleas don't use the term PCPU as this looks like > "Physical CPU". Just call it virDomainPerVcpuStat at least. > Ah, no, this is PerPhysicalStat > Also do you really need the absolute CPU time? yes, for virt-top -1. > As noted elsewhere, > this is in fact not implementable for ESX. But ESX can provide the > virtual CPU utilization in MHz and percent. > I need physical cpu utilization by domain. > See the virNodeGetCpuTime series [1] for a better approach. > > [1] https://www.redhat.com/archives/libvir-list/2011-April/msg00702.html > Thank you. -Kame From atodorov at otb.bg Fri Apr 15 08:57:06 2011 From: atodorov at otb.bg (Alexander Todorov) Date: Fri, 15 Apr 2011 11:57:06 +0300 Subject: [libvirt] [PATCH] implement BOOT_TIMEOUT In-Reply-To: <4DA5DE06.6070507@redhat.com> References: <1302682502-4967-1-git-send-email-atodorov@otb.bg> <4DA5DE06.6070507@redhat.com> Message-ID: <4DA80862.3090303@otb.bg> Hello folks, here's a second try at this wrt to Eric's comments. BOOT_TIMEOUT changed to START_DELAY, updated wording in the conf file to better reflect what this does and added a flag to skip sleeping for the first ever started guest. --- tools/libvirt-guests.init.sh | 7 +++++++ tools/libvirt-guests.sysconf | 3 +++ 2 files changed, 10 insertions(+), 0 deletions(-) diff --git a/tools/libvirt-guests.init.sh b/tools/libvirt-guests.init.sh index f247e5e..30f957a 100644 --- a/tools/libvirt-guests.init.sh +++ b/tools/libvirt-guests.init.sh @@ -42,6 +42,7 @@ URIS=default ON_BOOT=start ON_SHUTDOWN=suspend SHUTDOWN_TIMEOUT=0 +START_DELAY=0 test -f "$sysconfdir"/sysconfig/libvirt-guests && . "$sysconfdir"/sysconfig/libvirt-guests @@ -141,6 +142,7 @@ start() { return 0 fi + isfirst=true while read uri list; do configured=false set -f @@ -165,6 +167,11 @@ start() { if "$guest_running"; then gettext "already active"; echo else + if "$isfirst"; then + isfirst=false + else + sleep $START_DELAY + fi retval run_virsh "$uri" start "$name" >/dev/null && \ gettext "done"; echo fi diff --git a/tools/libvirt-guests.sysconf b/tools/libvirt-guests.sysconf index cd58728..37b258e 100644 --- a/tools/libvirt-guests.sysconf +++ b/tools/libvirt-guests.sysconf @@ -10,6 +10,9 @@ # libvirtd #ON_BOOT=start +# number of seconds to wait between each guest start +#START_DELAY=0 + # action taken on host shutdown # - suspend all running guests are suspended using virsh managedsave # - shutdown all running guests are asked to shutdown. Please be careful with From cfergeau at redhat.com Fri Apr 15 09:25:53 2011 From: cfergeau at redhat.com (Christophe Fergeau) Date: Fri, 15 Apr 2011 11:25:53 +0200 Subject: [libvirt] [PATCH] esx: Fix gcc 4.6 warning about initialized but unused variables In-Reply-To: References: Message-ID: <20110415092553.GA5368@teriyaki.cdg.redhat.com> Hi Matthias, On Thu, Apr 14, 2011 at 07:18:27PM +0200, Matthias Bolte wrote: > This is a speculative patch as I don't have gcc 4.6 at hand to test it. I no longer get the warning with this patch applied. At first I was worried about the use of ATTRIBUTE_UNUSED (I assumed it meant "this var is unused, feel free to optimize it away"), but gcc documentation indeed says: "unused This attribute, attached to a variable, means that the variable is meant to be possibly unused. GCC will not produce a warning for this variable." So this all looks good to me (aka ack from me) Christophe -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 198 bytes Desc: not available URL: From atodorov at otb.bg Fri Apr 15 12:49:59 2011 From: atodorov at otb.bg (Alexander Todorov) Date: Fri, 15 Apr 2011 15:49:59 +0300 Subject: [libvirt] libvirt-guests - order of stopping/starting guests Message-ID: <4DA83EF7.4020901@otb.bg> Hi all, on a previous thread [1] Eric Blake mentioned: > Without more code on the libvirt front, I think you're stuck renaming > the guests to enforce naming order (assuming that libvirt even goes by > sorted name order, as opposed to readdir() order where you have no control). I poked around the code and experimented a little bit and found the following. * When you first create new guest (or start already created guest) it is assigned a sequential ID, name and also UUID. IDs start from 1 and increase as long as libvirtd is running. * When libvirt-guests wants to start/shutdown guests it relies on the file /var/lib/libvirt/libvirt-guests. The format of this file is: URI libvirt-guests script will start the guests as written in the file. * The libvirt-guests file is initially created from the output of `virsh list' and `virsh dominfo' (to get the UUID). virsh list will list the guests ordered by their ID. * Order of starting/stopping guests is unreliable. The only thing that matters wrt start/shutdown order is the guest ID at the time when the libvirt-guests file is generated. By default the order is the order in which guests were created and it can change if you randomly stop/start guests while libvirtd is running . Names or UUIDs don't play here at all. I'm not exactly sure what IDs are used for but they change every time when a guest is stopped/started manually. Which in turn reflects the order in which libvirt-guests stops/starts all guests. Example: On a freshly installed system I created 5 guests in the following order: a1, b1, a2, c1, a11. Then I left all guests running. Upon stop/start of the libvirt-guests service the guests were stoped/started in the same order. Then I stopped libvirt-guests and libvirtd, renamed a1 to c2 and restarted both services. c2 was first in the list - name doesn't matter. virsh list shows IDs are 1 to 5 (c2 = 1). Then I did: virsh shutdown c2 && virsh start c2. c2 now has id of 6. Doing service libvirt-guests stop/start again now showed me a different order: b1, a2, c1, a11, c2 You see how the order in which guests are started/stopped is unreliable. If I were to stop c1 while all other guests were running and then start it again (e.g. after attaching a new disk image) then it will have the highest ID number and will become last in the list used for stopping/starting guests. I'm not sure if this can easily be fixed or it needs the concept of groups/relations implemented. [1] - https://www.redhat.com/archives/libvir-list/2011-April/msg00789.html Regards, Alexander. From thomas at scripty.at Fri Apr 15 13:03:10 2011 From: thomas at scripty.at (Thomas Treutner) Date: Fri, 15 Apr 2011 15:03:10 +0200 Subject: [libvirt] libvirt 0.9.0 crashes on first start since boot In-Reply-To: <4DA713FD.9080500@laine.org> References: <4DA6D0DD.10405@scripty.at> <4DA713FD.9080500@laine.org> Message-ID: <4DA8420E.2020901@scripty.at> Am 14.04.2011 17:34, schrieb Laine Stump: > On 04/14/2011 06:47 AM, Thomas Treutner wrote: >> Hi, >> >> I've upgraded to 0.9.0 today on my Debian Squeeze boxes. Everything >> went fine, expect on one node (and only on that one, although the >> setup is identical), the first start of libvirtd since boot (and >> again, only that start) crashes with SEGV. >> >> Here are traces from gdb: >> >> http://pastebin.com/DiZrw0S5 >> http://pastebin.com/eacJRv07 >> >> If I delete the PID-file and start libvirtd again, it works fine. It >> doesn't seem to matter when the first start since boot happens, I've >> deactivated startup of libvirtd at boot time. >> >> Any ideas or further infos needed? > > Aside from Michal's fix to the error *recovery*, the more interesting > question is why this is now failing. > > The bits of system log we can see in the pastebin shows that dnsmasq > failed with an exit code of 2. From the manpage, this means: > > 2 - A problem with network access occurred (address in use, attempt to > use privileged ports without permission). > > Do you have a system instance of dnsmasq already running? (perhaps it's > already listening on all interfaces) Can you send the output of "dnsmasq > -v; ps -AlF | grep dnsmasq"? Indeed: root at node05:~# dnsmasq -v; ps -AlF | grep dnsmasq Dnsmasq version 2.55 Copyright (c) 2000-2010 Simon Kelley Compile time options IPv6 GNU-getopt DBus I18N DHCP TFTP This software comes with ABSOLUTELY NO WARRANTY. Dnsmasq is free software, and you are welcome to redistribute it under the terms of the GNU General Public License, version 2 or 3. 5 S dnsmasq 2647 1 0 80 0 - 5981 - 856 3 14:54 ? 00:00:00 /usr/sbin/dnsmasq -x /var/run/dnsmasq/dnsmasq.pid -u dnsmasq -7 /etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new 0 S root 3544 3473 0 80 0 - 2180 - 852 3 14:56 pts/0 00:00:00 grep dnsmasq I removed dnsmasq startup from the runlevel, now it works fine. I have seen dnsmasq errors for a long time, but I didn't really care too much about, as I don't need dnsmasq and the warnings didn't stop libvrit from working. I think I'll just deinstall dnsmasq. > Also, does the directory > /usr/local/var/lib/libvirt/dnsmasq exist? Jep: # ls /usr/local/var/lib/libvirt/dnsmasq default.leases thanks, -t From thomas at scripty.at Fri Apr 15 13:11:23 2011 From: thomas at scripty.at (Thomas Treutner) Date: Fri, 15 Apr 2011 15:11:23 +0200 Subject: [libvirt] libvirt 0.9.0 crashes on first start since boot In-Reply-To: <4DA713FD.9080500@laine.org> References: <4DA6D0DD.10405@scripty.at> <4DA713FD.9080500@laine.org> Message-ID: <4DA843FB.4040808@scripty.at> Am 14.04.2011 17:34, schrieb Laine Stump: > Do you have a system instance of dnsmasq already running? PS: It was the only node where dnsmasq was installed, for whatever reason. Seems to narrow down the problem pretty good. From Jes.Sorensen at redhat.com Fri Apr 15 13:55:41 2011 From: Jes.Sorensen at redhat.com (Jes Sorensen) Date: Fri, 15 Apr 2011 15:55:41 +0200 Subject: [libvirt] LPC2011 Virtualization Micro Conf Message-ID: <4DA84E5D.6040300@redhat.com> Hi, With the success of last year's Virtualization micro-conference track at Linux Plumbers 2010, I have accepted to organize a similar track for Linux Plumbers 2011 in Santa Rosa. Please see the official Linux Plumbers 2011 website for full details about the conference: http://www.linuxplumbersconf.org/2011/ The Linux Plumbers 2011 Virtualization track is focusing on general free software Linux Virtualization. It is not reserved for a specific hypervisor, but will focus on general virtualization issues and in particular collaboration amongst projects. This would include KVM, Xen, QEMU, containers etc. Deadline: --------- The deadline for submissions is April 30th. Please visit the following link to submit your proposal: http://www.linuxplumbersconf.org/2011/ocw/events/LPC2011MC/proposals Example topics: --------------- - Kernel and Hypervisor KVM/QEMU/Xen interaction - QEMU integration, sharing of code between the different projects - IO Performance and scalability - Live Migration - Managing and supporting enterprise storage - Support for new hardware features, and/or provide guest access to these features. - Guest agents - Virtualization management tools, libvirt, etc. - Desktop integration - Consumer Electronics device emulation - Custom platform configuration and coordination with the kernel Audience: --------- Virtualization hypervisor developers, developers of virtualization management tools and applications, embedded virtualization developers, vendors and others. Best regards, Jes From eblake at redhat.com Fri Apr 15 16:27:35 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 10:27:35 -0600 Subject: [libvirt] [PATCH v2] Merge all returns paths from dispatcher into single path In-Reply-To: <1302787697-31789-1-git-send-email-berrange@redhat.com> References: <1302787697-31789-1-git-send-email-berrange@redhat.com> Message-ID: <4DA871F7.3020306@redhat.com> On 04/14/2011 07:28 AM, Daniel P. Berrange wrote: > The dispatcher functions have numerous places where they > return to the caller. This leads to duplicated cleanup > code, often resulting in memory leaks. It makes it harder > to ensure that errors are dispatched before freeing objects, > which may overwrite the original error. > Rather than review your entire patch again, I just reviewed this interdiff. You really did get rid of all remoteDispatchOOMError callers; I'd be fine if you squashed in deleting the declaration from daemon/dispatch.[ch] as part of this patch, or as a followup. > diff --git c/daemon/remote.c w/daemon/remote.c > index 8f4d6a6..a25c095 100644 > --- c/daemon/remote.c > +++ w/daemon/remote.c > @@ -912,7 +912,7 @@ remoteDispatchDomainGetSchedulerParameters(struct qemud_server *server ATTRIBUTE > remote_domain_get_scheduler_parameters_ret *ret) > { > virDomainPtr dom = NULL; > - virSchedParameterPtr params; > + virSchedParameterPtr params = NULL; > int i, r, nparams; > int rv = -1; > > @@ -927,10 +927,8 @@ remoteDispatchDomainGetSchedulerParameters(struct qemud_server *server ATTRIBUTE > virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large")); > goto cleanup; > } > - if (VIR_ALLOC_N(params, nparams) < 0) { > - virReportOOMError(); > - goto cleanup; > - } > + if (VIR_ALLOC_N(params, nparams) < 0) > + goto no_memory; > > dom = get_nonnull_domain(conn, args->dom); > if (dom == NULL) { > @@ -1002,7 +1000,7 @@ remoteDispatchDomainSetSchedulerParameters(struct qemud_server *server ATTRIBUTE > { > virDomainPtr dom = NULL; > int i, r, nparams; > - virSchedParameterPtr params; > + virSchedParameterPtr params = NULL; > int rv = -1; > > if (!conn) { > @@ -1960,7 +1958,7 @@ remoteDispatchDomainGetSecurityLabel(struct qemud_server *server ATTRIBUTE_UNUSE > remote_domain_get_security_label_ret *ret) > { > virDomainPtr dom = NULL; > - virSecurityLabelPtr seclabel; > + virSecurityLabelPtr seclabel = NULL; > int rv = -1; > > if (!conn) { > @@ -3041,7 +3039,7 @@ remoteDispatchDomainSetMemoryParameters(struct qemud_server *server > { > virDomainPtr dom = NULL; > int i, r, nparams; > - virMemoryParameterPtr params; > + virMemoryParameterPtr params = NULL; > unsigned int flags; > int rv = -1; > > @@ -3142,7 +3140,7 @@ remoteDispatchDomainGetMemoryParameters(struct qemud_server *server > * ret) > { > virDomainPtr dom = NULL; > - virMemoryParameterPtr params; > + virMemoryParameterPtr params = NULL; > int i, r, nparams; > unsigned int flags; > int rv = -1; > @@ -3233,8 +3231,6 @@ remoteDispatchDomainGetMemoryParameters(struct qemud_server *server > success: > rv = 0; > > -no_memory: > - virReportOOMError(); > cleanup: > if (rv < 0) { > remoteDispatchError(rerr); > @@ -3246,6 +3242,10 @@ cleanup: > virDomainFree(dom); > VIR_FREE(params); > return rv; > + > +no_memory: > + virReportOOMError(); > + goto cleanup; > } Good, this addresses my review comments. > > static int > @@ -3262,7 +3262,7 @@ remoteDispatchDomainSetBlkioParameters(struct qemud_server *server > { > virDomainPtr dom = NULL; > int i, r, nparams; > - virBlkioParameterPtr params; > + virBlkioParameterPtr params = NULL; > unsigned int flags; > int rv = -1; > > @@ -3363,7 +3363,7 @@ remoteDispatchDomainGetBlkioParameters(struct qemud_server *server > * ret) > { > virDomainPtr dom = NULL; > - virBlkioParameterPtr params; > + virBlkioParameterPtr params = NULL; > int i, r, nparams; > unsigned int flags; > int rv = -1; > @@ -4846,9 +4846,8 @@ remoteDispatchAuthSaslInit(struct qemud_server *server, > virStrerror(errno, ebuf, sizeof ebuf)); > goto error; > } > - if ((localAddr = virSocketFormatAddrFull(&sa, true, ";")) == NULL) { > + if ((localAddr = virSocketFormatAddrFull(&sa, true, ";")) == NULL) > goto error; > - } Looks like the cleanups from one of your followup patches leaked in here when you reverted your sasl changes, but no real harm leaving this hunk in. > > /* Get remote address in form IPADDR:PORT */ > sa.len = sizeof(sa.data.stor); > @@ -4964,7 +4963,7 @@ authfail: > error: > PROBE(CLIENT_AUTH_FAIL, "fd=%d, auth=%d", client->fd, REMOTE_AUTH_SASL); > virMutexUnlock(&client->lock); > - goto error; > + return -1; > } > > > @@ -5126,6 +5125,7 @@ remoteDispatchAuthSaslStart(struct qemud_server *server, > if (serverout) { > if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) { > virReportOOMError(); > + remoteDispatchError(rerr); > goto error; > } > memcpy(ret->data.data_val, serverout, serveroutlen); > @@ -5227,6 +5227,7 @@ remoteDispatchAuthSaslStep(struct qemud_server *server, > if (serverout) { > if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) { > virReportOOMError(); > + remoteDispatchError(rerr); > goto error; > } > memcpy(ret->data.data_val, serverout, serveroutlen); > @@ -5403,7 +5404,7 @@ remoteDispatchAuthPolkit(struct qemud_server *server, > client->auth = REMOTE_AUTH_NONE; > > virMutexUnlock(&client->lock); > - rv = 0; > + return 0; > > authfail: > PROBE(CLIENT_AUTH_FAIL, "fd=%d, auth=%d", client->fd, REMOTE_AUTH_POLKIT); > @@ -5535,7 +5536,7 @@ remoteDispatchAuthPolkit(struct qemud_server *server, > client->auth = REMOTE_AUTH_NONE; > > virMutexUnlock(&client->lock); > - rv = 0; > + return 0; Looks like you correctly reverted any changes to sasl code, as planned. > > authfail: > PROBE(CLIENT_AUTH_FAIL, "fd=%d, auth=%d", client->fd, REMOTE_AUTH_POLKIT); > @@ -6964,7 +6965,7 @@ remoteDispatchNodeDeviceGetParent(struct qemud_server *server ATTRIBUTE_UNUSED, > remote_node_device_get_parent_ret *ret) > { > virNodeDevicePtr dev = NULL; > - const char *parent; > + const char *parent = NULL; > int rv = -1; > > if (!conn) { > @@ -6988,8 +6989,8 @@ remoteDispatchNodeDeviceGetParent(struct qemud_server *server ATTRIBUTE_UNUSED, > virReportOOMError(); > goto cleanup; > } > - *parent_p = strdup(parent); > - if (*parent_p == NULL) { > + if (!(*parent_p = strdup(parent))) { > + VIR_FREE(parent_p); > virReportOOMError(); > goto cleanup; > } For all my waffling reviews, I think you got this one right now. > @@ -8413,7 +8414,7 @@ remoteDispatchDomainSnapshotCreateXml(struct qemud_server *server ATTRIBUTE_UNUS > remote_domain_snapshot_create_xml_args *args, > remote_domain_snapshot_create_xml_ret *ret) > { > - virDomainSnapshotPtr snapshot; > + virDomainSnapshotPtr snapshot = NULL; > virDomainPtr domain = NULL; > int rv = -1; > > @@ -8589,7 +8590,7 @@ remoteDispatchDomainSnapshotLookupByName(struct qemud_server *server ATTRIBUTE_U > remote_domain_snapshot_lookup_by_name_args *args, > remote_domain_snapshot_lookup_by_name_ret *ret) > { > - virDomainSnapshotPtr snapshot; > + virDomainSnapshotPtr snapshot = NULL; > virDomainPtr domain = NULL; > int rv = -1; > > @@ -8671,7 +8672,7 @@ remoteDispatchDomainSnapshotCurrent(struct qemud_server *server ATTRIBUTE_UNUSED > remote_domain_snapshot_current_args *args, > remote_domain_snapshot_current_ret *ret) > { > - virDomainSnapshotPtr snapshot; > + virDomainSnapshotPtr snapshot = NULL; > virDomainPtr domain = NULL; > int rv = -1; > ACK - you addressed all my findings from v1. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 15 16:36:10 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 10:36:10 -0600 Subject: [libvirt] [PATCH V3 2/2] enhance processWatchdogEvent() In-Reply-To: <4DA7B76B.3010308@cn.fujitsu.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1CED.20202@cn.fujitsu.com> <4DA75CD7.9080908@redhat.com> <4DA7B76B.3010308@cn.fujitsu.com> Message-ID: <4DA873FA.8080009@redhat.com> On 04/14/2011 09:11 PM, Wen Congyang wrote: > This patch do the following two things: s/do/does/ > 1. hold an extra reference while handling watchdog event > If the domain is not persistent, and qemu quits unexpectedly before > calling processWatchdogEvent(), vm will be freed and the function > processWatchdogEvent() will be dangerous. > > 2. unlock qemu driver and vm before returning from processWatchdogEvent() > When the function processWatchdogEvent() failed, we only free wdEvent, > but forget to unlock qemu driver and vm, free dumpfile. > > > --- > src/qemu/qemu_driver.c | 34 ++++++++++++++++++++++------------ > src/qemu/qemu_process.c | 4 ++++ > 2 files changed, 26 insertions(+), 12 deletions(-) Looks like your v2 caught my review comments correctly. But I found one more issue: > +++ b/src/qemu/qemu_process.c > @@ -428,6 +428,10 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > if (VIR_ALLOC(wdEvent) == 0) { > wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP; > wdEvent->vm = vm; > + /* Hold an extra reference because we can't allow 'vm' to be > + * deleted before handling watchdog event is finished. > + */ > + virDomainObjRef(vm); > ignore_value(virThreadPoolSendJob(driver->workerPool, wdEvent)); Now that we have increased the ref count, we should decrease it if we are unable to send a job to the thread pool. That is, replace the ignore_value() with: if (virThreadPoolSendJob(...) < 0) { virDomainObjUnref(vm); VIR_FREE(wdEvent); } ACK with that change squashed in. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 15 17:16:24 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 11:16:24 -0600 Subject: [libvirt] [PATCH] implement BOOT_TIMEOUT In-Reply-To: <4DA80862.3090303@otb.bg> References: <1302682502-4967-1-git-send-email-atodorov@otb.bg> <4DA5DE06.6070507@redhat.com> <4DA80862.3090303@otb.bg> Message-ID: <4DA87D68.3070803@redhat.com> On 04/15/2011 02:57 AM, Alexander Todorov wrote: > Hello folks, > here's a second try at this wrt to Eric's comments. > BOOT_TIMEOUT changed to START_DELAY, updated wording in the conf file to > better reflect what this does and added a flag to skip sleeping for the > first ever started guest. > > > --- > tools/libvirt-guests.init.sh | 7 +++++++ > tools/libvirt-guests.sysconf | 3 +++ > 2 files changed, 10 insertions(+), 0 deletions(-) Your mailer botched the patch (it used 2 instead of 1 leading space for each context line), and 'git apply' had a hard time applying it; I had to redo it by hand. ACK and pushed. Thanks for the contribution! I added you to AUTHORS; feel free to let me know (off-list if desired) if I need to adjust your listing. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 15 17:38:55 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 11:38:55 -0600 Subject: [libvirt] virsh memset In-Reply-To: References: Message-ID: <4DA882AF.8070803@redhat.com> On 04/14/2011 06:04 AM, Zvi Dubitzky wrote: > Hi > > Does anybody know if 'virsh memset' is working ok with its parameters > with the late libvirt code > (>= 0.8.8 )? With what libcgroup version ? 'virsh memset' doesn't depend on cgroups. It relies on the guest honoring virtio ballooning requests. Guests like Fedora are wired to do this out of the box, but not all guests support it. I'm not sure whether the virtio drivers for Windows can do ballooning. If a guest can't honor ballooning, then you can't change current memory at runtime; however, with very recent git (0.9.1), 'virsh memset --persistent' can be used to modify the persistent storage to affect the memory usage on the next guest boot. Or are you referring to 'virsh memtune', which does indeed require cgroup support, but does not require any guest interaction? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 15 17:53:21 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 11:53:21 -0600 Subject: [libvirt] [PATCH 0/6] Add support for injecting NMI to guest In-Reply-To: <4DA52D1A.1000307@cn.fujitsu.com> References: <4DA52D1A.1000307@cn.fujitsu.com> Message-ID: <4DA88611.7010701@redhat.com> On 04/12/2011 10:56 PM, Lai Jiangshan wrote: > > > This patch series implements a feature of injecting NMI to guest, > which is accessible via new virDomainInjectNMI API and > 'inject-nmi' command in virsh. > > Lai Jiangshan (6): > inject-nmi: Defining the public API > inject-nmi: Defining the internal API > inject-nmi: Implementing the public API > inject-nmi: Implementing the remote protocol > inject-nmi: Expose the new API in virsh > qemu,inject-nmi: Implement the driver methods This is v2 of: https://www.redhat.com/archives/libvir-list/2011-April/msg00036.html If you use 'git format-patch --subject-prefix=PATCHv2' (or send-email instead of format-patch), it makes it easier to see that this is a resend. Thanks for splitting it up; that helps review. My quick glance at 1-5 didn't turn up any glaring problems, but I'm still not sure we've got the semantics right. I'll reply to patch 6, and think we'll need another spin to get the API right. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 15 18:13:50 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 12:13:50 -0600 Subject: [libvirt] [PATCH 6/6] qemu, inject-nmi: Implement the driver methods In-Reply-To: <4DA52E3E.10402@cn.fujitsu.com> References: <4DA52D1A.1000307@cn.fujitsu.com> <4DA52E3E.10402@cn.fujitsu.com> Message-ID: <4DA88ADE.7050208@redhat.com> On 04/12/2011 11:01 PM, Lai Jiangshan wrote: > +++ b/src/qemu/qemu_driver.c > @@ -1701,6 +1701,48 @@ static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) > return qemudDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM); > } > > +static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags) > +{ > + struct qemud_driver *driver = domain->conn->privateData; > + virDomainObjPtr vm = NULL; > + int ret = -1; > + qemuDomainObjPrivatePtr priv; > + Right here, you should have a virCheckFlags(0, -1) to enforce that we don't honor any flags for now. At which point, you don't need to pass flags on down to the monitor calls. > +++ b/src/qemu/qemu_monitor_json.c > @@ -2513,3 +2513,32 @@ cleanup: > > return ret; > } > + > +int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon, unsigned int flags ATTRIBUTE_UNUSED) > +{ Since neither monitor needed flags this low, you don't have to propogate it any further than qemu_driver.c's virCheckFlags(). > + int ret; > + virJSONValuePtr cmd; > + virJSONValuePtr reply = NULL; > + > + /* > + * FIXME: qmp nmi is not supported until qemu-0.16.0, > + * use human-monitor-command instead temporary. > + * > + * FIXME: qemu's nmi command just injects NMI to a specified CPU, > + * use "nmi 0" instead temporary. > + */ > + cmd = qemuMonitorJSONMakeCommand("human-monitor-command", > + "s:command-line", "nmi 0", > + NULL); We've already got a preferred form for issuing HMP commands from JSON. Rather than building up human-monitor-command manually, you should instead be using qemuMonitorTextInjectNMI; for example, see how qemuMonitorJSONDriveDel falls back to hmp. This also covers the case of a qemu binary that has JSON but not hmp giving a more useful error message. > +++ b/src/qemu/qemu_monitor_text.c > @@ -2628,3 +2628,23 @@ int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, > > return ret; > } > + > +int qemuMonitorTextInjectNMI(qemuMonitorPtr mon, unsigned int flags ATTRIBUTE_UNUSED) > +{ > + const char *cmd = "nmi 0"; > + char *reply = NULL; > + > + /* > + * FIXME: qemu's nmi command just injects NMI to a specified CPU, > + * use "nmi 0" instead temporary. > + */ This bothers me. Is it possible to inject NMI to a particular CPU in bare-metal hardware? If so, then we ought to support that in the API. I know what Dan said: >>> +int virDomainSendEventNMI(virDomainPtr domain, unsigned int vcpu) >> >> Your proposal to qemu-devel to add inject-nmi for QMP does not >> include any CPU index parameter anymore. Instead it will automatically >> inject the NMI to all present CPUs. This libvirt API would appear to >> be incompatible with that QMP design. For Xen, it appears the API >> also does not allow a CPU index to be given - it just injects to the >> first CPU AFAICT. >> >> So do we really need to have a 'unsigned int vcpu' parameter in the >> libvirt API, or can we just leave it out and always inject to >> CPU==0 for HMP ? >> >> eg simplify to >> >> int virDomainSendNMI(virDomainPtr domain) but if there's ever any possibility that qemu might learn how to direct an NMI to a particular vcpu, I wonder if we should instead have: enum { VIR_DOMAIN_INJECT_NMI_FIRST = 1, VIR_DOMAIN_INJECT_NMI_ALL = 2, } /** * virDomainInjectNMI: * @domain: pointer to domain object, or NULL for Domain0 * @vcpu: which vcpu to send the NMI to * @flags: the flags for controlling behaviours * * Send NMI to the guest. If @flags contains * VIR_DOMAIN_INJECT_NMI_FIRST or VIR_DOMAIN_INJECT_NMI_ALL, * then @vcpu is ignored, and the NMI is sent to the first * possible vcpu or to all vcpus, respectively. Otherwise, * the NMI is sent to the specified vcpu; it is an error if * @vcpu does not correspond to a currently online processor. * * Not all hypervisors support fine-tuned control over which * vcpu(s) can be targetted, and might succeed only for a * particular value of @flags. * * Returns 0 in case of success, -1 in case of failure. */ int virDomainInjectNMI(virDomainPtr domain, unsigned int vcpu, unsigned int flags); Then xen would be hardcoded to require flags==_FIRST (and always ignore vcpu), whereas qemu can honor a particular vcpu. Or is the first vcpu always 0? That is, are there any hypervisors that let you offline vcpu 0 while leaving vcpu1 up, so that FIRST would imply 1? Maybe we don't need a flag for FIRST, but document that vcpu is ignored if ALL is passed, and then make xen error out if ALL is passed or if vcpu != 0. That said, I haven't looked at the proposed qemu side of the patches for how the monitor command for nmi will be implemented in the first place, and until that is in a formal qemu release, we may still need to be a bit flexible here on the libvirt side. Do any other hypervisors allow NMI injection, and with what semantics? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 15 18:33:45 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 12:33:45 -0600 Subject: [libvirt] [PATCH] esx: Fix gcc 4.6 warning about initialized but unused variables In-Reply-To: <20110415092553.GA5368@teriyaki.cdg.redhat.com> References: <20110415092553.GA5368@teriyaki.cdg.redhat.com> Message-ID: <4DA88F89.9080208@redhat.com> On 04/15/2011 03:25 AM, Christophe Fergeau wrote: > Hi Matthias, > > On Thu, Apr 14, 2011 at 07:18:27PM +0200, Matthias Bolte wrote: >> This is a speculative patch as I don't have gcc 4.6 at hand to test it. > > I no longer get the warning with this patch applied. At first I was worried > about the use of ATTRIBUTE_UNUSED (I assumed it meant "this var is unused, > feel free to optimize it away"), but gcc documentation indeed says: > "unused > This attribute, attached to a variable, means that the variable is > meant to be possibly unused. GCC will not produce a warning for this > variable." > > So this all looks good to me (aka ack from me) ACK from me as well; I went ahead and pushed it under the build-breaker rule. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jdenemar at redhat.com Fri Apr 15 20:04:53 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Fri, 15 Apr 2011 22:04:53 +0200 Subject: [libvirt] [PATCH] tests: Unit tests for internal hash APIs In-Reply-To: <20110413111532.GB18468@redhat.com> References: <20110413111532.GB18468@redhat.com> Message-ID: This is a basic set of tests for testing removals of hash entries during iteration. --- More tests for all other hash APIs will come on Monday. tests/Makefile.am | 8 +++- tests/hashdata.h | 33 +++++++++++ tests/hashtest.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+), 1 deletions(-) create mode 100644 tests/hashdata.h create mode 100644 tests/hashtest.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 5896442..063ab60 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -77,7 +77,8 @@ EXTRA_DIST = \ check_PROGRAMS = virshtest conftest sockettest \ nodeinfotest qparamtest virbuftest \ - commandtest commandhelper seclabeltest + commandtest commandhelper seclabeltest \ + hashtest if WITH_XEN check_PROGRAMS += xml2sexprtest sexpr2xmltest \ @@ -159,6 +160,7 @@ TESTS = virshtest \ sockettest \ commandtest \ seclabeltest \ + hashtest \ $(test_scripts) if WITH_XEN @@ -373,6 +375,10 @@ virbuftest_SOURCES = \ virbuftest.c testutils.h testutils.c virbuftest_LDADD = $(LDADDS) +hashtest_SOURCES = \ + hashtest.c hashdata.h testutils.h testutils.c +hashtest_LDADD = $(LDADDS) + if WITH_LIBVIRTD eventtest_SOURCES = \ eventtest.c testutils.h testutils.c diff --git a/tests/hashdata.h b/tests/hashdata.h new file mode 100644 index 0000000..2782255 --- /dev/null +++ b/tests/hashdata.h @@ -0,0 +1,33 @@ +const char *uuids[] = { +/* [ 46] */ "f17494ba-2353-4af0-b1ba-13680858edcc", + "64ab4e78-1b6e-4b88-b47f-2def46c79a86", + "f99b0d59-ecff-4cc6-a9d3-20159536edc8", +/* [ 75] */ "e1bfa30f-bc0b-4a24-99ae-bed7f3f21a7b", + "acda5fa0-58de-4e1e-aa65-2124d1e29c54", +/* [ 76] */ "5f476c28-8f26-48e0-98de-85745fe2f304", +/* [123] */ "8be1d21c-cd35-4c7c-8fee-4b5046c7a62b", + "830f0d57-9f21-40e8-bb86-cbf41de23fd6", + "57044958-1b8a-4c02-ab75-2298c6e44263", + "d526cd6c-4a99-4d5f-abfb-fc9419edd9d0", +/* [237] */ "3ab39f7f-4613-4da6-a216-c2d6acc441bb", + "ae20cf3c-38b8-483c-baea-6fb0994dc30c", + "cd204d90-2414-4b9e-9d4f-fed09c9a816f", +/* [240] */ "ed2cc723-db4b-43aa-ab02-0e3161087499", +/* [246] */ "8ada85bc-9bdf-4507-8334-849635ea0a01", + "8a7d5deb-615f-4cd3-8977-b5fab8ec4d05", +/* [247] */ "dc2173b0-48fe-4555-b190-8052be1120eb", + "040e434d-68d8-41a9-b3a1-1bee239914c1", + "d1a564b2-c7f3-4b76-8712-3b8f5aae6ded", + "0e614f33-c1da-4cfe-b6d5-65ecd2d066f2" +}; + +const char *uuids_subset[] = { + "64ab4e78-1b6e-4b88-b47f-2def46c79a86", + "acda5fa0-58de-4e1e-aa65-2124d1e29c54", + "830f0d57-9f21-40e8-bb86-cbf41de23fd6", + "57044958-1b8a-4c02-ab75-2298c6e44263", + "ae20cf3c-38b8-483c-baea-6fb0994dc30c", + "040e434d-68d8-41a9-b3a1-1bee239914c1", + "d1a564b2-c7f3-4b76-8712-3b8f5aae6ded", + "8ada85bc-9bdf-4507-8334-849635ea0a01" +}; diff --git a/tests/hashtest.c b/tests/hashtest.c new file mode 100644 index 0000000..dff0181 --- /dev/null +++ b/tests/hashtest.c @@ -0,0 +1,157 @@ +#include + +#include +#include +#include + +#include "internal.h" +#include "hash.h" +#include "hashdata.h" +#include "testutils.h" + + +#define testError(...) \ + do { \ + fprintf(stderr, __VA_ARGS__); \ + /* Pad to line up with test name ... in virTestRun */ \ + fprintf(stderr, "%74s", "... "); \ + } while (0) + + +static virHashTablePtr +testHashInit(int size) +{ + virHashTablePtr hash; + int i; + + if (!(hash = virHashCreate(size, NULL))) + return NULL; + + /* entires are added in reverse order so that they will be linked in + * collision list in the same order as in the uuids array + */ + for (i = ARRAY_CARDINALITY(uuids) - 1; i >= 0; i--) { + if (virHashAddEntry(hash, uuids[i], (void *) uuids[i]) < 0) { + virHashFree(hash); + return NULL; + } + } + + return hash; +} + + +static int +testHashCheckCount(virHashTablePtr hash, int count) +{ + if (virHashSize(hash) != count) { + testError("\nhash contains %d instead of %d elements\n", + virHashSize(hash), count); + return -1; + } + + return 0; +} + + +struct testInfo { + void *data; + int count; +}; + + +const int testHashCountRemoveForEachSome = + ARRAY_CARDINALITY(uuids) - ARRAY_CARDINALITY(uuids_subset); + +static void +testHashRemoveForEachSome(void *payload ATTRIBUTE_UNUSED, + const void *name, + void *data) +{ + virHashTablePtr hash = data; + int i; + + for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) { + if (STREQ(uuids_subset[i], name)) { + if (virHashRemoveEntry(hash, name) < 0 && virTestGetVerbose()) { + fprintf(stderr, "\nentry \"%s\" could not be removed", + uuids_subset[i]); + } + break; + } + } +} + + +const int testHashCountRemoveForEachAll = 0; + +static void +testHashRemoveForEachAll(void *payload ATTRIBUTE_UNUSED, + const void *name, + void *data) +{ + virHashTablePtr hash = data; + + virHashRemoveEntry(hash, name); +} + + +static int +testHashRemoveForEach(const void *data) +{ + const struct testInfo *info = data; + virHashTablePtr hash; + int count; + int ret = -1; + + if (!(hash = testHashInit(0))) + return -1; + + count = virHashForEach(hash, (virHashIterator) info->data, hash); + + if (count != ARRAY_CARDINALITY(uuids)) { + if (virTestGetVerbose()) { + testError("\nvirHashForEach didn't go through all entries," + " %d != %lu\n", + count, ARRAY_CARDINALITY(uuids)); + } + goto cleanup; + } + + if (testHashCheckCount(hash, info->count) < 0) + goto cleanup; + + ret = 0; + +cleanup: + virHashFree(hash); + return ret; +} + + +static int +mymain(int argc ATTRIBUTE_UNUSED, + char **argv ATTRIBUTE_UNUSED) +{ + int ret = 0; + +#define DO_TEST_FULL(name, cmd, data, count) \ + do { \ + struct testInfo info = { data, count }; \ + if (virtTestRun(name, 1, testHash ## cmd, &info) < 0) \ + ret = -1; \ + } while (0) + +#define DO_TEST_DATA(name, cmd, data) \ + DO_TEST_FULL(name "(" #data ")", \ + cmd, \ + testHash ## cmd ## data, \ + testHashCount ## cmd ## data) + + DO_TEST_DATA("Remove in ForEach", RemoveForEach, Some); + DO_TEST_DATA("Remove in ForEach", RemoveForEach, All); + + return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIRT_TEST_MAIN(mymain) -- 1.7.5.rc1 From matthias.bolte at googlemail.com Fri Apr 15 20:05:51 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 15 Apr 2011 22:05:51 +0200 Subject: [libvirt] [PATCHv2 1/9] maint: use lighter-weight function for straight appends In-Reply-To: <1302812555-3418-2-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-2-git-send-email-eblake@redhat.com> Message-ID: 2011/4/14 Eric Blake : > It costs quite a few processor cycles to go through printf parsing > just to determine that we only meant to append. > - ? ? ? ?virBufferVSprintf(&buf, "%s", k); > - ? ? ? ?virBufferVSprintf(&buf, "%s", "="); > - ? ? ? ?virBufferVSprintf(&buf, "%s", v); > + ? ? ? ?virBufferVSprintf(&buf, "%s=%s", k, v); Nice one :) ACK. Matthias From matthias.bolte at googlemail.com Fri Apr 15 20:09:48 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 15 Apr 2011 22:09:48 +0200 Subject: [libvirt] [PATCHv2 2/9] phyp: avoid a logic bug In-Reply-To: <1302812555-3418-3-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-3-git-send-email-eblake@redhat.com> Message-ID: 2011/4/14 Eric Blake : > Ever since commit ebc46f, the destroy function built two command > variants but only used one. ?I went with the variant that matches > the idiom used in the counterpart of phypBuildStoragePool. > > * src/phyp/phyp_driver.c (phypDestroyStoragePool): Avoid > clobbering cmd. ?Fix error message typo. > --- > ?src/phyp/phyp_driver.c | ? 11 +---------- > ?1 files changed, 1 insertions(+), 10 deletions(-) > > diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c > index 5742d95..7aa494d 100644 > --- a/src/phyp/phyp_driver.c > +++ b/src/phyp/phyp_driver.c > @@ -2936,19 +2936,10 @@ phypDestroyStoragePool(virStoragePoolPtr pool) > ? ? ? ? return -1; > ? ? } > ? ? cmd = virBufferContentAndReset(&buf); > - > - ? ?if (virAsprintf(&cmd, > - ? ? ? ? ? ? ? ? ? ?"viosvrcmd -m %s --id %d -c " > - ? ? ? ? ? ? ? ? ? ?"'rmsp %s'", managed_system, vios_id, > - ? ? ? ? ? ? ? ? ? ?pool->name) < 0) { > - ? ? ? ?virReportOOMError(); > - ? ? ? ?goto cleanup; > - ? ?} > - > ? ? ret = phypExec(session, cmd, &exit_status, conn); > > ? ? if (exit_status < 0) { > - ? ? ? ?VIR_ERROR(_("Unable to create Storage Pool: %s"), ret); > + ? ? ? ?VIR_ERROR(_("Unable to destroy Storage Pool: %s"), ret); > ? ? ? ? goto cleanup; > ? ? } I just noticed that the driver uses VIR_ERROR in many places where PHYP_ERROR should be used to report an actual libvirt API level error. But that a problem for another patch. ACK, to this one. Matthias From matthias.bolte at googlemail.com Fri Apr 15 20:12:41 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 15 Apr 2011 22:12:41 +0200 Subject: [libvirt] [PATCHv2 3/9] phyp: avoid memory leak on failure In-Reply-To: <1302812555-3418-4-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-4-git-send-email-eblake@redhat.com> Message-ID: 2011/4/14 Eric Blake : > * src/phyp/phyp_driver.c (phypUUIDTable_Init): Avoid memory leak > on error. > --- > ?src/phyp/phyp_driver.c | ? 46 +++++++++++++++++++++++++++------------------- > ?1 files changed, 27 insertions(+), 19 deletions(-) > ACK. Matthias From matthias.bolte at googlemail.com Fri Apr 15 20:25:19 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 15 Apr 2011 22:25:19 +0200 Subject: [libvirt] [PATCHv2 4/9] phyp: more return handling cleanup In-Reply-To: <1302812555-3418-5-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-5-git-send-email-eblake@redhat.com> Message-ID: 2011/4/14 Eric Blake : > * src/phyp/phyp_driver.c (phypInterfaceDestroy) > (phypInterfaceDefineXML, phypInterfaceLookupByName) > (phypInterfaceIsActive, phypListInterfaces, phypNumOfInterfaces): > Clean up return handling of recent additions. > --- > ?src/phyp/phyp_driver.c | ?130 +++++++++++++++++++++--------------------------- > ?1 files changed, 56 insertions(+), 74 deletions(-) > ACK. Mathias From jdenemar at redhat.com Fri Apr 15 20:26:33 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Fri, 15 Apr 2011 22:26:33 +0200 Subject: [libvirt] [PATCH 1/2] virsh: list required options first In-Reply-To: <1302644107-22840-2-git-send-email-eblake@redhat.com> References: <4DA4C473.9000908@redhat.com> <1302644107-22840-2-git-send-email-eblake@redhat.com> Message-ID: <20110415202633.GB7230@orkuz.home> On Tue, Apr 12, 2011 at 15:35:06 -0600, Eric Blake wrote: > The current state of virsh parsing is that: > > all lookup the volume by path (technically, the last two also attempt > a name lookup within a pool, whereas the first skips that step, but > the end result is the same); meanwhile: Is example virsh command line missing here? > complains about unexpected data. Why? Because the --pool option is > optional, so default was parsed as the --vol argument, and > /path/to/image.img doesn't match up with any remaining options that > require an argument. Therefore, the only way to specify pool is with > an explicit "--pool" argument (you can't specify it positionally). > However, named arguments can appear in any order, so: and here > have also always worked. Therefore, this patch has no functional > change on vol-info option parsing, but only on 'virsh help vol-info' > synopsis layout. However, it also allows the next patch to 1) enforce > that required options are always first (without this patch, the next > patch would fail the testsuite), and 2) allow the user to omit the > "--pool" argument. That is, the next patch makes it possible to do: and here > instead of the longer and here as well. > * tools/virsh.c (opts_vol_create_from, opts_vol_clone) > (opts_vol_upload, opts_vol_download, opts_vol_delete) > (opts_vol_wipe, opts_vol_info, opts_vol_dumpxml, opts_vol_key) > (opts_vol_path): List optional pool parameter after required > arguments. > --- > tools/virsh.c | 20 ++++++++++---------- > 1 files changed, 10 insertions(+), 10 deletions(-) Makes sense. I went through all virsh.c and didn't find more options that would need fixing. The only options which don't follow this "optional after required" rule are bool options which can safely stay where they are. ACK Jirka From matthias.bolte at googlemail.com Fri Apr 15 20:27:55 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 15 Apr 2011 22:27:55 +0200 Subject: [libvirt] [PATCHv2 5/9] phyp: use consistent style for labels In-Reply-To: <1302812555-3418-6-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-6-git-send-email-eblake@redhat.com> Message-ID: 2011/4/14 Eric Blake : > * src/phyp/phyp_driver.c: Match label style of rest of project. > (phypExec, phypUUIDTable_Pull): Drop an extra label. > --- > ?src/phyp/phyp_driver.c | ?129 +++++++++++++++++++++++------------------------- > ?1 files changed, 62 insertions(+), 67 deletions(-) > ACK. Matthias From matthias.bolte at googlemail.com Fri Apr 15 20:29:08 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 15 Apr 2011 22:29:08 +0200 Subject: [libvirt] [PATCHv2 6/9] phyp: prefer memcpy over memmove when legal In-Reply-To: <1302812555-3418-7-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-7-git-send-email-eblake@redhat.com> Message-ID: 2011/4/14 Eric Blake : > * src/phyp/phyp_driver.c (phypUUIDTable_AddLpar) > (phypGetLparUUID, phypGetStoragePoolUUID, phypVolumeGetXMLDesc) > (phypGetStoragePoolXMLDesc): Use faster method. > --- > ?src/phyp/phyp_driver.c | ? 10 +++++----- > ?1 files changed, 5 insertions(+), 5 deletions(-) > ACK. Matthias From matthias.bolte at googlemail.com Fri Apr 15 20:31:34 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 15 Apr 2011 22:31:34 +0200 Subject: [libvirt] [PATCHv2 7/9] phyp: use consistent return string handling In-Reply-To: <1302812555-3418-8-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-8-git-send-email-eblake@redhat.com> Message-ID: 2011/4/14 Eric Blake : > Use the name 'ret' for all phypExec results, to make it easier > to wrap phypExec. ?Don't allow a possibly NULL ret through printf. > > * src/phyp/phyp_driver.c (phypBuildVolume, phypDestroyStoragePool) > (phypBuildStoragePool, phypBuildLpar): Avoid NULL dereference. > (phypInterfaceDestroy): Avoid redundant free. > (phypVolumeLookupByPath, phypVolumeGetPath): Use consistent > naming. > --- > ?src/phyp/phyp_driver.c | ? 37 +++++++++++++++++-------------------- > ?1 files changed, 17 insertions(+), 20 deletions(-) > ACK. Matthias From eblake at redhat.com Fri Apr 15 20:33:30 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 14:33:30 -0600 Subject: [libvirt] [PATCH 1/2] virsh: list required options first In-Reply-To: <20110415202633.GB7230@orkuz.home> References: <4DA4C473.9000908@redhat.com> <1302644107-22840-2-git-send-email-eblake@redhat.com> <20110415202633.GB7230@orkuz.home> Message-ID: <4DA8AB9A.309@redhat.com> On 04/15/2011 02:26 PM, Jiri Denemark wrote: > On Tue, Apr 12, 2011 at 15:35:06 -0600, Eric Blake wrote: >> The current state of virsh parsing is that: >> >> all lookup the volume by path (technically, the last two also attempt >> a name lookup within a pool, whereas the first skips that step, but >> the end result is the same); meanwhile: > > Is example virsh command line missing here? Aargh. I wrote my commit message by using sample command prompts: # virsh ... But # is a comment character, and ate my message (and now I don't remember it off the top of my head). I'll have to figure that out again, and use $ prompts instead... >> * tools/virsh.c (opts_vol_create_from, opts_vol_clone) >> (opts_vol_upload, opts_vol_download, opts_vol_delete) >> (opts_vol_wipe, opts_vol_info, opts_vol_dumpxml, opts_vol_key) >> (opts_vol_path): List optional pool parameter after required >> arguments. >> --- >> tools/virsh.c | 20 ++++++++++---------- >> 1 files changed, 10 insertions(+), 10 deletions(-) > > Makes sense. I went through all virsh.c and didn't find more options that > would need fixing. The only options which don't follow this "optional after > required" rule are bool options which can safely stay where they are. > > ACK The review would have been much easier with a non-broken commit message, but you caught on to my drift. I'll post my revised commit message once I remember what it was... -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Fri Apr 15 20:56:19 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 15 Apr 2011 22:56:19 +0200 Subject: [libvirt] [PATCHv2 8/9] phyp: avoid memory leaks in command values In-Reply-To: <1302812555-3418-9-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-9-git-send-email-eblake@redhat.com> Message-ID: 2011/4/14 Eric Blake : > * src/phyp/phyp_driver.c (phypExecBuffer): New function. Use it > throughout file for less code, and for plugging a few leaks. > --- > > Amazing how much copy-and-paste code this consolidated. > > ?src/phyp/phyp_driver.c | ?803 ++++++------------------------------------------ > ?1 files changed, 92 insertions(+), 711 deletions(-) > > @@ -1823,17 +1706,8 @@ phypCreateServerSCSIAdapter(virConnectPtr conn) > ? ? virBufferVSprintf(&buf, " -r prof -i 'name=%s,lpar_id=%d," > ? ? ? ? ? ? ? ? ? ? ? "\"virtual_scsi_adapters=%s,%d/server/any/any/1\"'", > ? ? ? ? ? ? ? ? ? ? ? vios_name, vios_id, ret, slot); > - ? ?if (virBufferError(&buf)) { > - ? ? ? ?virBufferFreeAndReset(&buf); > - ? ? ? ?virReportOOMError(); > - ? ? ? ?goto cleanup; > - ? ?} > - > - ? ?VIR_FREE(cmd); > ? ? VIR_FREE(ret); > - > - ? ?cmd = virBufferContentAndReset(&buf); > - ? ?ret = phypExec(session, cmd, &exit_status, conn); > + ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > > ? ? if (exit_status < 0 || ret == NULL) > ? ? ? ? goto cleanup; > @@ -1847,17 +1721,7 @@ phypCreateServerSCSIAdapter(virConnectPtr conn) > ? ? virBufferVSprintf(&buf, > ? ? ? ? ? ? ? ? ? ? ? " -p %s -o a -s %d -d 0 -a \"adapter_type=server\"", > ? ? ? ? ? ? ? ? ? ? ? vios_name, slot); > - ? ?if (virBufferError(&buf)) { > - ? ? ? ?virBufferFreeAndReset(&buf); > - ? ? ? ?virReportOOMError(); > - ? ? ? ?goto cleanup; > - ? ?} > - > - ? ?VIR_FREE(cmd); > - ? ?VIR_FREE(ret); Why are you killing the VIR_FREE(ret) here, in the hunk before you left it in. It's necessary here too. > - ? ?cmd = virBufferContentAndReset(&buf); > - ? ?ret = phypExec(session, cmd, &exit_status, conn); > + ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > > ? ? if (exit_status < 0 || ret == NULL) > ? ? ? ? goto cleanup; > @@ -2000,18 +1841,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) > > ? ? if (system_type == HMC) > ? ? ? ? virBufferAddChar(&buf, '\''); > - > - ? ?if (virBufferError(&buf)) { > - ? ? ? ?virBufferFreeAndReset(&buf); > - ? ? ? ?virReportOOMError(); > - ? ? ? ?goto cleanup; > - ? ?} > - > - ? ?VIR_FREE(cmd); > - ? ?VIR_FREE(ret); Same for this VIR_FREE(ret) here, removing it produces a leak, doesn't it. > - > - ? ?cmd = virBufferContentAndReset(&buf); > - ? ?ret = phypExec(session, cmd, &exit_status, conn); > + ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > > ? ? if (exit_status < 0 || ret == NULL) > ? ? ? ? goto cleanup; > @@ -2029,17 +1859,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) > ? ? virBufferVSprintf(&buf, > ? ? ? ? ? ? ? ? ? ? ? " slot_num,backing_device|grep %s|cut -d, -f1", > ? ? ? ? ? ? ? ? ? ? ? dev->data.disk->src); > - ? ?if (virBufferError(&buf)) { > - ? ? ? ?virBufferFreeAndReset(&buf); > - ? ? ? ?virReportOOMError(); > - ? ? ? ?goto cleanup; > - ? ?} > - > - ? ?VIR_FREE(cmd); > - ? ?VIR_FREE(ret); And this VIR_FREE(ret) needs to stay too. > - > - ? ?cmd = virBufferContentAndReset(&buf); > - ? ?ret = phypExec(session, cmd, &exit_status, conn); > + ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > > ? ? if (exit_status < 0 || ret == NULL) > ? ? ? ? goto cleanup; > @@ -2057,17 +1877,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) > ? ? ? ? ? ? ? ? ? ? ? " -r prof --filter lpar_ids=%d,profile_names=%s" > ? ? ? ? ? ? ? ? ? ? ? " -F virtual_scsi_adapters|sed -e 's/\"//g'", > ? ? ? ? ? ? ? ? ? ? ? vios_id, profile); > - ? ?if (virBufferError(&buf)) { > - ? ? ? ?virBufferFreeAndReset(&buf); > - ? ? ? ?virReportOOMError(); > - ? ? ? ?goto cleanup; > - ? ?} > - > - ? ?VIR_FREE(cmd); > - ? ?VIR_FREE(ret); And this VIR_FREE(ret) needs to stay too. > - > - ? ?cmd = virBufferContentAndReset(&buf); > - ? ?ret = phypExec(session, cmd, &exit_status, conn); > + ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > > ? ? if (exit_status < 0 || ret == NULL) > ? ? ? ? goto cleanup; > @@ -2083,17 +1893,8 @@ phypAttachDevice(virDomainPtr domain, const char *xml) > ? ? ? ? ? ? ? ? ? ? ? "\"virtual_scsi_adapters=%s,%d/client/%d/%s/0\"'", > ? ? ? ? ? ? ? ? ? ? ? domain_name, domain->id, ret, slot, > ? ? ? ? ? ? ? ? ? ? ? vios_id, vios_name); > - ? ?if (virBufferError(&buf)) { > - ? ? ? ?virBufferFreeAndReset(&buf); > - ? ? ? ?virReportOOMError(); > - ? ? ? ?goto cleanup; > - ? ?} > - > - ? ?VIR_FREE(cmd); > ? ? VIR_FREE(ret); This one is left in correctly. > - > - ? ?cmd = virBufferContentAndReset(&buf); > - ? ?ret = phypExec(session, cmd, &exit_status, conn); > + ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > > ? ? if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) > ? ? ? ? goto cleanup; > @@ -2107,17 +1908,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) > ? ? virBufferVSprintf(&buf, > ? ? ? ? ? ? ? ? ? ? ? " -p %s -o a -s %d -d 0 -a \"adapter_type=server\"", > ? ? ? ? ? ? ? ? ? ? ? domain_name, slot); > - ? ?if (virBufferError(&buf)) { > - ? ? ? ?virBufferFreeAndReset(&buf); > - ? ? ? ?virReportOOMError(); > - ? ? ? ?goto cleanup; > - ? ?} > - > - ? ?VIR_FREE(cmd); > - ? ?VIR_FREE(ret); But this VIR_FREE(ret) needs to stay. > - > - ? ?cmd = virBufferContentAndReset(&buf); > - ? ?ret = phypExec(session, cmd, &exit_status, conn); > + ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > > ? ? if (exit_status < 0 || ret == NULL) { > ? ? ? ? VIR_ERROR0(_ ACK, with that VIR_FREEs left in. Matthias From matthias.bolte at googlemail.com Fri Apr 15 21:01:55 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 15 Apr 2011 23:01:55 +0200 Subject: [libvirt] [PATCHv2 9/9] phyp: another simplification In-Reply-To: <1302812555-3418-10-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-10-git-send-email-eblake@redhat.com> Message-ID: 2011/4/14 Eric Blake : > Rather than copying and pasting lots of code, factor it into a > single helper function. > > * src/phyp/phyp_driver.c (phypExecInt): New function. > (phypGetVIOSPartitionID, phypNumDomainsGeneric, phypGetLparID) > (phypGetLparMem, phypGetLparCPUGeneric, phypGetRemoteSlot) > (phypGetVIOSNextSlotNumber, phypAttachDevice) > (phypGetStoragePoolSize, phypStoragePoolNumOfVolumes) > (phypNumOfStoragePools, phypInterfaceDestroy) > (phypInterfaceDefineXML, phypInterfaceLookupByName) > (phypInterfaceIsActive, phypNumOfInterfaces): Use it. > --- > ?src/phyp/phyp_driver.c | ?316 ++++++++++-------------------------------------- > ?1 files changed, 67 insertions(+), 249 deletions(-) > > diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c > index bc24b76..98d5cd6 100644 > --- a/src/phyp/phyp_driver.c > +++ b/src/phyp/phyp_driver.c > @@ -228,6 +228,26 @@ phypExecBuffer(LIBSSH2_SESSION *session, virBufferPtr buf, int *exit_status, > ? ? return ret; > ?} > > +/* Convenience wrapper function */ > +static int phypExecInt(LIBSSH2_SESSION *, virBufferPtr, virConnectPtr, int *) > + ? ?ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); > +static int > +phypExecInt(LIBSSH2_SESSION *session, virBufferPtr buf, virConnectPtr conn, > + ? ? ? ? ? ?int *result) > +{ > + ? ?char *str; > + ? ?int ret; > + > + ? ?str = phypExecBuffer(session, buf, &ret, conn, true); > + ? ?if (!str || ret) { > + ? ? ? ?VIR_FREE(str); > + ? ? ? ?return -1; > + ? ?} > + ? ?ret = virStrToLong_i(str, NULL, 10, result); You made the parsing stricter by passing NULL as second argument to virStrToLong_i. I don't expect it but this might be possible that this breaks the behavior of the driver. > + ? ?VIR_FREE(str); > + ? ?return ret; > +} > + The rest of the patch looks fine. Matthias From eblake at redhat.com Fri Apr 15 21:12:42 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 15:12:42 -0600 Subject: [libvirt] [PATCHv2 9/9] phyp: another simplification In-Reply-To: References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-10-git-send-email-eblake@redhat.com> Message-ID: <4DA8B4CA.5020909@redhat.com> On 04/15/2011 03:01 PM, Matthias Bolte wrote: >> + str = phypExecBuffer(session, buf, &ret, conn, true); >> + if (!str || ret) { >> + VIR_FREE(str); >> + return -1; >> + } >> + ret = virStrToLong_i(str, NULL, 10, result); > > You made the parsing stricter by passing NULL as second argument to > virStrToLong_i. I don't expect it but this might be possible that this > breaks the behavior of the driver. That was an intentional decision of mine (I guess I should have documented it better), since the rest of the code was getting the character after the parsed integer but doing nothing with it. In most cases, it was like the code _expected_ a newline after the integer (such as the output of a sed -c run, where that holds true), but wasn't enforcing that expectation. Should I modify the commit message and push with the newer strict behavior, or modify the code to keep the older relaxed behavior (but this time add a VIR_WARN if garbage is found after the parse)? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 15 21:25:01 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 15:25:01 -0600 Subject: [libvirt] [PATCHv9 1/4] libvirt/qemu - persistent modification of devices. In-Reply-To: <20110413114931.a3357044.kamezawa.hiroyu@jp.fujitsu.com> References: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> <20110413114931.a3357044.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4DA8B7AD.4010308@redhat.com> On 04/12/2011 08:49 PM, KAMEZAWA Hiroyuki wrote: > > Now, qemudDomainAttachDeviceFlags() and qemudDomainDetachDeviceFlags() > doesn't support VIR_DOMAIN_DEVICE_MODIFY_CONFIG. By this, virsh's > at(de)tatch-device --persistent cannot modify qemu config. > (Xen allows it.) > > This patch is a base patch for adding support of devices in > step by step manner. Following patches will add some device > support. > > Signed-off-by: KAMEZAWA Hiroyuki > > Changelog: v8->v9 > - removed unnecessary comments. It's taken quite a few iterations, but I've finally scheduled time to start reviewing it. > +static int qemuDomainModifyDevicePersistent(virDomainPtr dom, > + const char *xml, > + unsigned int attach, You missed one. You changed attach and detach, but not update. This parameter can usefully forward to all three types of updates. In fact, I think I'd like to go one further, and refactor things further before we start adding persistent devices. It seems like there are two steps in all three categories of functions - obtain the locks, then do the work. I like how you've factored things into one function that obtains the locks then forwards on to other functions that do the work. Furthermore, I don't see any reason why we can't support LIVE|CONFIG at once, provided we know for which devices we can make a successful CONFIG change. > + * When both of MODIFY_CONFIG and MODIFY_LIVE are passed at the same time, > + * return error for now. We should support this later. > + */ > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { > + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", > + _("cannot modify active domain and its definition " > + "at the same time.")); > + return -1; > + } You are right that it's not implemented yet, but no worse than what we already have, so it's not a regression. But I think it is doable, by rewriting this into one giant function: 1. obtain lock 2. if CURRENT, convert to LIVE or CONFIG 3. if LIVE but not active, error 4. if CONFIG but not persistent, error 5. if CONFIG call, make temporary vmdef and modify that, or quit if that device is not supported yet 6. if LIVE, make live modification; if that errors out, quit 7. if CONFIG, make temporary vmdef permanent (hopefully it succeeds, because we don't roll back the LIVE portion of LIVE|CONFIG) 8. clean up locks I'll propose a followup patch that tries to capture this idiom in code. > +static int qemudDomainAttachDeviceFlags(virDomainPtr dom, > + const char *xml, > + unsigned int flags) > +{ > + int ret = -1; > + > + virCheckFlags((VIR_DOMAIN_DEVICE_MODIFY_CONFIG | > + VIR_DOMAIN_DEVICE_MODIFY_LIVE), -1); This causes a change in behavior. Previously, we silently ignored VIR_DOMAIN_DEVICE_MODIFY_FORCE, now we error out. But overall, that's a good change (FORCE only made sense for ModifyDevice, not Attach), and it goes to show that we don't use virCheckFlags on nearly enough APIs. > + > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) > + ret = qemuDomainModifyDevicePersistent(dom, xml, 1, flags); > + else if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) > + ret = qemudDomainAttachDevice(dom, xml); For example, here your logic is wrong. You covered the CONFIG|LIVE case with qemuDomainModifyDevicePersistent (by erroring out), but you _don't_ cover the CURRENT case (which should be either CONFIG or LIVE). But to learn if the vm is active, you have to obtain the lock, and the way you've written this, you've already forwarded into one of the two routines. Rather, all the public entries should forward into the one giant helper routine which grabs the locks, checks the flags, then calls into the right callbacks. > @@ -4141,14 +4242,19 @@ cleanup: > > static int qemudDomainDetachDeviceFlags(virDomainPtr dom, > const char *xml, > - unsigned int flags) { > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > - qemuReportError(VIR_ERR_OPERATION_INVALID, > - "%s", _("cannot modify the persistent configuration of a domain")); > - return -1; > - } > + unsigned int flags) > +{ > + int ret = -1; > + > + virCheckFlags((VIR_DOMAIN_DEVICE_MODIFY_CONFIG | > + VIR_DOMAIN_DEVICE_MODIFY_LIVE), -1); Another change in noisily rejecting FORCE, but I think it's good. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 15 21:33:49 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 15:33:49 -0600 Subject: [libvirt] [PATCHv2 8/9] phyp: avoid memory leaks in command values In-Reply-To: References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-9-git-send-email-eblake@redhat.com> Message-ID: <4DA8B9BD.8080105@redhat.com> On 04/15/2011 02:56 PM, Matthias Bolte wrote: > 2011/4/14 Eric Blake : >> * src/phyp/phyp_driver.c (phypExecBuffer): New function. Use it >> throughout file for less code, and for plugging a few leaks. >> --- >> >> Amazing how much copy-and-paste code this consolidated. >> >> " -p %s -o a -s %d -d 0 -a \"adapter_type=server\"", >> vios_name, slot); >> - if (virBufferError(&buf)) { >> - virBufferFreeAndReset(&buf); >> - virReportOOMError(); >> - goto cleanup; >> - } >> - >> - VIR_FREE(cmd); >> - VIR_FREE(ret); > > Why are you killing the VIR_FREE(ret) here, in the hunk before you > left it in. It's necessary here too. Accident of rebasing. I had previously inserted VIR_FREE(ret) earlier in the function, before your patch to independently fix leaks of ret, and missed that my rebase was deleting your instances. > > ACK, with that VIR_FREEs left in. I've added those back in, and pushed 1-8. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jdenemar at redhat.com Fri Apr 15 21:35:45 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Fri, 15 Apr 2011 23:35:45 +0200 Subject: [libvirt] [PATCH 2/2] virsh: fix regression in parsing optional integer In-Reply-To: <1302644107-22840-3-git-send-email-eblake@redhat.com> References: <4DA4C473.9000908@redhat.com> <1302644107-22840-3-git-send-email-eblake@redhat.com> Message-ID: <20110415213544.GC7230@orkuz.home> On Tue, Apr 12, 2011 at 15:35:07 -0600, Eric Blake wrote: > Regression introduced in 0.8.5, commit c1564268. The command > 'virsh freecell 0' quit working when it changed from an optional > string to an optional integer. > > This patch introduces a slight change that specifying an option > twice is now detected as an error. > > * tools/virsh.c (vshCmddefGetData, vshCmddefGetOption) > (vshCommandCheckOpts): Alter parameters to use bitmaps. > (vshCmddefOptParse): New function. > (vshCommandParse): Update for better handling of positional > arguments. > (vshCmddefHelp): Allow unit tests to validate options. > --- > tools/virsh.c | 149 +++++++++++++++++++++++++++++++++++++++----------------- > 1 files changed, 104 insertions(+), 45 deletions(-) 100iI hate command line parsing in virsh. ^[ The code looks like it does what it's supposed to do and I guess we should be fine with the limit for 32 arguments for a single virsh command :-) If not, there's clearly something wrong about the command which would need more. ACK Jirka From jdenemar at redhat.com Fri Apr 15 21:37:47 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Fri, 15 Apr 2011 23:37:47 +0200 Subject: [libvirt] [PATCH 3/2] tests: test recent virsh option parsing changes In-Reply-To: <1302645660-26625-1-git-send-email-eblake@redhat.com> References: <1302644107-22840-1-git-send-email-eblake@redhat.com> <1302645660-26625-1-git-send-email-eblake@redhat.com> Message-ID: <20110415213747.GD7230@orkuz.home> On Tue, Apr 12, 2011 at 16:01:00 -0600, Eric Blake wrote: > * tests/virsh-optparse: New file. > * tests/Makefile.am (test_scripts): Use it. > --- > > Hmm, I'd better take my own advice and test this stuff :) > > tests/Makefile.am | 1 + > tests/virsh-optparse | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 71 insertions(+), 0 deletions(-) > create mode 100755 tests/virsh-optparse And you also introduce this test for option parsing, nice. ACK Jirka From eblake at redhat.com Fri Apr 15 21:55:51 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 15:55:51 -0600 Subject: [libvirt] [PATCH 1/2] virsh: list required options first In-Reply-To: <4DA8AB9A.309@redhat.com> References: <4DA4C473.9000908@redhat.com> <1302644107-22840-2-git-send-email-eblake@redhat.com> <20110415202633.GB7230@orkuz.home> <4DA8AB9A.309@redhat.com> Message-ID: <4DA8BEE7.5070109@redhat.com> On 04/15/2011 02:33 PM, Eric Blake wrote: >> Is example virsh command line missing here? > > Aargh. I wrote my commit message by using sample command prompts: > > # virsh ... > > But # is a comment character, and ate my message (and now I don't > remember it off the top of my head). I'll have to figure that out > again, and use $ prompts instead... > >> ACK > > The review would have been much easier with a non-broken commit message, > but you caught on to my drift. I'll post my revised commit message once > I remember what it was... Pushed with the following commit message: commit 6b75a1a5b0d10b42e3fd344b2067a176ee294f46 Author: Eric Blake Date: Tue Apr 12 14:58:02 2011 -0600 virsh: list required options first The current state of virsh parsing is that: $ virsh vol-info /path/to/image $ virsh vol-info --pool default /path/to/image $ virsh vol-info --pool default --vol /path/to/image all lookup the volume by path (technically, the last two also attempt a name lookup within a pool, whereas the first skips that step, but the end result is the same); meanwhile: $ virsh vol-info default /path/to/image complains about unexpected data. Why? Because the --pool option is optional, so default was parsed as the --vol argument, and /path/to/image.img doesn't match up with any remaining options that require an argument. For proof, note that: $ virsh vol-info default --vol /path/to/image complains about looking up 'default' - the parser mis-associated both arguments with --vol. Given the above, the only way to specify pool is with an explicit "--pool" argument (you can't specify it positionally). However, named arguments can appear in any order, so: $ virsh vol-info /path/to/image --pool default $ virsh vol-info --vol /path/to/image --pool default have also always worked. Therefore, this patch has no functional change on vol-info option parsing, but only on 'virsh help vol-info' synopsis layout. However, it also allows the next patch to 1) enforce that required options are always first (without this patch, the next patch would fail the testsuite), and 2) allow the user to omit the "--pool" argument. That is, the next patch makes it possible to do: $ virsh vol-info /path/to/image default which to date was not possible. * tools/virsh.c (opts_vol_create_from, opts_vol_clone) (opts_vol_upload, opts_vol_download, opts_vol_delete) (opts_vol_wipe, opts_vol_info, opts_vol_dumpxml, opts_vol_key) (opts_vol_path): List optional pool parameter after required arguments. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 15 22:17:41 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 16:17:41 -0600 Subject: [libvirt] [PATCH 2/2] virsh: fix regression in parsing optional integer In-Reply-To: <20110415213544.GC7230@orkuz.home> References: <4DA4C473.9000908@redhat.com> <1302644107-22840-3-git-send-email-eblake@redhat.com> <20110415213544.GC7230@orkuz.home> Message-ID: <4DA8C405.2020500@redhat.com> On 04/15/2011 03:35 PM, Jiri Denemark wrote: > On Tue, Apr 12, 2011 at 15:35:07 -0600, Eric Blake wrote: >> Regression introduced in 0.8.5, commit c1564268. The command >> 'virsh freecell 0' quit working when it changed from an optional >> string to an optional integer. >> >> This patch introduces a slight change that specifying an option >> twice is now detected as an error. >> >> * tools/virsh.c (vshCmddefGetData, vshCmddefGetOption) >> (vshCommandCheckOpts): Alter parameters to use bitmaps. >> (vshCmddefOptParse): New function. >> (vshCommandParse): Update for better handling of positional >> arguments. >> (vshCmddefHelp): Allow unit tests to validate options. >> --- >> tools/virsh.c | 149 +++++++++++++++++++++++++++++++++++++++----------------- >> 1 files changed, 104 insertions(+), 45 deletions(-) > > 100iI hate command line parsing in virsh. > ^[ Me too. But it should be a lot better now. > > The code looks like it does what it's supposed to do and I guess we should be > fine with the limit for 32 arguments for a single virsh command :-) If not, > there's clearly something wrong about the command which would need more. > > ACK I tweaked the commit message, then pushed: commit b9973f526cb12b8e3d751ed19fb071b4a54ea1c0 Author: Eric Blake Date: Tue Apr 12 14:42:59 2011 -0600 virsh: fix regression in parsing optional integer Regression introduced in 0.8.5, commit c1564268. The command 'virsh freecell 0' quit working when it changed from an optional string to an optional integer. This patch introduces a slight change that specifying an option twice is now detected as an error. It also changes things so that a command that has more than 1 required option will not complain about missing options if one but not all of the options were given in long format, as in 'virsh vol-create --pool p file', as well as making positional parsing work for all optional options (each positional argument is associated with the earliest option that has not yet been seen by name). Optional boolean options can appear before required argument options, because they don't affect positional argument parsing, and obviously a required boolean option makes no sense. Technically, this patch renders VSH_OT_STRING and VSH_OT_DATA redundant; but cleaning that up can be a separate patch. No command should ever need more than 32 options, right? :) * tools/virsh.c (vshCmddefGetData, vshCmddefGetOption) (vshCommandCheckOpts): Alter parameters to use bitmaps. (vshCmddefOptParse): New function. (vshCommandParse): Update for better handling of positional arguments. (vshCmddefHelp): Allow unit tests to validate options. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 15 22:18:40 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 16:18:40 -0600 Subject: [libvirt] [PATCH 3/2] tests: test recent virsh option parsing changes In-Reply-To: <20110415213747.GD7230@orkuz.home> References: <1302644107-22840-1-git-send-email-eblake@redhat.com> <1302645660-26625-1-git-send-email-eblake@redhat.com> <20110415213747.GD7230@orkuz.home> Message-ID: <4DA8C440.9010608@redhat.com> On 04/15/2011 03:37 PM, Jiri Denemark wrote: > On Tue, Apr 12, 2011 at 16:01:00 -0600, Eric Blake wrote: >> * tests/virsh-optparse: New file. >> * tests/Makefile.am (test_scripts): Use it. >> --- >> >> Hmm, I'd better take my own advice and test this stuff :) >> >> tests/Makefile.am | 1 + >> tests/virsh-optparse | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 71 insertions(+), 0 deletions(-) >> create mode 100755 tests/virsh-optparse > > And you also introduce this test for option parsing, nice. > > ACK Thanks; pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 15 22:31:15 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 15 Apr 2011 16:31:15 -0600 Subject: [libvirt] [PATCH] tests: Unit tests for internal hash APIs In-Reply-To: References: <20110413111532.GB18468@redhat.com> Message-ID: <4DA8C733.3090005@redhat.com> On 04/15/2011 02:04 PM, Jiri Denemark wrote: > This is a basic set of tests for testing removals of hash entries during > iteration. > --- > More tests for all other hash APIs will come on Monday. Such as a test that gets 8 collisions into a single bucket to force hash table growth, or a test of custom hasher/comparator functions? > > tests/Makefile.am | 8 +++- > tests/hashdata.h | 33 +++++++++++ > tests/hashtest.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 197 insertions(+), 1 deletions(-) > create mode 100644 tests/hashdata.h > create mode 100644 tests/hashtest.c > > +++ b/tests/hashdata.h > @@ -0,0 +1,33 @@ > +const char *uuids[] = { > +/* [ 46] */ "f17494ba-2353-4af0-b1ba-13680858edcc", > + "64ab4e78-1b6e-4b88-b47f-2def46c79a86", > + "f99b0d59-ecff-4cc6-a9d3-20159536edc8", > +/* [ 75] */ "e1bfa30f-bc0b-4a24-99ae-bed7f3f21a7b", > + "acda5fa0-58de-4e1e-aa65-2124d1e29c54", > +/* [ 76] */ "5f476c28-8f26-48e0-98de-85745fe2f304", Looks suspiciously like you used gdb to dump an existing hash structure on a machine with lots of VMs :) Works for me. > +static virHashTablePtr > +testHashInit(int size) > +{ > + virHashTablePtr hash; > + int i; > + > + if (!(hash = virHashCreate(size, NULL))) > + return NULL; > + > + /* entires are added in reverse order so that they will be linked in > + * collision list in the same order as in the uuids array We're abusing an an internal detail. So good to have the comment - if the test breaks because of another rewrite, but the only breakage is due to a different link order in each bucket, then I'm okay modifying the test at that point, and meanwhile it justifies our abuse (that is, no change needed). > +#define DO_TEST_DATA(name, cmd, data) \ > + DO_TEST_FULL(name "(" #data ")", \ > + cmd, \ > + testHash ## cmd ## data, \ > + testHashCount ## cmd ## data) > + > + DO_TEST_DATA("Remove in ForEach", RemoveForEach, Some); > + DO_TEST_DATA("Remove in ForEach", RemoveForEach, All); > + > + return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE; Looks like a good test; it certainly would have caught the previous bugs before the most recent hash.c fixes. ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Sat Apr 16 05:21:02 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 16 Apr 2011 07:21:02 +0200 Subject: [libvirt] [PATCH] build: include esx_vi.generated.* into dist file In-Reply-To: References: <4DA7B4D3.4060308@cn.fujitsu.com> Message-ID: 2011/4/15 Matthias Bolte : > 2011/4/15 Wen Congyang : >> commit d4601696 introduces two more generated files: esx_vi.generated.h >> and esx_vi.generated.h. But we do not include them into dist file. >> It will break building if using dist file to build. >> >> --- >> ?src/Makefile.am | ? ?4 +++- >> ?1 files changed, 3 insertions(+), 1 deletions(-) >> >> diff --git a/src/Makefile.am b/src/Makefile.am >> index dce866e..1eaa7d1 100644 >> --- a/src/Makefile.am >> +++ b/src/Makefile.am >> @@ -332,7 +332,9 @@ ESX_DRIVER_GENERATED = ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ >> ? ? ? ? ? ? ? ?esx/esx_vi_types.generated.typedef ? ? ? ? ? ? ? ? ? ? ?\ >> ? ? ? ? ? ? ? ?esx/esx_vi_types.generated.typeenum ? ? ? ? ? ? ? ? ? ? \ >> ? ? ? ? ? ? ? ?esx/esx_vi_types.generated.typetostring ? ? ? ? ? ? ? ? \ >> - ? ? ? ? ? ? ? esx/esx_vi_types.generated.typefromstring >> + ? ? ? ? ? ? ? esx/esx_vi_types.generated.typefromstring ? ? ? ? ? ? ? \ >> + ? ? ? ? ? ? ? esx/esx_vi.generated.c ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ >> + ? ? ? ? ? ? ? esx/esx_vi.generated.h >> >> ?ESX_DRIVER_EXTRA_DIST = ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ >> ? ? ? ? ? ? ? ?esx/README ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ >> -- >> 1.7.1 >> > > ACK. > > Matthias > I went ahead and pushed it. Matthias From DUBI at il.ibm.com Sat Apr 16 06:13:11 2011 From: DUBI at il.ibm.com (Zvi Dubitzky) Date: Sat, 16 Apr 2011 09:13:11 +0300 Subject: [libvirt] virsh memset In-Reply-To: <4DA882AF.8070803@redhat.com> References: <4DA882AF.8070803@redhat.com> Message-ID: Sorry , I refer to 'virsh memtune' . Do you know if it is working ok for any late combination of libvirt and libcgroup ( e.g libvirt-0.8.8 ) . I could not operate it ., thanks Zvi Dubitzky Email:dubi at il.ibm.com Eric Blake wrote on 15/04/2011 20:38:55: > From: Eric Blake > To: Zvi Dubitzky/Haifa/IBM at IBMIL > Cc: libvir-list at redhat.com > Date: 15/04/2011 20:39 > Subject: Re: [libvirt] virsh memset > > On 04/14/2011 06:04 AM, Zvi Dubitzky wrote: > > Hi > > > > Does anybody know if 'virsh memset' is working ok with its parameters > > with the late libvirt code > > (>= 0.8.8 )? With what libcgroup version ? > > 'virsh memset' doesn't depend on cgroups. It relies on the guest > honoring virtio ballooning requests. Guests like Fedora are wired to do > this out of the box, but not all guests support it. I'm not sure > whether the virtio drivers for Windows can do ballooning. If a guest > can't honor ballooning, then you can't change current memory at runtime; > however, with very recent git (0.9.1), 'virsh memset --persistent' can > be used to modify the persistent storage to affect the memory usage on > the next guest boot. > > Or are you referring to 'virsh memtune', which does indeed require > cgroup support, but does not require any guest interaction? > > -- > Eric Blake eblake at redhat.com +1-801-349-2682 > Libvirt virtualization library http://libvirt.org > > [attachment "signature.asc" deleted by Zvi Dubitzky/Haifa/IBM] From matthias.bolte at googlemail.com Sat Apr 16 06:18:16 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 16 Apr 2011 08:18:16 +0200 Subject: [libvirt] [PATCHv2 9/9] phyp: another simplification In-Reply-To: <1302812555-3418-10-git-send-email-eblake@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-10-git-send-email-eblake@redhat.com> Message-ID: 2011/4/14 Eric Blake : > Rather than copying and pasting lots of code, factor it into a > single helper function. > > * src/phyp/phyp_driver.c (phypExecInt): New function. > (phypGetVIOSPartitionID, phypNumDomainsGeneric, phypGetLparID) > (phypGetLparMem, phypGetLparCPUGeneric, phypGetRemoteSlot) > (phypGetVIOSNextSlotNumber, phypAttachDevice) > (phypGetStoragePoolSize, phypStoragePoolNumOfVolumes) > (phypNumOfStoragePools, phypInterfaceDestroy) > (phypInterfaceDefineXML, phypInterfaceLookupByName) > (phypInterfaceIsActive, phypNumOfInterfaces): Use it. > --- > ?src/phyp/phyp_driver.c | ?316 ++++++++++-------------------------------------- > ?1 files changed, 67 insertions(+), 249 deletions(-) Okay lets take a look at each instance if stricter parsing is safe or not. > @@ -267,17 +284,7 @@ phypGetVIOSPartitionID(virConnectPtr conn) > ? ? ? ? virBufferVSprintf(&buf, " -m %s", managed_system); > ? ? virBufferAddLit(&buf, " -r lpar -F lpar_id,lpar_env" > ? ? ? ? ? ? ? ? ? ? "|sed -n '/vioserver/ {\n s/,.*$//\n p\n}'"); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &id) == -1) > - ? ? ? ?goto cleanup; > - > -cleanup: > - ? ?VIR_FREE(ret); > - > + ? ?phypExecInt(session, &buf, conn, &id); > ? ? return id; > ?} In this case I'm not sure that your change is safe. The executed command looks like it requests a table with two columns lpar_id,lpar_env and the uses some sed construct to pick the line that contains "vioserver". Then the lpar_id is parsed from the beginning of that line. I'm not sure that this sed construct just returns the number from the beginning of the line. If that is the case that your stricter parsing it safe. But it looks like that's not that case and ignoring content after the number in the selected line is important. > @@ -364,17 +368,7 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) > ? ? ? ? virBufferVSprintf(&buf, " -m %s", managed_system); > ? ? virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9]*'", > ? ? ? ? ? ? ? ? ? ? ? state); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &ndom) == -1) > - ? ? ? ?goto cleanup; > - > -cleanup: > - ? ?VIR_FREE(ret); > - > + ? ?phypExecInt(session, &buf, conn, &ndom); > ? ? return ndom; > ?} Here the stricter parsing will be safe as the last grep returns a count. But I wonder about the last grep. I thought it would be there to count the number of lines that start with a number, but it doesn't work: $ printf "aa\n22\n33\n" | grep -c '^[0-9]*' 3 I expected it to print 2 here. $ printf "aa\n22\n33\n\n" | grep -c '^[0-9]*' 4 So the '^[0-9]*' pattern matches every line. But $ printf "aa\n22\n33\n\n" | grep -c '^[0-9]+' 0 So the last grep here is just a wc -l. > @@ -1298,27 +1292,14 @@ phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system, > ?{ > ? ? phyp_driverPtr phyp_driver = conn->privateData; > ? ? int system_type = phyp_driver->system_type; > - ? ?int exit_status = 0; > ? ? int lpar_id = -1; > - ? ?char *char_ptr; > - ? ?char *ret = NULL; > ? ? virBuffer buf = VIR_BUFFER_INITIALIZER; > > ? ? virBufferAddLit(&buf, "lssyscfg -r lpar"); > ? ? if (system_type == HMC) > ? ? ? ? virBufferVSprintf(&buf, " -m %s", managed_system); > ? ? virBufferVSprintf(&buf, " --filter lpar_names=%s -F lpar_id", name); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) > - ? ? ? ?goto cleanup; > - > -cleanup: > - ? ?VIR_FREE(ret); > - > + ? ?phypExecInt(session, &buf, conn, &lpar_id); > ? ? return lpar_id; > ?} This one is safe too, as the requested output is just the lpar_id. > @@ -1397,17 +1375,7 @@ phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id, > ? ? virBufferVSprintf(&buf, > ? ? ? ? ? ? ? ? ? ? ? " -r mem --level lpar -F %s --filter lpar_ids=%d", > ? ? ? ? ? ? ? ? ? ? ? type ? "curr_mem" : "curr_max_mem", lpar_id); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &memory) == -1) > - ? ? ? ?goto cleanup; > - > -cleanup: > - ? ?VIR_FREE(ret); > - > + ? ?phypExecInt(session, &buf, conn, &memory); > ? ? return memory; > ?} This one is safe too, as the requested output is just the curr_mem or curr_max_mem. > @@ -1431,17 +1396,7 @@ phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system, > ? ? virBufferVSprintf(&buf, > ? ? ? ? ? ? ? ? ? ? ? " -r proc --level lpar -F %s --filter lpar_ids=%d", > ? ? ? ? ? ? ? ? ? ? ? type ? "curr_max_procs" : "curr_procs", lpar_id); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &vcpus) == -1) > - ? ? ? ?goto cleanup; > - > -cleanup: > - ? ?VIR_FREE(ret); > - > + ? ?phypExecInt(session, &buf, conn, &vcpus); > ? ? return vcpus; > ?} Safe too. > @@ -1491,17 +1443,7 @@ phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, > ? ? ? ? virBufferVSprintf(&buf, " -m %s", managed_system); > ? ? virBufferVSprintf(&buf, " -r virtualio --rsubtype scsi -F " > ? ? ? ? ? ? ? ? ? ? ? "remote_slot_num --filter lpar_names=%s", lpar_name); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &remote_slot) == -1) > - ? ? ? ?goto cleanup; > - > -cleanup: > - ? ?VIR_FREE(ret); > - > + ? ?phypExecInt(session, &buf, conn, &remote_slot); > ? ? return remote_slot; > ?} Safe too. > @@ -1632,21 +1571,9 @@ phypGetVIOSNextSlotNumber(virConnectPtr conn) > ? ? ? ? ? ? ? ? ? ? ? "virtual_serial_adapters|sed -e 's/\"//g' -e " > ? ? ? ? ? ? ? ? ? ? ? "'s/,/\\n/g'|sed -e 's/\\(^[0-9][0-9]\\*\\).*$/\\1/'" > ? ? ? ? ? ? ? ? ? ? ? "|sort|tail -n 1", profile); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) > - ? ? ? ?goto cleanup; > - > - ? ?slot += 1; > - > -cleanup: > - ? ?VIR_FREE(profile); > - ? ?VIR_FREE(ret); > - > - ? ?return slot; > + ? ?if (phypExecInt(session, &buf, conn, &slot) < 0) > + ? ? ? ?return -1; > + ? ?return slot + 1; > ?} Chain of seds transform line of comma separated items into a list of \n separated items, then strips the trailing non-number part of each item. Finally sorts the list and takes the last number. This makes the stricter parsing safe. > @@ -1859,12 +1785,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) > ? ? virBufferVSprintf(&buf, > ? ? ? ? ? ? ? ? ? ? ? " slot_num,backing_device|grep %s|cut -d, -f1", > ? ? ? ? ? ? ? ? ? ? ? dev->data.disk->src); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) > + ? ?if (phypExecInt(session, &buf, conn, &slot) < 0) > ? ? ? ? goto cleanup; The cut -d, -f1 makes stricter parsing safe here. > @@ -1893,10 +1814,7 @@ phypAttachDevice(virDomainPtr domain, const char *xml) > ? ? ? ? ? ? ? ? ? ? ? "\"virtual_scsi_adapters=%s,%d/client/%d/%s/0\"'", > ? ? ? ? ? ? ? ? ? ? ? domain_name, domain->id, ret, slot, > ? ? ? ? ? ? ? ? ? ? ? vios_id, vios_name); > - ? ?VIR_FREE(ret); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) > + ? ?if (phypExecInt(session, &buf, conn, &slot) < 0) > ? ? ? ? goto cleanup; There is no filtering of the output before parsing it here. Therefore, I'm not sure that stricter parsing is safe here. > @@ -2016,17 +1931,7 @@ phypGetStoragePoolSize(virConnectPtr conn, char *name) > ? ? ? ? virBufferAddChar(&buf, '\''); > > ? ? virBufferVSprintf(&buf, "|sed '1d; s/ //g'"); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &sp_size) == -1) > - ? ? ? ?goto cleanup; > - > -cleanup: > - ? ?VIR_FREE(ret); > - > + ? ?phypExecInt(session, &buf, conn, &sp_size); > ? ? return sp_size; > ?} Here the stricter parsing might be unsafe. > @@ -2530,21 +2432,11 @@ phypStoragePoolNumOfVolumes(virStoragePoolPtr pool) > ? ? if (system_type == HMC) > ? ? ? ? virBufferAddChar(&buf, '\''); > ? ? virBufferVSprintf(&buf, "|grep -c '^.*$'"); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &nvolumes) == -1) > - ? ? ? ?goto cleanup; > + ? ?if (phypExecInt(session, &buf, conn, &nvolumes) < 0) > + ? ? ? ?return -1; Here it's safe because of grep -c, that could be replaced by wc -l, as it doesn't have a specific pattern. > @@ -2650,17 +2539,7 @@ phypNumOfStoragePools(virConnectPtr conn) > ? ? ? ? virBufferAddChar(&buf, '\''); > > ? ? virBufferVSprintf(&buf, "|grep -c '^.*$'"); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &nsp) == -1) > - ? ? ? ?goto cleanup; > - > -cleanup: > - ? ?VIR_FREE(ret); > - > + ? ?phypExecInt(session, &buf, conn, &nsp); > ? ? return nsp; > ?} Safe because of grep -c. > @@ -2898,17 +2776,10 @@ phypInterfaceDestroy(virInterfacePtr iface, > ? ? ? ? ? ? ? ? ? ? ? " -r virtualio --rsubtype eth --level lpar " > ? ? ? ? ? ? ? ? ? ? ? " -F mac_addr,slot_num|" > ? ? ? ? ? ? ? ? ? ? ? " sed -n '/%s/ s/^.*,//p'", iface->mac); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &slot_num) == -1) > + ? ?if (phypExecInt(session, &buf, iface->conn, &slot_num) < 0) > ? ? ? ? goto cleanup; The final sed makes stricter parsing safe here. > @@ -2917,17 +2788,10 @@ phypInterfaceDestroy(virInterfacePtr iface, > ? ? ? ? ? ? ? ? ? ? ? " -r virtualio --rsubtype eth --level lpar " > ? ? ? ? ? ? ? ? ? ? ? " -F mac_addr,lpar_id|" > ? ? ? ? ? ? ? ? ? ? ? " sed -n '/%s/ s/^.*,//p'", iface->mac); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) > + ? ?if (phypExecInt(session, &buf, iface->conn, &lpar_id) < 0) > ? ? ? ? goto cleanup; Safe too. > @@ -2980,20 +2843,13 @@ phypInterfaceDefineXML(virConnectPtr conn, const char *xml, > ? ? ? ? ? ? ? ? ? ? ? " -r virtualio --rsubtype slot --level slot" > ? ? ? ? ? ? ? ? ? ? ? " -Fslot_num --filter lpar_names=%s" > ? ? ? ? ? ? ? ? ? ? ? " |sort|tail -n 1", def->name); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) > + ? ?if (phypExecInt(session, &buf, conn, &slot) < 0) > ? ? ? ? goto cleanup; Safe because of -Fslot_num. > @@ -3094,17 +2949,10 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) > ? ? ? ? ? ? ? ? ? ? ? " -r virtualio --rsubtype slot --level slot " > ? ? ? ? ? ? ? ? ? ? ? " -F drc_name,slot_num |" > ? ? ? ? ? ? ? ? ? ? ? " sed -n '/%s/ s/^.*,//p'", name); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &slot) == -1) > + ? ?if (phypExecInt(session, &buf, conn, &slot) < 0) > ? ? ? ? goto cleanup; Safe too because of the last sed. > ? ? ? ? virBufferVSprintf(&buf, "-m %s ", managed_system); > @@ -3113,12 +2961,7 @@ phypInterfaceLookupByName(virConnectPtr conn, const char *name) > ? ? ? ? ? ? ? ? ? ? ? " -r virtualio --rsubtype slot --level slot " > ? ? ? ? ? ? ? ? ? ? ? " -F drc_name,lpar_id |" > ? ? ? ? ? ? ? ? ? ? ? " sed -n '/%s/ s/^.*,//p'", name); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &lpar_id) == -1) > + ? ?if (phypExecInt(session, &buf, conn, &lpar_id) < 0) > ? ? ? ? goto cleanup; Again, safe too because of the last sed. > @@ -3167,16 +3006,7 @@ phypInterfaceIsActive(virInterfacePtr iface) > ? ? ? ? ? ? ? ? ? ? ? " -r virtualio --rsubtype eth --level lpar " > ? ? ? ? ? ? ? ? ? ? ? " -F mac_addr,state |" > ? ? ? ? ? ? ? ? ? ? ? " sed -n '/%s/ s/^.*,//p'", iface->mac); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &state) == -1) > - ? ? ? ?goto cleanup; > - > -cleanup: > - ? ?VIR_FREE(ret); > + ? ?phypExecInt(session, &buf, iface->conn, &state); > ? ? return state; > ?} Again, safe too because of the last sed. > @@ -3260,16 +3087,7 @@ phypNumOfInterfaces(virConnectPtr conn) > ? ? virBufferVSprintf(&buf, > ? ? ? ? ? ? ? ? ? ? ? "-r virtualio --rsubtype eth --level lpar|" > ? ? ? ? ? ? ? ? ? ? ? "grep -v lpar_id=%d|grep -c lpar_name", vios_id); > - ? ?ret = phypExecBuffer(session, &buf, &exit_status, conn, false); > - > - ? ?if (exit_status < 0 || ret == NULL) > - ? ? ? ?goto cleanup; > - > - ? ?if (virStrToLong_i(ret, &char_ptr, 10, &nnets) == -1) > - ? ? ? ?goto cleanup; > - > -cleanup: > - ? ?VIR_FREE(ret); > + ? ?phypExecInt(session, &buf, conn, &nnets); > ? ? return nnets; > ?} Safe because of grep -c. In most cases we can see from the code that stricter parsing will be safe, but in some places I'm not sure. So, as long as you don't have a PHYP system at hand to really test it, I'd suggest that we stick to the relaxed parsing. Matthias From matthias.bolte at googlemail.com Sat Apr 16 06:20:41 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 16 Apr 2011 08:20:41 +0200 Subject: [libvirt] [PATCHv2 9/9] phyp: another simplification In-Reply-To: <4DA8B4CA.5020909@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-10-git-send-email-eblake@redhat.com> <4DA8B4CA.5020909@redhat.com> Message-ID: 2011/4/15 Eric Blake : > On 04/15/2011 03:01 PM, Matthias Bolte wrote: >>> + ? ?str = phypExecBuffer(session, buf, &ret, conn, true); >>> + ? ?if (!str || ret) { >>> + ? ? ? ?VIR_FREE(str); >>> + ? ? ? ?return -1; >>> + ? ?} >>> + ? ?ret = virStrToLong_i(str, NULL, 10, result); >> >> You made the parsing stricter by passing NULL as second argument to >> virStrToLong_i. I don't expect it but this might be possible that this >> breaks the behavior of the driver. > > That was an intentional decision of mine (I guess I should have > documented it better), since the rest of the code was getting the > character after the parsed integer but doing nothing with it. ?In most > cases, it was like the code _expected_ a newline after the integer (such > as the output of a sed -c run, where that holds true), but wasn't > enforcing that expectation. > > Should I modify the commit message and push with the newer strict > behavior, or modify the code to keep the older relaxed behavior (but > this time add a VIR_WARN if garbage is found after the parse)? > See my other mail in this thread for a detailed analysis. Yes, lets stick to the relaxed parsing and add a VIR_WARN. Matthias From matthias.bolte at googlemail.com Sat Apr 16 08:32:43 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 16 Apr 2011 10:32:43 +0200 Subject: [libvirt] [PATCH v2] Remove virConnectPtr from virRaiseErrorFull Message-ID: <20110416083243.GA9352@sbox> And from all related macros and functions. --- I posted v1 a year ago :) https://www.redhat.com/archives/libvir-list/2010-April/msg00164.html src/conf/cpu_conf.c | 2 +- src/conf/domain_conf.c | 2 +- src/conf/domain_event.c | 2 +- src/conf/interface_conf.c | 2 +- src/conf/network_conf.c | 2 +- src/conf/node_device_conf.h | 2 +- src/conf/nwfilter_conf.h | 6 ++-- src/conf/secret_conf.h | 2 +- src/conf/storage_conf.h | 2 +- src/cpu/cpu.h | 2 +- src/datatypes.c | 2 +- src/esx/esx_private.h | 2 +- src/esx/esx_vi.h | 2 +- src/fdstream.c | 2 +- src/interface/netcf_driver.c | 2 +- src/internal.h | 3 +- src/libvirt-qemu.c | 4 +- src/libvirt.c | 26 +++++++++--------- src/libxl/libxl_conf.h | 2 +- src/lxc/lxc_conf.h | 2 +- src/lxc/veth.c | 2 +- src/network/bridge_driver.c | 2 +- src/nodeinfo.c | 2 +- src/openvz/openvz_conf.h | 2 +- src/phyp/phyp_driver.c | 2 +- src/qemu/qemu_conf.h | 2 +- src/remote/remote_driver.c | 11 +++----- src/security/security_manager.h | 2 +- src/test/test_driver.c | 2 +- src/uml/uml_conf.h | 2 +- src/util/command.c | 2 +- src/util/conf.c | 4 +- src/util/event_poll.c | 2 +- src/util/hooks.c | 2 +- src/util/hostusb.c | 2 +- src/util/interface.c | 2 +- src/util/iptables.c | 2 +- src/util/json.c | 2 +- src/util/macvtap.c | 2 +- src/util/network.c | 2 +- src/util/pci.c | 2 +- src/util/sexpr.c | 4 +- src/util/stats_linux.c | 2 +- src/util/sysinfo.c | 2 +- src/util/util.c | 2 +- src/util/virterror.c | 14 +++------ src/util/virterror_internal.h | 13 ++++----- src/util/xml.c | 2 +- src/vbox/vbox_driver.c | 2 +- src/vbox/vbox_tmpl.c | 2 +- src/vmware/vmware_conf.h | 2 +- src/vmx/vmx.c | 2 +- src/xen/block_stats.c | 57 +++++++++++++++++++-------------------- src/xen/block_stats.h | 2 +- src/xen/xen_driver.c | 2 +- src/xen/xen_hypervisor.c | 6 ++-- src/xen/xen_inotify.c | 2 +- src/xen/xend_internal.c | 2 +- src/xen/xm_internal.c | 2 +- src/xen/xs_internal.c | 2 +- src/xenapi/xenapi_driver.c | 2 +- src/xenapi/xenapi_utils.c | 4 +- src/xenxs/xenxs_private.h | 2 +- 63 files changed, 122 insertions(+), 132 deletions(-) diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index 7f03eaa..ad49916 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -32,7 +32,7 @@ #define VIR_FROM_THIS VIR_FROM_CPU #define virCPUReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_CPU, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_CPU, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) VIR_ENUM_IMPL(virCPUMatch, VIR_CPU_MATCH_LAST, diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index c827ef5..6b733d4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -415,7 +415,7 @@ VIR_ENUM_IMPL(virDomainTimerMode, VIR_DOMAIN_TIMER_MODE_LAST, "smpsafe"); #define virDomainReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_DOMAIN, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_DOMAIN, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define VIR_DOMAIN_XML_WRITE_FLAGS VIR_DOMAIN_XML_SECURE diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index 5f086bd..f0380d3 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -32,7 +32,7 @@ #define VIR_FROM_THIS VIR_FROM_NONE #define eventReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) struct _virDomainMeta { diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index b24526f..2fa2fa0 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -46,7 +46,7 @@ virInterfaceDefDevFormat(virBufferPtr buf, const virInterfaceDefPtr def, int level); #define virInterfaceReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_INTERFACE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_INTERFACE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) static diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index dcab9de..5738757 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -53,7 +53,7 @@ VIR_ENUM_IMPL(virNetworkForward, "none", "nat", "route" ) #define virNetworkReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NETWORK, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NETWORK, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjListPtr nets, diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index fe0f2bf..975abb3 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -219,7 +219,7 @@ struct _virDeviceMonitorState { }; # define virNodeDeviceReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NODEDEV, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NODEDEV, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) int virNodeDeviceHasCap(const virNodeDeviceObjPtr dev, const char *cap); diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h index 9281f56..12e2a5c 100644 --- a/src/conf/nwfilter_conf.h +++ b/src/conf/nwfilter_conf.h @@ -647,9 +647,9 @@ void virNWFilterUnlockFilterUpdates(void); int virNWFilterConfLayerInit(virHashIterator domUpdateCB); void virNWFilterConfLayerShutdown(void); -# define virNWFilterReportError(code, fmt...) \ - virReportErrorHelper(NULL, VIR_FROM_NWFILTER, code, __FILE__, \ - __FUNCTION__, __LINE__, fmt) +# define virNWFilterReportError(code, fmt...) \ + virReportErrorHelper(VIR_FROM_NWFILTER, code, __FILE__, \ + __FUNCTION__, __LINE__, fmt) typedef int (*virNWFilterRebuild)(virConnectPtr conn, diff --git a/src/conf/secret_conf.h b/src/conf/secret_conf.h index 66294ce..4b47c52 100644 --- a/src/conf/secret_conf.h +++ b/src/conf/secret_conf.h @@ -27,7 +27,7 @@ # include "util.h" # define virSecretReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_SECRET, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_SECRET, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) VIR_ENUM_DECL(virSecretUsageType) diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index 9e1f534..271441a 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -324,7 +324,7 @@ static inline int virStoragePoolObjIsActive(virStoragePoolObjPtr pool) { } # define virStorageReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_STORAGE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_STORAGE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) int virStoragePoolLoadAllConfigs(virStoragePoolObjListPtr pools, diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 76d0e8e..9f01f17 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -31,7 +31,7 @@ # define virCPUReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_CPU, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_CPU, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) diff --git a/src/datatypes.c b/src/datatypes.c index 3edd1ff..4c4cbd0 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -32,7 +32,7 @@ #define VIR_FROM_THIS VIR_FROM_NONE #define virLibConnError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) /************************************************************************ diff --git a/src/esx/esx_private.h b/src/esx/esx_private.h index 1da2552..7ce237e 100644 --- a/src/esx/esx_private.h +++ b/src/esx/esx_private.h @@ -29,7 +29,7 @@ # include "esx_vi.h" # define ESX_ERROR(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_ESX, code, __FILE__, __FUNCTION__, \ + virReportErrorHelper(VIR_FROM_ESX, code, __FILE__, __FUNCTION__, \ __LINE__, __VA_ARGS__) typedef struct _esxPrivate { diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index 560b2a6..75469ab 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -36,7 +36,7 @@ # define ESX_VI_ERROR(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_ESX, code, __FILE__, __FUNCTION__, \ + virReportErrorHelper(VIR_FROM_ESX, code, __FILE__, __FUNCTION__, \ __LINE__, __VA_ARGS__) diff --git a/src/fdstream.c b/src/fdstream.c index 3475bfd..d2325ae 100644 --- a/src/fdstream.c +++ b/src/fdstream.c @@ -45,7 +45,7 @@ #define VIR_FROM_THIS VIR_FROM_STREAMS #define streamsReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) /* Tunnelled migration stream support */ diff --git a/src/interface/netcf_driver.c b/src/interface/netcf_driver.c index 0217b90..0190bf4 100644 --- a/src/interface/netcf_driver.c +++ b/src/interface/netcf_driver.c @@ -34,7 +34,7 @@ #define VIR_FROM_THIS VIR_FROM_INTERFACE #define interfaceReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) /* Main driver state */ diff --git a/src/internal.h b/src/internal.h index 4641fc1..0fa097c 100644 --- a/src/internal.h +++ b/src/internal.h @@ -232,8 +232,7 @@ do { \ unsigned long __unsuppflags = flags & ~(supported); \ if (__unsuppflags) { \ - virReportErrorHelper(NULL, \ - VIR_FROM_THIS, \ + virReportErrorHelper(VIR_FROM_THIS, \ VIR_ERR_INVALID_ARG, \ __FILE__, \ __FUNCTION__, \ diff --git a/src/libvirt-qemu.c b/src/libvirt-qemu.c index d914ac8..46727c8 100644 --- a/src/libvirt-qemu.c +++ b/src/libvirt-qemu.c @@ -29,11 +29,11 @@ #include "libvirt/libvirt-qemu.h" #define virLibConnError(conn, error, info) \ - virReportErrorHelper(conn, VIR_FROM_NONE, error, NULL, __FUNCTION__, \ + virReportErrorHelper(VIR_FROM_NONE, error, NULL, __FUNCTION__, \ __LINE__, info) #define virLibDomainError(domain, error, info) \ - virReportErrorHelper(NULL, VIR_FROM_DOM, error, NULL, __FUNCTION__, \ + virReportErrorHelper(VIR_FROM_DOM, error, NULL, __FUNCTION__, \ __LINE__, info) int diff --git a/src/libvirt.c b/src/libvirt.c index 0da9885..9e6784b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -469,37 +469,37 @@ DllMain (HINSTANCE instance ATTRIBUTE_UNUSED, #endif #define virLibConnError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define virLibDomainError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_DOM, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_DOM, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define virLibNetworkError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NETWORK, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NETWORK, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define virLibStoragePoolError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_STORAGE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_STORAGE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define virLibStorageVolError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_STORAGE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_STORAGE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define virLibInterfaceError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_INTERFACE, code, __FILE__,\ + virReportErrorHelper(VIR_FROM_INTERFACE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define virLibNodeDeviceError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NODEDEV, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NODEDEV, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define virLibSecretError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_SECRET, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_SECRET, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define virLibStreamError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_STREAMS, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_STREAMS, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define virLibNWFilterError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NWFILTER, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NWFILTER, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) -#define virLibDomainSnapshotError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_DOMAIN_SNAPSHOT, code, __FILE__, \ +#define virLibDomainSnapshotError(code, ...) \ + virReportErrorHelper(VIR_FROM_DOMAIN_SNAPSHOT, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) @@ -1056,7 +1056,7 @@ do_open (const char *name, STRCASEEQ(ret->uri->scheme, "xenapi") || #endif false)) { - virReportErrorHelper(NULL, VIR_FROM_NONE, VIR_ERR_INVALID_ARG, + virReportErrorHelper(VIR_FROM_NONE, VIR_ERR_INVALID_ARG, __FILE__, __FUNCTION__, __LINE__, _("libvirt was built without the '%s' driver"), ret->uri->scheme); diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index f2f0d8a..8c87786 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -87,7 +87,7 @@ struct _libxlDomainObjPrivate { # define libxlError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_LIBXL, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_LIBXL, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) virCapsPtr diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h index f820d6d..4f1ead3 100644 --- a/src/lxc/lxc_conf.h +++ b/src/lxc/lxc_conf.h @@ -66,7 +66,7 @@ int lxcLoadDriverConfig(lxc_driver_t *driver); virCapsPtr lxcCapsInit(void); # define lxcError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_LXC, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_LXC, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #endif /* LXC_CONF_H */ diff --git a/src/lxc/veth.c b/src/lxc/veth.c index 26bf4ff..a00aa23 100644 --- a/src/lxc/veth.c +++ b/src/lxc/veth.c @@ -27,7 +27,7 @@ #define VIR_FROM_THIS VIR_FROM_LXC #define vethError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_LXC, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_LXC, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) /* Functions */ diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index f3952d4..8b5c1b6 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -70,7 +70,7 @@ #define VIR_FROM_THIS VIR_FROM_NETWORK #define networkReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NETWORK, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NETWORK, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) /* Main driver state */ diff --git a/src/nodeinfo.c b/src/nodeinfo.c index e1c9ad3..facac15 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -51,7 +51,7 @@ #define VIR_FROM_THIS VIR_FROM_NONE #define nodeReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #ifdef __linux__ diff --git a/src/openvz/openvz_conf.h b/src/openvz/openvz_conf.h index 4673fa6..9a57551 100644 --- a/src/openvz/openvz_conf.h +++ b/src/openvz/openvz_conf.h @@ -34,7 +34,7 @@ # include "threads.h" # define openvzError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_OPENVZ, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_OPENVZ, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index ae2ed70..8f8c3ba 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -65,7 +65,7 @@ #define VIR_FROM_THIS VIR_FROM_PHYP #define PHYP_ERROR(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_PHYP, code, __FILE__, __FUNCTION__, \ + virReportErrorHelper(VIR_FROM_PHYP, code, __FILE__, __FUNCTION__, \ __LINE__, __VA_ARGS__) /* diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 94918f6..f2bfa1e 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -146,7 +146,7 @@ struct _qemuDomainCmdlineDef { # define QEMUD_MIGRATION_NUM_PORTS 64 # define qemuReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_QEMU, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_QEMU, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index b979f71..e30780c 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -242,7 +242,7 @@ static int remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int #endif /* HAVE_POLKIT */ #define remoteError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_REMOTE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_REMOTE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain); @@ -8644,8 +8644,7 @@ remoteStreamHasError(virStreamPtr st) { } VIR_DEBUG0("Raising async error"); - virRaiseErrorFull(st->conn, - __FILE__, __FUNCTION__, __LINE__, + virRaiseErrorFull(__FILE__, __FUNCTION__, __LINE__, privst->err.domain, privst->err.code, privst->err.level, @@ -10908,8 +10907,7 @@ cleanup: * convert missing remote entry points into the unsupported * feature error */ - virRaiseErrorFull(flags & REMOTE_CALL_IN_OPEN ? NULL : conn, - __FILE__, __FUNCTION__, __LINE__, + virRaiseErrorFull(__FILE__, __FUNCTION__, __LINE__, thiscall->err.domain, VIR_ERR_NO_SUPPORT, thiscall->err.level, @@ -10921,8 +10919,7 @@ cleanup: "%s", *thiscall->err.message); rv = -1; } else { - virRaiseErrorFull(flags & REMOTE_CALL_IN_OPEN ? NULL : conn, - __FILE__, __FUNCTION__, __LINE__, + virRaiseErrorFull(__FILE__, __FUNCTION__, __LINE__, thiscall->err.domain, thiscall->err.code, thiscall->err.level, diff --git a/src/security/security_manager.h b/src/security/security_manager.h index 3f88801..8d7c220 100644 --- a/src/security/security_manager.h +++ b/src/security/security_manager.h @@ -24,7 +24,7 @@ # define VIR_SECURITY_MANAGER_H__ # define virSecurityReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_SECURITY, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_SECURITY, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 17f5ad9..0978214 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -117,7 +117,7 @@ static const virNodeInfo defaultNodeInfo = { #define testError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_TEST, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_TEST, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) static int testClose(virConnectPtr conn); diff --git a/src/uml/uml_conf.h b/src/uml/uml_conf.h index 64df5f7..1105f84 100644 --- a/src/uml/uml_conf.h +++ b/src/uml/uml_conf.h @@ -64,7 +64,7 @@ struct uml_driver { # define umlReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_UML, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_UML, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) virCapsPtr umlCapsInit (void); diff --git a/src/util/command.c b/src/util/command.c index 2e475a0..862a913 100644 --- a/src/util/command.c +++ b/src/util/command.c @@ -38,7 +38,7 @@ #define VIR_FROM_THIS VIR_FROM_NONE #define virCommandError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) enum { diff --git a/src/util/conf.c b/src/util/conf.c index 71a344f..4b8afb8 100644 --- a/src/util/conf.c +++ b/src/util/conf.c @@ -100,13 +100,13 @@ virConfError(virConfParserCtxtPtr ctxt, /* Construct the string 'filename:line: info' if we have that. */ if (ctxt && ctxt->filename) { - virRaiseError(NULL, NULL, NULL, VIR_FROM_CONF, error, VIR_ERR_ERROR, + virRaiseError(NULL, NULL, VIR_FROM_CONF, error, VIR_ERR_ERROR, info, ctxt->filename, NULL, ctxt->line, 0, "%s:%d: %s", ctxt->filename, ctxt->line, info); } else { format = virErrorMsg(error, info); - virRaiseError(NULL, NULL, NULL, VIR_FROM_CONF, error, VIR_ERR_ERROR, + virRaiseError(NULL, NULL, VIR_FROM_CONF, error, VIR_ERR_ERROR, info, NULL, NULL, ctxt ? ctxt->line : 0, 0, format, info); diff --git a/src/util/event_poll.c b/src/util/event_poll.c index cd1ff4a..c5eedd3 100644 --- a/src/util/event_poll.c +++ b/src/util/event_poll.c @@ -44,7 +44,7 @@ #define VIR_FROM_THIS VIR_FROM_EVENT #define virEventError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_EVENT, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_EVENT, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) static int virEventPollInterruptLocked(void); diff --git a/src/util/hooks.c b/src/util/hooks.c index 819c95c..a409d77 100644 --- a/src/util/hooks.c +++ b/src/util/hooks.c @@ -42,7 +42,7 @@ #define VIR_FROM_THIS VIR_FROM_HOOK #define virHookReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_HOOK, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_HOOK, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define LIBVIRT_HOOK_DIR SYSCONFDIR "/libvirt/hooks" diff --git a/src/util/hostusb.c b/src/util/hostusb.c index 2d6e414..d5b478b 100644 --- a/src/util/hostusb.c +++ b/src/util/hostusb.c @@ -55,7 +55,7 @@ struct _usbDevice { #define VIR_FROM_THIS VIR_FROM_NONE #define usbReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) static int usbSysReadFile(const char *f_name, const char *d_name, diff --git a/src/util/interface.c b/src/util/interface.c index fe58823..5e1987a 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -42,7 +42,7 @@ #include "files.h" #define ifaceError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NET, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NET, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #if __linux__ diff --git a/src/util/iptables.c b/src/util/iptables.c index 59f5cc7..76d412c 100644 --- a/src/util/iptables.c +++ b/src/util/iptables.c @@ -46,7 +46,7 @@ #define VIR_FROM_THIS VIR_FROM_NONE #define iptablesError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) enum { diff --git a/src/util/json.c b/src/util/json.c index be47f64..0daeae9 100644 --- a/src/util/json.c +++ b/src/util/json.c @@ -37,7 +37,7 @@ /* XXX fixme */ #define VIR_FROM_THIS VIR_FROM_NONE #define virJSONError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) diff --git a/src/util/macvtap.c b/src/util/macvtap.c index 346eaf6..a7af0cb 100644 --- a/src/util/macvtap.c +++ b/src/util/macvtap.c @@ -63,7 +63,7 @@ # define VIR_FROM_THIS VIR_FROM_NET # define macvtapError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NET, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NET, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) # define MACVTAP_NAME_PREFIX "macvtap" diff --git a/src/util/network.c b/src/util/network.c index 33028aa..eb16e0c 100644 --- a/src/util/network.c +++ b/src/util/network.c @@ -18,7 +18,7 @@ #define VIR_FROM_THIS VIR_FROM_NONE #define virSocketError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) /* diff --git a/src/util/pci.c b/src/util/pci.c index ff950d1..945f32a 100644 --- a/src/util/pci.c +++ b/src/util/pci.c @@ -82,7 +82,7 @@ struct _pciDeviceList { #define VIR_FROM_THIS VIR_FROM_NONE #define pciReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) /* Specifications referenced in comments: diff --git a/src/util/sexpr.c b/src/util/sexpr.c index da3d4b3..d6668f8 100644 --- a/src/util/sexpr.c +++ b/src/util/sexpr.c @@ -25,8 +25,8 @@ #define VIR_FROM_THIS VIR_FROM_SEXPR #define virSexprError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_SEXPR, code, __FILE__, \ - __FUNCTION__, __LINE__, __VA_ARGS__) + virReportErrorHelper(VIR_FROM_SEXPR, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) /** * sexpr_new: diff --git a/src/util/stats_linux.c b/src/util/stats_linux.c index 5397320..173cdc5 100644 --- a/src/util/stats_linux.c +++ b/src/util/stats_linux.c @@ -30,7 +30,7 @@ # define VIR_FROM_THIS VIR_FROM_STATS_LINUX # define virStatsError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) diff --git a/src/util/sysinfo.c b/src/util/sysinfo.c index 2b764ae..a865d25 100644 --- a/src/util/sysinfo.c +++ b/src/util/sysinfo.c @@ -41,7 +41,7 @@ #define VIR_FROM_THIS VIR_FROM_SYSINFO #define virSmbiosReportError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_SYSINFO, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_SYSINFO, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define SYSINFO_SMBIOS_DECODER "dmidecode" diff --git a/src/util/util.c b/src/util/util.c index 526f51c..d4d2610 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -89,7 +89,7 @@ verify(sizeof(gid_t) <= sizeof (unsigned int) && #define VIR_FROM_THIS VIR_FROM_NONE #define virUtilError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) /* Like read(), but restarts after EINTR */ diff --git a/src/util/virterror.c b/src/util/virterror.c index b7d8924..fbb4a45 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -663,7 +663,6 @@ virDispatchError(virConnectPtr conn) /** * virRaiseErrorFull: - * @conn: the connection to the hypervisor if available * @filename: filename where error was raised * @funcname: function name where error was raised * @linenr: line number where error was raised @@ -682,8 +681,7 @@ virDispatchError(virConnectPtr conn) * immediately if a callback is found and store it for later handling. */ void -virRaiseErrorFull(virConnectPtr conn ATTRIBUTE_UNUSED, - const char *filename ATTRIBUTE_UNUSED, +virRaiseErrorFull(const char *filename ATTRIBUTE_UNUSED, const char *funcname, size_t linenr, int domain, @@ -1214,7 +1212,6 @@ virErrorMsg(virErrorNumber error, const char *info) /** * virReportErrorHelper: * - * @conn: the connection to the hypervisor if available * @domcode: the virErrorDomain indicating where it's coming from * @errcode: the virErrorNumber code for the error * @filename: Source file error is dispatched from @@ -1226,8 +1223,7 @@ virErrorMsg(virErrorNumber error, const char *info) * Helper function to do most of the grunt work for individual driver * ReportError */ -void virReportErrorHelper(virConnectPtr conn, - int domcode, +void virReportErrorHelper(int domcode, int errcode, const char *filename, const char *funcname, @@ -1248,7 +1244,7 @@ void virReportErrorHelper(virConnectPtr conn, } virerr = virErrorMsg(errcode, (errorMessage[0] ? errorMessage : NULL)); - virRaiseErrorFull(conn, filename, funcname, linenr, + virRaiseErrorFull(filename, funcname, linenr, domcode, errcode, VIR_ERR_ERROR, virerr, errorMessage, NULL, -1, -1, virerr, errorMessage); @@ -1324,7 +1320,7 @@ void virReportSystemErrorFull(int domcode, if (!msgDetail) msgDetail = errnoDetail; - virRaiseErrorFull(NULL, filename, funcname, linenr, + virRaiseErrorFull(filename, funcname, linenr, domcode, VIR_ERR_SYSTEM_ERROR, VIR_ERR_ERROR, msg, msgDetail, NULL, -1, -1, msg, msgDetail); errno = save_errno; @@ -1348,7 +1344,7 @@ void virReportOOMErrorFull(int domcode, const char *virerr; virerr = virErrorMsg(VIR_ERR_NO_MEMORY, NULL); - virRaiseErrorFull(NULL, filename, funcname, linenr, + virRaiseErrorFull(filename, funcname, linenr, domcode, VIR_ERR_NO_MEMORY, VIR_ERR_ERROR, virerr, NULL, NULL, -1, -1, virerr, NULL); } diff --git a/src/util/virterror_internal.h b/src/util/virterror_internal.h index 8f32f41..df4b1d2 100644 --- a/src/util/virterror_internal.h +++ b/src/util/virterror_internal.h @@ -33,8 +33,7 @@ extern void *virUserData; * * ************************************************************************/ int virErrorInitialize(void); -void virRaiseErrorFull(virConnectPtr conn, - const char *filename, +void virRaiseErrorFull(const char *filename, const char *funcname, size_t linenr, int domain, @@ -46,22 +45,22 @@ void virRaiseErrorFull(virConnectPtr conn, int int1, int int2, const char *fmt, ...) - ATTRIBUTE_FMT_PRINTF(13, 14); + ATTRIBUTE_FMT_PRINTF(12, 13); /* Includes 'dom' and 'net' for compatbility, but they're ignored */ -# define virRaiseError(conn, dom, net, domain, code, level, \ +# define virRaiseError(dom, net, domain, code, level, \ str1, str2, str3, int1, int2, msg, ...) \ - virRaiseErrorFull(conn, __FILE__, __FUNCTION__, __LINE__, \ + virRaiseErrorFull(__FILE__, __FUNCTION__, __LINE__, \ domain, code, level, str1, str2, str3, int1, int2, \ msg, __VA_ARGS__) const char *virErrorMsg(virErrorNumber error, const char *info); -void virReportErrorHelper(virConnectPtr conn, int domcode, int errcode, +void virReportErrorHelper(int domcode, int errcode, const char *filename ATTRIBUTE_UNUSED, const char *funcname ATTRIBUTE_UNUSED, size_t linenr ATTRIBUTE_UNUSED, const char *fmt, ...) - ATTRIBUTE_FMT_PRINTF(7, 8); + ATTRIBUTE_FMT_PRINTF(6, 7); void virReportSystemErrorFull(int domcode, int theerrno, diff --git a/src/util/xml.c b/src/util/xml.c index 2c50e14..d2989e2 100644 --- a/src/util/xml.c +++ b/src/util/xml.c @@ -26,7 +26,7 @@ #define VIR_FROM_THIS VIR_FROM_XML #define virGenericReportError(from, code, ...) \ - virReportErrorHelper(NULL, from, code, __FILE__, \ + virReportErrorHelper(from, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define virXMLError(code, ...) \ diff --git a/src/vbox/vbox_driver.c b/src/vbox/vbox_driver.c index 9526ee4..fc43b8c 100644 --- a/src/vbox/vbox_driver.c +++ b/src/vbox/vbox_driver.c @@ -66,7 +66,7 @@ static virDriver vboxDriverDummy; #define VIR_FROM_THIS VIR_FROM_VBOX #define vboxError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_VBOX, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_VBOX, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) int vboxRegister(void) { diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 3ca34dd..8241d34 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -133,7 +133,7 @@ typedef IMediumAttachment IHardDiskAttachment; #endif /* VBOX_API_VERSION >= 3001 */ #define vboxError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_VBOX, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_VBOX, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define DEBUGPRUnichar(msg, strUtf16) \ diff --git a/src/vmware/vmware_conf.h b/src/vmware/vmware_conf.h index e47ce62..b6d9d60 100644 --- a/src/vmware/vmware_conf.h +++ b/src/vmware/vmware_conf.h @@ -31,7 +31,7 @@ # define PROGRAM_SENTINAL ((char *)0x1) # define vmwareError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_VMWARE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_VMWARE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) # define TYPE_PLAYER 0 diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c index b0d3218..daeedc3 100644 --- a/src/vmx/vmx.c +++ b/src/vmx/vmx.c @@ -471,7 +471,7 @@ def->parallels[0]... #define VIR_FROM_THIS VIR_FROM_NONE #define VMX_ERROR(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, __FUNCTION__, \ + virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, __FUNCTION__, \ __LINE__, __VA_ARGS__) #define VMX_BUILD_NAME_EXTRA(_suffix, _extra) \ diff --git a/src/xen/block_stats.c b/src/xen/block_stats.c index 1918257..a28212c 100644 --- a/src/xen/block_stats.c +++ b/src/xen/block_stats.c @@ -42,8 +42,7 @@ * Handle a stats error. */ static void -statsErrorFunc (virConnectPtr conn, - virErrorNumber error, const char *func, const char *info, +statsErrorFunc (virErrorNumber error, const char *func, const char *info, int value) { char fullinfo[1000]; @@ -55,7 +54,7 @@ statsErrorFunc (virConnectPtr conn, fullinfo[sizeof (fullinfo) - 1] = 0; info = fullinfo; } - virRaiseError(conn, NULL, NULL, VIR_FROM_STATS_LINUX, error, + virRaiseError(NULL, NULL, VIR_FROM_STATS_LINUX, error, VIR_ERR_ERROR, errmsg, info, NULL, value, 0, errmsg, info, value); @@ -180,8 +179,8 @@ check_bd_connected (xenUnifiedPrivatePtr priv, int device, int domid) } static int -read_bd_stats (virConnectPtr conn, xenUnifiedPrivatePtr priv, - int device, int domid, struct _virDomainBlockStats *stats) +read_bd_stats(xenUnifiedPrivatePtr priv, + int device, int domid, struct _virDomainBlockStats *stats) { stats->rd_req = read_bd_stat (device, domid, "rd_req"); stats->rd_bytes = read_bd_stat (device, domid, "rd_sect"); @@ -195,8 +194,8 @@ read_bd_stats (virConnectPtr conn, xenUnifiedPrivatePtr priv, if (stats->rd_req == -1 && stats->rd_bytes == -1 && stats->wr_req == -1 && stats->wr_bytes == -1 && stats->errs == -1) { - statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__, - "Failed to read any block statistics", domid); + statsErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__, + "Failed to read any block statistics", domid); return -1; } @@ -208,8 +207,8 @@ read_bd_stats (virConnectPtr conn, xenUnifiedPrivatePtr priv, stats->wr_req == 0 && stats->wr_bytes == 0 && stats->errs == 0 && !check_bd_connected (priv, device, domid)) { - statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__, - "Frontend block device not connected", domid); + statsErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__, + "Frontend block device not connected", domid); return -1; } @@ -218,18 +217,18 @@ read_bd_stats (virConnectPtr conn, xenUnifiedPrivatePtr priv, */ if (stats->rd_bytes > 0) { if (stats->rd_bytes >= ((unsigned long long)1)<<(63-9)) { - statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__, - "stats->rd_bytes would overflow 64 bit counter", - domid); + statsErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__, + "stats->rd_bytes would overflow 64 bit counter", + domid); return -1; } stats->rd_bytes *= 512; } if (stats->wr_bytes > 0) { if (stats->wr_bytes >= ((unsigned long long)1)<<(63-9)) { - statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__, - "stats->wr_bytes would overflow 64 bit counter", - domid); + statsErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__, + "stats->wr_bytes would overflow 64 bit counter", + domid); return -1; } stats->wr_bytes *= 512; @@ -270,7 +269,7 @@ disk_re_match(const char *regex, const char *path, int *part) } int -xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path) +xenLinuxDomainDeviceID(int domid, const char *path) { int major, minor; int part; @@ -347,20 +346,20 @@ xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path) * beginning of the strings for better error messages */ else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/sd")) - statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__, - "invalid path, device names must be in the range sda[1-15] - sdiv[1-15]", - domid); + statsErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__, + "invalid path, device names must be in the range sda[1-15] - sdiv[1-15]", + domid); else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/hd")) - statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__, - "invalid path, device names must be in the range hda[1-63] - hdt[1-63]", - domid); + statsErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__, + "invalid path, device names must be in the range hda[1-63] - hdt[1-63]", + domid); else if (strlen(mod_path) >= 8 && STRPREFIX(mod_path, "/dev/xvd")) - statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__, - "invalid path, device names must be in the range xvda[1-15] - xvdiz[1-15]", - domid); + statsErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__, + "invalid path, device names must be in the range xvda[1-15] - xvdiz[1-15]", + domid); else - statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__, - "unsupported path, use xvdN, hdN, or sdN", domid); + statsErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__, + "unsupported path, use xvdN, hdN, or sdN", domid); VIR_FREE(mod_path); @@ -373,12 +372,12 @@ xenLinuxDomainBlockStats (xenUnifiedPrivatePtr priv, const char *path, struct _virDomainBlockStats *stats) { - int device = xenLinuxDomainDeviceID(dom->conn, dom->id, path); + int device = xenLinuxDomainDeviceID(dom->id, path); if (device < 0) return -1; - return read_bd_stats (dom->conn, priv, device, dom->id, stats); + return read_bd_stats(priv, device, dom->id, stats); } #endif /* __linux__ */ diff --git a/src/xen/block_stats.h b/src/xen/block_stats.h index ba113d7..c94f645 100644 --- a/src/xen/block_stats.h +++ b/src/xen/block_stats.h @@ -19,7 +19,7 @@ extern int xenLinuxDomainBlockStats (xenUnifiedPrivatePtr priv, virDomainPtr dom, const char *path, struct _virDomainBlockStats *stats); -extern int xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *dev); +extern int xenLinuxDomainDeviceID(int domid, const char *dev); # endif /* __linux__ */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 9f47722..2a07b7b 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -79,7 +79,7 @@ static int inside_daemon; #endif #define xenUnifiedError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_XEN, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_XEN, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) /** diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c index 8a9dae5..9a5b41d 100644 --- a/src/xen/xen_hypervisor.c +++ b/src/xen/xen_hypervisor.c @@ -843,7 +843,7 @@ struct xenUnifiedDriver xenHypervisorDriver = { #define virXenError(code, ...) \ if (in_init == 0) \ - virReportErrorHelper(NULL, VIR_FROM_XEN, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_XEN, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) /** @@ -870,11 +870,11 @@ virXenErrorFunc(virErrorNumber error, const char *func, const char *info, if (func != NULL) { snprintf(fullinfo, 999, "%s: %s", func, info); fullinfo[999] = 0; - virRaiseError(NULL, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR, + virRaiseError(NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR, errmsg, fullinfo, NULL, value, 0, errmsg, fullinfo, value); } else { - virRaiseError(NULL, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR, + virRaiseError(NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR, errmsg, info, NULL, value, 0, errmsg, info, value); } diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c index 5a997e6..d809c45 100644 --- a/src/xen/xen_inotify.c +++ b/src/xen/xen_inotify.c @@ -46,7 +46,7 @@ #define VIR_FROM_THIS VIR_FROM_XEN_INOTIFY #define virXenInotifyError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_XEN_INOTIFY, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_XEN_INOTIFY, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) struct xenUnifiedDriver xenInotifyDriver = { diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 57422d3..b608a43 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -68,7 +68,7 @@ virDomainXMLDevID(virDomainPtr domain, int ref_len); #define virXendError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_XEND, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_XEND, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #define virXendErrorInt(code, ival) \ diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 9225808..db47a02 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -121,7 +121,7 @@ struct xenUnifiedDriver xenXMDriver = { }; #define xenXMError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_XENXM, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_XENXM, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) #ifndef WITH_XEN_INOTIFY diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c index d9aad1f..c318f6c 100644 --- a/src/xen/xs_internal.c +++ b/src/xen/xs_internal.c @@ -83,7 +83,7 @@ struct xenUnifiedDriver xenStoreDriver = { }; #define virXenStoreError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_XENSTORE, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_XENSTORE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) /************************************************************************ diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 60b23c7..3fbdcc6 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -44,7 +44,7 @@ #define VIR_FROM_THIS VIR_FROM_XENAPI #define xenapiError(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) /* diff --git a/src/xenapi/xenapi_utils.c b/src/xenapi/xenapi_utils.c index f50610a..ae20bf7 100644 --- a/src/xenapi/xenapi_utils.c +++ b/src/xenapi/xenapi_utils.c @@ -386,11 +386,11 @@ xenapiSessionErrorHandle(virConnectPtr conn, virErrorNumber errNum, if (buf == NULL && priv != NULL && priv->session != NULL) { char *ret = returnErrorFromSession(priv->session); - virReportErrorHelper(conn, VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s"), ret); + virReportErrorHelper(VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s"), ret); xen_session_clear_error(priv->session); VIR_FREE(ret); } else { - virReportErrorHelper(conn, VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s"), buf); + virReportErrorHelper(VIR_FROM_XENAPI, errNum, filename, func, lineno, _("%s"), buf); } } diff --git a/src/xenxs/xenxs_private.h b/src/xenxs/xenxs_private.h index 9bf1223..60d27d2 100644 --- a/src/xenxs/xenxs_private.h +++ b/src/xenxs/xenxs_private.h @@ -57,7 +57,7 @@ # define VIR_FROM_THIS VIR_FROM_NONE # define XENXS_ERROR(code, ...) \ - virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, __FUNCTION__, \ + virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, __FUNCTION__, \ __LINE__, __VA_ARGS__) #endif /* __VIR_XENXS_PRIVATE_H__ */ -- 1.7.0.4 From matthias.bolte at googlemail.com Sat Apr 16 09:31:28 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 16 Apr 2011 11:31:28 +0200 Subject: [libvirt] [PATCH] xen: Replace statsErrorFunc with a macro Message-ID: <20110416093128.GA6167@sbox> Also mark error messages in block_stats.c for translation, add the new macro to the msg_gen functions in cfg.mk and add block_stats.c to po/POTFILES.in --- cfg.mk | 1 + po/POTFILES.in | 1 + src/xen/block_stats.c | 79 ++++++++++++++++++------------------------------ 3 files changed, 32 insertions(+), 49 deletions(-) diff --git a/cfg.mk b/cfg.mk index 94db937..e54d170 100644 --- a/cfg.mk +++ b/cfg.mk @@ -420,6 +420,7 @@ msg_gen_function += xenUnifiedError msg_gen_function += xenXMError msg_gen_function += VIR_ERROR msg_gen_function += VIR_ERROR0 +msg_gen_function += statsError # Uncomment the following and run "make syntax-check" to see diagnostics # that are not yet marked for translation, but that need to be rewritten diff --git a/po/POTFILES.in b/po/POTFILES.in index cfa7cf8..766f8f6 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -114,6 +114,7 @@ src/vbox/vbox_tmpl.c src/vmware/vmware_conf.c src/vmware/vmware_driver.c src/vmx/vmx.c +src/xen/block_stats.c src/xen/xen_driver.c src/xen/xen_hypervisor.c src/xen/xen_inotify.c diff --git a/src/xen/block_stats.c b/src/xen/block_stats.c index a28212c..1cb5455 100644 --- a/src/xen/block_stats.c +++ b/src/xen/block_stats.c @@ -31,34 +31,12 @@ # define VIR_FROM_THIS VIR_FROM_STATS_LINUX -/** - * statsErrorFunc: - * @conn: the connection - * @error: the error number - * @func: the function failing - * @info: extra information string - * @value: extra information number - * - * Handle a stats error. - */ -static void -statsErrorFunc (virErrorNumber error, const char *func, const char *info, - int value) -{ - char fullinfo[1000]; - const char *errmsg; - - errmsg = virErrorMsg(error, info); - if (func != NULL) { - snprintf(fullinfo, sizeof (fullinfo) - 1, "%s: %s", func, info); - fullinfo[sizeof (fullinfo) - 1] = 0; - info = fullinfo; - } - virRaiseError(NULL, NULL, VIR_FROM_STATS_LINUX, error, - VIR_ERR_ERROR, - errmsg, info, NULL, value, 0, errmsg, info, - value); -} + + +# define statsError(code, ...) \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, __FUNCTION__, \ + __LINE__, __VA_ARGS__) + /*-------------------- Xen: block stats --------------------*/ @@ -194,8 +172,9 @@ read_bd_stats(xenUnifiedPrivatePtr priv, if (stats->rd_req == -1 && stats->rd_bytes == -1 && stats->wr_req == -1 && stats->wr_bytes == -1 && stats->errs == -1) { - statsErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__, - "Failed to read any block statistics", domid); + statsError(VIR_ERR_INTERNAL_ERROR, + _("Failed to read any block statistics for domain %d"), + domid); return -1; } @@ -207,8 +186,9 @@ read_bd_stats(xenUnifiedPrivatePtr priv, stats->wr_req == 0 && stats->wr_bytes == 0 && stats->errs == 0 && !check_bd_connected (priv, device, domid)) { - statsErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__, - "Frontend block device not connected", domid); + statsError(VIR_ERR_INTERNAL_ERROR, + _("Frontend block device not connected for domain %d"), + domid); return -1; } @@ -217,18 +197,18 @@ read_bd_stats(xenUnifiedPrivatePtr priv, */ if (stats->rd_bytes > 0) { if (stats->rd_bytes >= ((unsigned long long)1)<<(63-9)) { - statsErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__, - "stats->rd_bytes would overflow 64 bit counter", - domid); + statsError(VIR_ERR_INTERNAL_ERROR, + _("stats->rd_bytes would overflow 64 bit counter for domain %d"), + domid); return -1; } stats->rd_bytes *= 512; } if (stats->wr_bytes > 0) { if (stats->wr_bytes >= ((unsigned long long)1)<<(63-9)) { - statsErrorFunc(VIR_ERR_INTERNAL_ERROR, __FUNCTION__, - "stats->wr_bytes would overflow 64 bit counter", - domid); + statsError(VIR_ERR_INTERNAL_ERROR, + _("stats->wr_bytes would overflow 64 bit counter for domain %d"), + domid); return -1; } stats->wr_bytes *= 512; @@ -346,20 +326,21 @@ xenLinuxDomainDeviceID(int domid, const char *path) * beginning of the strings for better error messages */ else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/sd")) - statsErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__, - "invalid path, device names must be in the range sda[1-15] - sdiv[1-15]", - domid); + statsError(VIR_ERR_INVALID_ARG, + _("invalid path, device names must be in the range " + "sda[1-15] - sdiv[1-15] for domain %d"), domid); else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/hd")) - statsErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__, - "invalid path, device names must be in the range hda[1-63] - hdt[1-63]", - domid); + statsError(VIR_ERR_INVALID_ARG, + _("invalid path, device names must be in the range " + "hda[1-63] - hdt[1-63] for domain %d"), domid); else if (strlen(mod_path) >= 8 && STRPREFIX(mod_path, "/dev/xvd")) - statsErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__, - "invalid path, device names must be in the range xvda[1-15] - xvdiz[1-15]", - domid); + statsError(VIR_ERR_INVALID_ARG, + _("invalid path, device names must be in the range " + "xvda[1-15] - xvdiz[1-15] for domain %d"), domid); else - statsErrorFunc(VIR_ERR_INVALID_ARG, __FUNCTION__, - "unsupported path, use xvdN, hdN, or sdN", domid); + statsError(VIR_ERR_INVALID_ARG, + _("unsupported path, use xvdN, hdN, or sdN for domain %d"), + domid); VIR_FREE(mod_path); -- 1.7.0.4 From jdenemar at redhat.com Sat Apr 16 09:47:07 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Sat, 16 Apr 2011 11:47:07 +0200 Subject: [libvirt] [PATCH] tests: Unit tests for internal hash APIs In-Reply-To: <4DA8C733.3090005@redhat.com> References: <20110413111532.GB18468@redhat.com> <4DA8C733.3090005@redhat.com> Message-ID: <20110416094707.GE7230@orkuz.home> On Fri, Apr 15, 2011 at 16:31:15 -0600, Eric Blake wrote: > On 04/15/2011 02:04 PM, Jiri Denemark wrote: > > This is a basic set of tests for testing removals of hash entries during > > iteration. > > --- > > More tests for all other hash APIs will come on Monday. > > Such as a test that gets 8 collisions into a single bucket to force hash > table growth Yes. > , or a test of custom hasher/comparator functions? Not yet, but I'll add it, thanks for mentioning that :-) > > +++ b/tests/hashdata.h > > @@ -0,0 +1,33 @@ > > +const char *uuids[] = { > > +/* [ 46] */ "f17494ba-2353-4af0-b1ba-13680858edcc", > > + "64ab4e78-1b6e-4b88-b47f-2def46c79a86", > > + "f99b0d59-ecff-4cc6-a9d3-20159536edc8", > > +/* [ 75] */ "e1bfa30f-bc0b-4a24-99ae-bed7f3f21a7b", > > + "acda5fa0-58de-4e1e-aa65-2124d1e29c54", > > +/* [ 76] */ "5f476c28-8f26-48e0-98de-85745fe2f304", > > Looks suspiciously like you used gdb to dump an existing hash structure > on a machine with lots of VMs :) Works for me. Not really, I just generated a bunch of UUIDs with uuidgen, used them within this test to create a hash, dumped that in gdb and replaced the original list with this dump :-) The full set of UUIDs will come with the additional tests since these two test didn't really require so many entries in a hash table. > > > +static virHashTablePtr > > +testHashInit(int size) > > +{ > > + virHashTablePtr hash; > > + int i; > > + > > + if (!(hash = virHashCreate(size, NULL))) > > + return NULL; > > + > > + /* entires are added in reverse order so that they will be linked in > > + * collision list in the same order as in the uuids array > > We're abusing an an internal detail. So good to have the comment - if > the test breaks because of another rewrite, but the only breakage is due > to a different link order in each bucket, then I'm okay modifying the > test at that point, and meanwhile it justifies our abuse (that is, no > change needed). The order doesn't matter much. Actually the comment isn't even right for current hash code. It's correct only after applying the hash rewrite. Making sure link order matches the uuids array just helps with designing the tests. E.g., when removing entries, one can easily say which entry is the first, last or in the middle of the list and can select appropriate uuids to test removing from different places in the list. > > +#define DO_TEST_DATA(name, cmd, data) \ > > + DO_TEST_FULL(name "(" #data ")", \ > > + cmd, \ > > + testHash ## cmd ## data, \ > > + testHashCount ## cmd ## data) > > + > > + DO_TEST_DATA("Remove in ForEach", RemoveForEach, Some); > > + DO_TEST_DATA("Remove in ForEach", RemoveForEach, All); > > + > > + return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE; > > Looks like a good test; it certainly would have caught the previous bugs > before the most recent hash.c fixes. Yes, of course I tested this test with older libvirt code without the hash fixes and the test just segfaults. > ACK. Thanks, pushed. Jirka From matthias.bolte at googlemail.com Sat Apr 16 12:15:24 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 16 Apr 2011 14:15:24 +0200 Subject: [libvirt] [PATCH] esx: Move the Event type from the VI generator to manually written code Message-ID: <20110416121524.GA18713@sbox> Accept all types on deserialization in order to accept all Event subtypes. This will be used for the upcoming domain event support. --- src/esx/esx_vi_generator.input | 21 ++++---- src/esx/esx_vi_generator.py | 1 - src/esx/esx_vi_types.c | 100 ++++++++++++++++++++++++++++++++++++++- src/esx/esx_vi_types.h | 34 ++++++++++++++ 4 files changed, 142 insertions(+), 14 deletions(-) diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input index 98b5206..4ec9f93 100644 --- a/src/esx/esx_vi_generator.input +++ b/src/esx/esx_vi_generator.input @@ -209,16 +209,12 @@ object ElementDescription extends Description end -object Event - Int key r - Int chainId r - DateTime createdTime r - String userName r - DatacenterEventArgument datacenter i - ComputeResourceEventArgument computeResource i - HostEventArgument host i - VmEventArgument vm i - String fullFormattedMessage o +object EntityEventArgument extends EventArgument + String name r +end + + +object EventArgument end @@ -709,6 +705,11 @@ object VmDiskFileQueryFlags end +object VmEventArgument extends EntityEventArgument + ManagedObjectReference vm r +end + + object VmLogFileInfo extends FileInfo end diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index ab127a3..ac15c7f 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -1430,7 +1430,6 @@ additional_object_features = { "AutoStartDefaults" : Object.FEATURE__AN "AutoStartPowerInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__LIST, "DatastoreHostMount" : Object.FEATURE__DEEP_COPY | Object.FEATURE__LIST | Object.FEATURE__ANY_TYPE, "DatastoreInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__DYNAMIC_CAST, - "Event" : Object.FEATURE__LIST, "FileInfo" : Object.FEATURE__DYNAMIC_CAST, "FileQuery" : Object.FEATURE__DYNAMIC_CAST, "HostConfigManager" : Object.FEATURE__ANY_TYPE, diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c index d264583..dd83954 100644 --- a/src/esx/esx_vi_types.c +++ b/src/esx/esx_vi_types.c @@ -271,13 +271,14 @@ -#define ESX_VI__TEMPLATE__DESERIALIZE_EXTRA(_type, _extra, _deserialize) \ +#define ESX_VI__TEMPLATE__DESERIALIZE_EXTRA(_type, _extra1, _extra2, \ + _deserialize) \ int \ esxVI_##_type##_Deserialize(xmlNodePtr node, esxVI_##_type **ptrptr) \ { \ xmlNodePtr childNode = NULL; \ \ - _extra \ + _extra1 \ \ if (ptrptr == NULL || *ptrptr != NULL) { \ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", \ @@ -289,6 +290,8 @@ return -1; \ } \ \ + _extra2 \ + \ for (childNode = node->children; childNode != NULL; \ childNode = childNode->next) { \ if (childNode->type != XML_ELEMENT_NODE) { \ @@ -317,7 +320,8 @@ #define ESX_VI__TEMPLATE__DESERIALIZE(_type, _deserialize) \ - ESX_VI__TEMPLATE__DESERIALIZE_EXTRA(_type, /* nothing */, _deserialize) + ESX_VI__TEMPLATE__DESERIALIZE_EXTRA(_type, /* nothing */, /* nothing */, \ + _deserialize) @@ -647,6 +651,7 @@ __FUNCTION__, esxVI_Type_ToString(type)); \ return -1; \ }, \ + /* nothing */, \ _deserialize) @@ -773,6 +778,9 @@ esxVI_Type_ToString(esxVI_Type type) case esxVI_Type_ManagedObjectReference: return "ManagedObjectReference"; + case esxVI_Type_Event: + return "Event"; + #include "esx_vi_types.generated.typetostring" case esxVI_Type_Other: @@ -805,6 +813,8 @@ esxVI_Type_FromString(const char *type) return esxVI_Type_MethodFault; } else if (STREQ(type, "ManagedObjectReference")) { return esxVI_Type_ManagedObjectReference; + } else if (STREQ(type, "Event")) { + return esxVI_Type_Event; } #include "esx_vi_types.generated.typefromstring" @@ -1664,6 +1674,90 @@ esxVI_ManagedObjectReference_Deserialize +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VI Type: Event + */ + +/* esxVI_Event_Alloc */ +ESX_VI__TEMPLATE__ALLOC(Event) + +/* esxVI_Event_Free */ +ESX_VI__TEMPLATE__FREE(Event, +{ + esxVI_Event_Free(&item->_next); + VIR_FREE(item->_actualType); + + esxVI_Int_Free(&item->key); + esxVI_Int_Free(&item->chainId); + esxVI_DateTime_Free(&item->createdTime); + VIR_FREE(item->userName); + /* FIXME: datacenter is currently ignored */ + /* FIXME: computeResource is currently ignored */ + /* FIXME: host is currently ignored */ + esxVI_VmEventArgument_Free(&item->vm); + VIR_FREE(item->fullFormattedMessage); +}) + +/* esxVI_Event_Validate */ +ESX_VI__TEMPLATE__VALIDATE(Event, +{ + ESX_VI__TEMPLATE__PROPERTY__REQUIRE(key) + ESX_VI__TEMPLATE__PROPERTY__REQUIRE(chainId) + ESX_VI__TEMPLATE__PROPERTY__REQUIRE(createdTime) + ESX_VI__TEMPLATE__PROPERTY__REQUIRE(userName) + /* FIXME: datacenter is currently ignored */ + /* FIXME: computeResource is currently ignored */ + /* FIXME: host is currently ignored */ +}) + +/* esxVI_Event_AppendToList */ +ESX_VI__TEMPLATE__LIST__APPEND(Event) + +/* esxVI_Event_CastFromAnyType */ +ESX_VI__TEMPLATE__DYNAMIC_CAST_FROM_ANY_TYPE(Event, +{ + case esxVI_Type_Other: + /* Just accept everything here */ + break; +}) + +/* esxVI_Event_CastListFromAnyType */ +ESX_VI__TEMPLATE__LIST__CAST_FROM_ANY_TYPE(Event) + +/* esxVI_Event_Deserialize */ +ESX_VI__TEMPLATE__DESERIALIZE_EXTRA(Event, /* nothing */, +{ + (*ptrptr)->_actualType = + (char *)xmlGetNsProp(node, BAD_CAST "type", + BAD_CAST "http://www.w3.org/2001/XMLSchema-instance"); + + if ((*ptrptr)->_actualType == NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, + _("%s is missing 'type' property"), + esxVI_Type_ToString((*ptrptr)->_type)); + goto failure; + } +}, +{ + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, key) + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, chainId) + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(DateTime, createdTime) + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, userName) + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_IGNORE(datacenter) /* FIXME */ + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_IGNORE(computeResource) /* FIXME */ + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_IGNORE(host) /* FIXME */ + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(VmEventArgument, vm) + ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, fullFormattedMessage) + + /* Don't warn about unexpected properties */ + continue; +}) + +/* esxVI_Event_DeserializeList */ +ESX_VI__TEMPLATE__LIST__DESERIALIZE(Event) + + + #include "esx_vi_types.generated.c" diff --git a/src/esx/esx_vi_types.h b/src/esx/esx_vi_types.h index ac3741f..d141a38 100644 --- a/src/esx/esx_vi_types.h +++ b/src/esx/esx_vi_types.h @@ -55,8 +55,10 @@ typedef struct _esxVI_Fault esxVI_Fault; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * VI Objects */ + typedef struct _esxVI_MethodFault esxVI_MethodFault; typedef struct _esxVI_ManagedObjectReference esxVI_ManagedObjectReference; +typedef struct _esxVI_Event esxVI_Event; # include "esx_vi_types.generated.typedef" @@ -78,6 +80,7 @@ enum _esxVI_Type { esxVI_Type_Fault, esxVI_Type_MethodFault, esxVI_Type_ManagedObjectReference, + esxVI_Type_Event, # include "esx_vi_types.generated.typeenum" @@ -345,6 +348,37 @@ int esxVI_ManagedObjectReference_Deserialize +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VI Type: Event + */ + +struct _esxVI_Event { + esxVI_Event *_next; /* optional */ + esxVI_Type _type; /* required */ + char *_actualType; /* required */ + + esxVI_Int *key; /* required */ + esxVI_Int *chainId; /* required */ + esxVI_DateTime *createdTime; /* required */ + char *userName; /* required */ + /* FIXME: datacenter is currently ignored */ + /* FIXME: computeResource is currently ignored */ + /* FIXME: host is currently ignored */ + esxVI_VmEventArgument *vm; /* optional */ + char *fullFormattedMessage; /* optional */ +}; + +int esxVI_Event_Alloc(esxVI_Event **item); +void esxVI_Event_Free(esxVI_Event **item); +int esxVI_Event_Validate(esxVI_Event *item); +int esxVI_Event_AppendToList(esxVI_Event **list, esxVI_Event *item); +int esxVI_Event_CastFromAnyType(esxVI_AnyType *anyType, esxVI_Event **item); +int esxVI_Event_CastListFromAnyType(esxVI_AnyType *anyType, esxVI_Event **list); +int esxVI_Event_Deserialize(xmlNodePtr node, esxVI_Event **item); +int esxVI_Event_DeserializeList(xmlNodePtr node, esxVI_Event **list); + + + # include "esx_vi_types.generated.h" -- 1.7.0.4 From rjones at redhat.com Sat Apr 16 13:52:51 2011 From: rjones at redhat.com (Richard W.M. Jones) Date: Sat, 16 Apr 2011 14:52:51 +0100 Subject: [libvirt] [RFC][PATCHv1 2/5] libvirt - new API for getting percpu statistics of VM In-Reply-To: <20110415160452.63bd9216.kamezawa.hiroyu@jp.fujitsu.com> References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> <20110415160452.63bd9216.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110416135251.GI2641@amd.home.annexia.org> On Fri, Apr 15, 2011 at 04:04:52PM +0900, KAMEZAWA Hiroyuki wrote: [...] The idea and the implementation is sound. However I have a problem with this proposed API: > +typedef struct _virDomainPcpuStat virDomainPcpuStatStruct; > + > +struct _virDomainPcpuStat { > + unsigned long long cpuTime; > +}; > + > +typedef virDomainPcpuStatStruct *virDomainPcpuStatPtr; [...] > /** > + * virDomainPcpuStats: > + * @dom: pointer to the domain object > + * @stats: nr_stats-sized array of stat structures (returned) > + * @nr_stats: number of cpu statistics requested > + * @flags: unused, always pass 0 > + * > + * This function provides per-cpu statistics for the domain. 'cpu' here means > + * not vcpu. > + * > + * Up to 'nr_stats' elements of 'stats' will be populated with cpu statistics > + * from the domain. Only statistics supported by the domain, the driver, and > + * this version of libvirt will be returned. > + * > + * Now, only cpuTime per cpu is reported in nanoseconds. > + * > + * Returns: The number of stats provided or -1 in case of failure. > + */ > +int virDomainPcpuStats (virDomainPtr dom, virDomainPcpuStatPtr stats, > + unsigned int nr_stats, unsigned int flags) Am I correct that the caller sets nr_stats == number of physical cores, and allocates an array of nr_stats * virDomainPcpuStats structs? We could never add more elements to the _virDomainPcpuStat structure, because that would break the ABI for existing callers. (Or I guess we could use the flags field). I think we should forget about the structure, and just use an array of unsigned long long's, but I'd like to hear what others think. Is it likely that we would return other per-physical-CPU stats in future? Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From eblake at redhat.com Sat Apr 16 15:01:13 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 16 Apr 2011 09:01:13 -0600 Subject: [libvirt] [PATCH] xen: Replace statsErrorFunc with a macro In-Reply-To: <20110416093128.GA6167@sbox> References: <20110416093128.GA6167@sbox> Message-ID: <4DA9AF39.5070300@redhat.com> On 04/16/2011 03:31 AM, Matthias Bolte wrote: > Also mark error messages in block_stats.c for translation, add the > new macro to the msg_gen functions in cfg.mk and add block_stats.c > to po/POTFILES.in > --- > cfg.mk | 1 + > po/POTFILES.in | 1 + > src/xen/block_stats.c | 79 ++++++++++++++++++------------------------------ > 3 files changed, 32 insertions(+), 49 deletions(-) > > diff --git a/cfg.mk b/cfg.mk > index 94db937..e54d170 100644 > --- a/cfg.mk > +++ b/cfg.mk > @@ -420,6 +420,7 @@ msg_gen_function += xenUnifiedError > msg_gen_function += xenXMError > msg_gen_function += VIR_ERROR > msg_gen_function += VIR_ERROR0 > +msg_gen_function += statsError Nit - is it worth sorting these lines by function name? ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Sat Apr 16 15:02:22 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 16 Apr 2011 09:02:22 -0600 Subject: [libvirt] [PATCH v2] Remove virConnectPtr from virRaiseErrorFull In-Reply-To: <20110416083243.GA9352@sbox> References: <20110416083243.GA9352@sbox> Message-ID: <4DA9AF7E.5080800@redhat.com> On 04/16/2011 02:32 AM, Matthias Bolte wrote: > And from all related macros and functions. > --- > > I posted v1 a year ago :) > > https://www.redhat.com/archives/libvir-list/2010-April/msg00164.html And I even ack'd it, but a lot has changed in the meantime. > +++ b/src/conf/cpu_conf.c > @@ -32,7 +32,7 @@ > #define VIR_FROM_THIS VIR_FROM_CPU > > #define virCPUReportError(code, ...) \ > - virReportErrorHelper(NULL, VIR_FROM_CPU, code, __FILE__, \ > + virReportErrorHelper(VIR_FROM_CPU, code, __FILE__, \ > __FUNCTION__, __LINE__, __VA_ARGS__) The argument was truly unused, so this is a nice cleanup. ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Sat Apr 16 15:28:19 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 16 Apr 2011 09:28:19 -0600 Subject: [libvirt] [PATCH 1/4] qemu: implement older APIs by forwarding to flags version In-Reply-To: <4DA8B7AD.4010308@redhat.com> References: <4DA8B7AD.4010308@redhat.com> Message-ID: <1302967702-30065-1-git-send-email-eblake@redhat.com> Centralize device modification in the more flexible APIs, to allow future honoring of additional flags. Explicitly reject the VIR_DOMAIN_DEVICE_MODIFY_FORCE flag on attach/detach. * src/qemu/qemu_driver.c (qemudDomainAttachDevice) (qemudDomainAttachDeviceFlags): Swap bodies, and rename... (qemuDomainAttachDevice, qemuDomainAttachDeviceFlags): to this. (qemudDomainDetachDevice, qemudDomainDetachDeviceFlags): Likewise. --- src/qemu/qemu_driver.c | 72 +++++++++++++++++++++++++++-------------------- 1 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c1a44c9..ca06dd6 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3776,8 +3776,9 @@ cleanup: } -static int qemudDomainAttachDevice(virDomainPtr dom, - const char *xml) +static int +qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; @@ -3786,6 +3787,14 @@ static int qemudDomainAttachDevice(virDomainPtr dom, virCgroupPtr cgroup = NULL; int ret = -1; + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot modify the persistent configuration of a domain")); + return -1; + } + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { @@ -3933,22 +3942,17 @@ cleanup: return ret; } -static int qemudDomainAttachDeviceFlags(virDomainPtr dom, - const char *xml, - unsigned int flags) { - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return qemudDomainAttachDevice(dom, xml); +static int +qemuDomainAttachDevice(virDomainPtr dom, const char *xml) +{ + return qemuDomainAttachDeviceFlags(dom, xml, + VIR_DOMAIN_DEVICE_MODIFY_LIVE); } -static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, - const char *xml, - unsigned int flags) +static int +qemuDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; @@ -4068,14 +4072,25 @@ cleanup: } -static int qemudDomainDetachDevice(virDomainPtr dom, - const char *xml) { +static int +qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; virBitmapPtr qemuCaps = NULL; virDomainDeviceDefPtr dev = NULL; int ret = -1; + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot modify the persistent configuration of a domain")); + return -1; + } + + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { @@ -4154,16 +4169,11 @@ cleanup: return ret; } -static int qemudDomainDetachDeviceFlags(virDomainPtr dom, - const char *xml, - unsigned int flags) { - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return qemudDomainDetachDevice(dom, xml); +static int +qemuDomainDetachDevice(virDomainPtr dom, const char *xml) +{ + return qemuDomainDetachDeviceFlags(dom, xml, + VIR_DOMAIN_DEVICE_MODIFY_LIVE); } static int qemudDomainGetAutostart(virDomainPtr dom, @@ -6965,10 +6975,10 @@ static virDriver qemuDriver = { qemudDomainStartWithFlags, /* domainCreateWithFlags */ qemudDomainDefine, /* domainDefineXML */ qemudDomainUndefine, /* domainUndefine */ - qemudDomainAttachDevice, /* domainAttachDevice */ - qemudDomainAttachDeviceFlags, /* domainAttachDeviceFlags */ - qemudDomainDetachDevice, /* domainDetachDevice */ - qemudDomainDetachDeviceFlags, /* domainDetachDeviceFlags */ + qemuDomainAttachDevice, /* domainAttachDevice */ + qemuDomainAttachDeviceFlags, /* domainAttachDeviceFlags */ + qemuDomainDetachDevice, /* domainDetachDevice */ + qemuDomainDetachDeviceFlags, /* domainDetachDeviceFlags */ qemuDomainUpdateDeviceFlags, /* domainUpdateDeviceFlags */ qemudDomainGetAutostart, /* domainGetAutostart */ qemudDomainSetAutostart, /* domainSetAutostart */ -- 1.7.4.2 From eblake at redhat.com Sat Apr 16 15:28:20 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 16 Apr 2011 09:28:20 -0600 Subject: [libvirt] [PATCH 2/4] qemu: refactor device modification functions In-Reply-To: <1302967702-30065-1-git-send-email-eblake@redhat.com> References: <4DA8B7AD.4010308@redhat.com> <1302967702-30065-1-git-send-email-eblake@redhat.com> Message-ID: <1302967702-30065-2-git-send-email-eblake@redhat.com> The device modify functions (Attach, Update, Detach) are rather long, with boilerplate to obtain locks surrounding a case statement for acting on particular device types. In order for a future patch to share the boilerplate and allow persistent modification, factor out the device actions. * src/qemu/qemu_driver.c (qemuDomainAttachDeviceLive) (qemuDomainUpdateDeviceLive, qemuDomainDetachDeviceLive): New helper methods. (qemuDomainAttachDeviceFlags, qemuDomainUpdateDeviceFlags) (qemuDomainDetachDeviceFlags): Use it to separate case statements from locking setup. --- src/qemu/qemu_driver.c | 385 ++++++++++++++++++++++++++++-------------------- 1 files changed, 225 insertions(+), 160 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ca06dd6..c1a5ebb 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3776,72 +3776,36 @@ cleanup: } +/* Helper called on active vm while job condition is held */ static int -qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) +qemuDomainAttachDeviceLive(virDomainPtr dom, struct qemud_driver *driver, + virDomainObjPtr vm, virDomainDeviceDefPtr dev, + virBitmapPtr qemuCaps, + bool force ATTRIBUTE_UNUSED) { - struct qemud_driver *driver = dom->conn->privateData; - virDomainObjPtr vm; - virDomainDeviceDefPtr dev = NULL; - virBitmapPtr qemuCaps = NULL; virCgroupPtr cgroup = NULL; int ret = -1; - virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | - VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } - - qemuDriverLock(driver); - vm = virDomainFindByUUID(&driver->domains, dom->uuid); - 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 (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) - goto cleanup; - - if (!virDomainObjIsActive(vm)) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot attach device on inactive domain")); - goto endjob; - } - - dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, - VIR_DOMAIN_XML_INACTIVE); - if (dev == NULL) - goto endjob; - - if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch, - NULL, - &qemuCaps) < 0) - goto endjob; - - if (dev->type == VIR_DOMAIN_DEVICE_DISK) { + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: if (dev->data.disk->driverName != NULL && !STREQ(dev->data.disk->driverName, "qemu")) { qemuReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported driver name '%s' for disk '%s'"), dev->data.disk->driverName, dev->data.disk->src); - goto endjob; + goto cleanup; } if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { - if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=0 ) { + if (virCgroupForDomain(driver->cgroup, vm->def->name, + &cgroup, 0) !=0 ) { qemuReportError(VIR_ERR_INTERNAL_ERROR, _("Unable to find cgroup for %s"), vm->def->name); - goto endjob; + goto cleanup; } if (qemuSetupDiskCgroup(driver, vm, cgroup, dev->data.disk) < 0) - goto endjob; + goto cleanup; } switch (dev->data.disk->device) { @@ -3856,69 +3820,256 @@ qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, break; case VIR_DOMAIN_DISK_DEVICE_DISK: - if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) { + switch (dev->data.disk->bus) { + case VIR_DOMAIN_DISK_BUS_USB: ret = qemuDomainAttachUsbMassstorageDevice(driver, vm, - dev->data.disk, qemuCaps); - if (ret == 0) - dev->data.disk = NULL; - } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { + dev->data.disk, + qemuCaps); + break; + case VIR_DOMAIN_DISK_BUS_VIRTIO: ret = qemuDomainAttachPciDiskDevice(driver, vm, dev->data.disk, qemuCaps); - if (ret == 0) - dev->data.disk = NULL; - } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) { + break; + case VIR_DOMAIN_DISK_BUS_SCSI: ret = qemuDomainAttachSCSIDisk(driver, vm, dev->data.disk, qemuCaps); - if (ret == 0) - dev->data.disk = NULL; - } else { + break; + default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("disk bus '%s' cannot be hotplugged."), virDomainDiskBusTypeToString(dev->data.disk->bus)); - /* fallthrough */ + goto cleanup; } + if (ret == 0) + dev->data.disk = NULL; break; default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("disk device type '%s' cannot be hotplugged"), virDomainDiskDeviceTypeToString(dev->data.disk->device)); - /* Fallthrough */ - } - if (ret != 0 && cgroup) { - if (qemuTeardownDiskCgroup(driver, vm, cgroup, dev->data.disk) < 0) - VIR_WARN("Failed to teardown cgroup for disk path %s", - NULLSTR(dev->data.disk->src)); + goto cleanup; } - } else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) { + break; + case VIR_DOMAIN_DEVICE_CONTROLLER: if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) { ret = qemuDomainAttachPciControllerDevice(driver, vm, - dev->data.controller, qemuCaps); + dev->data.controller, + qemuCaps); if (ret == 0) dev->data.controller = NULL; } else { qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("disk controller bus '%s' cannot be hotplugged."), virDomainControllerTypeToString(dev->data.controller->type)); - /* fallthrough */ + goto cleanup; } - } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { + break; + case VIR_DOMAIN_DEVICE_NET: ret = qemuDomainAttachNetDevice(dom->conn, driver, vm, dev->data.net, qemuCaps); if (ret == 0) dev->data.net = NULL; - } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { + break; + case VIR_DOMAIN_DEVICE_HOSTDEV: ret = qemuDomainAttachHostDevice(driver, vm, dev->data.hostdev, qemuCaps); if (ret == 0) dev->data.hostdev = NULL; - } else { + break; + default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("device type '%s' cannot be attached"), virDomainDeviceTypeToString(dev->type)); + goto cleanup; + } + +cleanup: + if (ret != 0 && cgroup) { + if (qemuTeardownDiskCgroup(driver, vm, cgroup, dev->data.disk) < 0) + VIR_WARN("Failed to teardown cgroup for disk path %s", + NULLSTR(dev->data.disk->src)); + } + if (cgroup) + virCgroupFree(&cgroup); + return ret; +} + +/* Helper called on active vm while job condition is held */ +static int +qemuDomainUpdateDeviceLive(virDomainPtr dom ATTRIBUTE_UNUSED, + struct qemud_driver *driver, + virDomainObjPtr vm, virDomainDeviceDefPtr dev, + virBitmapPtr qemuCaps, bool force) +{ + virCgroupPtr cgroup = NULL; + int ret = -1; + + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { + if (virCgroupForDomain(driver->cgroup, vm->def->name, + &cgroup, 0) !=0 ) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to find cgroup for %s"), + vm->def->name); + goto cleanup; + } + if (qemuSetupDiskCgroup(driver, vm, cgroup, dev->data.disk) < 0) + goto cleanup; + } + + switch (dev->data.disk->device) { + case VIR_DOMAIN_DISK_DEVICE_CDROM: + case VIR_DOMAIN_DISK_DEVICE_FLOPPY: + ret = qemuDomainChangeEjectableMedia(driver, vm, + dev->data.disk, + qemuCaps, + force); + if (ret == 0) + dev->data.disk = NULL; + break; + + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk bus '%s' cannot be updated."), + virDomainDiskBusTypeToString(dev->data.disk->bus)); + goto cleanup; + } + break; + + case VIR_DOMAIN_DEVICE_GRAPHICS: + ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics); + break; + + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("device type '%s' cannot be updated"), + virDomainDeviceTypeToString(dev->type)); + goto cleanup; + } + +cleanup: + if (ret != 0 && cgroup) { + if (qemuTeardownDiskCgroup(driver, vm, cgroup, dev->data.disk) < 0) + VIR_WARN("Failed to teardown cgroup for disk path %s", + NULLSTR(dev->data.disk->src)); + } + if (cgroup) + virCgroupFree(&cgroup); + return ret; +} + +/* Helper called on active vm while job condition is held */ +static int +qemuDomainDetachDeviceLive(virDomainPtr dom ATTRIBUTE_UNUSED, + struct qemud_driver *driver, + virDomainObjPtr vm, virDomainDeviceDefPtr dev, + virBitmapPtr qemuCaps, + bool force ATTRIBUTE_UNUSED) +{ + int ret = -1; + + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) { + switch (dev->data.disk->bus) { + case VIR_DOMAIN_DISK_BUS_VIRTIO: + ret = qemuDomainDetachPciDiskDevice(driver, vm, dev, qemuCaps); + break; + case VIR_DOMAIN_DISK_BUS_SCSI: + ret = qemuDomainDetachDiskDevice(driver, vm, dev, qemuCaps); + break; + case VIR_DOMAIN_DISK_BUS_USB: + ret = qemuDomainDetachDiskDevice(driver, vm, dev, qemuCaps); + break; + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This type of disk cannot be hot unplugged")); + goto cleanup; + } + } else { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This type of disk cannot be hot unplugged")); + goto cleanup; + } + break; + case VIR_DOMAIN_DEVICE_NET: + ret = qemuDomainDetachNetDevice(driver, vm, dev, qemuCaps); + break; + case VIR_DOMAIN_DEVICE_CONTROLLER: + if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) { + ret = qemuDomainDetachPciControllerDevice(driver, vm, dev, + qemuCaps); + } else { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk controller bus '%s' cannot be hotunplugged."), + virDomainControllerTypeToString(dev->data.controller->type)); + goto cleanup; + } + break; + case VIR_DOMAIN_DEVICE_HOSTDEV: + ret = qemuDomainDetachHostDevice(driver, vm, dev, qemuCaps); + break; + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("This type of device cannot be hot unplugged")); + goto cleanup; + } + +cleanup: + return ret; +} + +static int +qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + virDomainDeviceDefPtr dev = NULL; + virBitmapPtr qemuCaps = NULL; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot modify the persistent configuration of a domain")); + return -1; + } + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + 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 (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot attach device on inactive domain")); goto endjob; } + dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, + VIR_DOMAIN_XML_INACTIVE); + if (dev == NULL) + goto endjob; + + if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch, + NULL, + &qemuCaps) < 0) + goto endjob; + + ret = qemuDomainAttachDeviceLive(dom, driver, vm, dev, qemuCaps, false); + /* update domain status forcibly because the domain status may be changed * even if we attach the device failed. For example, a new controller may * be created. @@ -3931,9 +4082,6 @@ endjob: vm = NULL; cleanup: - if (cgroup) - virCgroupFree(&cgroup); - qemuCapsFree(qemuCaps); virDomainDeviceDefFree(dev); if (vm) @@ -3958,7 +4106,6 @@ qemuDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, virDomainObjPtr vm; virDomainDeviceDefPtr dev = NULL; virBitmapPtr qemuCaps = NULL; - virCgroupPtr cgroup = NULL; int ret = -1; bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; @@ -4002,55 +4149,7 @@ qemuDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, &qemuCaps) < 0) goto endjob; - switch (dev->type) { - case VIR_DOMAIN_DEVICE_DISK: - if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { - if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=0 ) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to find cgroup for %s"), - vm->def->name); - goto endjob; - } - if (qemuSetupDiskCgroup(driver, vm, cgroup, dev->data.disk) < 0) - goto endjob; - } - - switch (dev->data.disk->device) { - case VIR_DOMAIN_DISK_DEVICE_CDROM: - case VIR_DOMAIN_DISK_DEVICE_FLOPPY: - ret = qemuDomainChangeEjectableMedia(driver, vm, - dev->data.disk, - qemuCaps, - force); - if (ret == 0) - dev->data.disk = NULL; - break; - - - default: - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("disk bus '%s' cannot be updated."), - virDomainDiskBusTypeToString(dev->data.disk->bus)); - break; - } - - if (ret != 0 && cgroup) { - if (qemuTeardownDiskCgroup(driver, vm, cgroup, dev->data.disk) < 0) - VIR_WARN("Failed to teardown cgroup for disk path %s", - NULLSTR(dev->data.disk->src)); - } - break; - - case VIR_DOMAIN_DEVICE_GRAPHICS: - ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics); - break; - - default: - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("device type '%s' cannot be updated"), - virDomainDeviceTypeToString(dev->type)); - break; - } + ret = qemuDomainUpdateDeviceLive(dom, driver, vm, dev, qemuCaps, force); if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) ret = -1; @@ -4060,9 +4159,6 @@ endjob: vm = NULL; cleanup: - if (cgroup) - virCgroupFree(&cgroup); - qemuCapsFree(qemuCaps); virDomainDeviceDefFree(dev); if (vm) @@ -4120,38 +4216,7 @@ qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, &qemuCaps) < 0) goto endjob; - if (dev->type == VIR_DOMAIN_DEVICE_DISK && - dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) { - if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { - ret = qemuDomainDetachPciDiskDevice(driver, vm, dev, qemuCaps); - } - else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) { - ret = qemuDomainDetachDiskDevice(driver, vm, dev, qemuCaps); - } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) { - ret = qemuDomainDetachDiskDevice(driver, vm, dev, qemuCaps); - } - else { - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("This type of disk cannot be hot unplugged")); - } - } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { - ret = qemuDomainDetachNetDevice(driver, vm, dev, qemuCaps); - } else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) { - if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) { - ret = qemuDomainDetachPciControllerDevice(driver, vm, dev, - qemuCaps); - } else { - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("disk controller bus '%s' cannot be hotunplugged."), - virDomainControllerTypeToString(dev->data.controller->type)); - /* fallthrough */ - } - } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { - ret = qemuDomainDetachHostDevice(driver, vm, dev, qemuCaps); - } else { - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - "%s", _("This type of device cannot be hot unplugged")); - } + ret = qemuDomainDetachDeviceLive(dom, driver, vm, dev, qemuCaps, false); if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) ret = -1; -- 1.7.4.2 From eblake at redhat.com Sat Apr 16 15:28:21 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 16 Apr 2011 09:28:21 -0600 Subject: [libvirt] [PATCH 3/4] qemu: consolidate device modification functions In-Reply-To: <1302967702-30065-1-git-send-email-eblake@redhat.com> References: <4DA8B7AD.4010308@redhat.com> <1302967702-30065-1-git-send-email-eblake@redhat.com> Message-ID: <1302967702-30065-3-git-send-email-eblake@redhat.com> No functional change, but now adding support for persistent modifications can be done at one point to affect 3 APIs. * src/qemu/qemu_driver.c (qemuDomainModifyDeviceCallback): New typedef. (qemuDomainModifyDeviceFlags) New function. (qemuDomainAttachDeviceFlags, qemuDomainUpdateDeviceFlags) (qemuDomainDetachDeviceFlags): Use it. --- src/qemu/qemu_driver.c | 158 +++++++++-------------------------------------- 1 files changed, 31 insertions(+), 127 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c1a5ebb..4f0a057 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3775,6 +3775,12 @@ cleanup: return ret; } +typedef int (*qemuDomainModifyDeviceCallback) (virDomainPtr dom, + struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev, + virBitmapPtr qemuCaps, + bool force); /* Helper called on active vm while job condition is held */ static int @@ -4021,21 +4027,22 @@ cleanup: return ret; } +/* Common boilerplate around modifying a device. */ static int -qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) +qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags, + qemuDomainModifyDeviceCallback cb) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; virDomainDeviceDefPtr dev = NULL; virBitmapPtr qemuCaps = NULL; int ret = -1; + bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; - virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | - VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify domain persistent configuration")); return -1; } @@ -4054,7 +4061,7 @@ qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, if (!virDomainObjIsActive(vm)) { qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot attach device on inactive domain")); + "%s", _("cannot modify device on inactive domain")); goto endjob; } @@ -4068,7 +4075,7 @@ qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, &qemuCaps) < 0) goto endjob; - ret = qemuDomainAttachDeviceLive(dom, driver, vm, dev, qemuCaps, false); + ret = (cb)(dom, driver, vm, dev, qemuCaps, force); /* update domain status forcibly because the domain status may be changed * even if we attach the device failed. For example, a new controller may @@ -4090,6 +4097,17 @@ cleanup: return ret; } + +static int +qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); + return qemuDomainModifyDeviceFlags(dom, xml, flags, + qemuDomainAttachDeviceLive); +} + static int qemuDomainAttachDevice(virDomainPtr dom, const char *xml) { @@ -4102,69 +4120,11 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) { - struct qemud_driver *driver = dom->conn->privateData; - virDomainObjPtr vm; - virDomainDeviceDefPtr dev = NULL; - virBitmapPtr qemuCaps = NULL; - int ret = -1; - bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; - - virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_CURRENT | - VIR_DOMAIN_DEVICE_MODIFY_LIVE | + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | VIR_DOMAIN_DEVICE_MODIFY_CONFIG | VIR_DOMAIN_DEVICE_MODIFY_FORCE, -1); - - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } - - qemuDriverLock(driver); - vm = virDomainFindByUUID(&driver->domains, dom->uuid); - 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 (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) - goto cleanup; - - if (!virDomainObjIsActive(vm)) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot attach device on inactive domain")); - goto endjob; - } - - dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, - VIR_DOMAIN_XML_INACTIVE); - if (dev == NULL) - goto endjob; - - if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch, - NULL, - &qemuCaps) < 0) - goto endjob; - - ret = qemuDomainUpdateDeviceLive(dom, driver, vm, dev, qemuCaps, force); - - if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) - ret = -1; - -endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; - -cleanup: - qemuCapsFree(qemuCaps); - virDomainDeviceDefFree(dev); - if (vm) - virDomainObjUnlock(vm); - qemuDriverUnlock(driver); - return ret; + return qemuDomainModifyDeviceFlags(dom, xml, flags, + qemuDomainUpdateDeviceLive); } @@ -4172,66 +4132,10 @@ static int qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) { - struct qemud_driver *driver = dom->conn->privateData; - virDomainObjPtr vm; - virBitmapPtr qemuCaps = NULL; - virDomainDeviceDefPtr dev = NULL; - int ret = -1; - virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } - - - qemuDriverLock(driver); - vm = virDomainFindByUUID(&driver->domains, dom->uuid); - 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 (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) - goto cleanup; - - if (!virDomainObjIsActive(vm)) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot detach device on inactive domain")); - goto endjob; - } - - dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, - VIR_DOMAIN_XML_INACTIVE); - if (dev == NULL) - goto endjob; - - if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch, - NULL, - &qemuCaps) < 0) - goto endjob; - - ret = qemuDomainDetachDeviceLive(dom, driver, vm, dev, qemuCaps, false); - - if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) - ret = -1; - -endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; - -cleanup: - qemuCapsFree(qemuCaps); - virDomainDeviceDefFree(dev); - if (vm) - virDomainObjUnlock(vm); - qemuDriverUnlock(driver); - return ret; + return qemuDomainModifyDeviceFlags(dom, xml, flags, + qemuDomainDetachDeviceLive); } static int -- 1.7.4.2 From eblake at redhat.com Sat Apr 16 15:28:22 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 16 Apr 2011 09:28:22 -0600 Subject: [libvirt] [PATCH 4/4] qemu: add plumbing for persistent device changes In-Reply-To: <1302967702-30065-1-git-send-email-eblake@redhat.com> References: <4DA8B7AD.4010308@redhat.com> <1302967702-30065-1-git-send-email-eblake@redhat.com> Message-ID: <1302967702-30065-4-git-send-email-eblake@redhat.com> There's still work to add persistent callback functions, and to make sure this all works, but this demonstrates how having a single function makes it easy to support flags for all three types of device modifications. * src/qemu/qemu_driver.c (qemuDomainModifyDeviceFlags): Add parameter, and support VIR_DOMAIN_DEVICE_MODIFY_CURRENT. (qemuDomainAttachDeviceFlags, qemuDomainUpdateDeviceFlags) (qemuDomainDetachDeviceFlags): Update callers. --- After this point, we can use Kame's patch 1/4 to add in the persistent function callbacks (with slight tweaks to their signatures), and 2/4 to make it easier to to temporary modifications to a config: if (flags & CONFIG) { create temporary def call persistent callback } if (flags & LIVE) { call live callback } if (no errors) commit temporary def and live state changes, as needed But with the benefit that CURRENT support is now provided. src/qemu/qemu_driver.c | 47 +++++++++++++++++++++++++++++++++++------------ 1 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 4f0a057..8c978be 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4031,7 +4031,8 @@ cleanup: static int qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags, - qemuDomainModifyDeviceCallback cb) + qemuDomainModifyDeviceCallback live, + qemuDomainModifyDeviceCallback persistent) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; @@ -4039,12 +4040,7 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, virBitmapPtr qemuCaps = NULL; int ret = -1; bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; - - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot modify domain persistent configuration")); - return -1; - } + bool active; qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -4059,12 +4055,32 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; - if (!virDomainObjIsActive(vm)) { + active = virDomainObjIsActive(vm); + + if ((flags & (VIR_DOMAIN_DEVICE_MODIFY_LIVE + | VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) == 0) + flags |= (active ? VIR_DOMAIN_DEVICE_MODIFY_LIVE + : VIR_DOMAIN_DEVICE_MODIFY_CONFIG); + + if ((flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) && !active) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot modify device on inactive domain")); goto endjob; } + if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot modify device on transient domain")); + goto endjob; + } + + /* XXX add persistent support */ + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify domain persistent configuration")); + return -1; + } + dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, VIR_DOMAIN_XML_INACTIVE); if (dev == NULL) @@ -4075,7 +4091,11 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, &qemuCaps) < 0) goto endjob; - ret = (cb)(dom, driver, vm, dev, qemuCaps, force); + ret = 0; + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) + ret = (live)(dom, driver, vm, dev, qemuCaps, force); + if (ret == 0 && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) + ret = (persistent)(dom, driver, vm, dev, qemuCaps, force); /* update domain status forcibly because the domain status may be changed * even if we attach the device failed. For example, a new controller may @@ -4105,7 +4125,8 @@ qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); return qemuDomainModifyDeviceFlags(dom, xml, flags, - qemuDomainAttachDeviceLive); + qemuDomainAttachDeviceLive, + NULL); } static int @@ -4124,7 +4145,8 @@ qemuDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, VIR_DOMAIN_DEVICE_MODIFY_CONFIG | VIR_DOMAIN_DEVICE_MODIFY_FORCE, -1); return qemuDomainModifyDeviceFlags(dom, xml, flags, - qemuDomainUpdateDeviceLive); + qemuDomainUpdateDeviceLive, + NULL); } @@ -4135,7 +4157,8 @@ qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); return qemuDomainModifyDeviceFlags(dom, xml, flags, - qemuDomainDetachDeviceLive); + qemuDomainDetachDeviceLive, + NULL); } static int -- 1.7.4.2 From rlaager at wiktel.com Sun Apr 17 02:19:15 2011 From: rlaager at wiktel.com (Richard Laager) Date: Sat, 16 Apr 2011 21:19:15 -0500 Subject: [libvirt] [PATCH] Fix two out-of-date comments in LVM backend Message-ID: <1303006755.8664.29.camel@watermelon.coderich.net> I think this change is pretty self-explanatory. Richard -------------- next part -------------- A non-text attachment was scrubbed... Name: libvirt-lvm-comment-fix.patch Type: text/x-patch Size: 870 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 198 bytes Desc: This is a digitally signed message part URL: From matthias.bolte at googlemail.com Sun Apr 17 05:50:22 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 17 Apr 2011 07:50:22 +0200 Subject: [libvirt] [PATCH v2] Remove virConnectPtr from virRaiseErrorFull In-Reply-To: <4DA9AF7E.5080800@redhat.com> References: <20110416083243.GA9352@sbox> <4DA9AF7E.5080800@redhat.com> Message-ID: 2011/4/16 Eric Blake : > On 04/16/2011 02:32 AM, Matthias Bolte wrote: >> And from all related macros and functions. >> --- >> >> I posted v1 a year ago :) >> >> https://www.redhat.com/archives/libvir-list/2010-April/msg00164.html > > And I even ack'd it, but a lot has changed in the meantime. > >> +++ b/src/conf/cpu_conf.c >> @@ -32,7 +32,7 @@ >> ?#define VIR_FROM_THIS VIR_FROM_CPU >> >> ?#define virCPUReportError(code, ...) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ >> - ? ?virReportErrorHelper(NULL, VIR_FROM_CPU, code, __FILE__, ? ? ?\ >> + ? ?virReportErrorHelper(VIR_FROM_CPU, code, __FILE__, ? ? ? ? ? ?\ >> ? ? ? ? ? ? ? ? ? ? ? ? ? __FUNCTION__, __LINE__, __VA_ARGS__) > > The argument was truly unused, so this is a nice cleanup. > > ACK. > Thanks, pushed now. I can't remember why I didn't push v1 :) Matthias From matthias.bolte at googlemail.com Sun Apr 17 06:00:26 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 17 Apr 2011 08:00:26 +0200 Subject: [libvirt] [PATCH] xen: Replace statsErrorFunc with a macro In-Reply-To: <4DA9AF39.5070300@redhat.com> References: <20110416093128.GA6167@sbox> <4DA9AF39.5070300@redhat.com> Message-ID: 2011/4/16 Eric Blake : > On 04/16/2011 03:31 AM, Matthias Bolte wrote: >> Also mark error messages in block_stats.c for translation, add the >> new macro to the msg_gen functions in cfg.mk and add block_stats.c >> to po/POTFILES.in >> --- >> ?cfg.mk ? ? ? ? ? ? ? ?| ? ?1 + >> ?po/POTFILES.in ? ? ? ?| ? ?1 + >> ?src/xen/block_stats.c | ? 79 ++++++++++++++++++------------------------------ >> ?3 files changed, 32 insertions(+), 49 deletions(-) >> >> diff --git a/cfg.mk b/cfg.mk >> index 94db937..e54d170 100644 >> --- a/cfg.mk >> +++ b/cfg.mk >> @@ -420,6 +420,7 @@ msg_gen_function += xenUnifiedError >> ?msg_gen_function += xenXMError >> ?msg_gen_function += VIR_ERROR >> ?msg_gen_function += VIR_ERROR0 >> +msg_gen_function += statsError > > Nit - is it worth sorting these lines by function name? You really like your lists sorted :) > ACK. > Thanks, pushed. Matthias From matthias.bolte at googlemail.com Sun Apr 17 06:30:49 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 17 Apr 2011 08:30:49 +0200 Subject: [libvirt] [PATCH] Update and sort msg_gen_function list and mark unmarked messages Message-ID: <20110417063049.GA8304@sbox> Inspired by Eric Blake --- cfg.mk | 45 ++++++++++++++++++++++++++++++++++------- src/interface/netcf_driver.c | 43 ++++++++++++++++++--------------------- src/nodeinfo.c | 2 +- src/phyp/phyp_driver.c | 18 ++++++++-------- src/util/stats_linux.c | 2 +- 5 files changed, 68 insertions(+), 42 deletions(-) diff --git a/cfg.mk b/cfg.mk index e54d170..72dd69c 100644 --- a/cfg.mk +++ b/cfg.mk @@ -380,47 +380,76 @@ sc_prohibit_xmlGetProp: msg_gen_function = msg_gen_function += ESX_ERROR msg_gen_function += ESX_VI_ERROR -msg_gen_function += macvtapError -msg_gen_function += remoteError +msg_gen_function += PHYP_ERROR +msg_gen_function += VIR_ERROR +msg_gen_function += VIR_ERROR0 +msg_gen_function += VMX_ERROR +msg_gen_function += XENXS_ERROR +msg_gen_function += eventReportError +msg_gen_function += ifaceError +msg_gen_function += interfaceReportError +msg_gen_function += iptablesError msg_gen_function += lxcError -msg_gen_function += networkLog +msg_gen_function += libxlError +msg_gen_function += macvtapError msg_gen_function += networkReportError -msg_gen_function += oneError +msg_gen_function += nodeReportError msg_gen_function += openvzError +msg_gen_function += pciReportError msg_gen_function += qemuReportError msg_gen_function += qemudDispatchClientFailure msg_gen_function += regerror +msg_gen_function += remoteError msg_gen_function += remoteDispatchFormatError +msg_gen_function += statsError +msg_gen_function += streamsReportError +msg_gen_function += usbReportError msg_gen_function += umlReportError msg_gen_function += vah_error msg_gen_function += vah_warning msg_gen_function += vboxError msg_gen_function += virCommandError msg_gen_function += virConfError +msg_gen_function += virCPUReportError +msg_gen_function += virEventError msg_gen_function += virDomainReportError +msg_gen_function += virGenericReportError msg_gen_function += virHashError +msg_gen_function += virHookReportError +msg_gen_function += virInterfaceReportError +msg_gen_function += virJSONError msg_gen_function += virLibConnError msg_gen_function += virLibDomainError +msg_gen_function += virLibDomainSnapshotError +msg_gen_function += virLibInterfaceError +msg_gen_function += virLibNetworkError +msg_gen_function += virLibNodeDeviceError +msg_gen_function += virLibNWFilterError +msg_gen_function += virLibSecretError +msg_gen_function += virLibStoragePoolError +msg_gen_function += virLibStorageVolError msg_gen_function += virNetworkReportError msg_gen_function += virNodeDeviceReportError +msg_gen_function += virNWFilterReportError msg_gen_function += virRaiseError msg_gen_function += virReportErrorHelper msg_gen_function += virReportSystemError +msg_gen_function += virSecretReportError msg_gen_function += virSecurityReportError msg_gen_function += virSexprError +msg_gen_function += virSmbiosReportError +msg_gen_function += virSocketError +msg_gen_function += virStatsError msg_gen_function += virStorageReportError +msg_gen_function += virUtilError msg_gen_function += virXMLError msg_gen_function += virXenInotifyError msg_gen_function += virXenStoreError msg_gen_function += virXendError msg_gen_function += vmwareError msg_gen_function += xenapiSessionErrorHandler -msg_gen_function += libxlError msg_gen_function += xenUnifiedError msg_gen_function += xenXMError -msg_gen_function += VIR_ERROR -msg_gen_function += VIR_ERROR0 -msg_gen_function += statsError # Uncomment the following and run "make syntax-check" to see diagnostics # that are not yet marked for translation, but that need to be rewritten diff --git a/src/interface/netcf_driver.c b/src/interface/netcf_driver.c index 0190bf4..709f09b 100644 --- a/src/interface/netcf_driver.c +++ b/src/interface/netcf_driver.c @@ -102,11 +102,12 @@ static struct netcf_if *interfaceDriverGetNetcfIF(struct netcf *ncf, virInterfac int errcode = ncf_error(ncf, &errmsg, &details); if (errcode != NETCF_NOERROR) { interfaceReportError(netcf_to_vir_err(errcode), - "couldn't find interface named '%s' (netcf: %s - %s)", - ifinfo->name, errmsg, details ? details : ""); + _("couldn't find interface named '%s' (netcf: %s - %s)"), + ifinfo->name, errmsg, details ? details : ""); } else { interfaceReportError(VIR_ERR_NO_INTERFACE, - "couldn't find interface named '%s'", ifinfo->name); + _("couldn't find interface named '%s'"), + ifinfo->name); } } return iface; @@ -182,8 +183,7 @@ static int interfaceNumOfInterfaces(virConnectPtr conn) const char *errmsg, *details; int errcode = ncf_error(driver->netcf, &errmsg, &details); interfaceReportError(netcf_to_vir_err(errcode), - "%s (netcf: %s - %s)", - _("failed to get number of interfaces on host"), + _("failed to get number of interfaces on host (netcf: %s - %s)"), errmsg, details ? details : ""); } @@ -203,8 +203,7 @@ static int interfaceListInterfaces(virConnectPtr conn, char **const names, int n const char *errmsg, *details; int errcode = ncf_error(driver->netcf, &errmsg, &details); interfaceReportError(netcf_to_vir_err(errcode), - "%s (netcf: %s - %s)", - _("failed to list host interfaces"), + _("failed to list host interfaces (netcf: %s - %s)"), errmsg, details ? details : ""); } @@ -224,8 +223,7 @@ static int interfaceNumOfDefinedInterfaces(virConnectPtr conn) const char *errmsg, *details; int errcode = ncf_error(driver->netcf, &errmsg, &details); interfaceReportError(netcf_to_vir_err(errcode), - "%s (netcf: %s - %s)", - _("failed to get number of defined interfaces on host"), + _("failed to get number of defined interfaces on host (netcf: %s - %s)"), errmsg, details ? details : ""); } @@ -245,8 +243,7 @@ static int interfaceListDefinedInterfaces(virConnectPtr conn, char **const names const char *errmsg, *details; int errcode = ncf_error(driver->netcf, &errmsg, &details); interfaceReportError(netcf_to_vir_err(errcode), - "%s (netcf: %s - %s)", - _("failed to list host defined interfaces"), + _("failed to list host defined interfaces (netcf: %s - %s)"), errmsg, details ? details : ""); } @@ -269,11 +266,11 @@ static virInterfacePtr interfaceLookupByName(virConnectPtr conn, int errcode = ncf_error(driver->netcf, &errmsg, &details); if (errcode != NETCF_NOERROR) { interfaceReportError(netcf_to_vir_err(errcode), - "couldn't find interface named '%s' (netcf: %s - %s)", + _("couldn't find interface named '%s' (netcf: %s - %s)"), name, errmsg, details ? details : ""); } else { interfaceReportError(VIR_ERR_NO_INTERFACE, - "couldn't find interface named '%s'", name); + _("couldn't find interface named '%s'"), name); } goto cleanup; } @@ -301,13 +298,13 @@ static virInterfacePtr interfaceLookupByMACString(virConnectPtr conn, const char *errmsg, *details; int errcode = ncf_error(driver->netcf, &errmsg, &details); interfaceReportError(netcf_to_vir_err(errcode), - "couldn't find interface with MAC address '%s' (netcf: %s - %s)", + _("couldn't find interface with MAC address '%s' (netcf: %s - %s)"), macstr, errmsg, details ? details : ""); goto cleanup; } if (niface == 0) { interfaceReportError(VIR_ERR_NO_INTERFACE, - "couldn't find interface with MAC address '%s'", + _("couldn't find interface with MAC address '%s'"), macstr); goto cleanup; } @@ -351,8 +348,8 @@ static char *interfaceGetXMLDesc(virInterfacePtr ifinfo, const char *errmsg, *details; int errcode = ncf_error(driver->netcf, &errmsg, &details); interfaceReportError(netcf_to_vir_err(errcode), - "could not get interface XML description (netcf: %s - %s)", - errmsg, details ? details : ""); + _("could not get interface XML description (netcf: %s - %s)"), + errmsg, details ? details : ""); goto cleanup; } @@ -405,8 +402,8 @@ static virInterfacePtr interfaceDefineXML(virConnectPtr conn, const char *errmsg, *details; int errcode = ncf_error(driver->netcf, &errmsg, &details); interfaceReportError(netcf_to_vir_err(errcode), - "could not get interface XML description (netcf: %s - %s)", - errmsg, details ? details : ""); + _("could not get interface XML description (netcf: %s - %s)"), + errmsg, details ? details : ""); goto cleanup; } @@ -438,7 +435,7 @@ static int interfaceUndefine(virInterfacePtr ifinfo) { const char *errmsg, *details; int errcode = ncf_error(driver->netcf, &errmsg, &details); interfaceReportError(netcf_to_vir_err(errcode), - "failed to undefine interface %s (netcf: %s - %s)", + _("failed to undefine interface %s (netcf: %s - %s)"), ifinfo->name, errmsg, details ? details : ""); goto cleanup; } @@ -469,7 +466,7 @@ static int interfaceCreate(virInterfacePtr ifinfo, const char *errmsg, *details; int errcode = ncf_error(driver->netcf, &errmsg, &details); interfaceReportError(netcf_to_vir_err(errcode), - "failed to create (start) interface %s (netcf: %s - %s)", + _("failed to create (start) interface %s (netcf: %s - %s)"), ifinfo->name, errmsg, details ? details : ""); goto cleanup; } @@ -500,7 +497,7 @@ static int interfaceDestroy(virInterfacePtr ifinfo, const char *errmsg, *details; int errcode = ncf_error(driver->netcf, &errmsg, &details); interfaceReportError(netcf_to_vir_err(errcode), - "failed to destroy (stop) interface %s (netcf: %s - %s)", + _("failed to destroy (stop) interface %s (netcf: %s - %s)"), ifinfo->name, errmsg, details ? details : ""); goto cleanup; } @@ -530,7 +527,7 @@ static int interfaceIsActive(virInterfacePtr ifinfo) const char *errmsg, *details; int errcode = ncf_error(driver->netcf, &errmsg, &details); interfaceReportError(netcf_to_vir_err(errcode), - "failed to get status of interface %s (netcf: %s - %s)", + _("failed to get status of interface %s (netcf: %s - %s)"), ifinfo->name, errmsg, details ? details : ""); goto cleanup; } diff --git a/src/nodeinfo.c b/src/nodeinfo.c index facac15..e0221f0 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -239,7 +239,7 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo, buf++; if (*buf != ':' || !buf[1]) { nodeReportError(VIR_ERR_INTERNAL_ERROR, - "parsing cpuinfo cpu cores %c", *buf); + _("parsing cpuinfo cpu cores %c"), *buf); return -1; } if (virStrToLong_ui(buf+1, &p, 10, &id) == 0 diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 8f8c3ba..c65824a 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -3659,28 +3659,28 @@ phypBuildLpar(virConnectPtr conn, virDomainDefPtr def) virBuffer buf = VIR_BUFFER_INITIALIZER; if (!def->mem.cur_balloon) { - PHYP_ERROR(VIR_ERR_XML_ERROR,"%s", - _("Field \"\" on the domain XML file is missing or has " - "invalid value.")); + PHYP_ERROR(VIR_ERR_XML_ERROR, "%s", + _("Field on the domain XML file is missing or has " + "invalid value.")); goto cleanup; } if (!def->mem.max_balloon) { - PHYP_ERROR(VIR_ERR_XML_ERROR,"%s", - _("Field \"\" on the domain XML file is missing or" - " has invalid value.")); + PHYP_ERROR(VIR_ERR_XML_ERROR, "%s", + _("Field on the domain XML file is missing or " + "has invalid value.")); goto cleanup; } if (def->ndisks < 1) { PHYP_ERROR(VIR_ERR_XML_ERROR, "%s", - _("Domain XML must contain at least one \"\" element.")); + _("Domain XML must contain at least one element.")); goto cleanup; } if (!def->disks[0]->src) { - PHYP_ERROR(VIR_ERR_XML_ERROR,"%s", - _("Field \"\" under \"\" on the domain XML file is " + PHYP_ERROR(VIR_ERR_XML_ERROR, "%s", + _("Field under on the domain XML file is " "missing.")); goto cleanup; } diff --git a/src/util/stats_linux.c b/src/util/stats_linux.c index 173cdc5..e728b7b 100644 --- a/src/util/stats_linux.c +++ b/src/util/stats_linux.c @@ -107,7 +107,7 @@ linuxDomainInterfaceStats(const char *path, VIR_FORCE_FCLOSE(fp); virStatsError(VIR_ERR_INTERNAL_ERROR, - "/proc/net/dev: Interface not found"); + _("/proc/net/dev: Interface not found")); return -1; } -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 17 06:40:47 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 17 Apr 2011 08:40:47 +0200 Subject: [libvirt] [PATCH] Fix two out-of-date comments in LVM backend In-Reply-To: <1303006755.8664.29.camel@watermelon.coderich.net> References: <1303006755.8664.29.camel@watermelon.coderich.net> Message-ID: 2011/4/17 Richard Laager : > I think this change is pretty self-explanatory. > > Richard > ACK. I added you to the authors list and applied the patch, thanks. Matthias From laine at laine.org Sun Apr 17 09:31:13 2011 From: laine at laine.org (Laine Stump) Date: Sun, 17 Apr 2011 05:31:13 -0400 Subject: [libvirt] libvirt 0.9.0 crashes on first start since boot In-Reply-To: <4DA8420E.2020901@scripty.at> References: <4DA6D0DD.10405@scripty.at> <4DA713FD.9080500@laine.org> <4DA8420E.2020901@scripty.at> Message-ID: <4DAAB361.9080105@laine.org> On 04/15/2011 09:03 AM, Thomas Treutner wrote: > > I removed dnsmasq startup from the runlevel, now it works fine. I have > seen dnsmasq errors for a long time, but I didn't really care too much > about, as I don't need dnsmasq and the warnings didn't stop libvrit > from working. I think I'll just deinstall dnsmasq. Are you sure you want to uninstall dnsmasq, and not just disable it in the system config? If you uninstall dnsmasq, libvirt will fail to start the virtual networks - it uses dnsmasq to provide DNS for those networks even if you don't specify a dhcp range or hosts. From kamezawa.hiroyu at jp.fujitsu.com Sun Apr 17 23:45:24 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Mon, 18 Apr 2011 08:45:24 +0900 Subject: [libvirt] [RFC][PATCHv1 2/5] libvirt - new API for getting percpu statistics of VM In-Reply-To: <20110416135251.GI2641@amd.home.annexia.org> References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> <20110415160452.63bd9216.kamezawa.hiroyu@jp.fujitsu.com> <20110416135251.GI2641@amd.home.annexia.org> Message-ID: <20110418084524.7a5dda64.kamezawa.hiroyu@jp.fujitsu.com> On Sat, 16 Apr 2011 14:52:51 +0100 "Richard W.M. Jones" wrote: > On Fri, Apr 15, 2011 at 04:04:52PM +0900, KAMEZAWA Hiroyuki wrote: > [...] > > The idea and the implementation is sound. However I have a problem > with this proposed API: > > > +typedef struct _virDomainPcpuStat virDomainPcpuStatStruct; > > + > > +struct _virDomainPcpuStat { > > + unsigned long long cpuTime; > > +}; > > + > > +typedef virDomainPcpuStatStruct *virDomainPcpuStatPtr; > > [...] > > > /** > > + * virDomainPcpuStats: > > + * @dom: pointer to the domain object > > + * @stats: nr_stats-sized array of stat structures (returned) > > + * @nr_stats: number of cpu statistics requested > > + * @flags: unused, always pass 0 > > + * > > + * This function provides per-cpu statistics for the domain. 'cpu' here means > > + * not vcpu. > > + * > > + * Up to 'nr_stats' elements of 'stats' will be populated with cpu statistics > > + * from the domain. Only statistics supported by the domain, the driver, and > > + * this version of libvirt will be returned. > > + * > > + * Now, only cpuTime per cpu is reported in nanoseconds. > > + * > > + * Returns: The number of stats provided or -1 in case of failure. > > + */ > > +int virDomainPcpuStats (virDomainPtr dom, virDomainPcpuStatPtr stats, > > + unsigned int nr_stats, unsigned int flags) > > Am I correct that the caller sets nr_stats == number of physical > cores, and allocates an array of nr_stats * virDomainPcpuStats > structs? > > We could never add more elements to the _virDomainPcpuStat structure, > because that would break the ABI for existing callers. (Or I guess we > could use the flags field). > > I think we should forget about the structure, and just use an array of > unsigned long long's, but I'd like to hear what others think. > I received the same reply from others and I'd like to go that way. > Is it likely that we would return other per-physical-CPU stats in > future? > Not sure. But if some guy adds more statistics to cpuacct cgroup, as # of vmenter/vmexit etc...we can count it. So, I'd like to pass 'What you want' flag as VirDomainPhysicalCpuStat(domain, unsigned long long *starts, int nr_stats, int what_I_want) and then, pass VIT_DOMAIN_PHYSICAL_CPU_STAT_CPUTIME as it argument. what_I_want. Thanks, -Kame From kamezawa.hiroyu at jp.fujitsu.com Sun Apr 17 23:52:53 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Mon, 18 Apr 2011 08:52:53 +0900 Subject: [libvirt] [PATCHv9 1/4] libvirt/qemu - persistent modification of devices. In-Reply-To: <4DA8B7AD.4010308@redhat.com> References: <20110413114717.989199d5.kamezawa.hiroyu@jp.fujitsu.com> <20110413114931.a3357044.kamezawa.hiroyu@jp.fujitsu.com> <4DA8B7AD.4010308@redhat.com> Message-ID: <20110418085253.ef9c4088.kamezawa.hiroyu@jp.fujitsu.com> On Fri, 15 Apr 2011 15:25:01 -0600 Eric Blake wrote: > On 04/12/2011 08:49 PM, KAMEZAWA Hiroyuki wrote: > > > > Now, qemudDomainAttachDeviceFlags() and qemudDomainDetachDeviceFlags() > > doesn't support VIR_DOMAIN_DEVICE_MODIFY_CONFIG. By this, virsh's > > at(de)tatch-device --persistent cannot modify qemu config. > > (Xen allows it.) > > > > This patch is a base patch for adding support of devices in > > step by step manner. Following patches will add some device > > support. > > > > Signed-off-by: KAMEZAWA Hiroyuki > > > > Changelog: v8->v9 > > - removed unnecessary comments. > > It's taken quite a few iterations, but I've finally scheduled time to > start reviewing it. > Thank you. > > +static int qemuDomainModifyDevicePersistent(virDomainPtr dom, > > + const char *xml, > > + unsigned int attach, > > You missed one. You changed attach and detach, but not update. This > parameter can usefully forward to all three types of updates. > > In fact, I think I'd like to go one further, and refactor things further > before we start adding persistent devices. > Hmm. > It seems like there are two steps in all three categories of functions - > obtain the locks, then do the work. I like how you've factored things > into one function that obtains the locks then forwards on to other > functions that do the work. Furthermore, I don't see any reason why we > can't support LIVE|CONFIG at once, provided we know for which devices we > can make a successful CONFIG change. > ok. > > + * When both of MODIFY_CONFIG and MODIFY_LIVE are passed at the same time, > > + * return error for now. We should support this later. > > + */ > > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { > > + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", > > + _("cannot modify active domain and its definition " > > + "at the same time.")); > > + return -1; > > + } > > You are right that it's not implemented yet, but no worse than what we > already have, so it's not a regression. But I think it is doable, by > rewriting this into one giant function: > > 1. obtain lock > 2. if CURRENT, convert to LIVE or CONFIG > 3. if LIVE but not active, error > 4. if CONFIG but not persistent, error > 5. if CONFIG call, make temporary vmdef and modify that, or quit if that > device is not supported yet > 6. if LIVE, make live modification; if that errors out, quit > 7. if CONFIG, make temporary vmdef permanent (hopefully it succeeds, > because we don't roll back the LIVE portion of LIVE|CONFIG) > 8. clean up locks > Sure, I'll include that logic. > I'll propose a followup patch that tries to capture this idiom in code. > > > +static int qemudDomainAttachDeviceFlags(virDomainPtr dom, > > + const char *xml, > > + unsigned int flags) > > +{ > > + int ret = -1; > > + > > + virCheckFlags((VIR_DOMAIN_DEVICE_MODIFY_CONFIG | > > + VIR_DOMAIN_DEVICE_MODIFY_LIVE), -1); > > This causes a change in behavior. Previously, we silently ignored > VIR_DOMAIN_DEVICE_MODIFY_FORCE, now we error out. But overall, that's a > good change (FORCE only made sense for ModifyDevice, not Attach), and it > goes to show that we don't use virCheckFlags on nearly enough APIs. > will fix. > > + > > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) > > + ret = qemuDomainModifyDevicePersistent(dom, xml, 1, flags); > > + else if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) > > + ret = qemudDomainAttachDevice(dom, xml); > > For example, here your logic is wrong. You covered the CONFIG|LIVE case > with qemuDomainModifyDevicePersistent (by erroring out), but you _don't_ > cover the CURRENT case (which should be either CONFIG or LIVE). But to > learn if the vm is active, you have to obtain the lock, and the way > you've written this, you've already forwarded into one of the two > routines. Rather, all the public entries should forward into the one > giant helper routine which grabs the locks, checks the flags, then calls > into the right callbacks. > > > @@ -4141,14 +4242,19 @@ cleanup: > > > > static int qemudDomainDetachDeviceFlags(virDomainPtr dom, > > const char *xml, > > - unsigned int flags) { > > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > > - qemuReportError(VIR_ERR_OPERATION_INVALID, > > - "%s", _("cannot modify the persistent configuration of a domain")); > > - return -1; > > - } > > + unsigned int flags) > > +{ > > + int ret = -1; > > + > > + virCheckFlags((VIR_DOMAIN_DEVICE_MODIFY_CONFIG | > > + VIR_DOMAIN_DEVICE_MODIFY_LIVE), -1); > > Another change in noisily rejecting FORCE, but I think it's good. > I'll learn your patch and merge it to mine. It seems longer way than I thought. Thanks, -Kame From wency at cn.fujitsu.com Mon Apr 18 01:41:21 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Mon, 18 Apr 2011 09:41:21 +0800 Subject: [libvirt] [PATCH V3 2/2] enhance processWatchdogEvent() In-Reply-To: <4DA873FA.8080009@redhat.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1CED.20202@cn.fujitsu.com> <4DA75CD7.9080908@redhat.com> <4DA7B76B.3010308@cn.fujitsu.com> <4DA873FA.8080009@redhat.com> Message-ID: <4DAB96C1.7000109@cn.fujitsu.com> At 04/16/2011 12:36 AM, Eric Blake Write: > On 04/14/2011 09:11 PM, Wen Congyang wrote: >> This patch do the following two things: > > s/do/does/ > >> 1. hold an extra reference while handling watchdog event >> If the domain is not persistent, and qemu quits unexpectedly before >> calling processWatchdogEvent(), vm will be freed and the function >> processWatchdogEvent() will be dangerous. >> >> 2. unlock qemu driver and vm before returning from processWatchdogEvent() >> When the function processWatchdogEvent() failed, we only free wdEvent, >> but forget to unlock qemu driver and vm, free dumpfile. >> >> >> --- >> src/qemu/qemu_driver.c | 34 ++++++++++++++++++++++------------ >> src/qemu/qemu_process.c | 4 ++++ >> 2 files changed, 26 insertions(+), 12 deletions(-) > > Looks like your v2 caught my review comments correctly. But I found one > more issue: > >> +++ b/src/qemu/qemu_process.c >> @@ -428,6 +428,10 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, >> if (VIR_ALLOC(wdEvent) == 0) { >> wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP; >> wdEvent->vm = vm; >> + /* Hold an extra reference because we can't allow 'vm' to be >> + * deleted before handling watchdog event is finished. >> + */ >> + virDomainObjRef(vm); >> ignore_value(virThreadPoolSendJob(driver->workerPool, wdEvent)); > > Now that we have increased the ref count, we should decrease it if we > are unable to send a job to the thread pool. That is, replace the > ignore_value() with: > > if (virThreadPoolSendJob(...) < 0) { > virDomainObjUnref(vm); > VIR_FREE(wdEvent); > } > > ACK with that change squashed in. I have pushed this series patch with this chaged squashed in. Thanks for reviewing. > From wency at cn.fujitsu.com Mon Apr 18 04:59:56 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Mon, 18 Apr 2011 12:59:56 +0800 Subject: [libvirt] [PATCH 4/4] qemu: add plumbing for persistent device changes In-Reply-To: <1302967702-30065-4-git-send-email-eblake@redhat.com> References: <4DA8B7AD.4010308@redhat.com> <1302967702-30065-1-git-send-email-eblake@redhat.com> <1302967702-30065-4-git-send-email-eblake@redhat.com> Message-ID: <4DABC54C.3020100@cn.fujitsu.com> At 04/16/2011 11:28 PM, Eric Blake Write: > There's still work to add persistent callback functions, and to > make sure this all works, but this demonstrates how having a > single function makes it easy to support flags for all three > types of device modifications. > > * src/qemu/qemu_driver.c (qemuDomainModifyDeviceFlags): Add > parameter, and support VIR_DOMAIN_DEVICE_MODIFY_CURRENT. > (qemuDomainAttachDeviceFlags, qemuDomainUpdateDeviceFlags) > (qemuDomainDetachDeviceFlags): Update callers. > --- > > After this point, we can use Kame's patch 1/4 to add in the > persistent function callbacks (with slight tweaks to their > signatures), and 2/4 to make it easier to to temporary > modifications to a config: > > if (flags & CONFIG) { > create temporary def > call persistent callback > } > if (flags & LIVE) { > call live callback > } > if (no errors) > commit temporary def and live state changes, as needed > > But with the benefit that CURRENT support is now provided. > > src/qemu/qemu_driver.c | 47 +++++++++++++++++++++++++++++++++++------------ > 1 files changed, 35 insertions(+), 12 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 4f0a057..8c978be 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -4031,7 +4031,8 @@ cleanup: > static int > qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > unsigned int flags, > - qemuDomainModifyDeviceCallback cb) > + qemuDomainModifyDeviceCallback live, > + qemuDomainModifyDeviceCallback persistent) > { > struct qemud_driver *driver = dom->conn->privateData; > virDomainObjPtr vm; > @@ -4039,12 +4040,7 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > virBitmapPtr qemuCaps = NULL; > int ret = -1; > bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; > - > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > - qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", > - _("cannot modify domain persistent configuration")); > - return -1; > - } > + bool active; > > qemuDriverLock(driver); > vm = virDomainFindByUUID(&driver->domains, dom->uuid); > @@ -4059,12 +4055,32 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) > goto cleanup; > > - if (!virDomainObjIsActive(vm)) { > + active = virDomainObjIsActive(vm); > + > + if ((flags & (VIR_DOMAIN_DEVICE_MODIFY_LIVE > + | VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) == 0) > + flags |= (active ? VIR_DOMAIN_DEVICE_MODIFY_LIVE > + : VIR_DOMAIN_DEVICE_MODIFY_CONFIG); > + > + if ((flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) && !active) { > qemuReportError(VIR_ERR_OPERATION_INVALID, > "%s", _("cannot modify device on inactive domain")); > goto endjob; > } > > + if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) { > + qemuReportError(VIR_ERR_OPERATION_INVALID, > + "%s", _("cannot modify device on transient domain")); > + goto endjob; > + } > + > + /* XXX add persistent support */ > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { kamezawa-san is writing patch to support persistent device modification(attach/detach) and Hu Tao is writing patch to support persistent device modification(update). We can detect whether persistent device modification is supported like this: if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !persistent) { So the caller can pass NULL when persistent device modification is not supported safely. > + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", > + _("cannot modify domain persistent configuration")); > + return -1; We should goto endjob to do some cleanup. > + } > + > dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, > VIR_DOMAIN_XML_INACTIVE); > if (dev == NULL) > @@ -4075,7 +4091,11 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > &qemuCaps) < 0) > goto endjob; > > - ret = (cb)(dom, driver, vm, dev, qemuCaps, force); > + ret = 0; > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) > + ret = (live)(dom, driver, vm, dev, qemuCaps, force); > + if (ret == 0 && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) > + ret = (persistent)(dom, driver, vm, dev, qemuCaps, force); > > /* update domain status forcibly because the domain status may be changed > * even if we attach the device failed. For example, a new controller may > @@ -4105,7 +4125,8 @@ qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, > virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | > VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); > return qemuDomainModifyDeviceFlags(dom, xml, flags, > - qemuDomainAttachDeviceLive); > + qemuDomainAttachDeviceLive, > + NULL); > } > > static int > @@ -4124,7 +4145,8 @@ qemuDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, > VIR_DOMAIN_DEVICE_MODIFY_CONFIG | > VIR_DOMAIN_DEVICE_MODIFY_FORCE, -1); > return qemuDomainModifyDeviceFlags(dom, xml, flags, > - qemuDomainUpdateDeviceLive); > + qemuDomainUpdateDeviceLive, > + NULL); > } > > > @@ -4135,7 +4157,8 @@ qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, > virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | > VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); > return qemuDomainModifyDeviceFlags(dom, xml, flags, > - qemuDomainDetachDeviceLive); > + qemuDomainDetachDeviceLive, > + NULL); > } > > static int The other modification and the other 3 patches look good to me. From kamezawa.hiroyu at jp.fujitsu.com Mon Apr 18 08:25:39 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Mon, 18 Apr 2011 17:25:39 +0900 Subject: [libvirt] [PATCH 4/4] qemu: add plumbing for persistent device changes In-Reply-To: <4DABC54C.3020100@cn.fujitsu.com> References: <4DA8B7AD.4010308@redhat.com> <1302967702-30065-1-git-send-email-eblake@redhat.com> <1302967702-30065-4-git-send-email-eblake@redhat.com> <4DABC54C.3020100@cn.fujitsu.com> Message-ID: <20110418172539.5f285bb2.kamezawa.hiroyu@jp.fujitsu.com> On Mon, 18 Apr 2011 12:59:56 +0800 Wen Congyang wrote: > At 04/16/2011 11:28 PM, Eric Blake Write: - qemuDomainDetachDeviceLive); > > + qemuDomainDetachDeviceLive, > > + NULL); > > } > > > > static int > > The other modification and the other 3 patches look good to me. > > I'll include Eric's series to the next v10 (with some modification). Next one will includes all Attach/Detach/Update consolidation and persistent modifications. Thanks, -Kame From laijs at cn.fujitsu.com Mon Apr 18 08:39:35 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Mon, 18 Apr 2011 16:39:35 +0800 Subject: [libvirt] [PATCH 6/6] qemu, inject-nmi: Implement the driver methods In-Reply-To: <4DA88ADE.7050208@redhat.com> References: <4DA52D1A.1000307@cn.fujitsu.com> <4DA52E3E.10402@cn.fujitsu.com> <4DA88ADE.7050208@redhat.com> Message-ID: <4DABF8C7.4060804@cn.fujitsu.com> On 04/16/2011 02:13 AM, Eric Blake wrote: > On 04/12/2011 11:01 PM, Lai Jiangshan wrote: >> +++ b/src/qemu/qemu_driver.c >> @@ -1701,6 +1701,48 @@ static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) >> return qemudDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM); >> } >> >> +static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags) >> +{ >> + struct qemud_driver *driver = domain->conn->privateData; >> + virDomainObjPtr vm = NULL; >> + int ret = -1; >> + qemuDomainObjPrivatePtr priv; >> + > > Right here, you should have a virCheckFlags(0, -1) to enforce that we > don't honor any flags for now. At which point, you don't need to pass > flags on down to the monitor calls. > >> +++ b/src/qemu/qemu_monitor_json.c >> @@ -2513,3 +2513,32 @@ cleanup: >> >> return ret; >> } >> + >> +int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon, unsigned int flags ATTRIBUTE_UNUSED) >> +{ > > Since neither monitor needed flags this low, you don't have to propogate > it any further than qemu_driver.c's virCheckFlags(). > >> + int ret; >> + virJSONValuePtr cmd; >> + virJSONValuePtr reply = NULL; >> + >> + /* >> + * FIXME: qmp nmi is not supported until qemu-0.16.0, >> + * use human-monitor-command instead temporary. >> + * >> + * FIXME: qemu's nmi command just injects NMI to a specified CPU, >> + * use "nmi 0" instead temporary. >> + */ >> + cmd = qemuMonitorJSONMakeCommand("human-monitor-command", >> + "s:command-line", "nmi 0", >> + NULL); > > We've already got a preferred form for issuing HMP commands from JSON. > Rather than building up human-monitor-command manually, you should > instead be using qemuMonitorTextInjectNMI; for example, see how > qemuMonitorJSONDriveDel falls back to hmp. This also covers the case of > a qemu binary that has JSON but not hmp giving a more useful error message. > >> +++ b/src/qemu/qemu_monitor_text.c >> @@ -2628,3 +2628,23 @@ int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, >> >> return ret; >> } >> + >> +int qemuMonitorTextInjectNMI(qemuMonitorPtr mon, unsigned int flags ATTRIBUTE_UNUSED) >> +{ >> + const char *cmd = "nmi 0"; >> + char *reply = NULL; >> + >> + /* >> + * FIXME: qemu's nmi command just injects NMI to a specified CPU, >> + * use "nmi 0" instead temporary. >> + */ > > This bothers me. Is it possible to inject NMI to a particular CPU in > bare-metal hardware? If so, then we ought to support that in the API. > The real world NMI button just sends NMI to all cpus, the qemu side code will also be modified that hmp nmi command just sends NMI to all CPU and the cpu-index parameter will be removed. My original qemu side patch lefts cpu-index parameter for kernel debugging, but the qemu guys persuade me that inject-nmi command should just send NMI to CPUs. I accepted it. I think the libvirt will handle it at the same way. Thanks, Lai. From gross at univention.de Mon Apr 18 09:16:33 2011 From: gross at univention.de (=?UTF-8?q?Markus=20Gro=C3=9F?=) Date: Mon, 18 Apr 2011 11:16:33 +0200 Subject: [libvirt] [PATCHv2] Add cputune support to libxl driver Message-ID: <1303118193-2965-1-git-send-email-gross@univention.de> Here is a new version of this patch: https://www.redhat.com/archives/libvir-list/2011-April/msg00337.html v2: - store the cputune info for the whole runtime of the domain - remove cputune info when domain is destroyed The nodeGetInfo code had to be moved into a helper function to reuse it without a virConnectPtr. --- src/libxl/libxl_driver.c | 159 +++++++++++++++++++++++++++++++++++----------- 1 files changed, 122 insertions(+), 37 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 3040914..247d78e 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -199,6 +199,46 @@ libxlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, virDomainObjUnlock(vm); } +static int +libxlDoNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info) +{ + libxl_physinfo phy_info; + const libxl_version_info* ver_info; + struct utsname utsname; + + if (libxl_get_physinfo(&driver->ctx, &phy_info)) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("libxl_get_physinfo_info failed")); + return -1; + } + + if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("libxl_get_version_info failed")); + return -1; + } + + uname(&utsname); + if (virStrncpy(info->model, + utsname.machine, + strlen(utsname.machine), + sizeof(info->model)) == NULL) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("machine type %s too big for destination"), + utsname.machine); + return -1; + } + + info->memory = phy_info.total_pages * (ver_info->pagesize / 1024); + info->cpus = phy_info.nr_cpus; + info->nodes = phy_info.nr_nodes; + info->cores = phy_info.cores_per_socket; + info->threads = phy_info.threads_per_core; + info->sockets = 1; + info->mhz = phy_info.cpu_khz / 1000; + return 0; +} + /* * Cleanup function for domain that has reached shutoff state. * @@ -210,6 +250,7 @@ libxlVmCleanup(libxlDriverPrivatePtr driver, virDomainObjPtr vm) libxlDomainObjPrivatePtr priv = vm->privateData; int vnc_port; char *file; + int i; if (priv->eventHdl >= 0) { virEventRemoveHandle(priv->eventHdl); @@ -238,6 +279,16 @@ libxlVmCleanup(libxlDriverPrivatePtr driver, virDomainObjPtr vm) } } + /* Remove any cputune settings */ + if (vm->def->cputune.nvcpupin) { + for (i = 0; i < vm->def->cputune.nvcpupin; ++i) { + VIR_FREE(vm->def->cputune.vcpupin[i]->cpumask); + VIR_FREE(vm->def->cputune.vcpupin[i]); + } + VIR_FREE(vm->def->cputune.vcpupin); + vm->def->cputune.nvcpupin = 0; + } + if (virAsprintf(&file, "%s/%s.xml", driver->stateDir, vm->def->name) > 0) { if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR) VIR_DEBUG("Failed to remove domain XML for %s", vm->def->name); @@ -391,6 +442,62 @@ error: return -1; } +static int +libxlDomainSetVcpuAffinites(libxlDriverPrivatePtr driver, virDomainObjPtr vm) +{ + libxlDomainObjPrivatePtr priv = vm->privateData; + virDomainDefPtr def = vm->def; + libxl_cpumap map; + uint8_t *cpumask = NULL; + uint8_t *cpumap = NULL; + virNodeInfo nodeinfo; + size_t cpumaplen; + unsigned int pos; + int vcpu, i; + int ret = -1; + + if (libxlDoNodeGetInfo(driver, &nodeinfo) < 0) + goto cleanup; + + cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo)); + + for (vcpu = 0; vcpu < def->cputune.nvcpupin; ++vcpu) { + if (vcpu != def->cputune.vcpupin[vcpu]->vcpuid) + continue; + + if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) { + virReportOOMError(); + goto cleanup; + } + + cpumask = (uint8_t*) def->cputune.vcpupin[vcpu]->cpumask; + + for (i = 0; i < VIR_DOMAIN_CPUMASK_LEN; ++i) { + if (cpumask[i]) { + pos = i / 8; + cpumap[pos] |= 1 << (i % 8); + } + } + + map.size = cpumaplen; + map.map = cpumap; + + if (libxl_set_vcpuaffinity(&priv->ctx, def->id, vcpu, &map) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to pin vcpu '%d' with libxenlight"), vcpu); + goto cleanup; + } + + VIR_FREE(cpumap); + } + + ret = 0; + +cleanup: + VIR_FREE(cpumap); + return ret; +} + /* * Start a domain through libxenlight. * @@ -440,6 +547,9 @@ libxlVmStart(libxlDriverPrivatePtr driver, if (libxlCreateDomEvents(vm) < 0) goto error; + if (libxlDomainSetVcpuAffinites(driver, vm) < 0) + goto error; + if (!start_paused) { libxl_domain_unpause(&priv->ctx, domid); vm->state = VIR_DOMAIN_RUNNING; @@ -756,7 +866,7 @@ libxlReload(void) &libxl_driver->domains, libxl_driver->configDir, libxl_driver->autostartDir, - 0, NULL, libxl_driver); + 1, NULL, libxl_driver); virHashForEach(libxl_driver->domains.objs, libxlAutostartDomain, libxl_driver); @@ -869,42 +979,7 @@ libxlGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) static int libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) { - libxl_physinfo phy_info; - const libxl_version_info* ver_info; - libxlDriverPrivatePtr driver = conn->privateData; - struct utsname utsname; - - if (libxl_get_physinfo(&driver->ctx, &phy_info)) { - libxlError(VIR_ERR_INTERNAL_ERROR, - _("libxl_get_physinfo_info failed")); - return -1; - } - - if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) { - libxlError(VIR_ERR_INTERNAL_ERROR, - _("libxl_get_version_info failed")); - return -1; - } - - uname(&utsname); - if (virStrncpy(info->model, - utsname.machine, - strlen(utsname.machine), - sizeof(info->model)) == NULL) { - libxlError(VIR_ERR_INTERNAL_ERROR, - _("machine type %s too big for destination"), - utsname.machine); - return -1; - } - - info->memory = phy_info.total_pages * (ver_info->pagesize / 1024); - info->cpus = phy_info.nr_cpus; - info->nodes = phy_info.nr_nodes; - info->cores = phy_info.cores_per_socket; - info->threads = phy_info.threads_per_core; - info->sockets = 1; - info->mhz = phy_info.cpu_khz / 1000; - return 0; + return libxlDoNodeGetInfo(conn->privateData, info); } static char * @@ -1712,6 +1787,16 @@ libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap, _("Failed to pin vcpu '%d' with libxenlight"), vcpu); goto cleanup; } + + if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + "%s", _("failed to update or add vcpupin xml")); + goto cleanup; + } + + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) + goto cleanup; + ret = 0; cleanup: -- 1.7.1 From jdenemar at redhat.com Mon Apr 18 09:49:17 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Mon, 18 Apr 2011 11:49:17 +0200 Subject: [libvirt] [PATCH v2] Experimental libvirtd upstart job Message-ID: <16d6b0d80afabe455f5d00e4a696913c281d0649.1303120085.git.jdenemar@redhat.com> From: Alan Pevec To install it, disable libvirtd sysv initscript: chkconfig libvirtd off service libvirtd stop and enable libvirtd upstart job: cp /usr/share/doc/libvirt-*/libvirtd.upstart \ /etc/init/libvirtd.conf initctl reload-configuration initctl start libvirtd Test: initctl status libvirtd libvirtd start/running, process 3929 killall -9 libvirtd initctl status libvirtd libvirtd start/running, process 4047 I looked into the possibility to use the upstart script from Ubuntu or at least getting inspiration from it but that's not possible. "expect daemon" is a nice thing but it only works if the process is defined with exec stanza instead of script ... no script. Unfortunately, with exec stanza environment variables can only be set within upstart script (i.e., configuration in /etc/sysconfig/libvirtd can't work). Hence, we need to use script stanza, source sysconfig, and execute libvirtd without --daemon. For similar reasons we can't use limit stanza and need to handle DAEMON_COREFILE_LIMIT in job's script. --- Notes: Version 2: - I took Allan's script and modified it a bit - DAEMON_COREFILE_LIMIT from sysconfig works - PID file handling limited to just removing it daemon/Makefile.am | 1 + daemon/libvirtd.upstart | 46 ++++++++++++++++++++++++++++++++++++++++++++++ libvirt.spec.in | 1 + 3 files changed, 48 insertions(+), 0 deletions(-) create mode 100644 daemon/libvirtd.upstart diff --git a/daemon/Makefile.am b/daemon/Makefile.am index cacec1c..af71188 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -26,6 +26,7 @@ EXTRA_DIST = \ remote_generate_stubs.pl \ libvirtd.conf \ libvirtd.init.in \ + libvirtd.upstart \ libvirtd.policy-0 \ libvirtd.policy-1 \ libvirtd.sasl \ diff --git a/daemon/libvirtd.upstart b/daemon/libvirtd.upstart new file mode 100644 index 0000000..fd1d951 --- /dev/null +++ b/daemon/libvirtd.upstart @@ -0,0 +1,46 @@ +# libvirtd upstart job +# +# XXX wait for rc to get all dependent initscripts started +# from sysv libvirtd initscript: Required-Start: $network messagebus +start on stopped rc RUNLEVEL=[345] +stop on runlevel [!345] + +respawn + +script + LIBVIRTD_CONFIG= + LIBVIRTD_ARGS= + KRB5_KTNAME=/etc/libvirt/krb5.tab + + if [ -f /etc/sysconfig/libvirtd ]; then + . /etc/sysconfig/libvirtd + fi + + export QEMU_AUDIO_DRV + export SDL_AUDIODRIVER + export KRB5_KTNAME + + LIBVIRTD_CONFIG_ARGS= + if [ -n "$LIBVIRTD_CONFIG" ]; then + LIBVIRTD_CONFIG_ARGS="--config $LIBVIRTD_CONFIG" + fi + + # DAEMON_COREFILE_LIMIT from /etc/sysconfig/libvirtd is not handled + # automatically + if [ -n "$DAEMON_COREFILE_LIMIT" ]; then + ulimit -c "$DAEMON_COREFILE_LIMIT" + fi + + # Clean up a pidfile that might be left around + rm -f /var/run/libvirtd.pid + + mkdir -p /var/cache/libvirt + rm -rf /var/cache/libvirt/* + + exec /usr/sbin/libvirtd $LIBVIRTD_CONFIG_ARGS $LIBVIRTD_ARGS +end script + +post-stop script + rm -f $PIDFILE + rm -rf /var/cache/libvirt/* +end script diff --git a/libvirt.spec.in b/libvirt.spec.in index 4162fba..bf6b9df 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -895,6 +895,7 @@ fi %{_sysconfdir}/libvirt/nwfilter/*.xml %{_sysconfdir}/rc.d/init.d/libvirtd +%doc daemon/libvirtd.upstart %config(noreplace) %{_sysconfdir}/sysconfig/libvirtd %config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf %if %{with_dtrace} -- 1.7.5.rc1 From berrange at redhat.com Mon Apr 18 11:30:45 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 18 Apr 2011 12:30:45 +0100 Subject: [libvirt] [PATCHv2 1/6] virNodeGetCPUTime: Expose new API In-Reply-To: <20110410045856.GI24838@redhat.com> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> <20110408203312.90723b75.usui@mxm.nes.nec.co.jp> <20110410045856.GI24838@redhat.com> Message-ID: <20110418113045.GE4648@redhat.com> On Sun, Apr 10, 2011 at 12:58:56PM +0800, Daniel Veillard wrote: > On Fri, Apr 08, 2011 at 08:33:12PM +0900, Minoru Usui wrote: > > virNodeGetCPUTime: Expose new API > > > > Signed-off-by: Minoru Usui > > --- > > include/libvirt/libvirt.h.in | 64 ++++++++++++++++++++++++++++++++++++++++++ > > src/libvirt_public.syms | 5 +++ > > 2 files changed, 69 insertions(+), 0 deletions(-) > > > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > > index bd36015..154c138 100644 > > --- a/include/libvirt/libvirt.h.in > > +++ b/include/libvirt/libvirt.h.in > > @@ -228,6 +228,57 @@ struct _virNodeInfo { > > unsigned int threads;/* number of threads per core */ > > }; > > > > +/** > > + * virNodeCpuTime: > > + * > > + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing > > + * the information for the cpu time of the node. > > + */ > > + > > +/** > > + * Cpu Time Statistics Tags: > > + */ > > +typedef enum { > > + /* > > + * The cumulative CPU time which spends by kernel, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_KERNEL = 0, > > + /* > > + * The cumulative CPU time which spends by user processes, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_USER = 1, > > + /* > > + * The cumulative idle CPU time, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_IDLE = 2, > > + /* > > + * The cumulative I/O wait CPU time, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_IOWAIT = 3, > > + /* > > + * The CPU utilization. > > + * The usage value is in percent and 100% represents all CPUs on > > + * the server. > > + */ > > + VIR_NODE_CPU_TIME_UTILIZATION = 4, > > + > > + /* > > + * The number of statistics supported by this version of the interface. > > + * To add new statistics, add them to the enum and increase this value. > > + */ > > + VIR_NODE_CPU_TIME_NR = 5, > > +} virNodeCpuTimeTags; > > + > > +typedef struct _virNodeCpuTime virNodeCpuTime; > > + > > +struct _virNodeCpuTime { > > + virNodeCpuTimeTags tag; > > + unsigned long long val; > > +}; > > NACK, the size of an enum is not defined by the C language and > hence is compiler dependant. We cannot use it as a component of a > structure in the API. > > > /** > > * virDomainSchedParameterType: > > @@ -460,6 +511,14 @@ int virDomainMigrateSetMaxSpeed(virDomainPtr domain, > > typedef virNodeInfo *virNodeInfoPtr; > > > > /** > > + * virNodeCpuTimePtr: > > + * > > + * a virNodeCpuTimePtr is a pointer to a virNodeCpuTime structure. > > + */ > > + > > +typedef virNodeCpuTime *virNodeCpuTimePtr; > > + > > +/** > > * virConnectFlags > > * > > * Flags when opening a connection to a hypervisor > > @@ -593,6 +652,11 @@ int virNodeGetInfo (virConnectPtr conn, > > virNodeInfoPtr info); > > char * virConnectGetCapabilities (virConnectPtr conn); > > > > +int virNodeGetCpuTime (virConnectPtr conn, > > + virNodeCpuTimePtr stats, > > + unsigned int nr_stats, > > + unsigned int flags); > > + > > I don't understand how the API is suppoed to work. Suppose you want > the cumulative CPU time, how do you ask for it ? Seems you can't ! You > just ask for a big stucture hoping that on return you may find it within > the results. That looks broken to me. This is the same design we've used in the virDomainGetMemoryStats, virDomainGetBlkioParameters, virDomainGetSchedularParamters without any undue trouble. > > Either you make a simple API giving back an unsigned long long and > you use the virNodeCpuTimeTags as the flag value > > int virNodeGetCpuTime(virConnectPtr conn, unsigned long long *time, > unsigned int flags); > > and the flags indicate the value you're interested into, but in that > case you have to ask multiple times. Or you make the VIR_NODE_CPU_TIME_* > values a bit field, and you pass an array > > int virNodeGetCpuTime(virConnectPtr conn, > unsigned long long *stats, > unsigned int nr_stats, > unsigned int flags); > > where flags is the logical or of the values you are interested into, and > the implementation put them in order based on the VIR_NODE_CPU_TIME_* > values. But in that case you must fail if one of the statistics is not > available. I think these are worse because you're relying on ordering of values, and not all hypervisors will be able to supply all values. In addition it makes this stats API completely different to the other stats APIs we have. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 18 11:32:03 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 18 Apr 2011 12:32:03 +0100 Subject: [libvirt] [PATCHv3 1/6] virNodeGetCPUTime: Expose new API In-Reply-To: <20110414190844.927ce596.usui@mxm.nes.nec.co.jp> References: <20110414185805.893c1ab0.usui@mxm.nes.nec.co.jp> <20110414190844.927ce596.usui@mxm.nes.nec.co.jp> Message-ID: <20110418113203.GF4648@redhat.com> On Thu, Apr 14, 2011 at 07:08:44PM +0900, Minoru Usui wrote: > virNodeGetCPUTime: Expose new API > > Signed-off-by: Minoru Usui > --- > include/libvirt/libvirt.h.in | 50 ++++++++++++++++++++++++++++++++++++++++++ > src/libvirt_public.syms | 5 ++++ > 2 files changed, 55 insertions(+), 0 deletions(-) > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > index 5783303..25cc08c 100644 > --- a/include/libvirt/libvirt.h.in > +++ b/include/libvirt/libvirt.h.in > @@ -228,6 +228,51 @@ struct _virNodeInfo { > unsigned int threads;/* number of threads per core */ > }; > > +/** > + * virNodeCpuTime: > + */ > + > +/** > + * virNodeCpuTimeFlags > + * > + * Flags when getting cpu statistics of the node. > + */ > +typedef enum { > + /* > + * The cumulative CPU time which spends by kernel, > + * when the node booting up.(in nanoseconds). > + */ > + VIR_NODE_CPU_TIME_KERNEL = 1, > + /* > + * The cumulative CPU time which spends by user processes, > + * when the node booting up.(in nanoseconds). > + */ > + VIR_NODE_CPU_TIME_USER = 2, > + /* > + * The cumulative idle CPU time, > + * when the node booting up.(in nanoseconds). > + */ > + VIR_NODE_CPU_TIME_IDLE = 4, > + /* > + * The cumulative I/O wait CPU time, > + * when the node booting up.(in nanoseconds). > + */ > + VIR_NODE_CPU_TIME_IOWAIT = 8, > + /* > + * The CPU utilization. > + * The usage value is in percent and 100% represents all CPUs on > + * the server. > + */ > + VIR_NODE_CPU_TIME_UTILIZATION = 16, > + > + /* > + * The number of statistics supported by this version of the interface. > + * To add new statistics, add them to the enum and increase this value. > + */ > + VIR_NODE_CPU_TIME_MAX = 32 > +} virNodeCpuTimeFlags; > + > +#define VIR_NODE_CPU_TIME_MASK (VIR_NODE_CPU_TIME_MAX - 1) > > /** > * virDomainSchedParameterType: > @@ -593,6 +638,11 @@ int virNodeGetInfo (virConnectPtr conn, > virNodeInfoPtr info); > char * virConnectGetCapabilities (virConnectPtr conn); > > +int virNodeGetCpuTime (virConnectPtr conn, > + unsigned long long *stats, > + unsigned int nr_stats, > + unsigned int flags); > + > unsigned long long virNodeGetFreeMemory (virConnectPtr conn); I'm sorry, but NACK to this API design. Your v2 design was consistent with the design of the other stats APIs we provide & better than this IMHO. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Mon Apr 18 11:41:23 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 18 Apr 2011 12:41:23 +0100 Subject: [libvirt] [PATCH V3 2/2] enhance processWatchdogEvent() In-Reply-To: <4DA873FA.8080009@redhat.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1CED.20202@cn.fujitsu.com> <4DA75CD7.9080908@redhat.com> <4DA7B76B.3010308@cn.fujitsu.com> <4DA873FA.8080009@redhat.com> Message-ID: <20110418114123.GG4648@redhat.com> On Fri, Apr 15, 2011 at 10:36:10AM -0600, Eric Blake wrote: > On 04/14/2011 09:11 PM, Wen Congyang wrote: > > This patch do the following two things: > > s/do/does/ > > > 1. hold an extra reference while handling watchdog event > > If the domain is not persistent, and qemu quits unexpectedly before > > calling processWatchdogEvent(), vm will be freed and the function > > processWatchdogEvent() will be dangerous. > > > > 2. unlock qemu driver and vm before returning from processWatchdogEvent() > > When the function processWatchdogEvent() failed, we only free wdEvent, > > but forget to unlock qemu driver and vm, free dumpfile. > > > > > > --- > > src/qemu/qemu_driver.c | 34 ++++++++++++++++++++++------------ > > src/qemu/qemu_process.c | 4 ++++ > > 2 files changed, 26 insertions(+), 12 deletions(-) > > Looks like your v2 caught my review comments correctly. But I found one > more issue: > > > +++ b/src/qemu/qemu_process.c > > @@ -428,6 +428,10 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > > if (VIR_ALLOC(wdEvent) == 0) { > > wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP; > > wdEvent->vm = vm; > > + /* Hold an extra reference because we can't allow 'vm' to be > > + * deleted before handling watchdog event is finished. > > + */ > > + virDomainObjRef(vm); > > ignore_value(virThreadPoolSendJob(driver->workerPool, wdEvent)); > > Now that we have increased the ref count, we should decrease it if we > are unable to send a job to the thread pool. That is, replace the > ignore_value() with: > > if (virThreadPoolSendJob(...) < 0) { > virDomainObjUnref(vm); > VIR_FREE(wdEvent); > } > > ACK with that change squashed in. This last minute addition caused a build failure cc1: warnings being treated as errors qemu/qemu_process.c: In function 'qemuProcessHandleWatchdog': qemu/qemu_process.c:436:34: error: ignoring return value of 'virDomainObjUnref', declared with attribute warn_unused_result [-Wunused-result] make[3]: *** [libvirt_driver_qemu_la-qemu_process.lo] Error 1 I think we also need this added: diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d405dda..5a81265 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -433,14 +433,16 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, */ virDomainObjRef(vm); if (virThreadPoolSendJob(driver->workerPool, wdEvent) < 0) { - virDomainObjUnref(vm); + if (virDomainObjUnref(vm) < 0) + vm = NULL; VIR_FREE(wdEvent); } } else virReportOOMError(); } - virDomainObjUnlock(vm); + if (vm) + virDomainObjUnlock(vm); if (watchdogEvent || lifecycleEvent) { qemuDriverLock(driver); Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From rjones at redhat.com Mon Apr 18 12:16:46 2011 From: rjones at redhat.com (Richard W.M. Jones) Date: Mon, 18 Apr 2011 13:16:46 +0100 Subject: [libvirt] Is a libvirt connection remote? Message-ID: <20110418121646.GA28346@amd.home.annexia.org> What's a good way to ask if a libvirt connection is remote or not? (Fundamentally I want to know if the disk images are openable as local files, and I'm using "remote" as an proxy for this property.) One way might be to compare virConnectGetHostname with the local hostname. This would fail if the client and server had the hostname set incorrectly (eg. "localhost.localdomain"). Another way might be some hairy libvirt URL parsing. Another way would be to speculatively open the disk images. This would fail if the client and server had guests with coincidentally named disk images. Or I could write a qemu block driver that could use virDomainBlockPeek. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From rjones at redhat.com Mon Apr 18 12:21:44 2011 From: rjones at redhat.com (Richard W.M. Jones) Date: Mon, 18 Apr 2011 13:21:44 +0100 Subject: [libvirt] [PATCH] Merge all returns paths from dispatcher into single path In-Reply-To: <1302718366-32246-1-git-send-email-berrange@redhat.com> References: <1302718366-32246-1-git-send-email-berrange@redhat.com> Message-ID: <20110418122144.GB28346@amd.home.annexia.org> On Wed, Apr 13, 2011 at 07:12:46PM +0100, Daniel P. Berrange wrote: > NB this was a tedious manual conversion of the code, so it > has potential for errors.... This code really ought to be generated ... The fact is that with libguestfs we have far more extensive RPC and language bindings than with libvirt, and yet they give us *no trouble at all*. Compare continual trouble and even security problems that libvirt is experiencing. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ From berrange at redhat.com Mon Apr 18 12:55:34 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 18 Apr 2011 13:55:34 +0100 Subject: [libvirt] [PATCH v2] Experimental libvirtd upstart job In-Reply-To: <16d6b0d80afabe455f5d00e4a696913c281d0649.1303120085.git.jdenemar@redhat.com> References: <16d6b0d80afabe455f5d00e4a696913c281d0649.1303120085.git.jdenemar@redhat.com> Message-ID: <20110418125534.GH4648@redhat.com> On Mon, Apr 18, 2011 at 11:49:17AM +0200, Jiri Denemark wrote: > From: Alan Pevec > > To install it, disable libvirtd sysv initscript: > chkconfig libvirtd off > service libvirtd stop > > and enable libvirtd upstart job: > cp /usr/share/doc/libvirt-*/libvirtd.upstart \ > /etc/init/libvirtd.conf > initctl reload-configuration > initctl start libvirtd > > Test: > initctl status libvirtd > libvirtd start/running, process 3929 > killall -9 libvirtd > initctl status libvirtd > libvirtd start/running, process 4047 > > I looked into the possibility to use the upstart script from Ubuntu or > at least getting inspiration from it but that's not possible. "expect > daemon" is a nice thing but it only works if the process is defined with > exec stanza instead of script ... no script. Unfortunately, with exec > stanza environment variables can only be set within upstart script > (i.e., configuration in /etc/sysconfig/libvirtd can't work). Hence, we > need to use script stanza, source sysconfig, and execute libvirtd > without --daemon. For similar reasons we can't use limit stanza and need > to handle DAEMON_COREFILE_LIMIT in job's script. > --- > Notes: > Version 2: > - I took Allan's script and modified it a bit > - DAEMON_COREFILE_LIMIT from sysconfig works > - PID file handling limited to just removing it > > daemon/Makefile.am | 1 + > daemon/libvirtd.upstart | 46 ++++++++++++++++++++++++++++++++++++++++++++++ > libvirt.spec.in | 1 + > 3 files changed, 48 insertions(+), 0 deletions(-) > create mode 100644 daemon/libvirtd.upstart > > diff --git a/daemon/Makefile.am b/daemon/Makefile.am > index cacec1c..af71188 100644 > --- a/daemon/Makefile.am > +++ b/daemon/Makefile.am > @@ -26,6 +26,7 @@ EXTRA_DIST = \ > remote_generate_stubs.pl \ > libvirtd.conf \ > libvirtd.init.in \ > + libvirtd.upstart \ > libvirtd.policy-0 \ > libvirtd.policy-1 \ > libvirtd.sasl \ > diff --git a/daemon/libvirtd.upstart b/daemon/libvirtd.upstart > new file mode 100644 > index 0000000..fd1d951 > --- /dev/null > +++ b/daemon/libvirtd.upstart > @@ -0,0 +1,46 @@ > +# libvirtd upstart job > +# > +# XXX wait for rc to get all dependent initscripts started > +# from sysv libvirtd initscript: Required-Start: $network messagebus > +start on stopped rc RUNLEVEL=[345] > +stop on runlevel [!345] > + > +respawn > + > +script > + LIBVIRTD_CONFIG= > + LIBVIRTD_ARGS= > + KRB5_KTNAME=/etc/libvirt/krb5.tab > + > + if [ -f /etc/sysconfig/libvirtd ]; then > + . /etc/sysconfig/libvirtd > + fi > + > + export QEMU_AUDIO_DRV > + export SDL_AUDIODRIVER > + export KRB5_KTNAME > + > + LIBVIRTD_CONFIG_ARGS= > + if [ -n "$LIBVIRTD_CONFIG" ]; then > + LIBVIRTD_CONFIG_ARGS="--config $LIBVIRTD_CONFIG" > + fi > + > + # DAEMON_COREFILE_LIMIT from /etc/sysconfig/libvirtd is not handled > + # automatically > + if [ -n "$DAEMON_COREFILE_LIMIT" ]; then > + ulimit -c "$DAEMON_COREFILE_LIMIT" > + fi > + > + # Clean up a pidfile that might be left around > + rm -f /var/run/libvirtd.pid > + > + mkdir -p /var/cache/libvirt > + rm -rf /var/cache/libvirt/* > + > + exec /usr/sbin/libvirtd $LIBVIRTD_CONFIG_ARGS $LIBVIRTD_ARGS > +end script > + > +post-stop script > + rm -f $PIDFILE > + rm -rf /var/cache/libvirt/* > +end script > diff --git a/libvirt.spec.in b/libvirt.spec.in > index 4162fba..bf6b9df 100644 > --- a/libvirt.spec.in > +++ b/libvirt.spec.in > @@ -895,6 +895,7 @@ fi > %{_sysconfdir}/libvirt/nwfilter/*.xml > > %{_sysconfdir}/rc.d/init.d/libvirtd > +%doc daemon/libvirtd.upstart > %config(noreplace) %{_sysconfdir}/sysconfig/libvirtd > %config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf > %if %{with_dtrace} ACK. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From serge.hallyn at canonical.com Mon Apr 18 13:09:48 2011 From: serge.hallyn at canonical.com (Serge Hallyn) Date: Mon, 18 Apr 2011 08:09:48 -0500 Subject: [libvirt] [PATCH v2] Experimental libvirtd upstart job In-Reply-To: <16d6b0d80afabe455f5d00e4a696913c281d0649.1303120085.git.jdenemar@redhat.com> References: <16d6b0d80afabe455f5d00e4a696913c281d0649.1303120085.git.jdenemar@redhat.com> Message-ID: <20110418130948.GC9184@hallyn.com> Quoting Jiri Denemark (jdenemar at redhat.com): > exec stanza instead of script ... no script. Unfortunately, with exec > stanza environment variables can only be set within upstart script > (i.e., configuration in /etc/sysconfig/libvirtd can't work). Hence, we > need to use script stanza, source sysconfig, and execute libvirtd > without --daemon. For similar reasons we can't use limit stanza and need > to handle DAEMON_COREFILE_LIMIT in job's script. Why can't you do that stuff in a pre-start script? thanks, -serge From jdenemar at redhat.com Mon Apr 18 13:20:21 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Mon, 18 Apr 2011 15:20:21 +0200 Subject: [libvirt] [PATCH v2] Experimental libvirtd upstart job In-Reply-To: <20110418130948.GC9184@hallyn.com> References: <16d6b0d80afabe455f5d00e4a696913c281d0649.1303120085.git.jdenemar@redhat.com> <20110418130948.GC9184@hallyn.com> Message-ID: <20110418132021.GD1245361@orkuz.home> On Mon, Apr 18, 2011 at 08:09:48 -0500, Serge Hallyn wrote: > Quoting Jiri Denemark (jdenemar at redhat.com): > > exec stanza instead of script ... no script. Unfortunately, with exec > > stanza environment variables can only be set within upstart script > > (i.e., configuration in /etc/sysconfig/libvirtd can't work). Hence, we > > need to use script stanza, source sysconfig, and execute libvirtd > > without --daemon. For similar reasons we can't use limit stanza and need > > to handle DAEMON_COREFILE_LIMIT in job's script. > > Why can't you do that stuff in a pre-start script? I tried that but any change to the variables didn't get propagated into variables used in the exec stanza. I tried something like: env LIBVIRTD_CONFIG_ARGS= env LIBVIRTD_ARGS= pre-start script source sysconfig files and set those variables end script exec /usr/sbin/libvirtd --daemon $LIBVIRTD_CONFIG_ARGS $LIBVIRTD_ARGS and libvirtd wasn't started with anything but --daemon. Jirka From jdenemar at redhat.com Mon Apr 18 13:23:45 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Mon, 18 Apr 2011 15:23:45 +0200 Subject: [libvirt] [PATCH v2] Experimental libvirtd upstart job In-Reply-To: <20110418125534.GH4648@redhat.com> References: <16d6b0d80afabe455f5d00e4a696913c281d0649.1303120085.git.jdenemar@redhat.com> <20110418125534.GH4648@redhat.com> Message-ID: <20110418132345.GE1245361@orkuz.home> On Mon, Apr 18, 2011 at 13:55:34 +0100, Daniel P. Berrange wrote: > On Mon, Apr 18, 2011 at 11:49:17AM +0200, Jiri Denemark wrote: > > From: Alan Pevec > > > > To install it, disable libvirtd sysv initscript: > > chkconfig libvirtd off > > service libvirtd stop > > > > and enable libvirtd upstart job: > > cp /usr/share/doc/libvirt-*/libvirtd.upstart \ > > /etc/init/libvirtd.conf > > initctl reload-configuration > > initctl start libvirtd > > > > Test: > > initctl status libvirtd > > libvirtd start/running, process 3929 > > killall -9 libvirtd > > initctl status libvirtd > > libvirtd start/running, process 4047 > > ... > > --- > > Notes: > > Version 2: > > - I took Allan's script and modified it a bit Alan, sorry for the typo in your name. That must be an influence of my boss :-) > ACK. Pushed, thanks. Jirka From eblake at redhat.com Mon Apr 18 13:48:42 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 18 Apr 2011 07:48:42 -0600 Subject: [libvirt] [PATCH] Update and sort msg_gen_function list and mark unmarked messages In-Reply-To: <20110417063049.GA8304@sbox> References: <20110417063049.GA8304@sbox> Message-ID: <4DAC413A.8060708@redhat.com> On 04/17/2011 12:30 AM, Matthias Bolte wrote: > Inspired by Eric Blake Good to know I'm setting expectations :) > --- > cfg.mk | 45 ++++++++++++++++++++++++++++++++++------- > src/interface/netcf_driver.c | 43 ++++++++++++++++++--------------------- > src/nodeinfo.c | 2 +- > src/phyp/phyp_driver.c | 18 ++++++++-------- > src/util/stats_linux.c | 2 +- > 5 files changed, 68 insertions(+), 42 deletions(-) > > @@ -182,8 +183,7 @@ static int interfaceNumOfInterfaces(virConnectPtr conn) > const char *errmsg, *details; > int errcode = ncf_error(driver->netcf, &errmsg, &details); > interfaceReportError(netcf_to_vir_err(errcode), > - "%s (netcf: %s - %s)", > - _("failed to get number of interfaces on host"), > + _("failed to get number of interfaces on host (netcf: %s - %s)"), This rewrite looks sane. I think that it would have also worked to use: _("%s (netcf: %s - %s"), _("failed to get number of interfaces on host"), but since I don't know whether translators would like that any better, I don't think you should bother changing it. ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From crobinso at redhat.com Mon Apr 18 14:37:08 2011 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 18 Apr 2011 10:37:08 -0400 Subject: [libvirt] Is a libvirt connection remote? In-Reply-To: <20110418121646.GA28346@amd.home.annexia.org> References: <20110418121646.GA28346@amd.home.annexia.org> Message-ID: <4DAC4C94.4090907@redhat.com> On 04/18/2011 08:16 AM, Richard W.M. Jones wrote: > What's a good way to ask if a libvirt connection is remote or not? > (Fundamentally I want to know if the disk images are openable as local > files, and I'm using "remote" as an proxy for this property.) > > One way might be to compare virConnectGetHostname with the local > hostname. This would fail if the client and server had the hostname > set incorrectly (eg. "localhost.localdomain"). > > Another way might be some hairy libvirt URL parsing. This is what we do in virt-manager, we just assume that presence of a hostname == remote. Granted that will incorrectly match qemu+ssh://localhost/system but I can't think of a valid use case for that besides testing. - Cole > > Another way would be to speculatively open the disk images. This > would fail if the client and server had guests with coincidentally > named disk images. > > Or I could write a qemu block driver that could use > virDomainBlockPeek. > > Rich. > From eblake at redhat.com Mon Apr 18 15:15:18 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 18 Apr 2011 09:15:18 -0600 Subject: [libvirt] [PATCH V3 2/2] enhance processWatchdogEvent() In-Reply-To: <20110418114123.GG4648@redhat.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1CED.20202@cn.fujitsu.com> <4DA75CD7.9080908@redhat.com> <4DA7B76B.3010308@cn.fujitsu.com> <4DA873FA.8080009@redhat.com> <20110418114123.GG4648@redhat.com> Message-ID: <4DAC5586.9070603@redhat.com> On 04/18/2011 05:41 AM, Daniel P. Berrange wrote: >> Looks like your v2 caught my review comments correctly. But I found one >> more issue: >> >> Now that we have increased the ref count, we should decrease it if we >> are unable to send a job to the thread pool. That is, replace the >> ignore_value() with: >> >> if (virThreadPoolSendJob(...) < 0) { >> virDomainObjUnref(vm); >> VIR_FREE(wdEvent); >> } >> >> ACK with that change squashed in. > > This last minute addition caused a build failure Oh well - that's what we get for incorporating something that I just typed, rather than testing... > I think we also need this added: > > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > index d405dda..5a81265 100644 > --- a/src/qemu/qemu_process.c > +++ b/src/qemu/qemu_process.c > @@ -433,14 +433,16 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > */ > virDomainObjRef(vm); > if (virThreadPoolSendJob(driver->workerPool, wdEvent) < 0) { > - virDomainObjUnref(vm); > + if (virDomainObjUnref(vm) < 0) > + vm = NULL; > VIR_FREE(wdEvent); > } > } else > virReportOOMError(); > } While we're at it, let's fix this else branch to have proper {} usage, per HACKING style guidelines. > > - virDomainObjUnlock(vm); > + if (vm) > + virDomainObjUnlock(vm); ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 18 15:31:21 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 18 Apr 2011 09:31:21 -0600 Subject: [libvirt] [PATCH] maint: ignore built file In-Reply-To: <20110416094707.GE7230@orkuz.home> References: <20110416094707.GE7230@orkuz.home> Message-ID: <1303140681-15660-1-git-send-email-eblake@redhat.com> * .gitignore: Add exemption for hashtest. --- Pushing this under the trivial rule. .gitignore | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index 35dbdde..803f2a3 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ /src/libvirt_iohelper /tests/*.log /tests/cputest +/tests/hashtest /tests/nwfilterxml2xmltest /update.log Makefile -- 1.7.4.2 From eblake at redhat.com Mon Apr 18 15:32:29 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 18 Apr 2011 09:32:29 -0600 Subject: [libvirt] [PATCH V3 2/2] enhance processWatchdogEvent() In-Reply-To: <4DAC5586.9070603@redhat.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1CED.20202@cn.fujitsu.com> <4DA75CD7.9080908@redhat.com> <4DA7B76B.3010308@cn.fujitsu.com> <4DA873FA.8080009@redhat.com> <20110418114123.GG4648@redhat.com> <4DAC5586.9070603@redhat.com> Message-ID: <4DAC598D.7030007@redhat.com> On 04/18/2011 09:15 AM, Eric Blake wrote: >> I think we also need this added: >> >> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c >> index d405dda..5a81265 100644 >> --- a/src/qemu/qemu_process.c >> +++ b/src/qemu/qemu_process.c >> @@ -433,14 +433,16 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, >> */ >> virDomainObjRef(vm); >> if (virThreadPoolSendJob(driver->workerPool, wdEvent) < 0) { >> - virDomainObjUnref(vm); >> + if (virDomainObjUnref(vm) < 0) >> + vm = NULL; >> VIR_FREE(wdEvent); >> } >> } else >> virReportOOMError(); >> } > > While we're at it, let's fix this else branch to have proper {} usage, > per HACKING style guidelines. > >> >> - virDomainObjUnlock(vm); >> + if (vm) >> + virDomainObjUnlock(vm); > > ACK. I've gone ahead and pushed this under your name, under the build-breaker rule. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 18 16:24:39 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 18 Apr 2011 10:24:39 -0600 Subject: [libvirt] [PATCHv2 9/9] phyp: another simplification In-Reply-To: References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-10-git-send-email-eblake@redhat.com> Message-ID: <4DAC65C7.3080903@redhat.com> On 04/16/2011 12:18 AM, Matthias Bolte wrote: > 2011/4/14 Eric Blake : >> Rather than copying and pasting lots of code, factor it into a >> single helper function. >> >> * src/phyp/phyp_driver.c (phypExecInt): New function. >> (phypGetVIOSPartitionID, phypNumDomainsGeneric, phypGetLparID) >> (phypGetLparMem, phypGetLparCPUGeneric, phypGetRemoteSlot) >> (phypGetVIOSNextSlotNumber, phypAttachDevice) >> (phypGetStoragePoolSize, phypStoragePoolNumOfVolumes) >> (phypNumOfStoragePools, phypInterfaceDestroy) >> (phypInterfaceDefineXML, phypInterfaceLookupByName) >> (phypInterfaceIsActive, phypNumOfInterfaces): Use it. >> --- >> src/phyp/phyp_driver.c | 316 ++++++++++-------------------------------------- >> 1 files changed, 67 insertions(+), 249 deletions(-) > > Okay lets take a look at each instance if stricter parsing is safe or not. Thanks for doing that. > >> @@ -364,17 +368,7 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) >> virBufferVSprintf(&buf, " -m %s", managed_system); >> virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9]*'", > Here the stricter parsing will be safe as the last grep returns a count. > > But I wonder about the last grep. I thought it would be there to count > the number of lines that start with a number, but it doesn't work: > > $ printf "aa\n22\n33\n" | grep -c '^[0-9]*' > 3 Oops - that's a definite bug; elsewhere in the file, we consistently use "[0-9][0-9]*" when matching a non-empty string of digits ([0-9]+ is not portable to POSIX BRE). > > In most cases we can see from the code that stricter parsing will be > safe, but in some places I'm not sure. > > So, as long as you don't have a PHYP system at hand to really test it, > I'd suggest that we stick to the relaxed parsing. Here's what I'm squashing in. Do I need to send a v3, or is this interdiff sufficient for an ack? diff --git i/src/phyp/phyp_driver.c w/src/phyp/phyp_driver.c index fc4ad5c..6bb9b49 100644 --- i/src/phyp/phyp_driver.c +++ w/src/phyp/phyp_driver.c @@ -237,13 +237,16 @@ phypExecInt(LIBSSH2_SESSION *session, virBufferPtr buf, virConnectPtr conn, { char *str; int ret; + char *char_ptr; str = phypExecBuffer(session, buf, &ret, conn, true); if (!str || ret) { VIR_FREE(str); return -1; } - ret = virStrToLong_i(str, NULL, 10, result); + ret = virStrToLong_i(str, &char_ptr, 10, result); + if (ret == 0 && *char_ptr) + VIR_WARN("ignoring suffix during integer parsing of '%s'", str); VIR_FREE(str); return ret; } @@ -366,7 +369,7 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) virBufferAddLit(&buf, "lssyscfg -r lpar"); if (system_type == HMC) virBufferVSprintf(&buf, " -m %s", managed_system); - virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9]*'", + virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9][0-9]*'", state); phypExecInt(session, &buf, conn, &ndom); return ndom; -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From laine at laine.org Mon Apr 18 16:25:21 2011 From: laine at laine.org (Laine Stump) Date: Mon, 18 Apr 2011 12:25:21 -0400 Subject: [libvirt] RFC: virInterface change transaction API In-Reply-To: <20110414130302.GG24239@redhat.com> References: <4D9F6279.6040806@laine.org> <20110414130302.GG24239@redhat.com> Message-ID: <4DAC65F1.6070206@laine.org> On 04/14/2011 09:03 AM, Dan Kenigsberg wrote: > On Fri, Apr 08, 2011 at 03:31:05PM -0400, Laine Stump wrote: > >> 1) libvirt >> >> At the libvirt layer, this feature just requires 3 new APIs, which >> are directly passed through to netcf: >> >> virInterfaceChangeStart(virConnectPtr conn, unsigned int flags); >> virInterfaceChangeCommit(virConnectPtr conn, unsigned int flags); >> virInterfaceChangeRollback(virConnectPtr conn, unsigned int flags); >> >> For the initial implementation, these will be simple passthroughs >> to similarly named netcf functions. (in the future, it would be >> useful for the server side of libvirt to determine if client<->server >> connectivity was lost due to the network changes, and automatically >> tell netcf to do a rollback). > When such a feature is added, we should make it dependent on FLAG_AUTO_ROLLBACK > passed to ChangeStart. Higher levels on the management stack may want full > controll over when rollback happens. So are you saying that when they don't add FLAG_AUTO_ROLLBACK that the originals should be available for rollback via virInterfaceChangeRollback(), but that if the system is rebooted, they will be lost? Or do you mean that the originals will still be available for rollback, but the initscript will notice a flag in the save directory and skip the rollback at boot time (leaving the originals there for later manual rollback)? (I think you mean the latter, but want to make sure) Should there also be a "-f" flag to force saving new originals, even if something is already there? Or is this too dangerous, and we should require the user to call virInterfaceChangeCommit() to erase the old originals? >> 2) netcf >> >> The netcf api will have these same three APIs, just named slightly >> differently: >> >> ncf_change_start(struct netcf *ncf, unsigned int flags); >> >> >> There are two possibilities for this. Either: >> >> A) call the initscript described below to save all config >> files that might possibly be changed (snapshot_config) >> >> or >> >> B) set a flag in *ncf indicating that all future calls >> to netcf that would end up modifying a particular >> config file should save off that file *if it hasn't >> already been saved*. >> >> (A) is simpler, but relies on the initscript having >> exact/complete matching knowledge of what files netcf may >> change. Should we worry about that and deal with the >> complexities of (B), or is (A) good enough for now? > I'm fine with gradual changes, so (A) is good enough for me, particularly as > long as netcf is shipping the initscripts (3). Okay. I will use the "copy/erase/restore everything matching a glob" approach for now. >> ncf_change_rollback(struct netcf *ncf, unsigned int flags); >> >> Again, two possbilities: >> >> A) >> a) save the config of all current interfaces (in memory) >> b) call the initscript below to restore the config to its >> original state. >> c) compare the new config to the old, and: >> * bring down any interfaces that no longer exist >> (PROBLEM: once an interface has no config files, you can >> no longer operate on it with "ifdown") >> * bounce any interfaces that have changed >> * bring up any interfaces that have been re-added >> or >> >> B) >> a) ifdown all interfaces >> b) call initscript to restore previous config >> (rollback_config) >> c) ifup all interfaces. >> >> (A) is much simpler, but may lead to unnecessary >> difficulties when we bounce interfaces that didn't really >> need it. So, the same question oas for ncf_change_start() - >> is the more exact operation worth the extra complexity? > (A) is simpler? Or did you mean (B)? I'm slightly worried about (B) causing > disconnection of completely unrelated interfaces; this may break concurrent > applications, or even the user of netcf. Sorry, I meant to swap (A) and (B) before I sent so that I was consistently putting simpler things first and more complicated things later. It sounds like in addition to saving the files, I need to save a list of interfaces during ncf_change_start; during ncf_change_rollback, I can: 1) get a list of interfaces as they are after the changes about to be rolled back. 2) use a diff of the two lists to ifdown/undefine the interfaces that will be "un-added" 3) use a "uniq -d" of the lists to get a list of all the interfaces that have just been changed (or not touched at all), and save the current XML for all of those interfaces 4) restore the files 5) Get a new list of interfaces, and for each: 5a) if it's not in the list from (3), ifup the interface 5b) if it is in the list from (3), compare the restored XML to modified ifdown/ifup the interface*only* if the two XMLs differ. Does that sound workable, or will there still be potential for problems (eg, if somebody bridged a host interface, then rolled back, what would happen?) >> ncf_change_commit(struct netcf *ncf, unsigned int flags); >> >> The simplest function - this will just call the initscript >> to erase the backup (commit_config). >> >> >> 3) initscript >> >> This initscript will at first live in (be installed by) netcf >> (called /etc/init.d/networking-config?), but hopefully it will >> eventually be accepted by the initscripts package (which includes >> the networking-related initscripts), as it is of general use. (Dan >> Kenigsberg already already took a stab at this script last year, >> but received no reply from the initscripts maintainers, implying >> they may not be too keen on the idea right now - it might take some >> convincing ;-) >> >> https://fedorahosted.org/pipermail/initscripts-devel/2010-February/000025.html >> >> It will have three commands, one of which will be called >> automatically by "start" (the command called automatically at boot >> time): >> >> snapshot_config >> >> This will save a copy of (what the script believes are - is this >> problematic?) all network-config related files. It may or may not >> be called by netcf (see the notes in ncf_start_change() above. >> >> If this function finds that a snapshot has already been taken, >> it should fail. >> >> >> rollback_config (automatically called from "start" at boottime) >> >> This will move back (from the saved copies) all files that were >> changed/removed since snapshot, *and delete any files that have >> been added*. >> >> Note that this command doesn't need to worry about ifup/ifdown, >> because it will be called prior to any other networking startup >> (part of the reason that netcf will need to deal with that). >> >> I notice that Dan K's version saves the modified files to a >> "rollback-${date}" directory. Does this seem like a good idea? >> It's nice to not lose anything, but there is no provision for >> eliminating old versions, so it could grow without bound. > I sleep better at night when there are backups... Obviously, I should not have > kept them beyond a certain limit (last 20). And I'd understand if you think that > it is the business of a backup system, or conf management system, to take theses > backups. I'm agnostic. Anyone else have an opinion? Does there need to be a method in the API to get to these backups? Or are they just there for manual intervention in the case of a catastrophe? >> commit_config >> >> This will just remove all the files in the save directory. >> >> >> So, the two problems I have right now: I guess the answers to the following questions are: 1) it's okay to take the easy road. 2) We have to do it the hard way. >> 1) Do we accept the inexact method of just saving all files that match >> a list of patterns during *start(), then in *rollback() erasing all >> files matching that pattern and copying the old file back? Or do we >> need to keep track of what files have been changed/removed and added, >> and copy back / delete only those files during rollback? >> >> (A version control system would keep track of this rather nicely, >> but that's too complex for something that's intended to be a >> failsafe (and that we would also like to eventually be in the base >> OS install). Dan B. at one point suggested using patchfiles if I >> wanted the save info to keep exact track of which files would need >> to be replaced/deleted on rollback, but on further thought this >> turns out to not be workable, since we would need to run diff (to >> create the patchfile) after all changes had been made, and any >> outside changes to any of the files would leave the patchfile >> un-appliable, thus causing our "failsafe" to fail :-( ). Therefore, >> we will need to rely on the list of globs to tell us what files >> need to be deleted, or keep our own list in a separate file.) >> >> 2) Is it going to be okay to ifdown all interfaces prior to the >> rollback, and ifup all interfaces afterwards? Or must we compare >> the new config to the original, and ifdown only those interfaces >> that had been previously added/changed, then ifup only those >> interfaces that had been previously removed/changed? >> >> 3) If anyone has ideas on making the initscript more palatable to the >> initscripts people, please speak up! :-) (one comment from an >> initscripts >> person was that 1) for the general case it would be difficult to >> draw the >> line on what parts of network connectivity should be included in this >> rollback functionality, and 2) at some point this becomes a general >> system config problem, and would really be better addressed by a >> general system wide config management system. These are both >> concerns that need well qualified answers. (I tend to think that this >> is intended as a failsafe to prevent unreachable systems, so it should >> be as simple as possible, and thus shouldn't be burdened with the >> complexity of a full system config management system (which could >> also co-exist at a higher level), but better answers are welcome.) >> >> -- >> libvir-list mailing list >> libvir-list at redhat.com >> https://www.redhat.com/mailman/listinfo/libvir-list From berrange at redhat.com Mon Apr 18 16:50:15 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 18 Apr 2011 17:50:15 +0100 Subject: [libvirt] RFC: virInterface change transaction API In-Reply-To: <4D9F6279.6040806@laine.org> References: <4D9F6279.6040806@laine.org> Message-ID: <20110418165015.GK4648@redhat.com> On Fri, Apr 08, 2011 at 03:31:05PM -0400, Laine Stump wrote: > I see 3 layers to this: > > 1) libvirt > > At the libvirt layer, this feature just requires 3 new APIs, which > are directly passed through to netcf: > > virInterfaceChangeStart(virConnectPtr conn, unsigned int flags); > virInterfaceChangeCommit(virConnectPtr conn, unsigned int flags); > virInterfaceChangeRollback(virConnectPtr conn, unsigned int flags); > > For the initial implementation, these will be simple passthroughs > to similarly named netcf functions. (in the future, it would be > useful for the server side of libvirt to determine if client<->server > connectivity was lost due to the network changes, and automatically > tell netcf to do a rollback). It helps to outline the usage scenarios for these APIs. The first scenario is where the app is running locally, and thus able to use the rollback API: a) Local app virInterfaceChangeStart n * virInterface{Define,Undefine,Start,Destroy} if (...app determined check to see if everything works..) virInterfaceChangeCommit else virInterfaceChangeRollback b) Remote app with rollback-on-reboot virInterfaceChangeStart n * virInterface{Define,Undefine,Start,Destroy} if (...app determined check to see if everything works..) virInterfaceChangeCommit else invoke remote power switch/fence agent to reboot ...init process does equivalent of virInterfaceChangeRollback c) Remote app with libvirt based auto-rollback virInterfaceChangeStart virInterfaceAutoRollbackTest("somehostname", someportnumber, somemillisecs) n * virInterface{Define,Undefine,Start,Destroy} virInterfaceChangeCommit (if they messed up, virInterfaceChangeCommit would have failed due to network failure, and after somemillisecs auto rollback test will trigger virInterfaceChangeRollback The virInterfaceAutoRollbackTest API is something I assume we'd build into libvirtd in the next stage of work after the basic APIs are done. > 2) netcf > > The netcf api will have these same three APIs, just named slightly > differently: > > ncf_change_start(struct netcf *ncf, unsigned int flags); > > > There are two possibilities for this. Either: > > A) call the initscript described below to save all config > files that might possibly be changed (snapshot_config) > > or > > B) set a flag in *ncf indicating that all future calls > to netcf that would end up modifying a particular > config file should save off that file *if it hasn't > already been saved*. > > (A) is simpler, but relies on the initscript having > exact/complete matching knowledge of what files netcf may > change. Should we worry about that and deal with the > complexities of (B), or is (A) good enough for now? I don't think it matters a huge amount. > ncf_change_rollback(struct netcf *ncf, unsigned int flags); > > Again, two possbilities: > > A) > a) save the config of all current interfaces (in memory) > b) call the initscript below to restore the config to its > original state. > c) compare the new config to the old, and: > * bring down any interfaces that no longer exist > (PROBLEM: once an interface has no config files, you can > no longer operate on it with "ifdown") > * bounce any interfaces that have changed > * bring up any interfaces that have been re-added Yes, this doesn't really work, because you need to determine what has changed *before* restoring the config, so that you can have a chance of doing 'ifdown' while the config still actually exists. > B) > a) ifdown all interfaces > b) call initscript to restore previous config > (rollback_config) > c) ifup all interfaces. > > (A) is much simpler, but may lead to unnecessary > difficulties when we bounce interfaces that didn't really > need it. So, the same question oas for ncf_change_start() - > is the more exact operation worth the extra complexity? To me A) seems more complex than B). The problem with B) is that if you have a multi-homed network, you may be taking down interfaces that where never changed. > ncf_change_commit(struct netcf *ncf, unsigned int flags); > > The simplest function - this will just call the initscript > to erase the backup (commit_config). > > > 3) initscript > > This initscript will at first live in (be installed by) netcf > (called /etc/init.d/networking-config?), but hopefully it will > eventually be accepted by the initscripts package (which includes > the networking-related initscripts), as it is of general use. (Dan > Kenigsberg already already took a stab at this script last year, > but received no reply from the initscripts maintainers, implying > they may not be too keen on the idea right now - it might take some > convincing ;-) > > https://fedorahosted.org/pipermail/initscripts-devel/2010-February/000025.html > > It will have three commands, one of which will be called > automatically by "start" (the command called automatically at boot > time): > > snapshot_config > > This will save a copy of (what the script believes are - is this > problematic?) all network-config related files. It may or may not > be called by netcf (see the notes in ncf_start_change() above. > > If this function finds that a snapshot has already been taken, > it should fail. > > > rollback_config (automatically called from "start" at boottime) > > This will move back (from the saved copies) all files that were > changed/removed since snapshot, *and delete any files that have > been added*. > > Note that this command doesn't need to worry about ifup/ifdown, > because it will be called prior to any other networking startup > (part of the reason that netcf will need to deal with that). > > I notice that Dan K's version saves the modified files to a > "rollback-${date}" directory. Does this seem like a good idea? > It's nice to not lose anything, but there is no provision for > eliminating old versions, so it could grow without bound. > > commit_config > > This will just remove all the files in the save directory. > > > So, the two problems I have right now: > > 1) Do we accept the inexact method of just saving all files that match > a list of patterns during *start(), then in *rollback() erasing all > files matching that pattern and copying the old file back? Or do we > need to keep track of what files have been changed/removed and added, > and copy back / delete only those files during rollback? > > (A version control system would keep track of this rather nicely, > but that's too complex for something that's intended to be a > failsafe (and that we would also like to eventually be in the base > OS install). Dan B. at one point suggested using patchfiles if I > wanted the save info to keep exact track of which files would need > to be replaced/deleted on rollback, but on further thought this > turns out to not be workable, since we would need to run diff (to > create the patchfile) after all changes had been made, and any > outside changes to any of the files would leave the patchfile > un-appliable, thus causing our "failsafe" to fail :-( ). Therefore, > we will need to rely on the list of globs to tell us what files > need to be deleted, or keep our own list in a separate file.) > > 2) Is it going to be okay to ifdown all interfaces prior to the > rollback, and ifup all interfaces afterwards? Or must we compare > the new config to the original, and ifdown only those interfaces > that had been previously added/changed, then ifup only those > interfaces that had been previously removed/changed? As long as that is hidden as a private impl detail, it is not critical. Long term I think you really only want to touch interfaces you actually changed. eg, if you messed up eth0 config (used for libvirtd access) but did not mess up eth1 (used for guest traffic), we don't really want to screw up all guest networking to repair eth0. (NB assuming eth1 and eth0 are separate LANs, so you couldn't just connect to libvirtd on eth1 and issue a virIntefaceChangeRollback call) > 3) If anyone has ideas on making the initscript more palatable to the > initscripts people, please speak up! :-) (one comment from an > initscripts > person was that 1) for the general case it would be difficult to > draw the > line on what parts of network connectivity should be included in this > rollback functionality, and 2) at some point this becomes a general > system config problem, and would really be better addressed by a > general system wide config management system. These are both > concerns that need well qualified answers. (I tend to think that this > is intended as a failsafe to prevent unreachable systems, so it should > be as simple as possible, and thus shouldn't be burdened with the > complexity of a full system config management system (which could > also co-exist at a higher level), but better answers are welcome.) We have a well defined set of files which we need to cope with so I think the scope is pretty clear. Trying to solve the entire OS system config problem is just insanity. We want to be able to ensure connectivity in as simple a manner as possible. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From thomas at scripty.at Mon Apr 18 16:50:47 2011 From: thomas at scripty.at (Thomas Treutner) Date: Mon, 18 Apr 2011 18:50:47 +0200 Subject: [libvirt] libvirt 0.9.0 crashes on first start since boot In-Reply-To: <4DAAB361.9080105@laine.org> References: <4DA6D0DD.10405@scripty.at> <4DA713FD.9080500@laine.org> <4DA8420E.2020901@scripty.at> <4DAAB361.9080105@laine.org> Message-ID: <4DAC6BE7.5000302@scripty.at> On 04/17/2011 11:31 AM, Laine Stump wrote: > On 04/15/2011 09:03 AM, Thomas Treutner wrote: >> >> I removed dnsmasq startup from the runlevel, now it works fine. I have >> seen dnsmasq errors for a long time, but I didn't really care too much >> about, as I don't need dnsmasq and the warnings didn't stop libvrit >> from working. I think I'll just deinstall dnsmasq. > > Are you sure you want to uninstall dnsmasq, and not just disable it in > the system config? If you uninstall dnsmasq, libvirt will fail to start > the virtual networks - it uses dnsmasq to provide DNS for those networks > even if you don't specify a dhcp range or hosts. Thanks for info, but I've not experienced such problems in my setup. I have a bridged network for the guests, static IPs and my DNS server in the guests /etc/resolv.conf - and everything works fine that way. I assume I don't need dnsmasq in such a setup? From matthias.bolte at googlemail.com Mon Apr 18 16:51:11 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 18 Apr 2011 18:51:11 +0200 Subject: [libvirt] [PATCHv2 9/9] phyp: another simplification In-Reply-To: <4DAC65C7.3080903@redhat.com> References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-10-git-send-email-eblake@redhat.com> <4DAC65C7.3080903@redhat.com> Message-ID: 2011/4/18 Eric Blake : > On 04/16/2011 12:18 AM, Matthias Bolte wrote: >> 2011/4/14 Eric Blake : >>> Rather than copying and pasting lots of code, factor it into a >>> single helper function. >>> >>> * src/phyp/phyp_driver.c (phypExecInt): New function. >>> (phypGetVIOSPartitionID, phypNumDomainsGeneric, phypGetLparID) >>> (phypGetLparMem, phypGetLparCPUGeneric, phypGetRemoteSlot) >>> (phypGetVIOSNextSlotNumber, phypAttachDevice) >>> (phypGetStoragePoolSize, phypStoragePoolNumOfVolumes) >>> (phypNumOfStoragePools, phypInterfaceDestroy) >>> (phypInterfaceDefineXML, phypInterfaceLookupByName) >>> (phypInterfaceIsActive, phypNumOfInterfaces): Use it. >>> --- >>> ?src/phyp/phyp_driver.c | ?316 ++++++++++-------------------------------------- >>> ?1 files changed, 67 insertions(+), 249 deletions(-) >> >> Okay lets take a look at each instance if stricter parsing is safe or not. > > Thanks for doing that. > >> >>> @@ -364,17 +368,7 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned int type) >>> ? ? ? ? virBufferVSprintf(&buf, " -m %s", managed_system); >>> ? ? virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9]*'", >> Here the stricter parsing will be safe as the last grep returns a count. >> >> But I wonder about the last grep. I thought it would be there to count >> the number of lines that start with a number, but it doesn't work: >> >> $ printf "aa\n22\n33\n" | grep -c '^[0-9]*' >> 3 > > Oops - that's a definite bug; elsewhere in the file, we consistently use > "[0-9][0-9]*" when matching a non-empty string of digits ([0-9]+ is not > portable to POSIX BRE). > >> >> In most cases we can see from the code that stricter parsing will be >> safe, but in some places I'm not sure. >> >> So, as long as you don't have a PHYP system at hand to really test it, >> I'd suggest that we stick to the relaxed parsing. > > Here's what I'm squashing in. ?Do I need to send a v3, or is this > interdiff sufficient for an ack? > > > diff --git i/src/phyp/phyp_driver.c w/src/phyp/phyp_driver.c > index fc4ad5c..6bb9b49 100644 > --- i/src/phyp/phyp_driver.c > +++ w/src/phyp/phyp_driver.c > @@ -237,13 +237,16 @@ phypExecInt(LIBSSH2_SESSION *session, virBufferPtr > buf, virConnectPtr conn, > ?{ > ? ? char *str; > ? ? int ret; > + ? ?char *char_ptr; > > ? ? str = phypExecBuffer(session, buf, &ret, conn, true); > ? ? if (!str || ret) { > ? ? ? ? VIR_FREE(str); > ? ? ? ? return -1; > ? ? } > - ? ?ret = virStrToLong_i(str, NULL, 10, result); > + ? ?ret = virStrToLong_i(str, &char_ptr, 10, result); > + ? ?if (ret == 0 && *char_ptr) > + ? ? ? ?VIR_WARN("ignoring suffix during integer parsing of '%s'", str); > ? ? VIR_FREE(str); > ? ? return ret; > ?} > @@ -366,7 +369,7 @@ phypNumDomainsGeneric(virConnectPtr conn, unsigned > int type) > ? ? virBufferAddLit(&buf, "lssyscfg -r lpar"); > ? ? if (system_type == HMC) > ? ? ? ? virBufferVSprintf(&buf, " -m %s", managed_system); > - ? ?virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9]*'", > + ? ?virBufferVSprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9][0-9]*'", > ? ? ? ? ? ? ? ? ? ? ? state); > ? ? phypExecInt(session, &buf, conn, &ndom); > ? ? return ndom; > Interdiff is fine, ACK. Matthias From berrange at redhat.com Mon Apr 18 16:53:05 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 18 Apr 2011 17:53:05 +0100 Subject: [libvirt] RFC: virInterface change transaction API In-Reply-To: <20110414130302.GG24239@redhat.com> References: <4D9F6279.6040806@laine.org> <20110414130302.GG24239@redhat.com> Message-ID: <20110418165305.GL4648@redhat.com> On Thu, Apr 14, 2011 at 04:03:03PM +0300, Dan Kenigsberg wrote: > On Fri, Apr 08, 2011 at 03:31:05PM -0400, Laine Stump wrote: > > I've been asked to implement what some people have termed as a > > "transaction-oriented" API for host interface configuration (ie > > virInterface*()). > > The basic intent is to allow rollback to a known-good config if > > anything goes > > wrong when changing around the host network config with virInterface*() > > functions. > > > > The most straightforward way to achieve this is that prior to calling > > virInterfaceDefine/virInterfaceUndefine, the current state of the > > host's network configuration (ie the /etc/sysconfig/network-scripts/ifcfg-* > > files in the case of Fedora and RHEL) would be saved off somewhere, and > > kept around until we're sure the new config is good; once we know that, > > we can just eliminate the backup. If, however, the user of virInterface*() > > explicitly requests, we could copy the files back; alternately if the system > > is rebooted without these known-good files being erased, we would assume > > that something went wrong and restore the original config. > > > > As with all other virInterface functions, the details of all this will > > be handled by netcf (and below), but since libvirt is the main consumer > > of netcf, I figure this is the appropriate place to discuss how it > > gets done, > > so please let me know any opinions on any piece of this. I plan to start > > the implementation "soon", as I want to be finished before the end of > > May. > > I like the idea, and think that virtInterface* users will benefit from it. > Few comments are inline. > > > > > I see 3 layers to this: > > > > 1) libvirt > > > > At the libvirt layer, this feature just requires 3 new APIs, which > > are directly passed through to netcf: > > > > virInterfaceChangeStart(virConnectPtr conn, unsigned int flags); > > virInterfaceChangeCommit(virConnectPtr conn, unsigned int flags); > > virInterfaceChangeRollback(virConnectPtr conn, unsigned int flags); > > > > For the initial implementation, these will be simple passthroughs > > to similarly named netcf functions. (in the future, it would be > > useful for the server side of libvirt to determine if client<->server > > connectivity was lost due to the network changes, and automatically > > tell netcf to do a rollback). > > When such a feature is added, we should make it dependent on FLAG_AUTO_ROLLBACK > passed to ChangeStart. Higher levels on the management stack may want full > controll over when rollback happens. I don't think a AUTO_ROLLBACK flag is sufficient. You'd almost certainly want to pass some info such as hostname/port number to test, and perhaps a test timeout in milliseconds, and perhaps a retry count. I suggest a separate API that is invoked just after starting the TXN, to provide auto-rollback data. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From eblake at redhat.com Mon Apr 18 16:55:08 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 18 Apr 2011 10:55:08 -0600 Subject: [libvirt] [PATCHv2 9/9] phyp: another simplification In-Reply-To: References: <1302812555-3418-1-git-send-email-eblake@redhat.com> <1302812555-3418-10-git-send-email-eblake@redhat.com> <4DAC65C7.3080903@redhat.com> Message-ID: <4DAC6CEC.2050001@redhat.com> On 04/18/2011 10:51 AM, Matthias Bolte wrote: > 2011/4/18 Eric Blake : >> On 04/16/2011 12:18 AM, Matthias Bolte wrote: >>> 2011/4/14 Eric Blake : >>>> Rather than copying and pasting lots of code, factor it into a >>>> single helper function. >>>> >>> So, as long as you don't have a PHYP system at hand to really test it, >>> I'd suggest that we stick to the relaxed parsing. >> >> Here's what I'm squashing in. Do I need to send a v3, or is this >> interdiff sufficient for an ack? >> > > Interdiff is fine, ACK. Thanks; pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From berrange at redhat.com Mon Apr 18 16:55:05 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 18 Apr 2011 17:55:05 +0100 Subject: [libvirt] RFC: virInterface change transaction API In-Reply-To: <4DAC65F1.6070206@laine.org> References: <4D9F6279.6040806@laine.org> <20110414130302.GG24239@redhat.com> <4DAC65F1.6070206@laine.org> Message-ID: <20110418165505.GM4648@redhat.com> On Mon, Apr 18, 2011 at 12:25:21PM -0400, Laine Stump wrote: > On 04/14/2011 09:03 AM, Dan Kenigsberg wrote: > >>3) initscript > >> > >> This initscript will at first live in (be installed by) netcf > >> (called /etc/init.d/networking-config?), but hopefully it will > >> eventually be accepted by the initscripts package (which includes > >> the networking-related initscripts), as it is of general use. (Dan > >> Kenigsberg already already took a stab at this script last year, > >> but received no reply from the initscripts maintainers, implying > >> they may not be too keen on the idea right now - it might take some > >> convincing ;-) > >> > >>https://fedorahosted.org/pipermail/initscripts-devel/2010-February/000025.html > >> > >> It will have three commands, one of which will be called > >> automatically by "start" (the command called automatically at boot > >> time): > >> > >> snapshot_config > >> > >> This will save a copy of (what the script believes are - is this > >> problematic?) all network-config related files. It may or may not > >> be called by netcf (see the notes in ncf_start_change() above. > >> > >> If this function finds that a snapshot has already been taken, > >> it should fail. > >> > >> > >> rollback_config (automatically called from "start" at boottime) > >> > >> This will move back (from the saved copies) all files that were > >> changed/removed since snapshot, *and delete any files that have > >> been added*. > >> > >> Note that this command doesn't need to worry about ifup/ifdown, > >> because it will be called prior to any other networking startup > >> (part of the reason that netcf will need to deal with that). > >> > >> I notice that Dan K's version saves the modified files to a > >> "rollback-${date}" directory. Does this seem like a good idea? > >> It's nice to not lose anything, but there is no provision for > >> eliminating old versions, so it could grow without bound. > >I sleep better at night when there are backups... Obviously, I should not have > >kept them beyond a certain limit (last 20). And I'd understand if you think that > >it is the business of a backup system, or conf management system, to take theses > >backups. > > > I'm agnostic. Anyone else have an opinion? Does there need to be a > method in the API to get to these backups? Or are they just there > for manual intervention in the case of a catastrophe? I think we're getting into overkill myself. Best to concentrate of getting the basic functionality present & working. If someone decides we need to extend this work to handle historical snapshots of the interface config we can deal with it later. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From matthias.bolte at googlemail.com Mon Apr 18 17:06:59 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 18 Apr 2011 19:06:59 +0200 Subject: [libvirt] [PATCH] Update and sort msg_gen_function list and mark unmarked messages In-Reply-To: <4DAC413A.8060708@redhat.com> References: <20110417063049.GA8304@sbox> <4DAC413A.8060708@redhat.com> Message-ID: 2011/4/18 Eric Blake : > On 04/17/2011 12:30 AM, Matthias Bolte wrote: >> Inspired by Eric Blake > > Good to know I'm setting expectations :) > >> --- >> ?cfg.mk ? ? ? ? ? ? ? ? ? ? ? | ? 45 ++++++++++++++++++++++++++++++++++------- >> ?src/interface/netcf_driver.c | ? 43 ++++++++++++++++++--------------------- >> ?src/nodeinfo.c ? ? ? ? ? ? ? | ? ?2 +- >> ?src/phyp/phyp_driver.c ? ? ? | ? 18 ++++++++-------- >> ?src/util/stats_linux.c ? ? ? | ? ?2 +- >> ?5 files changed, 68 insertions(+), 42 deletions(-) >> >> @@ -182,8 +183,7 @@ static int interfaceNumOfInterfaces(virConnectPtr conn) >> ? ? ? ? ?const char *errmsg, *details; >> ? ? ? ? ?int errcode = ncf_error(driver->netcf, &errmsg, &details); >> ? ? ? ? ?interfaceReportError(netcf_to_vir_err(errcode), >> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? "%s (netcf: %s - %s)", >> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? _("failed to get number of interfaces on host"), >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? _("failed to get number of interfaces on host (netcf: %s - %s)"), > > This rewrite looks sane. ?I think that it would have also worked to use: > > _("%s (netcf: %s - %s"), > _("failed to get number of interfaces on host"), > > but since I don't know whether translators would like that any better, I > don't think you should bother changing it. > > ACK. > Thanks, pushed. Matthias From jfehlig at novell.com Mon Apr 18 18:14:28 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Mon, 18 Apr 2011 12:14:28 -0600 Subject: [libvirt] [PATCHv2] Add cputune support to libxl driver In-Reply-To: <1303118193-2965-1-git-send-email-gross@univention.de> References: <1303118193-2965-1-git-send-email-gross@univention.de> Message-ID: <4DAC7F84.4040006@novell.com> Markus Gro? wrote: > Here is a new version of this patch: > https://www.redhat.com/archives/libvir-list/2011-April/msg00337.html > > v2: > - store the cputune info for the whole runtime of the domain > - remove cputune info when domain is destroyed > > The nodeGetInfo code had to be moved into a helper > function to reuse it without a virConnectPtr. > --- > src/libxl/libxl_driver.c | 159 +++++++++++++++++++++++++++++++++++----------- > 1 files changed, 122 insertions(+), 37 deletions(-) > I tested all sorts of combinations of starting domains (hvm and pv), pinning vcpus, shutting down domains, and restarting libvirt - looks good! Thanks Markus. ACK and pushed. Regards, Jim > diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c > index 3040914..247d78e 100644 > --- a/src/libxl/libxl_driver.c > +++ b/src/libxl/libxl_driver.c > @@ -199,6 +199,46 @@ libxlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, > virDomainObjUnlock(vm); > } > > +static int > +libxlDoNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info) > +{ > + libxl_physinfo phy_info; > + const libxl_version_info* ver_info; > + struct utsname utsname; > + > + if (libxl_get_physinfo(&driver->ctx, &phy_info)) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("libxl_get_physinfo_info failed")); > + return -1; > + } > + > + if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("libxl_get_version_info failed")); > + return -1; > + } > + > + uname(&utsname); > + if (virStrncpy(info->model, > + utsname.machine, > + strlen(utsname.machine), > + sizeof(info->model)) == NULL) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("machine type %s too big for destination"), > + utsname.machine); > + return -1; > + } > + > + info->memory = phy_info.total_pages * (ver_info->pagesize / 1024); > + info->cpus = phy_info.nr_cpus; > + info->nodes = phy_info.nr_nodes; > + info->cores = phy_info.cores_per_socket; > + info->threads = phy_info.threads_per_core; > + info->sockets = 1; > + info->mhz = phy_info.cpu_khz / 1000; > + return 0; > +} > + > /* > * Cleanup function for domain that has reached shutoff state. > * > @@ -210,6 +250,7 @@ libxlVmCleanup(libxlDriverPrivatePtr driver, virDomainObjPtr vm) > libxlDomainObjPrivatePtr priv = vm->privateData; > int vnc_port; > char *file; > + int i; > > if (priv->eventHdl >= 0) { > virEventRemoveHandle(priv->eventHdl); > @@ -238,6 +279,16 @@ libxlVmCleanup(libxlDriverPrivatePtr driver, virDomainObjPtr vm) > } > } > > + /* Remove any cputune settings */ > + if (vm->def->cputune.nvcpupin) { > + for (i = 0; i < vm->def->cputune.nvcpupin; ++i) { > + VIR_FREE(vm->def->cputune.vcpupin[i]->cpumask); > + VIR_FREE(vm->def->cputune.vcpupin[i]); > + } > + VIR_FREE(vm->def->cputune.vcpupin); > + vm->def->cputune.nvcpupin = 0; > + } > + > if (virAsprintf(&file, "%s/%s.xml", driver->stateDir, vm->def->name) > 0) { > if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR) > VIR_DEBUG("Failed to remove domain XML for %s", vm->def->name); > @@ -391,6 +442,62 @@ error: > return -1; > } > > +static int > +libxlDomainSetVcpuAffinites(libxlDriverPrivatePtr driver, virDomainObjPtr vm) > +{ > + libxlDomainObjPrivatePtr priv = vm->privateData; > + virDomainDefPtr def = vm->def; > + libxl_cpumap map; > + uint8_t *cpumask = NULL; > + uint8_t *cpumap = NULL; > + virNodeInfo nodeinfo; > + size_t cpumaplen; > + unsigned int pos; > + int vcpu, i; > + int ret = -1; > + > + if (libxlDoNodeGetInfo(driver, &nodeinfo) < 0) > + goto cleanup; > + > + cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo)); > + > + for (vcpu = 0; vcpu < def->cputune.nvcpupin; ++vcpu) { > + if (vcpu != def->cputune.vcpupin[vcpu]->vcpuid) > + continue; > + > + if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) { > + virReportOOMError(); > + goto cleanup; > + } > + > + cpumask = (uint8_t*) def->cputune.vcpupin[vcpu]->cpumask; > + > + for (i = 0; i < VIR_DOMAIN_CPUMASK_LEN; ++i) { > + if (cpumask[i]) { > + pos = i / 8; > + cpumap[pos] |= 1 << (i % 8); > + } > + } > + > + map.size = cpumaplen; > + map.map = cpumap; > + > + if (libxl_set_vcpuaffinity(&priv->ctx, def->id, vcpu, &map) != 0) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to pin vcpu '%d' with libxenlight"), vcpu); > + goto cleanup; > + } > + > + VIR_FREE(cpumap); > + } > + > + ret = 0; > + > +cleanup: > + VIR_FREE(cpumap); > + return ret; > +} > + > /* > * Start a domain through libxenlight. > * > @@ -440,6 +547,9 @@ libxlVmStart(libxlDriverPrivatePtr driver, > if (libxlCreateDomEvents(vm) < 0) > goto error; > > + if (libxlDomainSetVcpuAffinites(driver, vm) < 0) > + goto error; > + > if (!start_paused) { > libxl_domain_unpause(&priv->ctx, domid); > vm->state = VIR_DOMAIN_RUNNING; > @@ -756,7 +866,7 @@ libxlReload(void) > &libxl_driver->domains, > libxl_driver->configDir, > libxl_driver->autostartDir, > - 0, NULL, libxl_driver); > + 1, NULL, libxl_driver); > > virHashForEach(libxl_driver->domains.objs, libxlAutostartDomain, > libxl_driver); > @@ -869,42 +979,7 @@ libxlGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) > static int > libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) > { > - libxl_physinfo phy_info; > - const libxl_version_info* ver_info; > - libxlDriverPrivatePtr driver = conn->privateData; > - struct utsname utsname; > - > - if (libxl_get_physinfo(&driver->ctx, &phy_info)) { > - libxlError(VIR_ERR_INTERNAL_ERROR, > - _("libxl_get_physinfo_info failed")); > - return -1; > - } > - > - if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) { > - libxlError(VIR_ERR_INTERNAL_ERROR, > - _("libxl_get_version_info failed")); > - return -1; > - } > - > - uname(&utsname); > - if (virStrncpy(info->model, > - utsname.machine, > - strlen(utsname.machine), > - sizeof(info->model)) == NULL) { > - libxlError(VIR_ERR_INTERNAL_ERROR, > - _("machine type %s too big for destination"), > - utsname.machine); > - return -1; > - } > - > - info->memory = phy_info.total_pages * (ver_info->pagesize / 1024); > - info->cpus = phy_info.nr_cpus; > - info->nodes = phy_info.nr_nodes; > - info->cores = phy_info.cores_per_socket; > - info->threads = phy_info.threads_per_core; > - info->sockets = 1; > - info->mhz = phy_info.cpu_khz / 1000; > - return 0; > + return libxlDoNodeGetInfo(conn->privateData, info); > } > > static char * > @@ -1712,6 +1787,16 @@ libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap, > _("Failed to pin vcpu '%d' with libxenlight"), vcpu); > goto cleanup; > } > + > + if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) { > + libxlError(VIR_ERR_INTERNAL_ERROR, > + "%s", _("failed to update or add vcpupin xml")); > + goto cleanup; > + } > + > + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) > + goto cleanup; > + > ret = 0; > > cleanup: > From serge.hallyn at canonical.com Mon Apr 18 20:55:12 2011 From: serge.hallyn at canonical.com (Serge Hallyn) Date: Mon, 18 Apr 2011 15:55:12 -0500 Subject: [libvirt] [PATCH v2] Experimental libvirtd upstart job In-Reply-To: <20110418132021.GD1245361@orkuz.home> References: <16d6b0d80afabe455f5d00e4a696913c281d0649.1303120085.git.jdenemar@redhat.com> <20110418130948.GC9184@hallyn.com> <20110418132021.GD1245361@orkuz.home> Message-ID: <20110418205512.GE18316@hallyn.com> Quoting Jiri Denemark (jdenemar at redhat.com): > On Mon, Apr 18, 2011 at 08:09:48 -0500, Serge Hallyn wrote: > > Quoting Jiri Denemark (jdenemar at redhat.com): > > > exec stanza instead of script ... no script. Unfortunately, with exec > > > stanza environment variables can only be set within upstart script > > > (i.e., configuration in /etc/sysconfig/libvirtd can't work). Hence, we > > > need to use script stanza, source sysconfig, and execute libvirtd > > > without --daemon. For similar reasons we can't use limit stanza and need > > > to handle DAEMON_COREFILE_LIMIT in job's script. > > > > Why can't you do that stuff in a pre-start script? > > I tried that but any change to the variables didn't get propagated into > variables used in the exec stanza. Hm, right you are. I was thinking pre-start could set up env's, but it can't. thanks, -serge From rjones at redhat.com Mon Apr 18 22:12:42 2011 From: rjones at redhat.com (Richard W.M. Jones) Date: Mon, 18 Apr 2011 23:12:42 +0100 Subject: [libvirt] [PATCH DISCUSSION ONLY] Add inspection thread to virt-manager. In-Reply-To: <4DACB209.9090101@redhat.com> References: <20110418170146.GA485@amd.home.annexia.org> <4DACB209.9090101@redhat.com> Message-ID: <20110418221242.GM2641@amd.home.annexia.org> On Mon, Apr 18, 2011 at 05:50:01PM -0400, Cole Robinson wrote: > First, thanks a lot for the patch! I'm sure everyone will be glad to see > libguestfs integration in virt-manager. > > > [This patch is incomplete and just for discussion] > > > > Using libguestfs inspection[1], we can find out a lot about a virtual > > machine, such as what operating system is installed, the OS version, > > the OS distro, the hostname, the (real) disk usage, what apps are > > installed, and lots more. It would be nice if virt-manager could use > > this information: for example we could change the generic "computer" > > icon into a Windows or Fedora logo if Windows or Fedora was installed > > in the virtual machine. > > > > That icon bit was originally intended for the current design, but since we've > never really tracked OS info after install time, it never came about. > > Particularly for OS type/version tracking, I think we need a few things: > > - Everything standardize on some naming scheme, ideally libosinfo (though > nothing is using it yet :/ ). libosinfo could also distribute the OS icons We sort of got bored of waiting for that train. We have a primitive but rather effective system in libguestfs, which I explain at the end of this email. > - Libvirt domain XML schema is extended with a field to track the > installed OS. For most libvirt drivers this would just be metadata > (vmware/esx the exception). Even though the data might be out of > date if the guest is upgraded, I think it has become clear that > there is a lot of value in tracking this in XML. Yes, I agree. This also solves the persistence problem. It's a bit of a shame that the field in the libvirt XML isn't structured, at least so that different applications could store their own data there without it being trampled upon by users or other applications. (CC'd to libvir-list in case they have any thoughts about that). > - virt-manager can offer an option to set the XML OS value from libguestfs > inspection. Maybe even some preference to do this automatically for vms which > have no XML value, or some warning if the inspected OS doesn't match the > stored value. > > None of this affects the validity of the patch btw. > > > This patch adds a daemon thread running in the background which > > performs batch inspection on the virt-manager VMs. If inspection is > > successful, it then passes the results up to the UI (ie. the > > vmmManager object) to be displayed. > > > > Currently I've just added the inspected hostname to the UI as you can > > see in this screenshot: > > > > http://oirase.annexia.org/tmp/vmm-hostnames.png > > > > Ah, that's a nice idea, but I'd probably want to run it by the UX guys first. I've removed that from the code already. It was just a quick hack to show what could be done. > At the very least a first step would be showing the hostname under > Details->Overview, probably just add a new field under the Name: Agreed. > > In future there is room for much greater customization of the UI, such > > as changing the icons, displaying disk usage and more. > > > > The background thread is transparent to the UI. Well, in fact because > > of a bug in libguestfs, it is currently NOT transparent because we > > weren't releasing the Python GIL across libguestfs calls. If you > > apply the following patch to libguestfs, then it *is* transparent and > > doesn't interrupt the UI: > > > > https://www.redhat.com/archives/libguestfs/2011-April/msg00076.html > > > > Okay, so when this patch is committed we probably want to add a libguestfs > version check to make sure we aren't using bad bindings. Agreed. Also I have pushed the Python fix into: stable branch 1.8 version >= 1.8.6 stable branch 1.10 version >= 1.10.1 development branch version >= 1.11.2 and these should be available in Fedora 14 onwards in a few weeks. > > I think that virt-manager should probably cache the inspection data > > across runs. However I don't know if virt-manager has a mechanism to > > do this already or if we'd need to add one. > > Do you mean cache across runs of virt-manager? We could use gconf, we already > have examples of setting per-vm preferences like console scaling, we could use > the same to store hostname, os type/distro, etc. But then we have to decide > when to repoll this info, and if/how to allow the user to force repolling. Or libvirt XML maybe .. see above. > > Also this patch doesn't yet change ./configure, so it'll just fail if > > the python-libguestfs package is not installed. > > > > We don't really use configure for package checks actually. It's pretty easy in > the code to just try the import and disable the feature if the package isn't > available. Then distros just use rpm/dpkg deps to pull in the packages we want We should probably do the check entirely at runtime and make python-libguestfs completely optional (but on Debian, map it to an Enhances-type dependency). There's no need to have virt-manager depending on libguestfs, since this is just an extra feature, not a requirement. > > [1] http://libguestfs.org/virt-inspector.1.html > > > > On 04/18/2011 01:01 PM, Richard W.M. Jones wrote: > > From 11278a7509e4edbcb28eac4c2c4a50fc8d68342e Mon Sep 17 00:00:00 2001 > > From: Richard W.M. Jones > > Date: Mon, 18 Apr 2011 17:44:51 +0100 > > Subject: [PATCH] Add inspection thread to virt-manager. > > > > --- > > src/virtManager/engine.py | 14 ++++ > > src/virtManager/inspection.py | 162 +++++++++++++++++++++++++++++++++++++++++ > > src/virtManager/manager.py | 26 ++++++- > > 3 files changed, 200 insertions(+), 2 deletions(-) > > create mode 100644 src/virtManager/inspection.py > > > > diff --git a/src/virtManager/engine.py b/src/virtManager/engine.py > > index 383deb3..40d5b39 100644 > > --- a/src/virtManager/engine.py > > +++ b/src/virtManager/engine.py > > @@ -45,6 +45,7 @@ from virtManager.create import vmmCreate > > from virtManager.host import vmmHost > > from virtManager.error import vmmErrorDialog > > from virtManager.systray import vmmSystray > > +from virtManager.inspection import vmmInspection > > import virtManager.uihelpers as uihelpers > > import virtManager.util as util > > > > @@ -239,6 +240,9 @@ class vmmEngine(vmmGObject): > > if not self.config.support_threading: > > logging.debug("Libvirt doesn't support threading, skipping.") > > > > + self.inspection_thread = None > > + self.create_inspection_thread() > > + > > # Counter keeping track of how many manager and details windows > > # are open. When it is decremented to 0, close the app or > > # keep running in system tray if enabled > > @@ -533,6 +537,16 @@ class vmmEngine(vmmGObject): > > logging.debug("Exiting app normally.") > > gtk.main_quit() > > > > + def create_inspection_thread(self): > > + if not self.config.support_threading: > > + logging.debug("No inspection thread because " > > + "libvirt is not thread-safe.") > > + return > > + self.inspection_thread = vmmInspection(self) > > + self.inspection_thread.daemon = True > > + self.inspection_thread.start() > > + return > > + > > def add_connection(self, uri, readOnly=None, autoconnect=False): > > conn = self._check_connection(uri) > > if conn: > > diff --git a/src/virtManager/inspection.py b/src/virtManager/inspection.py > > new file mode 100644 > > index 0000000..70f2f52 > > --- /dev/null > > +++ b/src/virtManager/inspection.py > > @@ -0,0 +1,162 @@ > > +# > > +# Copyright (C) 2011 Red Hat, Inc. > > +# > > +# This program is free software; you can redistribute it and/or modify > > +# it under the terms of the GNU General Public License as published by > > +# the Free Software Foundation; either version 2 of the License, or > > +# (at your option) any later version. > > +# > > +# This program is distributed in the hope that it will be useful, > > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > +# GNU General Public License for more details. > > +# > > +# You should have received a copy of the GNU General Public License > > +# along with this program; if not, write to the Free Software > > +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, > > +# MA 02110-1301 USA. > > +# > > + > > +import sys > > +import time > > +import traceback > > +from Queue import Queue > > +from threading import Thread > > + > > +from guestfs import GuestFS > > + > > +import logging > > +import util > > + > > +class vmmInspection(Thread): > > + _name = "inspection thread" > > + _wait = 60 # seconds > > + > > + def __init__(self, engine): > > + Thread.__init__(self, name=self._name) > > + self._q = Queue() > > + self._engine = engine > > + self._vmcache = dict() > > + > > + # Called by the main thread whenever a VM is added to vmlist. > > + def vm_added(self, connection, vmuuid): > > + obj = (connection, vmuuid) > > + self._q.put(obj) > > + > > + def run(self): > > + # Wait a few seconds before we do anything. This prevents > > + # inspection from being a burden for initial virt-manager > > + # interactivity (although it shouldn't affect interactivity at > > + # all). > > + logging.debug("%s: waiting" % self._name) > > + time.sleep(self._wait) > > + > > + logging.debug("%s: ready" % self._name) > > + > > + while True: > > + obj = self._q.get(True) > > + (connection, vmuuid) = obj > > + > > + logging.debug("%s: %s: processing started, connection = %s" % > > + (self._name, vmuuid, connection)) > > + try: > > + self._process(connection, vmuuid) > > + except: > > + logging.debug("%s: %s: processing raised:\n%s" % > > + (self._name, vmuuid, traceback.format_exc())) > > + > > + self._q.task_done() > > + logging.debug("%s: %s: processing done" % (self._name, vmuuid)) > > + > > + def _process(self, connection, vmuuid): > > + if vmuuid in self._vmcache: > > + self._update_ui(connection, vmuuid) > > + return > > + > > + if not connection or connection.is_remote(): > > + logging.debug("%s: %s: no connection object or " > > + "connection is remote" % (self._name, vmuuid)) > > + return > > + vm = connection.get_vm(vmuuid) > > + if not vm: > > + logging.debug("%s: %s: no vm object" % (self._name, vmuuid)) > > + return > > + > > + xml = vm.get_xml() > > + if not xml: > > + logging.debug("%s: %s: cannot get domain XML" % > > + (self._name, vmuuid)) > > + return > > + > > This 2 calls won't ever be none, they'll either return something or throw an > exception. OK, I will fix it. > > + g = GuestFS() > > + # One day we will be able to do ... > > + #g.add_libvirt_dom(...) > > + # but until that day comes ... > > + disks = self._get_disks_from_xml(xml) > > + for (disk, format) in disks: > > + g.add_drive_opts(disk, readonly=1, format=format) > > + > > + g.launch() > > + > > + # Inspect the operating system. > > + roots = g.inspect_os() > > + if len(roots) == 0: > > + logging.debug("%s: %s: no operating systems found" % > > + (self._name, vmuuid)) > > + return > > + > > + # Arbitrarily pick the first root device. > > + root = roots[0] > > + > > + # Inspection. > > + name = g.inspect_get_type (root) > > + distro = g.inspect_get_distro (root) > > + hostname = g.inspect_get_hostname (root) > > + > > + self._vmcache[vmuuid] = (name, distro, hostname) > > + > > + # Force the libguestfs handle to close right now. > > + del g > > + > > + # Update the UI. > > + self._update_ui(connection, vmuuid) > > + > > + # Call back into the manager (if one is displayed) to update the > > + # inspection data for the particular VM. > > + def _update_ui(self, connection, vmuuid): > > + wm = self._engine.windowManager > > + if not wm: return > > + > > + name, distro, hostname = self._vmcache[vmuuid] > > + > > + wm.vm_set_inspection_data(connection, vmuuid, name, distro, hostname) > > + > > The preferred way to do this would be with gtk signals. Have the > inspection thread do something like vm.set_hostname(), which will > trigger a self.emit("config-changed"), which is already wired up in > manager.py to refresh the row listing. This will let you drop > self._engine (generally if we are passing engine around there is > probably a cleaner way to do things, but we aren't too disciplined > on that at the moment). OK, I will fix this too once I work out what gtk signals are .. > > + # Get the list of disks belonging to this VM from the libvirt XML. > > + def _get_disks_from_xml(self, xml): > > + def f(doc, ctx): > > + nodes = ctx.xpathEval("//devices/disk") > > + disks = [] > > + for node in nodes: > > + ctx.setContextNode(node) > > + types = ctx.xpathEval("./@type") > > + > > + if types and types[0].content: > > + t = types[0].content > > + disk = None > > + > > + if t == "file": > > + disk = ctx.xpathEval("./source/@file") > > + elif t == "block": > > + disk = ctx.xpathEval("./source/@dev") > > + > > + if disk and disk[0].content: > > + d = disk[0].content > > + types = ctx.xpathEval("./driver/@type") > > + if types and types[0].content: > > + disks.append((d, types[0].content)) > > + else: > > + disks.append((d, None)) > > + > > + return disks > > This _get_disk_from_xml function isn't needed. You can just do: > > for disk in vm.get_disk_devices(): > path = disk.path > driver_type = disk.driver_type > disks.append((path, driver_type)) > > the 'disk' in this case is a virtinst.VirtualDisk instance, incase you need > other XML values in the future OK, that's a much better idea! I'll make these and other changes and send an update in a few days. Thanks for looking at this. Rich. ---------------------------------------------------------------------- Operating systems are classified at two levels, 'type' and 'distro': http://libguestfs.org/guestfs.3.html#guestfs_inspect_get_type http://libguestfs.org/guestfs.3.html#guestfs_inspect_get_distro The version number of the OS is classified separately: http://libguestfs.org/guestfs.3.html#guestfs_inspect_get_major_version http://libguestfs.org/guestfs.3.html#guestfs_inspect_get_minor_version And finally in order to distinguish between certain flavours of Windows and RHEL you also need the "product variant": http://libguestfs.org/guestfs.3.html#guestfs_inspect_get_product_variant In the patch I sent, 'type' and 'distro' fields are pushed up to the vmmManager object already. ---------------------------------------------------------------------- -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v From crobinso at redhat.com Mon Apr 18 22:40:31 2011 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 18 Apr 2011 18:40:31 -0400 Subject: [libvirt] [PATCH DISCUSSION ONLY] Add inspection thread to virt-manager. In-Reply-To: <20110418221242.GM2641@amd.home.annexia.org> References: <20110418170146.GA485@amd.home.annexia.org> <4DACB209.9090101@redhat.com> <20110418221242.GM2641@amd.home.annexia.org> Message-ID: <4DACBDDF.6070003@redhat.com> On 04/18/2011 06:12 PM, Richard W.M. Jones wrote: > On Mon, Apr 18, 2011 at 05:50:01PM -0400, Cole Robinson wrote: >> First, thanks a lot for the patch! I'm sure everyone will be glad to see >> libguestfs integration in virt-manager. >> >>> [This patch is incomplete and just for discussion] >>> >>> Using libguestfs inspection[1], we can find out a lot about a virtual >>> machine, such as what operating system is installed, the OS version, >>> the OS distro, the hostname, the (real) disk usage, what apps are >>> installed, and lots more. It would be nice if virt-manager could use >>> this information: for example we could change the generic "computer" >>> icon into a Windows or Fedora logo if Windows or Fedora was installed >>> in the virtual machine. >>> >> >> That icon bit was originally intended for the current design, but since we've >> never really tracked OS info after install time, it never came about. >> >> Particularly for OS type/version tracking, I think we need a few things: >> >> - Everything standardize on some naming scheme, ideally libosinfo (though >> nothing is using it yet :/ ). libosinfo could also distribute the OS icons > > We sort of got bored of waiting for that train. We have a primitive > but rather effective system in libguestfs, which I explain at the end > of this email. > Yeah I hear you on that. However, for the libguestfs OS value to really be useful for us in virt-manager, we have to map it to the virtinst osdict which informs us of all the preferred device defaults (like virtio, usb tablet, virtio console, etc.). Which means more energy that would be better spent on getting libosinfo integrated. >> - Libvirt domain XML schema is extended with a field to track the >> installed OS. For most libvirt drivers this would just be metadata >> (vmware/esx the exception). Even though the data might be out of >> date if the guest is upgraded, I think it has become clear that >> there is a lot of value in tracking this in XML. > > Yes, I agree. This also solves the persistence problem. > > It's a bit of a shame that the field in the libvirt XML > isn't structured, at least so that different applications could store > their own data there without it being trampled upon by users or other > applications. (CC'd to libvir-list in case they have any thoughts > about that). > I think is fine the way it is, there is always going to be a use case for an end user freeform field like that. But there is certainly a case for a similar field (or multiple fields) for recording more metadata, possibly for use by apps. Maybe something with XML namespaces. Thanks, Cole From eblake at redhat.com Mon Apr 18 22:39:35 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 18 Apr 2011 16:39:35 -0600 Subject: [libvirt] [PATCH] virsh: nuke use of TRUE and FALSE Message-ID: <1303166375-17129-1-git-send-email-eblake@redhat.com> Gnulib already guarantees , so it is easier to just use the standardized spellings. * tools/virsh.c (vshCmdDef): Change callback to return real bool. (__vshControl): Change several fields to bool. (vshCommandOptBool): Change return type. All callers updated. * tools/Makefile.am (virsh-net-edit.c, virsh-pool-edit.c): Likewise. --- Mostly mechanical. tools/Makefile.am | 4 +- tools/virsh.c | 1674 ++++++++++++++++++++++++++--------------------------- 2 files changed, 835 insertions(+), 843 deletions(-) diff --git a/tools/Makefile.am b/tools/Makefile.am index 3e31dbd..826674a 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -64,7 +64,7 @@ BUILT_SOURCES = virsh-net-edit.c virsh-pool-edit.c virsh-net-edit.c: virsh.c Makefile.am $(AM_V_GEN)rm -f $@-tmp && \ echo '/* Automatically generated from: $^ */' > $@-tmp && \ - echo 'static int' >> $@-tmp && \ + echo 'static bool' >> $@-tmp && \ awk '/^cmdEdit/, /^}/' $< \ | sed -e 's/domain/network/g' \ -e 's/Domain/Network/g' \ @@ -79,7 +79,7 @@ virsh-net-edit.c: virsh.c Makefile.am virsh-pool-edit.c: virsh.c Makefile.am $(AM_V_GEN)rm -f $@-tmp && \ echo '/* Automatically generated from: $^ */' > $@-tmp && \ - echo 'static int' >> $@-tmp && \ + echo 'static bool' >> $@-tmp && \ awk '/^cmdEdit/, /^}/' $< \ | sed -e 's/domain/pool/g' \ -e 's/vshCommandOptDomain/vshCommandOptPool/g' \ diff --git a/tools/virsh.c b/tools/virsh.c index 486442e..21560d8 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -61,11 +61,6 @@ static char *progname; -#ifndef TRUE -# define TRUE 1 -# define FALSE 0 -#endif - #define VIRSH_MAX_XML_FILE 10*1024*1024 #define VSH_PROMPT_RW "virsh # " @@ -195,7 +190,7 @@ typedef struct vshCmdOpt { */ typedef struct { const char *name; - int (*handler) (vshControl *, const vshCmd *); /* command handler */ + bool (*handler) (vshControl *, const vshCmd *); /* command handler */ const vshCmdOptDef *opts; /* definition of command options */ const vshCmdInfo *info; /* details about command */ } vshCmdDef; @@ -217,11 +212,11 @@ typedef struct __vshControl { virConnectPtr conn; /* connection to hypervisor (MAY BE NULL) */ vshCmd *cmd; /* the current command */ char *cmdstr; /* string with command */ - int imode; /* interactive mode? */ - int quiet; /* quiet mode */ + bool imode; /* interactive mode? */ + bool quiet; /* quiet mode */ int debug; /* print debug messages? */ - int timing; /* print timing info? */ - int readonly; /* connect readonly (first time only, not + bool timing; /* print timing info? */ + bool readonly; /* connect readonly (first time only, not * during explicit connect command) */ char *logfile; /* log file name */ @@ -271,7 +266,7 @@ static int vshCommandOptLongLong(const vshCmd *cmd, const char *name, static int vshCommandOptULongLong(const vshCmd *cmd, const char *name, unsigned long long *value) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK; -static int vshCommandOptBool(const vshCmd *cmd, const char *name); +static bool vshCommandOptBool(const vshCmd *cmd, const char *name); static char *vshCommandOptArgv(const vshCmd *cmd, int count); #define VSH_BYID (1 << 1) @@ -599,7 +594,7 @@ static const vshCmdOptDef opts_help[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdHelp(vshControl *ctl, const vshCmd *cmd) { const char *name = NULL; @@ -621,7 +616,7 @@ cmdHelp(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, "\n"); } - return TRUE; + return true; } if (vshCmddefSearch(name)) { @@ -630,7 +625,7 @@ cmdHelp(vshControl *ctl, const vshCmd *cmd) return vshCmdGrpHelp(ctl, name); } else { vshError(ctl, _("command or command group '%s' doesn't exist"), name); - return FALSE; + return false; } } @@ -650,7 +645,7 @@ static const vshCmdOptDef opts_autostart[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdAutostart(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; @@ -658,10 +653,10 @@ cmdAutostart(vshControl *ctl, const vshCmd *cmd) int autostart; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) - return FALSE; + return false; autostart = !vshCommandOptBool(cmd, "disable"); @@ -671,7 +666,7 @@ cmdAutostart(vshControl *ctl, const vshCmd *cmd) else vshError(ctl, _("Failed to unmark domain %s as autostarted"), name); virDomainFree(dom); - return FALSE; + return false; } if (autostart) @@ -680,7 +675,7 @@ cmdAutostart(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, _("Domain %s unmarked as autostarted\n"), name); virDomainFree(dom); - return TRUE; + return true; } /* @@ -700,17 +695,17 @@ static const vshCmdOptDef opts_connect[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdConnect(vshControl *ctl, const vshCmd *cmd) { - int ro = vshCommandOptBool(cmd, "readonly"); + bool ro = vshCommandOptBool(cmd, "readonly"); const char *name = NULL; if (ctl->conn) { int ret; if ((ret = virConnectClose(ctl->conn)) != 0) { vshError(ctl, _("Failed to disconnect from the hypervisor, %d leaked reference(s)"), ret); - return FALSE; + return false; } ctl->conn = NULL; } @@ -718,15 +713,11 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd) VIR_FREE(ctl->name); if (vshCommandOptString(cmd, "name", &name) < 0) { vshError(ctl, "%s", _("Please specify valid connection URI")); - return FALSE; + return false; } ctl->name = vshStrdup(ctl, name); - if (!ro) { - ctl->readonly = 0; - } else { - ctl->readonly = 1; - } + ctl->readonly = ro; ctl->conn = virConnectOpenAuth(ctl->name, virConnectAuthPtrDefault, ctl->readonly ? VIR_CONNECT_RO : 0); @@ -734,7 +725,7 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd) if (!ctl->conn) vshError(ctl, "%s", _("Failed to connect to the hypervisor")); - return ctl->conn ? TRUE : FALSE; + return !!ctl->conn; } #ifndef WIN32 @@ -755,10 +746,10 @@ static const vshCmdOptDef opts_console[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdRunConsole(vshControl *ctl, virDomainPtr dom, const char *name) { - int ret = FALSE; + bool ret = false; virDomainInfo dominfo; if (virDomainGetInfo(dom, &dominfo) < 0) { @@ -774,25 +765,25 @@ cmdRunConsole(vshControl *ctl, virDomainPtr dom, const char *name) vshPrintExtra(ctl, _("Connected to domain %s\n"), virDomainGetName(dom)); vshPrintExtra(ctl, "%s", _("Escape character is ^]\n")); if (vshRunConsole(dom, name) == 0) - ret = TRUE; + ret = true; cleanup: return ret; } -static int +static bool cmdConsole(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - int ret = FALSE; + bool ret = false; const char *name = NULL; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptString(cmd, "devname", &name) < 0) { vshError(ctl, "%s", _("Invalid devname")); @@ -825,7 +816,7 @@ static const vshCmdOptDef opts_list[] = { }; -static int +static bool cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { int inactive = vshCommandOptBool(cmd, "inactive"); @@ -837,13 +828,13 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) inactive |= all; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (active) { maxid = virConnectNumOfDomains(ctl->conn); if (maxid < 0) { vshError(ctl, "%s", _("Failed to list active domains")); - return FALSE; + return false; } if (maxid) { ids = vshMalloc(ctl, sizeof(int) * maxid); @@ -851,7 +842,7 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) if ((maxid = virConnectListDomains(ctl->conn, &ids[0], maxid)) < 0) { vshError(ctl, "%s", _("Failed to list active domains")); VIR_FREE(ids); - return FALSE; + return false; } qsort(&ids[0], maxid, sizeof(int), idsorter); @@ -862,7 +853,7 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) if (maxname < 0) { vshError(ctl, "%s", _("Failed to list inactive domains")); VIR_FREE(ids); - return FALSE; + return false; } if (maxname) { names = vshMalloc(ctl, sizeof(char *) * maxname); @@ -871,7 +862,7 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) vshError(ctl, "%s", _("Failed to list inactive domains")); VIR_FREE(ids); VIR_FREE(names); - return FALSE; + return false; } qsort(&names[0], maxname, sizeof(char*), namesorter); @@ -923,7 +914,7 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } VIR_FREE(ids); VIR_FREE(names); - return TRUE; + return true; } /* @@ -940,24 +931,24 @@ static const vshCmdOptDef opts_domstate[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDomstate(vshControl *ctl, const vshCmd *cmd) { virDomainInfo info; virDomainPtr dom; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (virDomainGetInfo(dom, &info) == 0) vshPrint(ctl, "%s\n", _(vshDomainStateToString(info.state))); else - ret = FALSE; + ret = false; virDomainFree(dom); return ret; @@ -977,7 +968,7 @@ static const vshCmdOptDef opts_domblkstat[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; @@ -985,20 +976,20 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) struct _virDomainBlockStats stats; if (!vshConnectionUsability (ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain (ctl, cmd, &name))) - return FALSE; + return false; if (vshCommandOptString (cmd, "device", &device) <= 0) { virDomainFree(dom); - return FALSE; + return false; } if (virDomainBlockStats (dom, device, &stats, sizeof stats) == -1) { vshError(ctl, _("Failed to get block stats %s %s"), name, device); virDomainFree(dom); - return FALSE; + return false; } if (stats.rd_req >= 0) @@ -1017,7 +1008,7 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) vshPrint (ctl, "%s errs %lld\n", device, stats.errs); virDomainFree(dom); - return TRUE; + return true; } /* "domifstat" command @@ -1034,7 +1025,7 @@ static const vshCmdOptDef opts_domifstat[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDomIfstat (vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; @@ -1042,20 +1033,20 @@ cmdDomIfstat (vshControl *ctl, const vshCmd *cmd) struct _virDomainInterfaceStats stats; if (!vshConnectionUsability (ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain (ctl, cmd, &name))) - return FALSE; + return false; if (vshCommandOptString (cmd, "interface", &device) <= 0) { virDomainFree(dom); - return FALSE; + return false; } if (virDomainInterfaceStats (dom, device, &stats, sizeof stats) == -1) { vshError(ctl, _("Failed to get interface stats %s %s"), name, device); virDomainFree(dom); - return FALSE; + return false; } if (stats.rx_bytes >= 0) @@ -1083,7 +1074,7 @@ cmdDomIfstat (vshControl *ctl, const vshCmd *cmd) vshPrint (ctl, "%s tx_drop %lld\n", device, stats.tx_drop); virDomainFree(dom); - return TRUE; + return true; } /* @@ -1100,7 +1091,7 @@ static const vshCmdOptDef opts_dommemstat[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDomMemStat(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; @@ -1109,16 +1100,16 @@ cmdDomMemStat(vshControl *ctl, const vshCmd *cmd) unsigned int nr_stats, i; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) - return FALSE; + return false; nr_stats = virDomainMemoryStats (dom, stats, VIR_DOMAIN_MEMORY_STAT_NR, 0); if (nr_stats == -1) { vshError(ctl, _("Failed to get memory statistics for domain %s"), name); virDomainFree(dom); - return FALSE; + return false; } for (i = 0; i < nr_stats; i++) { @@ -1137,7 +1128,7 @@ cmdDomMemStat(vshControl *ctl, const vshCmd *cmd) } virDomainFree(dom); - return TRUE; + return true; } /* @@ -1155,28 +1146,28 @@ static const vshCmdOptDef opts_domblkinfo[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDomblkinfo(vshControl *ctl, const vshCmd *cmd) { virDomainBlockInfo info; virDomainPtr dom; - int ret = TRUE; + bool ret = true; const char *device = NULL; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptString (cmd, "device", &device) <= 0) { virDomainFree(dom); - return FALSE; + return false; } if (virDomainGetBlockInfo(dom, device, &info, 0) < 0) { virDomainFree(dom); - return FALSE; + return false; } vshPrint(ctl, "%-15s %llu\n", _("Capacity:"), info.capacity); @@ -1201,24 +1192,24 @@ static const vshCmdOptDef opts_suspend[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSuspend(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; const char *name; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) - return FALSE; + return false; if (virDomainSuspend(dom) == 0) { vshPrint(ctl, _("Domain %s suspended\n"), name); } else { vshError(ctl, _("Failed to suspend domain %s"), name); - ret = FALSE; + ret = false; } virDomainFree(dom); @@ -1243,12 +1234,12 @@ static const vshCmdOptDef opts_create[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdCreate(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; const char *from = NULL; - int ret = TRUE; + bool ret = true; char *buffer; #ifndef WIN32 int console = vshCommandOptBool(cmd, "console"); @@ -1256,13 +1247,13 @@ cmdCreate(vshControl *ctl, const vshCmd *cmd) unsigned int flags = VIR_DOMAIN_NONE; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return FALSE; + return false; if (vshCommandOptBool(cmd, "paused")) flags |= VIR_DOMAIN_START_PAUSED; @@ -1280,7 +1271,7 @@ cmdCreate(vshControl *ctl, const vshCmd *cmd) virDomainFree(dom); } else { vshError(ctl, _("Failed to create domain from %s"), from); - ret = FALSE; + ret = false; } return ret; } @@ -1299,22 +1290,22 @@ static const vshCmdOptDef opts_define[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDefine(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; const char *from = NULL; - int ret = TRUE; + bool ret = true; char *buffer; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return FALSE; + return false; dom = virDomainDefineXML(ctl->conn, buffer); VIR_FREE(buffer); @@ -1325,7 +1316,7 @@ cmdDefine(vshControl *ctl, const vshCmd *cmd) virDomainFree(dom); } else { vshError(ctl, _("Failed to define domain from %s"), from); - ret = FALSE; + ret = false; } return ret; } @@ -1344,19 +1335,19 @@ static const vshCmdOptDef opts_undefine[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdUndefine(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - int ret = TRUE; + bool ret = true; const char *name = NULL; int id; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "domain", &name) <= 0) - return FALSE; + return false; if (name && virStrToLong_i(name, NULL, 10, &id) == 0 && id >= 0 && (dom = virDomainLookupByID(ctl->conn, id))) { @@ -1366,17 +1357,17 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) " using its name or UUID"), name); virDomainFree(dom); - return FALSE; + return false; } if (!(dom = vshCommandOptDomainBy(ctl, cmd, &name, VSH_BYNAME|VSH_BYUUID))) - return FALSE; + return false; if (virDomainUndefine(dom) == 0) { vshPrint(ctl, _("Domain %s has been undefined\n"), name); } else { vshError(ctl, _("Failed to undefine domain %s"), name); - ret = FALSE; + ret = false; } virDomainFree(dom); @@ -1404,27 +1395,27 @@ static const vshCmdOptDef opts_start[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdStart(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - int ret = TRUE; + bool ret = true; #ifndef WIN32 int console = vshCommandOptBool(cmd, "console"); #endif unsigned int flags = VIR_DOMAIN_NONE; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL, VSH_BYNAME | VSH_BYUUID))) - return FALSE; + return false; if (virDomainGetID(dom) != (unsigned int)-1) { vshError(ctl, "%s", _("Domain is already active")); virDomainFree(dom); - return FALSE; + return false; } if (vshCommandOptBool(cmd, "paused")) @@ -1441,7 +1432,7 @@ cmdStart(vshControl *ctl, const vshCmd *cmd) #endif } else { vshError(ctl, _("Failed to start domain %s"), virDomainGetName(dom)); - ret = FALSE; + ret = false; } virDomainFree(dom); return ret; @@ -1462,28 +1453,28 @@ static const vshCmdOptDef opts_save[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSave(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; const char *name = NULL; const char *to = NULL; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &to) <= 0) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) - return FALSE; + return false; if (virDomainSave(dom, to) == 0) { vshPrint(ctl, _("Domain %s saved to %s\n"), name, to); } else { vshError(ctl, _("Failed to save domain %s to %s"), name, to); - ret = FALSE; + ret = false; } virDomainFree(dom); @@ -1507,24 +1498,24 @@ static const vshCmdOptDef opts_managedsave[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdManagedSave(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; const char *name; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) - return FALSE; + return false; if (virDomainManagedSave(dom, 0) == 0) { vshPrint(ctl, _("Domain %s state saved by libvirt\n"), name); } else { vshError(ctl, _("Failed to save domain %s state"), name); - ret = FALSE; + ret = false; } virDomainFree(dom); @@ -1545,19 +1536,19 @@ static const vshCmdOptDef opts_managedsaveremove[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdManagedSaveRemove(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; const char *name; - int ret = FALSE; + bool ret = false; int hassave; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) - return FALSE; + return false; hassave = virDomainHasManagedSaveImage(dom, 0); if (hassave < 0) { @@ -1578,7 +1569,7 @@ cmdManagedSaveRemove(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, _("Domain %s has no manage save image; removal skipped"), name); - ret = TRUE; + ret = true; cleanup: virDomainFree(dom); @@ -1602,7 +1593,7 @@ static const vshCmdOptDef opts_schedinfo[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSchedInfoUpdate(vshControl *ctl, const vshCmd *cmd, virSchedParameterPtr param) { @@ -1696,7 +1687,7 @@ cmdSchedInfoUpdate(vshControl *ctl, const vshCmd *cmd, } -static int +static bool cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) { char *schedulertype; @@ -1705,13 +1696,13 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) int nparams = 0; int update = 0; int i, ret; - int ret_val = FALSE; + int ret_val = false; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; /* Print SchedulerType */ schedulertype = virDomainGetSchedulerType(dom, &nparams); @@ -1763,7 +1754,7 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) } } - ret_val = TRUE; + ret_val = true; for (i = 0; i < nparams; i++){ switch (params[i].type) { case VIR_DOMAIN_SCHED_FIELD_INT: @@ -1810,23 +1801,23 @@ static const vshCmdOptDef opts_restore[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdRestore(vshControl *ctl, const vshCmd *cmd) { const char *from = NULL; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virDomainRestore(ctl->conn, from) == 0) { vshPrint(ctl, _("Domain restored from %s\n"), from); } else { vshError(ctl, _("Failed to restore domain from %s"), from); - ret = FALSE; + ret = false; } return ret; } @@ -1848,23 +1839,23 @@ static const vshCmdOptDef opts_dump[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDump(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; const char *name = NULL; const char *to = NULL; - int ret = TRUE; + bool ret = true; int flags = 0; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &to) <= 0) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) - return FALSE; + return false; if (vshCommandOptBool (cmd, "live")) flags |= VIR_DUMP_LIVE; @@ -1875,7 +1866,7 @@ cmdDump(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, _("Domain %s dumped to %s\n"), name, to); } else { vshError(ctl, _("Failed to core dump domain %s to %s"), name, to); - ret = FALSE; + ret = false; } virDomainFree(dom); @@ -1896,24 +1887,24 @@ static const vshCmdOptDef opts_resume[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdResume(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) - return FALSE; + return false; if (virDomainResume(dom) == 0) { vshPrint(ctl, _("Domain %s resumed\n"), name); } else { vshError(ctl, _("Failed to resume domain %s"), name); - ret = FALSE; + ret = false; } virDomainFree(dom); @@ -1934,24 +1925,24 @@ static const vshCmdOptDef opts_shutdown[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdShutdown(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) - return FALSE; + return false; if (virDomainShutdown(dom) == 0) { vshPrint(ctl, _("Domain %s is being shutdown\n"), name); } else { vshError(ctl, _("Failed to shutdown domain %s"), name); - ret = FALSE; + ret = false; } virDomainFree(dom); @@ -1972,24 +1963,24 @@ static const vshCmdOptDef opts_reboot[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdReboot(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) - return FALSE; + return false; if (virDomainReboot(dom, 0) == 0) { vshPrint(ctl, _("Domain %s is being rebooted\n"), name); } else { vshError(ctl, _("Failed to reboot domain %s"), name); - ret = FALSE; + ret = false; } virDomainFree(dom); @@ -2010,24 +2001,24 @@ static const vshCmdOptDef opts_destroy[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDestroy(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) - return FALSE; + return false; if (virDomainDestroy(dom) == 0) { vshPrint(ctl, _("Domain %s destroyed\n"), name); } else { vshError(ctl, _("Failed to destroy domain %s"), name); - ret = FALSE; + ret = false; } virDomainFree(dom); @@ -2048,7 +2039,7 @@ static const vshCmdOptDef opts_dominfo[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDominfo(vshControl *ctl, const vshCmd *cmd) { virDomainInfo info; @@ -2056,15 +2047,16 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) virSecurityModel secmodel; virSecurityLabelPtr seclabel; int persistent = 0; - int ret = TRUE, autostart; + bool ret = true; + int autostart; unsigned int id; char *str, uuid[VIR_UUID_STRING_BUFLEN]; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; id = virDomainGetID(dom); if (id == ((unsigned int)-1)) @@ -2106,7 +2098,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) info.memory); } else { - ret = FALSE; + ret = false; } /* Check and display whether the domain is persistent or not */ @@ -2128,7 +2120,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) if (virNodeGetSecurityModel(ctl->conn, &secmodel) == -1) { if (last_error->code != VIR_ERR_NO_SUPPORT) { virDomainFree(dom); - return FALSE; + return false; } else { virFreeError(last_error); last_error = NULL; @@ -2142,13 +2134,13 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) /* Security labels are only valid for active domains */ if (VIR_ALLOC(seclabel) < 0) { virDomainFree(dom); - return FALSE; + return false; } if (virDomainGetSecurityLabel(dom, seclabel) == -1) { virDomainFree(dom); VIR_FREE(seclabel); - return FALSE; + return false; } else { if (seclabel->label[0] != '\0') vshPrint(ctl, "%-15s %s (%s)\n", _("Security label:"), @@ -2177,18 +2169,18 @@ static const vshCmdOptDef opts_domjobinfo[] = { }; -static int +static bool cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd) { virDomainJobInfo info; virDomainPtr dom; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (virDomainGetJobInfo(dom, &info) == 0) { const char *unit; @@ -2238,7 +2230,7 @@ cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, "%-17s %-.3lf %s\n", _("File total:"), val, unit); } } else { - ret = FALSE; + ret = false; } cleanup: virDomainFree(dom); @@ -2259,20 +2251,20 @@ static const vshCmdOptDef opts_domjobabort[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDomjobabort(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (virDomainAbortJob(dom) < 0) - ret = FALSE; + ret = false; virDomainFree(dom); return ret; @@ -2293,10 +2285,10 @@ static const vshCmdOptDef opts_freecell[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdFreecell(vshControl *ctl, const vshCmd *cmd) { - int func_ret = FALSE; + int func_ret = false; int ret; int cell = -1, cell_given; unsigned long long memory; @@ -2312,7 +2304,7 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd) if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if ( (cell_given = vshCommandOptInt(cmd, "cellno", &cell)) < 0) { vshError(ctl, "%s", _("cell number has to be a number")); @@ -2399,7 +2391,7 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, "%d: %llu kB\n", cell, (memory/1024)); } - func_ret = TRUE; + func_ret = true; cleanup: xmlXPathFreeContext(ctxt); @@ -2426,7 +2418,7 @@ static const vshCmdOptDef opts_maxvcpus[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdMaxvcpus(vshControl *ctl, const vshCmd *cmd) { const char *type = NULL; @@ -2434,18 +2426,18 @@ cmdMaxvcpus(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptString(cmd, "type", &type) < 0) { vshError(ctl, "%s", _("Invalid type")); - return FALSE; + return false; } if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; vcpus = virConnectGetMaxVcpus(ctl->conn, type); if (vcpus < 0) - return FALSE; + return false; vshPrint(ctl, "%d\n", vcpus); - return TRUE; + return true; } /* @@ -2466,11 +2458,11 @@ static const vshCmdOptDef opts_vcpucount[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVcpucount(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - int ret = TRUE; + bool ret = true; int maximum = vshCommandOptBool(cmd, "maximum"); int current = vshCommandOptBool(cmd, "current"); int config = vshCommandOptBool(cmd, "config"); @@ -2481,12 +2473,12 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd) if (maximum && current) { vshError(ctl, "%s", _("--maximum and --current cannot both be specified")); - return FALSE; + return false; } if (config && live) { vshError(ctl, "%s", _("--config and --live cannot both be specified")); - return FALSE; + return false; } /* We want one of each pair of mutually exclusive options; that * is, use of flags requires exactly two options. */ @@ -2497,14 +2489,14 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd) : config ? "config" : "live"), maximum + current ? "config" : "maximum", maximum + current ? "live" : "current"); - return FALSE; + return false; } if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; /* In all cases, try the new API first; if it fails because we are * talking to an older client, try a fallback API before giving @@ -2528,7 +2520,7 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd) if (count < 0) { virshReportError(ctl); - ret = FALSE; + ret = false; } else if (all) { vshPrint(ctl, "%-12s %-12s %3d\n", _("maximum"), _("config"), count); @@ -2549,7 +2541,7 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd) if (count < 0) { virshReportError(ctl); - ret = FALSE; + ret = false; } else if (all) { vshPrint(ctl, "%-12s %-12s %3d\n", _("maximum"), _("live"), count); @@ -2586,7 +2578,7 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd) if (count < 0) { virshReportError(ctl); - ret = FALSE; + ret = false; } else if (all) { vshPrint(ctl, "%-12s %-12s %3d\n", _("current"), _("config"), count); @@ -2608,7 +2600,7 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd) if (count < 0) { virshReportError(ctl); - ret = FALSE; + ret = false; } else if (all) { vshPrint(ctl, "%-12s %-12s %3d\n", _("current"), _("live"), count); @@ -2637,7 +2629,7 @@ static const vshCmdOptDef opts_vcpuinfo[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVcpuinfo(vshControl *ctl, const vshCmd *cmd) { virDomainInfo info; @@ -2647,22 +2639,22 @@ cmdVcpuinfo(vshControl *ctl, const vshCmd *cmd) unsigned char *cpumap; int ncpus; size_t cpumaplen; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) { virDomainFree(dom); - return FALSE; + return false; } if (virDomainGetInfo(dom, &info) != 0) { virDomainFree(dom); - return FALSE; + return false; } cpuinfo = vshMalloc(ctl, sizeof(virVcpuInfo)*info.nrVirtCpu); @@ -2700,7 +2692,7 @@ cmdVcpuinfo(vshControl *ctl, const vshCmd *cmd) vshError(ctl, "%s", _("Domain shut off, virtual CPUs not present.")); } - ret = FALSE; + ret = false; } VIR_FREE(cpumap); @@ -2725,7 +2717,7 @@ static const vshCmdOptDef opts_vcpupin[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVcpupin(vshControl *ctl, const vshCmd *cmd) { virDomainInfo info; @@ -2733,44 +2725,44 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd) virNodeInfo nodeinfo; int vcpu; const char *cpulist = NULL; - int ret = TRUE; + bool ret = true; unsigned char *cpumap; int cpumaplen; int i; enum { expect_num, expect_num_or_comma } state; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptInt(cmd, "vcpu", &vcpu) <= 0) { vshError(ctl, "%s", _("vcpupin: Invalid or missing vCPU number.")); virDomainFree(dom); - return FALSE; + return false; } if (vshCommandOptString(cmd, "cpulist", &cpulist) <= 0) { virDomainFree(dom); - return FALSE; + return false; } if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) { virDomainFree(dom); - return FALSE; + return false; } if (virDomainGetInfo(dom, &info) != 0) { vshError(ctl, "%s", _("vcpupin: failed to get domain informations.")); virDomainFree(dom); - return FALSE; + return false; } if (vcpu >= info.nrVirtCpu) { vshError(ctl, "%s", _("vcpupin: Invalid vCPU number.")); virDomainFree(dom); - return FALSE; + return false; } /* Check that the cpulist parameter is a comma-separated list of @@ -2779,7 +2771,7 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd) if (cpulist[0] == '\0') { vshError(ctl, "%s", _("cpulist: Invalid format. Empty string.")); virDomainFree (dom); - return FALSE; + return false; } state = expect_num; @@ -2791,7 +2783,7 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd) "digit at position %d (near '%c')."), cpulist, i, cpulist[i]); virDomainFree (dom); - return FALSE; + return false; } state = expect_num_or_comma; break; @@ -2803,7 +2795,7 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd) "digit or comma at position %d (near '%c')."), cpulist, i, cpulist[i]); virDomainFree (dom); - return FALSE; + return false; } } } @@ -2812,7 +2804,7 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd) "at position %d."), cpulist, i); virDomainFree (dom); - return FALSE; + return false; } cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo)); @@ -2827,7 +2819,7 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd) vshError(ctl, _("Physical CPU %d doesn't exist."), cpu); VIR_FREE(cpumap); virDomainFree(dom); - return FALSE; + return false; } cpulist = strchr(cpulist, ','); if (cpulist) @@ -2835,7 +2827,7 @@ cmdVcpupin(vshControl *ctl, const vshCmd *cmd) } while (cpulist); if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) { - ret = FALSE; + ret = false; } VIR_FREE(cpumap); @@ -2861,12 +2853,12 @@ static const vshCmdOptDef opts_setvcpus[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; int count; - int ret = TRUE; + bool ret = true; int maximum = vshCommandOptBool(cmd, "maximum"); int config = vshCommandOptBool(cmd, "config"); int live = vshCommandOptBool(cmd, "live"); @@ -2875,10 +2867,10 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) (live ? VIR_DOMAIN_VCPU_LIVE : 0)); if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptInt(cmd, "count", &count) < 0) { vshError(ctl, "%s", _("Invalid number of virtual CPUs")); @@ -2887,7 +2879,7 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) if (!flags) { if (virDomainSetVcpus(dom, count) != 0) { - ret = FALSE; + ret = false; } } else { /* If the --maximum flag was given, we need to ensure only the @@ -2903,14 +2895,14 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) /* Warn the user about the invalid flag combination */ vshError(ctl, _("--maximum must be used with --config only")); - ret = FALSE; + ret = false; goto cleanup; } } /* Apply the virtual cpu changes */ if (virDomainSetVcpusFlags(dom, count, flags) < 0) { - ret = FALSE; + ret = false; } } @@ -2937,13 +2929,13 @@ static const vshCmdOptDef opts_setmem[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSetmem(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; virDomainInfo info; unsigned long kilobytes = 0; - int ret = TRUE; + bool ret = true; int config = vshCommandOptBool(cmd, "config"); int live = vshCommandOptBool(cmd, "live"); int current = vshCommandOptBool(cmd, "current"); @@ -2952,7 +2944,7 @@ cmdSetmem(vshControl *ctl, const vshCmd *cmd) if (current) { if (live || config) { vshError(ctl, "%s", _("--current must be specified exclusively")); - return FALSE; + return false; } flags = VIR_DOMAIN_MEM_CURRENT; } else { @@ -2966,42 +2958,42 @@ cmdSetmem(vshControl *ctl, const vshCmd *cmd) } if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptUL(cmd, "kilobytes", &kilobytes) < 0) { vshError(ctl, "%s", _("memory size has to be a number")); - return FALSE; + return false; } if (kilobytes <= 0) { virDomainFree(dom); vshError(ctl, _("Invalid value of %lu for memory size"), kilobytes); - return FALSE; + return false; } if (virDomainGetInfo(dom, &info) != 0) { virDomainFree(dom); vshError(ctl, "%s", _("Unable to verify MaxMemorySize")); - return FALSE; + return false; } if (kilobytes > info.maxMem) { virDomainFree(dom); vshError(ctl, _("Requested memory size %lu kb is larger than maximum of %lu kb"), kilobytes, info.maxMem); - return FALSE; + return false; } if (flags == -1) { if (virDomainSetMemory(dom, kilobytes) != 0) { - ret = FALSE; + ret = false; } } else { if (virDomainSetMemoryFlags(dom, kilobytes, flags) < 0) { - ret = FALSE; + ret = false; } } @@ -3027,13 +3019,13 @@ static const vshCmdOptDef opts_setmaxmem[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; virDomainInfo info; int kilobytes = 0; - int ret = TRUE; + bool ret = true; int config = vshCommandOptBool(cmd, "config"); int live = vshCommandOptBool(cmd, "live"); int current = vshCommandOptBool(cmd, "current"); @@ -3042,7 +3034,7 @@ cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd) if (current) { if (live || config) { vshError(ctl, "%s", _("--current must be specified exclusively")); - return FALSE; + return false; } } else { if (config) @@ -3055,37 +3047,37 @@ cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd) } if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptInt(cmd, "kilobytes", &kilobytes) < 0) { vshError(ctl, "%s", _("memory size has to be a number")); - return FALSE; + return false; } if (kilobytes <= 0) { virDomainFree(dom); vshError(ctl, _("Invalid value of %d for memory size"), kilobytes); - return FALSE; + return false; } if (virDomainGetInfo(dom, &info) != 0) { virDomainFree(dom); vshError(ctl, "%s", _("Unable to verify current MemorySize")); - return FALSE; + return false; } if (flags == -1) { if (virDomainSetMaxMemory(dom, kilobytes) != 0) { vshError(ctl, "%s", _("Unable to change MaxMemorySize")); - ret = FALSE; + ret = false; } } else { if (virDomainSetMemoryFlags(dom, kilobytes, flags) < 0) { vshError(ctl, "%s", _("Unable to change MaxMemorySize")); - ret = FALSE; + ret = false; } } @@ -3112,7 +3104,7 @@ static const vshCmdOptDef opts_blkiotune[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdBlkiotune(vshControl * ctl, const vshCmd * cmd) { virDomainPtr dom; @@ -3120,13 +3112,13 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd) int nparams = 0; unsigned int i = 0; virBlkioParameterPtr params = NULL, temp = NULL; - int ret = FALSE; + bool ret = false; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptInt(cmd, "weight", &weight) < 0) { vshError(ctl, "%s", @@ -3153,7 +3145,7 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd) if (nparams == 0) { /* nothing to output */ - ret = TRUE; + ret = true; goto cleanup; } @@ -3195,7 +3187,7 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd) } } - ret = TRUE; + ret = true; } else { /* set the blkio parameters */ params = vshCalloc(ctl, nparams, sizeof(*params)); @@ -3214,7 +3206,7 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd) if (virDomainSetBlkioParameters(dom, params, nparams, 0) != 0) vshError(ctl, "%s", _("Unable to change blkio parameters")); else - ret = TRUE; + ret = true; } cleanup: @@ -3248,7 +3240,7 @@ static const vshCmdOptDef opts_memtune[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdMemtune(vshControl * ctl, const vshCmd * cmd) { virDomainPtr dom; @@ -3257,13 +3249,13 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) int nparams = 0; unsigned int i = 0; virMemoryParameterPtr params = NULL, temp = NULL; - int ret = FALSE; + bool ret = false; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptLongLong(cmd, "hard-limit", &hard_limit) < 0 || vshCommandOptLongLong(cmd, "soft-limit", &soft_limit) < 0 || @@ -3296,7 +3288,7 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) if (nparams == 0) { /* nothing to output */ - ret = TRUE; + ret = true; goto cleanup; } @@ -3341,7 +3333,7 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) } } - ret = TRUE; + ret = true; } else { /* set the memory parameters */ params = vshCalloc(ctl, nparams, sizeof(*params)); @@ -3385,7 +3377,7 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) if (virDomainSetMemoryParameters(dom, params, nparams, 0) != 0) vshError(ctl, "%s", _("Unable to change memory parameters")); else - ret = TRUE; + ret = true; } cleanup: @@ -3403,17 +3395,17 @@ static const vshCmdInfo info_nodeinfo[] = { {NULL, NULL} }; -static int +static bool cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { virNodeInfo info; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (virNodeGetInfo(ctl->conn, &info) < 0) { vshError(ctl, "%s", _("failed to get node information")); - return FALSE; + return false; } vshPrint(ctl, "%-20s %s\n", _("CPU model:"), info.model); vshPrint(ctl, "%-20s %d\n", _("CPU(s):"), info.cpus); @@ -3424,7 +3416,7 @@ cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) vshPrint(ctl, "%-20s %d\n", _("NUMA cell(s):"), info.nodes); vshPrint(ctl, "%-20s %lu kB\n", _("Memory size:"), info.memory); - return TRUE; + return true; } /* @@ -3436,22 +3428,22 @@ static const vshCmdInfo info_capabilities[] = { {NULL, NULL} }; -static int +static bool cmdCapabilities (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { char *caps; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if ((caps = virConnectGetCapabilities (ctl->conn)) == NULL) { vshError(ctl, "%s", _("failed to get capabilities")); - return FALSE; + return false; } vshPrint (ctl, "%s\n", caps); VIR_FREE(caps); - return TRUE; + return true; } /* @@ -3471,11 +3463,11 @@ static const vshCmdOptDef opts_dumpxml[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDumpXML(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - int ret = TRUE; + bool ret = true; char *dump; int flags = 0; int inactive = vshCommandOptBool(cmd, "inactive"); @@ -3490,17 +3482,17 @@ cmdDumpXML(vshControl *ctl, const vshCmd *cmd) flags |= VIR_DOMAIN_XML_UPDATE_CPU; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; dump = virDomainGetXMLDesc(dom, flags); if (dump != NULL) { vshPrint(ctl, "%s", dump); VIR_FREE(dump); } else { - ret = FALSE; + ret = false; } virDomainFree(dom); @@ -3522,10 +3514,10 @@ static const vshCmdOptDef opts_domxmlfromnative[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDomXMLFromNative(vshControl *ctl, const vshCmd *cmd) { - int ret = TRUE; + bool ret = true; const char *format = NULL; const char *configFile = NULL; char *configData; @@ -3533,21 +3525,21 @@ cmdDomXMLFromNative(vshControl *ctl, const vshCmd *cmd) int flags = 0; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "format", &format) < 0 || vshCommandOptString(cmd, "config", &configFile) < 0) - return FALSE; + return false; if (virFileReadAll(configFile, 1024*1024, &configData) < 0) - return FALSE; + return false; xmlData = virConnectDomainXMLFromNative(ctl->conn, format, configData, flags); if (xmlData != NULL) { vshPrint(ctl, "%s", xmlData); VIR_FREE(xmlData); } else { - ret = FALSE; + ret = false; } return ret; @@ -3568,10 +3560,10 @@ static const vshCmdOptDef opts_domxmltonative[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDomXMLToNative(vshControl *ctl, const vshCmd *cmd) { - int ret = TRUE; + bool ret = true; const char *format = NULL; const char *xmlFile = NULL; char *configData; @@ -3579,21 +3571,21 @@ cmdDomXMLToNative(vshControl *ctl, const vshCmd *cmd) int flags = 0; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "format", &format) < 0 || vshCommandOptString(cmd, "xml", &xmlFile) < 0) - return FALSE; + return false; if (virFileReadAll(xmlFile, 1024*1024, &xmlData) < 0) - return FALSE; + return false; configData = virConnectDomainXMLToNative(ctl->conn, format, xmlData, flags); if (configData != NULL) { vshPrint(ctl, "%s", configData); VIR_FREE(configData); } else { - ret = FALSE; + ret = false; } return ret; @@ -3613,20 +3605,20 @@ static const vshCmdOptDef opts_domname[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDomname(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL, VSH_BYID|VSH_BYUUID))) - return FALSE; + return false; vshPrint(ctl, "%s\n", virDomainGetName(dom)); virDomainFree(dom); - return TRUE; + return true; } /* @@ -3643,17 +3635,17 @@ static const vshCmdOptDef opts_domid[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDomid(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; unsigned int id; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL, VSH_BYNAME|VSH_BYUUID))) - return FALSE; + return false; id = virDomainGetID(dom); if (id == ((unsigned int)-1)) @@ -3661,7 +3653,7 @@ cmdDomid(vshControl *ctl, const vshCmd *cmd) else vshPrint(ctl, "%d\n", id); virDomainFree(dom); - return TRUE; + return true; } /* @@ -3678,17 +3670,17 @@ static const vshCmdOptDef opts_domuuid[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDomuuid(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; char uuid[VIR_UUID_STRING_BUFLEN]; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL, VSH_BYNAME|VSH_BYID))) - return FALSE; + return false; if (virDomainGetUUIDString(dom, uuid) != -1) vshPrint(ctl, "%s\n", uuid); @@ -3696,7 +3688,7 @@ cmdDomuuid(vshControl *ctl, const vshCmd *cmd) vshError(ctl, "%s", _("failed to get domain UUID")); virDomainFree(dom); - return TRUE; + return true; } /* @@ -3849,7 +3841,7 @@ print_job_progress(unsigned long long remaining, unsigned long long total) fprintf(stderr, "\rMigration: [%3d %%]", progress); } -static int +static bool cmdMigrate (vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom = NULL; @@ -3874,13 +3866,13 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd) #endif if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptBool (cmd, "verbose")) verbose = true; if (vshCommandOptBool (cmd, "live")) - live_flag = TRUE; + live_flag = true; if (vshCommandOptInt(cmd, "timeout", &timeout) > 0) { if (! live_flag) { vshError(ctl, "%s", _("migrate: Unexpected timeout for offline migration")); @@ -3929,15 +3921,15 @@ repoll: if (ret > 0) { if (saferead(p[0], &retchar, sizeof(retchar)) > 0) { if (retchar == '0') { - ret = TRUE; + ret = true; if (verbose) { /* print [100 %] */ print_job_progress(0, 1); } } else - ret = FALSE; + ret = false; } else - ret = FALSE; + ret = false; break; } @@ -3945,7 +3937,7 @@ repoll: if (errno == EINTR) { if (intCaught) { virDomainAbortJob(dom); - ret = FALSE; + ret = false; intCaught = 0; } else goto repoll; @@ -4001,18 +3993,18 @@ static const vshCmdOptDef opts_migrate_setmaxdowntime[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdMigrateSetMaxDowntime(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom = NULL; long long downtime = 0; - int ret = FALSE; + bool ret = false; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptLongLong(cmd, "downtime", &downtime) < 0 || downtime < 1) { @@ -4023,7 +4015,7 @@ cmdMigrateSetMaxDowntime(vshControl *ctl, const vshCmd *cmd) if (virDomainMigrateSetMaxDowntime(dom, downtime, 0)) goto done; - ret = TRUE; + ret = true; done: virDomainFree(dom); @@ -4046,7 +4038,7 @@ static const vshCmdOptDef opts_network_autostart[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNetworkAutostart(vshControl *ctl, const vshCmd *cmd) { virNetworkPtr network; @@ -4054,10 +4046,10 @@ cmdNetworkAutostart(vshControl *ctl, const vshCmd *cmd) int autostart; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(network = vshCommandOptNetwork(ctl, cmd, &name))) - return FALSE; + return false; autostart = !vshCommandOptBool(cmd, "disable"); @@ -4067,7 +4059,7 @@ cmdNetworkAutostart(vshControl *ctl, const vshCmd *cmd) else vshError(ctl, _("failed to unmark network %s as autostarted"), name); virNetworkFree(network); - return FALSE; + return false; } if (autostart) @@ -4076,7 +4068,7 @@ cmdNetworkAutostart(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, _("Network %s unmarked as autostarted\n"), name); virNetworkFree(network); - return TRUE; + return true; } /* @@ -4093,22 +4085,22 @@ static const vshCmdOptDef opts_network_create[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNetworkCreate(vshControl *ctl, const vshCmd *cmd) { virNetworkPtr network; const char *from = NULL; - int ret = TRUE; + bool ret = true; char *buffer; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return FALSE; + return false; network = virNetworkCreateXML(ctl->conn, buffer); VIR_FREE(buffer); @@ -4119,7 +4111,7 @@ cmdNetworkCreate(vshControl *ctl, const vshCmd *cmd) virNetworkFree(network); } else { vshError(ctl, _("Failed to create network from %s"), from); - ret = FALSE; + ret = false; } return ret; } @@ -4139,22 +4131,22 @@ static const vshCmdOptDef opts_network_define[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNetworkDefine(vshControl *ctl, const vshCmd *cmd) { virNetworkPtr network; const char *from = NULL; - int ret = TRUE; + bool ret = true; char *buffer; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return FALSE; + return false; network = virNetworkDefineXML(ctl->conn, buffer); VIR_FREE(buffer); @@ -4165,7 +4157,7 @@ cmdNetworkDefine(vshControl *ctl, const vshCmd *cmd) virNetworkFree(network); } else { vshError(ctl, _("Failed to define network from %s"), from); - ret = FALSE; + ret = false; } return ret; } @@ -4185,24 +4177,24 @@ static const vshCmdOptDef opts_network_destroy[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNetworkDestroy(vshControl *ctl, const vshCmd *cmd) { virNetworkPtr network; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(network = vshCommandOptNetwork(ctl, cmd, &name))) - return FALSE; + return false; if (virNetworkDestroy(network) == 0) { vshPrint(ctl, _("Network %s destroyed\n"), name); } else { vshError(ctl, _("Failed to destroy network %s"), name); - ret = FALSE; + ret = false; } virNetworkFree(network); @@ -4224,25 +4216,25 @@ static const vshCmdOptDef opts_network_dumpxml[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNetworkDumpXML(vshControl *ctl, const vshCmd *cmd) { virNetworkPtr network; - int ret = TRUE; + bool ret = true; char *dump; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(network = vshCommandOptNetwork(ctl, cmd, NULL))) - return FALSE; + return false; dump = virNetworkGetXMLDesc(network, 0); if (dump != NULL) { vshPrint(ctl, "%s", dump); VIR_FREE(dump); } else { - ret = FALSE; + ret = false; } virNetworkFree(network); @@ -4263,7 +4255,7 @@ static const vshCmdOptDef opts_network_info[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNetworkInfo(vshControl *ctl, const vshCmd *cmd) { virNetworkPtr network; @@ -4274,11 +4266,11 @@ cmdNetworkInfo(vshControl *ctl, const vshCmd *cmd) char *bridge = NULL; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL, VSH_BYNAME))) - return FALSE; + return false; vshPrint(ctl, "%-15s %s\n", _("Name"), virNetworkGetName(network)); @@ -4305,7 +4297,7 @@ cmdNetworkInfo(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, "%-15s %s\n", _("Bridge:"), bridge); virNetworkFree(network); - return TRUE; + return true; } /* @@ -4322,10 +4314,10 @@ static const vshCmdOptDef opts_interface_edit[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdInterfaceEdit (vshControl *ctl, const vshCmd *cmd) { - int ret = FALSE; + bool ret = false; virInterfacePtr iface = NULL; char *tmp = NULL; char *doc = NULL; @@ -4360,7 +4352,7 @@ cmdInterfaceEdit (vshControl *ctl, const vshCmd *cmd) if (STREQ (doc, doc_edited)) { vshPrint (ctl, _("Interface %s XML configuration not changed.\n"), virInterfaceGetName (iface)); - ret = TRUE; + ret = true; goto cleanup; } @@ -4387,7 +4379,7 @@ cmdInterfaceEdit (vshControl *ctl, const vshCmd *cmd) vshPrint (ctl, _("Interface %s XML configuration edited.\n"), virInterfaceGetName(iface)); - ret = TRUE; + ret = true; cleanup: if (iface) @@ -4420,7 +4412,7 @@ static const vshCmdOptDef opts_network_list[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNetworkList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { int inactive = vshCommandOptBool(cmd, "inactive"); @@ -4431,13 +4423,13 @@ cmdNetworkList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) inactive |= all; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (active) { maxactive = virConnectNumOfNetworks(ctl->conn); if (maxactive < 0) { vshError(ctl, "%s", _("Failed to list active networks")); - return FALSE; + return false; } if (maxactive) { activeNames = vshMalloc(ctl, sizeof(char *) * maxactive); @@ -4446,7 +4438,7 @@ cmdNetworkList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) maxactive)) < 0) { vshError(ctl, "%s", _("Failed to list active networks")); VIR_FREE(activeNames); - return FALSE; + return false; } qsort(&activeNames[0], maxactive, sizeof(char *), namesorter); @@ -4457,7 +4449,7 @@ cmdNetworkList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) if (maxinactive < 0) { vshError(ctl, "%s", _("Failed to list inactive networks")); VIR_FREE(activeNames); - return FALSE; + return false; } if (maxinactive) { inactiveNames = vshMalloc(ctl, sizeof(char *) * maxinactive); @@ -4468,7 +4460,7 @@ cmdNetworkList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) vshError(ctl, "%s", _("Failed to list inactive networks")); VIR_FREE(activeNames); VIR_FREE(inactiveNames); - return FALSE; + return false; } qsort(&inactiveNames[0], maxinactive, sizeof(char*), namesorter); @@ -4528,7 +4520,7 @@ cmdNetworkList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } VIR_FREE(activeNames); VIR_FREE(inactiveNames); - return TRUE; + return true; } @@ -4546,20 +4538,20 @@ static const vshCmdOptDef opts_network_name[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNetworkName(vshControl *ctl, const vshCmd *cmd) { virNetworkPtr network; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL, VSH_BYUUID))) - return FALSE; + return false; vshPrint(ctl, "%s\n", virNetworkGetName(network)); virNetworkFree(network); - return TRUE; + return true; } @@ -4577,17 +4569,17 @@ static const vshCmdOptDef opts_network_start[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNetworkStart(vshControl *ctl, const vshCmd *cmd) { virNetworkPtr network; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL, VSH_BYNAME))) - return FALSE; + return false; if (virNetworkCreate(network) == 0) { vshPrint(ctl, _("Network %s started\n"), @@ -4595,7 +4587,7 @@ cmdNetworkStart(vshControl *ctl, const vshCmd *cmd) } else { vshError(ctl, _("Failed to start network %s"), virNetworkGetName(network)); - ret = FALSE; + ret = false; } virNetworkFree(network); return ret; @@ -4616,24 +4608,24 @@ static const vshCmdOptDef opts_network_undefine[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNetworkUndefine(vshControl *ctl, const vshCmd *cmd) { virNetworkPtr network; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(network = vshCommandOptNetwork(ctl, cmd, &name))) - return FALSE; + return false; if (virNetworkUndefine(network) == 0) { vshPrint(ctl, _("Network %s has been undefined\n"), name); } else { vshError(ctl, _("Failed to undefine network %s"), name); - ret = FALSE; + ret = false; } virNetworkFree(network); @@ -4655,18 +4647,18 @@ static const vshCmdOptDef opts_network_uuid[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNetworkUuid(vshControl *ctl, const vshCmd *cmd) { virNetworkPtr network; char uuid[VIR_UUID_STRING_BUFLEN]; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL, VSH_BYNAME))) - return FALSE; + return false; if (virNetworkGetUUIDString(network, uuid) != -1) vshPrint(ctl, "%s\n", uuid); @@ -4674,7 +4666,7 @@ cmdNetworkUuid(vshControl *ctl, const vshCmd *cmd) vshError(ctl, "%s", _("failed to get network UUID")); virNetworkFree(network); - return TRUE; + return true; } @@ -4693,7 +4685,7 @@ static const vshCmdOptDef opts_interface_list[] = { {"all", VSH_OT_BOOL, 0, N_("list inactive & active interfaces")}, {NULL, 0, 0, NULL} }; -static int +static bool cmdInterfaceList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { int inactive = vshCommandOptBool(cmd, "inactive"); @@ -4704,13 +4696,13 @@ cmdInterfaceList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) inactive |= all; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (active) { maxactive = virConnectNumOfInterfaces(ctl->conn); if (maxactive < 0) { vshError(ctl, "%s", _("Failed to list active interfaces")); - return FALSE; + return false; } if (maxactive) { activeNames = vshMalloc(ctl, sizeof(char *) * maxactive); @@ -4719,7 +4711,7 @@ cmdInterfaceList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) maxactive)) < 0) { vshError(ctl, "%s", _("Failed to list active interfaces")); VIR_FREE(activeNames); - return FALSE; + return false; } qsort(&activeNames[0], maxactive, sizeof(char *), namesorter); @@ -4730,7 +4722,7 @@ cmdInterfaceList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) if (maxinactive < 0) { vshError(ctl, "%s", _("Failed to list inactive interfaces")); VIR_FREE(activeNames); - return FALSE; + return false; } if (maxinactive) { inactiveNames = vshMalloc(ctl, sizeof(char *) * maxinactive); @@ -4741,7 +4733,7 @@ cmdInterfaceList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) vshError(ctl, "%s", _("Failed to list inactive interfaces")); VIR_FREE(activeNames); VIR_FREE(inactiveNames); - return FALSE; + return false; } qsort(&inactiveNames[0], maxinactive, sizeof(char*), namesorter); @@ -4787,7 +4779,7 @@ cmdInterfaceList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } VIR_FREE(activeNames); VIR_FREE(inactiveNames); - return TRUE; + return true; } @@ -4805,20 +4797,20 @@ static const vshCmdOptDef opts_interface_name[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdInterfaceName(vshControl *ctl, const vshCmd *cmd) { virInterfacePtr iface; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL, VSH_BYMAC))) - return FALSE; + return false; vshPrint(ctl, "%s\n", virInterfaceGetName(iface)); virInterfaceFree(iface); - return TRUE; + return true; } /* @@ -4835,20 +4827,20 @@ static const vshCmdOptDef opts_interface_mac[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdInterfaceMAC(vshControl *ctl, const vshCmd *cmd) { virInterfacePtr iface; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL, VSH_BYNAME))) - return FALSE; + return false; vshPrint(ctl, "%s\n", virInterfaceGetMACString(iface)); virInterfaceFree(iface); - return TRUE; + return true; } /* @@ -4866,11 +4858,11 @@ static const vshCmdOptDef opts_interface_dumpxml[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdInterfaceDumpXML(vshControl *ctl, const vshCmd *cmd) { virInterfacePtr iface; - int ret = TRUE; + bool ret = true; char *dump; int flags = 0; int inactive = vshCommandOptBool(cmd, "inactive"); @@ -4879,17 +4871,17 @@ cmdInterfaceDumpXML(vshControl *ctl, const vshCmd *cmd) flags |= VIR_INTERFACE_XML_INACTIVE; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(iface = vshCommandOptInterface(ctl, cmd, NULL))) - return FALSE; + return false; dump = virInterfaceGetXMLDesc(iface, flags); if (dump != NULL) { vshPrint(ctl, "%s", dump); VIR_FREE(dump); } else { - ret = FALSE; + ret = false; } virInterfaceFree(iface); @@ -4910,22 +4902,22 @@ static const vshCmdOptDef opts_interface_define[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdInterfaceDefine(vshControl *ctl, const vshCmd *cmd) { virInterfacePtr iface; const char *from = NULL; - int ret = TRUE; + bool ret = true; char *buffer; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return FALSE; + return false; iface = virInterfaceDefineXML(ctl->conn, buffer, 0); VIR_FREE(buffer); @@ -4936,7 +4928,7 @@ cmdInterfaceDefine(vshControl *ctl, const vshCmd *cmd) virInterfaceFree (iface); } else { vshError(ctl, _("Failed to define interface from %s"), from); - ret = FALSE; + ret = false; } return ret; } @@ -4955,24 +4947,24 @@ static const vshCmdOptDef opts_interface_undefine[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdInterfaceUndefine(vshControl *ctl, const vshCmd *cmd) { virInterfacePtr iface; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(iface = vshCommandOptInterface(ctl, cmd, &name))) - return FALSE; + return false; if (virInterfaceUndefine(iface) == 0) { vshPrint(ctl, _("Interface %s undefined\n"), name); } else { vshError(ctl, _("Failed to undefine interface %s"), name); - ret = FALSE; + ret = false; } virInterfaceFree(iface); @@ -4993,24 +4985,24 @@ static const vshCmdOptDef opts_interface_start[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdInterfaceStart(vshControl *ctl, const vshCmd *cmd) { virInterfacePtr iface; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(iface = vshCommandOptInterface(ctl, cmd, &name))) - return FALSE; + return false; if (virInterfaceCreate(iface, 0) == 0) { vshPrint(ctl, _("Interface %s started\n"), name); } else { vshError(ctl, _("Failed to start interface %s"), name); - ret = FALSE; + ret = false; } virInterfaceFree(iface); @@ -5031,24 +5023,24 @@ static const vshCmdOptDef opts_interface_destroy[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdInterfaceDestroy(vshControl *ctl, const vshCmd *cmd) { virInterfacePtr iface; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(iface = vshCommandOptInterface(ctl, cmd, &name))) - return FALSE; + return false; if (virInterfaceDestroy(iface, 0) == 0) { vshPrint(ctl, _("Interface %s destroyed\n"), name); } else { vshError(ctl, _("Failed to destroy interface %s"), name); - ret = FALSE; + ret = false; } virInterfaceFree(iface); @@ -5070,22 +5062,22 @@ static const vshCmdOptDef opts_nwfilter_define[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNWFilterDefine(vshControl *ctl, const vshCmd *cmd) { virNWFilterPtr nwfilter; const char *from = NULL; - int ret = TRUE; + bool ret = true; char *buffer; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return FALSE; + return false; nwfilter = virNWFilterDefineXML(ctl->conn, buffer); VIR_FREE(buffer); @@ -5096,7 +5088,7 @@ cmdNWFilterDefine(vshControl *ctl, const vshCmd *cmd) virNWFilterFree(nwfilter); } else { vshError(ctl, _("Failed to define network filter from %s"), from); - ret = FALSE; + ret = false; } return ret; } @@ -5116,24 +5108,24 @@ static const vshCmdOptDef opts_nwfilter_undefine[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNWFilterUndefine(vshControl *ctl, const vshCmd *cmd) { virNWFilterPtr nwfilter; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(nwfilter = vshCommandOptNWFilter(ctl, cmd, &name))) - return FALSE; + return false; if (virNWFilterUndefine(nwfilter) == 0) { vshPrint(ctl, _("Network filter %s undefined\n"), name); } else { vshError(ctl, _("Failed to undefine network filter %s"), name); - ret = FALSE; + ret = false; } virNWFilterFree(nwfilter); @@ -5155,25 +5147,25 @@ static const vshCmdOptDef opts_nwfilter_dumpxml[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNWFilterDumpXML(vshControl *ctl, const vshCmd *cmd) { virNWFilterPtr nwfilter; - int ret = TRUE; + bool ret = true; char *dump; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(nwfilter = vshCommandOptNWFilter(ctl, cmd, NULL))) - return FALSE; + return false; dump = virNWFilterGetXMLDesc(nwfilter, 0); if (dump != NULL) { vshPrint(ctl, "%s", dump); VIR_FREE(dump); } else { - ret = FALSE; + ret = false; } virNWFilterFree(nwfilter); @@ -5193,7 +5185,7 @@ static const vshCmdOptDef opts_nwfilter_list[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNWFilterList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { int numfilters, i; @@ -5201,12 +5193,12 @@ cmdNWFilterList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) char uuid[VIR_UUID_STRING_BUFLEN]; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; numfilters = virConnectNumOfNWFilters(ctl->conn); if (numfilters < 0) { vshError(ctl, "%s", _("Failed to list network filters")); - return FALSE; + return false; } names = vshMalloc(ctl, sizeof(char *) * numfilters); @@ -5215,7 +5207,7 @@ cmdNWFilterList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) numfilters)) < 0) { vshError(ctl, "%s", _("Failed to list network filters")); VIR_FREE(names); - return FALSE; + return false; } qsort(&names[0], numfilters, sizeof(char *), namesorter); @@ -5243,7 +5235,7 @@ cmdNWFilterList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } VIR_FREE(names); - return TRUE; + return true; } @@ -5261,10 +5253,10 @@ static const vshCmdOptDef opts_nwfilter_edit[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNWFilterEdit (vshControl *ctl, const vshCmd *cmd) { - int ret = FALSE; + bool ret = false; virNWFilterPtr nwfilter = NULL; char *tmp = NULL; char *doc = NULL; @@ -5298,7 +5290,7 @@ cmdNWFilterEdit (vshControl *ctl, const vshCmd *cmd) if (STREQ (doc, doc_edited)) { vshPrint (ctl, _("Network filter %s XML configuration not changed.\n"), virNWFilterGetName (nwfilter)); - ret = TRUE; + ret = true; goto cleanup; } @@ -5325,7 +5317,7 @@ cmdNWFilterEdit (vshControl *ctl, const vshCmd *cmd) vshPrint (ctl, _("Network filter %s XML configuration edited.\n"), virNWFilterGetName(nwfilter)); - ret = TRUE; + ret = true; cleanup: if (nwfilter) @@ -5361,7 +5353,7 @@ static const vshCmdOptDef opts_pool_autostart[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolAutostart(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; @@ -5369,10 +5361,10 @@ cmdPoolAutostart(vshControl *ctl, const vshCmd *cmd) int autostart; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) - return FALSE; + return false; autostart = !vshCommandOptBool(cmd, "disable"); @@ -5382,7 +5374,7 @@ cmdPoolAutostart(vshControl *ctl, const vshCmd *cmd) else vshError(ctl, _("failed to unmark pool %s as autostarted"), name); virStoragePoolFree(pool); - return FALSE; + return false; } if (autostart) @@ -5391,7 +5383,7 @@ cmdPoolAutostart(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, _("Pool %s unmarked as autostarted\n"), name); virStoragePoolFree(pool); - return TRUE; + return true; } /* @@ -5409,22 +5401,22 @@ static const vshCmdOptDef opts_pool_create[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolCreate(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; const char *from = NULL; - int ret = TRUE; + bool ret = true; char *buffer; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return FALSE; + return false; pool = virStoragePoolCreateXML(ctl->conn, buffer, 0); VIR_FREE(buffer); @@ -5435,7 +5427,7 @@ cmdPoolCreate(vshControl *ctl, const vshCmd *cmd) virStoragePoolFree(pool); } else { vshError(ctl, _("Failed to create pool from %s"), from); - ret = FALSE; + ret = false; } return ret; } @@ -5459,22 +5451,22 @@ static const vshCmdOptDef opts_node_device_create[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNodeDeviceCreate(vshControl *ctl, const vshCmd *cmd) { virNodeDevicePtr dev = NULL; const char *from = NULL; - int ret = TRUE; + bool ret = true; char *buffer; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return FALSE; + return false; dev = virNodeDeviceCreateXML(ctl->conn, buffer, 0); VIR_FREE(buffer); @@ -5485,7 +5477,7 @@ cmdNodeDeviceCreate(vshControl *ctl, const vshCmd *cmd) virNodeDeviceFree(dev); } else { vshError(ctl, _("Failed to create node device from %s"), from); - ret = FALSE; + ret = false; } return ret; @@ -5508,19 +5500,19 @@ static const vshCmdOptDef opts_node_device_destroy[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNodeDeviceDestroy(vshControl *ctl, const vshCmd *cmd) { virNodeDevicePtr dev = NULL; - int ret = TRUE; + bool ret = true; const char *name = NULL; if (!vshConnectionUsability(ctl, ctl->conn)) { - return FALSE; + return false; } if (vshCommandOptString(cmd, "name", &name) <= 0) - return FALSE; + return false; dev = virNodeDeviceLookupByName(ctl->conn, name); @@ -5528,7 +5520,7 @@ cmdNodeDeviceDestroy(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, _("Destroyed node device '%s'\n"), name); } else { vshError(ctl, _("Failed to destroy node device '%s'"), name); - ret = FALSE; + ret = false; } virNodeDeviceFree(dev); @@ -5600,16 +5592,16 @@ static int buildPoolXML(const vshCmd *cmd, const char **retname, char **xml) { if (virBufferError(&buf)) { vshPrint(ctl, "%s", _("Failed to allocate XML buffer")); - return FALSE; + return false; } *xml = virBufferContentAndReset(&buf); *retname = name; - return TRUE; + return true; cleanup: virBufferFreeAndReset(&buf); - return FALSE; + return false; } /* @@ -5621,7 +5613,7 @@ static const vshCmdInfo info_pool_create_as[] = { {NULL, NULL} }; -static int +static bool cmdPoolCreateAs(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; @@ -5630,10 +5622,10 @@ cmdPoolCreateAs(vshControl *ctl, const vshCmd *cmd) int printXML = vshCommandOptBool(cmd, "print-xml"); if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!buildPoolXML(cmd, &name, &xml)) - return FALSE; + return false; if (printXML) { vshPrint(ctl, "%s", xml); @@ -5647,10 +5639,10 @@ cmdPoolCreateAs(vshControl *ctl, const vshCmd *cmd) virStoragePoolFree(pool); } else { vshError(ctl, _("Failed to create pool %s"), name); - return FALSE; + return false; } } - return TRUE; + return true; } @@ -5668,22 +5660,22 @@ static const vshCmdOptDef opts_pool_define[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolDefine(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; const char *from = NULL; - int ret = TRUE; + bool ret = true; char *buffer; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return FALSE; + return false; pool = virStoragePoolDefineXML(ctl->conn, buffer, 0); VIR_FREE(buffer); @@ -5694,7 +5686,7 @@ cmdPoolDefine(vshControl *ctl, const vshCmd *cmd) virStoragePoolFree(pool); } else { vshError(ctl, _("Failed to define pool from %s"), from); - ret = FALSE; + ret = false; } return ret; } @@ -5709,7 +5701,7 @@ static const vshCmdInfo info_pool_define_as[] = { {NULL, NULL} }; -static int +static bool cmdPoolDefineAs(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; @@ -5718,10 +5710,10 @@ cmdPoolDefineAs(vshControl *ctl, const vshCmd *cmd) int printXML = vshCommandOptBool(cmd, "print-xml"); if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!buildPoolXML(cmd, &name, &xml)) - return FALSE; + return false; if (printXML) { vshPrint(ctl, "%s", xml); @@ -5735,10 +5727,10 @@ cmdPoolDefineAs(vshControl *ctl, const vshCmd *cmd) virStoragePoolFree(pool); } else { vshError(ctl, _("Failed to define pool %s"), name); - return FALSE; + return false; } } - return TRUE; + return true; } @@ -5756,24 +5748,24 @@ static const vshCmdOptDef opts_pool_build[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolBuild(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) - return FALSE; + return false; if (virStoragePoolBuild(pool, 0) == 0) { vshPrint(ctl, _("Pool %s built\n"), name); } else { vshError(ctl, _("Failed to build pool %s"), name); - ret = FALSE; + ret = false; } virStoragePoolFree(pool); @@ -5796,24 +5788,24 @@ static const vshCmdOptDef opts_pool_destroy[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolDestroy(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) - return FALSE; + return false; if (virStoragePoolDestroy(pool) == 0) { vshPrint(ctl, _("Pool %s destroyed\n"), name); } else { vshError(ctl, _("Failed to destroy pool %s"), name); - ret = FALSE; + ret = false; } virStoragePoolFree(pool); @@ -5835,24 +5827,24 @@ static const vshCmdOptDef opts_pool_delete[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolDelete(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) - return FALSE; + return false; if (virStoragePoolDelete(pool, 0) == 0) { vshPrint(ctl, _("Pool %s deleted\n"), name); } else { vshError(ctl, _("Failed to delete pool %s"), name); - ret = FALSE; + ret = false; } virStoragePoolFree(pool); @@ -5874,24 +5866,24 @@ static const vshCmdOptDef opts_pool_refresh[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolRefresh(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) - return FALSE; + return false; if (virStoragePoolRefresh(pool, 0) == 0) { vshPrint(ctl, _("Pool %s refreshed\n"), name); } else { vshError(ctl, _("Failed to refresh pool %s"), name); - ret = FALSE; + ret = false; } virStoragePoolFree(pool); @@ -5913,25 +5905,25 @@ static const vshCmdOptDef opts_pool_dumpxml[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolDumpXML(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; - int ret = TRUE; + bool ret = true; char *dump; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL))) - return FALSE; + return false; dump = virStoragePoolGetXMLDesc(pool, 0); if (dump != NULL) { vshPrint(ctl, "%s", dump); VIR_FREE(dump); } else { - ret = FALSE; + ret = false; } virStoragePoolFree(pool); @@ -5955,7 +5947,7 @@ static const vshCmdOptDef opts_pool_list[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { virStoragePoolInfo info; @@ -5985,14 +5977,14 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) /* Check the connection to libvirtd daemon is still working */ if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; /* Retrieve the number of active storage pools */ if (active) { numActivePools = virConnectNumOfStoragePools(ctl->conn); if (numActivePools < 0) { vshError(ctl, "%s", _("Failed to list active pools")); - return FALSE; + return false; } } @@ -6001,7 +5993,7 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) numInactivePools = virConnectNumOfDefinedStoragePools(ctl->conn); if (numInactivePools < 0) { vshError(ctl, "%s", _("Failed to list inactive pools")); - return FALSE; + return false; } } @@ -6020,7 +6012,7 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) vshError(ctl, "%s", _("Failed to list active pools")); VIR_FREE(poolInfoTexts); VIR_FREE(poolNames); - return FALSE; + return false; } } @@ -6032,7 +6024,7 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) vshError(ctl, "%s", _("Failed to list inactive pools")); VIR_FREE(poolInfoTexts); VIR_FREE(poolNames); - return FALSE; + return false; } } @@ -6210,7 +6202,7 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } /* Cleanup and return */ - functionReturn = TRUE; + functionReturn = true; goto cleanup; } @@ -6308,7 +6300,7 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } /* Cleanup and return */ - functionReturn = TRUE; + functionReturn = true; goto cleanup; asprintf_failure: @@ -6323,7 +6315,7 @@ asprintf_failure: /* Some other error */ vshError(ctl, _("virAsprintf failed (errno %d)"), errno); } - functionReturn = FALSE; + functionReturn = false; cleanup: @@ -6365,7 +6357,7 @@ static const vshCmdOptDef opts_find_storage_pool_sources_as[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolDiscoverSourcesAs(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) { const char *type = NULL, *host = NULL; @@ -6377,11 +6369,11 @@ cmdPoolDiscoverSourcesAs(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) vshCommandOptString(cmd, "host", &host) < 0 || vshCommandOptString(cmd, "initiator", &initiator) < 0) { vshError(ctl,"%s", _("missing argument")); - return FALSE; + return false; } if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (host) { const char *port = NULL; @@ -6390,7 +6382,7 @@ cmdPoolDiscoverSourcesAs(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) if (vshCommandOptString(cmd, "port", &port) < 0) { vshError(ctl, "%s", _("missing argument")); virBufferFreeAndReset(&buf); - return FALSE; + return false; } virBufferAddLit(&buf, "\n"); virBufferVSprintf(&buf, " \n"); if (virBufferError(&buf)) { vshError(ctl, "%s", _("Out of memory")); - return FALSE; + return false; } srcSpec = virBufferContentAndReset(&buf); } @@ -6414,12 +6406,12 @@ cmdPoolDiscoverSourcesAs(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) VIR_FREE(srcSpec); if (srcList == NULL) { vshError(ctl, _("Failed to find any %s pool sources"), type); - return FALSE; + return false; } vshPrint(ctl, "%s", srcList); VIR_FREE(srcList); - return TRUE; + return true; } @@ -6440,36 +6432,36 @@ static const vshCmdOptDef opts_find_storage_pool_sources[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolDiscoverSources(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) { const char *type = NULL, *srcSpecFile = NULL; char *srcSpec = NULL, *srcList; if (vshCommandOptString(cmd, "type", &type) <= 0) - return FALSE; + return false; if (vshCommandOptString(cmd, "srcSpec", &srcSpecFile) < 0) { vshError(ctl, "%s", _("missing option")); - return FALSE; + return false; } if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (srcSpecFile && virFileReadAll(srcSpecFile, VIRSH_MAX_XML_FILE, &srcSpec) < 0) - return FALSE; + return false; srcList = virConnectFindStoragePoolSources(ctl->conn, type, srcSpec, 0); VIR_FREE(srcSpec); if (srcList == NULL) { vshError(ctl, _("Failed to find any %s pool sources"), type); - return FALSE; + return false; } vshPrint(ctl, "%s", srcList); VIR_FREE(srcList); - return TRUE; + return true; } @@ -6487,21 +6479,21 @@ static const vshCmdOptDef opts_pool_info[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolInfo(vshControl *ctl, const vshCmd *cmd) { virStoragePoolInfo info; virStoragePoolPtr pool; int autostart = 0; int persistent = 0; - int ret = TRUE; + bool ret = true; char uuid[VIR_UUID_STRING_BUFLEN]; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL))) - return FALSE; + return false; vshPrint(ctl, "%-15s %s\n", _("Name:"), virStoragePoolGetName(pool)); @@ -6562,7 +6554,7 @@ cmdPoolInfo(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, "%-15s %2.2lf %s\n", _("Available:"), val, unit); } } else { - ret = FALSE; + ret = false; } virStoragePoolFree(pool); @@ -6584,20 +6576,20 @@ static const vshCmdOptDef opts_pool_name[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolName(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL, VSH_BYUUID))) - return FALSE; + return false; vshPrint(ctl, "%s\n", virStoragePoolGetName(pool)); virStoragePoolFree(pool); - return TRUE; + return true; } @@ -6615,24 +6607,24 @@ static const vshCmdOptDef opts_pool_start[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolStart(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL, VSH_BYNAME))) - return FALSE; + return false; if (virStoragePoolCreate(pool, 0) == 0) { vshPrint(ctl, _("Pool %s started\n"), virStoragePoolGetName(pool)); } else { vshError(ctl, _("Failed to start pool %s"), virStoragePoolGetName(pool)); - ret = FALSE; + ret = false; } virStoragePoolFree(pool); @@ -6688,7 +6680,7 @@ static int cmdVolSize(const char *data, unsigned long long *val) return 0; } -static int +static bool cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; @@ -6700,11 +6692,11 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) virBuffer buf = VIR_BUFFER_INITIALIZER; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL, VSH_BYNAME))) - return FALSE; + return false; if (vshCommandOptString(cmd, "name", &name) <= 0) goto cleanup; @@ -6771,13 +6763,13 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) } if (snapVol == NULL) { vshError(ctl, _("failed to get vol '%s'"), snapshotStrVol); - return FALSE; + return false; } char *snapshotStrVolPath; if ((snapshotStrVolPath = virStorageVolGetPath(snapVol)) == NULL) { virStorageVolFree(snapVol); - return FALSE; + return false; } /* Create XML for the backing store */ @@ -6796,7 +6788,7 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) if (virBufferError(&buf)) { vshPrint(ctl, "%s", _("Failed to allocate XML buffer")); - return FALSE; + return false; } xml = virBufferContentAndReset(&buf); vol = virStorageVolCreateXML(pool, xml, 0); @@ -6806,16 +6798,16 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) if (vol != NULL) { vshPrint(ctl, _("Vol %s created\n"), name); virStorageVolFree(vol); - return TRUE; + return true; } else { vshError(ctl, _("Failed to create vol %s"), name); - return FALSE; + return false; } cleanup: virBufferFreeAndReset(&buf); virStoragePoolFree(pool); - return FALSE; + return false; } @@ -6833,24 +6825,24 @@ static const vshCmdOptDef opts_pool_undefine[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolUndefine(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) - return FALSE; + return false; if (virStoragePoolUndefine(pool) == 0) { vshPrint(ctl, _("Pool %s has been undefined\n"), name); } else { vshError(ctl, _("Failed to undefine pool %s"), name); - ret = FALSE; + ret = false; } virStoragePoolFree(pool); @@ -6872,18 +6864,18 @@ static const vshCmdOptDef opts_pool_uuid[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdPoolUuid(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; char uuid[VIR_UUID_STRING_BUFLEN]; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL, VSH_BYNAME))) - return FALSE; + return false; if (virStoragePoolGetUUIDString(pool, uuid) != -1) vshPrint(ctl, "%s\n", uuid); @@ -6891,7 +6883,7 @@ cmdPoolUuid(vshControl *ctl, const vshCmd *cmd) vshError(ctl, "%s", _("failed to get pool UUID")); virStoragePoolFree(pool); - return TRUE; + return true; } @@ -6910,31 +6902,31 @@ static const vshCmdOptDef opts_vol_create[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVolCreate(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; virStorageVolPtr vol; const char *from = NULL; - int ret = TRUE; + bool ret = true; char *buffer; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL, VSH_BYNAME))) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) { virStoragePoolFree(pool); - return FALSE; + return false; } if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) { virshReportError(ctl); virStoragePoolFree(pool); - return FALSE; + return false; } vol = virStorageVolCreateXML(pool, buffer, 0); @@ -6947,7 +6939,7 @@ cmdVolCreate(vshControl *ctl, const vshCmd *cmd) virStorageVolFree(vol); } else { vshError(ctl, _("Failed to create vol from %s"), from); - ret = FALSE; + ret = false; } return ret; } @@ -6969,13 +6961,13 @@ static const vshCmdOptDef opts_vol_create_from[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVolCreateFrom(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool = NULL; virStorageVolPtr newvol = NULL, inputvol = NULL; const char *from = NULL; - int ret = FALSE; + bool ret = false; char *buffer = NULL; if (!vshConnectionUsability(ctl, ctl->conn)) @@ -7006,7 +6998,7 @@ cmdVolCreateFrom(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - ret = TRUE; + ret = true; cleanup: VIR_FREE(buffer); if (pool) @@ -7066,7 +7058,7 @@ static const vshCmdOptDef opts_vol_clone[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVolClone(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr origpool = NULL; @@ -7074,7 +7066,7 @@ cmdVolClone(vshControl *ctl, const vshCmd *cmd) const char *name = NULL; char *origxml = NULL; xmlChar *newxml = NULL; - int ret = FALSE; + bool ret = false; if (!vshConnectionUsability(ctl, ctl->conn)) goto cleanup; @@ -7112,7 +7104,7 @@ cmdVolClone(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - ret = TRUE; + ret = true; cleanup: VIR_FREE(origxml); @@ -7154,12 +7146,12 @@ cmdVolUploadSource(virStreamPtr st ATTRIBUTE_UNUSED, return saferead(*fd, bytes, nbytes); } -static int +static bool cmdVolUpload (vshControl *ctl, const vshCmd *cmd) { const char *file = NULL; virStorageVolPtr vol = NULL; - int ret = FALSE; + bool ret = false; int fd = -1; virStreamPtr st = NULL; const char *name = NULL; @@ -7170,16 +7162,16 @@ cmdVolUpload (vshControl *ctl, const vshCmd *cmd) if (vshCommandOptULongLong(cmd, "offset", &offset) < 0) { vshError(ctl, _("Unable to parse integer")); - return FALSE; + return false; } if (vshCommandOptULongLong(cmd, "length", &length) < 0) { vshError(ctl, _("Unable to parse integer")); - return FALSE; + return false; } if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) { - return FALSE; + return false; } if (vshCommandOptString(cmd, "file", &file) < 0) { @@ -7214,7 +7206,7 @@ cmdVolUpload (vshControl *ctl, const vshCmd *cmd) goto cleanup; } - ret = TRUE; + ret = true; cleanup: if (vol) @@ -7255,12 +7247,12 @@ cmdVolDownloadSink(virStreamPtr st ATTRIBUTE_UNUSED, return safewrite(*fd, bytes, nbytes); } -static int +static bool cmdVolDownload (vshControl *ctl, const vshCmd *cmd) { const char *file = NULL; virStorageVolPtr vol = NULL; - int ret = FALSE; + bool ret = false; int fd = -1; virStreamPtr st = NULL; const char *name = NULL; @@ -7272,16 +7264,16 @@ cmdVolDownload (vshControl *ctl, const vshCmd *cmd) if (vshCommandOptULongLong(cmd, "offset", &offset) < 0) { vshError(ctl, _("Unable to parse integer")); - return FALSE; + return false; } if (vshCommandOptULongLong(cmd, "length", &length) < 0) { vshError(ctl, _("Unable to parse integer")); - return FALSE; + return false; } if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &file) < 0) { vshError(ctl, _("file must not be empty")); @@ -7319,10 +7311,10 @@ cmdVolDownload (vshControl *ctl, const vshCmd *cmd) goto cleanup; } - ret = TRUE; + ret = true; cleanup: - if (ret == FALSE && created) + if (ret == false && created) unlink(file); if (vol) virStorageVolFree(vol); @@ -7348,25 +7340,25 @@ static const vshCmdOptDef opts_vol_delete[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVolDelete(vshControl *ctl, const vshCmd *cmd) { virStorageVolPtr vol; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) { - return FALSE; + return false; } if (virStorageVolDelete(vol, 0) == 0) { vshPrint(ctl, _("Vol %s deleted\n"), name); } else { vshError(ctl, _("Failed to delete vol %s"), name); - ret = FALSE; + ret = false; } virStorageVolFree(vol); @@ -7389,25 +7381,25 @@ static const vshCmdOptDef opts_vol_wipe[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVolWipe(vshControl *ctl, const vshCmd *cmd) { virStorageVolPtr vol; - int ret = TRUE; + bool ret = true; const char *name; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) { - return FALSE; + return false; } if (virStorageVolWipe(vol, 0) == 0) { vshPrint(ctl, _("Vol %s wiped\n"), name); } else { vshError(ctl, _("Failed to wipe vol %s"), name); - ret = FALSE; + ret = false; } virStorageVolFree(vol); @@ -7430,18 +7422,18 @@ static const vshCmdOptDef opts_vol_info[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVolInfo(vshControl *ctl, const vshCmd *cmd) { virStorageVolInfo info; virStorageVolPtr vol; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) - return FALSE; + return false; vshPrint(ctl, "%-15s %s\n", _("Name:"), virStorageVolGetName(vol)); @@ -7458,7 +7450,7 @@ cmdVolInfo(vshControl *ctl, const vshCmd *cmd) val = prettyCapacity(info.allocation, &unit); vshPrint(ctl, "%-15s %2.2lf %s\n", _("Allocation:"), val, unit); } else { - ret = FALSE; + ret = false; } virStorageVolFree(vol); @@ -7481,25 +7473,25 @@ static const vshCmdOptDef opts_vol_dumpxml[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVolDumpXML(vshControl *ctl, const vshCmd *cmd) { virStorageVolPtr vol; - int ret = TRUE; + bool ret = true; char *dump; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) - return FALSE; + return false; dump = virStorageVolGetXMLDesc(vol, 0); if (dump != NULL) { vshPrint(ctl, "%s", dump); VIR_FREE(dump); } else { - ret = FALSE; + ret = false; } virStorageVolFree(vol); @@ -7522,7 +7514,7 @@ static const vshCmdOptDef opts_vol_list[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { virStorageVolInfo volumeInfo; @@ -7548,11 +7540,11 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) /* Check the connection to libvirtd daemon is still working */ if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; /* Look up the pool information given to us by the user */ if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL))) - return FALSE; + return false; /* Determine the number of volumes in the pool */ numVolumes = virStoragePoolNumOfVolumes(pool); @@ -7560,7 +7552,7 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) if (numVolumes < 0) { vshError(ctl, "%s", _("Failed to list storage volumes")); virStoragePoolFree(pool); - return FALSE; + return false; } /* Retrieve the list of volume names in the pool */ @@ -7571,7 +7563,7 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) vshError(ctl, "%s", _("Failed to list active vols")); VIR_FREE(activeNames); virStoragePoolFree(pool); - return FALSE; + return false; } /* Sort the volume names */ @@ -7679,7 +7671,7 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } /* Cleanup and return */ - functionReturn = TRUE; + functionReturn = true; goto cleanup; } @@ -7750,7 +7742,7 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } /* Cleanup and return */ - functionReturn = TRUE; + functionReturn = true; goto cleanup; asprintf_failure: @@ -7765,7 +7757,7 @@ asprintf_failure: /* Some other error */ vshError(ctl, _("virAsprintf failed (errno %d)"), errno); } - functionReturn = FALSE; + functionReturn = false; cleanup: @@ -7804,21 +7796,21 @@ static const vshCmdOptDef opts_vol_name[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVolName(vshControl *ctl, const vshCmd *cmd) { virStorageVolPtr vol; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", "pool", NULL, VSH_BYUUID))) - return FALSE; + return false; vshPrint(ctl, "%s\n", virStorageVolGetName(vol)); virStorageVolFree(vol); - return TRUE; + return true; } @@ -7837,7 +7829,7 @@ static const vshCmdOptDef opts_vol_pool[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVolPool(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; @@ -7846,12 +7838,12 @@ cmdVolPool(vshControl *ctl, const vshCmd *cmd) /* Check the connection to libvirtd daemon is still working */ if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; /* Use the supplied string to locate the volume */ if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", "pool", NULL, VSH_BYUUID))) { - return FALSE; + return false; } /* Look up the parent storage pool for the volume */ @@ -7859,7 +7851,7 @@ cmdVolPool(vshControl *ctl, const vshCmd *cmd) if (pool == NULL) { vshError(ctl, "%s", _("failed to get parent pool")); virStorageVolFree(vol); - return FALSE; + return false; } /* Return the requested details of the parent storage pool */ @@ -7875,7 +7867,7 @@ cmdVolPool(vshControl *ctl, const vshCmd *cmd) /* Cleanup */ virStorageVolFree(vol); virStoragePoolFree(pool); - return TRUE; + return true; } @@ -7894,20 +7886,20 @@ static const vshCmdOptDef opts_vol_key[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVolKey(vshControl *ctl, const vshCmd *cmd) { virStorageVolPtr vol; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) - return FALSE; + return false; vshPrint(ctl, "%s\n", virStorageVolGetKey(vol)); virStorageVolFree(vol); - return TRUE; + return true; } @@ -7927,22 +7919,22 @@ static const vshCmdOptDef opts_vol_path[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVolPath(vshControl *ctl, const vshCmd *cmd) { virStorageVolPtr vol; const char *name = NULL; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) { - return FALSE; + return false; } vshPrint(ctl, "%s\n", virStorageVolGetPath(vol)); virStorageVolFree(vol); - return TRUE; + return true; } @@ -7960,7 +7952,7 @@ static const vshCmdOptDef opts_secret_define[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSecretDefine(vshControl *ctl, const vshCmd *cmd) { const char *from = NULL; @@ -7969,29 +7961,29 @@ cmdSecretDefine(vshControl *ctl, const vshCmd *cmd) char uuid[VIR_UUID_STRING_BUFLEN]; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return FALSE; + return false; res = virSecretDefineXML(ctl->conn, buffer, 0); VIR_FREE(buffer); if (res == NULL) { vshError(ctl, _("Failed to set attributes from %s"), from); - return FALSE; + return false; } if (virSecretGetUUIDString(res, &(uuid[0])) < 0) { vshError(ctl, "%s", _("Failed to get UUID of created secret")); virSecretFree(res); - return FALSE; + return false; } vshPrint(ctl, _("Secret %s created\n"), uuid); virSecretFree(res); - return TRUE; + return true; } /* @@ -8008,26 +8000,26 @@ static const vshCmdOptDef opts_secret_dumpxml[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSecretDumpXML(vshControl *ctl, const vshCmd *cmd) { virSecretPtr secret; - int ret = FALSE; + bool ret = false; char *xml; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; secret = vshCommandOptSecret(ctl, cmd, NULL); if (secret == NULL) - return FALSE; + return false; xml = virSecretGetXMLDesc(secret, 0); if (xml == NULL) goto cleanup; vshPrint(ctl, "%s", xml); VIR_FREE(xml); - ret = TRUE; + ret = true; cleanup: virSecretFree(secret); @@ -8049,21 +8041,21 @@ static const vshCmdOptDef opts_secret_set_value[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSecretSetValue(vshControl *ctl, const vshCmd *cmd) { virSecretPtr secret; size_t value_size; const char *base64 = NULL; char *value; - int res, ret = FALSE; + int res, ret = false; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; secret = vshCommandOptSecret(ctl, cmd, NULL); if (secret == NULL) - return FALSE; + return false; if (vshCommandOptString(cmd, "base64", &base64) <= 0) goto cleanup; @@ -8074,7 +8066,7 @@ cmdSecretSetValue(vshControl *ctl, const vshCmd *cmd) } if (value == NULL) { vshError(ctl, "%s", _("Failed to allocate memory")); - return FALSE; + return false; } res = virSecretSetValue(secret, (unsigned char *)value, value_size, 0); @@ -8086,7 +8078,7 @@ cmdSecretSetValue(vshControl *ctl, const vshCmd *cmd) goto cleanup; } vshPrint(ctl, "%s", _("Secret value set\n")); - ret = TRUE; + ret = true; cleanup: virSecretFree(secret); @@ -8107,21 +8099,21 @@ static const vshCmdOptDef opts_secret_get_value[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSecretGetValue(vshControl *ctl, const vshCmd *cmd) { virSecretPtr secret; char *base64; unsigned char *value; size_t value_size; - int ret = FALSE; + bool ret = false; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; secret = vshCommandOptSecret(ctl, cmd, NULL); if (secret == NULL) - return FALSE; + return false; value = virSecretGetValue(secret, &value_size, 0); if (value == NULL) @@ -8138,7 +8130,7 @@ cmdSecretGetValue(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, "%s", base64); memset(base64, 0, strlen(base64)); VIR_FREE(base64); - ret = TRUE; + ret = true; cleanup: virSecretFree(secret); @@ -8159,26 +8151,26 @@ static const vshCmdOptDef opts_secret_undefine[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSecretUndefine(vshControl *ctl, const vshCmd *cmd) { virSecretPtr secret; - int ret = FALSE; + bool ret = false; const char *uuid; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; secret = vshCommandOptSecret(ctl, cmd, &uuid); if (secret == NULL) - return FALSE; + return false; if (virSecretUndefine(secret) < 0) { vshError(ctl, _("Failed to delete secret %s"), uuid); goto cleanup; } vshPrint(ctl, _("Secret %s deleted\n"), uuid); - ret = TRUE; + ret = true; cleanup: virSecretFree(secret); @@ -8194,19 +8186,19 @@ static const vshCmdInfo info_secret_list[] = { {NULL, NULL} }; -static int +static bool cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { int maxuuids = 0, i; char **uuids = NULL; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; maxuuids = virConnectNumOfSecrets(ctl->conn); if (maxuuids < 0) { vshError(ctl, "%s", _("Failed to list secrets")); - return FALSE; + return false; } uuids = vshMalloc(ctl, sizeof(*uuids) * maxuuids); @@ -8214,7 +8206,7 @@ cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) if (maxuuids < 0) { vshError(ctl, "%s", _("Failed to list secrets")); VIR_FREE(uuids); - return FALSE; + return false; } qsort(uuids, maxuuids, sizeof(char *), namesorter); @@ -8249,7 +8241,7 @@ cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) VIR_FREE(uuids[i]); } VIR_FREE(uuids); - return TRUE; + return true; } @@ -8263,7 +8255,7 @@ static const vshCmdInfo info_version[] = { }; -static int +static bool cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { unsigned long hvVersion; @@ -8277,12 +8269,12 @@ cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) unsigned int rel; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; hvType = virConnectGetType(ctl->conn); if (hvType == NULL) { vshError(ctl, "%s", _("failed to get hypervisor type")); - return FALSE; + return false; } includeVersion = LIBVIR_VERSION_NUMBER; @@ -8296,7 +8288,7 @@ cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) ret = virGetVersion(&libVersion, hvType, &apiVersion); if (ret < 0) { vshError(ctl, "%s", _("failed to get the library version")); - return FALSE; + return false; } major = libVersion / 1000000; libVersion %= 1000000; @@ -8315,7 +8307,7 @@ cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) ret = virConnectGetVersion(ctl->conn, &hvVersion); if (ret < 0) { vshError(ctl, "%s", _("failed to get the hypervisor version")); - return FALSE; + return false; } if (hvVersion == 0) { vshPrint(ctl, @@ -8329,7 +8321,7 @@ cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) vshPrint(ctl, _("Running hypervisor: %s %d.%d.%d\n"), hvType, major, minor, rel); } - return TRUE; + return true; } /* @@ -8427,7 +8419,7 @@ cmdNodeListDevicesPrint(vshControl *ctl, } } -static int +static bool cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { const char *cap = NULL; @@ -8436,7 +8428,7 @@ cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) int tree = vshCommandOptBool(cmd, "tree"); if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "cap", &cap) <= 0) cap = NULL; @@ -8444,9 +8436,9 @@ cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) num_devices = virNodeNumOfDevices(ctl->conn, cap, 0); if (num_devices < 0) { vshError(ctl, "%s", _("Failed to count node devices")); - return FALSE; + return false; } else if (num_devices == 0) { - return TRUE; + return true; } devices = vshMalloc(ctl, sizeof(char *) * num_devices); @@ -8455,7 +8447,7 @@ cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) if (num_devices < 0) { vshError(ctl, "%s", _("Failed to list node devices")); VIR_FREE(devices); - return FALSE; + return false; } qsort(&devices[0], num_devices, sizeof(char*), namesorter); if (tree) { @@ -8496,7 +8488,7 @@ cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } } VIR_FREE(devices); - return TRUE; + return true; } /* @@ -8514,7 +8506,7 @@ static const vshCmdOptDef opts_node_device_dumpxml[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNodeDeviceDumpXML (vshControl *ctl, const vshCmd *cmd) { const char *name = NULL; @@ -8522,24 +8514,24 @@ cmdNodeDeviceDumpXML (vshControl *ctl, const vshCmd *cmd) char *xml; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "device", &name) <= 0) - return FALSE; + return false; if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) { vshError(ctl, "%s '%s'", _("Could not find matching device"), name); - return FALSE; + return false; } xml = virNodeDeviceGetXMLDesc(device, 0); if (!xml) { virNodeDeviceFree(device); - return FALSE; + return false; } vshPrint(ctl, "%s\n", xml); VIR_FREE(xml); virNodeDeviceFree(device); - return TRUE; + return true; } /* @@ -8557,27 +8549,27 @@ static const vshCmdOptDef opts_node_device_dettach[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNodeDeviceDettach (vshControl *ctl, const vshCmd *cmd) { const char *name = NULL; virNodeDevicePtr device; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "device", &name) <= 0) - return FALSE; + return false; if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) { vshError(ctl, "%s '%s'", _("Could not find matching device"), name); - return FALSE; + return false; } if (virNodeDeviceDettach(device) == 0) { vshPrint(ctl, _("Device %s dettached\n"), name); } else { vshError(ctl, _("Failed to dettach device %s"), name); - ret = FALSE; + ret = false; } virNodeDeviceFree(device); return ret; @@ -8598,27 +8590,27 @@ static const vshCmdOptDef opts_node_device_reattach[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNodeDeviceReAttach (vshControl *ctl, const vshCmd *cmd) { const char *name = NULL; virNodeDevicePtr device; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "device", &name) <= 0) - return FALSE; + return false; if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) { vshError(ctl, "%s '%s'", _("Could not find matching device"), name); - return FALSE; + return false; } if (virNodeDeviceReAttach(device) == 0) { vshPrint(ctl, _("Device %s re-attached\n"), name); } else { vshError(ctl, _("Failed to re-attach device %s"), name); - ret = FALSE; + ret = false; } virNodeDeviceFree(device); return ret; @@ -8639,27 +8631,27 @@ static const vshCmdOptDef opts_node_device_reset[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdNodeDeviceReset (vshControl *ctl, const vshCmd *cmd) { const char *name = NULL; virNodeDevicePtr device; - int ret = TRUE; + bool ret = true; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "device", &name) <= 0) - return FALSE; + return false; if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) { vshError(ctl, "%s '%s'", _("Could not find matching device"), name); - return FALSE; + return false; } if (virNodeDeviceReset(device) == 0) { vshPrint(ctl, _("Device %s reset\n"), name); } else { vshError(ctl, _("Failed to reset device %s"), name); - ret = FALSE; + ret = false; } virNodeDeviceFree(device); return ret; @@ -8674,24 +8666,24 @@ static const vshCmdInfo info_hostname[] = { {NULL, NULL} }; -static int +static bool cmdHostname (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { char *hostname; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; hostname = virConnectGetHostname (ctl->conn); if (hostname == NULL) { vshError(ctl, "%s", _("failed to get hostname")); - return FALSE; + return false; } vshPrint (ctl, "%s\n", hostname); VIR_FREE(hostname); - return TRUE; + return true; } /* @@ -8703,24 +8695,24 @@ static const vshCmdInfo info_uri[] = { {NULL, NULL} }; -static int +static bool cmdURI (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { char *uri; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; uri = virConnectGetURI (ctl->conn); if (uri == NULL) { vshError(ctl, "%s", _("failed to get URI")); - return FALSE; + return false; } vshPrint (ctl, "%s\n", uri); VIR_FREE(uri); - return TRUE; + return true; } /* @@ -8733,24 +8725,24 @@ static const vshCmdInfo info_sysinfo[] = { {NULL, NULL} }; -static int +static bool cmdSysinfo (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { char *sysinfo; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; sysinfo = virConnectGetSysinfo (ctl->conn, 0); if (sysinfo == NULL) { vshError(ctl, "%s", _("failed to get sysinfo")); - return FALSE; + return false; } vshPrint (ctl, "%s", sysinfo); VIR_FREE(sysinfo); - return TRUE; + return true; } /* @@ -8767,22 +8759,22 @@ static const vshCmdOptDef opts_vncdisplay[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdVNCDisplay(vshControl *ctl, const vshCmd *cmd) { xmlDocPtr xml = NULL; xmlXPathObjectPtr obj = NULL; xmlXPathContextPtr ctxt = NULL; virDomainPtr dom; - int ret = FALSE; + bool ret = false; int port = 0; char *doc; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; doc = virDomainGetXMLDesc(dom, 0); if (!doc) @@ -8817,7 +8809,7 @@ cmdVNCDisplay(vshControl *ctl, const vshCmd *cmd) } xmlXPathFreeObject(obj); obj = NULL; - ret = TRUE; + ret = true; cleanup: xmlXPathFreeObject(obj); @@ -8842,21 +8834,21 @@ static const vshCmdOptDef opts_ttyconsole[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdTTYConsole(vshControl *ctl, const vshCmd *cmd) { xmlDocPtr xml = NULL; xmlXPathObjectPtr obj = NULL; xmlXPathContextPtr ctxt = NULL; virDomainPtr dom; - int ret = FALSE; + bool ret = false; char *doc; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; doc = virDomainGetXMLDesc(dom, 0); if (!doc) @@ -8878,7 +8870,7 @@ cmdTTYConsole(vshControl *ctl, const vshCmd *cmd) goto cleanup; } vshPrint(ctl, "%s\n", (const char *)obj->stringval); - ret = TRUE; + ret = true; cleanup: xmlXPathFreeObject(obj); @@ -8905,30 +8897,30 @@ static const vshCmdOptDef opts_attach_device[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdAttachDevice(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; const char *from = NULL; char *buffer; - int ret = TRUE; + bool ret = true; unsigned int flags; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) { virDomainFree(dom); - return FALSE; + return false; } if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) { virshReportError(ctl); virDomainFree(dom); - return FALSE; + return false; } if (vshCommandOptBool(cmd, "persistent")) { @@ -8944,13 +8936,13 @@ cmdAttachDevice(vshControl *ctl, const vshCmd *cmd) if (ret < 0) { vshError(ctl, _("Failed to attach device from %s"), from); virDomainFree(dom); - return FALSE; + return false; } else { vshPrint(ctl, "%s", _("Device attached successfully\n")); } virDomainFree(dom); - return TRUE; + return true; } @@ -8970,30 +8962,30 @@ static const vshCmdOptDef opts_detach_device[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDetachDevice(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; const char *from = NULL; char *buffer; - int ret = TRUE; + bool ret = true; unsigned int flags; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) { virDomainFree(dom); - return FALSE; + return false; } if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) { virshReportError(ctl); virDomainFree(dom); - return FALSE; + return false; } if (vshCommandOptBool(cmd, "persistent")) { @@ -9009,13 +9001,13 @@ cmdDetachDevice(vshControl *ctl, const vshCmd *cmd) if (ret < 0) { vshError(ctl, _("Failed to detach device from %s"), from); virDomainFree(dom); - return FALSE; + return false; } else { vshPrint(ctl, "%s", _("Device detached successfully\n")); } virDomainFree(dom); - return TRUE; + return true; } @@ -9036,30 +9028,30 @@ static const vshCmdOptDef opts_update_device[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdUpdateDevice(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; const char *from = NULL; char *buffer; - int ret = TRUE; + bool ret = true; unsigned int flags; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) { virDomainFree(dom); - return FALSE; + return false; } if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) { virshReportError(ctl); virDomainFree(dom); - return FALSE; + return false; } if (vshCommandOptBool(cmd, "persistent")) { @@ -9079,13 +9071,13 @@ cmdUpdateDevice(vshControl *ctl, const vshCmd *cmd) if (ret < 0) { vshError(ctl, _("Failed to update device from %s"), from); virDomainFree(dom); - return FALSE; + return false; } else { vshPrint(ctl, "%s", _("Device updated successfully\n")); } virDomainFree(dom); - return TRUE; + return true; } @@ -9110,13 +9102,13 @@ static const vshCmdOptDef opts_attach_interface[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom = NULL; const char *mac = NULL, *target = NULL, *script = NULL, *type = NULL, *source = NULL, *model = NULL; - int typ, ret = FALSE; + int typ, ret = false; unsigned int flags; virBuffer buf = VIR_BUFFER_INITIALIZER; char *xml; @@ -9171,7 +9163,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) if (virBufferError(&buf)) { vshPrint(ctl, "%s", _("Failed to allocate XML buffer")); - return FALSE; + return false; } xml = virBufferContentAndReset(&buf); @@ -9189,10 +9181,10 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) if (ret != 0) { vshError(ctl, "%s", _("Failed to attach interface")); - ret = FALSE; + ret = false; } else { vshPrint(ctl, "%s", _("Interface attached successfully\n")); - ret = TRUE; + ret = true; } cleanup: @@ -9219,7 +9211,7 @@ static const vshCmdOptDef opts_detach_interface[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDetachInterface(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom = NULL; @@ -9231,7 +9223,7 @@ cmdDetachInterface(vshControl *ctl, const vshCmd *cmd) const char *mac =NULL, *type = NULL; char *doc; char buf[64]; - int i = 0, diff_mac, ret = FALSE; + int i = 0, diff_mac, ret = false; unsigned int flags; if (!vshConnectionUsability(ctl, ctl->conn)) @@ -9327,10 +9319,10 @@ cmdDetachInterface(vshControl *ctl, const vshCmd *cmd) if (ret != 0) { vshError(ctl, "%s", _("Failed to detach interface")); - ret = FALSE; + ret = false; } else { vshPrint(ctl, "%s", _("Interface detached successfully\n")); - ret = TRUE; + ret = true; } cleanup: @@ -9367,13 +9359,13 @@ static const vshCmdOptDef opts_attach_disk[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdAttachDisk(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom = NULL; const char *source = NULL, *target = NULL, *driver = NULL, *subdriver = NULL, *type = NULL, *mode = NULL; - int isFile = 0, ret = FALSE; + int isFile = 0, ret = false; unsigned int flags; const char *stype = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -9447,7 +9439,7 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd) if (virBufferError(&buf)) { vshPrint(ctl, "%s", _("Failed to allocate XML buffer")); - return FALSE; + return false; } xml = virBufferContentAndReset(&buf); @@ -9465,10 +9457,10 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd) if (ret != 0) { vshError(ctl, "%s", _("Failed to attach disk")); - ret = FALSE; + ret = false; } else { vshPrint(ctl, "%s", _("Disk attached successfully\n")); - ret = TRUE; + ret = true; } cleanup: @@ -9494,7 +9486,7 @@ static const vshCmdOptDef opts_detach_disk[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDetachDisk(vshControl *ctl, const vshCmd *cmd) { xmlDocPtr xml = NULL; @@ -9505,7 +9497,7 @@ cmdDetachDisk(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom = NULL; const char *target = NULL; char *doc; - int i = 0, diff_tgt, ret = FALSE; + int i = 0, diff_tgt, ret = false; unsigned int flags; if (!vshConnectionUsability(ctl, ctl->conn)) @@ -9586,10 +9578,10 @@ cmdDetachDisk(vshControl *ctl, const vshCmd *cmd) if (ret != 0) { vshError(ctl, "%s", _("Failed to detach disk")); - ret = FALSE; + ret = false; } else { vshPrint(ctl, "%s", _("Disk detached successfully\n")); - ret = TRUE; + ret = true; } cleanup: @@ -9618,22 +9610,22 @@ static const vshCmdOptDef opts_cpu_compare[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdCPUCompare(vshControl *ctl, const vshCmd *cmd) { const char *from = NULL; - int ret = TRUE; + bool ret = true; char *buffer; int result; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return FALSE; + return false; result = virConnectCompareCPU(ctl->conn, buffer, 0); VIR_FREE(buffer); @@ -9642,25 +9634,25 @@ cmdCPUCompare(vshControl *ctl, const vshCmd *cmd) case VIR_CPU_COMPARE_INCOMPATIBLE: vshPrint(ctl, _("CPU described in %s is incompatible with host CPU\n"), from); - ret = FALSE; + ret = false; break; case VIR_CPU_COMPARE_IDENTICAL: vshPrint(ctl, _("CPU described in %s is identical to host CPU\n"), from); - ret = TRUE; + ret = true; break; case VIR_CPU_COMPARE_SUPERSET: vshPrint(ctl, _("Host CPU is a superset of CPU described in %s\n"), from); - ret = TRUE; + ret = true; break; case VIR_CPU_COMPARE_ERROR: default: vshError(ctl, _("Failed to compare host CPU with %s"), from); - ret = FALSE; + ret = false; } return ret; @@ -9680,11 +9672,11 @@ static const vshCmdOptDef opts_cpu_baseline[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) { const char *from = NULL; - int ret = TRUE; + bool ret = true; char *buffer; char *result = NULL; const char **list = NULL; @@ -9698,13 +9690,13 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) int res, i; if (!vshConnectionUsability(ctl, ctl->conn)) - return FALSE; + return false; if (vshCommandOptString(cmd, "file", &from) <= 0) - return FALSE; + return false; if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return FALSE; + return false; doc = xmlNewDoc(NULL); if (doc == NULL) @@ -9714,7 +9706,7 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) (const xmlChar *)buffer, &node_list); if (res != 0) { vshError(ctl, _("Failed to parse XML fragment %s"), from); - ret = FALSE; + ret = false; goto cleanup; } @@ -9751,7 +9743,7 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) if (count == 0) { vshError(ctl, _("No host CPU specified in '%s'"), from); - ret = FALSE; + ret = false; goto cleanup; } @@ -9760,7 +9752,7 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) if (result) vshPrint(ctl, "%s", result); else - ret = FALSE; + ret = false; cleanup: xmlXPathFreeObject(obj); @@ -9778,7 +9770,7 @@ cleanup: no_memory: vshError(ctl, "%s", _("Out of memory")); - ret = FALSE; + ret = false; goto cleanup; } @@ -9909,16 +9901,16 @@ static const vshCmdOptDef opts_cd[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdCd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { const char *dir = NULL; char *dir_malloced = NULL; - int ret = TRUE; + bool ret = true; if (!ctl->imode) { vshError(ctl, "%s", _("cd: command valid only in interactive mode")); - return FALSE; + return false; } if (vshCommandOptString(cmd, "dir", &dir) <= 0) { @@ -9930,7 +9922,7 @@ cmdCd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) if (chdir(dir) == -1) { vshError(ctl, _("cd: %s: %s"), strerror(errno), dir); - ret = FALSE; + ret = false; } VIR_FREE(dir_malloced); @@ -9949,12 +9941,12 @@ static const vshCmdInfo info_pwd[] = { {NULL, NULL} }; -static int +static bool cmdPwd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { char *cwd; size_t path_max; - int err = TRUE; + int err = true; path_max = (size_t) PATH_MAX + 2; cwd = vshMalloc (ctl, path_max); @@ -9997,7 +9989,7 @@ static const vshCmdOptDef opts_echo[] = { /* Exists mainly for debugging virsh, but also handy for adding back * quotes for later evaluation. */ -static int +static bool cmdEcho (vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd) { bool shell = false; @@ -10043,13 +10035,13 @@ cmdEcho (vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd) if (virBufferError(&buf)) { vshPrint(ctl, "%s", _("Failed to allocate XML buffer")); - return FALSE; + return false; } arg = virBufferContentAndReset(&buf); if (arg) vshPrint(ctl, "%s", arg); VIR_FREE(arg); - return TRUE; + return true; } /* @@ -10069,10 +10061,10 @@ static const vshCmdOptDef opts_edit[] = { /* This function also acts as a template to generate cmdNetworkEdit * and cmdPoolEdit functions (below) using a sed script in the Makefile. */ -static int +static bool cmdEdit (vshControl *ctl, const vshCmd *cmd) { - int ret = FALSE; + bool ret = false; virDomainPtr dom = NULL; char *tmp = NULL; char *doc = NULL; @@ -10107,7 +10099,7 @@ cmdEdit (vshControl *ctl, const vshCmd *cmd) if (STREQ (doc, doc_edited)) { vshPrint (ctl, _("Domain %s XML configuration not changed.\n"), virDomainGetName (dom)); - ret = TRUE; + ret = true; goto cleanup; } @@ -10134,7 +10126,7 @@ cmdEdit (vshControl *ctl, const vshCmd *cmd) vshPrint (ctl, _("Domain %s XML configuration edited.\n"), virDomainGetName(dom)); - ret = TRUE; + ret = true; cleanup: if (dom) @@ -10196,11 +10188,11 @@ static const vshCmdInfo info_quit[] = { {NULL, NULL} }; -static int +static bool cmdQuit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { - ctl->imode = FALSE; - return TRUE; + ctl->imode = false; + return true; } /* @@ -10218,11 +10210,11 @@ static const vshCmdOptDef opts_snapshot_create[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSnapshotCreate(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom = NULL; - int ret = FALSE; + bool ret = false; const char *from = NULL; char *buffer = NULL; virDomainSnapshotPtr snapshot = NULL; @@ -10284,7 +10276,7 @@ cmdSnapshotCreate(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, _(" from '%s'"), from); vshPrint(ctl, "\n"); - ret = TRUE; + ret = true; cleanup: VIR_FREE(name); @@ -10315,11 +10307,11 @@ static const vshCmdOptDef opts_snapshot_current[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSnapshotCurrent(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom = NULL; - int ret = FALSE; + bool ret = false; int current; virDomainSnapshotPtr snapshot = NULL; @@ -10347,7 +10339,7 @@ cmdSnapshotCurrent(vshControl *ctl, const vshCmd *cmd) VIR_FREE(xml); } - ret = TRUE; + ret = true; cleanup: if (snapshot) @@ -10372,11 +10364,11 @@ static const vshCmdOptDef opts_snapshot_list[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom = NULL; - int ret = FALSE; + bool ret = false; int numsnaps; char **names = NULL; int actual = 0; @@ -10455,7 +10447,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) } } - ret = TRUE; + ret = true; cleanup: /* this frees up memory from the last iteration of the loop */ @@ -10490,11 +10482,11 @@ static const vshCmdOptDef opts_snapshot_dumpxml[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSnapshotDumpXML(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom = NULL; - int ret = FALSE; + bool ret = false; const char *name = NULL; virDomainSnapshotPtr snapshot = NULL; char *xml = NULL; @@ -10519,7 +10511,7 @@ cmdSnapshotDumpXML(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, "%s", xml); - ret = TRUE; + ret = true; cleanup: VIR_FREE(xml); @@ -10546,11 +10538,11 @@ static const vshCmdOptDef opts_snapshot_revert[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdDomainSnapshotRevert(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom = NULL; - int ret = FALSE; + bool ret = false; const char *name = NULL; virDomainSnapshotPtr snapshot = NULL; @@ -10571,7 +10563,7 @@ cmdDomainSnapshotRevert(vshControl *ctl, const vshCmd *cmd) if (virDomainRevertToSnapshot(snapshot, 0) < 0) goto cleanup; - ret = TRUE; + ret = true; cleanup: if (snapshot) @@ -10598,11 +10590,11 @@ static const vshCmdOptDef opts_snapshot_delete[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdSnapshotDelete(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom = NULL; - int ret = FALSE; + bool ret = false; const char *name = NULL; virDomainSnapshotPtr snapshot = NULL; unsigned int flags = 0; @@ -10627,7 +10619,7 @@ cmdSnapshotDelete(vshControl *ctl, const vshCmd *cmd) if (virDomainSnapshotDelete(snapshot, flags) < 0) goto cleanup; - ret = TRUE; + ret = true; cleanup: if (snapshot) @@ -10654,11 +10646,11 @@ static const vshCmdOptDef opts_qemu_monitor_command[] = { {NULL, 0, 0, NULL} }; -static int +static bool cmdQemuMonitorCommand(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom = NULL; - int ret = FALSE; + bool ret = false; const char *monitor_cmd = NULL; char *result = NULL; unsigned int flags = 0; @@ -10683,7 +10675,7 @@ cmdQemuMonitorCommand(vshControl *ctl, const vshCmd *cmd) printf("%s\n", result); - ret = TRUE; + ret = true; cleanup: VIR_FREE(result); @@ -11071,7 +11063,7 @@ vshCmdGrpHelp(vshControl *ctl, const char *grpname) if (!grp) { vshError(ctl, _("command group '%s' doesn't exist"), grpname); - return FALSE; + return false; } else { vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name, grp->keyword); @@ -11082,7 +11074,7 @@ vshCmdGrpHelp(vshControl *ctl, const char *grpname) } } - return TRUE; + return true; } static int @@ -11092,7 +11084,7 @@ vshCmddefHelp(vshControl *ctl, const char *cmdname) if (!def) { vshError(ctl, _("command '%s' doesn't exist"), cmdname); - return FALSE; + return false; } else { const char *desc = _(vshCmddefGetInfo(def, "desc")); const char *help = _(vshCmddefGetInfo(def, "help")); @@ -11103,7 +11095,7 @@ vshCmddefHelp(vshControl *ctl, const char *cmdname) if (vshCmddefOptParse(def, &opts_need_arg, &opts_required)) { vshError(ctl, _("internal error: bad options in command: '%s'"), def->name); - return FALSE; + return false; } fputs(_(" NAME\n"), stdout); @@ -11183,7 +11175,7 @@ vshCmddefHelp(vshControl *ctl, const char *cmdname) } fputc('\n', stdout); } - return TRUE; + return true; } /* --------------- @@ -11362,12 +11354,12 @@ vshCommandOptULongLong(const vshCmd *cmd, const char *name, /* - * Returns TRUE/FALSE if the option exists + * Returns true/false if the option exists */ -static int +static bool vshCommandOptBool(const vshCmd *cmd, const char *name) { - return vshCommandOpt(cmd, name) ? TRUE : FALSE; + return vshCommandOpt(cmd, name) != NULL; } /* @@ -11698,7 +11690,7 @@ vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name) static int vshCommandRun(vshControl *ctl, const vshCmd *cmd) { - int ret = TRUE; + bool ret = true; while (cmd) { struct timeval before, after; @@ -11715,11 +11707,11 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd) if (enable_timing) GETTIMEOFDAY(&after); - if (ret == FALSE) + if (ret == false) virshReportError(ctl); /* try to automatically catch disconnections */ - if ((ret == FALSE) && + if ((ret == false) && ((disconnected != 0) || ((last_error != NULL) && (((last_error->code == VIR_ERR_SYSTEM_ERROR) && @@ -11915,7 +11907,7 @@ get_data: break; } - return TRUE; + return true; syntaxError: if (ctl->cmd) { @@ -11925,7 +11917,7 @@ get_data: if (first) vshCommandOptFree(first); VIR_FREE(tkdata); - return FALSE; + return false; } /* -------------------- @@ -11951,7 +11943,7 @@ static int vshCommandArgvParse(vshControl *ctl, int nargs, char **argv) vshCommandParser parser; if (nargs <= 0) - return FALSE; + return false; parser.arg_pos = argv; parser.arg_end = argv + nargs; @@ -12029,7 +12021,7 @@ static int vshCommandStringParse(vshControl *ctl, char *cmdstr) vshCommandParser parser; if (cmdstr == NULL || *cmdstr == '\0') - return FALSE; + return false; parser.pos = cmdstr; parser.getNextArg = vshCommandStringGetArg; @@ -12086,9 +12078,9 @@ vshConnectionUsability(vshControl *ctl, virConnectPtr conn) */ if (!conn) { vshError(ctl, "%s", _("no valid connection")); - return FALSE; + return false; } - return TRUE; + return true; } static void @@ -12114,7 +12106,7 @@ vshPrintExtra(vshControl *ctl, const char *format, ...) va_list ap; char *str; - if (ctl && ctl->quiet == TRUE) + if (ctl && ctl->quiet == true) return; va_start(ap, format); @@ -12160,7 +12152,7 @@ static int vshInit(vshControl *ctl) { if (ctl->conn) - return FALSE; + return false; vshOpenLogFile(ctl); @@ -12171,7 +12163,7 @@ vshInit(vshControl *ctl) vshSetupSignals(); if (virEventRegisterDefaultImpl() < 0) - return FALSE; + return false; ctl->conn = virConnectOpenAuth(ctl->name, virConnectAuthPtrDefault, @@ -12185,10 +12177,10 @@ vshInit(vshControl *ctl) if (!ctl->conn) { virshReportError(ctl); vshError(ctl, "%s", _("failed to connect to the hypervisor")); - return FALSE; + return false; } - return TRUE; + return true; } #define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC) @@ -12557,7 +12549,7 @@ vshDeinit(vshControl *ctl) } virResetLastError(); - return TRUE; + return true; } /* @@ -12759,10 +12751,10 @@ vshParseArgv(vshControl *ctl, int argc, char **argv) help = true; break; case 'q': - ctl->quiet = TRUE; + ctl->quiet = true; break; case 't': - ctl->timing = TRUE; + ctl->timing = true; break; case 'c': ctl->name = vshStrdup(ctl, optarg); @@ -12777,7 +12769,7 @@ vshParseArgv(vshControl *ctl, int argc, char **argv) vshShowVersion(ctl); exit(EXIT_SUCCESS); case 'r': - ctl->readonly = TRUE; + ctl->readonly = true; break; case 'l': ctl->logfile = vshStrdup(ctl, optarg); @@ -12801,7 +12793,7 @@ vshParseArgv(vshControl *ctl, int argc, char **argv) if (argc > optind) { /* parse command */ - ctl->imode = FALSE; + ctl->imode = false; if (argc - optind == 1) { vshDebug(ctl, 2, "commands: \"%s\"\n", argv[optind]); return vshCommandStringParse(ctl, argv[optind]); @@ -12809,7 +12801,7 @@ vshParseArgv(vshControl *ctl, int argc, char **argv) return vshCommandArgvParse(ctl, argc - optind, argv + optind); } } - return TRUE; + return true; } int @@ -12817,7 +12809,7 @@ main(int argc, char **argv) { vshControl _ctl, *ctl = &_ctl; char *defaultConn; - int ret = TRUE; + bool ret = true; if (!setlocale(LC_ALL, "")) { perror("setlocale"); @@ -12838,7 +12830,7 @@ main(int argc, char **argv) progname++; memset(ctl, 0, sizeof(vshControl)); - ctl->imode = TRUE; /* default is interactive mode */ + ctl->imode = true; /* default is interactive mode */ ctl->log_fd = -1; /* Initialize log file descriptor */ if ((defaultConn = getenv("VIRSH_DEFAULT_CONNECT_URI"))) { -- 1.7.1 From eblake at redhat.com Mon Apr 18 22:54:25 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 18 Apr 2011 16:54:25 -0600 Subject: [libvirt] [PATCH 6/6] qemu, inject-nmi: Implement the driver methods In-Reply-To: <4DABF8C7.4060804@cn.fujitsu.com> References: <4DA52D1A.1000307@cn.fujitsu.com> <4DA52E3E.10402@cn.fujitsu.com> <4DA88ADE.7050208@redhat.com> <4DABF8C7.4060804@cn.fujitsu.com> Message-ID: <4DACC121.8030108@redhat.com> On 04/18/2011 02:39 AM, Lai Jiangshan wrote: >>> +int qemuMonitorTextInjectNMI(qemuMonitorPtr mon, unsigned int flags ATTRIBUTE_UNUSED) >>> +{ >>> + const char *cmd = "nmi 0"; >>> + char *reply = NULL; >>> + >>> + /* >>> + * FIXME: qemu's nmi command just injects NMI to a specified CPU, >>> + * use "nmi 0" instead temporary. >>> + */ >> >> This bothers me. Is it possible to inject NMI to a particular CPU in >> bare-metal hardware? If so, then we ought to support that in the API. >> > > The real world NMI button just sends NMI to all cpus, the qemu side code will > also be modified that hmp nmi command just sends NMI to all CPU and > the cpu-index parameter will be removed. > > My original qemu side patch lefts cpu-index parameter for kernel debugging, > but the qemu guys persuade me that inject-nmi command should just send NMI > to CPUs. I accepted it. I think the libvirt will handle it at the same way. Makes sense, and matches with what I learned on a google search about the "NMI button" on real hardware. Thus, the real fixme is that qemu's nmi command has a bogus argument during preliminary patch review that will be going away before inject-nmi is made official, and therefore, libvirt should just be sending "nmi" and not "nmi 0" once there is a released version of qemu that actually supports injecting NMI, and you are right that the API should not expose a vcpu parameter. Any timeframe on when a released qemu might support nmi injection, or even a pointer to a URL where the qemu patch stream is under discussion? It doesn't make too much sense to push this patch into libvirt until we are reasonably sure that the qemu interface is well-baked, to minimize needing later libvirt tweaks. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From wency at cn.fujitsu.com Tue Apr 19 02:01:57 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Tue, 19 Apr 2011 10:01:57 +0800 Subject: [libvirt] [PATCH V3 2/2] enhance processWatchdogEvent() In-Reply-To: <20110418114123.GG4648@redhat.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1CED.20202@cn.fujitsu.com> <4DA75CD7.9080908@redhat.com> <4DA7B76B.3010308@cn.fujitsu.com> <4DA873FA.8080009@redhat.com> <20110418114123.GG4648@redhat.com> Message-ID: <4DACED15.80704@cn.fujitsu.com> At 04/18/2011 07:41 PM, Daniel P. Berrange Write: > On Fri, Apr 15, 2011 at 10:36:10AM -0600, Eric Blake wrote: >> On 04/14/2011 09:11 PM, Wen Congyang wrote: >>> This patch do the following two things: >> >> s/do/does/ >> >>> 1. hold an extra reference while handling watchdog event >>> If the domain is not persistent, and qemu quits unexpectedly before >>> calling processWatchdogEvent(), vm will be freed and the function >>> processWatchdogEvent() will be dangerous. >>> >>> 2. unlock qemu driver and vm before returning from processWatchdogEvent() >>> When the function processWatchdogEvent() failed, we only free wdEvent, >>> but forget to unlock qemu driver and vm, free dumpfile. >>> >>> >>> --- >>> src/qemu/qemu_driver.c | 34 ++++++++++++++++++++++------------ >>> src/qemu/qemu_process.c | 4 ++++ >>> 2 files changed, 26 insertions(+), 12 deletions(-) >> >> Looks like your v2 caught my review comments correctly. But I found one >> more issue: >> >>> +++ b/src/qemu/qemu_process.c >>> @@ -428,6 +428,10 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, >>> if (VIR_ALLOC(wdEvent) == 0) { >>> wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP; >>> wdEvent->vm = vm; >>> + /* Hold an extra reference because we can't allow 'vm' to be >>> + * deleted before handling watchdog event is finished. >>> + */ >>> + virDomainObjRef(vm); >>> ignore_value(virThreadPoolSendJob(driver->workerPool, wdEvent)); >> >> Now that we have increased the ref count, we should decrease it if we >> are unable to send a job to the thread pool. That is, replace the >> ignore_value() with: >> >> if (virThreadPoolSendJob(...) < 0) { >> virDomainObjUnref(vm); >> VIR_FREE(wdEvent); >> } >> >> ACK with that change squashed in. > > This last minute addition caused a build failure Sorry for introducing a build failure. I have tested building before pushing this patch. But I did not meet any error, and I do not notice the warning. The default CFLAGS does not include '-Werror'. > > cc1: warnings being treated as errors > qemu/qemu_process.c: In function 'qemuProcessHandleWatchdog': > qemu/qemu_process.c:436:34: error: ignoring return value of 'virDomainObjUnref', declared with attribute warn_unused_result [-Wunused-result] > make[3]: *** [libvirt_driver_qemu_la-qemu_process.lo] Error 1 > > > I think we also need this added: > > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > index d405dda..5a81265 100644 > --- a/src/qemu/qemu_process.c > +++ b/src/qemu/qemu_process.c > @@ -433,14 +433,16 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > */ > virDomainObjRef(vm); > if (virThreadPoolSendJob(driver->workerPool, wdEvent) < 0) { > - virDomainObjUnref(vm); > + if (virDomainObjUnref(vm) < 0) > + vm = NULL; The return value of virDomainObjUnref() should not less than 0. If vm is unlocked in virDomainObjUnref(), the return value is 0. It is safe to check the return value here, but it should not happen, as we have held an extra reference when opening the monitor. This patch has been pushed, so I will post another patch to fix the problem. > VIR_FREE(wdEvent); > } > } else > virReportOOMError(); > } > > - virDomainObjUnlock(vm); > + if (vm) > + virDomainObjUnlock(vm); > > if (watchdogEvent || lifecycleEvent) { > qemuDriverLock(driver); > > Daniel From wency at cn.fujitsu.com Tue Apr 19 02:08:21 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Tue, 19 Apr 2011 10:08:21 +0800 Subject: [libvirt] [PATCH] qemu: fix the check of virDomainObjUnref()'s return value In-Reply-To: <20110418114123.GG4648@redhat.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1CED.20202@cn.fujitsu.com> <4DA75CD7.9080908@redhat.com> <4DA7B76B.3010308@cn.fujitsu.com> <4DA873FA.8080009@redhat.com> <20110418114123.GG4648@redhat.com> Message-ID: <4DACEE95.40400@cn.fujitsu.com> If vm is unlocked in virDomainObjUnref(), the return value is 0, not less than 0. --- src/qemu/qemu_process.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 1dfd005..7691cbe 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -433,7 +433,7 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, */ virDomainObjRef(vm); if (virThreadPoolSendJob(driver->workerPool, wdEvent) < 0) { - if (virDomainObjUnref(vm) < 0) + if (virDomainObjUnref(vm) == 0) vm = NULL; VIR_FREE(wdEvent); } -- 1.7.1 From usui at mxm.nes.nec.co.jp Tue Apr 19 03:06:29 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Tue, 19 Apr 2011 12:06:29 +0900 Subject: [libvirt] [PATCHv3 1/6] virNodeGetCPUTime: Expose new API In-Reply-To: <20110418113203.GF4648@redhat.com> References: <20110414185805.893c1ab0.usui@mxm.nes.nec.co.jp> <20110414190844.927ce596.usui@mxm.nes.nec.co.jp> <20110418113203.GF4648@redhat.com> Message-ID: <20110419120629.26eb429c.usui@mxm.nes.nec.co.jp> Hi, Daniel. On Mon, 18 Apr 2011 12:32:03 +0100 "Daniel P. Berrange" wrote: > On Thu, Apr 14, 2011 at 07:08:44PM +0900, Minoru Usui wrote: > > virNodeGetCPUTime: Expose new API > > > > Signed-off-by: Minoru Usui > > --- > > include/libvirt/libvirt.h.in | 50 ++++++++++++++++++++++++++++++++++++++++++ > > src/libvirt_public.syms | 5 ++++ > > 2 files changed, 55 insertions(+), 0 deletions(-) > > > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > > index 5783303..25cc08c 100644 > > --- a/include/libvirt/libvirt.h.in > > +++ b/include/libvirt/libvirt.h.in > > @@ -228,6 +228,51 @@ struct _virNodeInfo { > > unsigned int threads;/* number of threads per core */ > > }; > > > > +/** > > + * virNodeCpuTime: > > + */ > > + > > +/** > > + * virNodeCpuTimeFlags > > + * > > + * Flags when getting cpu statistics of the node. > > + */ > > +typedef enum { > > + /* > > + * The cumulative CPU time which spends by kernel, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_KERNEL = 1, > > + /* > > + * The cumulative CPU time which spends by user processes, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_USER = 2, > > + /* > > + * The cumulative idle CPU time, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_IDLE = 4, > > + /* > > + * The cumulative I/O wait CPU time, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_IOWAIT = 8, > > + /* > > + * The CPU utilization. > > + * The usage value is in percent and 100% represents all CPUs on > > + * the server. > > + */ > > + VIR_NODE_CPU_TIME_UTILIZATION = 16, > > + > > + /* > > + * The number of statistics supported by this version of the interface. > > + * To add new statistics, add them to the enum and increase this value. > > + */ > > + VIR_NODE_CPU_TIME_MAX = 32 > > +} virNodeCpuTimeFlags; > > + > > +#define VIR_NODE_CPU_TIME_MASK (VIR_NODE_CPU_TIME_MAX - 1) > > > > /** > > * virDomainSchedParameterType: > > @@ -593,6 +638,11 @@ int virNodeGetInfo (virConnectPtr conn, > > virNodeInfoPtr info); > > char * virConnectGetCapabilities (virConnectPtr conn); > > > > +int virNodeGetCpuTime (virConnectPtr conn, > > + unsigned long long *stats, > > + unsigned int nr_stats, > > + unsigned int flags); > > + > > unsigned long long virNodeGetFreeMemory (virConnectPtr conn); > > I'm sorry, but NACK to this API design. Your v2 design was consistent > with the design of the other stats APIs we provide & better than this > IMHO. I understand. I drop this v3 design. > > Daniel > -- > |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| > |: http://libvirt.org -o- http://virt-manager.org :| > |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| > |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- Minoru Usui From usui at mxm.nes.nec.co.jp Tue Apr 19 03:22:38 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Tue, 19 Apr 2011 12:22:38 +0900 Subject: [libvirt] [PATCHv2 1/6] virNodeGetCPUTime: Expose new API In-Reply-To: <20110418113045.GE4648@redhat.com> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> <20110408203312.90723b75.usui@mxm.nes.nec.co.jp> <20110410045856.GI24838@redhat.com> <20110418113045.GE4648@redhat.com> Message-ID: <20110419122238.7b22bfca.usui@mxm.nes.nec.co.jp> On Mon, 18 Apr 2011 12:30:45 +0100 "Daniel P. Berrange" wrote: > On Sun, Apr 10, 2011 at 12:58:56PM +0800, Daniel Veillard wrote: > > On Fri, Apr 08, 2011 at 08:33:12PM +0900, Minoru Usui wrote: > > > virNodeGetCPUTime: Expose new API > > > > > > Signed-off-by: Minoru Usui > > > --- > > > include/libvirt/libvirt.h.in | 64 ++++++++++++++++++++++++++++++++++++++++++ > > > src/libvirt_public.syms | 5 +++ > > > 2 files changed, 69 insertions(+), 0 deletions(-) > > > > > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > > > index bd36015..154c138 100644 > > > --- a/include/libvirt/libvirt.h.in > > > +++ b/include/libvirt/libvirt.h.in > > > @@ -228,6 +228,57 @@ struct _virNodeInfo { > > > unsigned int threads;/* number of threads per core */ > > > }; > > > > > > +/** > > > + * virNodeCpuTime: > > > + * > > > + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing > > > + * the information for the cpu time of the node. > > > + */ > > > + > > > +/** > > > + * Cpu Time Statistics Tags: > > > + */ > > > +typedef enum { > > > + /* > > > + * The cumulative CPU time which spends by kernel, > > > + * when the node booting up.(in nanoseconds). > > > + */ > > > + VIR_NODE_CPU_TIME_KERNEL = 0, > > > + /* > > > + * The cumulative CPU time which spends by user processes, > > > + * when the node booting up.(in nanoseconds). > > > + */ > > > + VIR_NODE_CPU_TIME_USER = 1, > > > + /* > > > + * The cumulative idle CPU time, > > > + * when the node booting up.(in nanoseconds). > > > + */ > > > + VIR_NODE_CPU_TIME_IDLE = 2, > > > + /* > > > + * The cumulative I/O wait CPU time, > > > + * when the node booting up.(in nanoseconds). > > > + */ > > > + VIR_NODE_CPU_TIME_IOWAIT = 3, > > > + /* > > > + * The CPU utilization. > > > + * The usage value is in percent and 100% represents all CPUs on > > > + * the server. > > > + */ > > > + VIR_NODE_CPU_TIME_UTILIZATION = 4, > > > + > > > + /* > > > + * The number of statistics supported by this version of the interface. > > > + * To add new statistics, add them to the enum and increase this value. > > > + */ > > > + VIR_NODE_CPU_TIME_NR = 5, > > > +} virNodeCpuTimeTags; > > > + > > > +typedef struct _virNodeCpuTime virNodeCpuTime; > > > + > > > +struct _virNodeCpuTime { > > > + virNodeCpuTimeTags tag; > > > + unsigned long long val; > > > +}; > > > > NACK, the size of an enum is not defined by the C language and > > hence is compiler dependant. We cannot use it as a component of a > > structure in the API. > > > > > /** > > > * virDomainSchedParameterType: > > > @@ -460,6 +511,14 @@ int virDomainMigrateSetMaxSpeed(virDomainPtr domain, > > > typedef virNodeInfo *virNodeInfoPtr; > > > > > > /** > > > + * virNodeCpuTimePtr: > > > + * > > > + * a virNodeCpuTimePtr is a pointer to a virNodeCpuTime structure. > > > + */ > > > + > > > +typedef virNodeCpuTime *virNodeCpuTimePtr; > > > + > > > +/** > > > * virConnectFlags > > > * > > > * Flags when opening a connection to a hypervisor > > > @@ -593,6 +652,11 @@ int virNodeGetInfo (virConnectPtr conn, > > > virNodeInfoPtr info); > > > char * virConnectGetCapabilities (virConnectPtr conn); > > > > > > +int virNodeGetCpuTime (virConnectPtr conn, > > > + virNodeCpuTimePtr stats, > > > + unsigned int nr_stats, > > > + unsigned int flags); > > > + > > > > I don't understand how the API is suppoed to work. Suppose you want > > the cumulative CPU time, how do you ask for it ? Seems you can't ! You > > just ask for a big stucture hoping that on return you may find it within > > the results. That looks broken to me. > > This is the same design we've used in the virDomainGetMemoryStats, > virDomainGetBlkioParameters, virDomainGetSchedularParamters without > any undue trouble. Yes. > > > > Either you make a simple API giving back an unsigned long long and > > you use the virNodeCpuTimeTags as the flag value > > > > int virNodeGetCpuTime(virConnectPtr conn, unsigned long long *time, > > unsigned int flags); > > > > and the flags indicate the value you're interested into, but in that > > case you have to ask multiple times. Or you make the VIR_NODE_CPU_TIME_* > > values a bit field, and you pass an array > > > > int virNodeGetCpuTime(virConnectPtr conn, > > unsigned long long *stats, > > unsigned int nr_stats, > > unsigned int flags); > > > > where flags is the logical or of the values you are interested into, and > > the implementation put them in order based on the VIR_NODE_CPU_TIME_* > > values. But in that case you must fail if one of the statistics is not > > available. > > I think these are worse because you're relying on ordering of values, > and not all hypervisors will be able to supply all values. In addition > it makes this stats API completely different to the other stats APIs > we have. OK. I drop v3 design. Everyone, how about this v2 patch series? Any other opinions? > > Daniel > -- > |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| > |: http://libvirt.org -o- http://virt-manager.org :| > |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| > |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- Minoru Usui From laine at laine.org Tue Apr 19 04:38:15 2011 From: laine at laine.org (Laine Stump) Date: Tue, 19 Apr 2011 00:38:15 -0400 Subject: [libvirt] libvirt 0.9.0 crashes on first start since boot In-Reply-To: <4DAC6BE7.5000302@scripty.at> References: <4DA6D0DD.10405@scripty.at> <4DA713FD.9080500@laine.org> <4DA8420E.2020901@scripty.at> <4DAAB361.9080105@laine.org> <4DAC6BE7.5000302@scripty.at> Message-ID: <4DAD11B7.3090105@laine.org> On 04/18/2011 12:50 PM, Thomas Treutner wrote: > On 04/17/2011 11:31 AM, Laine Stump wrote: >> On 04/15/2011 09:03 AM, Thomas Treutner wrote: >>> >>> I removed dnsmasq startup from the runlevel, now it works fine. I have >>> seen dnsmasq errors for a long time, but I didn't really care too much >>> about, as I don't need dnsmasq and the warnings didn't stop libvrit >>> from working. I think I'll just deinstall dnsmasq. >> >> Are you sure you want to uninstall dnsmasq, and not just disable it in >> the system config? If you uninstall dnsmasq, libvirt will fail to start >> the virtual networks - it uses dnsmasq to provide DNS for those networks >> even if you don't specify a dhcp range or hosts. > > Thanks for info, but I've not experienced such problems in my setup. I > have a bridged network for the guests, static IPs and my DNS server in > the guests /etc/resolv.conf - and everything works fine that way. I > assume I don't need dnsmasq in such a setup? > Ah, so even though you have a defined ("default", which is there when you install libvirt), you don't use it, so the failure to bring it up isn't an issue for you (as long as you don't mind the error message each time you restart libvirt). (dnsmasq is only setup/used for the virtual networks). If you're not using the default network, you might want to delete it... From matthias.bolte at googlemail.com Tue Apr 19 06:23:09 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Tue, 19 Apr 2011 08:23:09 +0200 Subject: [libvirt] [PATCH] virsh: nuke use of TRUE and FALSE In-Reply-To: <1303166375-17129-1-git-send-email-eblake@redhat.com> References: <1303166375-17129-1-git-send-email-eblake@redhat.com> Message-ID: 2011/4/19 Eric Blake : > Gnulib already guarantees , so it is easier to just > use the standardized spellings. > > * tools/virsh.c (vshCmdDef): Change callback to return real bool. > (__vshControl): Change several fields to bool. > (vshCommandOptBool): Change return type. > All callers updated. > * tools/Makefile.am (virsh-net-edit.c, virsh-pool-edit.c): > Likewise. > --- > > Mostly mechanical. > > ?tools/Makefile.am | ? ?4 +- > ?tools/virsh.c ? ? | 1674 ++++++++++++++++++++++++++--------------------------- > ?2 files changed, 835 insertions(+), 843 deletions(-) > Looks good in general, but you missed some places for s/int/bool/. Instead of pointing them out in the diff, here's a patch to be merged into yours. ACK with the attached patch merged in. Matthias -------------- next part -------------- A non-text attachment was scrubbed... Name: additions_to_virsh_nuke_use_of_TRUE_and_FALSE.patch Type: text/x-patch Size: 6695 bytes Desc: not available URL: From kamezawa.hiroyu at jp.fujitsu.com Tue Apr 19 07:38:30 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Tue, 19 Apr 2011 16:38:30 +0900 Subject: [libvirt] [PATCHv10 0/6] libvirt - support persistent device modification Message-ID: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> Hi, this is v10, totally refleshed. Thank you for advices. This version includes Eric's cleanup and Hu's Update device works. (And droppped some sanity check patches.) Because of many changes from v9, it may be better to write [RFC] in subject ;) This patch series does consolidate Attach/Detach/Update device's codes as.. == shared code (prepare lock, get objects etc..) switch(action) { case ATTACH case DETACH case UPDATE } shared code. == After that, adding persistent modification support as == shared code (prepare lock, get objects etc...) if (MODIFY_CONFIG) { switch (action) { case ATTACH: case DETACH: case UPDATE: } } if (MODIFY_LIVE) { switch (action) { case ATTACH: case DETACH: case UPDATE: } } shared code. (save config etc.) == Thanks, -Kame From kamezawa.hiroyu at jp.fujitsu.com Tue Apr 19 07:40:34 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Tue, 19 Apr 2011 16:40:34 +0900 Subject: [libvirt] [PATCHv10 1/6] libvirt/qemu - clean up for qemudDomainAt(de)tachDevice(Flags) In-Reply-To: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110419164034.9c8a82e3.kamezawa.hiroyu@jp.fujitsu.com> Centralize device modification in the more flexible APIs, to allow future honoring of additional flags. Explicitly reject the VIR_DOMAIN_DEVICE_MODIFY_FORCE flag on attach/detach. Based on Eric Blake's work. From: Eric Blake Signed-off-by: KAMEZAWA Hiroyuki * src/qemu/qemu_driver.c (qemudDomainAttachDevice) (qemudDomainAttachDeviceFlags): Swap bodies, and rename... (qemuDomainAttachDevice, qemuDomainAttachDeviceFlags): to this. (qemudDomainDetachDevice, qemudDomainDetachDeviceFlags): --- src/qemu/qemu_driver.c | 53 ++++++++++++++++++++++++++--------------------- 1 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f6e503a..a8f3849 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3786,8 +3786,8 @@ cleanup: } -static int qemudDomainAttachDevice(virDomainPtr dom, - const char *xml) +static int qemudDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; @@ -3796,6 +3796,14 @@ static int qemudDomainAttachDevice(virDomainPtr dom, virCgroupPtr cgroup = NULL; int ret = -1; + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot modify the persistent configuration of a domain")); + return -1; + } + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { @@ -3943,16 +3951,10 @@ cleanup: return ret; } -static int qemudDomainAttachDeviceFlags(virDomainPtr dom, - const char *xml, - unsigned int flags) { - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return qemudDomainAttachDevice(dom, xml); +static int qemudDomainAttachDevice(virDomainPtr dom, const char *xml) +{ + return qemudDomainAttachDeviceFlags(dom, xml, + VIR_DOMAIN_DEVICE_MODIFY_LIVE); } @@ -4078,14 +4080,23 @@ cleanup: } -static int qemudDomainDetachDevice(virDomainPtr dom, - const char *xml) { +static int qemudDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; virBitmapPtr qemuCaps = NULL; virDomainDeviceDefPtr dev = NULL; int ret = -1; + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE| + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); + + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot modify the persistent configuration of a domain:")); + return -1; + } qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { @@ -4164,16 +4175,10 @@ cleanup: return ret; } -static int qemudDomainDetachDeviceFlags(virDomainPtr dom, - const char *xml, - unsigned int flags) { - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return qemudDomainDetachDevice(dom, xml); +static int qemudDomainDetachDevice(virDomainPtr dom, const char *xml) +{ + return qemudDomainDetachDeviceFlags(dom, xml, + VIR_DOMAIN_DEVICE_MODIFY_LIVE); } static int qemudDomainGetAutostart(virDomainPtr dom, -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Tue Apr 19 07:43:09 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Tue, 19 Apr 2011 16:43:09 +0900 Subject: [libvirt] [PATCHv10 2/6] clean up At(De)tachDeviceFlags() for consolidation. In-Reply-To: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110419164309.8a35551f.kamezawa.hiroyu@jp.fujitsu.com> qemudDomainAttachDeviceFlags()/qemudDomainDetachFlags()/ qemudDomainUpdateDeviceFlags() has similar logics and copied codes. This patch series tries to unify them to use shared code when it can. At first, clean up At(De)tachDeviceFlags() and devide it into functions. By this, this patch pulls out shared components between functions. Based on patch series by Eric Blake, I added some modification as switch-case. From: Eric Blake Signed-off-by: KAMEZAWA Hiroyuki * src/qemu/qemu_driver.c (qemudDomainAttachDeviceFlags) : pulled out to qemudDomainModifyDeviceFlags() (qemudDomainModifyDeviceFlags) : impelements a generic codes for modify domain. (qemudDomainAttachDeviceFlagsLive) : codes for attaching devices to domain in live, no changes in logic from old code. (qemudDomainDetachDeviceFlagsLive) : codes for detaching devices to domain in live, no changes in logic from old code. --- src/qemu/qemu_driver.c | 429 ++++++++++++++++++++++++++---------------------- 1 files changed, 234 insertions(+), 195 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a8f3849..f33a7f4 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3785,15 +3785,223 @@ cleanup: return ret; } +static int qemudDomainAttachDeviceDiskLive(struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev, + virBitmapPtr qemuCaps) +{ + virDomainDiskDefPtr disk = dev->data.disk; + virCgroupPtr cgroup = NULL; + int ret = -1; -static int qemudDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) + if (disk->driverName != NULL && !STREQ(disk->driverName, "qemu")) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("unsupported driver name '%s' for disk '%s'"), + disk->driverName, disk->src); + goto end; + } + + if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { + if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to find cgroup for %s"), + vm->def->name); + goto end; + } + if (qemuSetupDiskCgroup(driver, vm, cgroup, disk) < 0) + goto end; + } + switch (disk->device) { + case VIR_DOMAIN_DISK_DEVICE_CDROM: + case VIR_DOMAIN_DISK_DEVICE_FLOPPY: + ret = qemuDomainChangeEjectableMedia(driver, vm, disk, qemuCaps, false); + break; + case VIR_DOMAIN_DISK_DEVICE_DISK: + if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) + ret = qemuDomainAttachUsbMassstorageDevice(driver, vm, + disk, qemuCaps); + else if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) + ret = qemuDomainAttachPciDiskDevice(driver, vm, disk, qemuCaps); + else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) + ret = qemuDomainAttachSCSIDisk(driver, vm, disk, qemuCaps); + else + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk bus '%s' cannot be hotplugged."), + virDomainDiskBusTypeToString(disk->bus)); + break; + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk device type '%s' cannot be hotplugged"), + virDomainDiskDeviceTypeToString(disk->device)); + break; + } + + if (ret != 0 && cgroup) { + if (qemuTeardownDiskCgroup(driver, vm, cgroup, disk) < 0) + VIR_WARN("Failed to teardown cgroup for disk path %s", + NULLSTR(disk->src)); + } +end: + if (cgroup) + virCgroupFree(&cgroup); + return ret; +} + +static int +qemudDomainAttachDeviceControllerLive(struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev, + virBitmapPtr qemuCaps) +{ + virDomainControllerDefPtr cont = dev->data.controller; + int ret = -1; + + switch (cont->type) { + case VIR_DOMAIN_CONTROLLER_TYPE_SCSI: + ret = qemuDomainAttachPciControllerDevice(driver, vm, cont, qemuCaps); + break; + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk controller bus '%s' cannot be hotplugged."), + virDomainControllerTypeToString(cont->type)); + break; + } + return ret; +} + +static int qemudDomainAttachDeviceLive(virDomainObjPtr vm, + virDomainDeviceDefPtr dev, + virDomainPtr dom, + virBitmapPtr qemuCaps) +{ + struct qemud_driver *driver = dom->conn->privateData; + int ret = -1; + + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + ret = qemudDomainAttachDeviceDiskLive(driver, vm, dev, qemuCaps); + if (!ret) + dev->data.disk = NULL; + break; + + case VIR_DOMAIN_DEVICE_CONTROLLER: + ret = qemudDomainAttachDeviceControllerLive(driver, vm, dev, qemuCaps); + if (!ret) + dev->data.controller = NULL; + break; + + case VIR_DOMAIN_DEVICE_NET: + ret = qemuDomainAttachNetDevice(dom->conn, driver, vm, + dev->data.net, qemuCaps); + if (!ret) + dev->data.net = NULL; + break; + + case VIR_DOMAIN_DEVICE_HOSTDEV: + ret = qemuDomainAttachHostDevice(driver, vm, + dev->data.hostdev, qemuCaps); + if (!ret) + dev->data.hostdev = NULL; + break; + + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("device type '%s' cannot be attached"), + virDomainDeviceTypeToString(dev->type)); + break; + } + + return ret; +} + +static int qemudDomainDetachDeviceDiskLive(struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev, + virBitmapPtr qemuCaps) +{ + virDomainDiskDefPtr disk = dev->data.disk; + int ret = -1; + + switch (disk->device) { + case VIR_DOMAIN_DISK_DEVICE_DISK: + if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) + ret = qemuDomainDetachPciDiskDevice(driver, vm, dev, qemuCaps); + else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) + ret = qemuDomainDetachDiskDevice(driver, vm, dev, qemuCaps); + else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) + ret = qemuDomainDetachDiskDevice(driver, vm, dev, qemuCaps); + else + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This type of disk cannot be hot unplugged")); + break; + default: + break; + } + return ret; +} + +static int +qemudDomainDetachDeviceControllerLive(struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev, + virBitmapPtr qemuCaps) +{ + virDomainControllerDefPtr cont = dev->data.controller; + int ret = -1; + + switch (cont->type) { + case VIR_DOMAIN_CONTROLLER_TYPE_SCSI: + ret = qemuDomainDetachPciControllerDevice(driver, vm, dev, qemuCaps); + break; + default : + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk controller bus '%s' cannot be hotunplugged."), + virDomainControllerTypeToString(cont->type)); + } + return ret; +} + +static int qemudDomainDetachDeviceLive(virDomainObjPtr vm, + virDomainDeviceDefPtr dev, + virDomainPtr dom, + virBitmapPtr qemuCaps) +{ + struct qemud_driver *driver = dom->conn->privateData; + int ret = -1; + + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + ret = qemudDomainDetachDeviceDiskLive(driver, vm, dev, qemuCaps); + break; + case VIR_DOMAIN_DEVICE_CONTROLLER: + ret = qemudDomainDetachDeviceControllerLive(driver, vm, dev, qemuCaps); + break; + case VIR_DOMAIN_DEVICE_NET: + ret = qemuDomainDetachNetDevice(driver, vm, dev, qemuCaps); + break; + case VIR_DOMAIN_DEVICE_HOSTDEV: + ret = qemuDomainDetachHostDevice(driver, vm, dev, qemuCaps); + break; + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("This type of device cannot be hot unplugged")); + break; + } + + return ret; +} + +enum { + QEMUD_DEVICE_ATTACH, QEMUD_DEVICE_DETACH, QEMUD_DEVICE_UPDATE, +}; + +static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags, int action) { struct qemud_driver *driver = dom->conn->privateData; - virDomainObjPtr vm; - virDomainDeviceDefPtr dev = NULL; virBitmapPtr qemuCaps = NULL; - virCgroupPtr cgroup = NULL; + virDomainObjPtr vm = NULL; + virDomainDeviceDefPtr dev = NULL; int ret = -1; virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | @@ -3833,106 +4041,22 @@ static int qemudDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, &qemuCaps) < 0) goto endjob; - if (dev->type == VIR_DOMAIN_DEVICE_DISK) { - if (dev->data.disk->driverName != NULL && - !STREQ(dev->data.disk->driverName, "qemu")) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - _("unsupported driver name '%s' for disk '%s'"), - dev->data.disk->driverName, dev->data.disk->src); - goto endjob; - } - - if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { - if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=0 ) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to find cgroup for %s"), - vm->def->name); - goto endjob; - } - if (qemuSetupDiskCgroup(driver, vm, cgroup, dev->data.disk) < 0) - goto endjob; - } - - switch (dev->data.disk->device) { - case VIR_DOMAIN_DISK_DEVICE_CDROM: - case VIR_DOMAIN_DISK_DEVICE_FLOPPY: - ret = qemuDomainChangeEjectableMedia(driver, vm, - dev->data.disk, - qemuCaps, - false); - if (ret == 0) - dev->data.disk = NULL; - break; - - case VIR_DOMAIN_DISK_DEVICE_DISK: - if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) { - ret = qemuDomainAttachUsbMassstorageDevice(driver, vm, - dev->data.disk, qemuCaps); - if (ret == 0) - dev->data.disk = NULL; - } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { - ret = qemuDomainAttachPciDiskDevice(driver, vm, - dev->data.disk, qemuCaps); - if (ret == 0) - dev->data.disk = NULL; - } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) { - ret = qemuDomainAttachSCSIDisk(driver, vm, - dev->data.disk, qemuCaps); - if (ret == 0) - dev->data.disk = NULL; - } else { - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("disk bus '%s' cannot be hotplugged."), - virDomainDiskBusTypeToString(dev->data.disk->bus)); - /* fallthrough */ - } - break; - - default: - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("disk device type '%s' cannot be hotplugged"), - virDomainDiskDeviceTypeToString(dev->data.disk->device)); - /* Fallthrough */ - } - if (ret != 0 && cgroup) { - if (qemuTeardownDiskCgroup(driver, vm, cgroup, dev->data.disk) < 0) - VIR_WARN("Failed to teardown cgroup for disk path %s", - NULLSTR(dev->data.disk->src)); - } - } else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) { - if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) { - ret = qemuDomainAttachPciControllerDevice(driver, vm, - dev->data.controller, qemuCaps); - if (ret == 0) - dev->data.controller = NULL; - } else { - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("disk controller bus '%s' cannot be hotplugged."), - virDomainControllerTypeToString(dev->data.controller->type)); - /* fallthrough */ - } - } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { - ret = qemuDomainAttachNetDevice(dom->conn, driver, vm, - dev->data.net, qemuCaps); - if (ret == 0) - dev->data.net = NULL; - } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { - ret = qemuDomainAttachHostDevice(driver, vm, - dev->data.hostdev, qemuCaps); - if (ret == 0) - dev->data.hostdev = NULL; - } else { - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("device type '%s' cannot be attached"), - virDomainDeviceTypeToString(dev->type)); - goto endjob; + switch (action) { + case QEMUD_DEVICE_ATTACH: + ret = qemudDomainAttachDeviceLive(vm, dev, dom, qemuCaps); + break; + case QEMUD_DEVICE_DETACH: + ret = qemudDomainDetachDeviceLive(vm, dev, dom, qemuCaps); + break; + default: + break; } - - /* update domain status forcibly because the domain status may be changed + /* + * update domain status forcibly because the domain status may be changed * even if we attach the device failed. For example, a new controller may * be created. */ - if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) + if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) ret = -1; endjob: @@ -3940,10 +4064,6 @@ endjob: vm = NULL; cleanup: - if (cgroup) - virCgroupFree(&cgroup); - - qemuCapsFree(qemuCaps); virDomainDeviceDefFree(dev); if (vm) virDomainObjUnlock(vm); @@ -3951,6 +4071,13 @@ cleanup: return ret; } +static int qemudDomainAttachDeviceFlags(virDomainPtr dom, + const char *xml, + unsigned int flags) +{ + return qemudDomainModifyDeviceFlags(dom, xml, flags, QEMUD_DEVICE_ATTACH); +} + static int qemudDomainAttachDevice(virDomainPtr dom, const char *xml) { return qemudDomainAttachDeviceFlags(dom, xml, @@ -4080,99 +4207,11 @@ cleanup: } + static int qemudDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) { - struct qemud_driver *driver = dom->conn->privateData; - virDomainObjPtr vm; - virBitmapPtr qemuCaps = NULL; - virDomainDeviceDefPtr dev = NULL; - int ret = -1; - - virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE| - VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); - - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain:")); - return -1; - } - qemuDriverLock(driver); - vm = virDomainFindByUUID(&driver->domains, dom->uuid); - 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 (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) - goto cleanup; - - if (!virDomainObjIsActive(vm)) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot detach device on inactive domain")); - goto endjob; - } - - dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, - VIR_DOMAIN_XML_INACTIVE); - if (dev == NULL) - goto endjob; - - if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch, - NULL, - &qemuCaps) < 0) - goto endjob; - - if (dev->type == VIR_DOMAIN_DEVICE_DISK && - dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) { - if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { - ret = qemuDomainDetachPciDiskDevice(driver, vm, dev, qemuCaps); - } - else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) { - ret = qemuDomainDetachDiskDevice(driver, vm, dev, qemuCaps); - } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) { - ret = qemuDomainDetachDiskDevice(driver, vm, dev, qemuCaps); - } - else { - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("This type of disk cannot be hot unplugged")); - } - } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { - ret = qemuDomainDetachNetDevice(driver, vm, dev, qemuCaps); - } else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) { - if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) { - ret = qemuDomainDetachPciControllerDevice(driver, vm, dev, - qemuCaps); - } else { - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("disk controller bus '%s' cannot be hotunplugged."), - virDomainControllerTypeToString(dev->data.controller->type)); - /* fallthrough */ - } - } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { - ret = qemuDomainDetachHostDevice(driver, vm, dev, qemuCaps); - } else { - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - "%s", _("This type of device cannot be hot unplugged")); - } - - if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) - ret = -1; - -endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; - -cleanup: - qemuCapsFree(qemuCaps); - virDomainDeviceDefFree(dev); - if (vm) - virDomainObjUnlock(vm); - qemuDriverUnlock(driver); - return ret; + return qemudDomainModifyDeviceFlags(dom, xml, flags, QEMUD_DEVICE_DETACH); } static int qemudDomainDetachDevice(virDomainPtr dom, const char *xml) -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Tue Apr 19 07:44:43 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Tue, 19 Apr 2011 16:44:43 +0900 Subject: [libvirt] [PATCHv10 3/6] clean up UpdateDevice for consolidation In-Reply-To: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110419164443.8b4446a8.kamezawa.hiroyu@jp.fujitsu.com> This patch strips reusable part of qemudDomainUpdateDeviceFlags() and consolidate it to qemudDomainModifyDeviceFlags(). No functional changes. Based on Eric's and Hu's work. Signed-off-by: KAMEZAWA Hiroyuki * src/qemu/qemu_driver.c (qemudDomainUpdateDeviceLive) : core of UpdateDevice, extracted from UpdateDeviceFlags() (qemudDomainUpdateDeviceFlags): reworked as a wrapper function of ModifyDeviceFlags() --- src/qemu/qemu_driver.c | 209 +++++++++++++++++++++--------------------------- 1 files changed, 90 insertions(+), 119 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f33a7f4..2bdf42e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3991,6 +3991,74 @@ static int qemudDomainDetachDeviceLive(virDomainObjPtr vm, return ret; } +static int +qemudDomainChangeDiskMediaLive(virDomainObjPtr vm, + virDomainDeviceDefPtr dev, + struct qemud_driver *driver, + virBitmapPtr qemuCaps, + bool force) +{ + virDomainDiskDefPtr disk = dev->data.disk; + virCgroupPtr cgroup = NULL; + int ret; + + if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { + if (virCgroupForDomain(driver->cgroup, + vm->def->name, &cgroup, 0) !=0 ) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to find cgroup for %s"), + vm->def->name); + goto end; + } + if (qemuSetupDiskCgroup(driver, vm, cgroup, disk) < 0) + goto end; + } + + switch (disk->device) { + case VIR_DOMAIN_DISK_DEVICE_CDROM: + case VIR_DOMAIN_DISK_DEVICE_FLOPPY: + ret = qemuDomainChangeEjectableMedia(driver, vm, disk, qemuCaps, force); + if (ret == 0) + dev->data.disk = NULL; + break; + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk bus '%s' cannot be updated."), + virDomainDiskBusTypeToString(disk->bus)); + break; + } +end: + if (cgroup) + virCgroupFree(&cgroup); + return ret; +} + +static int qemudDomainUpdateDeviceLive(virDomainObjPtr vm, + virDomainDeviceDefPtr dev, + virDomainPtr dom, + virBitmapPtr qemuCaps, + bool force) +{ + struct qemud_driver *driver = dom->conn->privateData; + int ret = -1; + + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + ret = qemudDomainChangeDiskMediaLive(vm, dev, driver, qemuCaps, force); + break; + case VIR_DOMAIN_DEVICE_GRAPHICS: + ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics); + break; + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("device type '%s' cannot be updated"), + virDomainDeviceTypeToString(dev->type)); + break; + } + + return ret; +} + enum { QEMUD_DEVICE_ATTACH, QEMUD_DEVICE_DETACH, QEMUD_DEVICE_UPDATE, }; @@ -4002,10 +4070,25 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, virBitmapPtr qemuCaps = NULL; virDomainObjPtr vm = NULL; virDomainDeviceDefPtr dev = NULL; + bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; int ret = -1; - virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | - VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); + switch (action) { + case QEMUD_DEVICE_ATTACH: + case QEMUD_DEVICE_DETACH: + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); + break; + case QEMUD_DEVICE_UPDATE: + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_CURRENT | + VIR_DOMAIN_DEVICE_MODIFY_LIVE | + VIR_DOMAIN_DEVICE_MODIFY_CONFIG | + VIR_DOMAIN_DEVICE_MODIFY_FORCE, -1); + break; + default: + break; + } + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot modify the persistent configuration of a domain")); @@ -4048,9 +4131,13 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, case QEMUD_DEVICE_DETACH: ret = qemudDomainDetachDeviceLive(vm, dev, dom, qemuCaps); break; + case QEMUD_DEVICE_UPDATE: + ret = qemudDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force); + break; default: break; } + /* * update domain status forcibly because the domain status may be changed * even if we attach the device failed. For example, a new controller may @@ -4089,125 +4176,9 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) { - struct qemud_driver *driver = dom->conn->privateData; - virDomainObjPtr vm; - virDomainDeviceDefPtr dev = NULL; - virBitmapPtr qemuCaps = NULL; - virCgroupPtr cgroup = NULL; - int ret = -1; - bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; - - virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_CURRENT | - VIR_DOMAIN_DEVICE_MODIFY_LIVE | - VIR_DOMAIN_DEVICE_MODIFY_CONFIG | - VIR_DOMAIN_DEVICE_MODIFY_FORCE, -1); - - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } - - qemuDriverLock(driver); - vm = virDomainFindByUUID(&driver->domains, dom->uuid); - 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 (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) - goto cleanup; - - if (!virDomainObjIsActive(vm)) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot attach device on inactive domain")); - goto endjob; - } - - dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, - VIR_DOMAIN_XML_INACTIVE); - if (dev == NULL) - goto endjob; - - if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch, - NULL, - &qemuCaps) < 0) - goto endjob; - - switch (dev->type) { - case VIR_DOMAIN_DEVICE_DISK: - if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { - if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=0 ) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to find cgroup for %s"), - vm->def->name); - goto endjob; - } - if (qemuSetupDiskCgroup(driver, vm, cgroup, dev->data.disk) < 0) - goto endjob; - } - - switch (dev->data.disk->device) { - case VIR_DOMAIN_DISK_DEVICE_CDROM: - case VIR_DOMAIN_DISK_DEVICE_FLOPPY: - ret = qemuDomainChangeEjectableMedia(driver, vm, - dev->data.disk, - qemuCaps, - force); - if (ret == 0) - dev->data.disk = NULL; - break; - - - default: - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("disk bus '%s' cannot be updated."), - virDomainDiskBusTypeToString(dev->data.disk->bus)); - break; - } - - if (ret != 0 && cgroup) { - if (qemuTeardownDiskCgroup(driver, vm, cgroup, dev->data.disk) < 0) - VIR_WARN("Failed to teardown cgroup for disk path %s", - NULLSTR(dev->data.disk->src)); - } - break; - - case VIR_DOMAIN_DEVICE_GRAPHICS: - ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics); - break; - - default: - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("device type '%s' cannot be updated"), - virDomainDeviceTypeToString(dev->type)); - break; - } - - if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) - ret = -1; - -endjob: - if (qemuDomainObjEndJob(vm) == 0) - vm = NULL; - -cleanup: - if (cgroup) - virCgroupFree(&cgroup); - - qemuCapsFree(qemuCaps); - virDomainDeviceDefFree(dev); - if (vm) - virDomainObjUnlock(vm); - qemuDriverUnlock(driver); - return ret; + return qemudDomainModifyDeviceFlags(dom, xml, flags, QEMUD_DEVICE_UPDATE); } - - static int qemudDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) { -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Tue Apr 19 07:46:07 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Tue, 19 Apr 2011 16:46:07 +0900 Subject: [libvirt] [PATCHv10 4/6] libvirt/qemu support persistent device modification In-Reply-To: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110419164607.6e94a6fd.kamezawa.hiroyu@jp.fujitsu.com> This patch adds functions for modify domain's persistent definition. To do error recovery in easy way, we use a copy of vmdef and update it. The whole sequence will be: make a copy of domain definition. if (flags & MODIFY_CONFIG) update copied domain definition if (flags & MODIF_LIVE) do hotplug. if (no error) save copied one to the file and update cached definition. else discard copied definition. This patch is mixuture of Eric Blake's work and mine. From: Eric Blake Signed-off-by: KAMEZAWA Hiroyuki (virDomainObjCopyPersistentDef): make a copy of persistent vm definition (qemudDomainModifyDeviceFlags): add support for MODIFY_CONFIG and MODIFY_CURRENT (qemudDomainAttach/Detach/UpdateDeviceConfig) : callbacks. now empty --- src/conf/domain_conf.c | 18 ++++++ src/conf/domain_conf.h | 3 + src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 148 ++++++++++++++++++++++++++++++++++++---------- 4 files changed, 139 insertions(+), 31 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6b733d4..bb8f0a4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9510,3 +9510,21 @@ cleanup: return ret; } + + +virDomainDefPtr +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom) +{ + char *xml; + virDomainDefPtr cur, ret; + + cur = virDomainObjGetPersistentDef(caps, dom); + + xml = virDomainDefFormat(cur, VIR_DOMAIN_XML_WRITE_FLAGS); + if (!xml) + return NULL; + + ret = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS); + + return ret; +} diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6ea30b9..ddf111a 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1288,6 +1288,9 @@ int virDomainObjSetDefTransient(virCapsPtr caps, virDomainDefPtr virDomainObjGetPersistentDef(virCapsPtr caps, virDomainObjPtr domain); +virDomainDefPtr +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom); + void virDomainRemoveInactive(virDomainObjListPtr doms, virDomainObjPtr dom); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ba7739d..f732431 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -287,6 +287,7 @@ virDomainMemballoonModelTypeToString; virDomainNetDefFree; virDomainNetTypeToString; virDomainObjAssignDef; +virDomainObjCopyPersistentDef; virDomainObjSetDefTransient; virDomainObjGetPersistentDef; virDomainObjIsDuplicate; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2bdf42e..4ac8f7e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4059,6 +4059,48 @@ static int qemudDomainUpdateDeviceLive(virDomainObjPtr vm, return ret; } +static int +qemudDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev) +{ + switch (dev->type) { + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("persistent update of device is not supported")); + return -1; + } + return 0; +} + + +static int +qemudDomainDetachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev) +{ + switch (dev->type) { + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("persistent update of device is not supported")); + return -1; + } + return 0; +} + +static int +qemudDomainUpdateDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev, + bool force ATTRIBUTE_UNUSED) +{ + switch (dev->type) { + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("persistent update of device is not supported")); + return -1; + } + return 0; + +} + enum { QEMUD_DEVICE_ATTACH, QEMUD_DEVICE_DETACH, QEMUD_DEVICE_UPDATE, }; @@ -4069,6 +4111,7 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, struct qemud_driver *driver = dom->conn->privateData; virBitmapPtr qemuCaps = NULL; virDomainObjPtr vm = NULL; + virDomainDefPtr vmdef = NULL; virDomainDeviceDefPtr dev = NULL; bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; int ret = -1; @@ -4077,7 +4120,8 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, case QEMUD_DEVICE_ATTACH: case QEMUD_DEVICE_DETACH: virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | - VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); + VIR_DOMAIN_DEVICE_MODIFY_CONFIG | + VIR_DOMAIN_DEVICE_MODIFY_CURRENT, -1); break; case QEMUD_DEVICE_UPDATE: virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_CURRENT | @@ -4089,12 +4133,6 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, break; } - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } - qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { @@ -4108,11 +4146,29 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; - if (!virDomainObjIsActive(vm)) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot attach device on inactive domain")); - goto endjob; + if (virDomainObjIsActive(vm)) { + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CURRENT) + flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE; + } else { + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CURRENT) + flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG; + /* check consistency between flags and the vm state */ + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", + _("cannot modify device on inactive domain")); + goto endjob; + } + } + + if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot modify device on transient domain")); + goto endjob; } + /* At updating config, we update a copy */ + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) + vmdef = virDomainObjCopyPersistentDef(driver->caps, vm); dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, VIR_DOMAIN_XML_INACTIVE); @@ -4124,33 +4180,63 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, &qemuCaps) < 0) goto endjob; - switch (action) { - case QEMUD_DEVICE_ATTACH: - ret = qemudDomainAttachDeviceLive(vm, dev, dom, qemuCaps); - break; - case QEMUD_DEVICE_DETACH: - ret = qemudDomainDetachDeviceLive(vm, dev, dom, qemuCaps); - break; - case QEMUD_DEVICE_UPDATE: - ret = qemudDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force); - break; - default: - break; - } + ret = 0; - /* - * update domain status forcibly because the domain status may be changed - * even if we attach the device failed. For example, a new controller may - * be created. - */ - if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) - ret = -1; + /* Update a copy of persistent definition */ + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + switch (action) { + case QEMUD_DEVICE_ATTACH: + ret = qemudDomainAttachDeviceConfig(vmdef, dev); + break; + case QEMUD_DEVICE_DETACH: + ret = qemudDomainDetachDeviceConfig(vmdef, dev); + break; + case QEMUD_DEVICE_UPDATE: + ret = qemudDomainUpdateDeviceConfig(vmdef, dev, force); + break; + default: + break; + } + } + /* Update Live */ + if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE)) { + switch (action) { + case QEMUD_DEVICE_ATTACH: + ret = qemudDomainAttachDeviceLive(vm, dev, dom, qemuCaps); + break; + case QEMUD_DEVICE_DETACH: + ret = qemudDomainDetachDeviceLive(vm, dev, dom, qemuCaps); + break; + case QEMUD_DEVICE_UPDATE: + ret = qemudDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force); + break; + default: + break; + } + /* + * update domain status forcibly because the domain status may be + * changed even if we attach the device failed. For example, a new + * controller may be created. + */ + if (!ret && + virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) + ret = -1; + } + /* No error until here, we can save persistent definition */ + if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) { + ret = virDomainSaveConfig(driver->configDir, vmdef); + if (!ret) { + virDomainObjAssignDef(vm, vmdef, false); + vmdef = NULL; + } + } endjob: if (qemuDomainObjEndJob(vm) == 0) vm = NULL; cleanup: + virDomainDefFree(vmdef); virDomainDeviceDefFree(dev); if (vm) virDomainObjUnlock(vm); -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Tue Apr 19 07:47:18 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Tue, 19 Apr 2011 16:47:18 +0900 Subject: [libvirt] [PATCHv10 5/6] libvirt/qemu - support persistent disk modification In-Reply-To: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110419164718.cf44cebd.kamezawa.hiroyu@jp.fujitsu.com> support changes of disks by VIR_DOMAIN_DEVICE_MODIFY_CONFIG for qemu. This patch includes patches for Attach/Detach. Signed-off-by: KAMEZAWA Hiroyuki * /src/conf/domain_conf.c (virDomainDiskIndexByName): returns array index of disk in vmdef. (virDomainDiskRemoveByName): removes a disk which has the name. * src/qemu/qemu_driver.c (qemudDomainAttachDeviceConfig): add support for Disks. (qemudDomainDetachDeviceConfig): add support for Disks. --- src/conf/domain_conf.c | 22 ++++++++++++++++++++++ src/conf/domain_conf.h | 2 ++ src/libvirt_private.syms | 2 ++ src/qemu/qemu_driver.c | 36 ++++++++++++++++++++++++++++++++++-- 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index bb8f0a4..43e9330 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -5007,6 +5007,19 @@ virVirtualPortProfileFormat(virBufferPtr buf, virBufferVSprintf(buf, "%s\n", indent); } +int virDomainDiskIndexByName(virDomainDefPtr def, const char *name) +{ + virDomainDiskDefPtr vdisk; + int i; + + for (i = 0; i < def->ndisks; i++) { + vdisk = def->disks[i]; + if (STREQ(vdisk->dst, name)) + return i; + } + return -1; +} + int virDomainDiskInsert(virDomainDefPtr def, virDomainDiskDefPtr disk) { @@ -5078,6 +5091,15 @@ void virDomainDiskRemove(virDomainDefPtr def, size_t i) } } +int virDomainDiskRemoveByName(virDomainDefPtr def, const char *name) +{ + int i = virDomainDiskIndexByName(def, name); + if (i < 0) + return -1; + virDomainDiskRemove(def, i); + return 0; +} + int virDomainControllerInsert(virDomainDefPtr def, virDomainControllerDefPtr controller) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ddf111a..1dadf98 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1329,6 +1329,7 @@ int virDomainVcpupinAdd(virDomainDefPtr def, int maplen, int vcpu); +int virDomainDiskIndexByName(virDomainDefPtr def, const char *name); int virDomainDiskInsert(virDomainDefPtr def, virDomainDiskDefPtr disk); void virDomainDiskInsertPreAlloced(virDomainDefPtr def, @@ -1336,6 +1337,7 @@ void virDomainDiskInsertPreAlloced(virDomainDefPtr def, int virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def); void virDomainDiskRemove(virDomainDefPtr def, size_t i); +int virDomainDiskRemoveByName(virDomainDefPtr def, const char *name); int virDomainControllerInsert(virDomainDefPtr def, virDomainControllerDefPtr controller); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f732431..c469259 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -246,11 +246,13 @@ virDomainDiskDefFree; virDomainDiskDeviceTypeToString; virDomainDiskErrorPolicyTypeFromString; virDomainDiskErrorPolicyTypeToString; +virDomainDiskIndexByName; virDomainDiskInsert; virDomainDiskInsertPreAlloced; virDomainDiskIoTypeFromString; virDomainDiskIoTypeToString; virDomainDiskRemove; +virDomainDiskRemoveByName; virDomainDiskTypeFromString; virDomainDiskTypeToString; virDomainFSDefFree; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 4ac8f7e..92643ef 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4060,10 +4060,32 @@ static int qemudDomainUpdateDeviceLive(virDomainObjPtr vm, } static int -qemudDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, +qemudDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { + virDomainDiskDefPtr disk; + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + disk = dev->data.disk; + if (virDomainDiskIndexByName(vmdef, disk->dst) >= 0) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("target %s already exists."), disk->dst); + return -1; + } + if (virDomainDiskInsert(vmdef, disk)) { + virReportOOMError(); + return -1; + } + /* vmdef has the pointer. Generic codes for vmdef will do all jobs */ + dev->data.disk = NULL; + if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO) + if (virDomainDefAddImplicitControllers(vmdef) < 0) + return -1; + if (qemuDomainAssignPCIAddresses(vmdef) < 0) + return -1; + break; + default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent update of device is not supported")); @@ -4074,10 +4096,20 @@ qemudDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, static int -qemudDomainDetachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, +qemudDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { + virDomainDiskDefPtr disk; + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + disk = dev->data.disk; + if (virDomainDiskRemoveByName(vmdef, disk->dst)) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("no target device %s"), disk->dst); + return -1; + } + break; default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent update of device is not supported")); -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Tue Apr 19 07:48:43 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Tue, 19 Apr 2011 16:48:43 +0900 Subject: [libvirt] [PATCHv10 6/6] support update device persistent. In-Reply-To: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110419164843.fd763fbe.kamezawa.hiroyu@jp.fujitsu.com> This patch adds support for Disk exchange in persistent. Signed-off-by: KAMEZAWA Hiroyuki * src/qemu/qemu_driver.c (qemudDomainUpdateDeviceConfig): add cdrom/floppy exchange code. --- src/qemu/qemu_driver.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 39 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 92643ef..6188722 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4119,11 +4119,49 @@ qemudDomainDetachDeviceConfig(virDomainDefPtr vmdef, } static int -qemudDomainUpdateDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, +qemudDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev, bool force ATTRIBUTE_UNUSED) { + virDomainDiskDefPtr orig, disk; + int pos; + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + disk = dev->data.disk; + pos = virDomainDiskIndexByName(vmdef, disk->dst); + if (pos < 0) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("target %s doesn't exists."), disk->dst); + return -1; + } + orig = vmdef->disks[pos]; + if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM) && + !(orig->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("this disk doesn't support update")); + return -1; + } + /* + * Update 'orig' + * We allow updating src/type//driverType/cachemode/ + */ + VIR_FREE(orig->src); + orig->src = disk->src; + orig->type = disk->type; + orig->cachemode = disk->cachemode; + if (disk->driverName) { + VIR_FREE(orig->driverName); + orig->driverName = disk->driverName; + disk->driverName = NULL; + } + if (disk->driverType) { + VIR_FREE(orig->driverType); + orig->driverType = disk->driverType; + disk->driverType = NULL; + } + disk->src = NULL; + break; default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent update of device is not supported")); -- 1.7.4.1 From liyong at skybility.com Tue Apr 19 08:17:48 2011 From: liyong at skybility.com (Lyre) Date: Tue, 19 Apr 2011 16:17:48 +0800 Subject: [libvirt] [libvirt-php 1/1] Make doc package noarch Message-ID: <1303201068-15189-1-git-send-email-liyong@skybility.com> --- libvirt-php.spec.in | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/libvirt-php.spec.in b/libvirt-php.spec.in index 07e11a1..41408a2 100644 --- a/libvirt-php.spec.in +++ b/libvirt-php.spec.in @@ -46,6 +46,7 @@ For more details see: http://www.libvirt.org/php/ %package -n libvirt-php-doc Summary: Document of libvirt-php Group: Development/Libraries/PHP +BuildArch: noarch Requires: libvirt-php = %{version} %description -n libvirt-php-doc -- 1.7.3.4 From minovotn at redhat.com Tue Apr 19 08:34:47 2011 From: minovotn at redhat.com (Michal Novotny) Date: Tue, 19 Apr 2011 10:34:47 +0200 Subject: [libvirt] [libvirt-php 1/1] Make doc package noarch In-Reply-To: <1303201068-15189-1-git-send-email-liyong@skybility.com> References: <1303201068-15189-1-git-send-email-liyong@skybility.com> Message-ID: <4DAD4927.7050400@redhat.com> On 04/19/2011 10:17 AM, Lyre wrote: > --- > libvirt-php.spec.in | 1 + > 1 files changed, 1 insertions(+), 0 deletions(-) > > diff --git a/libvirt-php.spec.in b/libvirt-php.spec.in > index 07e11a1..41408a2 100644 > --- a/libvirt-php.spec.in > +++ b/libvirt-php.spec.in > @@ -46,6 +46,7 @@ For more details see: http://www.libvirt.org/php/ > %package -n libvirt-php-doc > Summary: Document of libvirt-php > Group: Development/Libraries/PHP > +BuildArch: noarch > Requires: libvirt-php = %{version} > > %description -n libvirt-php-doc Good to change this to be noarch since docs are not architecture dependent. Thanks a lot for your patch. ACKed and pushed by: Michal Novotny Thanks, Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From wency at cn.fujitsu.com Tue Apr 19 09:29:08 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Tue, 19 Apr 2011 17:29:08 +0800 Subject: [libvirt] [PATCHv10 1/6] libvirt/qemu - clean up for qemudDomainAt(de)tachDevice(Flags) In-Reply-To: <20110419164034.9c8a82e3.kamezawa.hiroyu@jp.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> <20110419164034.9c8a82e3.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4DAD55E4.4090400@cn.fujitsu.com> At 04/19/2011 03:40 PM, KAMEZAWA Hiroyuki Write: > > Centralize device modification in the more flexible APIs, to allow > future honoring of additional flags. Explicitly reject the > VIR_DOMAIN_DEVICE_MODIFY_FORCE flag on attach/detach. > > Based on Eric Blake's work. > > From: Eric Blake > Signed-off-by: KAMEZAWA Hiroyuki > > * src/qemu/qemu_driver.c (qemudDomainAttachDevice) > (qemudDomainAttachDeviceFlags): Swap bodies, and rename... Hmm, you do not rename the function(qemudDomainAttachDevice ===> qemuDomainAttachDevice) > (qemuDomainAttachDevice, qemuDomainAttachDeviceFlags): to this. Hmm, it may be update not attach here. > (qemudDomainDetachDevice, qemudDomainDetachDeviceFlags): Missing 'Likewise.' > --- > src/qemu/qemu_driver.c | 53 ++++++++++++++++++++++++++--------------------- > 1 files changed, 29 insertions(+), 24 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index f6e503a..a8f3849 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -3786,8 +3786,8 @@ cleanup: > } > > > -static int qemudDomainAttachDevice(virDomainPtr dom, > - const char *xml) > +static int qemudDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, > + unsigned int flags) > { > struct qemud_driver *driver = dom->conn->privateData; > virDomainObjPtr vm; > @@ -3796,6 +3796,14 @@ static int qemudDomainAttachDevice(virDomainPtr dom, > virCgroupPtr cgroup = NULL; > int ret = -1; > > + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | > + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > + qemuReportError(VIR_ERR_OPERATION_INVALID, > + "%s", _("cannot modify the persistent configuration of a domain")); > + return -1; > + } > + > qemuDriverLock(driver); > vm = virDomainFindByUUID(&driver->domains, dom->uuid); > if (!vm) { > @@ -3943,16 +3951,10 @@ cleanup: > return ret; > } > > -static int qemudDomainAttachDeviceFlags(virDomainPtr dom, > - const char *xml, > - unsigned int flags) { > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > - qemuReportError(VIR_ERR_OPERATION_INVALID, > - "%s", _("cannot modify the persistent configuration of a domain")); > - return -1; > - } > - > - return qemudDomainAttachDevice(dom, xml); > +static int qemudDomainAttachDevice(virDomainPtr dom, const char *xml) > +{ > + return qemudDomainAttachDeviceFlags(dom, xml, > + VIR_DOMAIN_DEVICE_MODIFY_LIVE); > } > > > @@ -4078,14 +4080,23 @@ cleanup: > } > > > -static int qemudDomainDetachDevice(virDomainPtr dom, > - const char *xml) { > +static int qemudDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, > + unsigned int flags) > +{ > struct qemud_driver *driver = dom->conn->privateData; > virDomainObjPtr vm; > virBitmapPtr qemuCaps = NULL; > virDomainDeviceDefPtr dev = NULL; > int ret = -1; > > + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE| > + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); > + > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > + qemuReportError(VIR_ERR_OPERATION_INVALID, > + "%s", _("cannot modify the persistent configuration of a domain:")); > + return -1; > + } > qemuDriverLock(driver); > vm = virDomainFindByUUID(&driver->domains, dom->uuid); > if (!vm) { > @@ -4164,16 +4175,10 @@ cleanup: > return ret; > } > > -static int qemudDomainDetachDeviceFlags(virDomainPtr dom, > - const char *xml, > - unsigned int flags) { > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > - qemuReportError(VIR_ERR_OPERATION_INVALID, > - "%s", _("cannot modify the persistent configuration of a domain")); > - return -1; > - } > - > - return qemudDomainDetachDevice(dom, xml); > +static int qemudDomainDetachDevice(virDomainPtr dom, const char *xml) > +{ > + return qemudDomainDetachDeviceFlags(dom, xml, > + VIR_DOMAIN_DEVICE_MODIFY_LIVE); > } > > static int qemudDomainGetAutostart(virDomainPtr dom, From berrange at redhat.com Tue Apr 19 09:33:44 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 10:33:44 +0100 Subject: [libvirt] [PATCH 6/6] qemu, inject-nmi: Implement the driver methods In-Reply-To: <4DACC121.8030108@redhat.com> References: <4DA52D1A.1000307@cn.fujitsu.com> <4DA52E3E.10402@cn.fujitsu.com> <4DA88ADE.7050208@redhat.com> <4DABF8C7.4060804@cn.fujitsu.com> <4DACC121.8030108@redhat.com> Message-ID: <20110419093344.GA11901@redhat.com> On Mon, Apr 18, 2011 at 04:54:25PM -0600, Eric Blake wrote: > On 04/18/2011 02:39 AM, Lai Jiangshan wrote: > >>> +int qemuMonitorTextInjectNMI(qemuMonitorPtr mon, unsigned int flags ATTRIBUTE_UNUSED) > >>> +{ > >>> + const char *cmd = "nmi 0"; > >>> + char *reply = NULL; > >>> + > >>> + /* > >>> + * FIXME: qemu's nmi command just injects NMI to a specified CPU, > >>> + * use "nmi 0" instead temporary. > >>> + */ > >> > >> This bothers me. Is it possible to inject NMI to a particular CPU in > >> bare-metal hardware? If so, then we ought to support that in the API. > >> > > > > The real world NMI button just sends NMI to all cpus, the qemu side code will > > also be modified that hmp nmi command just sends NMI to all CPU and > > the cpu-index parameter will be removed. > > > > My original qemu side patch lefts cpu-index parameter for kernel debugging, > > but the qemu guys persuade me that inject-nmi command should just send NMI > > to CPUs. I accepted it. I think the libvirt will handle it at the same way. > > Makes sense, and matches with what I learned on a google search about > the "NMI button" on real hardware. Thus, the real fixme is that qemu's > nmi command has a bogus argument during preliminary patch review that > will be going away before inject-nmi is made official, and therefore, > libvirt should just be sending "nmi" and not "nmi 0" once there is a > released version of qemu that actually supports injecting NMI, and you > are right that the API should not expose a vcpu parameter. > > Any timeframe on when a released qemu might support nmi injection, or > even a pointer to a URL where the qemu patch stream is under discussion? > It doesn't make too much sense to push this patch into libvirt until we > are reasonably sure that the qemu interface is well-baked, to minimize > needing later libvirt tweaks. QEMU has included an HMP command for NMI for quite a while. We're only arguing upstream about the QMP version of it. We could take this patch with the HMP command any time we like, but it would be nice to have a little more clarity about what's going to happen to the QMP version in qemu-devel. We don't have to wait for a new QEMU release, but in ideal world we'd see them accept Lai's QMP patches into GIT. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Tue Apr 19 09:34:50 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 10:34:50 +0100 Subject: [libvirt] [PATCH] qemu: fix the check of virDomainObjUnref()'s return value In-Reply-To: <4DACEE95.40400@cn.fujitsu.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1CED.20202@cn.fujitsu.com> <4DA75CD7.9080908@redhat.com> <4DA7B76B.3010308@cn.fujitsu.com> <4DA873FA.8080009@redhat.com> <20110418114123.GG4648@redhat.com> <4DACEE95.40400@cn.fujitsu.com> Message-ID: <20110419093450.GB11901@redhat.com> On Tue, Apr 19, 2011 at 10:08:21AM +0800, Wen Congyang wrote: > If vm is unlocked in virDomainObjUnref(), the return value is 0, not less > than 0. > > --- > src/qemu/qemu_process.c | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c > index 1dfd005..7691cbe 100644 > --- a/src/qemu/qemu_process.c > +++ b/src/qemu/qemu_process.c > @@ -433,7 +433,7 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > */ > virDomainObjRef(vm); > if (virThreadPoolSendJob(driver->workerPool, wdEvent) < 0) { > - if (virDomainObjUnref(vm) < 0) > + if (virDomainObjUnref(vm) == 0) > vm = NULL; > VIR_FREE(wdEvent); ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Tue Apr 19 09:41:56 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 10:41:56 +0100 Subject: [libvirt] [virt-tools-list] [PATCH DISCUSSION ONLY] Add inspection thread to virt-manager. In-Reply-To: <4DACBDDF.6070003@redhat.com> References: <20110418170146.GA485@amd.home.annexia.org> <4DACB209.9090101@redhat.com> <20110418221242.GM2641@amd.home.annexia.org> <4DACBDDF.6070003@redhat.com> Message-ID: <20110419094156.GC11901@redhat.com> On Mon, Apr 18, 2011 at 06:40:31PM -0400, Cole Robinson wrote: > On 04/18/2011 06:12 PM, Richard W.M. Jones wrote: > > On Mon, Apr 18, 2011 at 05:50:01PM -0400, Cole Robinson wrote: > >> First, thanks a lot for the patch! I'm sure everyone will be glad to see > >> libguestfs integration in virt-manager. > >> > >>> [This patch is incomplete and just for discussion] > >>> > >>> Using libguestfs inspection[1], we can find out a lot about a virtual > >>> machine, such as what operating system is installed, the OS version, > >>> the OS distro, the hostname, the (real) disk usage, what apps are > >>> installed, and lots more. It would be nice if virt-manager could use > >>> this information: for example we could change the generic "computer" > >>> icon into a Windows or Fedora logo if Windows or Fedora was installed > >>> in the virtual machine. > >>> > >> > >> That icon bit was originally intended for the current design, but since we've > >> never really tracked OS info after install time, it never came about. > >> > >> Particularly for OS type/version tracking, I think we need a few things: > >> > >> - Everything standardize on some naming scheme, ideally libosinfo (though > >> nothing is using it yet :/ ). libosinfo could also distribute the OS icons > > > > We sort of got bored of waiting for that train. We have a primitive > > but rather effective system in libguestfs, which I explain at the end > > of this email. > > > > Yeah I hear you on that. However, for the libguestfs OS value to really be > useful for us in virt-manager, we have to map it to the virtinst osdict which > informs us of all the preferred device defaults (like virtio, usb tablet, > virtio console, etc.). Which means more energy that would be better spent on > getting libosinfo integrated. Yep, it is way overdue to integrate that work. > >> - Libvirt domain XML schema is extended with a field to track the > >> installed OS. For most libvirt drivers this would just be metadata > >> (vmware/esx the exception). Even though the data might be out of > >> date if the guest is upgraded, I think it has become clear that > >> there is a lot of value in tracking this in XML. > > > > Yes, I agree. This also solves the persistence problem. > > > > It's a bit of a shame that the field in the libvirt XML > > isn't structured, at least so that different applications could store > > their own data there without it being trampled upon by users or other > > applications. (CC'd to libvir-list in case they have any thoughts > > about that). > > > > I think is fine the way it is, there is always going to be a use > case for an end user freeform field like that. But there is certainly a case > for a similar field (or multiple fields) for recording more metadata, possibly > for use by apps. Maybe something with XML namespaces. We could easily define a element and a bunch of specific fields within it, and also setup some way to parse & preserve app specific metadata there. The main issue is finding a way to support it for all hypervisors. For QEMU, LXC, UML & XenLight we can do it because the master config file is our XML. For XenD, VMWare, VirutalBox we use the native config file. If they have a generic description field, we could steal that and store the XML in that and re-parse. Or something. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Tue Apr 19 10:48:55 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 11:48:55 +0100 Subject: [libvirt] [PATCHv2 1/6] virNodeGetCPUTime: Expose new API In-Reply-To: <20110408203312.90723b75.usui@mxm.nes.nec.co.jp> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> <20110408203312.90723b75.usui@mxm.nes.nec.co.jp> Message-ID: <20110419104855.GD11901@redhat.com> On Fri, Apr 08, 2011 at 08:33:12PM +0900, Minoru Usui wrote: > virNodeGetCPUTime: Expose new API > > Signed-off-by: Minoru Usui > --- > include/libvirt/libvirt.h.in | 64 ++++++++++++++++++++++++++++++++++++++++++ > src/libvirt_public.syms | 5 +++ > 2 files changed, 69 insertions(+), 0 deletions(-) > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > index bd36015..154c138 100644 > --- a/include/libvirt/libvirt.h.in > +++ b/include/libvirt/libvirt.h.in > @@ -228,6 +228,57 @@ struct _virNodeInfo { > unsigned int threads;/* number of threads per core */ > }; > > +/** > + * virNodeCpuTime: > + * > + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing > + * the information for the cpu time of the node. > + */ > + > +/** > + * Cpu Time Statistics Tags: > + */ > +typedef enum { > + /* > + * The cumulative CPU time which spends by kernel, > + * when the node booting up.(in nanoseconds). > + */ > + VIR_NODE_CPU_TIME_KERNEL = 0, > + /* > + * The cumulative CPU time which spends by user processes, > + * when the node booting up.(in nanoseconds). > + */ > + VIR_NODE_CPU_TIME_USER = 1, > + /* > + * The cumulative idle CPU time, > + * when the node booting up.(in nanoseconds). > + */ > + VIR_NODE_CPU_TIME_IDLE = 2, > + /* > + * The cumulative I/O wait CPU time, > + * when the node booting up.(in nanoseconds). > + */ > + VIR_NODE_CPU_TIME_IOWAIT = 3, > + /* > + * The CPU utilization. > + * The usage value is in percent and 100% represents all CPUs on > + * the server. > + */ > + VIR_NODE_CPU_TIME_UTILIZATION = 4, > + > + /* > + * The number of statistics supported by this version of the interface. > + * To add new statistics, add them to the enum and increase this value. > + */ > + VIR_NODE_CPU_TIME_NR = 5, > +} virNodeCpuTimeTags; > + > +typedef struct _virNodeCpuTime virNodeCpuTime; > + > +struct _virNodeCpuTime { > + virNodeCpuTimeTags tag; > + unsigned long long val; > +}; I've just remembered that the virSchedParameter, virMemoryParameter and virBlkioParameter structs all use a string to represent the data value, rather than an enum. I wonder if we ought todo the same here. eg, something like #define VIR_NODE_CPUE_FIELD_LENGTH 80 struct _virNodeCpuParameter { char field[VIR_NODE_CPU_FIELD_LENGTH] unsigned long long value; }; They also have a union for returning different data types, beyond just 'unsigned long long' but I think that might be overkill here. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Tue Apr 19 10:53:31 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 11:53:31 +0100 Subject: [libvirt] [PATCHv2 3/6] virNodeGetCPUTime: Implement public API In-Reply-To: <20110408203512.44ba817c.usui@mxm.nes.nec.co.jp> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> <20110408203512.44ba817c.usui@mxm.nes.nec.co.jp> Message-ID: <20110419105330.GE11901@redhat.com> On Fri, Apr 08, 2011 at 08:35:12PM +0900, Minoru Usui wrote: > virNodeGetCPUTime: Implement public API > > Signed-off-by: Minoru Usui > --- > src/libvirt.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 70 insertions(+), 0 deletions(-) > > diff --git a/src/libvirt.c b/src/libvirt.c > index 8be18d4..a65bfc6 100644 > --- a/src/libvirt.c > +++ b/src/libvirt.c > @@ -4260,6 +4260,76 @@ error: > } > > /** > + * virNodeGetCpuTime: > + * @stats: nr_stats-sized array of stat structures (returned) > + * @nr_stats: number of cpu time statistics requested of the node. > + * @flags: unused, always pass 0 > + * > + * This function provides cpu time statistics of the node. > + * > + * Up to 'nr_stats' elements of 'stats' will be populated with cpu time statistics > + * of the node. Only statistics supported by the driver, and this version of > + * libvirt will be returned. > + * > + * Cpu time Statistics: > + * > + * VIR_NODE_CPU_TIME_KERNEL: > + * The cumulative CPU time which spends by kernel, > + * when the node booting up.(nanoseconds) > + * VIR_NODE_CPU_TIME_USER: > + * The cumulative CPU time which spends by user processes, > + * when the node booting up.(nanoseconds) > + * VIR_NODE_CPU_TIME_IDLE: > + * The cumulative idle CPU time, when the node booting up.(nanoseconds) > + * VIR_NODE_CPU_TIME_IOWAIT: > + * The cumulative I/O wait CPU time, when the node booting up.(nanoseconds) > + * VIR_NODE_CPU_TIME_UTILIZATION: > + * The CPU utilization. The usage value is in percent and 100% > + * represents all CPUs on the server. > + * > + * Returns: The number of stats provided or -1 in case of failure. > + */ > +int virNodeGetCpuTime (virConnectPtr conn, virNodeCpuTimePtr stats, > + unsigned int nr_stats, unsigned int flags) > +{ > + unsigned long nr_stats_ret = 0; This ought to have been an 'int' to match the function return type, and better to declare it later in the block where it was first used. > + > + VIR_DEBUG("conn=%p, stats=%p, nr_stats=%u", conn, stats, nr_stats); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECT (conn)) { > + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); > + virDispatchError(NULL); > + return 0; > + } > + > + if (flags != 0) { > + virLibConnError(VIR_ERR_INVALID_ARG, _("flags must be zero")); > + goto error; > + } Instead of this, use the standard macro we have: virCheckFlags(flags, 0); > + if (!stats || nr_stats == 0) > + return 0; > + > + if (nr_stats > VIR_NODE_CPU_TIME_NR) > + nr_stats = VIR_NODE_CPU_TIME_NR; If we're following the pattern of virDomainGetMemoryParameters/BlkioParameters then we should have passed in a pointer to nr_stats. It would be allowed to be zero, in which case the hypervisor would initialize it with the required size for the number of parameters. eg, the signature would be int virNodeGetCpuParameters(virConnectPtr conn, virNodeCpuParameterPtr params, int *nparams, unsigned int flags) and then check if ((nparams == NULL) || (*nparams < 0)) { virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } > + > + if (conn->driver->nodeGetCpuTime) { > + nr_stats_ret = conn->driver->nodeGetCpuTime (conn, stats, nr_stats, flags); > + if (nr_stats_ret == -1) > + goto error; > + return nr_stats_ret; > + } > + > + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + virDispatchError(conn); > + return -1; > +} > + > +/** Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Tue Apr 19 10:58:00 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 11:58:00 +0100 Subject: [libvirt] [PATCHv2 4/6] virNodeGetCPUTime: Implement remote protocol In-Reply-To: <20110408203602.7765f701.usui@mxm.nes.nec.co.jp> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> <20110408203602.7765f701.usui@mxm.nes.nec.co.jp> Message-ID: <20110419105800.GF11901@redhat.com> On Fri, Apr 08, 2011 at 08:36:02PM +0900, Minoru Usui wrote: > virNodeGetCPUTime: Implement remote protocol > > Signed-off-by: Minoru Usui > --- > daemon/remote.c | 48 +++++++++++++++++++++++++++++++++++ > daemon/remote_dispatch_args.h | 1 + > daemon/remote_dispatch_prototypes.h | 8 ++++++ > daemon/remote_dispatch_ret.h | 1 + > daemon/remote_dispatch_table.h | 5 +++ > src/remote/remote_driver.c | 37 +++++++++++++++++++++++++++ > src/remote/remote_protocol.c | 33 ++++++++++++++++++++++++ > src/remote/remote_protocol.h | 28 ++++++++++++++++++++ > src/remote/remote_protocol.x | 20 ++++++++++++++- > src/remote_protocol-structs | 14 ++++++++++ > 10 files changed, 194 insertions(+), 1 deletions(-) > > diff --git a/daemon/remote.c b/daemon/remote.c > index 1700c2d..a6c21eb 100644 > --- a/daemon/remote.c > +++ b/daemon/remote.c > @@ -679,6 +679,54 @@ remoteDispatchGetCapabilities (struct qemud_server *server ATTRIBUTE_UNUSED, > } > > static int > +remoteDispatchNodeGetCpuTime (struct qemud_server *server ATTRIBUTE_UNUSED, > + struct qemud_client *client ATTRIBUTE_UNUSED, > + virConnectPtr conn, > + remote_message_header *hdr ATTRIBUTE_UNUSED, > + remote_error *rerr, > + remote_node_get_cpu_time_args *args, > + remote_node_get_cpu_time_ret *ret) > +{ > + struct _virNodeCpuTime *stats; > + unsigned int nr_stats, i; > + > + if (args->maxStats > REMOTE_NODE_CPU_TIME_MAX) { > + remoteDispatchFormatError (rerr, "%s", > + _("maxStats > REMOTE_NODE_CPU_TIME_MAX")); > + return -1; > + } > + > + /* Allocate stats array for making dispatch call */ > + if (VIR_ALLOC_N(stats, args->maxStats) < 0) { > + remoteDispatchOOMError(rerr); > + return -1; > + } > + > + nr_stats = virNodeGetCpuTime (conn, stats, args->maxStats, 0); > + if (nr_stats == -1) { > + VIR_FREE(stats); > + remoteDispatchConnError(rerr, conn); > + return -1; > + } > + > + /* Allocate return buffer */ > + if (VIR_ALLOC_N(ret->stats.stats_val, args->maxStats) < 0) { > + VIR_FREE(stats); > + remoteDispatchOOMError(rerr); > + return -1; > + } > + > + /* Copy the stats into the xdr return structure */ > + for (i = 0; i < nr_stats; i++) { > + ret->stats.stats_val[i].tag = stats[i].tag; > + ret->stats.stats_val[i].val = stats[i].val; > + } > + ret->stats.stats_len = nr_stats; > + VIR_FREE(stats); > + return 0; > +} I recently re-structured all the APIs in this file, to follow a new coding style. This method would need to be updated to match. { virNodeCpuTime *stats = NULL; int nr_stats, i; int rv = -1; if (args->maxStats > REMOTE_NODE_CPU_TIME_MAX) { virNetError (VIR_ERR_INTERNAL_ERROR, "%s", _("maxStats > REMOTE_NODE_CPU_TIME_MAX")); goto cleanup; } /* Allocate stats array for making dispatch call */ if (VIR_ALLOC_N(stats, args->maxStats) < 0) { virReportOOMError(); goto cleanup; } if ((nr_stats = virNodeGetCpuTime (conn, stats, args->maxStats, 0)) < 0) goto cleanup; /* Allocate return buffer */ if (VIR_ALLOC_N(ret->stats.stats_val, args->maxStats) < 0) { virReportOOMError(); goto cleanup; } /* Copy the stats into the xdr return structure */ for (i = 0; i < nr_stats; i++) { ret->stats.stats_val[i].tag = stats[i].tag; ret->stats.stats_val[i].val = stats[i].val; } ret->stats.stats_len = nr_stats; rv = 0; cleanup: if (rv < 0) remoteDispatchError(rerr); VIR_FREE(stats); return rv; } Of course, if we change the public API as I suggest, it'll need a couple more changes too. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Tue Apr 19 11:01:34 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 12:01:34 +0100 Subject: [libvirt] [PATCHv2 5/6] virNodeGetCPUTime: Implement virsh support In-Reply-To: <20110408203652.eb88d49c.usui@mxm.nes.nec.co.jp> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> <20110408203652.eb88d49c.usui@mxm.nes.nec.co.jp> Message-ID: <20110419110134.GG11901@redhat.com> On Fri, Apr 08, 2011 at 08:36:52PM +0900, Minoru Usui wrote: > virNodeGetCPUTime: Implement virsh support > > Add nodecputime subcommand to virsh. > This subcommand prints below output. > > [Linux] > # build/tools/virsh nodecputime > usage: 2.8% > user : 0.8% > system: 1.9% > idle : 97.2% > iowait: 0.0% > > [can get cpu utilization directly(ESX?)] > # build/tools/virsh nodecputime > usage: 2.8% > > Signed-off-by: Minoru Usui > --- > tools/virsh.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > tools/virsh.pod | 4 ++ > 2 files changed, 100 insertions(+), 0 deletions(-) > > diff --git a/tools/virsh.c b/tools/virsh.c > index 19e3449..93288ba 100644 > --- a/tools/virsh.c > +++ b/tools/virsh.c > @@ -3388,6 +3388,101 @@ cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) > } > > /* > + * "nodecputime" command > + */ > +static const vshCmdInfo info_nodecputime[] = { > + {"help", N_("Prints cpu utilizatoin of the node.")}, > + {"desc", N_("Returns cpu utilizatoin of the node.(%)")}, > + {NULL, NULL} > +}; > + > +static int > +cmdNodeCpuTime(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) > +{ > + int i, j; > + int flag_utilization = FALSE; > + virNodeCpuTime stats[VIR_NODE_CPU_TIME_NR]; > + int nr_stats; > + struct cpu_time { > + unsigned long long user; > + unsigned long long sys; > + unsigned long long idle; > + unsigned long long iowait; > + unsigned long long util; > + } cpu_time[2]; > + double user_time, sys_time, idle_time, iowait_time, total_time; > + double usage; > + > + if (!vshConnectionUsability(ctl, ctl->conn)) > + return FALSE; > + > + memset(cpu_time, 0, sizeof(struct cpu_time) * 2); > + > + for (i = 0; i < 2; i++) { > + memset(stats, 0, sizeof(virNodeCpuTime) * VIR_NODE_CPU_TIME_NR); > + nr_stats = virNodeGetCpuTime(ctl->conn, &stats[0], > + VIR_NODE_CPU_TIME_NR, 0); > + if (nr_stats < 0) { > + vshError(ctl, "%s", _("failed to get cpu time of the node.")); > + return FALSE; > + } > + > + for (j = 0; j < nr_stats; j++) { > + switch (stats[j].tag) { > + case VIR_NODE_CPU_TIME_KERNEL: > + cpu_time[i].sys = stats[j].val; > + break; > + case VIR_NODE_CPU_TIME_USER: > + cpu_time[i].user = stats[j].val; > + break; > + case VIR_NODE_CPU_TIME_IDLE: > + cpu_time[i].idle = stats[j].val; > + break; > + case VIR_NODE_CPU_TIME_IOWAIT: > + cpu_time[i].iowait = stats[j].val; > + break; > + case VIR_NODE_CPU_TIME_UTILIZATION: > + flag_utilization = TRUE; > + cpu_time[i].util = stats[j].val; > + break; > + case VIR_NODE_CPU_TIME_NR: > + default: > + break; > + } > + } > + > + sleep(1); > + } I'm not sure about this bit. In other places in virsh, we just report the absolute CPU time value, and don't try to calculate the deltas. There is a virt-top program that might like to use this data to provide a continuous display of utilization. Alternatively, we could add an arg for this to request that it calculate delta over 'n' seconds. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Tue Apr 19 11:29:05 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 12:29:05 +0100 Subject: [libvirt] [RFC][PATCHv1 2/5] libvirt - new API for getting percpu statistics of VM In-Reply-To: <20110415164303.455ab625.kamezawa.hiroyu@jp.fujitsu.com> References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> <20110415160452.63bd9216.kamezawa.hiroyu@jp.fujitsu.com> <20110415164303.455ab625.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110419112904.GI11901@redhat.com> On Fri, Apr 15, 2011 at 04:43:03PM +0900, KAMEZAWA Hiroyuki wrote: > On Fri, 15 Apr 2011 09:43:15 +0200 > Matthias Bolte wrote: > > > 2011/4/15 KAMEZAWA Hiroyuki : > > > Per (host) cpu activity of VMs are very insterested numbers > > > when running VMs on large SMPs. virt-top -1 mode tries to > > > provide the information. (But it's not implemented.) > > > > > > This patch adds a libvirt interface to get per cpu statistics > > > of each nodes. This patch just adds an interface and driver > > > entry points. So, > > > ?- doesn't include patches for python. > > > ?- doesn't include any driver. > > > > > > Following patches will add some drivers and codes for python. > > > > > > Signed-off-by: KAMEZAWA Hiroyuki > > > --- > > > ?include/libvirt/libvirt.h.in | ? 13 ++++++++++ > > > ?src/driver.h ? ? ? ? ? ? ? ? | ? ?6 ++++ > > > ?src/esx/esx_driver.c ? ? ? ? | ? ?1 + > > > ?src/libvirt.c ? ? ? ? ? ? ? ?| ? 55 ++++++++++++++++++++++++++++++++++++++++++ > > > ?src/libvirt_public.syms ? ? ?| ? ?4 +++ > > > ?src/libxl/libxl_driver.c ? ? | ? ?1 + > > > ?src/lxc/lxc_driver.c ? ? ? ? | ? ?1 + > > > ?src/openvz/openvz_driver.c ? | ? ?1 + > > > ?src/phyp/phyp_driver.c ? ? ? | ? ?1 + > > > ?src/qemu/qemu_driver.c ? ? ? | ? ?1 + > > > ?src/remote/remote_driver.c ? | ? ?1 + > > > ?src/test/test_driver.c ? ? ? | ? ?1 + > > > ?src/uml/uml_driver.c ? ? ? ? | ? ?1 + > > > ?src/vbox/vbox_tmpl.c ? ? ? ? | ? ?1 + > > > ?src/vmware/vmware_driver.c ? | ? ?1 + > > > ?src/xen/xen_driver.c ? ? ? ? | ? ?1 + > > > ?src/xenapi/xenapi_driver.c ? | ? ?1 + > > > ?17 files changed, 91 insertions(+), 0 deletions(-) > > > > > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > > > index 5783303..6b9292c 100644 > > > --- a/include/libvirt/libvirt.h.in > > > +++ b/include/libvirt/libvirt.h.in > > > @@ -400,6 +400,13 @@ struct _virDomainMemoryStat { > > > > > > ?typedef virDomainMemoryStatStruct *virDomainMemoryStatPtr; > > > > > > +typedef struct _virDomainPcpuStat virDomainPcpuStatStruct; > > > + > > > +struct _virDomainPcpuStat { > > > + ? ?unsigned long long cpuTime; > > > +}; > > > + > > > > NACK to adding another public struct to the API. > > Oh, yes. I searched a sutiable existing API but cannot found. > > Maybe adding new enum to Usui's work will be good but I need an array. > Hmm, returning an array of unsigned long long is ok ? > > > It's not expendable. > > As a stylistic nit pleas don't use the term PCPU as this looks like > > "Physical CPU". Just call it virDomainPerVcpuStat at least. > > > Ah, no, this is PerPhysicalStat > > > > Also do you really need the absolute CPU time? > yes, for virt-top -1. I don't think that is correct. What virt-top ultimately displays to the end user is a % utilization. So it would be happy to get data in either % util & display that directly, or get absolute CPU time and calculate deltas to display % util. I wonder if we could provide an API that could be used to provide either per-VCPU or per-PCPU statistics in one go, so that we can finally have an API for cpu time that works well for VMWare. eg typedef struct _virDomainCPUTime virDomainCPUTime; typedef virDomainCPUTime *virDomainCPUTimePtr; #define VIR_DOMAIN_CPUTIME_ABS "abs" #define VIR_DOMAIN_CPUTIME_UTIL "util" ...define more stats later if desired... struct _virDomainCPUTime { char field[VIR_DOMAIN_CPU_TIME_FIELD_LENGTH]; unsigned long long value; }; typedef enum { VIR_DOMAIN_CPU_TIME_VIRTUAL = 0, VIR_DOMAIN_CPU_TIME_PHYSICAL = 1, } virDomainCPUTimeFlags; int virDomainGetCPUTime(virDomainPtr dom, virDomainCPUTimePtr stats, int *nstats, unsigned int flags); When querying per-virtual CPU time, nstats would be the number of virtual CPUs in the guest. eg virDomainInfo info; virDomainGetInfo(dom, &info); virDomainCPUTimePtr stats; stats = malloc(sizeof(*stats)*info.nrVirtCPU); virDomainGetCPUTime(dom, stats, info.nrVirtCPU, VIR_DOMAIN_CPU_TIME_VIRTUAL); Or to get the break down per physical CPU, use the VIR_NODEINFO_MAX_CPUS macro virNodeInfo info; virNodeGetInfo(conn, &info); virDomainCPUTimePtr stats; stats = malloc(sizeof(*stats)*VIR_NODEINFO_MAX_CPUS(info)) virDomainGetCPUTime(dom, stats, VIR_NODEINFO_MAX_CPUS(info), VIR_DOMAIN_CPU_TIME_PHYSICAL); We could also allow 'nstats' to be 0, in which case the API would simply populate 'nstats' with the required number and return. The caller can then re-invoke with correct nstats and allocated memory. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Tue Apr 19 11:38:37 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 12:38:37 +0100 Subject: [libvirt] [PATCH 1/6] Add virObject and virAtomic. In-Reply-To: <20110407074915.GB7711@localhost.localdomain> References: <4D9CCAED.4040508@redhat.com> <20110407074915.GB7711@localhost.localdomain> Message-ID: <20110419113837.GA14373@redhat.com> On Thu, Apr 07, 2011 at 03:49:15PM +0800, Hu Tao wrote: > On Wed, Apr 06, 2011 at 02:19:57PM -0600, Eric Blake wrote: > > On 04/06/2011 01:19 AM, Hu Tao wrote: > > > virObject is the base struct that manages reference-counting > > > for all structs that need the ability of reference-counting. > > > > > > virAtomic provides atomic operations which are thread-safe. > > > --- > > > src/Makefile.am | 2 + > > > src/libvirt_private.syms | 5 ++++ > > > src/util/viratomic.c | 46 ++++++++++++++++++++++++++++++++++++++++ > > > src/util/viratomic.h | 30 ++++++++++++++++++++++++++ > > > src/util/virobject.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ > > > src/util/virobject.h | 39 ++++++++++++++++++++++++++++++++++ > > > 6 files changed, 174 insertions(+), 0 deletions(-) > > > create mode 100644 src/util/viratomic.c > > > create mode 100644 src/util/viratomic.h > > > create mode 100644 src/util/virobject.c > > > create mode 100644 src/util/virobject.h > > > > > +++ b/src/libvirt_private.syms > > > @@ -993,3 +993,8 @@ virXPathUInt; > > > virXPathULong; > > > virXPathULongHex; > > > virXPathULongLong; > > > + > > > +# object.h > > > > virobject.h, and float this section to appear before virtaudit.h (hmm, > > Oops, there are always things escape from under your nose:( > > > maybe we should do a preliminary patch to rename that to viraudit.h, so > > that we aren't mixing vir vs. virt in quite so many places). > > > > > +virObjectInit; > > > +virObjectRef; > > > +virObjectUnref; > > > > Missing exports from viratomic.h. > > Why the linker doesn't complain about this this time? > > > > > > diff --git a/src/util/viratomic.c b/src/util/viratomic.c > > > new file mode 100644 > > > index 0000000..629f189 > > > --- /dev/null > > > +++ b/src/util/viratomic.c > > > @@ -0,0 +1,46 @@ > > > > > + > > > +#ifdef WIN32 > > > +long virAtomicInc(long *value) > > > +{ > > > + return InterlockedIncrement(value); > > > +} > > > + > > > +long virAtomicDec(long *value) > > > +{ > > > + return InterlockedDecrement(value); > > > > This is an OS-specific replacement. > > > > > +} > > > +#else /* WIN32 */ > > > +long virAtomicInc(long *value) > > > +{ > > > + return __sync_add_and_fetch(value, 1); > > > > This is a gcc builtin, and will fail to compile with other C99 > > Yes. > > > compilers. Meanwhile, won't the gcc builtin just work for mingw (that > > Not sure about this. I don't have a mingw environment to test, but I > trust gcc and guess it does. > > > is, no need to use the OS-specific InterlockedIncrement if you have the > > compiler builtin instead). > > > > I think this file needs three implementations: > > > > #if defined __GNUC__ || > > use compiler builtins of __sync_add_and_fetch > > #elif defined WIN32 > > use OS primitives, like InterlockedIncrement > > #else > > we're hosed when it comes to lightweight versions, but we can still > > implement a heavyweight replacement that uses virMutex > > #endif > > Agreed, this is a better way. > > > > > > +++ b/src/util/viratomic.h > > > @@ -0,0 +1,30 @@ > > > > > +#ifndef __VIR_ATOMIC_H > > > +#define __VIR_ATOMIC_H > > > + > > > +long virAtomicInc(long *value); > > > +long virAtomicDec(long *value); > > > > Mark both of these ATTRIBUTE_NONNULL(1) > > OK. > > > > > I'm debating whether they should also be marked ATTRIBUTE_RETURN_CHECK > > No, there are cases you just want to inc/dec a value but do not check > the modified value. > > > > > > +++ b/src/util/virobject.c > > > @@ -0,0 +1,52 @@ > > > + > > > +#include "viratomic.h" > > > +#include "virobject.h" > > > +#include "logging.h" > > > + > > > +int virObjectInit(virObjectPtr obj, void (*free)(virObjectPtr obj)) > > > > You should declare a typedef: > > > > typedef void (*virObjectFreer)(virObjectPtr); > > > > then it becomes simpler to read: > > > > int virObjectInit(virObjectPtr obj, virObjectFreer f) > > > > Use a different name (I used freer/f above) to avoid -Wshadow warnings > > with free(). > > OK. > > > > > > +{ > > > + if (!free) { > > > > Especially since shadowing means it's impossible to tell if this > > statement is always true (the address of free() exists) or conditional > > (there is a local variable named free shadowing the global function), > > and context-sensitive code reviews are tougher :) > > > > > + VIR_ERROR0("method free is required."); > > > + return -1; > > > + } > > > > Should this function also check and return -1 if obj->free was not NULL > > on entry (that is, guarantee that you can't initialize an object twice)? > > Agreed. And it is dangerous to initialize an object more than once > because the ref count may already changed and a second initializaton > just do the wrong thing. > > > > > > + > > > + obj->ref = 1; > > > + obj->free = free; > > > + > > > + return 0; > > > +} > > > + > > > +void virObjectRef(virObjectPtr obj) > > > +{ > > > + sa_assert(obj->ref > 0); > > > > This is useless. It only helps static analyzers (like clang), > > > > > + virAtomicInc(&obj->ref); > > > > but there's nothing to analyze that depends on knowing the value was > > positive. > > > > I'm debating whether to do checking. Maybe we should do: > > > > if (virAtomicInc(&obj->ref) < 2) > > This means bad things happened, and it is not enough to just give a > warning. Think about this: > > two threads visit an object whose memory is corrupted that it's ref > count becomes 0 but it doesn't get freed. > > thread 1: thread 2: > > ref the object > (ref count becomes 1) > > unref the object > (ref count becomes 0, object being > freed) > > do something with > the object, but it > is already freed by > thread 2 > > We should catch abnormal ref count by some way(if not sa_assert) > > > VIR_WARN("invalid call to virObjectRef"); > > > > > +void virObjectUnref(virObjectPtr obj) > > > +{ > > > + sa_assert(obj->ref > 0); > > > > Again, I'm not sure that this buys anything. But we may want to do: > > > > int ref = virAtomicDec(&obj->ref); > > if (ref < 0) > > VIR_WARN("invalid call to virObjectUnref"); > > else if (ref == 0) > > obj->free(obj) > > > > > + if (virAtomicDec(&obj->ref) == 0) > > > + obj->free(obj); > > > +} > > > diff --git a/src/util/virobject.h b/src/util/virobject.h > > > new file mode 100644 > > > index 0000000..cd7d3e8 > > > --- /dev/null > > > +++ b/src/util/virobject.h > > > > > + > > > +typedef struct _virObject virObject; > > > +typedef virObject *virObjectPtr; > > > + > > > +struct _virObject { > > > + long ref; > > > + void (*free)(virObjectPtr obj); > > > > Is virObjectPtr the right thing to use here? If we assume that all > > clients will always have a virObjectPtr as their first member, then they > > can cast that back into the larger object. Is void* opaque any better, > > Exactly the way(you have already saw my other patches when I was typing > this:)) > > > although that then it requires a third parameter for virObjectInit? > > Maybe it's worth some documentation on intended use in this header (am I > > OK. > > > getting this usage right? I haven't looked at how you used it later in > > the series, but am just guessing): > > > > struct _virFoo { > > virObject obj; /* Must be first member */ > > ... > > }; > > static void virFooFree(virObjectPtr obj) > > { > > virFooPtr foo = obj; > > ... > > } > > virFooPtr virFooNew(void) > > { > > virFooPtr foo; > > if (VIR_ALLOC(foo) < 0) { > > virReportOOMError(); > > return NULL; > > } > > virObjectInit(&foo->obj, virFooFree); > > ... > > return foo; > > } > > > > > > > +}; > > > + > > > +int virObjectInit(virObjectPtr obj, void (*free)(virObjectPtr obj)); > > > > ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK > > > > > +void virObjectRef(virObjectPtr obj); > > > > ATTRIBUTE_NONNULL(1) > > > > Also, should this return the current reference count? Not all callers > > will need it, but returning void is harsh if someone might be able to > > use it. > > No. It is meaningless to return the current reference count, because it > may already changed by others after the caller reads the returned value > on which it is not safe to make some choice. I wondered if you had an updated copy of this single patch, with the changes from this discussion included ? Even though we're still debating the rest of this patch series, I'd like us to commit this first virAtomic / virObject patch, so I can use it in some other code I have waiting. So if you are able to re-post just this first virObject patch that would be very helpful Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From jdenemar at redhat.com Tue Apr 19 13:22:07 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 19 Apr 2011 15:22:07 +0200 Subject: [libvirt] [PATCH] tests: More unit tests for internal hash APIs In-Reply-To: <0ebc29ed7078c909b92f692d28c572f0c05ff9b9.1302629114.git.jdenemar@redhat.com> References: <0ebc29ed7078c909b92f692d28c572f0c05ff9b9.1302629114.git.jdenemar@redhat.com> Message-ID: This adds several tests for remaining hash APIs (custom hasher/comparator functions are not covered yet, though). All tests pass both before and after the "Simplify hash implementation". --- src/util/hash.c | 18 +++ src/util/hash.h | 1 + tests/hashdata.h | 237 +++++++++++++++++++++++++++++++++++- tests/hashtest.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 615 insertions(+), 2 deletions(-) diff --git a/src/util/hash.c b/src/util/hash.c index fc7652d..5dbc7f1 100644 --- a/src/util/hash.c +++ b/src/util/hash.c @@ -499,6 +499,24 @@ virHashSize(virHashTablePtr table) } /** + * virHashTableSize: + * @table: the hash table + * + * Query the size of the hash @table, i.e., number of keys in the table. + * + * Returns the number of keys in the hash table or + * -1 in case of error + */ +int +virHashTableSize(virHashTablePtr table) +{ + if (table == NULL) + return -1; + return table->size; +} + + +/** * virHashRemoveEntry: * @table: the hash table * @name: the name of the userdata diff --git a/src/util/hash.h b/src/util/hash.h index 44ac1fb..7583abc 100644 --- a/src/util/hash.h +++ b/src/util/hash.h @@ -103,6 +103,7 @@ virHashTablePtr virHashCreateFull(int size, virHashKeyFree keyFree); void virHashFree(virHashTablePtr table); int virHashSize(virHashTablePtr table); +int virHashTableSize(virHashTablePtr table); /* * Add a new entry to the hash table. diff --git a/tests/hashdata.h b/tests/hashdata.h index 2782255..73c3572 100644 --- a/tests/hashdata.h +++ b/tests/hashdata.h @@ -1,24 +1,238 @@ const char *uuids[] = { +/* [ 2] */ "a9b02f96-e430-4f7c-a7ff-a647d080447a", +/* [ 4] */ "202e32ca-f82c-4f13-9266-28dc8d002074", +/* [ 5] */ "e0233ed8-22da-4a1e-a1a2-2d0343635173", + "4ce4f92a-e116-4c38-81ca-acebbdcab410", +/* [ 6] */ "4121c24d-bfc3-45f9-85c6-899679b5cc60", + "e641740a-85dd-4414-bdbf-37dbaee39e26", +/* [ 9] */ "a0c94fa8-7d41-4100-8907-9b9209e7954a", +/* [ 10] */ "d3c7d973-046d-4c49-90bb-7a353aaea8a2", + "ad15e406-8258-49ad-a47e-cbb955b34220", +/* [ 11] */ "0979803b-6bcc-4305-917c-079dcc0f1cb4", +/* [ 12] */ "0311fc3f-e5b1-48f5-ab9e-e577fbfc6b82", +/* [ 14] */ "512aa755-3c48-456b-9545-3cc6f729444f", +/* [ 16] */ "43b7e89e-c5cb-44c6-9bdb-7f070d6e5cf7", +/* [ 17] */ "3e4fd85d-57d8-4d1d-867e-71ba3b898dc3", +/* [ 18] */ "8433c800-1cda-4bf1-8a3d-879f657e0068", +/* [ 20] */ "fb55ed30-a8fe-44ab-aa25-4d609c487975", +/* [ 21] */ "b7fa38f1-f329-430d-8450-57d75175f578", +/* [ 22] */ "bbbff7ba-73d8-42a0-ace3-dbf39906223a", +/* [ 23] */ "1ef274ef-2c99-488f-ba25-21da0285d7fe", +/* [ 26] */ "24e30027-16cf-4848-a4be-6dffae973757", +/* [ 28] */ "fd056c9c-9f39-43b8-90be-aaff3909a56c", +/* [ 29] */ "2c53a1dc-3b62-4369-a583-71cad3d1fa98", + "063b19c7-1c96-4cc8-ac18-bc007f073a13", +/* [ 32] */ "f210da80-6e0a-4185-a96e-7bd32a779e72", +/* [ 33] */ "dd557d13-0f6d-460a-8002-9392ce483e50", +/* [ 34] */ "d16f07e4-f5be-4744-b70a-dc6e26666c44", +/* [ 35] */ "dafe133f-d48c-4a30-b156-f073725401f5", +/* [ 36] */ "96dfe074-7236-4898-aad2-81963c23adda", + "c971ea2e-9410-4b3c-9027-d678a0d9db8d", +/* [ 38] */ "7b417156-b90a-4450-9c77-e1e94e1c980c", +/* [ 39] */ "a7334316-6572-47d5-9330-9a3e70c30c6d", +/* [ 40] */ "1e33c931-ef3a-497f-9374-6d9dddf04893", + "ebc4d160-4418-41cd-bd2f-0ef2741ffafb", +/* [ 41] */ "6e13dd0b-67f8-447c-8445-9b8476a2e556", +/* [ 42] */ "6123a5df-4b0b-421e-8dcb-4ecb3b33113d", +/* [ 44] */ "75fc3921-558b-4093-82ba-e9807551de84", +/* [ 45] */ "3308bc39-5d59-4ae8-8e45-bc1607a5d5d3", + "ad064af6-e55a-4de9-95b8-6a0afc77ad81", /* [ 46] */ "f17494ba-2353-4af0-b1ba-13680858edcc", "64ab4e78-1b6e-4b88-b47f-2def46c79a86", "f99b0d59-ecff-4cc6-a9d3-20159536edc8", +/* [ 48] */ "a697613f-349b-41f8-80c5-f416ee462ca2", +/* [ 52] */ "e9af1e6f-016d-43f3-8890-a33d924b4368", + "4e5c715a-4f37-4260-ae33-a86bc97f2a69", +/* [ 54] */ "ae82cd8a-d67a-4fc7-9323-06511cbe9f4d", + "32d7a14c-4138-459e-aa19-5263d4a6b410", +/* [ 56] */ "9aba27ea-37e4-485c-983c-42de92c2d2ea", +/* [ 59] */ "45826b95-3120-417b-a5ff-5480e342f25e", + "834a24b7-5c77-4287-9266-82c2f2c9e9fc", +/* [ 62] */ "d4d09671-8132-4809-badf-efbef39c9dac", +/* [ 66] */ "b0bd3bd8-1271-4755-84e7-e89fabb929b2", +/* [ 69] */ "86e2a115-3e5b-480e-9109-12ac4b525761", +/* [ 70] */ "2896d83a-ede2-4a01-8047-25a0db868b27", +/* [ 71] */ "1f290a52-51ad-4ea6-ae11-b90c50ba8ea6", +/* [ 72] */ "511b890f-d9f5-4fb4-90d4-39e93719c4bf", +/* [ 74] */ "51bf1c00-6c0a-4ca4-8acc-1ab9c6bc44ce", /* [ 75] */ "e1bfa30f-bc0b-4a24-99ae-bed7f3f21a7b", "acda5fa0-58de-4e1e-aa65-2124d1e29c54", /* [ 76] */ "5f476c28-8f26-48e0-98de-85745fe2f304", +/* [ 79] */ "4a1f1b60-4c53-4525-b687-f0175b6e19bc", +/* [ 80] */ "608bcc5e-5ccc-4967-a58f-4d61665685bc", + "b7028f70-6d4d-4d0a-8c78-ec61fd6e38fc", +/* [ 81] */ "03cc8179-3b0e-4c9f-a665-9ca416ee0e9b", +/* [ 83] */ "2f32ba02-7a07-46e0-b859-a7b82a5de8e0", +/* [ 85] */ "490b8a1b-4d7a-4d14-81c3-af6c4824632f", +/* [ 88] */ "48e8c968-c1b7-4b3b-a24a-abb94604758b", +/* [ 89] */ "242fd86e-d804-4b7e-9a92-b8227becdb91", +/* [ 90] */ "13315204-76aa-4ae6-9f27-44434facea60", +/* [ 91] */ "548544c8-1737-4efe-8661-4783e4b6ef12", +/* [ 92] */ "3e6f26ce-ddb3-485c-86ca-b455fcfb802a", +/* [ 93] */ "a6b1df31-2f3f-4314-87f9-fd794aad8d5a", + "bce3d144-820d-489b-8506-f04fdea2ee48", +/* [ 95] */ "e400060d-4de7-4c12-9533-a9aa4296c44c", +/* [ 96] */ "9a0a6b84-7263-46d3-a45e-ad9e7b61a109", + "a9734665-e800-4c99-96ec-dd0426e20b00", +/* [ 97] */ "d3efc444-1758-4733-9cfb-50412ba7cf79", + "999edbf0-b194-43aa-87ed-afc2ae0fe30b", +/* [ 98] */ "e866d6bf-2e7c-4f97-8178-1ca758020d2c", +/* [ 99] */ "87b97bc3-62d1-465d-94a8-7ae22efd8103", +/* [100] */ "050d33f5-e7b1-42e8-a253-292b2769069a", + "1b5fff42-37dc-4770-9a41-6df2fe4b7858", + "d6a4b1a3-6c19-46e1-90b9-2de3ef471eb3", +/* [101] */ "51e8e981-dd6a-4e85-a6b4-ed60d38a72ac", +/* [102] */ "7f62af6b-3954-4a7a-9b32-721d770da3d8", + "8016379a-9905-43cb-a6bd-98fc83296982", + "e003782c-fcec-449a-a0e4-cda41893e78f", +/* [103] */ "954d5d6a-98b6-45ad-a95c-85721664b1ea", +/* [105] */ "ccd3680a-d8ac-4f68-ac08-a7b59f31af10", +/* [106] */ "cded8a5d-874c-4400-86a4-eb483cfe0265", +/* [109] */ "356df5ef-c744-4696-a697-91f4634c8559", +/* [110] */ "faee6c44-f212-4c8a-8e8c-bea91fb26532", +/* [113] */ "84377685-45f9-4c89-ad4f-5776f6ffcff4", +/* [116] */ "b69c50ec-2bd3-4162-bca3-eec4398f2d12", + "fb5e4a60-efdb-4884-bb9e-ac911b1b5100", + "d59a5c99-5ce5-46bf-8a80-cdf916f71576", +/* [117] */ "c09322ef-0b70-4ea0-922b-95832bb5469c", +/* [118] */ "47e88680-4f46-4096-9f77-1bd4e271acd5", +/* [119] */ "570d5f36-31e6-412b-84dd-e5aabb73dd5b", + "56cf0509-741a-4a5c-a82c-51060f009b9a", +/* [122] */ "c257b495-e53c-4be5-8b05-491057531120", + "654139f2-cef5-48df-a6b2-6ca6e9abb1de", /* [123] */ "8be1d21c-cd35-4c7c-8fee-4b5046c7a62b", "830f0d57-9f21-40e8-bb86-cbf41de23fd6", "57044958-1b8a-4c02-ab75-2298c6e44263", "d526cd6c-4a99-4d5f-abfb-fc9419edd9d0", +/* [124] */ "36492c15-ce5a-4f9b-b75a-97937981f9b4", + "66a984a9-cd04-4683-b241-2b296da662bc", + "0b3404eb-022b-4ef1-a78d-a2b12230b258", +/* [125] */ "f8d7efcf-1138-422b-a844-feffa7478be8", +/* [130] */ "4f8ca175-6efa-476e-ab58-11efe9211415", +/* [131] */ "87fcc2e2-0b65-4eaa-8bea-74de85abf3fe", + "ea0d108f-8a39-414a-88c6-fcabce029af7", + "b1f17225-efb3-4b8a-aae3-a2ca53eeb99e", + "45dcb41d-0628-485f-9f14-3296410555a5", +/* [133] */ "a2b16b3f-93df-4d5a-a226-5f340bf2b0a3", +/* [140] */ "373025da-238a-467f-8164-b5675cfe6422", +/* [141] */ "8969aa50-6d2b-4659-ade1-b4a2169e0ed1", +/* [142] */ "ba092226-be95-4ec2-8c35-215db61448e6", +/* [143] */ "4213fb5a-6d28-4296-85a6-bb149a0468b7", +/* [144] */ "05bd2d12-1062-46c3-9ac2-362617175b04", +/* [145] */ "97cff77b-9f8d-40e9-8c41-601dc280a413", + "4d05b973-b30b-4416-bdd8-e3773b30cb6e", + "95382996-dfce-483d-8ff8-1d05c6c65bb5", +/* [146] */ "04213584-d98a-4e82-a884-1238a7568c48", +/* [148] */ "68bad966-22ec-4e87-9c6c-c1dd000959c4", + "f1b44f04-2028-4855-ad6c-9538ef6e44a2", +/* [149] */ "8748c9ae-624d-4fb1-a3d3-5073716c882c", +/* [150] */ "e0eb4d5b-d251-41c9-9215-0e2830413fe4", + "426795e5-a6e2-4b42-a81d-41cddb79f9b6", + "a16297c6-e9f4-49c4-b244-4e2ae2803ce3", +/* [151] */ "ea07d3ec-4f35-41db-afd2-4bc2b3273e0f", + "f013f77d-8bd8-4a8e-82e9-82512071ac0f", +/* [152] */ "754038bd-c382-4605-b53d-600f165aac10", +/* [156] */ "06575e79-74dd-46c1-a752-de53b8bf8987", +/* [158] */ "00a14b42-e60e-4214-9de1-9ff187a67e6e", +/* [159] */ "93d02eb8-325b-42cc-b1b6-435eeb6e0449", +/* [163] */ "f9e5528e-52ec-4164-8b4d-0b25a4715ce6", +/* [166] */ "f1a3af6e-b8c3-4836-95da-3c4b740dab80", +/* [169] */ "81af0cbf-b3c5-49b9-ae04-bf93e493943f", +/* [170] */ "ab7bd5e5-68cc-4a04-9773-e668bf1d5e55", +/* [172] */ "55ff86fa-2fc0-46c1-a222-3b9bfef434be", +/* [174] */ "ed7dda66-4ec3-438b-8444-5f998528c7c1", +/* [175] */ "3929d8b1-f6f7-44f6-8366-8ccc6d6c8dae", +/* [178] */ "455a7a4c-1602-453b-9729-03c040ba1ed7", + "6e68d708-26c3-45db-ae71-52c0ef0e3879", +/* [179] */ "c6be4f40-aad8-4be5-bc50-e8bb9217e988", +/* [181] */ "550e511b-3105-485f-8856-593761339f08", +/* [182] */ "dea7c93f-a9e5-4622-9da5-0959f2561e33", +/* [183] */ "705c2f9b-08d2-4502-b53e-0b01db35acd3", + "819c7473-898f-439b-935d-fe4a96f64150", +/* [185] */ "8c1fc53f-7867-4399-8c6c-a6e4b128a9f8", +/* [187] */ "a1bf2aed-639d-4e1b-9aa3-6b7be8a49c59", +/* [188] */ "4e92f93d-4667-414e-a7bf-b42d33bc409e", + "4013ec51-05a8-479b-9d5a-8f1149039e34", + "796ec0f2-b9f9-4a9e-ac8e-1ce726eef88c", +/* [189] */ "7328ee55-9cd2-4f37-ac3c-630287a65f7c", + "225d01da-9bbd-4cb1-b892-fd8a4a604c76", +/* [190] */ "97fd798d-94a7-4089-aaf6-50919d105c4c", + "cb792c37-7cd2-4649-ab92-180fef7b9911", +/* [191] */ "7edcabaa-70f7-447d-9bb8-95537cd48b0d", +/* [192] */ "df3348bf-5eda-480a-9a3b-c26eb9df3d80", +/* [193] */ "854b565d-0ea7-40b3-ba41-054e2d4e1869", + "079d9a35-331e-489d-b153-493ca28fe95c", +/* [194] */ "589778f4-cca0-4969-a27c-ccd29b2d35f0", +/* [195] */ "e0505dd6-3f2c-4ac1-8d93-41fb021af558", +/* [196] */ "ab8be1c6-18f4-4ecb-a115-8d839dba1bd0", +/* [197] */ "7dab18d4-4fc6-451f-9558-0b719bb2ecec", +/* [200] */ "f9c10e12-877a-4750-a697-d39691443c54", + "a5be8e6c-7d4c-48aa-b457-22168cf56ddf", + "72160964-cd58-4a01-bdbf-7f5151975ffe", +/* [202] */ "84d91759-4a70-4bc3-808d-24a8fc4c0816", + "fad2acc3-ebda-490c-9698-06cd6690b924", + "17191452-f402-47a0-b3e9-ae3e5688a534", +/* [203] */ "f328382f-2706-4a0b-aac8-b9ffed687997", + "5cbd8451-cc3e-4dc4-bd3b-0033d8c869ff", +/* [204] */ "704436e1-e9b3-4269-813a-a1c6a425cb4d", +/* [206] */ "80748ed5-3d42-4d95-ba21-30b071ac17ad", + "bb3f3be2-2ab7-48fb-b71b-45041b732887", +/* [207] */ "ae45b5a6-ea00-4e0c-948a-ebf3c84dfd01", + "10363e09-d2e0-40a5-afce-0fdf852222d7", +/* [209] */ "777174f9-d80c-46f9-9fe8-5d59c93abd64", + "5c75455b-4317-4285-818f-3ffc165b05f9", + "dc708225-bcb0-447b-99ca-4291d717a600", +/* [210] */ "1dc43c46-ff0a-4527-9b01-34dde0abf4b8", + "559813cd-ba6f-446f-af56-224170d39cce", + "3c1c7283-78e1-4082-a191-d2eeed51d7fd", +/* [212] */ "1cda8175-d221-452a-8aad-e96d2da674ed", +/* [213] */ "751bcb18-2235-4bb9-b320-36551c3e8810", +/* [214] */ "fe3a9c52-6058-4203-9fa0-6c657852026c", +/* [215] */ "29fb462f-6975-41b0-b6fa-c2556a658a68", +/* [216] */ "c0f80985-d1cc-4ea6-839e-02e52b33623f", + "404e1b0c-5e34-4419-818e-6707b8f90248", + "34d224fc-9803-4da5-a08e-4b49e5d24592", +/* [217] */ "2977ad89-0ec8-4f60-8228-1b82a65a7c7c", + "b954246e-29cf-4792-ae60-b841e5710111", +/* [218] */ "b54ede2a-70af-4a63-9d17-410ba5ee6c0c", +/* [219] */ "b2baf136-de10-48ca-ae6b-0f802acbf09c", +/* [220] */ "e55df82c-2128-43bf-a681-e626a2c4d1c3", + "67338b47-c2f1-4f73-956c-4b54e427e6e4", +/* [221] */ "450cca9c-38f6-4eb8-b537-190fc3fff99d", +/* [222] */ "6b4ccebf-e741-4a54-97a4-20ac92c18107", +/* [225] */ "3a7ea080-fb0b-4ef3-b005-5b9e2aa931a2", + "78d7fc2b-883d-48b1-9896-bf660ca0fe5a", + "f12574f2-452c-4363-90a1-eeaa353936d6", +/* [226] */ "1ae1d3f8-974e-47a7-8f26-a105766fc24d", +/* [227] */ "9f2506cf-4aea-4c47-8897-f6b83ba814fb", +/* [228] */ "125dba5c-b19a-4218-928f-553788c02637", +/* [229] */ "5c7eb444-84c1-4a3b-8385-ccf4c6632dc3", +/* [232] */ "5c2dfc36-cf78-4718-acf4-c2823c95054a", + "b6442198-b321-4f0d-9fdb-c12115831875", + "0cf5fc99-c43f-4a36-837a-b3bad7902cb8", +/* [233] */ "b3631261-7322-405d-bb14-245bf29e729c", + "2cc98dd0-5ae1-4a01-b2fd-7e1074bc9110", + "3c6a9e1c-0425-4af3-aef8-d4e336fe4397", +/* [235] */ "2f52aab9-c383-4ac6-b1e1-c317198a3105", + "b06bf0b1-0b05-42ed-b79e-4770671c90e2", /* [237] */ "3ab39f7f-4613-4da6-a216-c2d6acc441bb", "ae20cf3c-38b8-483c-baea-6fb0994dc30c", "cd204d90-2414-4b9e-9d4f-fed09c9a816f", /* [240] */ "ed2cc723-db4b-43aa-ab02-0e3161087499", +/* [241] */ "9cc96bd6-0ca0-466a-b897-e11eb7540b07", +/* [244] */ "8d45a51f-a945-4de1-b89c-2b39d1a5b90e", +/* [245] */ "6cd02e53-40ac-4269-91c9-4e1088af91f1", /* [246] */ "8ada85bc-9bdf-4507-8334-849635ea0a01", "8a7d5deb-615f-4cd3-8977-b5fab8ec4d05", /* [247] */ "dc2173b0-48fe-4555-b190-8052be1120eb", "040e434d-68d8-41a9-b3a1-1bee239914c1", "d1a564b2-c7f3-4b76-8712-3b8f5aae6ded", - "0e614f33-c1da-4cfe-b6d5-65ecd2d066f2" + "0e614f33-c1da-4cfe-b6d5-65ecd2d066f2", +/* [250] */ "334fdaba-f373-42ff-8546-219c1463a7c5", + "d4ff408e-8d43-46ff-94a4-bcfa6c994776", +/* [253] */ "d1abd887-d5de-46b0-88d6-f71f31a61305", +/* [254] */ "1d76af65-64d6-4211-b1b5-f5b799595e4d", +/* [255] */ "b3ad4257-29b0-4c44-b7a7-95f1d102769c" }; const char *uuids_subset[] = { @@ -29,5 +243,24 @@ const char *uuids_subset[] = { "ae20cf3c-38b8-483c-baea-6fb0994dc30c", "040e434d-68d8-41a9-b3a1-1bee239914c1", "d1a564b2-c7f3-4b76-8712-3b8f5aae6ded", - "8ada85bc-9bdf-4507-8334-849635ea0a01" + "8ada85bc-9bdf-4507-8334-849635ea0a01", + "97cff77b-9f8d-40e9-8c41-601dc280a413", + "4d05b973-b30b-4416-bdd8-e3773b30cb6e", + "95382996-dfce-483d-8ff8-1d05c6c65bb5", +}; + +const char *uuids_new[] = { + "a103cc42-d0e5-40fb-8f7f-3c1bee93e327", + "01e13dc5-e65b-4988-a0cc-0d2f1f1e10fe", + "71f3678a-a8c6-4176-a26e-c34779067135", + "4f054508-22d5-49e1-9962-7508225c8b16", + "e572116b-5b7b-45fd-bbe9-296029ce16b5", + "695c8cfe-9830-4d9a-be67-50a124cefb76", + "ea244996-645b-4a19-ad4a-48f3022b8e94", + "0fd98758-9cc4-4779-b403-95ae3500f138", + "b86772b4-0728-46ae-99e8-027799697838", + "1c0cd559-81cd-4c27-8e24-6aef6f5af7f1", + "2a37fe4a-8825-4fd6-9284-e1606967548a", + "5920cc9d-62a3-4772-9e73-eb97f0bc483c", + "53c215dd-bdba-4fdc-887a-86ab6f860df4" }; diff --git a/tests/hashtest.c b/tests/hashtest.c index dff0181..e8eb091 100644 --- a/tests/hashtest.c +++ b/tests/hashtest.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "internal.h" #include "hash.h" @@ -31,12 +32,32 @@ testHashInit(int size) * collision list in the same order as in the uuids array */ for (i = ARRAY_CARDINALITY(uuids) - 1; i >= 0; i--) { + int oldsize = virHashTableSize(hash); if (virHashAddEntry(hash, uuids[i], (void *) uuids[i]) < 0) { virHashFree(hash); return NULL; } + + if (virHashTableSize(hash) != oldsize && virTestGetDebug()) { + fprintf(stderr, "\nhash grown from %d to %d", + oldsize, virHashTableSize(hash)); + } + } + + for (i = 0; i < ARRAY_CARDINALITY(uuids); i++) { + if (!virHashLookup(hash, uuids[i])) { + if (virTestGetVerbose()) { + fprintf(stderr, "\nentry \"%s\" could not be found\n", + uuids[i]); + } + virHashFree(hash); + return NULL; + } } + if (size && size != virHashTableSize(hash) && virTestGetDebug()) + fprintf(stderr, "\n"); + return hash; } @@ -60,6 +81,101 @@ struct testInfo { }; +static int +testHashGrow(const void *data) +{ + const struct testInfo *info = data; + virHashTablePtr hash; + int ret = -1; + + if (!(hash = testHashInit(info->count))) + return -1; + + if (testHashCheckCount(hash, ARRAY_CARDINALITY(uuids)) < 0) + goto cleanup; + + ret = 0; + +cleanup: + virHashFree(hash); + return ret; +} + + +static int +testHashUpdate(const void *data ATTRIBUTE_UNUSED) +{ + int count = ARRAY_CARDINALITY(uuids) + ARRAY_CARDINALITY(uuids_new); + virHashTablePtr hash; + int i; + int ret = -1; + + if (!(hash = testHashInit(0))) + return -1; + + for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) { + if (virHashUpdateEntry(hash, uuids_subset[i], (void *) 1) < 0) { + if (virTestGetVerbose()) { + fprintf(stderr, "\nentry \"%s\" could not be updated\n", + uuids_subset[i]); + } + goto cleanup; + } + } + + for (i = 0; i < ARRAY_CARDINALITY(uuids_new); i++) { + if (virHashUpdateEntry(hash, uuids_new[i], (void *) 1) < 0) { + if (virTestGetVerbose()) { + fprintf(stderr, "\nnew entry \"%s\" could not be updated\n", + uuids_new[i]); + } + goto cleanup; + } + } + + if (testHashCheckCount(hash, count) < 0) + goto cleanup; + + ret = 0; + +cleanup: + virHashFree(hash); + return ret; +} + + +static int +testHashRemove(const void *data ATTRIBUTE_UNUSED) +{ + int count = ARRAY_CARDINALITY(uuids) - ARRAY_CARDINALITY(uuids_subset); + virHashTablePtr hash; + int i; + int ret = -1; + + if (!(hash = testHashInit(0))) + return -1; + + for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) { + if (virHashRemoveEntry(hash, uuids_subset[i]) < 0) { + if (virTestGetVerbose()) { + fprintf(stderr, "\nentry \"%s\" could not be removed\n", + uuids_subset[i]); + } + goto cleanup; + } + } + + if (testHashCheckCount(hash, count) < 0) + goto cleanup; + + ret = 0; + +cleanup: + virHashFree(hash); + return ret; +} + + const int testHashCountRemoveForEachSome = ARRAY_CARDINALITY(uuids) - ARRAY_CARDINALITY(uuids_subset); @@ -96,6 +212,32 @@ testHashRemoveForEachAll(void *payload ATTRIBUTE_UNUSED, } +const int testHashCountRemoveForEachForbidden = ARRAY_CARDINALITY(uuids); + +static void +testHashRemoveForEachForbidden(void *payload ATTRIBUTE_UNUSED, + const void *name, + void *data) +{ + virHashTablePtr hash = data; + int i; + + for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) { + if (STREQ(uuids_subset[i], name)) { + int next = (i + 1) % ARRAY_CARDINALITY(uuids_subset); + + if (virHashRemoveEntry(hash, uuids_subset[next]) == 0 && + virTestGetVerbose()) { + fprintf(stderr, + "\nentry \"%s\" should not be allowed to be removed", + uuids_subset[next]); + } + break; + } + } +} + + static int testHashRemoveForEach(const void *data) { @@ -130,6 +272,209 @@ cleanup: static int +testHashSteal(const void *data ATTRIBUTE_UNUSED) +{ + int count = ARRAY_CARDINALITY(uuids) - ARRAY_CARDINALITY(uuids_subset); + virHashTablePtr hash; + int i; + int ret = -1; + + if (!(hash = testHashInit(0))) + return -1; + + for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) { + if (!virHashSteal(hash, uuids_subset[i])) { + if (virTestGetVerbose()) { + fprintf(stderr, "\nentry \"%s\" could not be stolen\n", + uuids_subset[i]); + } + goto cleanup; + } + } + + if (testHashCheckCount(hash, count) < 0) + goto cleanup; + + ret = 0; + +cleanup: + virHashFree(hash); + return ret; +} + + +static void +testHashIter(void *payload ATTRIBUTE_UNUSED, + const void *name ATTRIBUTE_UNUSED, + void *data ATTRIBUTE_UNUSED) +{ + return; +} + +static void +testHashForEachIter(void *payload ATTRIBUTE_UNUSED, + const void *name ATTRIBUTE_UNUSED, + void *data) +{ + virHashTablePtr hash = data; + + if (virHashAddEntry(hash, uuids_new[0], NULL) == 0 && + virTestGetVerbose()) { + fprintf(stderr, "\nadding entries in ForEach should be forbidden"); + } + + if (virHashUpdateEntry(hash, uuids_new[0], NULL) == 0 && + virTestGetVerbose()) { + fprintf(stderr, "\nupdating entries in ForEach should be forbidden"); + } + + if (virHashSteal(hash, uuids_new[0]) != NULL && + virTestGetVerbose()) { + fprintf(stderr, "\nstealing entries in ForEach should be forbidden"); + } + + if (virHashSteal(hash, uuids_new[0]) != NULL && + virTestGetVerbose()) { + fprintf(stderr, "\nstealing entries in ForEach should be forbidden"); + } + + if (virHashForEach(hash, testHashIter, NULL) >= 0 && + virTestGetVerbose()) { + fprintf(stderr, "\niterating through hash in ForEach" + " should be forbidden"); + } +} + +static int +testHashForEach(const void *data ATTRIBUTE_UNUSED) +{ + virHashTablePtr hash; + int count; + int ret = -1; + + if (!(hash = testHashInit(0))) + return -1; + + count = virHashForEach(hash, testHashForEachIter, hash); + + if (count != ARRAY_CARDINALITY(uuids)) { + if (virTestGetVerbose()) { + testError("\nvirHashForEach didn't go through all entries," + " %d != %lu\n", + count, ARRAY_CARDINALITY(uuids)); + } + goto cleanup; + } + + ret = 0; + +cleanup: + virHashFree(hash); + return ret; +} + + +static int +testHashRemoveSetIter(const void *payload ATTRIBUTE_UNUSED, + const void *name, + const void *data) +{ + int *count = (int *) data; + bool rem = false; + int i; + + for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) { + if (STREQ(uuids_subset[i], name)) { + rem = true; + break; + } + } + + if (rem || rand() % 2) { + (*count)++; + return 1; + } else { + return 0; + } +} + +static int +testHashRemoveSet(const void *data ATTRIBUTE_UNUSED) +{ + virHashTablePtr hash; + int count = 0; + int rcount; + int ret = -1; + + if (!(hash = testHashInit(0))) + return -1; + + srand(time(NULL)); + + rcount = virHashRemoveSet(hash, testHashRemoveSetIter, &count); + + if (count != rcount) { + if (virTestGetVerbose()) { + testError("\nvirHashRemoveSet didn't remove expected number of" + " entries, %d != %u\n", + rcount, count); + } + goto cleanup; + } + + if (testHashCheckCount(hash, ARRAY_CARDINALITY(uuids) - count) < 0) + goto cleanup; + + ret = 0; + +cleanup: + virHashFree(hash); + return ret; +} + + +const int testSearchIndex = ARRAY_CARDINALITY(uuids_subset) / 2; + +static int +testHashSearchIter(const void *payload ATTRIBUTE_UNUSED, + const void *name, + const void *data ATTRIBUTE_UNUSED) +{ + return STREQ(uuids_subset[testSearchIndex], name); +} + +static int +testHashSearch(const void *data ATTRIBUTE_UNUSED) +{ + virHashTablePtr hash; + void *entry; + int ret = -1; + + if (!(hash = testHashInit(0))) + return -1; + + entry = virHashSearch(hash, testHashSearchIter, NULL); + + if (!entry || STRNEQ(uuids_subset[testSearchIndex], entry)) { + if (virTestGetVerbose()) { + testError("\nvirHashSearch didn't find entry '%s'\n", + uuids_subset[testSearchIndex]); + } + goto cleanup; + } + + if (testHashCheckCount(hash, ARRAY_CARDINALITY(uuids)) < 0) + goto cleanup; + + ret = 0; + +cleanup: + virHashFree(hash); + return ret; +} + + +static int mymain(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { @@ -148,8 +493,24 @@ mymain(int argc ATTRIBUTE_UNUSED, testHash ## cmd ## data, \ testHashCount ## cmd ## data) +#define DO_TEST_COUNT(name, cmd, count) \ + DO_TEST_FULL(name "(" #count ")", cmd, NULL, count) + +#define DO_TEST(name, cmd) \ + DO_TEST_FULL(name, cmd, NULL, -1) + + DO_TEST_COUNT("Grow", Grow, 1); + DO_TEST_COUNT("Grow", Grow, 10); + DO_TEST_COUNT("Grow", Grow, 42); + DO_TEST("Update", Update); + DO_TEST("Remove", Remove); DO_TEST_DATA("Remove in ForEach", RemoveForEach, Some); DO_TEST_DATA("Remove in ForEach", RemoveForEach, All); + DO_TEST_DATA("Remove in ForEach", RemoveForEach, Forbidden); + DO_TEST("Steal", Steal); + DO_TEST("Forbidden ops in ForEach", ForEach); + DO_TEST("RemoveSet", RemoveSet); + DO_TEST("Search", Search); return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.7.5.rc1 From berrange at redhat.com Tue Apr 19 13:41:13 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 14:41:13 +0100 Subject: [libvirt] [PATCH] Pull in gnulib fnmatch module Message-ID: <1303220473-31443-1-git-send-email-berrange@redhat.com> The libvirtd daemon uses fnmatch. Although we don't yet build it on Win32, we should use gnulib's fnmatch module to ensure portability to all platforms. * bootstrap.conf: Add fnmatch --- bootstrap.conf | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/bootstrap.conf b/bootstrap.conf index 293f86e..8db4e87 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -34,6 +34,7 @@ count-one-bits crypto/md5 dirname-lgpl fcntl-h +fnmatch func getaddrinfo gethostname -- 1.7.4.4 From berrange at redhat.com Tue Apr 19 13:45:50 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 14:45:50 +0100 Subject: [libvirt] [PATCH] Allow handshake with child process during startup In-Reply-To: <4D9A1C9C.3020501@redhat.com> References: <1301921731-32248-1-git-send-email-berrange@redhat.com> <4D9A1C9C.3020501@redhat.com> Message-ID: <20110419134550.GA31485@redhat.com> On Mon, Apr 04, 2011 at 01:31:40PM -0600, Eric Blake wrote: > On 04/04/2011 06:55 AM, Daniel P. Berrange wrote: > > Allow the parent process to perform a bi-directional handshake > > with the child process during fork/exec. The child process > > will fork and do its initial setup. Immediately prior to the > > exec(), it will stop & wait for a handshake from the parent > > process. The parent process will spawn the child and wait > > until the child reaches the handshake point. It will do > > whatever extra setup work is required, before signalling the > > child to continue. > > > > The implementation of this is done using two pairs of blocking > > pipes. The first pair is used to block the parent, until the > > child writes a single byte. Then the second pair pair is used > > to block the child, until the parent confirms with another > > single byte. > > How worried are we about the child not doing any async-unsafe actions if > it wishes to avoid deadlock? We've already previously identified this > as a bug (such as in our handling of malloc in the child), but it's > somewhat of a corner-case, and I'm not sure how invasive it will be to > fix properly; so I am okay if a fixed version of this patch goes in > while we still leave that larger issue open for thought. IMHO, this patch doesn't make the existing problem any worse. eg, if VIR_DEBUG was going to cause deadlock, it would have happened before we get as far this new code I'm adding. > > +++ b/src/util/command.c > > @@ -35,6 +35,11 @@ > > #include "files.h" > > #include "buf.h" > > > > +#include > > +#include > > "internal.h" guaranteed this one for us. Opps, yes. > > +#include > > +#include > > Why do we need this one? We're already using WIFEXITED and friends > without explicitly needing this header. I'll double check whether we need this. > > > @@ -1115,7 +1129,6 @@ virCommandRun(virCommandPtr cmd, int *exitstatus) > > return ret; > > } > > > > - > > /* > > * Perform all virCommand-specific actions, along with the user hook. > > */ > > Spurious whitespace change? > > > @@ -1125,12 +1138,61 @@ virCommandHook(void *data) > > virCommandPtr cmd = data; > > int res = 0; > > > > - if (cmd->hook) > > + if (cmd->hook) { > > + VIR_DEBUG("Run hook %p %p", cmd->hook, cmd->opaque); > > res = cmd->hook(cmd->opaque); > > + VIR_DEBUG("Done hook %d", res); > > This adds yet more calls to malloc() inside the child > > > + } > > if (res == 0 && cmd->pwd) { > > VIR_DEBUG("Running child in %s", cmd->pwd); > > ...but no worse than what we've already been doing. If VIR_DEBUG were > the only use of malloc() in the child, then it could just boil down to > conditionally compiling VIR_DEBUG statements where they can be turned on > for debugging the implementation, but compiled out later to avoid > deadlock (at least, I'm assuming that VIR_DEBUG uses malloc() to format > a timestamp prior to the message when posting to the circular buffer). In addition, VIR_DEBUG should be a no-op in normal operation. Only if someone raises the debug level significantly will it do work that triggers malloc & thus exposes the risk. > > res = chdir(cmd->pwd); > > + if (res < 0) { > > + virReportSystemError(errno, > > + _("Unable to change to %s"), cmd->pwd); > > + } > > + } > > + if (cmd->handshake) { > > + char c = res < 0 ? '0' : '1'; > > + int rv; > > + VIR_DEBUG("Notifying parent for handshake start on %d", cmd->handshakeWait[1]); > > + if (safewrite(cmd->handshakeWait[1], &c, sizeof(c)) != sizeof(c)) { > > Since c is char, sizeof(c) == 1 by definition. But I'm okay with you > spelling out the longer form. > > > + virReportSystemError(errno, "%s", _("Unable to notify parent process")); > > + return -1; > > + } > > + > > + /* On failure we pass the error message back to parent, > > + * so they don't have to dig through stderr logs > > + */ > > + if (res < 0) { > > + virErrorPtr err = virGetLastError(); > > + const char *msg = err ? err->message : > > + _("Unknown failure during hook execution"); > > Hmm, now that's a lot more use of malloc(), and not just in VIR_DEBUG() > calls. Code earlier that actually use virRaiseError would have already triggered malloc, so I still think this isn't making things any worse. > > + > > +void virCommandRequireHandshake(virCommandPtr cmd) > > +{ > > + if (pipe(cmd->handshakeWait) < 0) { > > NULL dereference if cmd had a previous failure. You need to guard with: > > if (!cmd || cmd->has_error) return; Opps, yeah. > > > + > > +int virCommandHandshakeWait(virCommandPtr cmd) > > +{ > > + char c; > > + int rv; > > + VIR_DEBUG("Wait for handshake on %d", cmd->handshakeWait[0]); > > Likewise. > > > + > > +int virCommandHandshakeNotify(virCommandPtr cmd) > > +{ > > + char c = '1'; > > + VIR_DEBUG("Notify handshake on %d", cmd->handshakeWait[0]); > > Likewise. > > > +++ b/src/util/command.h > > @@ -274,6 +274,11 @@ int virCommandRunAsync(virCommandPtr cmd, > > int virCommandWait(virCommandPtr cmd, > > int *exitstatus) ATTRIBUTE_RETURN_CHECK; > > > > +void virCommandRequireHandshake(virCommandPtr cmd); > > + > > +int virCommandHandshakeWait(virCommandPtr cmd); > > +int virCommandHandshakeNotify(virCommandPtr cmd); > > These last two could use ATTRIBUTE_RETURN_CHECK. All three could use > documentation. Ok. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From wencongyang at gmail.com Tue Apr 19 13:49:05 2011 From: wencongyang at gmail.com (Wen Congyang) Date: Tue, 19 Apr 2011 21:49:05 +0800 Subject: [libvirt] [PATCH] qemu: fix the check of virDomainObjUnref()'s return value In-Reply-To: <20110419093450.GB11901@redhat.com> References: <4D9C1BE7.3000200@cn.fujitsu.com> <4D9C1CED.20202@cn.fujitsu.com> <4DA75CD7.9080908@redhat.com> <4DA7B76B.3010308@cn.fujitsu.com> <4DA873FA.8080009@redhat.com> <20110418114123.GG4648@redhat.com> <4DACEE95.40400@cn.fujitsu.com> <20110419093450.GB11901@redhat.com> Message-ID: <4DAD92D1.7070303@gmail.com> ? 2011-4-19 17:34, Daniel P. Berrange ??: > On Tue, Apr 19, 2011 at 10:08:21AM +0800, Wen Congyang wrote: >> If vm is unlocked in virDomainObjUnref(), the return value is 0, not less >> than 0. >> >> --- >> src/qemu/qemu_process.c | 2 +- >> 1 files changed, 1 insertions(+), 1 deletions(-) >> >> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c >> index 1dfd005..7691cbe 100644 >> --- a/src/qemu/qemu_process.c >> +++ b/src/qemu/qemu_process.c >> @@ -433,7 +433,7 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, >> */ >> virDomainObjRef(vm); >> if (virThreadPoolSendJob(driver->workerPool, wdEvent)< 0) { >> - if (virDomainObjUnref(vm)< 0) >> + if (virDomainObjUnref(vm) == 0) >> vm = NULL; >> VIR_FREE(wdEvent); > > ACK Thanks, pushed. > > > Daniel From eblake at redhat.com Tue Apr 19 14:05:10 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 19 Apr 2011 08:05:10 -0600 Subject: [libvirt] [PATCH] Pull in gnulib fnmatch module In-Reply-To: <1303220473-31443-1-git-send-email-berrange@redhat.com> References: <1303220473-31443-1-git-send-email-berrange@redhat.com> Message-ID: <4DAD9696.80000@redhat.com> On 04/19/2011 07:41 AM, Daniel P. Berrange wrote: > The libvirtd daemon uses fnmatch. Although we don't yet build > it on Win32, we should use gnulib's fnmatch module to ensure > portability to all platforms. > > * bootstrap.conf: Add fnmatch > --- > bootstrap.conf | 1 + > 1 files changed, 1 insertions(+), 0 deletions(-) > > diff --git a/bootstrap.conf b/bootstrap.conf > index 293f86e..8db4e87 100644 > --- a/bootstrap.conf > +++ b/bootstrap.conf > @@ -34,6 +34,7 @@ count-one-bits > crypto/md5 > dirname-lgpl > fcntl-h > +fnmatch ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From stefanb at linux.vnet.ibm.com Tue Apr 19 14:25:19 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Tue, 19 Apr 2011 10:25:19 -0400 Subject: [libvirt] [PATCH] nwfilter: no support for direct type of interface Message-ID: <4DAD9B4F.6030708@linux.vnet.ibm.com> Ebtables filtering doesn't work on macvtap device. Remove support for direct type of interface. Signed-off-by: Stefan Berger --- docs/formatnwfilter.html.in | 2 -- src/conf/domain_conf.c | 1 - src/nwfilter/nwfilter_ebiptables_driver.c | 16 +--------------- 3 files changed, 1 insertion(+), 18 deletions(-) Index: libvirt-acl/src/conf/domain_conf.c =================================================================== --- libvirt-acl.orig/src/conf/domain_conf.c +++ libvirt-acl/src/conf/domain_conf.c @@ -2862,7 +2862,6 @@ virDomainNetDefParseXML(virCapsPtr caps, case VIR_DOMAIN_NET_TYPE_ETHERNET: case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_BRIDGE: - case VIR_DOMAIN_NET_TYPE_DIRECT: def->filter = filter; filter = NULL; def->filterparams = filterparams; Index: libvirt-acl/docs/formatnwfilter.html.in =================================================================== --- libvirt-acl.orig/docs/formatnwfilter.html.in +++ libvirt-acl/docs/formatnwfilter.html.in @@ -52,8 +52,6 @@
  • network
  • ethernet -- must be used in bridging mode
  • bridge
  • -
  • direct -- only protocols mac, arp, ip and ipv6 - can be filtered
  • The interface XML is used to reference a top-level filter. In the Index: libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_ebiptables_driver.c +++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c @@ -2357,7 +2357,7 @@ err_exit: */ static int ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED, - enum virDomainNetType nettype, + enum virDomainNetType nettype ATTRIBUTE_UNUSED, virNWFilterDefPtr nwfilter, virNWFilterRuleDefPtr rule, const char *ifname, @@ -2409,13 +2409,6 @@ ebiptablesCreateRuleInstance(virConnectP case VIR_NWFILTER_RULE_PROTOCOL_ICMP: case VIR_NWFILTER_RULE_PROTOCOL_IGMP: case VIR_NWFILTER_RULE_PROTOCOL_ALL: - if (nettype == VIR_DOMAIN_NET_TYPE_DIRECT) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, - _("'%s' protocol not support for net type '%s'"), - virNWFilterRuleProtocolTypeToString(rule->prtclType), - virDomainNetTypeToString(nettype)); - return 1; - } isIPv6 = 0; rc = iptablesCreateRuleInstance(nwfilter, rule, @@ -2433,13 +2426,6 @@ ebiptablesCreateRuleInstance(virConnectP case VIR_NWFILTER_RULE_PROTOCOL_SCTPoIPV6: case VIR_NWFILTER_RULE_PROTOCOL_ICMPV6: case VIR_NWFILTER_RULE_PROTOCOL_ALLoIPV6: - if (nettype == VIR_DOMAIN_NET_TYPE_DIRECT) { - virNWFilterReportError(VIR_ERR_OPERATION_FAILED, - _("'%s' protocol not support for net type '%s'"), - virNWFilterRuleProtocolTypeToString(rule->prtclType), - virDomainNetTypeToString(nettype)); - return 1; - } isIPv6 = 1; rc = iptablesCreateRuleInstance(nwfilter, rule, From eblake at redhat.com Tue Apr 19 14:25:38 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 19 Apr 2011 08:25:38 -0600 Subject: [libvirt] [PATCH] virsh: nuke use of TRUE and FALSE In-Reply-To: References: <1303166375-17129-1-git-send-email-eblake@redhat.com> Message-ID: <4DAD9B62.2020009@redhat.com> On 04/19/2011 12:23 AM, Matthias Bolte wrote: > 2011/4/19 Eric Blake : >> Gnulib already guarantees , so it is easier to just >> use the standardized spellings. >> >> * tools/virsh.c (vshCmdDef): Change callback to return real bool. >> (__vshControl): Change several fields to bool. >> (vshCommandOptBool): Change return type. >> All callers updated. >> * tools/Makefile.am (virsh-net-edit.c, virsh-pool-edit.c): >> Likewise. >> --- >> >> Mostly mechanical. >> >> tools/Makefile.am | 4 +- >> tools/virsh.c | 1674 ++++++++++++++++++++++++++--------------------------- >> 2 files changed, 835 insertions(+), 843 deletions(-) >> > > Looks good in general, but you missed some places for s/int/bool/. > Instead of pointing them out in the diff, here's a patch to be merged > into yours. > > ACK with the attached patch merged in. ACK to your additions, so I've pushed the combined patch. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From berrange at redhat.com Tue Apr 19 14:34:11 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 15:34:11 +0100 Subject: [libvirt] [PATCH] nwfilter: no support for direct type of interface In-Reply-To: <4DAD9B4F.6030708@linux.vnet.ibm.com> References: <4DAD9B4F.6030708@linux.vnet.ibm.com> Message-ID: <20110419143411.GL11901@redhat.com> On Tue, Apr 19, 2011 at 10:25:19AM -0400, Stefan Berger wrote: > Ebtables filtering doesn't work on macvtap device. Remove support > for direct type of interface. > > Signed-off-by: Stefan Berger > > --- > docs/formatnwfilter.html.in | 2 -- > src/conf/domain_conf.c | 1 - > src/nwfilter/nwfilter_ebiptables_driver.c | 16 +--------------- > 3 files changed, 1 insertion(+), 18 deletions(-) ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From danken at redhat.com Tue Apr 19 14:59:41 2011 From: danken at redhat.com (Dan Kenigsberg) Date: Tue, 19 Apr 2011 17:59:41 +0300 Subject: [libvirt] RFC: virInterface change transaction API In-Reply-To: <20110418165305.GL4648@redhat.com> References: <4D9F6279.6040806@laine.org> <20110414130302.GG24239@redhat.com> <20110418165305.GL4648@redhat.com> Message-ID: <20110419145940.GC22023@redhat.com> On Mon, Apr 18, 2011 at 05:53:05PM +0100, Daniel P. Berrange wrote: > On Thu, Apr 14, 2011 at 04:03:03PM +0300, Dan Kenigsberg wrote: > > On Fri, Apr 08, 2011 at 03:31:05PM -0400, Laine Stump wrote: > > > I've been asked to implement what some people have termed as a > > > "transaction-oriented" API for host interface configuration (ie > > > virInterface*()). > > > The basic intent is to allow rollback to a known-good config if > > > anything goes > > > wrong when changing around the host network config with virInterface*() > > > functions. > > > > > > The most straightforward way to achieve this is that prior to calling > > > virInterfaceDefine/virInterfaceUndefine, the current state of the > > > host's network configuration (ie the /etc/sysconfig/network-scripts/ifcfg-* > > > files in the case of Fedora and RHEL) would be saved off somewhere, and > > > kept around until we're sure the new config is good; once we know that, > > > we can just eliminate the backup. If, however, the user of virInterface*() > > > explicitly requests, we could copy the files back; alternately if the system > > > is rebooted without these known-good files being erased, we would assume > > > that something went wrong and restore the original config. > > > > > > As with all other virInterface functions, the details of all this will > > > be handled by netcf (and below), but since libvirt is the main consumer > > > of netcf, I figure this is the appropriate place to discuss how it > > > gets done, > > > so please let me know any opinions on any piece of this. I plan to start > > > the implementation "soon", as I want to be finished before the end of > > > May. > > > > I like the idea, and think that virtInterface* users will benefit from it. > > Few comments are inline. > > > > > > > > I see 3 layers to this: > > > > > > 1) libvirt > > > > > > At the libvirt layer, this feature just requires 3 new APIs, which > > > are directly passed through to netcf: > > > > > > virInterfaceChangeStart(virConnectPtr conn, unsigned int flags); > > > virInterfaceChangeCommit(virConnectPtr conn, unsigned int flags); > > > virInterfaceChangeRollback(virConnectPtr conn, unsigned int flags); > > > > > > For the initial implementation, these will be simple passthroughs > > > to similarly named netcf functions. (in the future, it would be > > > useful for the server side of libvirt to determine if client<->server > > > connectivity was lost due to the network changes, and automatically > > > tell netcf to do a rollback). > > > > When such a feature is added, we should make it dependent on FLAG_AUTO_ROLLBACK > > passed to ChangeStart. Higher levels on the management stack may want full > > controll over when rollback happens. > > I don't think a AUTO_ROLLBACK flag is sufficient. You'd almost certainly > want to pass some info such as hostname/port number to test, and perhaps > a test timeout in milliseconds, and perhaps a retry count. Yes, that's why I wanted complete control over auto rollback, when it is inroduced. > I suggest a > separate API that is invoked just after starting the TXN, to provide > auto-rollback data. > > Regards, > Daniel > -- > |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| > |: http://libvirt.org -o- http://virt-manager.org :| > |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| > |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From otubo at linux.vnet.ibm.com Tue Apr 19 15:34:08 2011 From: otubo at linux.vnet.ibm.com (Eduardo Otubo) Date: Tue, 19 Apr 2011 12:34:08 -0300 Subject: [libvirt] [PATCH] PHYP: Adding reboot domain function Message-ID: <1303227248-18738-1-git-send-email-otubo@linux.vnet.ibm.com> Adding reboot function for pHyp driver. --- src/phyp/phyp_driver.c | 35 ++++++++++++++++++++++++++++++++++- 1 files changed, 34 insertions(+), 1 deletions(-) diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index bb0e0ac..228751d 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -3384,6 +3384,39 @@ cleanup: } static int +phypDomainReboot(virDomainPtr dom) +{ + int result = -1; + ConnectionData *connection_data = dom->conn->networkPrivateData; + virConnectPtr conn = dom->conn; + LIBSSH2_SESSION *session = connection_data->session; + phyp_driverPtr phyp_driver = conn->privateData; + int system_type = phyp_driver->system_type; + char *managed_system = phyp_driver->managed_system; + int exit_status = 0; + char *ret = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + virBufferAddLit(&buf, "chsysstate"); + if (system_type == HMC) + virBufferVSprintf(&buf, " -m %s", managed_system); + virBufferVSprintf(&buf, + " -r lpar -o shutdown --id %d --immed --restart", + dom->id); + ret = phypExecBuffer(session, &buf, &exit_status, dom->conn, false); + + if (exit_status < 0) + goto cleanup; + + result = 0; + + cleanup: + VIR_FREE(ret); + + return result; +} + +static int phypDomainShutdown(virDomainPtr dom) { int result = -1; @@ -3707,7 +3740,7 @@ static virDriver phypDriver = { NULL, /* domainSuspend */ phypDomainResume, /* domainResume */ phypDomainShutdown, /* domainShutdown */ - NULL, /* domainReboot */ + phypDomainReboot, /* domainReboot */ phypDomainDestroy, /* domainDestroy */ NULL, /* domainGetOSType */ NULL, /* domainGetMaxMemory */ -- 1.7.1 From berrange at redhat.com Tue Apr 19 16:12:08 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 19 Apr 2011 17:12:08 +0100 Subject: [libvirt] [PATCH] Allow handshake with child process during startup Message-ID: <1303229528-19873-1-git-send-email-berrange@redhat.com> Allow the parent process to perform a bi-directional handshake with the child process during fork/exec. The child process will fork and do its initial setup. Immediately prior to the exec(), it will stop & wait for a handshake from the parent process. The parent process will spawn the child and wait until the child reaches the handshake point. It will do whatever extra setup work is required, before signalling the child to continue. The implementation of this is done using two pairs of blocking pipes. The first pair is used to block the parent, until the child writes a single byte. Then the second pair pair is used to block the child, until the parent confirms with another single byte. * src/util/command.c, src/util/command.h, src/libvirt_private.syms: Add APIs to perform a handshake --- src/libvirt_private.syms | 3 + src/util/command.c | 161 +++++++++++++++++++++++++++++++++++++++++++++- src/util/command.h | 22 ++++++ 3 files changed, 185 insertions(+), 1 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b787811..b91727a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -106,11 +106,14 @@ virCommandAddEnvString; virCommandClearCaps; virCommandDaemonize; virCommandFree; +virCommandHandshakeNotify; +virCommandHandshakeWait; virCommandNew; virCommandNewArgList; virCommandNewArgs; virCommandNonblockingFDs; virCommandPreserveFD; +virCommandRequireHandshake; virCommandRun; virCommandRunAsync; virCommandSetErrorBuffer; diff --git a/src/util/command.c b/src/util/command.c index 862a913..6213a3d 100644 --- a/src/util/command.c +++ b/src/util/command.c @@ -35,6 +35,8 @@ #include "files.h" #include "buf.h" +#include + #define VIR_FROM_THIS VIR_FROM_NONE #define virCommandError(code, ...) \ @@ -76,6 +78,10 @@ struct _virCommand { int *outfdptr; int *errfdptr; + bool handshake; + int handshakeWait[2]; + int handshakeNotify[2]; + virExecHook hook; void *opaque; @@ -107,6 +113,11 @@ virCommandNewArgs(const char *const*args) if (VIR_ALLOC(cmd) < 0) return NULL; + cmd->handshakeWait[0] = -1; + cmd->handshakeWait[1] = -1; + cmd->handshakeNotify[0] = -1; + cmd->handshakeNotify[1] = -1; + FD_ZERO(&cmd->preserve); FD_ZERO(&cmd->transfer); cmd->infd = cmd->outfd = cmd->errfd = -1; @@ -1125,12 +1136,61 @@ virCommandHook(void *data) virCommandPtr cmd = data; int res = 0; - if (cmd->hook) + if (cmd->hook) { + VIR_DEBUG("Run hook %p %p", cmd->hook, cmd->opaque); res = cmd->hook(cmd->opaque); + VIR_DEBUG("Done hook %d", res); + } if (res == 0 && cmd->pwd) { VIR_DEBUG("Running child in %s", cmd->pwd); res = chdir(cmd->pwd); + if (res < 0) { + virReportSystemError(errno, + _("Unable to change to %s"), cmd->pwd); + } + } + if (cmd->handshake) { + char c = res < 0 ? '0' : '1'; + int rv; + VIR_DEBUG("Notifying parent for handshake start on %d", cmd->handshakeWait[1]); + if (safewrite(cmd->handshakeWait[1], &c, sizeof(c)) != sizeof(c)) { + virReportSystemError(errno, "%s", _("Unable to notify parent process")); + return -1; + } + + /* On failure we pass the error message back to parent, + * so they don't have to dig through stderr logs + */ + if (res < 0) { + virErrorPtr err = virGetLastError(); + const char *msg = err ? err->message : + _("Unknown failure during hook execution"); + size_t len = strlen(msg) + 1; + if (safewrite(cmd->handshakeWait[1], msg, len) != len) { + virReportSystemError(errno, "%s", _("Unable to send error to parent process")); + return -1; + } + return -1; + } + + VIR_DEBUG("Waiting on parent for handshake complete on %d", cmd->handshakeNotify[0]); + if ((rv = saferead(cmd->handshakeNotify[0], &c, sizeof(c))) != sizeof(c)) { + if (rv < 0) + virReportSystemError(errno, "%s", _("Unable to wait on parent process")); + else + virReportSystemError(EIO, "%s", _("libvirtd quit during handshake")); + return -1; + } + if (c != '1') { + virReportSystemError(EINVAL, _("Unexpected confirm code '%c' from parent process"), c); + return -1; + } + VIR_FORCE_CLOSE(cmd->handshakeWait[1]); + VIR_FORCE_CLOSE(cmd->handshakeNotify[0]); } + + VIR_DEBUG("Hook is done %d", res); + return res; } @@ -1220,6 +1280,10 @@ virCommandRunAsync(virCommandPtr cmd, pid_t *pid) FD_CLR(i, &cmd->transfer); } } + if (cmd->handshake) { + VIR_FORCE_CLOSE(cmd->handshakeWait[1]); + VIR_FORCE_CLOSE(cmd->handshakeNotify[0]); + } if (ret == 0 && pid) *pid = cmd->pid; @@ -1360,6 +1424,94 @@ virCommandAbort(virCommandPtr cmd ATTRIBUTE_UNUSED) } #endif + +void virCommandRequireHandshake(virCommandPtr cmd) +{ + if (!cmd || cmd->has_error) + return; + + if (pipe(cmd->handshakeWait) < 0) { + cmd->has_error = errno; + return; + } + if (pipe(cmd->handshakeNotify) < 0) { + VIR_FORCE_CLOSE(cmd->handshakeWait[0]); + VIR_FORCE_CLOSE(cmd->handshakeWait[1]); + cmd->has_error = errno; + return; + } + + VIR_DEBUG("Transfer handshake wait=%d notify=%d", + cmd->handshakeWait[1], cmd->handshakeNotify[0]); + virCommandPreserveFD(cmd, cmd->handshakeWait[1]); + virCommandPreserveFD(cmd, cmd->handshakeNotify[0]); + cmd->handshake = true; +} + +int virCommandHandshakeWait(virCommandPtr cmd) +{ + char c; + int rv; + if (!cmd ||cmd->has_error == ENOMEM) { + virReportOOMError(); + return -1; + } + if (cmd->has_error) { + virCommandError(VIR_ERR_INTERNAL_ERROR, "%s", + _("invalid use of command API")); + return -1; + } + + VIR_DEBUG("Wait for handshake on %d", cmd->handshakeWait[0]); + if ((rv = saferead(cmd->handshakeWait[0], &c, sizeof(c))) != sizeof(c)) { + if (rv < 0) + virReportSystemError(errno, "%s", _("Unable to wait for child process")); + else + virReportSystemError(EIO, "%s", _("Child process quit during startup handshake")); + return -1; + } + if (c != '1') { + char *msg; + ssize_t len; + if (VIR_ALLOC_N(msg, 1024) < 0) { + virReportOOMError(); + return -1; + } + if ((len = saferead(cmd->handshakeWait[0], msg, 1024)) < 0) { + VIR_FREE(msg); + virReportSystemError(errno, "%s", _("No error message from child failure")); + return -1; + } + msg[len-1] = '\0'; + virCommandError(VIR_ERR_INTERNAL_ERROR, "%s", msg); + VIR_FREE(msg); + return -1; + } + return 0; +} + +int virCommandHandshakeNotify(virCommandPtr cmd) +{ + char c = '1'; + if (!cmd ||cmd->has_error == ENOMEM) { + virReportOOMError(); + return -1; + } + if (cmd->has_error) { + virCommandError(VIR_ERR_INTERNAL_ERROR, "%s", + _("invalid use of command API")); + return -1; + } + + VIR_DEBUG("Notify handshake on %d", cmd->handshakeWait[0]); + if (safewrite(cmd->handshakeNotify[1], &c, sizeof(c)) != sizeof(c)) { + virReportSystemError(errno, "%s", _("Unable to notify child process")); + return -1; + } + return 0; +} + + /* * Release all resources */ @@ -1391,6 +1543,13 @@ virCommandFree(virCommandPtr cmd) VIR_FREE(cmd->pwd); + if (cmd->handshake) { + VIR_FORCE_CLOSE(cmd->handshakeWait[0]); + VIR_FORCE_CLOSE(cmd->handshakeWait[1]); + VIR_FORCE_CLOSE(cmd->handshakeNotify[0]); + VIR_FORCE_CLOSE(cmd->handshakeNotify[1]); + } + VIR_FREE(cmd->pidfile); if (cmd->reap) diff --git a/src/util/command.h b/src/util/command.h index ff8ccf5..f1b372b 100644 --- a/src/util/command.h +++ b/src/util/command.h @@ -275,6 +275,28 @@ int virCommandWait(virCommandPtr cmd, int *exitstatus) ATTRIBUTE_RETURN_CHECK; /* + * Request that the child perform a handshake with + * the parent when the hook function has completed + * execution. The child will not exec() until the + * parent has notified + */ +void virCommandRequireHandshake(virCommandPtr cmd); + +/* + * Wait for the child to complete execution of its + * hook function + */ +int virCommandHandshakeWait(virCommandPtr cmd) + ATTRIBUTE_RETURN_CHECK; + +/* + * Notify the child that it is OK to exec() the + * real binary now + */ +int virCommandHandshakeNotify(virCommandPtr cmd) + ATTRIBUTE_RETURN_CHECK; + +/* * Abort an async command if it is running, without issuing * any errors or affecting errno. Designed for error paths * where some but not all paths to the cleanup code might -- 1.7.4.4 From laine at laine.org Tue Apr 19 19:35:10 2011 From: laine at laine.org (Laine Stump) Date: Tue, 19 Apr 2011 15:35:10 -0400 Subject: [libvirt] RFC: virInterface change transaction API In-Reply-To: <20110419145940.GC22023@redhat.com> References: <4D9F6279.6040806@laine.org> <20110414130302.GG24239@redhat.com> <20110418165305.GL4648@redhat.com> <20110419145940.GC22023@redhat.com> Message-ID: <4DADE3EE.7080005@laine.org> On 04/19/2011 10:59 AM, Dan Kenigsberg wrote: > On Mon, Apr 18, 2011 at 05:53:05PM +0100, Daniel P. Berrange wrote: >> On Thu, Apr 14, 2011 at 04:03:03PM +0300, Dan Kenigsberg wrote: >>> On Fri, Apr 08, 2011 at 03:31:05PM -0400, Laine Stump wrote: >>>> 1) libvirt >>>> >>>> At the libvirt layer, this feature just requires 3 new APIs, which >>>> are directly passed through to netcf: >>>> >>>> virInterfaceChangeStart(virConnectPtr conn, unsigned int flags); >>>> virInterfaceChangeCommit(virConnectPtr conn, unsigned int flags); >>>> virInterfaceChangeRollback(virConnectPtr conn, unsigned int flags); >>>> >>>> For the initial implementation, these will be simple passthroughs >>>> to similarly named netcf functions. (in the future, it would be >>>> useful for the server side of libvirt to determine if client<->server >>>> connectivity was lost due to the network changes, and automatically >>>> tell netcf to do a rollback). >>> When such a feature is added, we should make it dependent on FLAG_AUTO_ROLLBACK >>> passed to ChangeStart. Higher levels on the management stack may want full >>> controll over when rollback happens. >> I don't think a AUTO_ROLLBACK flag is sufficient. You'd almost certainly >> want to pass some info such as hostname/port number to test, and perhaps >> a test timeout in milliseconds, and perhaps a retry count. > Yes, that's why I wanted complete control over auto rollback, when it is > inroduced. What about the rollback that takes place at boot time if the changes haven't been committed? Should that *always* happen, or should it be controllable by flags as well. I had intended that at least that automatic rollback would be present in the first implementation... From stefanb at linux.vnet.ibm.com Tue Apr 19 20:53:25 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Tue, 19 Apr 2011 16:53:25 -0400 Subject: [libvirt] [PATCH] nwfilter: no support for direct type of interface In-Reply-To: <20110419143411.GL11901@redhat.com> References: <4DAD9B4F.6030708@linux.vnet.ibm.com> <20110419143411.GL11901@redhat.com> Message-ID: <4DADF645.1090304@linux.vnet.ibm.com> On 04/19/2011 10:34 AM, Daniel P. Berrange wrote: > On Tue, Apr 19, 2011 at 10:25:19AM -0400, Stefan Berger wrote: >> Ebtables filtering doesn't work on macvtap device. Remove support >> for direct type of interface. >> >> Signed-off-by: Stefan Berger >> >> --- >> docs/formatnwfilter.html.in | 2 -- >> src/conf/domain_conf.c | 1 - >> src/nwfilter/nwfilter_ebiptables_driver.c | 16 +--------------- >> 3 files changed, 1 insertion(+), 18 deletions(-) > ACK > Pushed. Stefan > Daniel From kamezawa.hiroyu at jp.fujitsu.com Tue Apr 19 23:58:58 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Wed, 20 Apr 2011 08:58:58 +0900 Subject: [libvirt] [RFC][PATCHv1 2/5] libvirt - new API for getting percpu statistics of VM In-Reply-To: <20110419112904.GI11901@redhat.com> References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> <20110415160452.63bd9216.kamezawa.hiroyu@jp.fujitsu.com> <20110415164303.455ab625.kamezawa.hiroyu@jp.fujitsu.com> <20110419112904.GI11901@redhat.com> Message-ID: <20110420085858.35b807ca.kamezawa.hiroyu@jp.fujitsu.com> On Tue, 19 Apr 2011 12:29:05 +0100 "Daniel P. Berrange" wrote: > On Fri, Apr 15, 2011 at 04:43:03PM +0900, KAMEZAWA Hiroyuki wrote: > > On Fri, 15 Apr 2011 09:43:15 +0200 > > Matthias Bolte wrote: > > > > > 2011/4/15 KAMEZAWA Hiroyuki : > > > Also do you really need the absolute CPU time? > > yes, for virt-top -1. > > I don't think that is correct. What virt-top ultimately displays > to the end user is a % utilization. So it would be happy to get > data in either % util & display that directly, or get absolute > CPU time and calculate deltas to display % util. > virt-top calculate delta by itself. > I wonder if we could provide an API that could be used to provide > either per-VCPU or per-PCPU statistics in one go, so that we > can finally have an API for cpu time that works well for VMWare. > VMWare ? > eg > > typedef struct _virDomainCPUTime virDomainCPUTime; > typedef virDomainCPUTime *virDomainCPUTimePtr; > > #define VIR_DOMAIN_CPUTIME_ABS "abs" > #define VIR_DOMAIN_CPUTIME_UTIL "util" > ...define more stats later if desired... > To calculate 'util', we need 'interval' for calculating it. What interval do we use ? The libvirt need to calculate it periodically by making a thread ? "util" can be very easily calculated by util = cpuTime-delta / (interval(sec) * 1000000000) * 100. So, it depens on interval. For example, when we make fair-share-scheduler's balancing interval to 1sec, we never want interaval smaller than 1 sec. IIUC, virt-top users can specify 'interval'. So, virt-top needs to use absolute cpuTime delta even if libvirt provides 'util'. Because to show what users want, virt-top needs to use interval users want. > struct _virDomainCPUTime { > char field[VIR_DOMAIN_CPU_TIME_FIELD_LENGTH]; > unsigned long long value; > }; > > typedef enum { > VIR_DOMAIN_CPU_TIME_VIRTUAL = 0, > VIR_DOMAIN_CPU_TIME_PHYSICAL = 1, > } virDomainCPUTimeFlags; > > int virDomainGetCPUTime(virDomainPtr dom, > virDomainCPUTimePtr stats, > int *nstats, > unsigned int flags); > > > When querying per-virtual CPU time, nstats would be the number of > virtual CPUs in the guest. eg > Why we take care of vcpus ? > virDomainInfo info; > virDomainGetInfo(dom, &info); > virDomainCPUTimePtr stats; > > stats = malloc(sizeof(*stats)*info.nrVirtCPU); > > virDomainGetCPUTime(dom, stats, info.nrVirtCPU, > VIR_DOMAIN_CPU_TIME_VIRTUAL); > > > > Or to get the break down per physical CPU, use the VIR_NODEINFO_MAX_CPUS > macro > per vcpu pcpu time is not what I want. Hmm, others needs such information ? And virt-top need to re-calculate per-vm pcpu time by making sum of cputime per vcpu on pcus ? Anyway, cpuacct cgroup/ Linux kernel cannot provide per-vcpu-per-pcpu time and I cannot implement qemu driver. Thanks, -Kame From kamezawa.hiroyu at jp.fujitsu.com Wed Apr 20 00:00:05 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Wed, 20 Apr 2011 09:00:05 +0900 Subject: [libvirt] [PATCHv10 1/6] libvirt/qemu - clean up for qemudDomainAt(de)tachDevice(Flags) In-Reply-To: <4DAD55E4.4090400@cn.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> <20110419164034.9c8a82e3.kamezawa.hiroyu@jp.fujitsu.com> <4DAD55E4.4090400@cn.fujitsu.com> Message-ID: <20110420090005.ff61a2f2.kamezawa.hiroyu@jp.fujitsu.com> On Tue, 19 Apr 2011 17:29:08 +0800 Wen Congyang wrote: > At 04/19/2011 03:40 PM, KAMEZAWA Hiroyuki Write: > > > > Centralize device modification in the more flexible APIs, to allow > > future honoring of additional flags. Explicitly reject the > > VIR_DOMAIN_DEVICE_MODIFY_FORCE flag on attach/detach. > > > > Based on Eric Blake's work. > > > > From: Eric Blake > > Signed-off-by: KAMEZAWA Hiroyuki > > > > * src/qemu/qemu_driver.c (qemudDomainAttachDevice) > > (qemudDomainAttachDeviceFlags): Swap bodies, and rename... > > Hmm, you do not rename the function(qemudDomainAttachDevice ===> qemuDomainAttachDevice) > typo > > (qemuDomainAttachDevice, qemuDomainAttachDeviceFlags): to this. > > Hmm, it may be update not attach here. > typo > > (qemudDomainDetachDevice, qemudDomainDetachDeviceFlags): > > Missing 'Likewise.' > ? Thanks, -Kame > > --- > > src/qemu/qemu_driver.c | 53 ++++++++++++++++++++++++++--------------------- > > 1 files changed, 29 insertions(+), 24 deletions(-) > > > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > > index f6e503a..a8f3849 100644 > > --- a/src/qemu/qemu_driver.c > > +++ b/src/qemu/qemu_driver.c > > @@ -3786,8 +3786,8 @@ cleanup: > > } > > > > > > -static int qemudDomainAttachDevice(virDomainPtr dom, > > - const char *xml) > > +static int qemudDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, > > + unsigned int flags) > > { > > struct qemud_driver *driver = dom->conn->privateData; > > virDomainObjPtr vm; > > @@ -3796,6 +3796,14 @@ static int qemudDomainAttachDevice(virDomainPtr dom, > > virCgroupPtr cgroup = NULL; > > int ret = -1; > > > > + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | > > + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); > > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > > + qemuReportError(VIR_ERR_OPERATION_INVALID, > > + "%s", _("cannot modify the persistent configuration of a domain")); > > + return -1; > > + } > > + > > qemuDriverLock(driver); > > vm = virDomainFindByUUID(&driver->domains, dom->uuid); > > if (!vm) { > > @@ -3943,16 +3951,10 @@ cleanup: > > return ret; > > } > > > > -static int qemudDomainAttachDeviceFlags(virDomainPtr dom, > > - const char *xml, > > - unsigned int flags) { > > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > > - qemuReportError(VIR_ERR_OPERATION_INVALID, > > - "%s", _("cannot modify the persistent configuration of a domain")); > > - return -1; > > - } > > - > > - return qemudDomainAttachDevice(dom, xml); > > +static int qemudDomainAttachDevice(virDomainPtr dom, const char *xml) > > +{ > > + return qemudDomainAttachDeviceFlags(dom, xml, > > + VIR_DOMAIN_DEVICE_MODIFY_LIVE); > > } > > > > > > @@ -4078,14 +4080,23 @@ cleanup: > > } > > > > > > -static int qemudDomainDetachDevice(virDomainPtr dom, > > - const char *xml) { > > +static int qemudDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, > > + unsigned int flags) > > +{ > > struct qemud_driver *driver = dom->conn->privateData; > > virDomainObjPtr vm; > > virBitmapPtr qemuCaps = NULL; > > virDomainDeviceDefPtr dev = NULL; > > int ret = -1; > > > > + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE| > > + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); > > + > > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > > + qemuReportError(VIR_ERR_OPERATION_INVALID, > > + "%s", _("cannot modify the persistent configuration of a domain:")); > > + return -1; > > + } > > qemuDriverLock(driver); > > vm = virDomainFindByUUID(&driver->domains, dom->uuid); > > if (!vm) { > > @@ -4164,16 +4175,10 @@ cleanup: > > return ret; > > } > > > > -static int qemudDomainDetachDeviceFlags(virDomainPtr dom, > > - const char *xml, > > - unsigned int flags) { > > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > > - qemuReportError(VIR_ERR_OPERATION_INVALID, > > - "%s", _("cannot modify the persistent configuration of a domain")); > > - return -1; > > - } > > - > > - return qemudDomainDetachDevice(dom, xml); > > +static int qemudDomainDetachDevice(virDomainPtr dom, const char *xml) > > +{ > > + return qemudDomainDetachDeviceFlags(dom, xml, > > + VIR_DOMAIN_DEVICE_MODIFY_LIVE); > > } > > > > static int qemudDomainGetAutostart(virDomainPtr dom, > > From kamezawa.hiroyu at jp.fujitsu.com Wed Apr 20 00:04:13 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Wed, 20 Apr 2011 09:04:13 +0900 Subject: [libvirt] [PATCHv10 1/6] libvirt/qemu - clean up for qemudDomainAt(de)tachDevice(Flags) In-Reply-To: <20110419164034.9c8a82e3.kamezawa.hiroyu@jp.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> <20110419164034.9c8a82e3.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110420090413.8a220efa.kamezawa.hiroyu@jp.fujitsu.com> Fixed typos in commit comments. == >From 58c8e35fbadce5a7b085045fec41b0bf57ae9a92 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Tue, 19 Apr 2011 13:21:57 +0900 Subject: [PATCHv10 1/6] libvirt/qemu - clean up for qemudDomainAt(de)tachDevice(Flags) Centralize device modification in the more flexible APIs, to allow future honoring of additional flags. Explicitly reject the VIR_DOMAIN_DEVICE_MODIFY_FORCE flag on attach/detach. Based on Eric Blake's work. From: Eric Blake Signed-off-by: KAMEZAWA Hiroyuki * src/qemu/qemu_driver.c (qemudDomainAttachDevice)(qemudDomainAttachDeviceFlags): Swap bodies, and rename... (qemudDomainDetachDevice, qemudDomainDetachDeviceFlags): Likewise. --- src/qemu/qemu_driver.c | 53 ++++++++++++++++++++++++++--------------------- 1 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f6e503a..a8f3849 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3786,8 +3786,8 @@ cleanup: } -static int qemudDomainAttachDevice(virDomainPtr dom, - const char *xml) +static int qemudDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; @@ -3796,6 +3796,14 @@ static int qemudDomainAttachDevice(virDomainPtr dom, virCgroupPtr cgroup = NULL; int ret = -1; + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot modify the persistent configuration of a domain")); + return -1; + } + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { @@ -3943,16 +3951,10 @@ cleanup: return ret; } -static int qemudDomainAttachDeviceFlags(virDomainPtr dom, - const char *xml, - unsigned int flags) { - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return qemudDomainAttachDevice(dom, xml); +static int qemudDomainAttachDevice(virDomainPtr dom, const char *xml) +{ + return qemudDomainAttachDeviceFlags(dom, xml, + VIR_DOMAIN_DEVICE_MODIFY_LIVE); } @@ -4078,14 +4080,23 @@ cleanup: } -static int qemudDomainDetachDevice(virDomainPtr dom, - const char *xml) { +static int qemudDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; virBitmapPtr qemuCaps = NULL; virDomainDeviceDefPtr dev = NULL; int ret = -1; + virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE| + VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); + + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot modify the persistent configuration of a domain:")); + return -1; + } qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { @@ -4164,16 +4175,10 @@ cleanup: return ret; } -static int qemudDomainDetachDeviceFlags(virDomainPtr dom, - const char *xml, - unsigned int flags) { - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return qemudDomainDetachDevice(dom, xml); +static int qemudDomainDetachDevice(virDomainPtr dom, const char *xml) +{ + return qemudDomainDetachDeviceFlags(dom, xml, + VIR_DOMAIN_DEVICE_MODIFY_LIVE); } static int qemudDomainGetAutostart(virDomainPtr dom, -- 1.7.4.1 From dallan at redhat.com Wed Apr 20 02:09:49 2011 From: dallan at redhat.com (Dave Allan) Date: Tue, 19 Apr 2011 22:09:49 -0400 Subject: [libvirt] RFC: virInterface change transaction API In-Reply-To: <4DADE3EE.7080005@laine.org> References: <4D9F6279.6040806@laine.org> <20110414130302.GG24239@redhat.com> <20110418165305.GL4648@redhat.com> <20110419145940.GC22023@redhat.com> <4DADE3EE.7080005@laine.org> Message-ID: <20110420020949.GU4087@redhat.com> On Tue, Apr 19, 2011 at 03:35:10PM -0400, Laine Stump wrote: > On 04/19/2011 10:59 AM, Dan Kenigsberg wrote: > >On Mon, Apr 18, 2011 at 05:53:05PM +0100, Daniel P. Berrange wrote: > >>On Thu, Apr 14, 2011 at 04:03:03PM +0300, Dan Kenigsberg wrote: > >>>On Fri, Apr 08, 2011 at 03:31:05PM -0400, Laine Stump wrote: > >>>>1) libvirt > >>>> > >>>> At the libvirt layer, this feature just requires 3 new APIs, which > >>>> are directly passed through to netcf: > >>>> > >>>> virInterfaceChangeStart(virConnectPtr conn, unsigned int flags); > >>>> virInterfaceChangeCommit(virConnectPtr conn, unsigned int flags); > >>>> virInterfaceChangeRollback(virConnectPtr conn, unsigned int flags); > >>>> > >>>> For the initial implementation, these will be simple passthroughs > >>>> to similarly named netcf functions. (in the future, it would be > >>>> useful for the server side of libvirt to determine if client<->server > >>>> connectivity was lost due to the network changes, and automatically > >>>> tell netcf to do a rollback). > >>>When such a feature is added, we should make it dependent on FLAG_AUTO_ROLLBACK > >>>passed to ChangeStart. Higher levels on the management stack may want full > >>>controll over when rollback happens. > >>I don't think a AUTO_ROLLBACK flag is sufficient. You'd almost certainly > >>want to pass some info such as hostname/port number to test, and perhaps > >>a test timeout in milliseconds, and perhaps a retry count. > >Yes, that's why I wanted complete control over auto rollback, when it is > >inroduced. > > What about the rollback that takes place at boot time if the changes > haven't been committed? Should that *always* happen, or should it be > controllable by flags as well. I had intended that at least that > automatic rollback would be present in the first implementation... Somewhat related, I think the definition of and test for a successful configuration should be left to the application developer. We could provide some prepackaged tests, e.g., ping some host, connect to some host on some port, but I think the definition of working connectivity can be subtle, and I don't think we should impose one definition, or even a set of definitions, on all applications. Dave From wency at cn.fujitsu.com Wed Apr 20 02:19:42 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 20 Apr 2011 10:19:42 +0800 Subject: [libvirt] [PATCHv10 2/6] clean up At(De)tachDeviceFlags() for consolidation. In-Reply-To: <20110419164309.8a35551f.kamezawa.hiroyu@jp.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> <20110419164309.8a35551f.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4DAE42BE.7030103@cn.fujitsu.com> At 04/19/2011 03:43 PM, KAMEZAWA Hiroyuki Write: > qemudDomainAttachDeviceFlags()/qemudDomainDetachFlags()/ > qemudDomainUpdateDeviceFlags() has similar logics and copied codes. > > This patch series tries to unify them to use shared code when it can. > At first, clean up At(De)tachDeviceFlags() and devide it into functions. > > By this, this patch pulls out shared components between functions. > Based on patch series by Eric Blake, I added some modification as > switch-case. > > From: Eric Blake > Signed-off-by: KAMEZAWA Hiroyuki > > * src/qemu/qemu_driver.c > (qemudDomainAttachDeviceFlags) : pulled out to qemudDomainModifyDeviceFlags() > (qemudDomainModifyDeviceFlags) : impelements a generic codes for modify domain. > (qemudDomainAttachDeviceFlagsLive) : codes for attaching devices to domain > in live, no changes in logic from old code. > (qemudDomainDetachDeviceFlagsLive) : codes for detaching devices to domain > in live, no changes in logic from old code. You introduce some functions qemudDomainAttachXXXLive() and qemudDomainDetachXXXLive() to make qemudDomainAttachDeviceFlags() and qemudDomainDetachDeviceFlags() to be small. You should log them in commit messages. > --- > src/qemu/qemu_driver.c | 429 ++++++++++++++++++++++++++---------------------- > 1 files changed, 234 insertions(+), 195 deletions(-) > From liyong at skybility.com Wed Apr 20 02:33:02 2011 From: liyong at skybility.com (Lyre) Date: Wed, 20 Apr 2011 10:33:02 +0800 Subject: [libvirt] [libvirt-php] Add libvirt_storagepool_build() function Message-ID: <1303266782-14061-1-git-send-email-liyong@skybility.com> also add flags for this function, currently not used. --- src/libvirt-php.c | 31 +++++++++++++++++++++++++++++++ src/libvirt-php.h | 1 + 2 files changed, 32 insertions(+), 0 deletions(-) diff --git a/src/libvirt-php.c b/src/libvirt-php.c index d436e1c..54331bb 100644 --- a/src/libvirt-php.c +++ b/src/libvirt-php.c @@ -129,6 +129,7 @@ static function_entry libvirt_functions[] = { PHP_FE(libvirt_storagepool_refresh, NULL) PHP_FE(libvirt_storagepool_set_autostart, NULL) PHP_FE(libvirt_storagepool_get_autostart, NULL) + PHP_FE(libvirt_storagepool_build, NULL) /* Network functions */ PHP_FE(libvirt_network_define_xml, NULL) PHP_FE(libvirt_network_undefine, NULL) @@ -542,6 +543,13 @@ PHP_MINIT_FUNCTION(libvirt) /* Forcibly modify device (ex. force eject a cdrom) */ REGISTER_LONG_CONSTANT("VIR_DOMAIN_DEVICE_MODIFY_FORCE", 4, CONST_CS | CONST_PERSISTENT); + /* REGISTER_LONG_CONSTANT */ + REGISTER_LONG_CONSTANT("VIR_STORAGE_POOL_BUILD_NEW", 0, CONST_CS | CONST_PERSISTENT); + /* Repair / reinitialize */ + REGISTER_LONG_CONSTANT("VIR_STORAGE_POOL_BUILD_REPAIR", 1, CONST_CS | CONST_PERSISTENT); + /* Extend existing pool */ + REGISTER_LONG_CONSTANT("VIR_STORAGE_POOL_BUILD_RESIZE", 2, CONST_CS | CONST_PERSISTENT); + REGISTER_INI_ENTRIES(); /* Initialize libvirt and set up error callback */ @@ -3582,6 +3590,29 @@ PHP_FUNCTION(libvirt_storagepool_get_autostart) } } +/* + Function name: libvirt_storagepool_build + Since version: 0.4.2 + Description: Function is used to Build the underlying storage pool, e.g. create the destination directory for NFS + Arguments: @res [resource]: libvirt storagepool resource + Returns: TRUE if success, FALSE on error +*/ +PHP_FUNCTION(libvirt_storagepool_build) +{ + php_libvirt_storagepool *pool = NULL; + zval *zpool; + int flags = 0; + + GET_STORAGEPOOL_FROM_ARGS ("r", &zpool); + + if (virStoragePoolBuild (pool->pool, flags) == 0) + { + RETURN_TRUE; + } + + RETURN_FALSE; +} + /* Listing functions */ /* Function name: libvirt_list_storagepools diff --git a/src/libvirt-php.h b/src/libvirt-php.h index 4e8dec6..2d79f60 100644 --- a/src/libvirt-php.h +++ b/src/libvirt-php.h @@ -193,6 +193,7 @@ PHP_FUNCTION(libvirt_storagepool_get_volume_count); PHP_FUNCTION(libvirt_storagepool_refresh); PHP_FUNCTION(libvirt_storagepool_set_autostart); PHP_FUNCTION(libvirt_storagepool_get_autostart); +PHP_FUNCTION(libvirt_storagepool_build); /* Network functions */ PHP_FUNCTION(libvirt_network_define_xml); PHP_FUNCTION(libvirt_network_undefine); -- 1.7.3.4 From wency at cn.fujitsu.com Wed Apr 20 02:34:13 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 20 Apr 2011 10:34:13 +0800 Subject: [libvirt] [PATCHv10 3/6] clean up UpdateDevice for consolidation In-Reply-To: <20110419164443.8b4446a8.kamezawa.hiroyu@jp.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> <20110419164443.8b4446a8.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4DAE4625.8000007@cn.fujitsu.com> At 04/19/2011 03:44 PM, KAMEZAWA Hiroyuki Write: > This patch strips reusable part of qemudDomainUpdateDeviceFlags() > and consolidate it to qemudDomainModifyDeviceFlags(). > No functional changes. > Based on Eric's and Hu's work. > > > Signed-off-by: KAMEZAWA Hiroyuki > > * src/qemu/qemu_driver.c > (qemudDomainUpdateDeviceLive) : core of UpdateDevice, extracted from > UpdateDeviceFlags() > (qemudDomainUpdateDeviceFlags): reworked as a wrapper function of > ModifyDeviceFlags() > --- > src/qemu/qemu_driver.c | 209 +++++++++++++++++++++--------------------------- > 1 files changed, 90 insertions(+), 119 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index f33a7f4..2bdf42e 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -3991,6 +3991,74 @@ static int qemudDomainDetachDeviceLive(virDomainObjPtr vm, > return ret; > } > > +static int > +qemudDomainChangeDiskMediaLive(virDomainObjPtr vm, > + virDomainDeviceDefPtr dev, > + struct qemud_driver *driver, > + virBitmapPtr qemuCaps, > + bool force) > +{ > + virDomainDiskDefPtr disk = dev->data.disk; > + virCgroupPtr cgroup = NULL; > + int ret; > + > + if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { > + if (virCgroupForDomain(driver->cgroup, > + vm->def->name, &cgroup, 0) !=0 ) { > + qemuReportError(VIR_ERR_INTERNAL_ERROR, > + _("Unable to find cgroup for %s"), > + vm->def->name); > + goto end; > + } > + if (qemuSetupDiskCgroup(driver, vm, cgroup, disk) < 0) > + goto end; > + } > + > + switch (disk->device) { > + case VIR_DOMAIN_DISK_DEVICE_CDROM: > + case VIR_DOMAIN_DISK_DEVICE_FLOPPY: > + ret = qemuDomainChangeEjectableMedia(driver, vm, disk, qemuCaps, force); > + if (ret == 0) > + dev->data.disk = NULL; > + break; > + default: > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, > + _("disk bus '%s' cannot be updated."), > + virDomainDiskBusTypeToString(disk->bus)); > + break; > + } > +end: If ret is not 0 and cgroup is not NULL, you should call qemuTeardownDiskCgroup() to do some cleanup. > + if (cgroup) > + virCgroupFree(&cgroup); > + return ret; > +} > + From wency at cn.fujitsu.com Wed Apr 20 02:52:41 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 20 Apr 2011 10:52:41 +0800 Subject: [libvirt] [PATCHv10 4/6] libvirt/qemu support persistent device modification In-Reply-To: <20110419164607.6e94a6fd.kamezawa.hiroyu@jp.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> <20110419164607.6e94a6fd.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4DAE4A79.5020507@cn.fujitsu.com> At 04/19/2011 03:46 PM, KAMEZAWA Hiroyuki Write: > This patch adds functions for modify domain's persistent definition. > To do error recovery in easy way, we use a copy of vmdef and update it. > > The whole sequence will be: > > make a copy of domain definition. > > if (flags & MODIFY_CONFIG) > update copied domain definition > if (flags & MODIF_LIVE) > do hotplug. > if (no error) > save copied one to the file and update cached definition. > else > discard copied definition. > > This patch is mixuture of Eric Blake's work and mine. > From: Eric Blake > Signed-off-by: KAMEZAWA Hiroyuki > > (virDomainObjCopyPersistentDef): make a copy of persistent vm definition > (qemudDomainModifyDeviceFlags): add support for MODIFY_CONFIG and MODIFY_CURRENT > (qemudDomainAttach/Detach/UpdateDeviceConfig) : callbacks. now empty > --- > src/conf/domain_conf.c | 18 ++++++ > src/conf/domain_conf.h | 3 + > src/libvirt_private.syms | 1 + > src/qemu/qemu_driver.c | 148 ++++++++++++++++++++++++++++++++++++---------- > 4 files changed, 139 insertions(+), 31 deletions(-) > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index 6b733d4..bb8f0a4 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -9510,3 +9510,21 @@ cleanup: > > return ret; > } > + > + > +virDomainDefPtr > +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom) > +{ > + char *xml; > + virDomainDefPtr cur, ret; > + > + cur = virDomainObjGetPersistentDef(caps, dom); > + > + xml = virDomainDefFormat(cur, VIR_DOMAIN_XML_WRITE_FLAGS); > + if (!xml) > + return NULL; > + > + ret = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS); > + > + return ret; > +} > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > index 6ea30b9..ddf111a 100644 > --- a/src/conf/domain_conf.h > +++ b/src/conf/domain_conf.h > @@ -1288,6 +1288,9 @@ int virDomainObjSetDefTransient(virCapsPtr caps, > virDomainDefPtr > virDomainObjGetPersistentDef(virCapsPtr caps, > virDomainObjPtr domain); > +virDomainDefPtr > +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom); > + > void virDomainRemoveInactive(virDomainObjListPtr doms, > virDomainObjPtr dom); > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index ba7739d..f732431 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -287,6 +287,7 @@ virDomainMemballoonModelTypeToString; > virDomainNetDefFree; > virDomainNetTypeToString; > virDomainObjAssignDef; > +virDomainObjCopyPersistentDef; > virDomainObjSetDefTransient; > virDomainObjGetPersistentDef; > virDomainObjIsDuplicate; > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 2bdf42e..4ac8f7e 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -4059,6 +4059,48 @@ static int qemudDomainUpdateDeviceLive(virDomainObjPtr vm, > return ret; > } > > +static int > +qemudDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, > + virDomainDeviceDefPtr dev) > +{ > + switch (dev->type) { > + default: > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("persistent update of device is not supported")); > + return -1; > + } > + return 0; > +} > + > + > +static int > +qemudDomainDetachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, > + virDomainDeviceDefPtr dev) > +{ > + switch (dev->type) { > + default: > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("persistent update of device is not supported")); > + return -1; > + } > + return 0; > +} > + > +static int > +qemudDomainUpdateDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, > + virDomainDeviceDefPtr dev, > + bool force ATTRIBUTE_UNUSED) > +{ > + switch (dev->type) { > + default: > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("persistent update of device is not supported")); > + return -1; > + } > + return 0; > + > +} > + > enum { > QEMUD_DEVICE_ATTACH, QEMUD_DEVICE_DETACH, QEMUD_DEVICE_UPDATE, > }; > @@ -4069,6 +4111,7 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > struct qemud_driver *driver = dom->conn->privateData; > virBitmapPtr qemuCaps = NULL; > virDomainObjPtr vm = NULL; > + virDomainDefPtr vmdef = NULL; > virDomainDeviceDefPtr dev = NULL; > bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; > int ret = -1; > @@ -4077,7 +4120,8 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > case QEMUD_DEVICE_ATTACH: > case QEMUD_DEVICE_DETACH: > virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | > - VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); > + VIR_DOMAIN_DEVICE_MODIFY_CONFIG | > + VIR_DOMAIN_DEVICE_MODIFY_CURRENT, -1); > break; > case QEMUD_DEVICE_UPDATE: > virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_CURRENT | > @@ -4089,12 +4133,6 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > break; > } > > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > - qemuReportError(VIR_ERR_OPERATION_INVALID, > - "%s", _("cannot modify the persistent configuration of a domain")); > - return -1; > - } > - > qemuDriverLock(driver); > vm = virDomainFindByUUID(&driver->domains, dom->uuid); > if (!vm) { > @@ -4108,11 +4146,29 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) > goto cleanup; > > - if (!virDomainObjIsActive(vm)) { > - qemuReportError(VIR_ERR_OPERATION_INVALID, > - "%s", _("cannot attach device on inactive domain")); > - goto endjob; > + if (virDomainObjIsActive(vm)) { > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CURRENT) > + flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE; VIR_DOMAIN_DEVICE_MODIFY_CURRENT is 0. So you should check 'flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT' instead of 'flags & VIR_DOMAIN_DEVICE_MODIFY_CURRENT'. > + } else { > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CURRENT) > + flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG; Tha same as above. > + /* check consistency between flags and the vm state */ > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { > + qemuReportError(VIR_ERR_OPERATION_INVALID, > + "%s", > + _("cannot modify device on inactive domain")); > + goto endjob; > + } > + } > + > + if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) { > + qemuReportError(VIR_ERR_OPERATION_INVALID, > + "%s", _("cannot modify device on transient domain")); > + goto endjob; > } > + /* At updating config, we update a copy */ > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) > + vmdef = virDomainObjCopyPersistentDef(driver->caps, vm); > > dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, > VIR_DOMAIN_XML_INACTIVE); > @@ -4124,33 +4180,63 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > &qemuCaps) < 0) > goto endjob; > > - switch (action) { > - case QEMUD_DEVICE_ATTACH: > - ret = qemudDomainAttachDeviceLive(vm, dev, dom, qemuCaps); > - break; > - case QEMUD_DEVICE_DETACH: > - ret = qemudDomainDetachDeviceLive(vm, dev, dom, qemuCaps); > - break; > - case QEMUD_DEVICE_UPDATE: > - ret = qemudDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force); > - break; > - default: > - break; > - } > + ret = 0; > > - /* > - * update domain status forcibly because the domain status may be changed > - * even if we attach the device failed. For example, a new controller may > - * be created. > - */ > - if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) > - ret = -1; > + /* Update a copy of persistent definition */ > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > + switch (action) { > + case QEMUD_DEVICE_ATTACH: > + ret = qemudDomainAttachDeviceConfig(vmdef, dev); > + break; > + case QEMUD_DEVICE_DETACH: > + ret = qemudDomainDetachDeviceConfig(vmdef, dev); > + break; > + case QEMUD_DEVICE_UPDATE: > + ret = qemudDomainUpdateDeviceConfig(vmdef, dev, force); > + break; > + default: > + break; > + } > + } > + /* Update Live */ > + if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE)) { > + switch (action) { > + case QEMUD_DEVICE_ATTACH: > + ret = qemudDomainAttachDeviceLive(vm, dev, dom, qemuCaps); > + break; > + case QEMUD_DEVICE_DETACH: > + ret = qemudDomainDetachDeviceLive(vm, dev, dom, qemuCaps); > + break; > + case QEMUD_DEVICE_UPDATE: > + ret = qemudDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force); > + break; > + default: > + break; > + } > + /* > + * update domain status forcibly because the domain status may be > + * changed even if we attach the device failed. For example, a new > + * controller may be created. > + */ > + if (!ret && > + virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) > + ret = -1; > + } > + /* No error until here, we can save persistent definition */ > + if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) { > + ret = virDomainSaveConfig(driver->configDir, vmdef); > + if (!ret) { > + virDomainObjAssignDef(vm, vmdef, false); > + vmdef = NULL; > + } > + } > > endjob: > if (qemuDomainObjEndJob(vm) == 0) > vm = NULL; > > cleanup: > + virDomainDefFree(vmdef); > virDomainDeviceDefFree(dev); > if (vm) > virDomainObjUnlock(vm); From kamezawa.hiroyu at jp.fujitsu.com Wed Apr 20 03:05:37 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Wed, 20 Apr 2011 12:05:37 +0900 Subject: [libvirt] [PATCHv10 4/6] libvirt/qemu support persistent device modification In-Reply-To: <4DAE4A79.5020507@cn.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> <20110419164607.6e94a6fd.kamezawa.hiroyu@jp.fujitsu.com> <4DAE4A79.5020507@cn.fujitsu.com> Message-ID: <20110420120537.41f8aa26.kamezawa.hiroyu@jp.fujitsu.com> On Wed, 20 Apr 2011 10:52:41 +0800 Wen Congyang wrote: > At 04/19/2011 03:46 PM, KAMEZAWA Hiroyuki Write: > > This patch adds functions for modify domain's persistent definition. > > To do error recovery in easy way, we use a copy of vmdef and update it. > > > > The whole sequence will be: > > > > make a copy of domain definition. > > > > if (flags & MODIFY_CONFIG) > > update copied domain definition > > if (flags & MODIF_LIVE) > > do hotplug. > > if (no error) > > save copied one to the file and update cached definition. > > else > > discard copied definition. > > > > This patch is mixuture of Eric Blake's work and mine. > > From: Eric Blake > > Signed-off-by: KAMEZAWA Hiroyuki > > > > (virDomainObjCopyPersistentDef): make a copy of persistent vm definition > > (qemudDomainModifyDeviceFlags): add support for MODIFY_CONFIG and MODIFY_CURRENT > > (qemudDomainAttach/Detach/UpdateDeviceConfig) : callbacks. now empty > > --- > > src/conf/domain_conf.c | 18 ++++++ > > src/conf/domain_conf.h | 3 + > > src/libvirt_private.syms | 1 + > > src/qemu/qemu_driver.c | 148 ++++++++++++++++++++++++++++++++++++---------- > > 4 files changed, 139 insertions(+), 31 deletions(-) > > > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > > index 6b733d4..bb8f0a4 100644 > > --- a/src/conf/domain_conf.c > > +++ b/src/conf/domain_conf.c > > @@ -9510,3 +9510,21 @@ cleanup: > > > > return ret; > > } > > + > > + > > +virDomainDefPtr > > +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom) > > +{ > > + char *xml; > > + virDomainDefPtr cur, ret; > > + > > + cur = virDomainObjGetPersistentDef(caps, dom); > > + > > + xml = virDomainDefFormat(cur, VIR_DOMAIN_XML_WRITE_FLAGS); > > + if (!xml) > > + return NULL; > > + > > + ret = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS); > > + > > + return ret; > > +} > > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > > index 6ea30b9..ddf111a 100644 > > --- a/src/conf/domain_conf.h > > +++ b/src/conf/domain_conf.h > > @@ -1288,6 +1288,9 @@ int virDomainObjSetDefTransient(virCapsPtr caps, > > virDomainDefPtr > > virDomainObjGetPersistentDef(virCapsPtr caps, > > virDomainObjPtr domain); > > +virDomainDefPtr > > +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom); > > + > > void virDomainRemoveInactive(virDomainObjListPtr doms, > > virDomainObjPtr dom); > > > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > > index ba7739d..f732431 100644 > > --- a/src/libvirt_private.syms > > +++ b/src/libvirt_private.syms > > @@ -287,6 +287,7 @@ virDomainMemballoonModelTypeToString; > > virDomainNetDefFree; > > virDomainNetTypeToString; > > virDomainObjAssignDef; > > +virDomainObjCopyPersistentDef; > > virDomainObjSetDefTransient; > > virDomainObjGetPersistentDef; > > virDomainObjIsDuplicate; > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > > index 2bdf42e..4ac8f7e 100644 > > --- a/src/qemu/qemu_driver.c > > +++ b/src/qemu/qemu_driver.c > > @@ -4059,6 +4059,48 @@ static int qemudDomainUpdateDeviceLive(virDomainObjPtr vm, > > return ret; > > } > > > > +static int > > +qemudDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, > > + virDomainDeviceDefPtr dev) > > +{ > > + switch (dev->type) { > > + default: > > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > > + _("persistent update of device is not supported")); > > + return -1; > > + } > > + return 0; > > +} > > + > > + > > +static int > > +qemudDomainDetachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, > > + virDomainDeviceDefPtr dev) > > +{ > > + switch (dev->type) { > > + default: > > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > > + _("persistent update of device is not supported")); > > + return -1; > > + } > > + return 0; > > +} > > + > > +static int > > +qemudDomainUpdateDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, > > + virDomainDeviceDefPtr dev, > > + bool force ATTRIBUTE_UNUSED) > > +{ > > + switch (dev->type) { > > + default: > > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > > + _("persistent update of device is not supported")); > > + return -1; > > + } > > + return 0; > > + > > +} > > + > > enum { > > QEMUD_DEVICE_ATTACH, QEMUD_DEVICE_DETACH, QEMUD_DEVICE_UPDATE, > > }; > > @@ -4069,6 +4111,7 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > > struct qemud_driver *driver = dom->conn->privateData; > > virBitmapPtr qemuCaps = NULL; > > virDomainObjPtr vm = NULL; > > + virDomainDefPtr vmdef = NULL; > > virDomainDeviceDefPtr dev = NULL; > > bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; > > int ret = -1; > > @@ -4077,7 +4120,8 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > > case QEMUD_DEVICE_ATTACH: > > case QEMUD_DEVICE_DETACH: > > virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | > > - VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); > > + VIR_DOMAIN_DEVICE_MODIFY_CONFIG | > > + VIR_DOMAIN_DEVICE_MODIFY_CURRENT, -1); > > break; > > case QEMUD_DEVICE_UPDATE: > > virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_CURRENT | > > @@ -4089,12 +4133,6 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > > break; > > } > > > > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > > - qemuReportError(VIR_ERR_OPERATION_INVALID, > > - "%s", _("cannot modify the persistent configuration of a domain")); > > - return -1; > > - } > > - > > qemuDriverLock(driver); > > vm = virDomainFindByUUID(&driver->domains, dom->uuid); > > if (!vm) { > > @@ -4108,11 +4146,29 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > > if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) > > goto cleanup; > > > > - if (!virDomainObjIsActive(vm)) { > > - qemuReportError(VIR_ERR_OPERATION_INVALID, > > - "%s", _("cannot attach device on inactive domain")); > > - goto endjob; > > + if (virDomainObjIsActive(vm)) { > > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CURRENT) > > + flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE; > > VIR_DOMAIN_DEVICE_MODIFY_CURRENT is 0. So you should check 'flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT' > instead of 'flags & VIR_DOMAIN_DEVICE_MODIFY_CURRENT'. > Hmm, ok. I missed that. > > + } else { > > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CURRENT) > > + flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG; > > Tha same as above. > Sure. Thanks, -Kame From kamezawa.hiroyu at jp.fujitsu.com Wed Apr 20 03:06:35 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Wed, 20 Apr 2011 12:06:35 +0900 Subject: [libvirt] [PATCHv10 3/6] clean up UpdateDevice for consolidation In-Reply-To: <4DAE4625.8000007@cn.fujitsu.com> References: <20110419163830.29903fb3.kamezawa.hiroyu@jp.fujitsu.com> <20110419164443.8b4446a8.kamezawa.hiroyu@jp.fujitsu.com> <4DAE4625.8000007@cn.fujitsu.com> Message-ID: <20110420120635.9977a307.kamezawa.hiroyu@jp.fujitsu.com> On Wed, 20 Apr 2011 10:34:13 +0800 Wen Congyang wrote: > At 04/19/2011 03:44 PM, KAMEZAWA Hiroyuki Write: > > This patch strips reusable part of qemudDomainUpdateDeviceFlags() > > and consolidate it to qemudDomainModifyDeviceFlags(). > > No functional changes. > > Based on Eric's and Hu's work. > > > > > > Signed-off-by: KAMEZAWA Hiroyuki > > > > * src/qemu/qemu_driver.c > > (qemudDomainUpdateDeviceLive) : core of UpdateDevice, extracted from > > UpdateDeviceFlags() > > (qemudDomainUpdateDeviceFlags): reworked as a wrapper function of > > ModifyDeviceFlags() > > --- > > src/qemu/qemu_driver.c | 209 +++++++++++++++++++++--------------------------- > > 1 files changed, 90 insertions(+), 119 deletions(-) > > > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > > index f33a7f4..2bdf42e 100644 > > --- a/src/qemu/qemu_driver.c > > +++ b/src/qemu/qemu_driver.c > > @@ -3991,6 +3991,74 @@ static int qemudDomainDetachDeviceLive(virDomainObjPtr vm, > > return ret; > > } > > > > +static int > > +qemudDomainChangeDiskMediaLive(virDomainObjPtr vm, > > + virDomainDeviceDefPtr dev, > > + struct qemud_driver *driver, > > + virBitmapPtr qemuCaps, > > + bool force) > > +{ > > + virDomainDiskDefPtr disk = dev->data.disk; > > + virCgroupPtr cgroup = NULL; > > + int ret; > > + > > + if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { > > + if (virCgroupForDomain(driver->cgroup, > > + vm->def->name, &cgroup, 0) !=0 ) { > > + qemuReportError(VIR_ERR_INTERNAL_ERROR, > > + _("Unable to find cgroup for %s"), > > + vm->def->name); > > + goto end; > > + } > > + if (qemuSetupDiskCgroup(driver, vm, cgroup, disk) < 0) > > + goto end; > > + } > > + > > + switch (disk->device) { > > + case VIR_DOMAIN_DISK_DEVICE_CDROM: > > + case VIR_DOMAIN_DISK_DEVICE_FLOPPY: > > + ret = qemuDomainChangeEjectableMedia(driver, vm, disk, qemuCaps, force); > > + if (ret == 0) > > + dev->data.disk = NULL; > > + break; > > + default: > > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, > > + _("disk bus '%s' cannot be updated."), > > + virDomainDiskBusTypeToString(disk->bus)); > > + break; > > + } > > +end: > > If ret is not 0 and cgroup is not NULL, you should call qemuTeardownDiskCgroup() to do > some cleanup. > Ah, yes. it's mistake. Will fix in v11. Thanks, -Kame From jyang at redhat.com Wed Apr 20 07:30:25 2011 From: jyang at redhat.com (Osier Yang) Date: Wed, 20 Apr 2011 15:30:25 +0800 Subject: [libvirt] [PATCH] qemu: Unlink managed state file when a domain is undefined Message-ID: <1303284625-15782-1-git-send-email-jyang@redhat.com> The managed state file is not useful anymore after the domain is undefined, and perhaps cause confusion. E.g. define & start a domain which has same name with previous undefined domain later. --- src/qemu/qemu_driver.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f6e503a..874b455 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3739,6 +3739,7 @@ static int qemudDomainUndefine(virDomainPtr dom) { virDomainObjPtr vm; virDomainEventPtr event = NULL; int ret = -1; + char *managed_save = NULL; qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -3766,6 +3767,13 @@ static int qemudDomainUndefine(virDomainPtr dom) { if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0) goto cleanup; + if (!(managed_save = qemuDomainManagedSavePath(driver, vm))) + goto cleanup; + + if (virFileExists(managed_save) && (unlink(managed_save) < 0)) { + VIR_WARN("Failed to remove the managed state %s", managed_save); + } + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED, VIR_DOMAIN_EVENT_UNDEFINED_REMOVED); -- 1.7.4 From matthias.bolte at googlemail.com Wed Apr 20 07:32:07 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Wed, 20 Apr 2011 09:32:07 +0200 Subject: [libvirt] [RFC][PATCHv1 2/5] libvirt - new API for getting percpu statistics of VM In-Reply-To: <20110420085858.35b807ca.kamezawa.hiroyu@jp.fujitsu.com> References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> <20110415160452.63bd9216.kamezawa.hiroyu@jp.fujitsu.com> <20110415164303.455ab625.kamezawa.hiroyu@jp.fujitsu.com> <20110419112904.GI11901@redhat.com> <20110420085858.35b807ca.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: 2011/4/20 KAMEZAWA Hiroyuki : > On Tue, 19 Apr 2011 12:29:05 +0100 > "Daniel P. Berrange" wrote: > >> On Fri, Apr 15, 2011 at 04:43:03PM +0900, KAMEZAWA Hiroyuki wrote: >> > On Fri, 15 Apr 2011 09:43:15 +0200 >> > Matthias Bolte wrote: >> > >> > > 2011/4/15 KAMEZAWA Hiroyuki : >> > > Also do you really need the absolute CPU time? >> > yes, for virt-top -1. >> >> I don't think that is correct. What virt-top ultimately displays >> to the end user is a % utilization. So it would be happy to get >> data in either % util & display that directly, or get absolute >> CPU time and calculate deltas to display % util. >> > > virt-top calculate delta by itself. > > >> I wonder if we could provide an API that could be used to provide >> either per-VCPU or per-PCPU ?statistics in one go, so that we >> can finally have an API for cpu time that works well for VMWare. >> > > VMWare ? > VMware can provide various statistics about a virtual machine, but most (actually all, I think) are not provided as absolute values but in 20 sec slots with 1h of history (a vCenter can store longer history). Therefore, it's nearly impossible to get the absolute CPU time of a virtual machine since bootup. In most cases the enduser is not interested in the absolute CPU time but in the current CPU utilization in percent. VMware already calculates the utilization, but libvirt currently has not API to expose that. http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.PerformanceManager.html http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/cpu_counters.html Matthias From kamezawa.hiroyu at jp.fujitsu.com Wed Apr 20 08:06:29 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Wed, 20 Apr 2011 17:06:29 +0900 Subject: [libvirt] [RFC][PATCHv1 2/5] libvirt - new API for getting percpu statistics of VM In-Reply-To: References: <20110415160217.8e3c8296.kamezawa.hiroyu@jp.fujitsu.com> <20110415160452.63bd9216.kamezawa.hiroyu@jp.fujitsu.com> <20110415164303.455ab625.kamezawa.hiroyu@jp.fujitsu.com> <20110419112904.GI11901@redhat.com> <20110420085858.35b807ca.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110420170629.7f7e4466.kamezawa.hiroyu@jp.fujitsu.com> On Wed, 20 Apr 2011 09:32:07 +0200 Matthias Bolte wrote: > 2011/4/20 KAMEZAWA Hiroyuki : > > On Tue, 19 Apr 2011 12:29:05 +0100 > > "Daniel P. Berrange" wrote: > > > >> On Fri, Apr 15, 2011 at 04:43:03PM +0900, KAMEZAWA Hiroyuki wrote: > >> > On Fri, 15 Apr 2011 09:43:15 +0200 > >> > Matthias Bolte wrote: > >> > > >> > > 2011/4/15 KAMEZAWA Hiroyuki : > >> > > Also do you really need the absolute CPU time? > >> > yes, for virt-top -1. > >> > >> I don't think that is correct. What virt-top ultimately displays > >> to the end user is a % utilization. So it would be happy to get > >> data in either % util & display that directly, or get absolute > >> CPU time and calculate deltas to display % util. > >> > > > > virt-top calculate delta by itself. > > > > > >> I wonder if we could provide an API that could be used to provide > >> either per-VCPU or per-PCPU ?statistics in one go, so that we > >> can finally have an API for cpu time that works well for VMWare. > >> > > > > VMWare ? > > > > VMware can provide various statistics about a virtual machine, but > most (actually all, I think) are not provided as absolute values but > in 20 sec slots with 1h of history (a vCenter can store longer > history). Therefore, it's nearly impossible to get the absolute CPU > time of a virtual machine since bootup. > > In most cases the enduser is not interested in the absolute CPU time > but in the current CPU utilization in percent. VMware already > calculates the utilization, but libvirt currently has not API to > expose that. > > http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.PerformanceManager.html > http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/cpu_counters.html > Hmm, okay. thank you for clarification. Then, I'll prepare 2 options. int virDomainGetPhysCPUStatistics(domain, unsigned long long *stats, int nr_stats, enum PhysCPU_Stat); PhysCPU_ABS_CPUTIME : Per Physical cpu abosolute usage time of domain. PhysCPU_UTIL : Per Physical cpu utilization of domain. The definition of 'utilization' depends on each VM. VMWare can provide its 20sec utilization. KVM will.....maybe 3sec interval is the best because it's 'top's default. But I myself don't take care of this interface and leave this as empty. To calculate it in 3sec interval, it seems to run a thread for doing that job. Maybe interval should be configurable by qemu.conf. If VMWare can provides PerVcpuPhysCPUUtilzation, please add it. I have no idea. Thanks, -Kame From minovotn at redhat.com Wed Apr 20 08:52:18 2011 From: minovotn at redhat.com (Michal Novotny) Date: Wed, 20 Apr 2011 10:52:18 +0200 Subject: [libvirt] [libvirt-php] Add libvirt_storagepool_build() function In-Reply-To: <1303266782-14061-1-git-send-email-liyong@skybility.com> References: <1303266782-14061-1-git-send-email-liyong@skybility.com> Message-ID: <4DAE9EC2.5050705@redhat.com> On 04/20/2011 04:33 AM, Lyre wrote: > also add flags for this function, currently not used. > --- > src/libvirt-php.c | 31 +++++++++++++++++++++++++++++++ > src/libvirt-php.h | 1 + > 2 files changed, 32 insertions(+), 0 deletions(-) > > diff --git a/src/libvirt-php.c b/src/libvirt-php.c > index d436e1c..54331bb 100644 > --- a/src/libvirt-php.c > +++ b/src/libvirt-php.c > @@ -129,6 +129,7 @@ static function_entry libvirt_functions[] = { > PHP_FE(libvirt_storagepool_refresh, NULL) > PHP_FE(libvirt_storagepool_set_autostart, NULL) > PHP_FE(libvirt_storagepool_get_autostart, NULL) > + PHP_FE(libvirt_storagepool_build, NULL) > /* Network functions */ > PHP_FE(libvirt_network_define_xml, NULL) > PHP_FE(libvirt_network_undefine, NULL) > @@ -542,6 +543,13 @@ PHP_MINIT_FUNCTION(libvirt) > /* Forcibly modify device (ex. force eject a cdrom) */ > REGISTER_LONG_CONSTANT("VIR_DOMAIN_DEVICE_MODIFY_FORCE", 4, CONST_CS | CONST_PERSISTENT); > > + /* REGISTER_LONG_CONSTANT */ > + REGISTER_LONG_CONSTANT("VIR_STORAGE_POOL_BUILD_NEW", 0, CONST_CS | CONST_PERSISTENT); > + /* Repair / reinitialize */ > + REGISTER_LONG_CONSTANT("VIR_STORAGE_POOL_BUILD_REPAIR", 1, CONST_CS | CONST_PERSISTENT); > + /* Extend existing pool */ > + REGISTER_LONG_CONSTANT("VIR_STORAGE_POOL_BUILD_RESIZE", 2, CONST_CS | CONST_PERSISTENT); > + > REGISTER_INI_ENTRIES(); > > /* Initialize libvirt and set up error callback */ > @@ -3582,6 +3590,29 @@ PHP_FUNCTION(libvirt_storagepool_get_autostart) > } > } > > +/* > + Function name: libvirt_storagepool_build > + Since version: 0.4.2 > + Description: Function is used to Build the underlying storage pool, e.g. create the destination directory for NFS > + Arguments: @res [resource]: libvirt storagepool resource > + Returns: TRUE if success, FALSE on error > +*/ > +PHP_FUNCTION(libvirt_storagepool_build) > +{ > + php_libvirt_storagepool *pool = NULL; > + zval *zpool; > + int flags = 0; > + > + GET_STORAGEPOOL_FROM_ARGS ("r", &zpool); > + > + if (virStoragePoolBuild (pool->pool, flags) == 0) > + { > + RETURN_TRUE; > + } > + > + RETURN_FALSE; > +} > + > /* Listing functions */ > /* > Function name: libvirt_list_storagepools > diff --git a/src/libvirt-php.h b/src/libvirt-php.h > index 4e8dec6..2d79f60 100644 > --- a/src/libvirt-php.h > +++ b/src/libvirt-php.h > @@ -193,6 +193,7 @@ PHP_FUNCTION(libvirt_storagepool_get_volume_count); > PHP_FUNCTION(libvirt_storagepool_refresh); > PHP_FUNCTION(libvirt_storagepool_set_autostart); > PHP_FUNCTION(libvirt_storagepool_get_autostart); > +PHP_FUNCTION(libvirt_storagepool_build); > /* Network functions */ > PHP_FUNCTION(libvirt_network_define_xml); > PHP_FUNCTION(libvirt_network_undefine); Thanks a lot for your patch Lyre! I've never used this function in libvirt so based on this I never implemented it. Honestly, I rarely use storage pools. It's already been pushed into the repo however ;-) Thanks, Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From hutao at cn.fujitsu.com Wed Apr 20 09:14:33 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Wed, 20 Apr 2011 17:14:33 +0800 Subject: [libvirt] [PATCH v2 1/2] Add static mutex initializer. In-Reply-To: <20110419113837.GA14373@redhat.com> Message-ID: <11a7bd558e33eb347c21d5efebb4a82759125382.1303290824.git.hutao@cn.fujitsu.com> This prepares for the next patch. The bad is we have no way to check the return value for CreateMutex when it is used as a static initializer. --- src/util/threads-pthread.h | 5 +++++ src/util/threads-win32.h | 5 +++++ 2 files changed, 10 insertions(+), 0 deletions(-) diff --git a/src/util/threads-pthread.h b/src/util/threads-pthread.h index b25d0c2..ff50253 100644 --- a/src/util/threads-pthread.h +++ b/src/util/threads-pthread.h @@ -23,6 +23,11 @@ #include +#define VIR_MUTEX_INITIALIZER \ +{ \ + .lock = PTHREAD_MUTEX_INITIALIZER \ +} + struct virMutex { pthread_mutex_t lock; }; diff --git a/src/util/threads-win32.h b/src/util/threads-win32.h index bb7c455..cfadbe4 100644 --- a/src/util/threads-win32.h +++ b/src/util/threads-win32.h @@ -23,6 +23,11 @@ #include +#define VIR_MUTEX_INITIALIZER \ +{ \ + .lock = CreateMutex(NULL, FALSE, NULL) \ +} + struct virMutex { HANDLE lock; }; -- 1.7.3.1 From hutao at cn.fujitsu.com Wed Apr 20 09:15:29 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Wed, 20 Apr 2011 17:15:29 +0800 Subject: [libvirt] [PATCH v2 2/2] Add virObject and virAtomic. In-Reply-To: <11a7bd558e33eb347c21d5efebb4a82759125382.1303290824.git.hutao@cn.fujitsu.com> References: <11a7bd558e33eb347c21d5efebb4a82759125382.1303290824.git.hutao@cn.fujitsu.com> Message-ID: <019f40454f8b412d17f965052a23422f933b2ee2.1303290824.git.hutao@cn.fujitsu.com> virObject is the base struct that manages reference-counting for all structs that need the ability of reference-counting. virAtomic provides atomic operations which are thread-safe. --- src/Makefile.am | 2 + src/libvirt_private.syms | 11 ++++++ src/util/viratomic.c | 80 ++++++++++++++++++++++++++++++++++++++++++ src/util/viratomic.h | 32 +++++++++++++++++ src/util/virobject.c | 64 ++++++++++++++++++++++++++++++++++ src/util/virobject.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 275 insertions(+), 0 deletions(-) create mode 100644 src/util/viratomic.c create mode 100644 src/util/viratomic.h create mode 100644 src/util/virobject.c create mode 100644 src/util/virobject.h diff --git a/src/Makefile.am b/src/Makefile.am index dce866e..cb8acc3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -81,6 +81,8 @@ UTIL_SOURCES = \ util/util.c util/util.h \ util/xml.c util/xml.h \ util/virtaudit.c util/virtaudit.h \ + util/viratomic.c util/viratomic.h \ + util/virobject.c util/virobject.h \ util/virterror.c util/virterror_internal.h EXTRA_DIST += util/threads-pthread.c util/threads-win32.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 54e4482..a33e877 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -958,6 +958,17 @@ virUUIDGenerate; virUUIDParse; +# virobject.h +virObjectInit; +virObjectRef; +virObjectUnref; + + +# viratomic.h +virAtomicInc; +virAtomicDec; + + # virtaudit.h virAuditClose; virAuditEncode; diff --git a/src/util/viratomic.c b/src/util/viratomic.c new file mode 100644 index 0000000..c7bb44f --- /dev/null +++ b/src/util/viratomic.c @@ -0,0 +1,80 @@ +/* + * viratomic.c: atomic operations + * + * Copyright (C) 2011 Hu Tao + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Hu Tao + */ + +#include + +#include "viratomic.h" + +#if defined(__GNUC__) + +long virAtomicInc(long *value) +{ + return __sync_add_and_fetch(value, 1); +} + +long virAtomicDec(long *value) +{ + return __sync_sub_and_fetch(value, 1); +} + +#elif defined(WIN32) + +long virAtomicInc(long *value) +{ + return InterlockedIncrement(value); +} + +long virAtomicDec(long *value) +{ + return InterlockedDecrement(value); +} + +#else + +#include "threads.h" + +static virMutex virAtomicLock = VIR_MUTEX_INITIALIZER; + +long virAtomicInc(long *value) +{ + long result; + virMutexLock(&virAtomicLock); + *value += 1; + result = *value; + virMutexUnlock(&virAtomicLock); + + return result; +} + +long virAtomicDec(long *value) +{ + long result; + virMutexLock(&virAtomicLock); + *value -= 1; + result = *value; + virMutexUnlock(&virAtomicLock); + + return result; +} + +#endif diff --git a/src/util/viratomic.h b/src/util/viratomic.h new file mode 100644 index 0000000..2b40c77 --- /dev/null +++ b/src/util/viratomic.h @@ -0,0 +1,32 @@ +/* + * viratomic.h: atomic operations + * + * Copyright (C) 2011 Hu Tao + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Hu Tao + */ + +#ifndef __VIR_ATOMIC_H +#define __VIR_ATOMIC_H + +#include "internal.h" + +long virAtomicInc(long *value) ATTRIBUTE_NONNULL(1); +long virAtomicDec(long *value) ATTRIBUTE_NONNULL(1); + +#endif /* __VIR_ATOMIC_H */ diff --git a/src/util/virobject.c b/src/util/virobject.c new file mode 100644 index 0000000..0af53e9 --- /dev/null +++ b/src/util/virobject.c @@ -0,0 +1,64 @@ +/* + * virobject.c: base object that manages reference-counting + * + * Copyright (C) 2011 Hu Tao + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Hu Tao + */ + +#include + +#include "viratomic.h" +#include "virobject.h" +#include "logging.h" + +int virObjectInit(virObjectPtr obj, virObjectFree f) +{ + if (obj->free) { + /* This means the obj is already initialized. A second + * initialization will destroy ref field, which is bad. + */ + VIR_ERROR("Object %p is already initialized.", obj); + return -1; + } + + if (!f) { + VIR_ERROR0("virObjectFree method is required."); + abort(); + } + + obj->ref = 1; + obj->free = f; + + return 0; +} + +void virObjectRef(virObjectPtr obj) +{ + if (virAtomicInc(&obj->ref) < 2) + abort(); /* BUG if we get here */ +} + +void virObjectUnref(virObjectPtr obj) +{ + long ref = virAtomicDec(&obj->ref); + if (ref == 0) + obj->free(obj); + else if (ref < 0) + abort(); /* BUG if we get here */ +} diff --git a/src/util/virobject.h b/src/util/virobject.h new file mode 100644 index 0000000..a9d3d35 --- /dev/null +++ b/src/util/virobject.h @@ -0,0 +1,86 @@ +/* + * virobject.h: base object that manages reference-counting + * + * Copyright (C) 2011 Hu Tao + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Hu Tao + */ + +#ifndef __VIR_OBJECT_H +#define __VIR_OBJECT_H + +typedef struct _virObject virObject; +typedef virObject *virObjectPtr; + +typedef void (*virObjectFree)(virObjectPtr obj); + +/* A thread owns a virObject by incrementing its reference-count by 1. + * If a thread owns a virObject, the virObject is guarenteed not be + * freed until the thread releases ownership by decrementing its + * reference-count by 1. A thread can't access a virObject after it + * releases the ownership of virObject because it can be freed at + * anytime. + * + * A thread can own a virObject legally in these ways: + * + * - a thread owns a virObject that it creates. + * - a thread owns a virObject if another thread passes the ownership + * to it. Example: qemuMonitorOpen + * - a thread gets a virObject from a container. + * Example: virDomainFindByUUID + * - a container owns a virObject by incrementing its reference-count + * by 1 before adding it to the container + * - if a virObject is removed from a container its reference-count + * must be decremented by 1 + */ +/* + * Usage of virObject: + * + * 1. embed virObject into your struct as the first member. + * + * struct foo { + * virObject obj; // must be the first member + * ... + * } + * + * 2. call virObjectInit(obj, fooFree) in your struct's initialization + * function. fooFree is the free method which be called automatically + * when the ref count becomes 0. + * + * 3. implement two functions to ref/unref your struct like this: + * + * void FooRef(struct foo *f) + * { + * virObjectRef(f->obj); + * } + * + * void FooUnref(struct foo *f) + * { + * virObjectUnref(f->obj); + * } + */ +struct _virObject { + long ref; + virObjectFree free; +}; + +int virObjectInit(virObjectPtr obj, virObjectFree f); +void virObjectRef(virObjectPtr obj); +void virObjectUnref(virObjectPtr obj); + +#endif /* __VIR_OBJECT_H */ -- 1.7.3.1 -- Thanks, Hu Tao From berrange at redhat.com Wed Apr 20 09:40:16 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 20 Apr 2011 10:40:16 +0100 Subject: [libvirt] RFC: virInterface change transaction API In-Reply-To: <4DADE3EE.7080005@laine.org> References: <4D9F6279.6040806@laine.org> <20110414130302.GG24239@redhat.com> <20110418165305.GL4648@redhat.com> <20110419145940.GC22023@redhat.com> <4DADE3EE.7080005@laine.org> Message-ID: <20110420094016.GA12989@redhat.com> On Tue, Apr 19, 2011 at 03:35:10PM -0400, Laine Stump wrote: > On 04/19/2011 10:59 AM, Dan Kenigsberg wrote: > >On Mon, Apr 18, 2011 at 05:53:05PM +0100, Daniel P. Berrange wrote: > >>On Thu, Apr 14, 2011 at 04:03:03PM +0300, Dan Kenigsberg wrote: > >>>On Fri, Apr 08, 2011 at 03:31:05PM -0400, Laine Stump wrote: > >>>>1) libvirt > >>>> > >>>> At the libvirt layer, this feature just requires 3 new APIs, which > >>>> are directly passed through to netcf: > >>>> > >>>> virInterfaceChangeStart(virConnectPtr conn, unsigned int flags); > >>>> virInterfaceChangeCommit(virConnectPtr conn, unsigned int flags); > >>>> virInterfaceChangeRollback(virConnectPtr conn, unsigned int flags); > >>>> > >>>> For the initial implementation, these will be simple passthroughs > >>>> to similarly named netcf functions. (in the future, it would be > >>>> useful for the server side of libvirt to determine if client<->server > >>>> connectivity was lost due to the network changes, and automatically > >>>> tell netcf to do a rollback). > >>>When such a feature is added, we should make it dependent on FLAG_AUTO_ROLLBACK > >>>passed to ChangeStart. Higher levels on the management stack may want full > >>>controll over when rollback happens. > >>I don't think a AUTO_ROLLBACK flag is sufficient. You'd almost certainly > >>want to pass some info such as hostname/port number to test, and perhaps > >>a test timeout in milliseconds, and perhaps a retry count. > >Yes, that's why I wanted complete control over auto rollback, when it is > >inroduced. > > What about the rollback that takes place at boot time if the changes > haven't been committed? Should that *always* happen, or should it be > controllable by flags as well. I had intended that at least that > automatic rollback would be present in the first implementation... Rollback on reboot should always happen. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From jason.krieg at collax.com Wed Apr 20 09:41:27 2011 From: jason.krieg at collax.com (Jason Krieg) Date: Wed, 20 Apr 2011 11:41:27 +0200 Subject: [libvirt] tunnelled migration with libvirt 0.9.0 Message-ID: <4DAEAA47.6080500@collax.com> Hi, is tunnelled migration with libvirt 0.9.0 and qemu-kvm 0.14.0 broken ? all I get is an error "unknown migration protocol" while looking at the code in src/qemu/qemu_migration.c src/qemu/qemu_migration.c: /* Start the QEMU daemon, with the same command-line arguments plus * -incoming stdin (which qemu_command might convert to exec:cat or fd:n) */ internalret = qemuProcessStart(dconn, driver, vm, "stdin", true, dataFD[1], NULL, VIR_VM_OP_MIGRATE_IN_START); migrateFrom is set to "stdin" but in src/qemu/qemu_command.c there is no such match which ends in the above error. Regards, Jason From berrange at redhat.com Wed Apr 20 10:24:11 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 20 Apr 2011 11:24:11 +0100 Subject: [libvirt] [libvirt-snmp][PATCH v5 4/4] Add SNMP trap/notification support. In-Reply-To: <1302784253-2608-5-git-send-email-mprivozn@redhat.com> References: <1302784253-2608-1-git-send-email-mprivozn@redhat.com> <1302784253-2608-5-git-send-email-mprivozn@redhat.com> Message-ID: <20110420102411.GC12989@redhat.com> On Thu, Apr 14, 2011 at 02:30:53PM +0200, Michal Privoznik wrote: > This patch adds support for domain lifecycle notification support > over SNMP traps. SNMP subagent monitors any domain events and when > something interesting happens, it sends a trap. > > Monitoring is done in a joinable thread using polling (used > domain-events example from libvirt) so we won't block the agent itself. > > Some debug info can be printed out by setting LIBVIRT_SNMP_VERBOSE > environment variable. > --- > INSTALL.1st | 9 +- > configure.ac | 17 +- > libvirt-snmp.spec.in | 7 +- > src/Makefile.am | 21 ++- > src/README.txt | 2 + > src/event_poll.c | 724 ++++++++++++++++++++++++++++++++++++++++++++ > src/event_poll.h | 132 ++++++++ > src/ignore-value.h | 64 ++++ > src/internal.h | 267 ++++++++++++++++ > src/libvirtNotifications.c | 16 +- > src/libvirtNotifications.h | 16 +- > src/libvirtSnmp.c | 154 +++++++++- > src/memory.c | 313 +++++++++++++++++++ > src/memory.h | 212 +++++++++++++ > src/threads.c | 251 +++++++++++++++ > src/threads.h | 101 ++++++ > src/util.c | 105 +++++++ > src/util.h | 38 +++ > 18 files changed, 2433 insertions(+), 16 deletions(-) > create mode 100644 src/event_poll.c > create mode 100644 src/event_poll.h > create mode 100644 src/ignore-value.h > create mode 100644 src/internal.h > create mode 100644 src/memory.c > create mode 100644 src/memory.h > create mode 100644 src/threads.c > create mode 100644 src/threads.h > create mode 100644 src/util.c > create mode 100644 src/util.h > > diff --git a/INSTALL.1st b/INSTALL.1st > index 31345d8..c439bf3 100644 > --- a/INSTALL.1st > +++ b/INSTALL.1st > @@ -15,14 +15,17 @@ Now it's time for make: > make > su -c "make install" > > -This compile all sources producing runable SNMP subagent > -libvirtMib_subagent, which is installed right after. > +This compiles all source producing a runnable SNMP subagent, > +libvirtMib_subagent, which is installed afterward. > But before we run it, we need to edit /etc/snmp/snmpd.conf > -so it contains this two lines: > +so it contains these four lines: > > rwcommunity public > master agentx > > +trap2sink localhost > +trapcommunity public > + > and then restart snmpd: > /etc/init.d/snmpd restart > > diff --git a/configure.ac b/configure.ac > index dcab0ae..d12f540 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -1,4 +1,4 @@ > -AC_INIT([libvirt-snmp],[0.0.1],[libvir-list at redhat.com],[],[http://libvirt.org]) > +AC_INIT([libvirt-snmp],[0.0.2],[libvir-list at redhat.com],[],[http://libvirt.org]) > AM_INIT_AUTOMAKE([-Wall -Werror]) > AC_CONFIG_HEADERS([config.h]) > > @@ -32,6 +32,14 @@ fi > AC_SUBST([LIBVIRT_CFLAGS]) > AC_SUBST([LIBVIRT_LIBS]) > > +dnl do we have old libvirt? > +AC_CHECK_LIB([virt], [virEventRunDefaultImpl], [old=0], [old=1]) > +if test $old = 1 ; then > + AC_DEFINE_UNQUOTED([LIBVIRT_OLD], ["$old"], [we are using old libvirt > + which does not have new event api]) > +fi > +AM_CONDITIONAL([LIBVIRT_OLD], [test $old = 1]) > + > SNMP_CONFIG="net-snmp-config" > SNMP_CFLAGS="" > SNMP_LIBS="" > @@ -86,5 +94,12 @@ fi > > AC_SUBST([MIB_DIR]) > > +dnl pthread > +PTHREAD_LIBS= > +AC_CHECK_HEADERS(pthread.h, [], [AC_MSG_ERROR([pthread.h required])]) > +AC_CHECK_LIB(pthread, pthread_create, [PTHREAD_LIBS="-lpthread"]) > + > +AC_SUBST([PTHREAD_LIBS]) > + > AC_OUTPUT(Makefile src/Makefile docs/Makefile libvirt-snmp.spec) > > diff --git a/libvirt-snmp.spec.in b/libvirt-snmp.spec.in > index bbc5602..293c375 100644 > --- a/libvirt-snmp.spec.in > +++ b/libvirt-snmp.spec.in > @@ -1,6 +1,6 @@ > Name: libvirt-snmp > Version: @VERSION@ > -Release: 3%{?dist}%{?extra_release} > +Release: 1%{?dist}%{?extra_release} > Summary: SNMP functionality for libvirt > > Group: Development/Libraries > @@ -36,8 +36,11 @@ make install DESTDIR=$RPM_BUILD_ROOT > > > %changelog > +* Wed Mar 23 2011 Michal Privoznik 0.0.2-1 > +- add SNMP trap/notification support > + > * Fri Mar 11 2011 Michal Privoznik 0.0.1-3 > -- remove LIBVIRT-MIB.txt from %doc > +- remove LIBVIRT-MIB.txt from doc > > * Wed Mar 9 2011 Michal Privoznik 0.0.1-2 > - resolve licensing conflicts > diff --git a/src/Makefile.am b/src/Makefile.am > index dcd463a..1a60c91 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -9,8 +9,23 @@ AM_CFLAGS = \ > > AM_LDFLAGS = \ > $(COVERAGE_LDFLAGS) \ > + $(PTHREAD_LIBS) \ > $(SNMP_LIBS) > > +LIBVIRT_OLD_SRCS = \ > + threads.c \ > + event_poll.c \ > + memory.c \ > + util.c > + > +LIBVIRT_OLD_HDRS = \ > + internal.h \ > + ignore-value.h \ > + threads.h \ > + event_poll.h \ > + memory.h \ > + util.h > + > USER_SRCS = \ > libvirtGuestTable_data_get.c \ > libvirtGuestTable_data_set.c \ > @@ -43,10 +58,14 @@ HDRS = \ > libvirtMib_subagent_SOURCES=${SRCS} ${HDRS} > libvirtMib_subagent_LDFLAGS=${AM_LDFLAGS} > > +if LIBVIRT_OLD > +libvirtMib_subagent_SOURCES+=${LIBVIRT_OLD_SRCS} ${LIBVIRT_OLD_HDRS} > +endif > + > EXTRA_DIST = LIBVIRT-MIB.txt > > install-data-local: > - $(MKDIR_P) "$(DESTDIR)$(MIB_DIR)" > + test -z "$(DESTDIR)$(MIB_DIR)" || @mkdir_p@ "$(DESTDIR)$(MIB_DIR)" > $(INSTALL_DATA) "$(srcdir)/LIBVIRT-MIB.txt" \ > "$(DESTDIR)$(MIB_DIR)/LIBVIRT-MIB.txt" > > diff --git a/src/README.txt b/src/README.txt > index 6d010f6..5e9823a 100644 > --- a/src/README.txt > +++ b/src/README.txt > @@ -47,6 +47,8 @@ $ make > 2. use following /etc/snmp/snmpd.conf: > rwcommunity public > master agentx > +trap2sink localhost > +trapcommunity public > > 3. service snmpd start > > diff --git a/src/event_poll.c b/src/event_poll.c > new file mode 100644 > index 0000000..f8c4a8b > --- /dev/null > +++ b/src/event_poll.c > @@ -0,0 +1,724 @@ > +/* > + * event.c: event loop for monitoring file handles > + * > + * Copyright (C) 2007, 2010-2011 Red Hat, Inc. > + * Copyright (C) 2007 Daniel P. Berrange > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + * > + * Author: Daniel P. Berrange > + */ > + > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "threads.h" > +#include "event_poll.h" > +#include "memory.h" > +#include "util.h" > +#include "ignore-value.h" > + > +#define EVENT_DEBUG(fmt, ...) VIR_DEBUG(fmt, __VA_ARGS__) > + > +static int virEventPollInterruptLocked(void); > + > +/* State for a single file handle being monitored */ > +struct virEventPollHandle { > + int watch; > + int fd; > + int events; > + virEventHandleCallback cb; > + virFreeCallback ff; > + void *opaque; > + int deleted; > +}; > + > +/* State for a single timer being generated */ > +struct virEventPollTimeout { > + int timer; > + int frequency; > + unsigned long long expiresAt; > + virEventTimeoutCallback cb; > + virFreeCallback ff; > + void *opaque; > + int deleted; > +}; > + > +/* Allocate extra slots for virEventPollHandle/virEventPollTimeout > + records in this multiple */ > +#define EVENT_ALLOC_EXTENT 10 > + > +/* State for the main event loop */ > +struct virEventPollLoop { > + virMutex lock; > + int running; > + virThread leader; > + int wakeupfd[2]; > + size_t handlesCount; > + size_t handlesAlloc; > + struct virEventPollHandle *handles; > + size_t timeoutsCount; > + size_t timeoutsAlloc; > + struct virEventPollTimeout *timeouts; > +}; > + > +/* Only have one event loop */ > +static struct virEventPollLoop eventLoop; > + > +/* Unique ID for the next FD watch to be registered */ > +static int nextWatch = 1; > + > +/* Unique ID for the next timer to be registered */ > +static int nextTimer = 1; > + > +/* > + * Register a callback for monitoring file handle events. > + * NB, it *must* be safe to call this from within a callback > + * For this reason we only ever append to existing list. > + */ > +int virEventPollAddHandle(int fd, int events, > + virEventHandleCallback cb, > + void *opaque, > + virFreeCallback ff) { > + int watch; > + EVENT_DEBUG("Add handle fd=%d events=%d cb=%p opaque=%p", fd, events, cb, opaque); > + virMutexLock(&eventLoop.lock); > + if (eventLoop.handlesCount == eventLoop.handlesAlloc) { > + EVENT_DEBUG("Used %zu handle slots, adding at least %d more", > + eventLoop.handlesAlloc, EVENT_ALLOC_EXTENT); > + if (VIR_RESIZE_N(eventLoop.handles, eventLoop.handlesAlloc, > + eventLoop.handlesCount, EVENT_ALLOC_EXTENT) < 0) { > + virMutexUnlock(&eventLoop.lock); > + return -1; > + } > + } > + > + watch = nextWatch++; > + > + eventLoop.handles[eventLoop.handlesCount].watch = watch; > + eventLoop.handles[eventLoop.handlesCount].fd = fd; > + eventLoop.handles[eventLoop.handlesCount].events = > + virEventPollToNativeEvents(events); > + eventLoop.handles[eventLoop.handlesCount].cb = cb; > + eventLoop.handles[eventLoop.handlesCount].ff = ff; > + eventLoop.handles[eventLoop.handlesCount].opaque = opaque; > + eventLoop.handles[eventLoop.handlesCount].deleted = 0; > + > + eventLoop.handlesCount++; > + > + virEventPollInterruptLocked(); > + virMutexUnlock(&eventLoop.lock); > + > + return watch; > +} > + > +void virEventPollUpdateHandle(int watch, int events) { > + int i; > + EVENT_DEBUG("Update handle w=%d e=%d", watch, events); > + > + if (watch <= 0) { > + VIR_WARN("Ignoring invalid update watch %d", watch); > + return; > + } > + > + virMutexLock(&eventLoop.lock); > + for (i = 0 ; i < eventLoop.handlesCount ; i++) { > + if (eventLoop.handles[i].watch == watch) { > + eventLoop.handles[i].events = > + virEventPollToNativeEvents(events); > + virEventPollInterruptLocked(); > + break; > + } > + } > + virMutexUnlock(&eventLoop.lock); > +} > + > +/* > + * Unregister a callback from a file handle > + * NB, it *must* be safe to call this from within a callback > + * For this reason we only ever set a flag in the existing list. > + * Actual deletion will be done out-of-band > + */ > +int virEventPollRemoveHandle(int watch) { > + int i; > + EVENT_DEBUG("Remove handle w=%d", watch); > + > + if (watch <= 0) { > + VIR_WARN("Ignoring invalid remove watch %d", watch); > + return -1; > + } > + > + virMutexLock(&eventLoop.lock); > + for (i = 0 ; i < eventLoop.handlesCount ; i++) { > + if (eventLoop.handles[i].deleted) > + continue; > + > + if (eventLoop.handles[i].watch == watch) { > + EVENT_DEBUG("mark delete %d %d", i, eventLoop.handles[i].fd); > + eventLoop.handles[i].deleted = 1; > + virEventPollInterruptLocked(); > + virMutexUnlock(&eventLoop.lock); > + return 0; > + } > + } > + virMutexUnlock(&eventLoop.lock); > + return -1; > +} > + > + > +/* > + * Register a callback for a timer event > + * NB, it *must* be safe to call this from within a callback > + * For this reason we only ever append to existing list. > + */ > +int virEventPollAddTimeout(int frequency, > + virEventTimeoutCallback cb, > + void *opaque, > + virFreeCallback ff) { > + struct timeval now; > + int ret; > + EVENT_DEBUG("Adding timer %d with %d ms freq", nextTimer, frequency); > + if (gettimeofday(&now, NULL) < 0) { > + return -1; > + } > + > + virMutexLock(&eventLoop.lock); > + if (eventLoop.timeoutsCount == eventLoop.timeoutsAlloc) { > + EVENT_DEBUG("Used %zu timeout slots, adding at least %d more", > + eventLoop.timeoutsAlloc, EVENT_ALLOC_EXTENT); > + if (VIR_RESIZE_N(eventLoop.timeouts, eventLoop.timeoutsAlloc, > + eventLoop.timeoutsCount, EVENT_ALLOC_EXTENT) < 0) { > + virMutexUnlock(&eventLoop.lock); > + return -1; > + } > + } > + > + eventLoop.timeouts[eventLoop.timeoutsCount].timer = nextTimer++; > + eventLoop.timeouts[eventLoop.timeoutsCount].frequency = frequency; > + eventLoop.timeouts[eventLoop.timeoutsCount].cb = cb; > + eventLoop.timeouts[eventLoop.timeoutsCount].ff = ff; > + eventLoop.timeouts[eventLoop.timeoutsCount].opaque = opaque; > + eventLoop.timeouts[eventLoop.timeoutsCount].deleted = 0; > + eventLoop.timeouts[eventLoop.timeoutsCount].expiresAt = > + frequency >= 0 ? frequency + > + (((unsigned long long)now.tv_sec)*1000) + > + (((unsigned long long)now.tv_usec)/1000) : 0; > + > + eventLoop.timeoutsCount++; > + ret = nextTimer-1; > + virEventPollInterruptLocked(); > + virMutexUnlock(&eventLoop.lock); > + return ret; > +} > + > +void virEventPollUpdateTimeout(int timer, int frequency) { > + struct timeval tv; > + int i; > + EVENT_DEBUG("Updating timer %d timeout with %d ms freq", timer, frequency); > + > + if (timer <= 0) { > + VIR_WARN("Ignoring invalid update timer %d", timer); > + return; > + } > + > + if (gettimeofday(&tv, NULL) < 0) { > + return; > + } > + > + virMutexLock(&eventLoop.lock); > + for (i = 0 ; i < eventLoop.timeoutsCount ; i++) { > + if (eventLoop.timeouts[i].timer == timer) { > + eventLoop.timeouts[i].frequency = frequency; > + eventLoop.timeouts[i].expiresAt = > + frequency >= 0 ? frequency + > + (((unsigned long long)tv.tv_sec)*1000) + > + (((unsigned long long)tv.tv_usec)/1000) : 0; > + virEventPollInterruptLocked(); > + break; > + } > + } > + virMutexUnlock(&eventLoop.lock); > +} > + > +/* > + * Unregister a callback for a timer > + * NB, it *must* be safe to call this from within a callback > + * For this reason we only ever set a flag in the existing list. > + * Actual deletion will be done out-of-band > + */ > +int virEventPollRemoveTimeout(int timer) { > + int i; > + EVENT_DEBUG("Remove timer %d", timer); > + > + if (timer <= 0) { > + VIR_WARN("Ignoring invalid remove timer %d", timer); > + return -1; > + } > + > + virMutexLock(&eventLoop.lock); > + for (i = 0 ; i < eventLoop.timeoutsCount ; i++) { > + if (eventLoop.timeouts[i].deleted) > + continue; > + > + if (eventLoop.timeouts[i].timer == timer) { > + eventLoop.timeouts[i].deleted = 1; > + virEventPollInterruptLocked(); > + virMutexUnlock(&eventLoop.lock); > + return 0; > + } > + } > + virMutexUnlock(&eventLoop.lock); > + return -1; > +} > + > +/* Iterates over all registered timeouts and determine which > + * will be the first to expire. > + * @timeout: filled with expiry time of soonest timer, or -1 if > + * no timeout is pending > + * returns: 0 on success, -1 on error > + */ > +static int virEventPollCalculateTimeout(int *timeout) { > + unsigned long long then = 0; > + int i; > + EVENT_DEBUG("Calculate expiry of %zu timers", eventLoop.timeoutsCount); > + /* Figure out if we need a timeout */ > + for (i = 0 ; i < eventLoop.timeoutsCount ; i++) { > + if (eventLoop.timeouts[i].frequency < 0) > + continue; > + > + EVENT_DEBUG("Got a timeout scheduled for %llu", eventLoop.timeouts[i].expiresAt); > + if (then == 0 || > + eventLoop.timeouts[i].expiresAt < then) > + then = eventLoop.timeouts[i].expiresAt; > + } > + > + /* Calculate how long we should wait for a timeout if needed */ > + if (then > 0) { > + struct timeval tv; > + > + if (gettimeofday(&tv, NULL) < 0) { > + perror("Unable to get current time"); > + return -1; > + } > + > + *timeout = then - > + ((((unsigned long long)tv.tv_sec)*1000) + > + (((unsigned long long)tv.tv_usec)/1000)); > + > + if (*timeout < 0) > + *timeout = 0; > + } else { > + *timeout = -1; > + } > + > + EVENT_DEBUG("Timeout at %llu due in %d ms", then, *timeout); > + > + return 0; > +} > + > +/* > + * Allocate a pollfd array containing data for all registered > + * file handles. The caller must free the returned data struct > + * returns: the pollfd array, or NULL on error > + */ > +static struct pollfd *virEventPollMakePollFDs(int *nfds) { > + struct pollfd *fds; > + int i; > + > + *nfds = 0; > + for (i = 0 ; i < eventLoop.handlesCount ; i++) { > + if (eventLoop.handles[i].events && !eventLoop.handles[i].deleted) > + (*nfds)++; > + } > + > + /* Setup the poll file handle data structs */ > + if (VIR_ALLOC_N(fds, *nfds) < 0) { > + perror("unable to allocate memory"); > + return NULL; > + } > + > + *nfds = 0; > + for (i = 0 ; i < eventLoop.handlesCount ; i++) { > + EVENT_DEBUG("Prepare n=%d w=%d, f=%d e=%d d=%d", i, > + eventLoop.handles[i].watch, > + eventLoop.handles[i].fd, > + eventLoop.handles[i].events, > + eventLoop.handles[i].deleted); > + if (!eventLoop.handles[i].events || eventLoop.handles[i].deleted) > + continue; > + fds[*nfds].fd = eventLoop.handles[i].fd; > + fds[*nfds].events = eventLoop.handles[i].events; > + fds[*nfds].revents = 0; > + (*nfds)++; > + //EVENT_DEBUG("Wait for %d %d", eventLoop.handles[i].fd, eventLoop.handles[i].events); > + } > + > + return fds; > +} > + > + > +/* > + * Iterate over all timers and determine if any have expired. > + * Invoke the user supplied callback for each timer whose > + * expiry time is met, and schedule the next timeout. Does > + * not try to 'catch up' on time if the actual expiry time > + * was later than the requested time. > + * > + * This method must cope with new timers being registered > + * by a callback, and must skip any timers marked as deleted. > + * > + * Returns 0 upon success, -1 if an error occurred > + */ > +static int virEventPollDispatchTimeouts(void) { > + struct timeval tv; > + unsigned long long now; > + int i; > + /* Save this now - it may be changed during dispatch */ > + int ntimeouts = eventLoop.timeoutsCount; > + VIR_DEBUG("Dispatch %d", ntimeouts); > + > + if (gettimeofday(&tv, NULL) < 0) { > + perror("Unable to get current time"); > + return -1; > + } > + now = (((unsigned long long)tv.tv_sec)*1000) + > + (((unsigned long long)tv.tv_usec)/1000); > + > + for (i = 0 ; i < ntimeouts ; i++) { > + if (eventLoop.timeouts[i].deleted || eventLoop.timeouts[i].frequency < 0) > + continue; > + > + /* Add 20ms fuzz so we don't pointlessly spin doing > + * <10ms sleeps, particularly on kernels with low HZ > + * it is fine that a timer expires 20ms earlier than > + * requested > + */ > + if (eventLoop.timeouts[i].expiresAt <= (now+20)) { > + virEventTimeoutCallback cb = eventLoop.timeouts[i].cb; > + int timer = eventLoop.timeouts[i].timer; > + void *opaque = eventLoop.timeouts[i].opaque; > + eventLoop.timeouts[i].expiresAt = > + now + eventLoop.timeouts[i].frequency; > + > + virMutexUnlock(&eventLoop.lock); > + (cb)(timer, opaque); > + virMutexLock(&eventLoop.lock); > + } > + } > + return 0; > +} > + > + > +/* Iterate over all file handles and dispatch any which > + * have pending events listed in the poll() data. Invoke > + * the user supplied callback for each handle which has > + * pending events > + * > + * This method must cope with new handles being registered > + * by a callback, and must skip any handles marked as deleted. > + * > + * Returns 0 upon success, -1 if an error occurred > + */ > +static int virEventPollDispatchHandles(int nfds, struct pollfd *fds) { > + int i, n; > + VIR_DEBUG("Dispatch %d", nfds); > + > + /* NB, use nfds not eventLoop.handlesCount, because new > + * fds might be added on end of list, and they're not > + * in the fds array we've got */ > + for (i = 0, n = 0 ; n < nfds && i < eventLoop.handlesCount ; n++) { > + while ((eventLoop.handles[i].fd != fds[n].fd || > + eventLoop.handles[i].events == 0) && > + i < eventLoop.handlesCount) { > + i++; > + } > + if (i == eventLoop.handlesCount) > + break; > + > + VIR_DEBUG("i=%d w=%d", i, eventLoop.handles[i].watch); > + if (eventLoop.handles[i].deleted) { > + EVENT_DEBUG("Skip deleted n=%d w=%d f=%d", i, > + eventLoop.handles[i].watch, eventLoop.handles[i].fd); > + continue; > + } > + > + if (fds[n].revents) { > + virEventHandleCallback cb = eventLoop.handles[i].cb; > + int watch = eventLoop.handles[i].watch; > + void *opaque = eventLoop.handles[i].opaque; > + int hEvents = virEventPollFromNativeEvents(fds[n].revents); > + EVENT_DEBUG("Dispatch n=%d f=%d w=%d e=%d %p", i, > + fds[n].fd, watch, fds[n].revents, opaque); > + virMutexUnlock(&eventLoop.lock); > + (cb)(watch, fds[n].fd, hEvents, opaque); > + virMutexLock(&eventLoop.lock); > + } > + } > + > + return 0; > +} > + > + > +/* Used post dispatch to actually remove any timers that > + * were previously marked as deleted. This asynchronous > + * cleanup is needed to make dispatch re-entrant safe. > + */ > +static void virEventPollCleanupTimeouts(void) { > + int i; > + size_t gap; > + VIR_DEBUG("Cleanup %zu", eventLoop.timeoutsCount); > + > + /* Remove deleted entries, shuffling down remaining > + * entries as needed to form contiguous series > + */ > + for (i = 0 ; i < eventLoop.timeoutsCount ; ) { > + if (!eventLoop.timeouts[i].deleted) { > + i++; > + continue; > + } > + > + EVENT_DEBUG("Purging timeout %d with id %d", i, > + eventLoop.timeouts[i].timer); > + if (eventLoop.timeouts[i].ff) { > + virFreeCallback ff = eventLoop.timeouts[i].ff; > + void *opaque = eventLoop.timeouts[i].opaque; > + virMutexUnlock(&eventLoop.lock); > + ff(opaque); > + virMutexLock(&eventLoop.lock); > + } > + > + if ((i+1) < eventLoop.timeoutsCount) { > + memmove(eventLoop.timeouts+i, > + eventLoop.timeouts+i+1, > + sizeof(struct virEventPollTimeout)*(eventLoop.timeoutsCount > + -(i+1))); > + } > + eventLoop.timeoutsCount--; > + } > + > + /* Release some memory if we've got a big chunk free */ > + gap = eventLoop.timeoutsAlloc - eventLoop.timeoutsCount; > + if (eventLoop.timeoutsCount == 0 || > + (gap > eventLoop.timeoutsCount && gap > EVENT_ALLOC_EXTENT)) { > + EVENT_DEBUG("Found %zu out of %zu timeout slots used, releasing %zu", > + eventLoop.timeoutsCount, eventLoop.timeoutsAlloc, gap); > + VIR_SHRINK_N(eventLoop.timeouts, eventLoop.timeoutsAlloc, gap); > + } > +} > + > +/* Used post dispatch to actually remove any handles that > + * were previously marked as deleted. This asynchronous > + * cleanup is needed to make dispatch re-entrant safe. > + */ > +static void virEventPollCleanupHandles(void) { > + int i; > + size_t gap; > + VIR_DEBUG("Cleanup %zu", eventLoop.handlesCount); > + > + /* Remove deleted entries, shuffling down remaining > + * entries as needed to form contiguous series > + */ > + for (i = 0 ; i < eventLoop.handlesCount ; ) { > + if (!eventLoop.handles[i].deleted) { > + i++; > + continue; > + } > + > + if (eventLoop.handles[i].ff) { > + virFreeCallback ff = eventLoop.handles[i].ff; > + void *opaque = eventLoop.handles[i].opaque; > + virMutexUnlock(&eventLoop.lock); > + ff(opaque); > + virMutexLock(&eventLoop.lock); > + } > + > + if ((i+1) < eventLoop.handlesCount) { > + memmove(eventLoop.handles+i, > + eventLoop.handles+i+1, > + sizeof(struct virEventPollHandle)*(eventLoop.handlesCount > + -(i+1))); > + } > + eventLoop.handlesCount--; > + } > + > + /* Release some memory if we've got a big chunk free */ > + gap = eventLoop.handlesAlloc - eventLoop.handlesCount; > + if (eventLoop.handlesCount == 0 || > + (gap > eventLoop.handlesCount && gap > EVENT_ALLOC_EXTENT)) { > + EVENT_DEBUG("Found %zu out of %zu handles slots used, releasing %zu", > + eventLoop.handlesCount, eventLoop.handlesAlloc, gap); > + VIR_SHRINK_N(eventLoop.handles, eventLoop.handlesAlloc, gap); > + } > +} > + > +/* > + * Run a single iteration of the event loop, blocking until > + * at least one file handle has an event, or a timer expires > + */ > +int virEventPollRunOnce(void) { > + struct pollfd *fds = NULL; > + int ret, timeout, nfds; > + > + virMutexLock(&eventLoop.lock); > + eventLoop.running = 1; > + virThreadSelf(&eventLoop.leader); > + > + virEventPollCleanupTimeouts(); > + virEventPollCleanupHandles(); > + > + if (!(fds = virEventPollMakePollFDs(&nfds)) || > + virEventPollCalculateTimeout(&timeout) < 0) > + goto error; > + > + virMutexUnlock(&eventLoop.lock); > + > + retry: > + EVENT_DEBUG("Poll on %d handles %p timeout %d", nfds, fds, timeout); > + ret = poll(fds, nfds, timeout); > + if (ret < 0) { > + EVENT_DEBUG("Poll got error event %d", errno); > + if (errno == EINTR) { > + goto retry; > + } > + perror("Unable to poll on file handles"); > + goto error_unlocked; > + } > + EVENT_DEBUG("Poll got %d event(s)", ret); > + > + virMutexLock(&eventLoop.lock); > + if (virEventPollDispatchTimeouts() < 0) > + goto error; > + > + if (ret > 0 && > + virEventPollDispatchHandles(nfds, fds) < 0) > + goto error; > + > + virEventPollCleanupTimeouts(); > + virEventPollCleanupHandles(); > + > + eventLoop.running = 0; > + virMutexUnlock(&eventLoop.lock); > + VIR_FREE(fds); > + return 0; > + > +error: > + virMutexUnlock(&eventLoop.lock); > +error_unlocked: > + VIR_FREE(fds); > + return -1; > +} > + > + > +static void virEventPollHandleWakeup(int watch ATTRIBUTE_UNUSED, > + int fd, > + int events ATTRIBUTE_UNUSED, > + void *opaque ATTRIBUTE_UNUSED) > +{ > + char c; > + virMutexLock(&eventLoop.lock); > + ignore_value(saferead(fd, &c, sizeof(c))); > + virMutexUnlock(&eventLoop.lock); > +} > + > +int virEventPollInit(void) > +{ > + if (virMutexInit(&eventLoop.lock) < 0) { > + perror("Unable to initialize mutex"); > + return -1; > + } > + > + if (pipe(eventLoop.wakeupfd) < 0 || > + virSetNonBlock(eventLoop.wakeupfd[0]) < 0 || > + virSetNonBlock(eventLoop.wakeupfd[1]) < 0 || > + virSetCloseExec(eventLoop.wakeupfd[0]) < 0 || > + virSetCloseExec(eventLoop.wakeupfd[1]) < 0) { > + perror("Unable to setup wakeup pipe"); > + return -1; > + } > + > + if (virEventPollAddHandle(eventLoop.wakeupfd[0], > + VIR_EVENT_HANDLE_READABLE, > + virEventPollHandleWakeup, NULL, NULL) < 0) { > + fprintf(stderr, "Unable to add handle %d to event loop", > + eventLoop.wakeupfd[0]); > + return -1; > + } > + > + return 0; > +} > + > +static int virEventPollInterruptLocked(void) > +{ > + char c = '\0'; > + > + if (!eventLoop.running || > + virThreadIsSelf(&eventLoop.leader)) { > + VIR_DEBUG("Skip interrupt, %d %d", eventLoop.running, > + virThreadID(&eventLoop.leader)); > + return 0; > + } > + > + VIR_DEBUG0("Interrupting"); > + if (safewrite(eventLoop.wakeupfd[1], &c, sizeof(c)) != sizeof(c)) > + return -1; > + return 0; > +} > + > +int virEventPollInterrupt(void) > +{ > + int ret; > + virMutexLock(&eventLoop.lock); > + ret = virEventPollInterruptLocked(); > + virMutexUnlock(&eventLoop.lock); > + return ret; > +} > + > +int > +virEventPollToNativeEvents(int events) > +{ > + int ret = 0; > + if(events & VIR_EVENT_HANDLE_READABLE) > + ret |= POLLIN; > + if(events & VIR_EVENT_HANDLE_WRITABLE) > + ret |= POLLOUT; > + if(events & VIR_EVENT_HANDLE_ERROR) > + ret |= POLLERR; > + if(events & VIR_EVENT_HANDLE_HANGUP) > + ret |= POLLHUP; > + return ret; > +} > + > +int > +virEventPollFromNativeEvents(int events) > +{ > + int ret = 0; > + if(events & POLLIN) > + ret |= VIR_EVENT_HANDLE_READABLE; > + if(events & POLLOUT) > + ret |= VIR_EVENT_HANDLE_WRITABLE; > + if(events & POLLERR) > + ret |= VIR_EVENT_HANDLE_ERROR; > + if(events & POLLNVAL) /* Treat NVAL as error, since libvirt doesn't distinguish */ > + ret |= VIR_EVENT_HANDLE_ERROR; > + if(events & POLLHUP) > + ret |= VIR_EVENT_HANDLE_HANGUP; > + return ret; > +} > diff --git a/src/event_poll.h b/src/event_poll.h > new file mode 100644 > index 0000000..4ab3789 > --- /dev/null > +++ b/src/event_poll.h > @@ -0,0 +1,132 @@ > +/* > + * event.h: event loop for monitoring file handles > + * > + * Copyright (C) 2007 Daniel P. Berrange > + * Copyright (C) 2007 Red Hat, Inc. > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + * > + * Author: Daniel P. Berrange > + */ > + > +#ifndef __VIR_EVENT_POLL_H__ > +# define __VIR_EVENT_POLL_H__ > + > +# include "internal.h" > + > +/** > + * virEventPollAddHandle: register a callback for monitoring file handle events > + * > + * @fd: file handle to monitor for events > + * @events: bitset of events to watch from POLLnnn constants > + * @cb: callback to invoke when an event occurs > + * @opaque: user data to pass to callback > + * > + * returns -1 if the file handle cannot be registered, 0 upon success > + */ > +int virEventPollAddHandle(int fd, int events, > + virEventHandleCallback cb, > + void *opaque, > + virFreeCallback ff); > + > +/** > + * virEventPollUpdateHandle: change event set for a monitored file handle > + * > + * @watch: watch whose handle to update > + * @events: bitset of events to watch from POLLnnn constants > + * > + * Will not fail if fd exists > + */ > +void virEventPollUpdateHandle(int watch, int events); > + > +/** > + * virEventPollRemoveHandle: unregister a callback from a file handle > + * > + * @watch: watch whose handle to remove > + * > + * returns -1 if the file handle was not registered, 0 upon success > + */ > +int virEventPollRemoveHandle(int watch); > + > +/** > + * virEventPollAddTimeout: register a callback for a timer event > + * > + * @frequency: time between events in milliseconds > + * @cb: callback to invoke when an event occurs > + * @opaque: user data to pass to callback > + * > + * Setting frequency to -1 will disable the timer. Setting the frequency > + * to zero will cause it to fire on every event loop iteration. > + * > + * returns -1 if the file handle cannot be registered, a positive > + * integer timer id upon success > + */ > +int virEventPollAddTimeout(int frequency, > + virEventTimeoutCallback cb, > + void *opaque, > + virFreeCallback ff); > + > +/** > + * virEventPollUpdateTimeout: change frequency for a timer > + * > + * @timer: timer id to change > + * @frequency: time between events in milliseconds > + * > + * Setting frequency to -1 will disable the timer. Setting the frequency > + * to zero will cause it to fire on every event loop iteration. > + * > + * Will not fail if timer exists > + */ > +void virEventPollUpdateTimeout(int timer, int frequency); > + > +/** > + * virEventPollRemoveTimeout: unregister a callback for a timer > + * > + * @timer: the timer id to remove > + * > + * returns -1 if the timer was not registered, 0 upon success > + */ > +int virEventPollRemoveTimeout(int timer); > + > +/** > + * virEventPollInit: Initialize the event loop > + * > + * returns -1 if initialization failed > + */ > +int virEventPollInit(void); > + > +/** > + * virEventPollRunOnce: run a single iteration of the event loop. > + * > + * Blocks the caller until at least one file handle has an > + * event or the first timer expires. > + * > + * returns -1 if the event monitoring failed > + */ > +int virEventPollRunOnce(void); > + > +int virEventPollFromNativeEvents(int events); > +int virEventPollToNativeEvents(int events); > + > + > +/** > + * virEventPollInterrupt: wakeup any thread waiting in poll() > + * > + * return -1 if wakup failed > + */ > +int virEventPollInterrupt(void); > + > + > +#endif /* __VIRTD_EVENT_H__ */ > diff --git a/src/ignore-value.h b/src/ignore-value.h > new file mode 100644 > index 0000000..0df1c01 > --- /dev/null > +++ b/src/ignore-value.h > @@ -0,0 +1,64 @@ > +/* -*- buffer-read-only: t -*- vi: set ro: */ > +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ > +/* ignore a function return without a compiler warning > + > + Copyright (C) 2008-2011 Free Software Foundation, Inc. > + > + This program is free software: you can redistribute it and/or modify > + it under the terms of the GNU Lesser General Public License as published by > + the Free Software Foundation; either version 2.1 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public License > + along with this program. If not, see . */ > + > +/* Written by Jim Meyering, Eric Blake and P?draig Brady. */ > + > +/* Use "ignore_value" to avoid a warning when using a function declared with > + gcc's warn_unused_result attribute, but for which you really do want to > + ignore the result. Traditionally, people have used a "(void)" cast to > + indicate that a function's return value is deliberately unused. However, > + if the function is declared with __attribute__((warn_unused_result)), > + gcc issues a warning even with the cast. > + > + Caution: most of the time, you really should heed gcc's warning, and > + check the return value. However, in those exceptional cases in which > + you're sure you know what you're doing, use this function. > + > + For the record, here's one of the ignorable warnings: > + "copy.c:233: warning: ignoring return value of 'fchown', > + declared with attribute warn_unused_result". */ > + > +#ifndef _GL_IGNORE_VALUE_H > +# define _GL_IGNORE_VALUE_H > + > +# ifndef _GL_ATTRIBUTE_DEPRECATED > +/* The __attribute__((__deprecated__)) feature > + is available in gcc versions 3.1 and newer. */ > +# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 1) > +# define _GL_ATTRIBUTE_DEPRECATED /* empty */ > +# else > +# define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__)) > +# endif > +# endif > + > +/* The __attribute__((__warn_unused_result__)) feature > + is available in gcc versions 3.4 and newer, > + while the typeof feature has been available since 2.7 at least. */ > +# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) > +# define ignore_value(x) ((void) (x)) > +# else > +# define ignore_value(x) (({ __typeof__ (x) __x = (x); (void) __x; })) > +# endif > + > +/* ignore_value works for scalars, pointers and aggregates; > + deprecate ignore_ptr. */ > +static inline void _GL_ATTRIBUTE_DEPRECATED > +ignore_ptr (void *p) { (void) p; } /* deprecated: use ignore_value */ > + > +#endif > diff --git a/src/internal.h b/src/internal.h > new file mode 100644 > index 0000000..eaa6d70 > --- /dev/null > +++ b/src/internal.h > @@ -0,0 +1,267 @@ > +/* > + * internal.h: internal definitions just used by code from the library > + * > + * Copy: Copyright (C) 2005-2006, 2010-2011 Red Hat, Inc. > + * > + * See libvirt's COPYING.LIB for the License of this software > + * > + */ > + > +#ifndef __INTERNAL_H__ > +# define __INTERNAL_H__ > + > +# include > +# include > +# include > +# include > +# include > +# include > +# include > +# include Since you have included libvirt.h > +/** > + * virEventHandleCallback: > + * > + * @watch: watch on which the event occurred > + * @fd: file handle on which the event occurred > + * @events: bitset of events from virEventHandleType constants > + * @opaque: user data registered with handle > + * > + * Callback for receiving file handle events. The callback will > + * be invoked once for each event which is pending. > + */ > +typedef void (*virEventHandleCallback)(int watch, int fd, int events, void *opaque); > + > +/** > + * virEventAddHandleFunc: > + * @fd: file descriptor to listen on > + * @event: bitset of events on which to fire the callback > + * @cb: the callback to be called when an event occurrs > + * @opaque: user data to pass to the callback > + * @ff: the callback invoked to free opaque data blob > + * > + * Part of the EventImpl, this callback Adds a file handle callback to > + * listen for specific events. The same file handle can be registered > + * multiple times provided the requested event sets are non-overlapping > + * > + * If the opaque user data requires free'ing when the handle > + * is unregistered, then a 2nd callback can be supplied for > + * this purpose. > + * > + * Returns a handle watch number to be used for updating > + * and unregistering for events > + */ > +typedef int (*virEventAddHandleFunc)(int fd, int event, > + virEventHandleCallback cb, > + void *opaque, > + virFreeCallback ff); > + > +/** > + * virEventUpdateHandleFunc: > + * @watch: file descriptor watch to modify > + * @event: new events to listen on > + * > + * Part of the EventImpl, this user-provided callback is notified when > + * events to listen on change > + */ > +typedef void (*virEventUpdateHandleFunc)(int watch, int event); > + > +/** > + * virEventRemoveHandleFunc: > + * @watch: file descriptor watch to stop listening on > + * > + * Part of the EventImpl, this user-provided callback is notified when > + * an fd is no longer being listened on. > + * > + * If a virEventHandleFreeFunc was supplied when the handle was > + * registered, it will be invoked some time during, or after this > + * function call, when it is safe to release the user data. > + */ > +typedef int (*virEventRemoveHandleFunc)(int watch); > + > +/** > + * virEventTimeoutCallback: > + * > + * @timer: timer id emitting the event > + * @opaque: user data registered with handle > + * > + * callback for receiving timer events > + */ > +typedef void (*virEventTimeoutCallback)(int timer, void *opaque); > + > +/** > + * virEventAddTimeoutFunc: > + * @timeout: The timeout to monitor > + * @cb: the callback to call when timeout has expired > + * @opaque: user data to pass to the callback > + * @ff: the callback invoked to free opaque data blob > + * > + * Part of the EventImpl, this user-defined callback handles adding an > + * event timeout. > + * > + * If the opaque user data requires free'ing when the handle > + * is unregistered, then a 2nd callback can be supplied for > + * this purpose. > + * > + * Returns a timer value > + */ > +typedef int (*virEventAddTimeoutFunc)(int timeout, > + virEventTimeoutCallback cb, > + void *opaque, > + virFreeCallback ff); > + > +/** > + * virEventUpdateTimeoutFunc: > + * @timer: the timer to modify > + * @timeout: the new timeout value > + * > + * Part of the EventImpl, this user-defined callback updates an > + * event timeout. > + */ > +typedef void (*virEventUpdateTimeoutFunc)(int timer, int timeout); > + > +/** > + * virEventRemoveTimeoutFunc: > + * @timer: the timer to remove > + * > + * Part of the EventImpl, this user-defined callback removes a timer > + * > + * If a virEventTimeoutFreeFunc was supplied when the handle was > + * registered, it will be invoked some time during, or after this > + * function call, when it is safe to release the user data. > + * > + * Returns 0 on success, -1 on failure > + */ > +typedef int (*virEventRemoveTimeoutFunc)(int timer); > + > +void virEventRegisterImpl(virEventAddHandleFunc addHandle, > + virEventUpdateHandleFunc updateHandle, > + virEventRemoveHandleFunc removeHandle, > + virEventAddTimeoutFunc addTimeout, > + virEventUpdateTimeoutFunc updateTimeout, > + virEventRemoveTimeoutFunc removeTimeout); > + > +int virEventRegisterDefaultImpl(void); > +int virEventRunDefaultImpl(void); You don't need any of these functions or typedefs. ACK if those are removed. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From wency at cn.fujitsu.com Wed Apr 20 10:23:40 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 20 Apr 2011 18:23:40 +0800 Subject: [libvirt] tunnelled migration with libvirt 0.9.0 In-Reply-To: <4DAEAA47.6080500@collax.com> References: <4DAEAA47.6080500@collax.com> Message-ID: <4DAEB42C.70900@cn.fujitsu.com> At 04/20/2011 05:41 PM, Jason Krieg Write: > Hi, > > is tunnelled migration with libvirt 0.9.0 and qemu-kvm 0.14.0 broken ? > > all I get is an error "unknown migration protocol" > > while looking at the code in src/qemu/qemu_migration.c > > src/qemu/qemu_migration.c: > > /* Start the QEMU daemon, with the same command-line arguments plus > * -incoming stdin (which qemu_command might convert to exec:cat or > fd:n) > */ > internalret = qemuProcessStart(dconn, driver, vm, "stdin", true, > dataFD[1], > NULL, VIR_VM_OP_MIGRATE_IN_START); > > > > migrateFrom is set to "stdin" but in src/qemu/qemu_command.c > there is no such match which ends in the above error. Yes, the tunnelled migration has been broken. Please applied the following patch and try it again: >From 55dac9d193644b7957ea730b8739633cd185d494 Mon Sep 17 00:00:00 2001 From: Wen Congyang Date: Wed, 20 Apr 2011 18:20:12 +0800 Subject: [PATCH] fix tunnelled migration's regression If the migrateFrom is "stdio" not "stdin", qemuBuildCommandLine() will convert it to exec:cat or fd:n. --- src/qemu/qemu_migration.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 43741e1..bba76d5 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -316,9 +316,9 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, goto endjob; } /* Start the QEMU daemon, with the same command-line arguments plus - * -incoming stdin (which qemu_command might convert to exec:cat or fd:n) + * -incoming stdio (which qemu_command might convert to exec:cat or fd:n) */ - internalret = qemuProcessStart(dconn, driver, vm, "stdin", true, dataFD[1], + internalret = qemuProcessStart(dconn, driver, vm, "stdio", true, dataFD[1], NULL, VIR_VM_OP_MIGRATE_IN_START); if (internalret < 0) { qemuAuditDomainStart(vm, "migrated", false); -- 1.7.1 > > Regards, > Jason > > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list > From jason.krieg at collax.com Wed Apr 20 11:13:51 2011 From: jason.krieg at collax.com (Jason Krieg) Date: Wed, 20 Apr 2011 13:13:51 +0200 Subject: [libvirt] tunnelled migration with libvirt 0.9.0 In-Reply-To: <4DAEB42C.70900@cn.fujitsu.com> References: <4DAEAA47.6080500@collax.com> <4DAEB42C.70900@cn.fujitsu.com> Message-ID: <4DAEBFEF.1060806@collax.com> On 04/20/2011 12:23 PM, Wen Congyang wrote: > At 04/20/2011 05:41 PM, Jason Krieg Write: >> Hi, >> >> is tunnelled migration with libvirt 0.9.0 and qemu-kvm 0.14.0 broken ? >> >> all I get is an error "unknown migration protocol" >> >> while looking at the code in src/qemu/qemu_migration.c >> >> src/qemu/qemu_migration.c: >> >> /* Start the QEMU daemon, with the same command-line arguments plus >> * -incoming stdin (which qemu_command might convert to exec:cat or >> fd:n) >> */ >> internalret = qemuProcessStart(dconn, driver, vm, "stdin", true, >> dataFD[1], >> NULL, VIR_VM_OP_MIGRATE_IN_START); >> >> >> >> migrateFrom is set to "stdin" but in src/qemu/qemu_command.c >> there is no such match which ends in the above error. > Yes, the tunnelled migration has been broken. > > Please applied the following patch and try it again: > > From 55dac9d193644b7957ea730b8739633cd185d494 Mon Sep 17 00:00:00 2001 > From: Wen Congyang > Date: Wed, 20 Apr 2011 18:20:12 +0800 > Subject: [PATCH] fix tunnelled migration's regression > > If the migrateFrom is "stdio" not "stdin", qemuBuildCommandLine() > will convert it to exec:cat or fd:n. > > --- > src/qemu/qemu_migration.c | 4 ++-- > 1 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c > index 43741e1..bba76d5 100644 > --- a/src/qemu/qemu_migration.c > +++ b/src/qemu/qemu_migration.c > @@ -316,9 +316,9 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, > goto endjob; > } > /* Start the QEMU daemon, with the same command-line arguments plus > - * -incoming stdin (which qemu_command might convert to exec:cat or fd:n) > + * -incoming stdio (which qemu_command might convert to exec:cat or fd:n) > */ > - internalret = qemuProcessStart(dconn, driver, vm, "stdin", true, dataFD[1], > + internalret = qemuProcessStart(dconn, driver, vm, "stdio", true, dataFD[1], > NULL, VIR_VM_OP_MIGRATE_IN_START); > if (internalret< 0) { > qemuAuditDomainStart(vm, "migrated", false); that was my first guess but it does not work the remote monitor socket does not show up libvirt is running as root so it should not be a permission problem qemuMonitorOpenUnix:289 : monitor socket did not show up.: Connection refused qemuProcessWaitForMonitor:1059 : internal error process exited while connecting to monitor: Migration failed. Exit code fd:14(-22), exiting. From eblake at redhat.com Wed Apr 20 13:01:25 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 20 Apr 2011 07:01:25 -0600 Subject: [libvirt] tunnelled migration with libvirt 0.9.0 In-Reply-To: <4DAEB42C.70900@cn.fujitsu.com> References: <4DAEAA47.6080500@collax.com> <4DAEB42C.70900@cn.fujitsu.com> Message-ID: <4DAED925.8070506@redhat.com> On 04/20/2011 04:23 AM, Wen Congyang wrote: >> migrateFrom is set to "stdin" but in src/qemu/qemu_command.c >> there is no such match which ends in the above error. > > Yes, the tunnelled migration has been broken. Aargh - another typo strikes my patches. :( > > Please applied the following patch and try it again: > >>From 55dac9d193644b7957ea730b8739633cd185d494 Mon Sep 17 00:00:00 2001 > From: Wen Congyang > Date: Wed, 20 Apr 2011 18:20:12 +0800 > Subject: [PATCH] fix tunnelled migration's regression > > If the migrateFrom is "stdio" not "stdin", qemuBuildCommandLine() > will convert it to exec:cat or fd:n. > > --- > src/qemu/qemu_migration.c | 4 ++-- > 1 files changed, 2 insertions(+), 2 deletions(-) ACK, please apply. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 20 13:06:33 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 20 Apr 2011 07:06:33 -0600 Subject: [libvirt] tunnelled migration with libvirt 0.9.0 In-Reply-To: <4DAEBFEF.1060806@collax.com> References: <4DAEAA47.6080500@collax.com> <4DAEB42C.70900@cn.fujitsu.com> <4DAEBFEF.1060806@collax.com> Message-ID: <4DAEDA59.7010103@redhat.com> On 04/20/2011 05:13 AM, Jason Krieg wrote: > that was my first guess but it does not work the remote monitor socket > does not show up > > libvirt is running as root so it should not be a permission problem > > qemuMonitorOpenUnix:289 : monitor socket did not show up.: Connection > refused > qemuProcessWaitForMonitor:1059 : internal error process exited while > connecting to monitor: Migration failed. Exit code fd:14(-22), exiting. Exit code fd:14(-22) is EBADF on fd 14; I've seen it in the past when we were incorrectly leaving FD_CLOEXEC set on fd 14, but I don't see how that would be possible in the code path for qemuMigrationPrepareTunnel. I'll have to see if I can reproduce this. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From guisgb13 at gmail.com Wed Apr 20 13:10:37 2011 From: guisgb13 at gmail.com (Guilherme Santos) Date: Wed, 20 Apr 2011 10:10:37 -0300 Subject: [libvirt] Application Development Guide Message-ID: Good morning! I am one of the developers of OurGrid (http://www.ourgrid.org), a middleware that enables the creation of peer-to-peer computational grids, and we are studying your Libvirt API in order to see if it satisfies our middleware's demands. So we found out your Application Development Guide, and it is being quite useful. I just found small mistakes in the code examples. Even though don't know if this is the appropriate place to notify you guys, here you are: At section 3.9, in the main function, the if block above: if (conn4 == NULL) { fprintf(stderr, "Failed to open connection to qemu:///system\n"); virConnectClose(conn3); virConnectClose(conn2); virConnectClose(conn1); return 3; } The 'return 3' was meant to be 'return 4', right? And I guess that the final If block at section 4.3 is just missing a return statement too. With that being said, I want to take this opportunity to say that documentation of section 9.3 (Java bindings) would be of great help to us, since we are developing everything using Java. Cheers and congratulations for this great job you guys are doing. Moreover, sorry for my poor english. Guilherme Santos -- Guilherme Santos G. Baptista Graduando em Ci?ncia da Computa??o pela UFCG LSD - Laborat?rio de Sistemas Distribu?dos -------------- next part -------------- An HTML attachment was scrubbed... URL: From supriyak at in.ibm.com Wed Apr 20 13:24:27 2011 From: supriyak at in.ibm.com (Supriya Kannery) Date: Wed, 20 Apr 2011 18:54:27 +0530 Subject: [libvirt] libvirt and virsh logging Message-ID: <4DAEDE8B.6000306@in.ibm.com> I am trying to get virsh commands with timestamp logged into a file along with logs collected from libvirt. Finding that virsh and libvirt logs into separate log files. Please suggest on what could be a right approach to get both virsh and libvirt logs into a single file. Thanks, Supriya From eblake at redhat.com Wed Apr 20 13:17:04 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 20 Apr 2011 07:17:04 -0600 Subject: [libvirt] [PATCH] qemu: Unlink managed state file when a domain is undefined In-Reply-To: <1303284625-15782-1-git-send-email-jyang@redhat.com> References: <1303284625-15782-1-git-send-email-jyang@redhat.com> Message-ID: <4DAEDCD0.6040201@redhat.com> On 04/20/2011 01:30 AM, Osier Yang wrote: > The managed state file is not useful anymore after the domain is > undefined, and perhaps cause confusion. E.g. define & start a domain > which has same name with previous undefined domain later. > --- > src/qemu/qemu_driver.c | 8 ++++++++ > 1 files changed, 8 insertions(+), 0 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index f6e503a..874b455 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -3739,6 +3739,7 @@ static int qemudDomainUndefine(virDomainPtr dom) { > virDomainObjPtr vm; > virDomainEventPtr event = NULL; > int ret = -1; > + char *managed_save = NULL; > > qemuDriverLock(driver); > vm = virDomainFindByUUID(&driver->domains, dom->uuid); > @@ -3766,6 +3767,13 @@ static int qemudDomainUndefine(virDomainPtr dom) { > if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0) > goto cleanup; > > + if (!(managed_save = qemuDomainManagedSavePath(driver, vm))) > + goto cleanup; > + > + if (virFileExists(managed_save) && (unlink(managed_save) < 0)) { > + VIR_WARN("Failed to remove the managed state %s", managed_save); > + } Hmm, I'm wondering if we should instead swap this to occur before virDomainDeleteConfig, and fail the undefine operation if unlink() fails (doing it after the deletion and only doing a VIR_WARN while still succeeding seems rather weak). -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From wencongyang at gmail.com Wed Apr 20 14:55:40 2011 From: wencongyang at gmail.com (Wen Congyang) Date: Wed, 20 Apr 2011 22:55:40 +0800 Subject: [libvirt] tunnelled migration with libvirt 0.9.0 In-Reply-To: <4DAED925.8070506@redhat.com> References: <4DAEAA47.6080500@collax.com> <4DAEB42C.70900@cn.fujitsu.com> <4DAED925.8070506@redhat.com> Message-ID: <4DAEF3EC.50504@gmail.com> At 2011-4-20 21:01, Eric Blake write: > On 04/20/2011 04:23 AM, Wen Congyang wrote: >>> migrateFrom is set to "stdin" but in src/qemu/qemu_command.c >>> there is no such match which ends in the above error. >> >> Yes, the tunnelled migration has been broken. > > Aargh - another typo strikes my patches. :( > >> >> Please applied the following patch and try it again: >> >> > From 55dac9d193644b7957ea730b8739633cd185d494 Mon Sep 17 00:00:00 2001 >> From: Wen Congyang >> Date: Wed, 20 Apr 2011 18:20:12 +0800 >> Subject: [PATCH] fix tunnelled migration's regression >> >> If the migrateFrom is "stdio" not "stdin", qemuBuildCommandLine() >> will convert it to exec:cat or fd:n. >> >> --- >> src/qemu/qemu_migration.c | 4 ++-- >> 1 files changed, 2 insertions(+), 2 deletions(-) > > ACK, please apply. Thanks. Applied. > > > > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list From eblake at redhat.com Wed Apr 20 20:15:31 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 20 Apr 2011 14:15:31 -0600 Subject: [libvirt] [PATCH] build: use gnulib passfd for simpler SCM_RIGHTS code Message-ID: <1303330531-25818-1-git-send-email-eblake@redhat.com> * bootstrap.conf (gnulib_modules): Add passfd. * src/util/util.c (virFileOpenAs): Simplify. --- It's always nice to shove the maintenance burden onto gnulib. bootstrap.conf | 1 + src/util/util.c | 38 ++++++++------------------------------ 2 files changed, 9 insertions(+), 30 deletions(-) diff --git a/bootstrap.conf b/bootstrap.conf index 293f86e..3b3a90f 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -52,6 +52,7 @@ mkstemps mktempd netdb nonblocking +passfd perror physmem pipe-posix diff --git a/src/util/util.c b/src/util/util.c index d4d2610..de4e3b3 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -78,6 +78,7 @@ #include "files.h" #include "command.h" #include "nonblocking.h" +#include "passfd.h" #ifndef NSIG # define NSIG 32 @@ -1480,11 +1481,6 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, int waitret, status, ret = 0; int fd = -1; int pair[2] = { -1, -1 }; - struct msghdr msg; - struct cmsghdr *cmsg; - char buf[CMSG_SPACE(sizeof(fd))]; - char dummy = 0; - struct iovec iov; int forkRet; if ((!(flags & VIR_FILE_OPEN_AS_UID)) @@ -1506,18 +1502,6 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, return ret; } - memset(&msg, 0, sizeof(msg)); - iov.iov_base = &dummy; - iov.iov_len = 1; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = buf; - msg.msg_controllen = sizeof(buf); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); - forkRet = virFork(&pid); if (pid < 0) { @@ -1529,26 +1513,20 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, VIR_FORCE_CLOSE(pair[1]); do { - ret = recvmsg(pair[0], &msg, 0); + ret = recvfd(pair[0], 0); } while (ret < 0 && errno == EINTR); - if (ret < 0) { + if (ret < 0 && errno != EACCES) { ret = -errno; VIR_FORCE_CLOSE(pair[0]); while ((waitret = waitpid(pid, NULL, 0) == -1) && (errno == EINTR)); goto parenterror; + } else { + fd = ret; } VIR_FORCE_CLOSE(pair[0]); - /* See if fd was transferred. */ - cmsg = CMSG_FIRSTHDR(&msg); - if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(fd)) && - cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_RIGHTS) { - memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); - } - /* wait for child to complete, and retrieve its exit code */ while ((waitret = waitpid(pid, &status, 0) == -1) && (errno == EINTR)); @@ -1557,12 +1535,14 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, virReportSystemError(errno, _("failed to wait for child creating '%s'"), path); + VIR_FORCE_CLOSE(fd); goto parenterror; } if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == -EACCES || fd == -1) { /* fall back to the simpler method, which works better in * some cases */ + VIR_FORCE_CLOSE(fd); return virFileOpenAsNoFork(path, openflags, mode, uid, gid, flags); } if (!ret) @@ -1627,10 +1607,9 @@ parenterror: path, mode); goto childerror; } - memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); do { - ret = sendmsg(pair[1], &msg, 0); + ret = sendfd(pair[1], fd); } while (ret < 0 && errno == EINTR); if (ret < 0) { @@ -1638,7 +1617,6 @@ parenterror: goto childerror; } - ret = 0; childerror: /* ret tracks -errno on failure, but exit value must be positive. * If the child exits with EACCES, then the parent tries again. */ -- 1.7.1 From eblake at redhat.com Wed Apr 20 20:46:34 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 20 Apr 2011 14:46:34 -0600 Subject: [libvirt] [PATCH v2 1/2] Add static mutex initializer. In-Reply-To: <11a7bd558e33eb347c21d5efebb4a82759125382.1303290824.git.hutao@cn.fujitsu.com> References: <11a7bd558e33eb347c21d5efebb4a82759125382.1303290824.git.hutao@cn.fujitsu.com> Message-ID: <4DAF462A.2010803@redhat.com> On 04/20/2011 03:14 AM, Hu Tao wrote: > This prepares for the next patch. > > The bad is we have no way to check the return value for > CreateMutex when it is used as a static initializer. > --- > src/util/threads-pthread.h | 5 +++++ > src/util/threads-win32.h | 5 +++++ > 2 files changed, 10 insertions(+), 0 deletions(-) Then again, the next patch doesn't use VIR_MUTEX_INITIALIZER under WIN32 (it is only used in the fallback after gcc builtins and WIN32 native functions are bypassed). So, even simpler is just leaving it undefined for that platform, and deferring the problem of a working solution until the next time (if ever) we think we need the usage pattern of a static-initialized mutex to begin with. In other words, > > diff --git a/src/util/threads-pthread.h b/src/util/threads-pthread.h > index b25d0c2..ff50253 100644 > --- a/src/util/threads-pthread.h > +++ b/src/util/threads-pthread.h > @@ -23,6 +23,11 @@ > > #include > > +#define VIR_MUTEX_INITIALIZER \ > +{ \ > + .lock = PTHREAD_MUTEX_INITIALIZER \ > +} > + ACK to this hunk, > struct virMutex { > pthread_mutex_t lock; > }; > diff --git a/src/util/threads-win32.h b/src/util/threads-win32.h > index bb7c455..cfadbe4 100644 > --- a/src/util/threads-win32.h > +++ b/src/util/threads-win32.h > @@ -23,6 +23,11 @@ > > #include > > +#define VIR_MUTEX_INITIALIZER \ > +{ \ > + .lock = CreateMutex(NULL, FALSE, NULL) \ > +} > + NAK to this hunk. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 20 20:53:56 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 20 Apr 2011 14:53:56 -0600 Subject: [libvirt] [PATCH 1/6] Add virObject and virAtomic. In-Reply-To: <20110407074915.GB7711@localhost.localdomain> References: <4D9CCAED.4040508@redhat.com> <20110407074915.GB7711@localhost.localdomain> Message-ID: <4DAF47E4.3020203@redhat.com> On 04/07/2011 01:49 AM, Hu Tao wrote: >> >>> +virObjectInit; >>> +virObjectRef; >>> +virObjectUnref; >> >> Missing exports from viratomic.h. > > Why the linker doesn't complain about this this time? Because you didn't run configure (via ./autogen.sh) with the --with-driver-modules option. Missing exports don't bite until you are forcing dlopen() interaction between the various libraries, rather than linking them into one giant executable. (Which reminds me, I need to revive my patch to make ./autobuild.sh enable that option, to increase its test coverage). -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 20 21:05:30 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 20 Apr 2011 15:05:30 -0600 Subject: [libvirt] [PATCH v2 1/2] Add static mutex initializer. In-Reply-To: <4DAF462A.2010803@redhat.com> References: <11a7bd558e33eb347c21d5efebb4a82759125382.1303290824.git.hutao@cn.fujitsu.com> <4DAF462A.2010803@redhat.com> Message-ID: <4DAF4A9A.9030400@redhat.com> On 04/20/2011 02:46 PM, Eric Blake wrote: > On 04/20/2011 03:14 AM, Hu Tao wrote: >> This prepares for the next patch. >> >> The bad is we have no way to check the return value for >> CreateMutex when it is used as a static initializer. >> --- >> src/util/threads-pthread.h | 5 +++++ >> src/util/threads-win32.h | 5 +++++ >> 2 files changed, 10 insertions(+), 0 deletions(-) > > Then again, the next patch doesn't use VIR_MUTEX_INITIALIZER under WIN32 > (it is only used in the fallback after gcc builtins and WIN32 native > functions are bypassed). So, even simpler is just leaving it undefined > for that platform, and deferring the problem of a working solution until > the next time (if ever) we think we need the usage pattern of a > static-initialized mutex to begin with. In fact, I think that pthread_once/InitOnceExecuteOnce provides the perfect pthread vs. WIN32 approach to one-time initialization without relying on static initializers, and that it would be fairly easy to write virOnce as the wrapper function that covers the underlying functionality of both threading approaches. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From benve at cisco.com Wed Apr 20 21:28:12 2011 From: benve at cisco.com (Christian Benvenuti (benve)) Date: Wed, 20 Apr 2011 16:28:12 -0500 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <4DA4DC52.8010509@redhat.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com><1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> Message-ID: <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> Daniel, I looked at the patch-set you sent out on the 2/9/11 [libvirt] [PATCH 0/6] Introduce a new migration protocol to QEMU driver http://www.mail-archive.com/libvir-list at redhat.com/msg33223.html What is the status of this new migration protocol? Is there any pending issue blocking its integration? I would like to propose an RFC enhancement to the migration algorithm. Here is a quick summary of the proposal/idea. - finer control on migration result - possibility of specifying what features cannot fail their initialization on the dst host during migration. Migration should not succeed if any of them fails. - optional: each one of those features should be able to provide a deinit function to cleanup resources on the dst host if migration fails. This functionality would come useful for the (NIC) set port profile feature VDP (802.1Qbg/1Qbh), but what I propose is a generic config option / API that can be used by any feature. And now the details. ---------------------------------------------- enhancement: finer control on migration result ---------------------------------------------- There are different reasons why a VM may need (or be forced) to migrate. You can classify the types of the migrations also based on different semantics. For simplicity I'll classify them into two categories, based on how important it is for the VM to migrate as fast as possible: (1) It IS important In this case, whether the VM will not be able to (temporary) make use of certain resources (for example the network) on the dst host, is not that important, because the completion of the migration is considered higher priority. A possible scenario could be a server that must migrate ASAP because of a disaster/emergency. (2) It IS NOT important I can think of a VM whose applications/servers need a network connection in order to work properly. Loosing such network connectivity as a consequence of a migration would not be acceptable (or highly undesirable). Given the case (2) above, I have a comment about the Finish step, with regards to the port profile (VDP) codepath. The call to qemuMigrationVPAssociatePortProfile in qemuMigrationFinish can fail, but its result (success or failure) does not influence the result of the migration Finish step (it was already like this in migration V2). It is therefore possible for a VM to lose its network connectivity after a (successful) migration. Given that you are in the process of adding a new migration version, I was wondering if we could add a mechanism for the src host to select behavior/policy (1) or (2). It would be one more option in the libvirt XML domain config file. The above example refers to one specific feature (network connectivity based on the use of a port profile, ie VDP), but in theory this feature could be made generic such that the same policy (1)/(2) could be used for any feature that the admin may not be willing to lose as result of a (successful) migration. The management application on the src host (virt-manager, RHEV-M, etc) can for example, in case (2), retry the migration toward the same host or try with another destination host. The port profile configuration happens in two stages: - there is a 1st call during PREPARE: openMacvtaptap | +-> (a) vpAssociatePortProfileId (PREASSOCIATE) - and a second call during FINISH: qemuMigrationVPAssociatePortProfile | +-> (b) vpAssociatePortProfileId (ASSOCIATE) Right now, both in migration V2 and V3: - (a) cannot fail (ie, if it fails, migration fails too), - (b) can fail (ie, if it fails, migration does not fail and VM loses connectivity). With the introduction of the policy (1)/(2) mentioned above, this would be the new behavior: - Case (1) above, ie fast migration --> (a) and (b) are non blocking --> Their result does not affect migration result. - Case (2) above, ie possibly slower migration --> (a) and (b) are blocking --> Their result does affect migration result. It may be not possible to handle all possible scenarios (there can be cases where dependencies between features would make it difficult to chose between (1) and (2) on a per feature basis), but that should not be a reason not to provide this policy for a subset of features (network connectivity being one). The 5-steps new migration version V3 makes it easier (compared to V2) to introduce this kind of policy. I guess we could use the cookies to carry the necessary information/acks. There are still numerous things that can go wrong. For example, if migration aborts after (a), or even after (b), there should be a way for Libvirt to undo the set port profile. Actually, there should be a way for any feature (not just VDP) that successfully initialized on the dst host to (at least try to) cleanup. For this reason, it could make sense, for each one of the features using policy (2) (ie, cannot fail during migration) to also provide a deinit routine (as part of the API that marks the feature as "can't fail"). Such routine/s can be called by libvirt to revert/rollback the initializations that successfully completed during the migration attempt. This could be done probably at the end of the Finish3 phase. If something goes wrong (including a signal that aborts migration just before Confirm3 completes), we may have a small problem. I do not know how we can handle that case without another cleanup RPC call. If you agree that this kind of functionality/policy described above has some value, I can help with its implementation and testing. BTW, would the new functionality being discussed in this 3D "RFC: virInterface change transaction API" http://www.redhat.com/archives/libvir-list/2011-April/msg00499.html be able to provide the same configuration "atomicity" (ie, rollback in case of migration failure)? My understanding is that: - Such new framework would apply to (host) network config only. Even though it may cover the VDP (port profile) use case I mentioned above, it would not apply to other features that may need some kind of rollback after a migration failure. - Would it be possible to design that new transaction API (or a sister API) such that it would come useful for the guest migration case too? If so, the deinit/rollback routine I proposed may be defined as a simple wrapper around the transaction API and let other (non networking) features use their own deinit functions. Thanks /Chris > -----Original Message----- > From: libvir-list-bounces at redhat.com [mailto:libvir-list- > bounces at redhat.com] On Behalf Of Eric Blake > Sent: Tuesday, April 12, 2011 4:12 PM > To: Daniel P. Berrange > Cc: libvir-list at redhat.com > Subject: Re: [libvirt] [PATCH 3/6] Introduce yet another migration > version in API. > > On 02/09/2011 09:58 AM, Daniel P. Berrange wrote: > > This patch attempts to introduce a version 3 that uses the improved 5 > > step sequence > > > > * Src: Begin > > - Generate XML to pass to dst > > - Generate optional cookie to pass to dst > > > > * Dst: Prepare > > - Get ready to accept incoming VM > > - Generate optional cookie to pass to src > > > > * Src: Perform > > - Start migration and wait for send completion > > - Generate optional cookie to pass to dst > > > > * Dst: Finish > > - Wait for recv completion and check status > > - Kill off VM if failed, resume if success > > - Generate optional cookie to pass to src > > > > * Src: Confirm > > - Kill off VM if success, resume if failed > > I've been thinking about this a bit more, and have a question. What > happens when the source side decides to abort the migration? For > example, if libvirtd on the source gets a SIGHUP or SIGINT, it would be > nice to have the cleanup code abort any in-flight migrations so that > when libvirtd is restarted, the guest is still operational on the > source, and the guest does not have to wait for a full TCP timeout > cycle to realize that the source is not going to complete the > migration. > > Does this call for additional internal points in the RPC implementation > of v3 migration? > > -- > Eric Blake eblake at redhat.com +1-801-349-2682 > Libvirt virtualization library http://libvirt.org From eblake at redhat.com Wed Apr 20 21:36:00 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 20 Apr 2011 15:36:00 -0600 Subject: [libvirt] [PATCH v2 2/2] Add virObject and virAtomic. In-Reply-To: <019f40454f8b412d17f965052a23422f933b2ee2.1303290824.git.hutao@cn.fujitsu.com> References: <11a7bd558e33eb347c21d5efebb4a82759125382.1303290824.git.hutao@cn.fujitsu.com> <019f40454f8b412d17f965052a23422f933b2ee2.1303290824.git.hutao@cn.fujitsu.com> Message-ID: <4DAF51C0.8040204@redhat.com> On 04/20/2011 03:15 AM, Hu Tao wrote: > virObject is the base struct that manages reference-counting > for all structs that need the ability of reference-counting. > > virAtomic provides atomic operations which are thread-safe. > --- > src/Makefile.am | 2 + > src/libvirt_private.syms | 11 ++++++ > src/util/viratomic.c | 80 ++++++++++++++++++++++++++++++++++++++++++ > src/util/viratomic.h | 32 +++++++++++++++++ > src/util/virobject.c | 64 ++++++++++++++++++++++++++++++++++ > src/util/virobject.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++ > 6 files changed, 275 insertions(+), 0 deletions(-) > create mode 100644 src/util/viratomic.c > create mode 100644 src/util/viratomic.h > create mode 100644 src/util/virobject.c > create mode 100644 src/util/virobject.h > +++ b/src/libvirt_private.syms > @@ -958,6 +958,17 @@ virUUIDGenerate; > virUUIDParse; > > > +# virobject.h > +virObjectInit; > +virObjectRef; > +virObjectUnref; > + > + > +# viratomic.h > +virAtomicInc; > +virAtomicDec; Swap these two sections (chunks are alphabetic by header), as well as swap these two lines (within a header, lines are alphabetic). > +++ b/src/util/viratomic.c > +#else > + > +#include "threads.h" > + > +static virMutex virAtomicLock = VIR_MUTEX_INITIALIZER; Hmm, if I implement virOnce first, maybe we should use that instead. > + > +long virAtomicInc(long *value) > +{ > + long result; > + virMutexLock(&virAtomicLock); > + *value += 1; > + result = *value; > + virMutexUnlock(&virAtomicLock); Clunky, but does the job ;) > +#include > + > +#include "viratomic.h" > +#include "virobject.h" > +#include "logging.h" > + > +int virObjectInit(virObjectPtr obj, virObjectFree f) > +{ > + if (obj->free) { > + /* This means the obj is already initialized. A second > + * initialization will destroy ref field, which is bad. > + */ > + VIR_ERROR("Object %p is already initialized.", obj); > + return -1; > + } > + > + if (!f) { > + VIR_ERROR0("virObjectFree method is required."); > + abort(); Either both failures should abort(), or both should return -1. They are both programming errors, so I'm personally okay with abort(), but this would be the first use of abort() outside gnulib files, so I'll see if either Dan has opinions as well. In fact, if we go with abort() in both places, then this can return void instead of int. Likewise, by adding ATTRIBUTE_NONNULL(2) to the prototype, then the compiler (well, at least clang) will help catch coding errors of failing to pass a callback function. Oops - you used TAB instead of space; 'make syntax-check' should have caught that. > + > +void virObjectRef(virObjectPtr obj) > +{ > + if (virAtomicInc(&obj->ref) < 2) > + abort(); /* BUG if we get here */ If we keep the abort, then we _need_ the VIR_ERROR before hand saying why we quit. > +} > + > +void virObjectUnref(virObjectPtr obj) > +{ > + long ref = virAtomicDec(&obj->ref); > + if (ref == 0) > + obj->free(obj); > + else if (ref < 0) > + abort(); /* BUG if we get here */ Again, don't ever abort() without VIR_ERROR stating why. And maybe we should think about installing a SIGABRT handler so that aborts print a nicer message for the end user? > + > +typedef struct _virObject virObject; > +typedef virObject *virObjectPtr; > + > +typedef void (*virObjectFree)(virObjectPtr obj); I dislike extra casts, and this signature forces every client to have an explicit cast in their free function. Could we instead make this: typedef void (*virObjectFree)(void *obj); with some additional fallout documented below? Also, can we attach ATTRIBUTE_NONNULL(1) to a typedef? (I'm not quite sure how that works with gcc). > + > +/* A thread owns a virObject by incrementing its reference-count by 1. > + * If a thread owns a virObject, the virObject is guarenteed not be s/guarenteed/guaranteed to/ > + * freed until the thread releases ownership by decrementing its > + * reference-count by 1. A thread can't access a virObject after it > + * releases the ownership of virObject because it can be freed at > + * anytime. > + * > + * A thread can own a virObject legally in these ways: > + * > + * - a thread owns a virObject that it creates. > + * - a thread owns a virObject if another thread passes the ownership > + * to it. Example: qemuMonitorOpen > + * - a thread gets a virObject from a container. > + * Example: virDomainFindByUUID > + * - a container owns a virObject by incrementing its reference-count > + * by 1 before adding it to the container > + * - if a virObject is removed from a container its reference-count > + * must be decremented by 1 > + */ > +/* > + * Usage of virObject: > + * > + * 1. embed virObject into your struct as the first member. > + * > + * struct foo { > + * virObject obj; // must be the first member > + * ... > + * } > + * > + * 2. call virObjectInit(obj, fooFree) in your struct's initialization > + * function. fooFree is the free method which be called automatically > + * when the ref count becomes 0. The argument to fooFree will be &obj, which in turn can be cast as struct foo* because obj is the first member. struct foo * fooCreate() { struct foo *myfoo; if (VIR_ALLOC(myfoo) < 0) { virReportOOMError(); return NULL; } virObjectInit(&myfoo->obj, fooFree); ... // all other contents of myfoo return myfoo; } > + * > + * 3. implement two functions to ref/unref your struct like this: > + * > + * void FooRef(struct foo *f) > + * { > + * virObjectRef(f->obj); > + * } > + * > + * void FooUnref(struct foo *f) > + * { > + * virObjectUnref(f->obj); > + * } 4. implement the free method for your struct like this: static void fooFree(void *obj) { struct foo *myfoo = obj; ... // all other contents of myfoo VIR_FREE(myfoo); } > + */ > +struct _virObject { > + long ref; > + virObjectFree free; > +}; > + > +int virObjectInit(virObjectPtr obj, virObjectFree f); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) > +void virObjectRef(virObjectPtr obj); ATTRIBUTE_NONNULL(1) > +void virObjectUnref(virObjectPtr obj); ATTRIBUTE_NONNULL(1) -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Wed Apr 20 22:43:39 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 20 Apr 2011 16:43:39 -0600 Subject: [libvirt] [PATCH] threads: add one-time initialization support Message-ID: <1303339419-13159-1-git-send-email-eblake@redhat.com> mingw lacks the counterpart to PTHREAD_MUTEX_INITIALIZER, so the best we can do is portably expose once-only runtime initialization. * src/util/threads.h (virOnceControlPtr): New opaque type. (virOnceFunc): New callback type. (virOnce): New prototype. * src/util/threads-pthread.h (virOnceControl): Declare. (VIR_ONCE_CONTROL_INITIALIZER): Define. * src/util/threads-win32.h (virOnceControl) (VIR_ONCE_CONTROL_INITIALIZER): Likewise. * src/util/threads-pthread.c (virOnce): Implement in pthreads. * src/util/threads-win32.c (virOnce): Implement in WIN32. * src/libvirt_private.syms: Export it. --- src/libvirt_private.syms | 1 + src/util/threads-pthread.c | 5 +++++ src/util/threads-pthread.h | 11 ++++++++++- src/util/threads-win32.c | 15 ++++++++++++++- src/util/threads-win32.h | 11 ++++++++++- src/util/threads.h | 21 ++++++++++++++++++++- 6 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ba7739d..cb67861 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -866,6 +866,7 @@ virMutexInit; virMutexInitRecursive; virMutexLock; virMutexUnlock; +virOnce; virThreadCreate; virThreadID; virThreadIsSelf; diff --git a/src/util/threads-pthread.c b/src/util/threads-pthread.c index 898c4d4..82ce5c6 100644 --- a/src/util/threads-pthread.c +++ b/src/util/threads-pthread.c @@ -40,6 +40,11 @@ void virThreadOnExit(void) { } +int virOnce(virOnceControlPtr once, virOnceFunc init) +{ + return pthread_once(&once->once, init); +} + int virMutexInit(virMutexPtr m) { diff --git a/src/util/threads-pthread.h b/src/util/threads-pthread.h index b25d0c2..dcaacb7 100644 --- a/src/util/threads-pthread.h +++ b/src/util/threads-pthread.h @@ -1,7 +1,7 @@ /* * threads.c: basic thread synchronization primitives * - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009, 2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -38,3 +38,12 @@ struct virThread { struct virThreadLocal { pthread_key_t key; }; + +struct virOnceControl { + pthread_once_t once; +}; + +#define VIR_ONCE_CONTROL_INITIALIZER \ +{ \ + .once = PTHREAD_ONCE_INIT \ +} diff --git a/src/util/threads-win32.c b/src/util/threads-win32.c index 5661437..f717f98 100644 --- a/src/util/threads-win32.c +++ b/src/util/threads-win32.c @@ -1,7 +1,7 @@ /* * threads-win32.c: basic thread synchronization primitives * - * Copyright (C) 2009-2010 Red Hat, Inc. + * Copyright (C) 2009-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -69,6 +69,19 @@ void virThreadOnExit(void) virMutexUnlock(&virThreadLocalLock); } +static BOOL CALLBACK +virOnceCallback(PINIT_ONCE once, PVOID param, PVOID *context ATTRIBUTE_UNUSED) +{ + virOnceFunc func = param; + func(); + return TRUE; +} + +int virOnce(virOnceControlPtr once, virOnceFunc init) +{ + return InitOnceExecuteOnce(&once->once, virOnceCallback, init, + NULL) ? 0 : -1; +} int virMutexInit(virMutexPtr m) { diff --git a/src/util/threads-win32.h b/src/util/threads-win32.h index bb7c455..f169460 100644 --- a/src/util/threads-win32.h +++ b/src/util/threads-win32.h @@ -1,7 +1,7 @@ /* * threads-win32.h basic thread synchronization primitives * - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009, 2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -41,3 +41,12 @@ struct virThread { struct virThreadLocal { DWORD key; }; + +struct virOnceControl { + INIT_ONCE once; +}; + +#define VIR_ONCE_CONTROL_INITIALIZER \ +{ \ + .once = INIT_ONCE_STATIC_INIT \ +} diff --git a/src/util/threads.h b/src/util/threads.h index c129301..b72610c 100644 --- a/src/util/threads.h +++ b/src/util/threads.h @@ -1,7 +1,7 @@ /* * threads.h: basic thread synchronization primitives * - * Copyright (C) 2009-2010 Red Hat, Inc. + * Copyright (C) 2009-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -36,6 +36,10 @@ typedef virThreadLocal *virThreadLocalPtr; typedef struct virThread virThread; typedef virThread *virThreadPtr; +typedef struct virOnceControl virOnceControl; +typedef virOnceControl *virOnceControlPtr; + +typedef void (*virOnceFunc)(void); int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK; void virThreadOnExit(void); @@ -57,6 +61,21 @@ void virThreadJoin(virThreadPtr thread); int virThreadSelfID(void); int virThreadID(virThreadPtr thread); +/* Static initialization of mutexes is not possible, so we instead + * provide for guaranteed one-time initialization via a callback + * function. Usage: + * static virOnceControl once = VIR_ONCE_CONTROL_INITIALIZER; + * static void initializer(void) { ... } + * void myfunc() + * { + * if (virOnce(&once, initializer) < 0) + * goto error; + * ...now guaranteed that initializer has completed exactly once + * } + */ +int virOnce(virOnceControlPtr once, virOnceFunc init) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; + int virMutexInit(virMutexPtr m) ATTRIBUTE_RETURN_CHECK; int virMutexInitRecursive(virMutexPtr m) ATTRIBUTE_RETURN_CHECK; void virMutexDestroy(virMutexPtr m); -- 1.7.1 From eblake at redhat.com Wed Apr 20 23:00:17 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 20 Apr 2011 17:00:17 -0600 Subject: [libvirt] tunnelled migration with libvirt 0.9.0 In-Reply-To: <4DAEF3EC.50504@gmail.com> References: <4DAEAA47.6080500@collax.com> <4DAEB42C.70900@cn.fujitsu.com> <4DAED925.8070506@redhat.com> <4DAEF3EC.50504@gmail.com> Message-ID: <4DAF6581.9020504@redhat.com> On 04/20/2011 08:55 AM, Wen Congyang wrote: >>> If the migrateFrom is "stdio" not "stdin", qemuBuildCommandLine() >>> will convert it to exec:cat or fd:n. >>> >>> --- >>> src/qemu/qemu_migration.c | 4 ++-- >>> 1 files changed, 2 insertions(+), 2 deletions(-) >> >> ACK, please apply. > > Thanks. Applied. Except that your committer setup was broken, and produced an invalid email address (using spaces instead of . and @), which resulted in 'make syntax-check' complaining. I've pushed a correction to .mailmap under the build-breaker rule. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 620 bytes Desc: OpenPGP digital signature URL: From stefanb at linux.vnet.ibm.com Wed Apr 20 23:03:55 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Wed, 20 Apr 2011 19:03:55 -0400 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com><1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> Message-ID: <4DAF665B.2070500@linux.vnet.ibm.com> On 04/20/2011 05:28 PM, Christian Benvenuti (benve) wrote: > Daniel, > I looked at the patch-set you sent out on the 2/9/11 > > [libvirt] [PATCH 0/6] Introduce a new migration protocol > to QEMU driver > http://www.mail-archive.com/libvir-list at redhat.com/msg33223.html > > What is the status of this new migration protocol? > Is there any pending issue blocking its integration? > > I would like to propose an RFC enhancement to the migration > algorithm. > > Here is a quick summary of the proposal/idea. > > - finer control on migration result > > - possibility of specifying what features cannot fail > their initialization on the dst host during migration. > Migration should not succeed if any of them fails. > - optional: each one of those features should be able to > provide a deinit function to cleanup resources > on the dst host if migration fails. > > This functionality would come useful for the (NIC) set port > profile feature VDP (802.1Qbg/1Qbh), but what I propose is > a generic config option / API that can be used by any feature. > > And now the details. > > ---------------------------------------------- > enhancement: finer control on migration result > ---------------------------------------------- > > There are different reasons why a VM may need (or be forced) to > migrate. > You can classify the types of the migrations also based on > different semantics. > For simplicity I'll classify them into two categories, based on > how important it is for the VM to migrate as fast as possible: > > (1) It IS important > > In this case, whether the VM will not be able to (temporary) > make use of certain resources (for example the network) on the > dst host, is not that important, because the completion of the > migration is considered higher priority. > A possible scenario could be a server that must migrate ASAP > because of a disaster/emergency. > > (2) It IS NOT important > > I can think of a VM whose applications/servers need a network > connection in order to work properly. Loosing such network > connectivity as a consequence of a migration would not be > acceptable (or highly undesirable). > > Given the case (2) above, I have a comment about the Finish > step, with regards to the port profile (VDP) codepath. > > The call to > > qemuMigrationVPAssociatePortProfile > > in > qemuMigrationFinish > > can fail, but its result (success or failure) does not influence > the result of the migration Finish step (it was already like this > in migration V2). I *believe* the underlying problem is Qemu's switch-over. Once Qemu decides that the migration was successful, Qemu on the source side dies and continues running on the destination side. I don't think there are more handshakes foreseen with higher layers that this could be reversed or the switch-over delayed, but correct me if I am wrong... So now whatever we do, we'd have to associate the port profile before the actual switch-over, if we wanted to do something better than what is there now and have the opportunity to terminate the migration before the switch-over by Qemu happens in case of failure to associate profiles. The problem is to know when the switch-over happens or when the migration goes into the final phase where the source side doesn't run anymore. The would allow us to not associate the ports right at the beginning of the migration but maybe towards the time when for example in live-migration the source is not running anymore *and* also we have the result of the association before Qemu on the source dies for good. I think some additional coordination between libvirt and Qemu would be necessary so that if higher layer ops fail before the resume on the destination side happens that Qemu can still fall back to the source side. I believe what could happen now is that a VM could be transferred too fast (by the Qemu process) while the association (in libvirt) happens, Qemu on the source side dies, and then we only get the negative result of the association. Maybe the simplest solution would be if Qemu on the source side waited for a command before transferring the last packet so we still have a chance to cancel and Qemu doesn't just 'run away' underneath libvirt's feet ;-). I assume that 2 associations with the same profile are possible with 802.1Qbg and Qbh. Both are also going through a Pre-associate state now. Are there any side-effects if associating twice on the same switch like no packets that can be sent on the source side or something like that -- obviously this would be bad if this happened early during live-migration and we'd want to push the association close to the 'final migration phase', which in turn may require more coordination with Qemu (don't know whether the final phase can be determine now -- maybe via polling Qemu's monitor). Regards, Stefan From eblake at redhat.com Wed Apr 20 23:50:19 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 20 Apr 2011 17:50:19 -0600 Subject: [libvirt] [PATCH] build: use gnulib passfd for simpler SCM_RIGHTS code In-Reply-To: <1303330531-25818-1-git-send-email-eblake@redhat.com> References: <1303330531-25818-1-git-send-email-eblake@redhat.com> Message-ID: <4DAF713B.1050308@redhat.com> On 04/20/2011 02:15 PM, Eric Blake wrote: > * bootstrap.conf (gnulib_modules): Add passfd. > * src/util/util.c (virFileOpenAs): Simplify. > --- > > It's always nice to shove the maintenance burden onto gnulib. > > bootstrap.conf | 1 + > src/util/util.c | 38 ++++++++------------------------------ > 2 files changed, 9 insertions(+), 30 deletions(-) Self-NAK. Until gnulib provides a replacement header, gnulib's passfd.c won't compile on mingw. At that point, I'll have to also update .gnulib, then the rest of this patch should work as-is. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 21 00:03:55 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 20 Apr 2011 18:03:55 -0600 Subject: [libvirt] [PATCH] threads: add one-time initialization support In-Reply-To: <1303339419-13159-1-git-send-email-eblake@redhat.com> References: <1303339419-13159-1-git-send-email-eblake@redhat.com> Message-ID: <4DAF746B.9010401@redhat.com> On 04/20/2011 04:43 PM, Eric Blake wrote: > mingw lacks the counterpart to PTHREAD_MUTEX_INITIALIZER, so the > best we can do is portably expose once-only runtime initialization. > > * src/util/threads.h (virOnceControlPtr): New opaque type. > (virOnceFunc): New callback type. > (virOnce): New prototype. > * src/util/threads-pthread.h (virOnceControl): Declare. > (VIR_ONCE_CONTROL_INITIALIZER): Define. > * src/util/threads-win32.h (virOnceControl) > (VIR_ONCE_CONTROL_INITIALIZER): Likewise. > * src/util/threads-pthread.c (virOnce): Implement in pthreads. > * src/util/threads-win32.c (virOnce): Implement in WIN32. > * src/libvirt_private.syms: Export it. > +++ b/src/util/threads-win32.h > @@ -1,7 +1,7 @@ > /* > * threads-win32.h basic thread synchronization primitives > * > - * Copyright (C) 2009 Red Hat, Inc. > + * Copyright (C) 2009, 2011 Red Hat, Inc. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public > @@ -41,3 +41,12 @@ struct virThread { > struct virThreadLocal { > DWORD key; > }; > + > +struct virOnceControl { > + INIT_ONCE once; > +}; Self-NAK - not all versions of Windows support INIT_ONCE yet, http://msdn.microsoft.com/en-us/library/ms684122%28v=vs.85%29.aspx states that applications must use InterlockedIncrement to set up their own critical sections instead. The idea is still doable, it just requires more work on the WIN32 side of things. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Thu Apr 21 06:14:40 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Thu, 21 Apr 2011 08:14:40 +0200 Subject: [libvirt] [PATCH] esx: Move CURL handling code to it's own type In-Reply-To: <20110410133929.GA28461@sbox> References: <20110410133929.GA28461@sbox> Message-ID: 2011/4/10 Matthias Bolte : > --- > ?src/esx/esx_driver.c | ? ?4 +- > ?src/esx/esx_vi.c ? ? | ?348 ++++++++++++++++++++++++++------------------------ > ?src/esx/esx_vi.h ? ? | ? 29 +++- > ?3 files changed, 205 insertions(+), 176 deletions(-) > > diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c > index deda372..ef76350 100644 > --- a/src/esx/esx_driver.c > +++ b/src/esx/esx_driver.c > @@ -2642,7 +2642,7 @@ esxDomainDumpXML(virDomainPtr domain, int flags) > > ? ? url = virBufferContentAndReset(&buffer); > > - ? ?if (esxVI_Context_DownloadFile(priv->primary, url, &vmx) < 0) { > + ? ?if (esxVI_CURL_Download(priv->primary->curl, url, &vmx) < 0) { > ? ? ? ? goto cleanup; > ? ? } > > @@ -3111,7 +3111,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml) > ? ? /* Upload VMX file */ > ? ? VIR_DEBUG("Uploading .vmx config, url='%s' vmx='%s'", url, vmx); > > - ? ?if (esxVI_Context_UploadFile(priv->primary, url, vmx) < 0) { > + ? ?if (esxVI_CURL_Upload(priv->primary->curl, url, vmx) < 0) { > ? ? ? ? goto cleanup; > ? ? } > > diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c > index fbab347..2fd09cd 100644 > --- a/src/esx/esx_vi.c > +++ b/src/esx/esx_vi.c > @@ -76,42 +76,25 @@ > > > ?/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > - * Context > + * CURL > ?*/ > > -/* esxVI_Context_Alloc */ > -ESX_VI__TEMPLATE__ALLOC(Context); > +/* esxVI_CURL_Alloc */ > +ESX_VI__TEMPLATE__ALLOC(CURL) > > -/* esxVI_Context_Free */ > -ESX_VI__TEMPLATE__FREE(Context, > +/* esxVI_CURL_Free */ > +ESX_VI__TEMPLATE__FREE(CURL, > ?{ > - ? ?VIR_FREE(item->url); > - ? ?VIR_FREE(item->ipAddress); > - > - ? ?if (item->curl_handle != NULL) { > - ? ? ? ?curl_easy_cleanup(item->curl_handle); > + ? ?if (item->handle != NULL) { > + ? ? ? ?curl_easy_cleanup(item->handle); > ? ? } > > - ? ?if (item->curl_headers != NULL) { > - ? ? ? ?curl_slist_free_all(item->curl_headers); > + ? ?if (item->headers != NULL) { > + ? ? ? ?curl_slist_free_all(item->headers); > ? ? } > > - ? ?virMutexDestroy(&item->curl_lock); > - > - ? ?VIR_FREE(item->username); > - ? ?VIR_FREE(item->password); > - ? ?esxVI_ServiceContent_Free(&item->service); > - ? ?esxVI_UserSession_Free(&item->session); > - ? ?esxVI_Datacenter_Free(&item->datacenter); > - ? ?esxVI_ComputeResource_Free(&item->computeResource); > - ? ?esxVI_HostSystem_Free(&item->hostSystem); > - ? ?esxVI_SelectionSpec_Free(&item->selectSet_folderToChildEntity); > - ? ?esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToParent); > - ? ?esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToVm); > - ? ?esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToDatastore); > - ? ?esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToHost); > - ? ?esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToParentToParent); > -}); > + ? ?virMutexDestroy(&item->lock); > +}) > > ?static size_t > ?esxVI_CURL_ReadString(char *data, size_t size, size_t nmemb, void *ptrptr) > @@ -218,7 +201,7 @@ esxVI_CURL_Debug(CURL *curl ATTRIBUTE_UNUSED, curl_infotype type, > ?#endif > > ?static int > -esxVI_CURL_Perform(esxVI_Context *ctx, const char *url) > +esxVI_CURL_Perform(esxVI_CURL *curl, const char *url) > ?{ > ? ? CURLcode errorCode; > ? ? long responseCode = 0; > @@ -226,23 +209,23 @@ esxVI_CURL_Perform(esxVI_Context *ctx, const char *url) > ? ? const char *redirectUrl = NULL; > ?#endif > > - ? ?errorCode = curl_easy_perform(ctx->curl_handle); > + ? ?errorCode = curl_easy_perform(curl->handle); > > ? ? if (errorCode != CURLE_OK) { > ? ? ? ? ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, > ? ? ? ? ? ? ? ? ? ? ?_("curl_easy_perform() returned an error: %s (%d) : %s"), > - ? ? ? ? ? ? ? ? ? ? curl_easy_strerror(errorCode), errorCode, ctx->curl_error); > + ? ? ? ? ? ? ? ? ? ? curl_easy_strerror(errorCode), errorCode, curl->error); > ? ? ? ? return -1; > ? ? } > > - ? ?errorCode = curl_easy_getinfo(ctx->curl_handle, CURLINFO_RESPONSE_CODE, > + ? ?errorCode = curl_easy_getinfo(curl->handle, CURLINFO_RESPONSE_CODE, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &responseCode); > > ? ? if (errorCode != CURLE_OK) { > ? ? ? ? ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, > ? ? ? ? ? ? ? ? ? ? ?_("curl_easy_getinfo(CURLINFO_RESPONSE_CODE) returned an " > ? ? ? ? ? ? ? ? ? ? ? ?"error: %s (%d) : %s"), curl_easy_strerror(errorCode), > - ? ? ? ? ? ? ? ? ? ? errorCode, ctx->curl_error); > + ? ? ? ? ? ? ? ? ? ? errorCode, curl->error); > ? ? ? ? return -1; > ? ? } > > @@ -255,7 +238,7 @@ esxVI_CURL_Perform(esxVI_Context *ctx, const char *url) > > ? ? if (responseCode == 301) { > ?#if LIBCURL_VERSION_NUM >= 0x071202 /* 7.18.2 */ > - ? ? ? ?errorCode = curl_easy_getinfo(ctx->curl_handle, CURLINFO_REDIRECT_URL, > + ? ? ? ?errorCode = curl_easy_getinfo(curl->handle, CURLINFO_REDIRECT_URL, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &redirectUrl); > > ? ? ? ? if (errorCode != CURLE_OK) { > @@ -263,7 +246,7 @@ esxVI_CURL_Perform(esxVI_Context *ctx, const char *url) > ? ? ? ? ? ? ? ? ? ? ? ? ?_("curl_easy_getinfo(CURLINFO_REDIRECT_URL) returned " > ? ? ? ? ? ? ? ? ? ? ? ? ? ?"an error: %s (%d) : %s"), > ? ? ? ? ? ? ? ? ? ? ? ? ?curl_easy_strerror(errorCode), > - ? ? ? ? ? ? ? ? ? ? ? ? errorCode, ctx->curl_error); > + ? ? ? ? ? ? ? ? ? ? ? ? errorCode, curl->error); > ? ? ? ? } else { > ? ? ? ? ? ? ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, > ? ? ? ? ? ? ? ? ? ? ? ? ?_("The server redirects from '%s' to '%s'"), url, > @@ -281,32 +264,23 @@ esxVI_CURL_Perform(esxVI_Context *ctx, const char *url) > ?} > > ?int > -esxVI_Context_Connect(esxVI_Context *ctx, const char *url, > - ? ? ? ? ? ? ? ? ? ? ?const char *ipAddress, const char *username, > - ? ? ? ? ? ? ? ? ? ? ?const char *password, esxUtil_ParsedUri *parsedUri) > +esxVI_CURL_Connect(esxVI_CURL *curl, esxUtil_ParsedUri *parsedUri) > ?{ > - ? ?if (ctx == NULL || url == NULL || ipAddress == NULL || username == NULL || > - ? ? ? ?password == NULL || ctx->url != NULL || ctx->service != NULL || > - ? ? ? ?ctx->curl_handle != NULL || ctx->curl_headers != NULL) { > - ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); > - ? ? ? ?return -1; > - ? ?} > - > - ? ?if (esxVI_String_DeepCopyValue(&ctx->url, url) < 0 || > - ? ? ? ?esxVI_String_DeepCopyValue(&ctx->ipAddress, ipAddress) < 0) { > + ? ?if (curl->handle != NULL) { > + ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid call")); > ? ? ? ? return -1; > ? ? } > > - ? ?ctx->curl_handle = curl_easy_init(); > + ? ?curl->handle = curl_easy_init(); > > - ? ?if (ctx->curl_handle == NULL) { > + ? ?if (curl->handle == NULL) { > ? ? ? ? ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", > ? ? ? ? ? ? ? ? ? ? ?_("Could not initialize CURL")); > ? ? ? ? return -1; > ? ? } > > - ? ?ctx->curl_headers = curl_slist_append(ctx->curl_headers, "Content-Type: " > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"text/xml; charset=UTF-8"); > + ? ?curl->headers = curl_slist_append(curl->headers, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"Content-Type: text/xml; charset=UTF-8"); > > ? ? /* > ? ? ?* Add a dummy expect header to stop CURL from waiting for a response code > @@ -316,56 +290,179 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url, > ? ? ?* 100 (Continue) response and the wait times out resulting in wasting > ? ? ?* approx. 2 sec per POST operation. > ? ? ?*/ > - ? ?ctx->curl_headers = curl_slist_append(ctx->curl_headers, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"Expect: nothing"); > + ? ?curl->headers = curl_slist_append(curl->headers, "Expect: nothing"); > > - ? ?if (ctx->curl_headers == NULL) { > + ? ?if (curl->headers == NULL) { > ? ? ? ? ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", > ? ? ? ? ? ? ? ? ? ? ?_("Could not build CURL header list")); > ? ? ? ? return -1; > ? ? } > > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, ctx->url); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_USERAGENT, "libvirt-esx"); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_HEADER, 0); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_FOLLOWLOCATION, 0); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_SSL_VERIFYPEER, > + ? ?curl_easy_setopt(curl->handle, CURLOPT_USERAGENT, "libvirt-esx"); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_HEADER, 0); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_FOLLOWLOCATION, 0); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_SSL_VERIFYPEER, > ? ? ? ? ? ? ? ? ? ? ?parsedUri->noVerify ? 0 : 1); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_SSL_VERIFYHOST, > + ? ?curl_easy_setopt(curl->handle, CURLOPT_SSL_VERIFYHOST, > ? ? ? ? ? ? ? ? ? ? ?parsedUri->noVerify ? 0 : 2); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_COOKIEFILE, ""); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_HTTPHEADER, ctx->curl_headers); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_READFUNCTION, > + ? ?curl_easy_setopt(curl->handle, CURLOPT_COOKIEFILE, ""); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_HTTPHEADER, curl->headers); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_READFUNCTION, > ? ? ? ? ? ? ? ? ? ? ?esxVI_CURL_ReadString); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEFUNCTION, > + ? ?curl_easy_setopt(curl->handle, CURLOPT_WRITEFUNCTION, > ? ? ? ? ? ? ? ? ? ? ?esxVI_CURL_WriteBuffer); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_ERRORBUFFER, > - ? ? ? ? ? ? ? ? ? ? ctx->curl_error); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_ERRORBUFFER, curl->error); > ?#if ESX_VI__CURL__ENABLE_DEBUG_OUTPUT > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_DEBUGFUNCTION, esxVI_CURL_Debug); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_VERBOSE, 1); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_DEBUGFUNCTION, esxVI_CURL_Debug); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_VERBOSE, 1); > ?#endif > > ? ? if (parsedUri->proxy) { > - ? ? ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_PROXY, > + ? ? ? ?curl_easy_setopt(curl->handle, CURLOPT_PROXY, > ? ? ? ? ? ? ? ? ? ? ? ? ?parsedUri->proxy_hostname); > - ? ? ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_PROXYTYPE, > + ? ? ? ?curl_easy_setopt(curl->handle, CURLOPT_PROXYTYPE, > ? ? ? ? ? ? ? ? ? ? ? ? ?parsedUri->proxy_type); > - ? ? ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_PROXYPORT, > + ? ? ? ?curl_easy_setopt(curl->handle, CURLOPT_PROXYPORT, > ? ? ? ? ? ? ? ? ? ? ? ? ?parsedUri->proxy_port); > ? ? } > > - ? ?if (virMutexInit(&ctx->curl_lock) < 0) { > + ? ?if (virMutexInit(&curl->lock) < 0) { > ? ? ? ? ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", > ? ? ? ? ? ? ? ? ? ? ?_("Could not initialize CURL mutex")); > ? ? ? ? return -1; > ? ? } > > - ? ?ctx->username = strdup(username); > - ? ?ctx->password = strdup(password); > + ? ?return 0; > +} > + > +int > +esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content) > +{ > + ? ?virBuffer buffer = VIR_BUFFER_INITIALIZER; > + ? ?int responseCode = 0; > > - ? ?if (ctx->username == NULL || ctx->password == NULL) { > + ? ?if (content == NULL || *content != NULL) { > + ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); > + ? ? ? ?return -1; > + ? ?} > + > + ? ?virMutexLock(&curl->lock); > + > + ? ?curl_easy_setopt(curl->handle, CURLOPT_URL, url); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_WRITEDATA, &buffer); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_UPLOAD, 0); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_HTTPGET, 1); > + > + ? ?responseCode = esxVI_CURL_Perform(curl, url); > + > + ? ?virMutexUnlock(&curl->lock); > + > + ? ?if (responseCode < 0) { > + ? ? ? ?goto cleanup; > + ? ?} else if (responseCode != 200) { > + ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, > + ? ? ? ? ? ? ? ? ? ? _("HTTP response code %d for download from '%s'"), > + ? ? ? ? ? ? ? ? ? ? responseCode, url); > + ? ? ? ?goto cleanup; > + ? ?} > + > + ? ?if (virBufferError(&buffer)) { > ? ? ? ? virReportOOMError(); > + ? ? ? ?goto cleanup; > + ? ?} > + > + ? ?*content = virBufferContentAndReset(&buffer); > + > + ?cleanup: > + ? ?if (*content == NULL) { > + ? ? ? ?virBufferFreeAndReset(&buffer); > + ? ? ? ?return -1; > + ? ?} > + > + ? ?return 0; > +} > + > +int > +esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content) > +{ > + ? ?int responseCode = 0; > + > + ? ?if (content == NULL) { > + ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); > + ? ? ? ?return -1; > + ? ?} > + > + ? ?virMutexLock(&curl->lock); > + > + ? ?curl_easy_setopt(curl->handle, CURLOPT_URL, url); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_READDATA, &content); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_UPLOAD, 1); > + ? ?curl_easy_setopt(curl->handle, CURLOPT_INFILESIZE, strlen(content)); > + > + ? ?responseCode = esxVI_CURL_Perform(curl, url); > + > + ? ?virMutexUnlock(&curl->lock); > + > + ? ?if (responseCode < 0) { > + ? ? ? ?return -1; > + ? ?} else if (responseCode != 200 && responseCode != 201) { > + ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, > + ? ? ? ? ? ? ? ? ? ? _("HTTP response code %d for upload to '%s'"), > + ? ? ? ? ? ? ? ? ? ? responseCode, url); > + ? ? ? ?return -1; > + ? ?} > + > + ? ?return 0; > +} > + > + > + > +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > + * Context > + */ > + > +/* esxVI_Context_Alloc */ > +ESX_VI__TEMPLATE__ALLOC(Context) > + > +/* esxVI_Context_Free */ > +ESX_VI__TEMPLATE__FREE(Context, > +{ > + ? ?esxVI_CURL_Free(&item->curl); > + ? ?VIR_FREE(item->url); > + ? ?VIR_FREE(item->ipAddress); > + ? ?VIR_FREE(item->username); > + ? ?VIR_FREE(item->password); > + ? ?esxVI_ServiceContent_Free(&item->service); > + ? ?esxVI_UserSession_Free(&item->session); > + ? ?esxVI_Datacenter_Free(&item->datacenter); > + ? ?esxVI_ComputeResource_Free(&item->computeResource); > + ? ?esxVI_HostSystem_Free(&item->hostSystem); > + ? ?esxVI_SelectionSpec_Free(&item->selectSet_folderToChildEntity); > + ? ?esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToParent); > + ? ?esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToVm); > + ? ?esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToDatastore); > + ? ?esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToHost); > + ? ?esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToParentToParent); > +}) > + > +int > +esxVI_Context_Connect(esxVI_Context *ctx, const char *url, > + ? ? ? ? ? ? ? ? ? ? ?const char *ipAddress, const char *username, > + ? ? ? ? ? ? ? ? ? ? ?const char *password, esxUtil_ParsedUri *parsedUri) > +{ > + ? ?if (ctx == NULL || url == NULL || ipAddress == NULL || username == NULL || > + ? ? ? ?password == NULL || ctx->url != NULL || ctx->service != NULL || > + ? ? ? ?ctx->curl != NULL) { > + ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); > + ? ? ? ?return -1; > + ? ?} > + > + ? ?if (esxVI_CURL_Alloc(&ctx->curl) < 0 || > + ? ? ? ?esxVI_CURL_Connect(ctx->curl, parsedUri) < 0 || > + ? ? ? ?esxVI_String_DeepCopyValue(&ctx->url, url) < 0 || > + ? ? ? ?esxVI_String_DeepCopyValue(&ctx->ipAddress, ipAddress) < 0 || > + ? ? ? ?esxVI_String_DeepCopyValue(&ctx->username, username) < 0 || > + ? ? ? ?esxVI_String_DeepCopyValue(&ctx->password, password) < 0) { > ? ? ? ? return -1; > ? ? } > > @@ -577,87 +674,6 @@ esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx, > ?} > > ?int > -esxVI_Context_DownloadFile(esxVI_Context *ctx, const char *url, char **content) > -{ > - ? ?virBuffer buffer = VIR_BUFFER_INITIALIZER; > - ? ?int responseCode = 0; > - > - ? ?if (content == NULL || *content != NULL) { > - ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); > - ? ? ? ?return -1; > - ? ?} > - > - ? ?virMutexLock(&ctx->curl_lock); > - > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, url); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEDATA, &buffer); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_UPLOAD, 0); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_HTTPGET, 1); > - > - ? ?responseCode = esxVI_CURL_Perform(ctx, url); > - > - ? ?virMutexUnlock(&ctx->curl_lock); > - > - ? ?if (responseCode < 0) { > - ? ? ? ?goto cleanup; > - ? ?} else if (responseCode != 200) { > - ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, > - ? ? ? ? ? ? ? ? ? ? _("HTTP response code %d for download from '%s'"), > - ? ? ? ? ? ? ? ? ? ? responseCode, url); > - ? ? ? ?goto cleanup; > - ? ?} > - > - ? ?if (virBufferError(&buffer)) { > - ? ? ? ?virReportOOMError(); > - ? ? ? ?goto cleanup; > - ? ?} > - > - ? ?*content = virBufferContentAndReset(&buffer); > - > - ?cleanup: > - ? ?if (*content == NULL) { > - ? ? ? ?virBufferFreeAndReset(&buffer); > - ? ? ? ?return -1; > - ? ?} > - > - ? ?return 0; > -} > - > -int > -esxVI_Context_UploadFile(esxVI_Context *ctx, const char *url, > - ? ? ? ? ? ? ? ? ? ? ? ? const char *content) > -{ > - ? ?int responseCode = 0; > - > - ? ?if (content == NULL) { > - ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); > - ? ? ? ?return -1; > - ? ?} > - > - ? ?virMutexLock(&ctx->curl_lock); > - > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, url); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_READDATA, &content); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_UPLOAD, 1); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_INFILESIZE, strlen(content)); > - > - ? ?responseCode = esxVI_CURL_Perform(ctx, url); > - > - ? ?virMutexUnlock(&ctx->curl_lock); > - > - ? ?if (responseCode < 0) { > - ? ? ? ?return -1; > - ? ?} else if (responseCode != 200 && responseCode != 201) { > - ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, > - ? ? ? ? ? ? ? ? ? ? _("HTTP response code %d for upload to '%s'"), > - ? ? ? ? ? ? ? ? ? ? responseCode, url); > - ? ? ? ?return -1; > - ? ?} > - > - ? ?return 0; > -} > - > -int > ?esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName, > ? ? ? ? ? ? ? ? ? ? ? const char *request, esxVI_Response **response, > ? ? ? ? ? ? ? ? ? ? ? esxVI_Occurrence occurrence) > @@ -678,17 +694,17 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName, > ? ? ? ? return -1; > ? ? } > > - ? ?virMutexLock(&ctx->curl_lock); > + ? ?virMutexLock(&ctx->curl->lock); > > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, ctx->url); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEDATA, &buffer); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_UPLOAD, 0); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDS, request); > - ? ?curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDSIZE, strlen(request)); > + ? ?curl_easy_setopt(ctx->curl->handle, CURLOPT_URL, ctx->url); > + ? ?curl_easy_setopt(ctx->curl->handle, CURLOPT_WRITEDATA, &buffer); > + ? ?curl_easy_setopt(ctx->curl->handle, CURLOPT_UPLOAD, 0); > + ? ?curl_easy_setopt(ctx->curl->handle, CURLOPT_POSTFIELDS, request); > + ? ?curl_easy_setopt(ctx->curl->handle, CURLOPT_POSTFIELDSIZE, strlen(request)); > > - ? ?(*response)->responseCode = esxVI_CURL_Perform(ctx, ctx->url); > + ? ?(*response)->responseCode = esxVI_CURL_Perform(ctx->curl, ctx->url); > > - ? ?virMutexUnlock(&ctx->curl_lock); > + ? ?virMutexUnlock(&ctx->curl->lock); > > ? ? if ((*response)->responseCode < 0) { > ? ? ? ? goto cleanup; > @@ -869,7 +885,7 @@ esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName, > ?*/ > > ?/* esxVI_Response_Alloc */ > -ESX_VI__TEMPLATE__ALLOC(Response); > +ESX_VI__TEMPLATE__ALLOC(Response) > > ?/* esxVI_Response_Free */ > ?ESX_VI__TEMPLATE__FREE(Response, > @@ -879,7 +895,7 @@ ESX_VI__TEMPLATE__FREE(Response, > ? ? if (item->document != NULL) { > ? ? ? ? xmlFreeDoc(item->document); > ? ? } > -}); > +}) > > > > diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h > index d046bf9..57788ac 100644 > --- a/src/esx/esx_vi.h > +++ b/src/esx/esx_vi.h > @@ -82,6 +82,7 @@ typedef enum _esxVI_APIVersion esxVI_APIVersion; > ?typedef enum _esxVI_ProductVersion esxVI_ProductVersion; > ?typedef enum _esxVI_Occurrence esxVI_Occurrence; > ?typedef struct _esxVI_ParsedHostCpuIdInfo esxVI_ParsedHostCpuIdInfo; > +typedef struct _esxVI_CURL esxVI_CURL; > ?typedef struct _esxVI_Context esxVI_Context; > ?typedef struct _esxVI_Response esxVI_Response; > ?typedef struct _esxVI_Enumeration esxVI_Enumeration; > @@ -142,16 +143,32 @@ struct _esxVI_ParsedHostCpuIdInfo { > > > ?/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > + * CURL > + */ > + > +struct _esxVI_CURL { > + ? ?CURL *handle; > + ? ?virMutex lock; > + ? ?struct curl_slist *headers; > + ? ?char error[CURL_ERROR_SIZE]; > +}; > + > +int esxVI_CURL_Alloc(esxVI_CURL **curl); > +void esxVI_CURL_Free(esxVI_CURL **curl); > +int esxVI_CURL_Connect(esxVI_CURL *curl, esxUtil_ParsedUri *parsedUri); > +int esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content); > +int esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content); > + > + > + > +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > ?* Context > ?*/ > > ?struct _esxVI_Context { > + ? ?esxVI_CURL *curl; > ? ? char *url; > ? ? char *ipAddress; > - ? ?CURL *curl_handle; > - ? ?struct curl_slist *curl_headers; > - ? ?char curl_error[CURL_ERROR_SIZE]; > - ? ?virMutex curl_lock; > ? ? char *username; > ? ? char *password; > ? ? esxVI_ServiceContent *service; > @@ -180,10 +197,6 @@ int esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? esxUtil_ParsedUri *parsedUri); > ?int esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const char *hostSystemIpAddress); > -int esxVI_Context_DownloadFile(esxVI_Context *ctx, const char *url, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? char **content); > -int esxVI_Context_UploadFile(esxVI_Context *ctx, const char *url, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? const char *content); > ?int esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName, > ? ? ? ? ? ? ? ? ? ? ? ? ? const char *request, esxVI_Response **response, > ? ? ? ? ? ? ? ? ? ? ? ? ? esxVI_Occurrence occurrence); > -- > 1.7.0.4 > Ping :) Matthias From matthias.bolte at googlemail.com Thu Apr 21 06:15:16 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Thu, 21 Apr 2011 08:15:16 +0200 Subject: [libvirt] [PATCH] esx: Add a wrapper for shared CURL handles In-Reply-To: <20110410151724.GA29031@sbox> References: <20110410151724.GA29031@sbox> Message-ID: 2011/4/10 Matthias Bolte : > To be used to share a CURL handle between multiple threads in the > upcoming domain event support. > --- > ?src/esx/esx_vi.c | ?176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ?src/esx/esx_vi.h | ? 19 ++++++ > ?2 files changed, 195 insertions(+), 0 deletions(-) > > diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c > index 2fd09cd..84ff2e2 100644 > --- a/src/esx/esx_vi.c > +++ b/src/esx/esx_vi.c > @@ -85,6 +85,16 @@ ESX_VI__TEMPLATE__ALLOC(CURL) > ?/* esxVI_CURL_Free */ > ?ESX_VI__TEMPLATE__FREE(CURL, > ?{ > + ? ?esxVI_SharedCURL *shared = item->shared; > + > + ? ?if (shared != NULL) { > + ? ? ? ?esxVI_SharedCURL_Remove(shared, item); > + > + ? ? ? ?if (shared->count == 0) { > + ? ? ? ? ? ?esxVI_SharedCURL_Free(&shared); > + ? ? ? ?} > + ? ?} > + > ? ? if (item->handle != NULL) { > ? ? ? ? curl_easy_cleanup(item->handle); > ? ? } > @@ -418,6 +428,172 @@ esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content) > > > ?/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > + * SharedCURL > + */ > + > +static void > +esxVI_SharedCURL_Lock(CURL *handle ATTRIBUTE_UNUSED, curl_lock_data data, > + ? ? ? ? ? ? ? ? ? ? ?curl_lock_access access_ ATTRIBUTE_UNUSED, void *userptr) > +{ > + ? ?int i; > + ? ?esxVI_SharedCURL *shared = userptr; > + > + ? ?switch (data) { > + ? ? ?case CURL_LOCK_DATA_SHARE: > + ? ? ? ?i = 0; > + ? ? ? ?break; > + > + ? ? ?case CURL_LOCK_DATA_COOKIE: > + ? ? ? ?i = 1; > + ? ? ? ?break; > + > + ? ? ?case CURL_LOCK_DATA_DNS: > + ? ? ? ?i = 2; > + ? ? ? ?break; > + > + ? ? ?default: > + ? ? ? ?VIR_ERROR(_("Trying to lock unknown SharedCURL lock %d"), (int)data); > + ? ? ? ?return; > + ? ?} > + > + ? ?virMutexLock(&shared->locks[i]); > +} > + > +static void > +esxVI_SharedCURL_Unlock(CURL *handle ATTRIBUTE_UNUSED, curl_lock_data data, > + ? ? ? ? ? ? ? ? ? ? ? ?void *userptr) > +{ > + ? ?int i; > + ? ?esxVI_SharedCURL *shared = userptr; > + > + ? ?switch (data) { > + ? ? ?case CURL_LOCK_DATA_SHARE: > + ? ? ? ?i = 0; > + ? ? ? ?break; > + > + ? ? ?case CURL_LOCK_DATA_COOKIE: > + ? ? ? ?i = 1; > + ? ? ? ?break; > + > + ? ? ?case CURL_LOCK_DATA_DNS: > + ? ? ? ?i = 2; > + ? ? ? ?break; > + > + ? ? ?default: > + ? ? ? ?VIR_ERROR(_("Trying to unlock unknown SharedCURL lock %d"), (int)data); > + ? ? ? ?return; > + ? ?} > + > + ? ?virMutexUnlock(&shared->locks[i]); > +} > + > +/* esxVI_SharedCURL_Alloc */ > +ESX_VI__TEMPLATE__ALLOC(SharedCURL) > + > +/* esxVI_SharedCURL_Free */ > +ESX_VI__TEMPLATE__FREE(SharedCURL, > +{ > + ? ?int i; > + > + ? ?if (item->count > 0) { > + ? ? ? ?/* Better leak than crash */ > + ? ? ? ?VIR_ERROR0(_("Trying to free SharedCURL object that is still in use")); > + ? ? ? ?return; > + ? ?} > + > + ? ?if (item->handle != NULL) { > + ? ? ? ?curl_share_cleanup(item->handle); > + ? ?} > + > + ? ?for (i = 0; i < ARRAY_CARDINALITY(item->locks); ++i) { > + ? ? ? ?virMutexDestroy(&item->locks[i]); > + ? ?} > +}) > + > +int > +esxVI_SharedCURL_Add(esxVI_SharedCURL *shared, esxVI_CURL *curl) > +{ > + ? ?int i; > + > + ? ?if (curl->handle == NULL) { > + ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", > + ? ? ? ? ? ? ? ? ? ? _("Cannot share uninitialized CURL handle")); > + ? ? ? ?return -1; > + ? ?} > + > + ? ?if (curl->shared != NULL) { > + ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", > + ? ? ? ? ? ? ? ? ? ? _("Cannot share CURL handle that is already shared")); > + ? ? ? ?return -1; > + ? ?} > + > + ? ?if (shared->handle == NULL) { > + ? ? ? ?shared->handle = curl_share_init(); > + > + ? ? ? ?if (shared->handle == NULL) { > + ? ? ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", > + ? ? ? ? ? ? ? ? ? ? ? ? _("Could not initialize CURL (share)")); > + ? ? ? ? ? ?return -1; > + ? ? ? ?} > + > + ? ? ? ?curl_share_setopt(shared->handle, CURLSHOPT_LOCKFUNC, > + ? ? ? ? ? ? ? ? ? ? ? ? ?esxVI_SharedCURL_Lock); > + ? ? ? ?curl_share_setopt(shared->handle, CURLSHOPT_UNLOCKFUNC, > + ? ? ? ? ? ? ? ? ? ? ? ? ?esxVI_SharedCURL_Unlock); > + ? ? ? ?curl_share_setopt(shared->handle, CURLSHOPT_USERDATA, shared); > + ? ? ? ?curl_share_setopt(shared->handle, CURLSHOPT_SHARE, > + ? ? ? ? ? ? ? ? ? ? ? ? ?CURL_LOCK_DATA_COOKIE); > + ? ? ? ?curl_share_setopt(shared->handle, CURLSHOPT_SHARE, > + ? ? ? ? ? ? ? ? ? ? ? ? ?CURL_LOCK_DATA_DNS); > + > + ? ? ? ?for (i = 0; i < ARRAY_CARDINALITY(shared->locks); ++i) { > + ? ? ? ? ? ?if (virMutexInit(&shared->locks[i]) < 0) { > + ? ? ? ? ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? _("Could not initialize a CURL (share) mutex")); > + ? ? ? ? ? ? ? ?return -1; > + ? ? ? ? ? ?} > + ? ? ? ?} > + ? ?} > + > + ? ?curl_easy_setopt(curl->handle, CURLOPT_SHARE, shared->handle); > + > + ? ?curl->shared = shared; > + ? ?++shared->count; > + > + ? ?return 0; > +} > + > +int > +esxVI_SharedCURL_Remove(esxVI_SharedCURL *shared, esxVI_CURL *curl) > +{ > + ? ?if (curl->handle == NULL) { > + ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", > + ? ? ? ? ? ? ? ? ? ? _("Cannot unshare uninitialized CURL handle")); > + ? ? ? ?return -1; > + ? ?} > + > + ? ?if (curl->shared == NULL) { > + ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", > + ? ? ? ? ? ? ? ? ? ? _("Cannot unshare CURL handle that is not shared")); > + ? ? ? ?return -1; > + ? ?} > + > + ? ?if (curl->shared != shared) { > + ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("CURL (share) mismatch")); > + ? ? ? ?return -1; > + ? ?} > + > + ? ?curl_easy_setopt(curl->handle, CURLOPT_SHARE, NULL); > + > + ? ?curl->shared = NULL; > + ? ?--shared->count; > + > + ? ?return 0; > +} > + > + > + > +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > ?* Context > ?*/ > > diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h > index 57788ac..560b2a6 100644 > --- a/src/esx/esx_vi.h > +++ b/src/esx/esx_vi.h > @@ -83,6 +83,7 @@ typedef enum _esxVI_ProductVersion esxVI_ProductVersion; > ?typedef enum _esxVI_Occurrence esxVI_Occurrence; > ?typedef struct _esxVI_ParsedHostCpuIdInfo esxVI_ParsedHostCpuIdInfo; > ?typedef struct _esxVI_CURL esxVI_CURL; > +typedef struct _esxVI_SharedCURL esxVI_SharedCURL; > ?typedef struct _esxVI_Context esxVI_Context; > ?typedef struct _esxVI_Response esxVI_Response; > ?typedef struct _esxVI_Enumeration esxVI_Enumeration; > @@ -151,6 +152,7 @@ struct _esxVI_CURL { > ? ? virMutex lock; > ? ? struct curl_slist *headers; > ? ? char error[CURL_ERROR_SIZE]; > + ? ?esxVI_SharedCURL *shared; > ?}; > > ?int esxVI_CURL_Alloc(esxVI_CURL **curl); > @@ -162,6 +164,23 @@ int esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content); > > > ?/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > + * SharedCURL > + */ > + > +struct _esxVI_SharedCURL { > + ? ?CURLSH *handle; > + ? ?virMutex locks[3]; /* share, cookie, dns */ > + ? ?size_t count; > +}; > + > +int esxVI_SharedCURL_Alloc(esxVI_SharedCURL **shared); > +void esxVI_SharedCURL_Free(esxVI_SharedCURL **shared); > +int esxVI_SharedCURL_Add(esxVI_SharedCURL *shared, esxVI_CURL *curl); > +int esxVI_SharedCURL_Remove(esxVI_SharedCURL *shared, esxVI_CURL *curl); > + > + > + > +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > ?* Context > ?*/ > > -- > 1.7.0.4 > Ping :) Matthias From matthias.bolte at googlemail.com Thu Apr 21 06:26:05 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Thu, 21 Apr 2011 08:26:05 +0200 Subject: [libvirt] [PATCH] PHYP: Adding reboot domain function In-Reply-To: <1303227248-18738-1-git-send-email-otubo@linux.vnet.ibm.com> References: <1303227248-18738-1-git-send-email-otubo@linux.vnet.ibm.com> Message-ID: 2011/4/19 Eduardo Otubo : > Adding reboot function for pHyp driver. > --- > ?src/phyp/phyp_driver.c | ? 35 ++++++++++++++++++++++++++++++++++- > ?1 files changed, 34 insertions(+), 1 deletions(-) > > diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c > index bb0e0ac..228751d 100644 > --- a/src/phyp/phyp_driver.c > +++ b/src/phyp/phyp_driver.c > @@ -3384,6 +3384,39 @@ cleanup: > ?} > > ?static int > +phypDomainReboot(virDomainPtr dom) > +{ ACK in general. But the signature of this function is incomplete, the flags parameter is missing. I added parameter and pushed the result. Matthias From laijs at cn.fujitsu.com Thu Apr 21 06:42:47 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Thu, 21 Apr 2011 14:42:47 +0800 Subject: [libvirt] [PATCH 0/6 V3] Add support for injecting NMI to guest In-Reply-To: <20110419093344.GA11901@redhat.com> References: <4DA52D1A.1000307@cn.fujitsu.com> <4DA52E3E.10402@cn.fujitsu.com> <4DA88ADE.7050208@redhat.com> <4DABF8C7.4060804@cn.fujitsu.com> <4DACC121.8030108@redhat.com> <20110419093344.GA11901@redhat.com> Message-ID: <4DAFD1E7.2010307@cn.fujitsu.com> This patch series implements a feature of injecting NMI to guest, which is accessible via new virDomainInjectNMI API and 'inject-nmi' command in virsh. Lai Jiangshan (6): inject-nmi: Defining the public API inject-nmi: Defining the internal API inject-nmi: Implementing the public API inject-nmi: Implementing the remote protocol inject-nmi: Expose the new API in virsh qemu,inject-nmi: Implement the driver methods daemon/remote.c | 28 +++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++++ daemon/remote_dispatch_table.h | 5 ++++ include/libvirt/libvirt.h.in | 2 + src/driver.h | 4 +++ src/esx/esx_driver.c | 1 + src/libvirt.c | 44 ++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 ++++ src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 3 +- src/qemu/qemu_driver.c | 45 +++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 14 +++++++++++ src/qemu/qemu_monitor.h | 2 + src/qemu/qemu_monitor_json.c | 27 +++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 1 + src/qemu/qemu_monitor_text.c | 20 +++++++++++++++ src/qemu/qemu_monitor_text.h | 1 + src/remote/remote_driver.c | 25 +++++++++++++++++++ src/remote/remote_protocol.c | 11 ++++++++ src/remote/remote_protocol.h | 10 +++++++ src/remote/remote_protocol.x | 8 +++++- src/remote_protocol-structs | 4 +++ src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xen/xen_driver.h | 1 + src/xen/xen_hypervisor.c | 1 + src/xen/xen_inotify.c | 1 + src/xen/xend_internal.c | 1 + src/xen/xm_internal.c | 1 + src/xen/xs_internal.c | 1 + src/xenapi/xenapi_driver.c | 1 + tools/virsh.c | 35 +++++++++++++++++++++++++++ tools/virsh.pod | 4 +++ 39 files changed, 321 insertions(+), 2 deletions(-) -- 1.7.4 From laijs at cn.fujitsu.com Thu Apr 21 06:42:52 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Thu, 21 Apr 2011 14:42:52 +0800 Subject: [libvirt] [PATCH 1/6 V3] inject-nmi: Defining the public API In-Reply-To: <20110419093344.GA11901@redhat.com> References: <4DA52D1A.1000307@cn.fujitsu.com> <4DA52E3E.10402@cn.fujitsu.com> <4DA88ADE.7050208@redhat.com> <4DABF8C7.4060804@cn.fujitsu.com> <4DACC121.8030108@redhat.com> <20110419093344.GA11901@redhat.com> Message-ID: <4DAFD1EC.6070900@cn.fujitsu.com> Signed-off-by: Lai Jiangshan --- include/libvirt/libvirt.h.in | 2 ++ src/libvirt_public.syms | 5 +++++ 2 files changed, 7 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 5783303..0e1e27a 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2519,6 +2519,8 @@ int virDomainOpenConsole(virDomainPtr dom, virStreamPtr st, unsigned int flags); +int virDomainInjectNMI(virDomainPtr domain, unsigned int flags); + #ifdef __cplusplus } #endif diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b4aed41..f5bbc01 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -436,4 +436,9 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8; +LIBVIRT_0.9.1 { + global: + virDomainInjectNMI; +} LIBVIRT_0.9.0; + # .... define new API here using predicted next version number .... -- 1.7.4 From laijs at cn.fujitsu.com Thu Apr 21 06:42:55 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Thu, 21 Apr 2011 14:42:55 +0800 Subject: [libvirt] [PATCH 2/6 V3] inject-nmi: Defining the internal API In-Reply-To: <20110419093344.GA11901@redhat.com> References: <4DA52D1A.1000307@cn.fujitsu.com> <4DA52E3E.10402@cn.fujitsu.com> <4DA88ADE.7050208@redhat.com> <4DABF8C7.4060804@cn.fujitsu.com> <4DACC121.8030108@redhat.com> <20110419093344.GA11901@redhat.com> Message-ID: <4DAFD1EF.5020806@cn.fujitsu.com> Signed-off-by: Lai Jiangshan --- src/driver.h | 4 ++++ src/esx/esx_driver.c | 1 + src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 3 ++- src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 1 + src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xen/xen_driver.h | 1 + src/xen/xen_hypervisor.c | 1 + src/xen/xen_inotify.c | 1 + src/xen/xend_internal.c | 1 + src/xen/xm_internal.c | 1 + src/xen/xs_internal.c | 1 + src/xenapi/xenapi_driver.c | 1 + 20 files changed, 24 insertions(+), 1 deletions(-) diff --git a/src/driver.h b/src/driver.h index a8b79e6..94cc37d 100644 --- a/src/driver.h +++ b/src/driver.h @@ -515,6 +515,9 @@ typedef int virStreamPtr st, unsigned int flags); +typedef int + (*virDrvDomainInjectNMI)(virDomainPtr dom, unsigned int flags); + /** * _virDriver: @@ -639,6 +642,7 @@ struct _virDriver { virDrvDomainSnapshotDelete domainSnapshotDelete; virDrvQemuDomainMonitorCommand qemuDomainMonitorCommand; virDrvDomainOpenConsole domainOpenConsole; + virDrvDomainInjectNMI domainInjectNMI; }; typedef int diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 50c631b..5b9edea 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4672,6 +4672,7 @@ static virDriver esxDriver = { esxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 247d78e..bc6d0d9 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2748,6 +2748,7 @@ static virDriver libxlDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; static virStateDriver libxlStateDriver = { diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e905302..fbbe803 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2906,6 +2906,7 @@ static virDriver lxcDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ lxcDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; static virStateDriver lxcStateDriver = { diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 4af28e9..96f82bb 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1667,6 +1667,7 @@ static virDriver openvzDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; int openvzRegister(void) { diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index bb0e0ac..33848ff 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -3794,7 +3794,8 @@ static virDriver phypDriver = { NULL, /* domainRevertToSnapshot */ NULL, /* domainSnapshotDelete */ NULL, /* qemuMonitorCommand */ - NULL, /* domainOpenConsole */ + NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; static virStorageDriver phypStorageDriver = { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f6e503a..ac1adbb 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7031,6 +7031,7 @@ static virDriver qemuDriver = { qemuDomainSnapshotDelete, /* domainSnapshotDelete */ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ qemuDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index e30780c..4655338 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -11298,6 +11298,7 @@ static virDriver remote_driver = { remoteDomainSnapshotDelete, /* domainSnapshotDelete */ remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ remoteDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; static virNetworkDriver network_driver = { diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 0978214..f3df6a5 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5447,6 +5447,7 @@ static virDriver testDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; static virNetworkDriver testNetworkDriver = { diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 33849a0..73a5415 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2253,6 +2253,7 @@ static virDriver umlDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ umlDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; static int diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 8241d34..6d3f533 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8652,6 +8652,7 @@ virDriver NAME(Driver) = { vboxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; virNetworkDriver NAME(NetworkDriver) = { diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index bbfb1a4..0bf3bb5 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -1007,6 +1007,7 @@ static virDriver vmwareDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; int diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 2a07b7b..4b29c01 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2141,6 +2141,7 @@ static virDriver xenUnifiedDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ xenUnifiedDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; /** diff --git a/src/xen/xen_driver.h b/src/xen/xen_driver.h index 58b8561..7cc363c 100644 --- a/src/xen/xen_driver.h +++ b/src/xen/xen_driver.h @@ -108,6 +108,7 @@ struct xenUnifiedDriver { virDrvDomainGetSchedulerType domainGetSchedulerType; virDrvDomainGetSchedulerParameters domainGetSchedulerParameters; virDrvDomainSetSchedulerParameters domainSetSchedulerParameters; + virDrvDomainInjectNMI domainInjectNMI; }; typedef struct xenXMConfCache *xenXMConfCachePtr; diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c index 9a5b41d..959e949 100644 --- a/src/xen/xen_hypervisor.c +++ b/src/xen/xen_hypervisor.c @@ -839,6 +839,7 @@ struct xenUnifiedDriver xenHypervisorDriver = { xenHypervisorGetSchedulerType, /* domainGetSchedulerType */ xenHypervisorGetSchedulerParameters, /* domainGetSchedulerParameters */ xenHypervisorSetSchedulerParameters, /* domainSetSchedulerParameters */ + NULL, /* domainInjectNMI */ }; #define virXenError(code, ...) \ diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c index d809c45..a586438 100644 --- a/src/xen/xen_inotify.c +++ b/src/xen/xen_inotify.c @@ -87,6 +87,7 @@ struct xenUnifiedDriver xenInotifyDriver = { NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ + NULL, /* domainInjectNMI */ }; static int diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index b608a43..0b4432f 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -3879,6 +3879,7 @@ struct xenUnifiedDriver xenDaemonDriver = { xenDaemonGetSchedulerType, /* domainGetSchedulerType */ xenDaemonGetSchedulerParameters, /* domainGetSchedulerParameters */ xenDaemonSetSchedulerParameters, /* domainSetSchedulerParameters */ + NULL, /* domainInjectNMI */ }; diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index db47a02..9ae7d61 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -118,6 +118,7 @@ struct xenUnifiedDriver xenXMDriver = { NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ + NULL, /* domainInjectNMI */ }; #define xenXMError(code, ...) \ diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c index c318f6c..858a321 100644 --- a/src/xen/xs_internal.c +++ b/src/xen/xs_internal.c @@ -80,6 +80,7 @@ struct xenUnifiedDriver xenStoreDriver = { NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ + NULL, /* domainInjectNMI */ }; #define virXenStoreError(code, ...) \ diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 3fbdcc6..030510c 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1889,6 +1889,7 @@ static virDriver xenapiDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainInjectNMI */ }; /** -- 1.7.4 From laijs at cn.fujitsu.com Thu Apr 21 06:42:58 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Thu, 21 Apr 2011 14:42:58 +0800 Subject: [libvirt] [PATCH 3/6 V3] inject-nmi: Implementing the public API In-Reply-To: <20110419093344.GA11901@redhat.com> References: <4DA52D1A.1000307@cn.fujitsu.com> <4DA52E3E.10402@cn.fujitsu.com> <4DA88ADE.7050208@redhat.com> <4DABF8C7.4060804@cn.fujitsu.com> <4DACC121.8030108@redhat.com> <20110419093344.GA11901@redhat.com> Message-ID: <4DAFD1F2.2060008@cn.fujitsu.com> Signed-off-by: Lai Jiangshan --- src/libvirt.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 44 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 9e6784b..32446d1 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -5214,6 +5214,50 @@ error: } /** + * virDomainInjectNMI: + * @domain: pointer to domain object, or NULL for Domain0 + * @flags: the flags for controlling behaviours + * + * Send NMI to the guest + * + * Returns 0 in case of success, -1 in case of failure. + */ + +int virDomainInjectNMI(virDomainPtr domain, unsigned int flags) +{ + virConnectPtr conn; + VIR_DOMAIN_DEBUG(domain, "flags=%u", flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return (-1); + } + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainInjectNMI) { + int ret; + ret = conn->driver->domainInjectNMI(domain, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} + +/** * virDomainSetVcpus: * @domain: pointer to domain object, or NULL for Domain0 * @nvcpus: the new number of virtual CPUs for this domain -- 1.7.4 From laijs at cn.fujitsu.com Thu Apr 21 06:43:01 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Thu, 21 Apr 2011 14:43:01 +0800 Subject: [libvirt] [PATCH 4/6 V3] inject-nmi: Implementing the remote protocol In-Reply-To: <20110419093344.GA11901@redhat.com> References: <4DA52D1A.1000307@cn.fujitsu.com> <4DA52E3E.10402@cn.fujitsu.com> <4DA88ADE.7050208@redhat.com> <4DABF8C7.4060804@cn.fujitsu.com> <4DACC121.8030108@redhat.com> <20110419093344.GA11901@redhat.com> Message-ID: <4DAFD1F5.1070007@cn.fujitsu.com> Signed-off-by: Lai Jiangshan --- daemon/remote.c | 28 ++++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++++++ daemon/remote_dispatch_table.h | 5 +++++ src/remote/remote_driver.c | 26 +++++++++++++++++++++++++- src/remote/remote_protocol.c | 11 +++++++++++ src/remote/remote_protocol.h | 10 ++++++++++ src/remote/remote_protocol.x | 8 +++++++- src/remote_protocol-structs | 4 ++++ 9 files changed, 99 insertions(+), 2 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 54fef64..9ae232e 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -3288,6 +3288,34 @@ no_memory: } static int +remoteDispatchDomainInjectNmi(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_inject_nmi_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virDomainPtr dom; + int rv = -1; + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainInjectNMI(dom, args->flags) == -1) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int remoteDispatchDomainSetVcpus(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index f9537d7..4887d7c 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -178,3 +178,4 @@ remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; remote_storage_vol_upload_args val_remote_storage_vol_upload_args; remote_storage_vol_download_args val_remote_storage_vol_download_args; + remote_domain_inject_nmi_args val_remote_domain_inject_nmi_args; diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 18bf41d..3de6046 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -338,6 +338,14 @@ static int remoteDispatchDomainHasManagedSaveImage( remote_error *err, remote_domain_has_managed_save_image_args *args, remote_domain_has_managed_save_image_ret *ret); +static int remoteDispatchDomainInjectNmi( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_inject_nmi_args *args, + void *ret); static int remoteDispatchDomainInterfaceStats( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index b39f7c2..dacafdb 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1052,3 +1052,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* DomainInjectNmi => 210 */ + .fn = (dispatch_fn) remoteDispatchDomainInjectNmi, + .args_filter = (xdrproc_t) xdr_remote_domain_inject_nmi_args, + .ret_filter = (xdrproc_t) xdr_void, +}, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 4655338..58eb682 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2933,6 +2933,30 @@ done: } static int +remoteDomainInjectNMI(virDomainPtr domain, unsigned int flags) +{ + int rv = -1; + remote_domain_inject_nmi_args args; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + make_nonnull_domain (&args.dom, domain); + args.flags = flags; + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_INJECT_NMI, + (xdrproc_t) xdr_remote_domain_inject_nmi_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int remoteDomainSetVcpus (virDomainPtr domain, unsigned int nvcpus) { int rv = -1; @@ -11298,7 +11322,7 @@ static virDriver remote_driver = { remoteDomainSnapshotDelete, /* domainSnapshotDelete */ remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ remoteDomainOpenConsole, /* domainOpenConsole */ - NULL, /* domainInjectNMI */ + remoteDomainInjectNMI, /* domainInjectNMI */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 5604371..3ff0b1f 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -1463,6 +1463,17 @@ xdr_remote_domain_undefine_args (XDR *xdrs, remote_domain_undefine_args *objp) } bool_t +xdr_remote_domain_inject_nmi_args (XDR *xdrs, remote_domain_inject_nmi_args *objp) +{ + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_domain_set_vcpus_args (XDR *xdrs, remote_domain_set_vcpus_args *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index d9bf151..4da003e 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -2200,6 +2200,13 @@ struct remote_storage_vol_download_args { u_int flags; }; typedef struct remote_storage_vol_download_args remote_storage_vol_download_args; + +struct remote_domain_inject_nmi_args { + remote_nonnull_domain dom; + u_int flags; +}; +typedef struct remote_domain_inject_nmi_args remote_domain_inject_nmi_args; + #define REMOTE_PROGRAM 0x20008086 #define REMOTE_PROTOCOL_VERSION 1 @@ -2413,6 +2420,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_INJECT_NMI = 210, }; typedef enum remote_procedure remote_procedure; @@ -2561,6 +2569,7 @@ extern bool_t xdr_remote_domain_create_with_flags_ret (XDR *, remote_domain_cre extern bool_t xdr_remote_domain_define_xml_args (XDR *, remote_domain_define_xml_args*); extern bool_t xdr_remote_domain_define_xml_ret (XDR *, remote_domain_define_xml_ret*); extern bool_t xdr_remote_domain_undefine_args (XDR *, remote_domain_undefine_args*); +extern bool_t xdr_remote_domain_inject_nmi_args (XDR *, remote_domain_inject_nmi_args*); extern bool_t xdr_remote_domain_set_vcpus_args (XDR *, remote_domain_set_vcpus_args*); extern bool_t xdr_remote_domain_set_vcpus_flags_args (XDR *, remote_domain_set_vcpus_flags_args*); extern bool_t xdr_remote_domain_get_vcpus_flags_args (XDR *, remote_domain_get_vcpus_flags_args*); @@ -2918,6 +2927,7 @@ extern bool_t xdr_remote_domain_create_with_flags_ret (); extern bool_t xdr_remote_domain_define_xml_args (); extern bool_t xdr_remote_domain_define_xml_ret (); extern bool_t xdr_remote_domain_undefine_args (); +extern bool_t xdr_remote_domain_inject_nmi_args (); extern bool_t xdr_remote_domain_set_vcpus_args (); extern bool_t xdr_remote_domain_set_vcpus_flags_args (); extern bool_t xdr_remote_domain_get_vcpus_flags_args (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 675eccd..1aacf99 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -817,6 +817,11 @@ struct remote_domain_undefine_args { remote_nonnull_domain dom; }; +struct remote_domain_inject_nmi_args { + remote_nonnull_domain dom; + unsigned int flags; +}; + struct remote_domain_set_vcpus_args { remote_nonnull_domain dom; int nvcpus; @@ -2176,8 +2181,9 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_INJECT_NMI = 210, /* * Notice how the entries are grouped in sets of 10 ? * Nice isn't it. Please keep it this way when adding more. diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 944553c..4b75e33 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1435,3 +1435,7 @@ struct remote_message_header { u_int serial; remote_message_status status; }; +struct remote_domain_inject_nmi_args { + remote_nonnull_domain dom; + unsigned int flags; +}; -- 1.7.4 From laijs at cn.fujitsu.com Thu Apr 21 06:43:04 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Thu, 21 Apr 2011 14:43:04 +0800 Subject: [libvirt] [PATCH 5/6 V3] inject-nmi: Expose the new API in virsh In-Reply-To: <20110419093344.GA11901@redhat.com> References: <4DA52D1A.1000307@cn.fujitsu.com> <4DA52E3E.10402@cn.fujitsu.com> <4DA88ADE.7050208@redhat.com> <4DABF8C7.4060804@cn.fujitsu.com> <4DACC121.8030108@redhat.com> <20110419093344.GA11901@redhat.com> Message-ID: <4DAFD1F8.1030402@cn.fujitsu.com> Signed-off-by: Lai Jiangshan --- tools/virsh.c | 35 +++++++++++++++++++++++++++++++++++ tools/virsh.pod | 4 ++++ 2 files changed, 39 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 9ac27b3..54fd6bf 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2912,6 +2912,40 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) } /* + * "inject-nmi" command + */ +static const vshCmdInfo info_inject_nmi[] = { + {"help", N_("Inject NMI to the guest")}, + {"desc", N_("Inject NMI to the guest domain.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_inject_nmi[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {NULL, 0, 0, NULL} +}; + + +static bool +cmdInjectNMI(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + int ret = true; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + return false; + + if (virDomainInjectNMI(dom, 0) < 0) + ret = false; + + virDomainFree(dom); + return ret; +} + +/* * "setmemory" command */ static const vshCmdInfo info_setmem[] = { @@ -10730,6 +10764,7 @@ static const vshCmdDef domManagementCmds[] = { {"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem}, {"setmem", cmdSetmem, opts_setmem, info_setmem}, {"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus}, + {"inject-nmi", cmdInjectNMI, opts_inject_nmi, info_inject_nmi}, {"shutdown", cmdShutdown, opts_shutdown, info_shutdown}, {"start", cmdStart, opts_start, info_start}, {"suspend", cmdSuspend, opts_suspend, info_suspend}, diff --git a/tools/virsh.pod b/tools/virsh.pod index 2a708f6..f317c57 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -290,6 +290,10 @@ running B. When in a paused state the domain will still consume allocated resources like memory, but will not be eligible for scheduling by the hypervisor. +=item B I + +Inject NMI to the guest + =item B The domain is in the process of shutting down, i.e. the guest operating system -- 1.7.4 From laijs at cn.fujitsu.com Thu Apr 21 06:43:07 2011 From: laijs at cn.fujitsu.com (Lai Jiangshan) Date: Thu, 21 Apr 2011 14:43:07 +0800 Subject: [libvirt] [PATCH 6/6 V3] qemu, inject-nmi: Implement the driver methods In-Reply-To: <20110419093344.GA11901@redhat.com> References: <4DA52D1A.1000307@cn.fujitsu.com> <4DA52E3E.10402@cn.fujitsu.com> <4DA88ADE.7050208@redhat.com> <4DABF8C7.4060804@cn.fujitsu.com> <4DACC121.8030108@redhat.com> <20110419093344.GA11901@redhat.com> Message-ID: <4DAFD1FB.30505@cn.fujitsu.com> Signed-off-by: Lai Jiangshan --- src/qemu/qemu_driver.c | 46 +++++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_monitor.c | 14 ++++++++++++ src/qemu/qemu_monitor.h | 2 + src/qemu/qemu_monitor_json.c | 27 ++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 1 + src/qemu/qemu_monitor_text.c | 20 ++++++++++++++++++ src/qemu/qemu_monitor_text.h | 1 + 7 files changed, 110 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ac1adbb..548e657 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1702,6 +1702,50 @@ static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) return qemudDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM); } +static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags) +{ + struct qemud_driver *driver = domain->conn->privateData; + virDomainObjPtr vm = NULL; + int ret = -1; + qemuDomainObjPrivatePtr priv; + + virCheckFlags(0, -1); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, domain->uuid); + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(domain->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; + } + + priv = vm->privateData; + + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + goto cleanup; + qemuDomainObjEnterMonitorWithDriver(driver, vm); + ret = qemuMonitorInjectNMI(priv->mon); + qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjEndJob(vm) == 0) { + vm = NULL; + goto cleanup; + } + +cleanup: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); + return ret; +} + static int qemudDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { @@ -7031,7 +7075,7 @@ static virDriver qemuDriver = { qemuDomainSnapshotDelete, /* domainSnapshotDelete */ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ qemuDomainOpenConsole, /* domainOpenConsole */ - NULL, /* domainInjectNMI */ + qemuDomainInjectNMI, /* domainInjectNMI */ }; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 2d28f8d..5ed41e1 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2228,3 +2228,17 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, ret = qemuMonitorTextArbitraryCommand(mon, cmd, reply); return ret; } + + +int qemuMonitorInjectNMI(qemuMonitorPtr mon) +{ + int ret; + + VIR_DEBUG("mon=%p", mon); + + if (mon->json) + ret = qemuMonitorJSONInjectNMI(mon); + else + ret = qemuMonitorTextInjectNMI(mon); + return ret; +} diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c90219b..b84e230 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -423,6 +423,8 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, char **reply, bool hmp); +int qemuMonitorInjectNMI(qemuMonitorPtr mon); + /** * When running two dd process and using <> redirection, we need a * shell that will not truncate files. These two strings serve that diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 20a78e1..04ef077 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2513,3 +2513,30 @@ cleanup: return ret; } + +int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon) +{ + int ret; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + + cmd = qemuMonitorJSONMakeCommand("inject-nmi", NULL); + if (!cmd) + return -1; + + if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0) + goto cleanup; + + if (qemuMonitorJSONHasError(reply, "CommandNotFound") && + qemuMonitorCheckHMP(mon, "inject-nmi")) { + VIR_DEBUG0("inject-nmi command not found, trying HMP"); + ret = qemuMonitorTextInjectNMI(mon); + } else { + ret = qemuMonitorJSONCheckError(cmd, reply); + } + +cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 086f0e1..f2dc4d2 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -204,4 +204,5 @@ int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon, char **reply_str, bool hmp); +int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon); #endif /* QEMU_MONITOR_JSON_H */ diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 53781c8..2ce871c 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -2628,3 +2628,23 @@ int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, return ret; } + +int qemuMonitorTextInjectNMI(qemuMonitorPtr mon) +{ + const char *cmd = "nmi 0"; + char *reply = NULL; + + /* + * FIXME: qemu's inject-nmi command is not introduced until qemu-0.15, + * use "nmi 0" instead temporary. + */ + if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("failed to inject NMI using command '%s'"), + cmd); + return -1; + } + + VIR_FREE(reply); + return 0; +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 0838a2b..dbae72b 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -198,4 +198,5 @@ int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name); int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply); +int qemuMonitorTextInjectNMI(qemuMonitorPtr mon); #endif /* QEMU_MONITOR_TEXT_H */ -- 1.7.4 From benve at cisco.com Thu Apr 21 03:38:40 2011 From: benve at cisco.com (Christian Benvenuti (benve)) Date: Wed, 20 Apr 2011 22:38:40 -0500 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <4DAF665B.2070500@linux.vnet.ibm.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com><1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> <4DAF665B.2070500@linux.vnet.ibm.com> Message-ID: <184D23435BECB444AB6B9D4630C8EC830190B4BE@XMB-RCD-303.cisco.com> > On 04/20/2011 05:28 PM, Christian Benvenuti (benve) wrote: > > Daniel, > > I looked at the patch-set you sent out on the 2/9/11 > > > > [libvirt] [PATCH 0/6] Introduce a new migration protocol > > to QEMU driver > > http://www.mail-archive.com/libvir-list at redhat.com/msg33223.html > > > > What is the status of this new migration protocol? > > Is there any pending issue blocking its integration? > > > > I would like to propose an RFC enhancement to the migration > > algorithm. > > > > Here is a quick summary of the proposal/idea. > > > > - finer control on migration result > > > > - possibility of specifying what features cannot fail > > their initialization on the dst host during migration. > > Migration should not succeed if any of them fails. > > - optional: each one of those features should be able to > > provide a deinit function to cleanup resources > > on the dst host if migration fails. > > > > This functionality would come useful for the (NIC) set port > > profile feature VDP (802.1Qbg/1Qbh), but what I propose is > > a generic config option / API that can be used by any feature. > > > > And now the details. > > > > ---------------------------------------------- > > enhancement: finer control on migration result > > ---------------------------------------------- > > > > There are different reasons why a VM may need (or be forced) to > > migrate. > > You can classify the types of the migrations also based on > > different semantics. > > For simplicity I'll classify them into two categories, based on > > how important it is for the VM to migrate as fast as possible: > > > > (1) It IS important > > > > In this case, whether the VM will not be able to (temporary) > > make use of certain resources (for example the network) on the > > dst host, is not that important, because the completion of the > > migration is considered higher priority. > > A possible scenario could be a server that must migrate ASAP > > because of a disaster/emergency. > > > > (2) It IS NOT important > > > > I can think of a VM whose applications/servers need a network > > connection in order to work properly. Loosing such network > > connectivity as a consequence of a migration would not be > > acceptable (or highly undesirable). > > > > Given the case (2) above, I have a comment about the Finish > > step, with regards to the port profile (VDP) codepath. > > > > The call to > > > > qemuMigrationVPAssociatePortProfile > > > > in > > qemuMigrationFinish > > > > can fail, but its result (success or failure) does not influence > > the result of the migration Finish step (it was already like this > > in migration V2). > > I *believe* the underlying problem is Qemu's switch-over. Once Qemu > decides that the migration was successful, Qemu on the source side dies > and continues running on the destination side. I don't think there are > more handshakes foreseen with higher layers that this could be reversed > or the switch-over delayed, but correct me if I am wrong... Actually I think this is not what happens in migration V3. My understanding is this: - the qemu cmdline built by Libvirt on the dst host during Prepare3 includes the "-S" option (ie no autostart) - the VM on the dst host does not start running until libvirt calls qemuProcessStartCPUs in the Finish3 step. This fn simply sends the "-cont" cmd to the monitor to start the VM/CPUs. If I am right, libvirt does have full control on how/when to start the CPU on the dst host, it is not QEMU to do it. The only thing libvirt does not control is when to pause the VM on the src host: QEMU does it during the stage-2 of the live-ram-copy based on the max_downtime config. However I do not think this represents a problem. Can someone confirm my understanding of the algorithm? Stefan, if this is correct, I guess the algorithm allows us to abort the migration at any time based on the success of the port profile configuration, and it would make the implementation of the policies (1)/(2) relatively easy. /Christian > So now > whatever we do, we'd have to associate the port profile before the > actual switch-over, if we wanted to do something better than what is > there now and have the opportunity to terminate the migration before > the > switch-over by Qemu happens in case of failure to associate profiles. > The problem is to know when the switch-over happens or when the > migration goes into the final phase where the source side doesn't run > anymore. The would allow us to not associate the ports right at the > beginning of the migration but maybe towards the time when for example > in live-migration the source is not running anymore *and* also we have > the result of the association before Qemu on the source dies for good. > I > think some additional coordination between libvirt and Qemu would be > necessary so that if higher layer ops fail before the resume on the > destination side happens that Qemu can still fall back to the source > side. I believe what could happen now is that a VM could be transferred > too fast (by the Qemu process) while the association (in libvirt) > happens, Qemu on the source side dies, and then we only get the > negative > result of the association. Maybe the simplest solution would be if Qemu > on the source side waited for a command before transferring the last > packet so we still have a chance to cancel and Qemu doesn't just 'run > away' underneath libvirt's feet ;-). > > I assume that 2 associations with the same profile are possible with > 802.1Qbg and Qbh. Both are also going through a Pre-associate state > now. > Are there any side-effects if associating twice on the same switch like > no packets that can be sent on the source side or something like that - > - > obviously this would be bad if this happened early during live- > migration > and we'd want to push the association close to the 'final migration > phase', which in turn may require more coordination with Qemu (don't > know whether the final phase can be determine now -- maybe via polling > Qemu's monitor). > > Regards, > Stefan From benve at cisco.com Thu Apr 21 03:52:37 2011 From: benve at cisco.com (Christian Benvenuti (benve)) Date: Wed, 20 Apr 2011 22:52:37 -0500 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <4DAF665B.2070500@linux.vnet.ibm.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com><1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> <4DAF665B.2070500@linux.vnet.ibm.com> Message-ID: <184D23435BECB444AB6B9D4630C8EC830190B4C2@XMB-RCD-303.cisco.com> > I assume that 2 associations with the same profile are possible with > 802.1Qbg and Qbh. According to the IEEE standard, it is possible to have a transient period during which you have two associations and therefore standard-compliant implementations are supposed to be able to handle it. /Christian From stefanb at linux.vnet.ibm.com Thu Apr 21 11:37:30 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Thu, 21 Apr 2011 07:37:30 -0400 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <184D23435BECB444AB6B9D4630C8EC830190B4BE@XMB-RCD-303.cisco.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com><1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> <4DAF665B.2070500@linux.vnet.ibm.com> <184D23435BECB444AB6B9D4630C8EC830190B4BE@XMB-RCD-303.cisco.com> Message-ID: <4DB016FA.7070509@linux.vnet.ibm.com> On 04/20/2011 11:38 PM, Christian Benvenuti (benve) wrote: >> On 04/20/2011 05:28 PM, Christian Benvenuti (benve) wrote: >>> Daniel, >>> I looked at the patch-set you sent out on the 2/9/11 >>> >>> [libvirt] [PATCH 0/6] Introduce a new migration protocol >>> to QEMU driver >>> http://www.mail-archive.com/libvir-list at redhat.com/msg33223.html >>> >>> What is the status of this new migration protocol? >>> Is there any pending issue blocking its integration? >>> >>> I would like to propose an RFC enhancement to the migration >>> algorithm. >>> >>> Here is a quick summary of the proposal/idea. >>> >>> - finer control on migration result >>> >>> - possibility of specifying what features cannot fail >>> their initialization on the dst host during migration. >>> Migration should not succeed if any of them fails. >>> - optional: each one of those features should be able to >>> provide a deinit function to cleanup resources >>> on the dst host if migration fails. >>> >>> This functionality would come useful for the (NIC) set port >>> profile feature VDP (802.1Qbg/1Qbh), but what I propose is >>> a generic config option / API that can be used by any feature. >>> >>> And now the details. >>> >>> ---------------------------------------------- >>> enhancement: finer control on migration result >>> ---------------------------------------------- >>> >>> There are different reasons why a VM may need (or be forced) to >>> migrate. >>> You can classify the types of the migrations also based on >>> different semantics. >>> For simplicity I'll classify them into two categories, based on >>> how important it is for the VM to migrate as fast as possible: >>> >>> (1) It IS important >>> >>> In this case, whether the VM will not be able to (temporary) >>> make use of certain resources (for example the network) on the >>> dst host, is not that important, because the completion of the >>> migration is considered higher priority. >>> A possible scenario could be a server that must migrate ASAP >>> because of a disaster/emergency. >>> >>> (2) It IS NOT important >>> >>> I can think of a VM whose applications/servers need a network >>> connection in order to work properly. Loosing such network >>> connectivity as a consequence of a migration would not be >>> acceptable (or highly undesirable). >>> >>> Given the case (2) above, I have a comment about the Finish >>> step, with regards to the port profile (VDP) codepath. >>> >>> The call to >>> >>> qemuMigrationVPAssociatePortProfile >>> >>> in >>> qemuMigrationFinish >>> >>> can fail, but its result (success or failure) does not influence >>> the result of the migration Finish step (it was already like this >>> in migration V2). >> I *believe* the underlying problem is Qemu's switch-over. Once Qemu >> decides that the migration was successful, Qemu on the source side > dies >> and continues running on the destination side. I don't think there are >> more handshakes foreseen with higher layers that this could be > reversed >> or the switch-over delayed, but correct me if I am wrong... > Actually I think this is not what happens in migration V3. > My understanding is this: > > - the qemu cmdline built by Libvirt on the dst host during Prepare3 > includes the "-S" option (ie no autostart) > > - the VM on the dst host does not start running until libvirt > calls qemuProcessStartCPUs in the Finish3 step. > This fn simply sends the "-cont" cmd to the monitor to > start the VM/CPUs. That's correct, but it's doing this already in v2. The non-autostart (-S) corresponds to Qemu's autostart here (migration.c): void process_incoming_migration(QEMUFile *f) { if (qemu_loadvm_state(f) < 0) { fprintf(stderr, "load of migration failed\n"); exit(0); } qemu_announce_self(); DPRINTF("successfully loaded vm state\n"); incoming_expected = false; if (autostart) vm_start(); } and simply doesn't start the VM. After this function is called all sockets are closed and the communication with the source host is cut. I don't think it allows for fall-back at this point. Rather we may need a 'wait' option for migration and before the qemu_put_byte(f, QEMU_VM_EOF); in qemu_savevm_state_complete() sync with the monitor and either wait for something like migrate_finish or migrate_cancel. Regards, Stefan From berrange at redhat.com Thu Apr 21 11:43:58 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 12:43:58 +0100 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <4DB016FA.7070509@linux.vnet.ibm.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com> <1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> <4DAF665B.2070500@linux.vnet.ibm.com> <184D23435BECB444AB6B9D4630C8EC830190B4BE@XMB-RCD-303.cisco.com> <4DB016FA.7070509@linux.vnet.ibm.com> Message-ID: <20110421114358.GC25985@redhat.com> On Thu, Apr 21, 2011 at 07:37:30AM -0400, Stefan Berger wrote: > On 04/20/2011 11:38 PM, Christian Benvenuti (benve) wrote: > >>On 04/20/2011 05:28 PM, Christian Benvenuti (benve) wrote: > >>>Daniel, > >>> I looked at the patch-set you sent out on the 2/9/11 > >>> > >>> [libvirt] [PATCH 0/6] Introduce a new migration protocol > >>> to QEMU driver > >>> http://www.mail-archive.com/libvir-list at redhat.com/msg33223.html > >>> > >>>What is the status of this new migration protocol? > >>>Is there any pending issue blocking its integration? > >>> > >>>I would like to propose an RFC enhancement to the migration > >>>algorithm. > >>> > >>>Here is a quick summary of the proposal/idea. > >>> > >>>- finer control on migration result > >>> > >>> - possibility of specifying what features cannot fail > >>> their initialization on the dst host during migration. > >>> Migration should not succeed if any of them fails. > >>> - optional: each one of those features should be able to > >>> provide a deinit function to cleanup resources > >>> on the dst host if migration fails. > >>> > >>>This functionality would come useful for the (NIC) set port > >>>profile feature VDP (802.1Qbg/1Qbh), but what I propose is > >>>a generic config option / API that can be used by any feature. > >>> > >>>And now the details. > >>> > >>>---------------------------------------------- > >>>enhancement: finer control on migration result > >>>---------------------------------------------- > >>> > >>>There are different reasons why a VM may need (or be forced) to > >>>migrate. > >>>You can classify the types of the migrations also based on > >>>different semantics. > >>>For simplicity I'll classify them into two categories, based on > >>>how important it is for the VM to migrate as fast as possible: > >>> > >>>(1) It IS important > >>> > >>> In this case, whether the VM will not be able to (temporary) > >>> make use of certain resources (for example the network) on the > >>> dst host, is not that important, because the completion of the > >>> migration is considered higher priority. > >>> A possible scenario could be a server that must migrate ASAP > >>> because of a disaster/emergency. > >>> > >>>(2) It IS NOT important > >>> > >>> I can think of a VM whose applications/servers need a network > >>> connection in order to work properly. Loosing such network > >>> connectivity as a consequence of a migration would not be > >>> acceptable (or highly undesirable). > >>> > >>>Given the case (2) above, I have a comment about the Finish > >>>step, with regards to the port profile (VDP) codepath. > >>> > >>>The call to > >>> > >>> qemuMigrationVPAssociatePortProfile > >>> > >>>in > >>> qemuMigrationFinish > >>> > >>>can fail, but its result (success or failure) does not influence > >>>the result of the migration Finish step (it was already like this > >>>in migration V2). > >>I *believe* the underlying problem is Qemu's switch-over. Once Qemu > >>decides that the migration was successful, Qemu on the source side > >dies > >>and continues running on the destination side. I don't think there are > >>more handshakes foreseen with higher layers that this could be > >reversed > >>or the switch-over delayed, but correct me if I am wrong... > >Actually I think this is not what happens in migration V3. > >My understanding is this: > > > >- the qemu cmdline built by Libvirt on the dst host during Prepare3 > > includes the "-S" option (ie no autostart) > > > >- the VM on the dst host does not start running until libvirt > > calls qemuProcessStartCPUs in the Finish3 step. > > This fn simply sends the "-cont" cmd to the monitor to > > start the VM/CPUs. > That's correct, but it's doing this already in v2. The non-autostart > (-S) corresponds to Qemu's autostart here (migration.c): > > void process_incoming_migration(QEMUFile *f) > { > if (qemu_loadvm_state(f) < 0) { > fprintf(stderr, "load of migration failed\n"); > exit(0); > } > qemu_announce_self(); > DPRINTF("successfully loaded vm state\n"); > > incoming_expected = false; > > if (autostart) > vm_start(); > } > > and simply doesn't start the VM. After this function is called all > sockets are closed and the communication with the source host is > cut. I don't think it allows for fall-back at this point. Sure it does. As long as the destination QEMU CPUs have not been started, you can fallback by simply killing the dest QEMU and restarting CPUs on the src QEMU. > Rather we may need a 'wait' option for migration and before the > > qemu_put_byte(f, QEMU_VM_EOF); > > in qemu_savevm_state_complete() sync with the monitor and either > wait for something like migrate_finish or migrate_cancel. The real problem, is that while we can tell from 'info migrate' on the src, when the src has finished sending all data, there is no way to ask the dest QEMU when it has finished receiving all data. So libvirt assumes that 'src finished sending' == success, and will attempt to start the dst QEMU CPUs. As raised many times in the past, we need 'info migrate' to work on the destination too, in order to query success/fail. And ideally need async events emitted when migration completes, so we don't have to poll on 'info migrate' every 50ms Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Thu Apr 21 11:52:37 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 12:52:37 +0100 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <184D23435BECB444AB6B9D4630C8EC830190B4BE@XMB-RCD-303.cisco.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com> <1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> <4DAF665B.2070500@linux.vnet.ibm.com> <184D23435BECB444AB6B9D4630C8EC830190B4BE@XMB-RCD-303.cisco.com> Message-ID: <20110421115237.GD25985@redhat.com> On Wed, Apr 20, 2011 at 10:38:40PM -0500, Christian Benvenuti (benve) wrote: > > On 04/20/2011 05:28 PM, Christian Benvenuti (benve) wrote: > > > Daniel, > > > I looked at the patch-set you sent out on the 2/9/11 > > > > > > [libvirt] [PATCH 0/6] Introduce a new migration protocol > > > to QEMU driver > > > http://www.mail-archive.com/libvir-list at redhat.com/msg33223.html > > > > > > What is the status of this new migration protocol? > > > Is there any pending issue blocking its integration? > > > > > > I would like to propose an RFC enhancement to the migration > > > algorithm. > > > > > > Here is a quick summary of the proposal/idea. > > > > > > - finer control on migration result > > > > > > - possibility of specifying what features cannot fail > > > their initialization on the dst host during migration. > > > Migration should not succeed if any of them fails. > > > - optional: each one of those features should be able to > > > provide a deinit function to cleanup resources > > > on the dst host if migration fails. > > > > > > This functionality would come useful for the (NIC) set port > > > profile feature VDP (802.1Qbg/1Qbh), but what I propose is > > > a generic config option / API that can be used by any feature. > > > > > > And now the details. > > > > > > ---------------------------------------------- > > > enhancement: finer control on migration result > > > ---------------------------------------------- > > > > > > There are different reasons why a VM may need (or be forced) to > > > migrate. > > > You can classify the types of the migrations also based on > > > different semantics. > > > For simplicity I'll classify them into two categories, based on > > > how important it is for the VM to migrate as fast as possible: > > > > > > (1) It IS important > > > > > > In this case, whether the VM will not be able to (temporary) > > > make use of certain resources (for example the network) on the > > > dst host, is not that important, because the completion of the > > > migration is considered higher priority. > > > A possible scenario could be a server that must migrate ASAP > > > because of a disaster/emergency. > > > > > > (2) It IS NOT important > > > > > > I can think of a VM whose applications/servers need a network > > > connection in order to work properly. Loosing such network > > > connectivity as a consequence of a migration would not be > > > acceptable (or highly undesirable). > > > > > > Given the case (2) above, I have a comment about the Finish > > > step, with regards to the port profile (VDP) codepath. > > > > > > The call to > > > > > > qemuMigrationVPAssociatePortProfile > > > > > > in > > > qemuMigrationFinish > > > > > > can fail, but its result (success or failure) does not influence > > > the result of the migration Finish step (it was already like this > > > in migration V2). > > > > I *believe* the underlying problem is Qemu's switch-over. Once Qemu > > decides that the migration was successful, Qemu on the source side > dies > > and continues running on the destination side. I don't think there are > > more handshakes foreseen with higher layers that this could be > reversed > > or the switch-over delayed, but correct me if I am wrong... > > Actually I think this is not what happens in migration V3. > My understanding is this: > > - the qemu cmdline built by Libvirt on the dst host during Prepare3 > includes the "-S" option (ie no autostart) > > - the VM on the dst host does not start running until libvirt > calls qemuProcessStartCPUs in the Finish3 step. > This fn simply sends the "-cont" cmd to the monitor to > start the VM/CPUs. > > If I am right, libvirt does have full control on how/when to start > the CPU on the dst host, it is not QEMU to do it. That is correct. It is libvirt that decides when to kill the src QEMU, and in theory when to start the CPUs on the dst. In practice we can't reliably determine the latter, until QEMU gives us more info, so we just start CPUs once src has finished sending data. > The only thing libvirt does not control is when to pause the VM > on the src host: QEMU does it during the stage-2 of the live-ram-copy > based on the max_downtime config. > However I do not think this represents a problem. Correct, that's no problem. The key thing is that libvirt decides when to start dst CPUs & kill src QEMU process. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From berrange at redhat.com Thu Apr 21 12:01:32 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 13:01:32 +0100 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com> <1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> Message-ID: <20110421120132.GE25985@redhat.com> On Wed, Apr 20, 2011 at 04:28:12PM -0500, Christian Benvenuti (benve) wrote: > Daniel, > I looked at the patch-set you sent out on the 2/9/11 > > [libvirt] [PATCH 0/6] Introduce a new migration protocol > to QEMU driver > http://www.mail-archive.com/libvir-list at redhat.com/msg33223.html > > What is the status of this new migration protocol? > Is there any pending issue blocking its integration? > > I would like to propose an RFC enhancement to the migration > algorithm. > > Here is a quick summary of the proposal/idea. > > - finer control on migration result > > - possibility of specifying what features cannot fail > their initialization on the dst host during migration. > Migration should not succeed if any of them fails. > - optional: each one of those features should be able to > provide a deinit function to cleanup resources > on the dst host if migration fails. I'm not really very convinced that allowing things to fail during migration is useful, not least from the POV of the app determining just what worked vs failed. IMHO, migration should be atomic and only succeed, if everything related to the guest succeeds. If we want to support a case where the dst can't connect to the same network, then we should add an API that lets us change the network backend on the fly. NB, this is different from NIC hotplug/unplug, in that the guest device never changes. We merely change how the guest is connected to the host. So, if you have a guest with a NIC configureed using VEPA, then you can re-configure it to use a 'no op' (aka /dev/null) NIC backend, and then perform the migration. > ---------------------------------------------- > enhancement: finer control on migration result > ---------------------------------------------- > > There are different reasons why a VM may need (or be forced) to > migrate. > You can classify the types of the migrations also based on > different semantics. > For simplicity I'll classify them into two categories, based on > how important it is for the VM to migrate as fast as possible: > > (1) It IS important > > In this case, whether the VM will not be able to (temporary) > make use of certain resources (for example the network) on the > dst host, is not that important, because the completion of the > migration is considered higher priority. > A possible scenario could be a server that must migrate ASAP > because of a disaster/emergency. > > (2) It IS NOT important > > I can think of a VM whose applications/servers need a network > connection in order to work properly. Loosing such network > connectivity as a consequence of a migration would not be > acceptable (or highly undesirable). > > Given the case (2) above, I have a comment about the Finish > step, with regards to the port profile (VDP) codepath. > > The call to > > qemuMigrationVPAssociatePortProfile > > in > qemuMigrationFinish > > can fail, but its result (success or failure) does not influence > the result of the migration Finish step (it was already like this > in migration V2). > It is therefore possible for a VM to lose its network connectivity > after a (successful) migration. That is a clear bug in our code - something that can fail during migration, should be causing migration to abort, leaving the guest on the original host unchanged. > BTW, would the new functionality being discussed in this 3D > > "RFC: virInterface change transaction API" > http://www.redhat.com/archives/libvir-list/2011-April/msg00499.html > > be able to provide the same configuration "atomicity" (ie, rollback > in case of migration failure)? > My understanding is that: > > - Such new framework would apply to (host) network config only. > Even though it may cover the VDP (port profile) use case I > mentioned above, it would not apply to other features that > may need some kind of rollback after a migration failure. Host NIC configuration from virInterface isn't really tied into the migration at all. It is something the mgmt app has to do on the source & dest hosts, before setting up any VMs, let alone getting to migration. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From jdenemar at redhat.com Thu Apr 21 12:21:51 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Thu, 21 Apr 2011 14:21:51 +0200 Subject: [libvirt] [PATCH] Remove artificial minimum limit for guest memory Message-ID: <068add8ea95750f9551a4de5e8d8c698612a14ab.1303388511.git.jdenemar@redhat.com> Remove the artificial minimum of 4096 KB for guest memory. It's drivers' job to set the limit if needed. --- src/libvirt.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 9e6784b..10c3cdf 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -2738,7 +2738,7 @@ virDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); goto error; } - if (memory < 4096) { + if (!memory) { virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } @@ -2792,7 +2792,7 @@ virDomainSetMemory(virDomainPtr domain, unsigned long memory) virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); goto error; } - if (memory < 4096) { + if (!memory) { virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } @@ -2861,7 +2861,7 @@ virDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory, goto error; } - if (memory < 4096) { + if (!memory) { virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } -- 1.7.5.rc1 From eblake at redhat.com Thu Apr 21 12:40:58 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 21 Apr 2011 06:40:58 -0600 Subject: [libvirt] [PATCH] Remove artificial minimum limit for guest memory In-Reply-To: <068add8ea95750f9551a4de5e8d8c698612a14ab.1303388511.git.jdenemar@redhat.com> References: <068add8ea95750f9551a4de5e8d8c698612a14ab.1303388511.git.jdenemar@redhat.com> Message-ID: <4DB025DA.5030608@redhat.com> On 04/21/2011 06:21 AM, Jiri Denemark wrote: > Remove the artificial minimum of 4096 KB for guest memory. It's drivers' > job to set the limit if needed. > --- > src/libvirt.c | 6 +++--- > 1 files changed, 3 insertions(+), 3 deletions(-) ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From berrange at redhat.com Thu Apr 21 13:33:56 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 14:33:56 +0100 Subject: [libvirt] tunnelled migration with libvirt 0.9.0 In-Reply-To: <4DAEDA59.7010103@redhat.com> References: <4DAEAA47.6080500@collax.com> <4DAEB42C.70900@cn.fujitsu.com> <4DAEBFEF.1060806@collax.com> <4DAEDA59.7010103@redhat.com> Message-ID: <20110421133356.GF25985@redhat.com> On Wed, Apr 20, 2011 at 07:06:33AM -0600, Eric Blake wrote: > On 04/20/2011 05:13 AM, Jason Krieg wrote: > > that was my first guess but it does not work the remote monitor socket > > does not show up > > > > libvirt is running as root so it should not be a permission problem > > > > qemuMonitorOpenUnix:289 : monitor socket did not show up.: Connection > > refused > > qemuProcessWaitForMonitor:1059 : internal error process exited while > > connecting to monitor: Migration failed. Exit code fd:14(-22), exiting. > > Exit code fd:14(-22) is EBADF on fd 14; I've seen it in the past when we > were incorrectly leaving FD_CLOEXEC set on fd 14, but I don't see how > that would be possible in the code path for qemuMigrationPrepareTunnel. The problem is that '-incoming fd:NNN' wants a file descriptor *read* from, but we're passing it the *write* end of the pipe. Thus fopen(fd, "rb") fails with EINVAL Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From jdenemar at redhat.com Thu Apr 21 13:45:35 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Thu, 21 Apr 2011 15:45:35 +0200 Subject: [libvirt] [PATCH] Remove artificial minimum limit for guest memory In-Reply-To: <4DB025DA.5030608@redhat.com> References: <068add8ea95750f9551a4de5e8d8c698612a14ab.1303388511.git.jdenemar@redhat.com> <4DB025DA.5030608@redhat.com> Message-ID: <20110421134535.GI1245361@orkuz.home> On Thu, Apr 21, 2011 at 06:40:58 -0600, Eric Blake wrote: > On 04/21/2011 06:21 AM, Jiri Denemark wrote: > > Remove the artificial minimum of 4096 KB for guest memory. It's drivers' > > job to set the limit if needed. > > --- > > src/libvirt.c | 6 +++--- > > 1 files changed, 3 insertions(+), 3 deletions(-) > > ACK. Pushed, thanks. Jirka From stefanb at linux.vnet.ibm.com Thu Apr 21 13:33:42 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Thu, 21 Apr 2011 09:33:42 -0400 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <20110421114358.GC25985@redhat.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com> <1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> <4DAF665B.2070500@linux.vnet.ibm.com> <184D23435BECB444AB6B9D4630C8EC830190B4BE@XMB-RCD-303.cisco.com> <4DB016FA.7070509@linux.vnet.ibm.com> <20110421114358.GC25985@redhat.com> Message-ID: <4DB03236.7000005@linux.vnet.ibm.com> On 04/21/2011 07:43 AM, Daniel P. Berrange wrote: > On Thu, Apr 21, 2011 at 07:37:30AM -0400, Stefan Berger wrote: >> >> and simply doesn't start the VM. After this function is called all >> sockets are closed and the communication with the source host is >> cut. I don't think it allows for fall-back at this point. > Sure it does. As long as the destination QEMU CPUs have not been > started, you can fallback by simply killing the dest QEMU and > restarting CPUs on the src QEMU. > FWIW, I did a test and disabled the starting of the CPUs on the destination side and did a sleep() instead. Before the sleep() was over the Qemu on the source side had already disappeared. Stefan From berrange at redhat.com Thu Apr 21 14:24:31 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 15:24:31 +0100 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <4DB03236.7000005@linux.vnet.ibm.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com> <1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> <4DAF665B.2070500@linux.vnet.ibm.com> <184D23435BECB444AB6B9D4630C8EC830190B4BE@XMB-RCD-303.cisco.com> <4DB016FA.7070509@linux.vnet.ibm.com> <20110421114358.GC25985@redhat.com> <4DB03236.7000005@linux.vnet.ibm.com> Message-ID: <20110421142431.GG25985@redhat.com> On Thu, Apr 21, 2011 at 09:33:42AM -0400, Stefan Berger wrote: > On 04/21/2011 07:43 AM, Daniel P. Berrange wrote: > >On Thu, Apr 21, 2011 at 07:37:30AM -0400, Stefan Berger wrote: > >> > >>and simply doesn't start the VM. After this function is called all > >>sockets are closed and the communication with the source host is > >>cut. I don't think it allows for fall-back at this point. > >Sure it does. As long as the destination QEMU CPUs have not been > >started, you can fallback by simply killing the dest QEMU and > >restarting CPUs on the src QEMU. > > > FWIW, I did a test and disabled the starting of the CPUs on the > destination side and > did a sleep() instead. Before the sleep() was over the Qemu on the > source side had already disappeared. That is with the old v2 migration protocol. In the new v3 protocol that has changed to work as I described. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| From eblake at redhat.com Thu Apr 21 14:26:21 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 21 Apr 2011 08:26:21 -0600 Subject: [libvirt] [PATCH] build: fix 32-bit test failure Message-ID: <1303395981-26718-1-git-send-email-eblake@redhat.com> ARRAY_CARDINALITY is typed as size_t, not long; this matters on 32-bit platforms: hashtest.c: In function 'testHashRemoveForEach': hashtest.c:114: error: format '%lu' expects type 'long unsigned int', but argument 4 has type 'unsigned int' [-Wformat] * tests/hashtest.c (testHashRemoveForEach): Use correct format. --- Pushing under the build-breaker rule. tests/hashtest.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/tests/hashtest.c b/tests/hashtest.c index dff0181..722b44c 100644 --- a/tests/hashtest.c +++ b/tests/hashtest.c @@ -112,7 +112,7 @@ testHashRemoveForEach(const void *data) if (count != ARRAY_CARDINALITY(uuids)) { if (virTestGetVerbose()) { testError("\nvirHashForEach didn't go through all entries," - " %d != %lu\n", + " %d != %zu\n", count, ARRAY_CARDINALITY(uuids)); } goto cleanup; -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 15:05:44 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 16:05:44 +0100 Subject: [libvirt] [PATCH] Fix QEMU tunnelled migration FD handling Message-ID: <1303398344-12641-1-git-send-email-berrange@redhat.com> The two ends of the pipe used for feeding QEMU tunnelled migration data were interchanged, so QEMU got given the "write" end instead of the "read" end. The qemuMigrationPrepareTunnel method was also immediately closing the "write" end of the pipe, so the stream failed to actually write anything. * src/qemu/qemu_migration.c: Swap tunnelled migration pipe FDs & don't close pipe given to stream --- src/qemu/qemu_migration.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index bba76d5..7f4b111 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -301,7 +301,7 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, vm->def->id = -1; if (pipe(dataFD) < 0 || - virSetCloseExec(dataFD[0]) < 0) { + virSetCloseExec(dataFD[1]) < 0) { virReportSystemError(errno, "%s", _("cannot create pipe for tunnelled migration")); goto endjob; @@ -318,7 +318,7 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, /* Start the QEMU daemon, with the same command-line arguments plus * -incoming stdio (which qemu_command might convert to exec:cat or fd:n) */ - internalret = qemuProcessStart(dconn, driver, vm, "stdio", true, dataFD[1], + internalret = qemuProcessStart(dconn, driver, vm, "stdio", true, dataFD[0], NULL, VIR_VM_OP_MIGRATE_IN_START); if (internalret < 0) { qemuAuditDomainStart(vm, "migrated", false); @@ -332,7 +332,7 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, goto endjob; } - if (virFDStreamOpen(st, dataFD[0]) < 0) { + if (virFDStreamOpen(st, dataFD[1]) < 0) { qemuAuditDomainStart(vm, "migrated", false); qemuProcessStop(driver, vm, 0); if (!vm->persistent) { @@ -344,6 +344,7 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, _("cannot pass pipe for tunnelled migration")); goto endjob; } + dataFD[1] = -1; /* 'st' owns the FD now & will close it */ qemuAuditDomainStart(vm, "migrated", true); -- 1.7.4.4 From mprivozn at redhat.com Thu Apr 21 15:27:40 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Thu, 21 Apr 2011 17:27:40 +0200 Subject: [libvirt] [PATCH] Add support for s390(x) cpu options parsing Message-ID: <1303399660-21831-1-git-send-email-mprivozn@redhat.com> Up to now we missed parser for cpuinfo on x390(x) machines. Those machines have only 1 thread, core, socket. What is missing is information about CPU frequency. --- src/nodeinfo.c | 29 +++++++++++++++++++++++++++-- 1 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/nodeinfo.c b/src/nodeinfo.c index e0221f0..f55c83e 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -165,8 +165,10 @@ static int parse_socket(unsigned int cpu) { int ret = get_cpu_value(cpu, "topology/physical_package_id", false); # if defined(__powerpc__) || \ - defined(__powerpc64__) - /* ppc has -1 */ + defined(__powerpc64__) || \ + defined(__s390__) || \ + defined(__s390x__) + /* ppc and s390(x) has -1 */ if (ret < 0) ret = 0; # endif @@ -265,6 +267,29 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo, && (*p == '\0' || *p == '.' || c_isspace(*p))) nodeinfo->mhz = ui; } +# elif defined(__s390__) || \ + defined(__s390x__) + } else if (STRPREFIX(buf, "# processors")) { + char *p; + unsigned int ui; + buf += 12; + while (*buf && c_isspace(*buf)) + buf++; + if (*buf != ':' || !buf[1]) { + nodeReportError(VIR_ERR_INTERNAL_ERROR, + _("parsing number of processors %c"), *buf); + return -1; + } + if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 + && (*p == '\0' || c_isspace(*p))) + nodeinfo->cpus = ui; + /* No other interesting infos are available in /proc/cpuinfo. + * However, there is a line identifying processor's version, + * identification and machine, but we don't want it to be caught + * and parsed in next iteration, because it is not in expected + * format and thus lead to error. */ + break; + } # else # warning Parser for /proc/cpuinfo needs to be adapted for your architecture # endif -- 1.7.4.4 From eblake at redhat.com Thu Apr 21 16:04:16 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 21 Apr 2011 10:04:16 -0600 Subject: [libvirt] [PATCH] Fix QEMU tunnelled migration FD handling In-Reply-To: <1303398344-12641-1-git-send-email-berrange@redhat.com> References: <1303398344-12641-1-git-send-email-berrange@redhat.com> Message-ID: <4DB05580.4060805@redhat.com> On 04/21/2011 09:05 AM, Daniel P. Berrange wrote: > The two ends of the pipe used for feeding QEMU tunnelled > migration data were interchanged, so QEMU got given the > "write" end instead of the "read" end. > > The qemuMigrationPrepareTunnel method was also immediately > closing the "write" end of the pipe, so the stream failed > to actually write anything. > > * src/qemu/qemu_migration.c: Swap tunnelled migration > pipe FDs & don't close pipe given to stream > --- > src/qemu/qemu_migration.c | 7 ++++--- > 1 files changed, 4 insertions(+), 3 deletions(-) ACK - fixes regression introduced in commit c7af07ac. > > diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c > index bba76d5..7f4b111 100644 > --- a/src/qemu/qemu_migration.c > +++ b/src/qemu/qemu_migration.c > @@ -301,7 +301,7 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, > vm->def->id = -1; > > if (pipe(dataFD) < 0 || > - virSetCloseExec(dataFD[0]) < 0) { > + virSetCloseExec(dataFD[1]) < 0) { And sorry for botching it. socketpair() is a bit nicer than pipe() in that it's bi-directional and you don't have to think about which end is the write end. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 21 16:08:30 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 21 Apr 2011 10:08:30 -0600 Subject: [libvirt] [PATCH] Add support for s390(x) cpu options parsing In-Reply-To: <1303399660-21831-1-git-send-email-mprivozn@redhat.com> References: <1303399660-21831-1-git-send-email-mprivozn@redhat.com> Message-ID: <4DB0567E.7000808@redhat.com> On 04/21/2011 09:27 AM, Michal Privoznik wrote: > Up to now we missed parser for cpuinfo on x390(x) machines. Those machines > have only 1 thread, core, socket. What is missing is information about > CPU frequency. > --- > src/nodeinfo.c | 29 +++++++++++++++++++++++++++-- > 1 files changed, 27 insertions(+), 2 deletions(-) ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From berrange at redhat.com Thu Apr 21 16:32:39 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:39 +0100 Subject: [libvirt] [PATCH 00/16] Implement migration v3 protocol Message-ID: <1303403575-20220-1-git-send-email-berrange@redhat.com> This is an major update to http://www.redhat.com/archives/libvir-list/2011-February/msg00257.html In this update - Bug fixes from previous review - Remove assert() usage - Introduce SPICE graphics relocation - Refactoring of peer2peer & tunnelled migration code - Support for v3 migration with p2p & tunnelled migration - A (broken) attempt to make job signal/status updates work with tunnelled migration The latter item seemed to be working fine, but I've since found that it can cause QEMU to deadlock. While we're sending QEMU a montor command to update status, QEMU may be trying to write some migration data and it often blocks on write() to the migration socket. This could be a bug with us not giving it a non-blocking socket, or it could be a QEMU limitation. To be investigated.... From berrange at redhat.com Thu Apr 21 16:32:40 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:40 +0100 Subject: [libvirt] [PATCH 01/16] Remove bogus assert() from migration code In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-2-git-send-email-berrange@redhat.com> assert() is forbidden in libvirt code, and these two cases would in fact never execute due to earlier error checks. * src/libvirt.c: Remove assert() usage --- src/libvirt.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 10c3cdf..d369aae 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -3368,7 +3367,6 @@ virDomainMigrateVersion1 (virDomainPtr domain, } if (uri_out) uri = uri_out; /* Did domainMigratePrepare change URI? */ - assert (uri != NULL); /* Perform the migration. The driver isn't supposed to return * until the migration is complete. @@ -3458,7 +3456,6 @@ virDomainMigrateVersion2 (virDomainPtr domain, } if (uri_out) uri = uri_out; /* Did domainMigratePrepare2 change URI? */ - assert (uri != NULL); /* Perform the migration. The driver isn't supposed to return * until the migration is complete. -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:41 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:41 +0100 Subject: [libvirt] [PATCH 02/16] Introduce yet another migration version in API. In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-3-git-send-email-berrange@redhat.com> Migration just seems togo from bad to worse. We already had to introduce a second migration protocol when adding the QEMU driver, since the one from Xen was insufficiently flexible to cope with passing the data the QEMU driver required. It turns out that this protocol still has some flaws that we need to address. The current sequence is * Src: DumpXML - Generate XML to pass to dst * Dst: Prepare - Get ready to accept incoming VM - Generate optional cookie to pass to src * Src: Perform - Start migration and wait for send completion - Kill off VM if successful, resume if failed * Dst: Finish - Wait for recv completion and check status - Kill off VM if unsuccessful The problems with this are: - Since the first step is a generic 'DumpXML' call, we can't add in other migration specific data. eg, we can't include any VM lease data from lock manager plugins - Since the first step is a generic 'DumpXML' call, we can't emit any 'migration begin' event on the source, or have any hook that runs right at the start of the process - Since there is no final step on the source, if the Finish method fails to receive all migration data & has to kill the VM, then there's no way to resume the original VM on the source This patch attempts to introduce a version 3 that uses the improved 5 step sequence * Src: Begin - Generate XML to pass to dst - Generate optional cookie to pass to dst * Dst: Prepare - Get ready to accept incoming VM - Generate optional cookie to pass to src * Src: Perform - Start migration and wait for send completion - Generate optional cookie to pass to dst * Dst: Finish - Wait for recv completion and check status - Kill off VM if failed, resume if success - Generate optional cookie to pass to src * Src: Confirm - Kill off VM if success, resume if failed The API is designed to allow both input and output cookies in all methods where applicable. This lets us pass around arbitrary extra driver specific data between src & dst during migration. Combined with the extra 'Begin' method this lets us pass lease information from source to dst at the start of migration Moving the killing of the source VM out of Perform and into Confirm, means we can now recover if the dst host can't successfully Finish receiving migration data. --- src/driver.h | 77 ++++++- src/esx/esx_driver.c | 6 + src/libvirt.c | 578 ++++++++++++++++++++++++++++++++++++++++++-- src/libvirt_internal.h | 66 +++++ src/libvirt_private.syms | 6 + src/lxc/lxc_driver.c | 6 + src/openvz/openvz_driver.c | 6 + src/phyp/phyp_driver.c | 6 + src/qemu/qemu_driver.c | 6 + src/remote/remote_driver.c | 6 + src/test/test_driver.c | 6 + src/uml/uml_driver.c | 6 + src/vbox/vbox_tmpl.c | 6 + src/vmware/vmware_driver.c | 6 + src/xen/xen_driver.c | 6 + src/xenapi/xenapi_driver.c | 6 + 16 files changed, 779 insertions(+), 20 deletions(-) diff --git a/src/driver.h b/src/driver.h index a8b79e6..80c9ebc 100644 --- a/src/driver.h +++ b/src/driver.h @@ -403,7 +403,7 @@ typedef int typedef int (*virDrvDomainMigratePrepareTunnel) - (virConnectPtr conn, + (virConnectPtr dconn, virStreamPtr st, unsigned long flags, const char *dname, @@ -515,6 +515,75 @@ typedef int virStreamPtr st, unsigned int flags); +typedef char * + (*virDrvDomainMigrateBegin3) + (virDomainPtr domain, + char **cookieout, + int *cookieoutlen, + unsigned long flags, + const char *dname, + unsigned long resource); + +typedef int + (*virDrvDomainMigratePrepare3) + (virConnectPtr dconn, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri_in, + char **uri_out, + unsigned long flags, + const char *dname, + unsigned long resource, + const char *dom_xml); + +typedef int + (*virDrvDomainMigratePrepareTunnel3) + (virConnectPtr dconn, + virStreamPtr st, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + unsigned long flags, + const char *dname, + unsigned long resource, + const char *dom_xml); + + +typedef int + (*virDrvDomainMigratePerform3) + (virDomainPtr dom, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri, + unsigned long flags, + const char *dname, + unsigned long resource); + +typedef int + (*virDrvDomainMigrateFinish3) + (virConnectPtr dconn, + const char *dname, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri, + unsigned long flags, + int cancelled, + virDomainPtr *newdom); + +typedef int + (*virDrvDomainMigrateConfirm3) + (virDomainPtr domain, + const char *cookiein, + int cookieinlen, + unsigned long flags, + int cancelled); /** * _virDriver: @@ -639,6 +708,12 @@ struct _virDriver { virDrvDomainSnapshotDelete domainSnapshotDelete; virDrvQemuDomainMonitorCommand qemuDomainMonitorCommand; virDrvDomainOpenConsole domainOpenConsole; + virDrvDomainMigrateBegin3 domainMigrateBegin3; + virDrvDomainMigratePrepare3 domainMigratePrepare3; + virDrvDomainMigratePrepareTunnel3 domainMigratePrepareTunnel3; + virDrvDomainMigratePerform3 domainMigratePerform3; + virDrvDomainMigrateFinish3 domainMigrateFinish3; + virDrvDomainMigrateConfirm3 domainMigrateConfirm3; }; typedef int diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 50c631b..bfe8127 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4672,6 +4672,12 @@ static virDriver esxDriver = { esxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainMigrateBegin3 */ + NULL, /* domainMigratePrepare3 */ + NULL, /* domainMigratePrepareTunnel3 */ + NULL, /* domainMigratePerform3 */ + NULL, /* domainMigrateFinish3 */ + NULL, /* domainMigrateConfirm3 */ }; diff --git a/src/libvirt.c b/src/libvirt.c index d369aae..5389df7 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3325,6 +3325,22 @@ error: } +/* + * Sequence v1: + * + * Dst: Prepare + * - Get ready to accept incoming VM + * - Generate optional cookie to pass to src + * + * Src: Perform + * - Start migration and wait for send completion + * - Kill off VM if successful, resume if failed + * + * Dst: Finish + * - Wait for recv completion and check status + * - Kill off VM if unsuccessful + * + */ static virDomainPtr virDomainMigrateVersion1 (virDomainPtr domain, virConnectPtr dconn, @@ -3393,6 +3409,25 @@ virDomainMigrateVersion1 (virDomainPtr domain, return ddomain; } +/* + * Sequence v2: + * + * Src: DumpXML + * - Generate XML to pass to dst + * + * Dst: Prepare + * - Get ready to accept incoming VM + * - Generate optional cookie to pass to src + * + * Src: Perform + * - Start migration and wait for send completion + * - Kill off VM if successful, resume if failed + * + * Dst: Finish + * - Wait for recv completion and check status + * - Kill off VM if unsuccessful + * + */ static virDomainPtr virDomainMigrateVersion2 (virDomainPtr domain, virConnectPtr dconn, @@ -3441,6 +3476,7 @@ virDomainMigrateVersion2 (virDomainPtr domain, flags |= VIR_MIGRATE_PAUSED; } + VIR_DEBUG("Prepare2 %p", dconn); ret = dconn->driver->domainMigratePrepare2 (dconn, &cookie, &cookielen, uri, &uri_out, flags, dname, bandwidth, dom_xml); @@ -3460,6 +3496,7 @@ virDomainMigrateVersion2 (virDomainPtr domain, /* Perform the migration. The driver isn't supposed to return * until the migration is complete. */ + VIR_DEBUG("Perform %p", domain->conn); ret = domain->conn->driver->domainMigratePerform (domain, cookie, cookielen, uri, flags, dname, bandwidth); @@ -3472,6 +3509,7 @@ virDomainMigrateVersion2 (virDomainPtr domain, * so it can do any cleanup if the migration failed. */ dname = dname ? dname : domain->name; + VIR_DEBUG("Finish2 %p ret=%d", dconn, ret); ddomain = dconn->driver->domainMigrateFinish2 (dconn, dname, cookie, cookielen, uri, flags, ret); @@ -3486,13 +3524,181 @@ virDomainMigrateVersion2 (virDomainPtr domain, } +/* + * Sequence v3: + * + * Src: Begin + * - Generate XML to pass to dst + * - Generate optional cookie to pass to dst + * + * Dst: Prepare + * - Get ready to accept incoming VM + * - Generate optional cookie to pass to src + * + * Src: Perform + * - Start migration and wait for send completion + * - Generate optional cookie to pass to dst + * + * Dst: Finish + * - Wait for recv completion and check status + * - Kill off VM if failed, resume if success + * - Generate optional cookie to pass to src + * + * Src: Confirm + * - Kill off VM if success, resume if failed + * + */ +static virDomainPtr +virDomainMigrateVersion3(virDomainPtr domain, + virConnectPtr dconn, + unsigned long flags, + const char *dname, + const char *uri, + unsigned long bandwidth) +{ + virDomainPtr ddomain = NULL; + char *uri_out = NULL; + char *cookiein = NULL; + char *cookieout = NULL; + char *dom_xml = NULL; + int cookieinlen = 0; + int cookieoutlen = 0; + int ret; + virDomainInfo info; + virErrorPtr orig_err = NULL; + int cancelled; + + if (!domain->conn->driver->domainMigrateBegin3 || + !domain->conn->driver->domainMigratePerform3 || + !domain->conn->driver->domainMigrateConfirm3 || + !dconn->driver->domainMigratePrepare3 || + !dconn->driver->domainMigrateFinish3) { + virLibConnError(VIR_ERR_INTERNAL_ERROR, __FUNCTION__); + virDispatchError(domain->conn); + return NULL; + } + + VIR_DEBUG("Begin3 %p", domain->conn); + dom_xml = domain->conn->driver->domainMigrateBegin3 + (domain, &cookieout, &cookieoutlen, flags, dname, + bandwidth); + if (!dom_xml) + goto done; + + ret = virDomainGetInfo (domain, &info); + if (ret == 0 && info.state == VIR_DOMAIN_PAUSED) { + flags |= VIR_MIGRATE_PAUSED; + } + + VIR_DEBUG("Prepare3 %p", dconn); + cookiein = cookieout; + cookieinlen = cookieoutlen; + cookieout = NULL; + cookieoutlen = 0; + ret = dconn->driver->domainMigratePrepare3 + (dconn, cookiein, cookieinlen, &cookieout, &cookieoutlen, + uri, &uri_out, flags, dname, bandwidth, dom_xml); + VIR_FREE (dom_xml); + if (ret == -1) + goto done; + + if (uri == NULL && uri_out == NULL) { + virLibConnError(VIR_ERR_INTERNAL_ERROR, + _("domainMigratePrepare3 did not set uri")); + virDispatchError(domain->conn); + goto done; + } + if (uri_out) + uri = uri_out; /* Did domainMigratePrepare3 change URI? */ + + /* Perform the migration. The driver isn't supposed to return + * until the migration is complete. The src VM should remain + * running, but in paused state until the destination can + * confirm migration completion. + */ + VIR_DEBUG("Perform3 %p uri=%s", domain->conn, uri); + VIR_FREE(cookiein); + cookiein = cookieout; + cookieinlen = cookieoutlen; + cookieout = NULL; + cookieoutlen = 0; + ret = domain->conn->driver->domainMigratePerform3 + (domain, cookiein, cookieinlen, &cookieout, &cookieoutlen, + uri, flags, dname, bandwidth); + + /* Perform failed. Make sure Finish doesn't overwrite the error */ + if (ret < 0) + orig_err = virSaveLastError(); + + /* If Perform returns < 0, then we need to cancel the VM + * startup on the destination + */ + cancelled = ret < 0 ? 1 : 0; + + /* + * The status code from the source is passed to the destination. + * The dest can cleanup if the source indicated it failed to + * send all migration data. Returns NULL for ddomain if + * the dest was unable to complete migration. + */ + VIR_DEBUG("Finish3 %p ret=%d", dconn, ret); + VIR_FREE(cookiein); + cookiein = cookieout; + cookieinlen = cookieoutlen; + cookieout = NULL; + cookieoutlen = 0; + dname = dname ? dname : domain->name; + ret = dconn->driver->domainMigrateFinish3 + (dconn, dname, cookiein, cookieinlen, &cookieout, &cookieoutlen, + uri, flags, cancelled, &ddomain); + + /* If ret is 0 then 'ddomain' indicates whether the VM is + * running on the dest. If not running, we can restart + * the source. If ret is -1, we can't be sure what happened + * to the VM on the dest, thus the only safe option is to + * kill the VM on the source, even though that may leave + * no VM at all on either host. + */ + cancelled = ret == 0 && ddomain == NULL ? 1 : 0; + + /* + * If cancelled, then src VM will be restarted, else + * it will be killed + */ + VIR_DEBUG("Confirm3 %p ret=%d domain=%p", domain->conn, ret, domain); + VIR_FREE(cookiein); + cookiein = cookieout; + cookieinlen = cookieoutlen; + cookieout = NULL; + cookieoutlen = 0; + ret = domain->conn->driver->domainMigrateConfirm3 + (domain, cookiein, cookieinlen, + flags, cancelled); + /* If Confirm3 returns -1, there's nothing more we can + * do, but fortunately worst case is that there is a + * domain left in 'paused' state on source. + */ + + done: + if (orig_err) { + virSetError(orig_err); + virFreeError(orig_err); + } + VIR_FREE(uri_out); + VIR_FREE(cookiein); + VIR_FREE(cookieout); + return ddomain; +} + + /* - * This is sort of a migration v3 + * In normal migration, the libvirt client co-ordinates communcation + * between the 2 libvirtd instances on source & dest hosts. * - * In this version, the client does not talk to the destination - * libvirtd. The source libvirtd will still try to talk to the - * destination libvirtd though, and will do the prepare/perform/finish - * steps. + * In this peer-2-peer migration alternative, the libvirt client + * only talks to the source libvirtd instance. The source libvirtd + * then opens its own connection to the destination and co-ordinates + * migration itself. */ static int virDomainMigratePeer2Peer (virDomainPtr domain, @@ -3538,14 +3744,15 @@ virDomainMigratePeer2Peer (virDomainPtr domain, /* - * This is a variation on v1 & 2 migration + * In normal migration, the libvirt client co-ordinates communcation + * between the 2 libvirtd instances on source & dest hosts. * - * This is for hypervisors which can directly handshake - * without any libvirtd involvement on destination either - * from client, or source libvirt. + * Some hypervisors support an alternative, direct migration where + * there is no requirement for a libvirtd instance on the dest host. + * In this case * - * eg, XenD can talk direct to XenD, so libvirtd on dest - * does not need to be involved at all, or even running + * eg, XenD can talk direct to XenD, so libvirtd on dest does not + * need to be involved at all, or even running */ static int virDomainMigrateDirect (virDomainPtr domain, @@ -3685,6 +3892,7 @@ virDomainMigrate (virDomainPtr domain, return NULL; } + VIR_DEBUG0("Using peer2peer migration"); if (virDomainMigratePeer2Peer(domain, flags, dname, uri ? uri : dstURI, bandwidth) < 0) { VIR_FREE(dstURI); goto error; @@ -3706,16 +3914,24 @@ virDomainMigrate (virDomainPtr domain, /* Check that migration is supported by both drivers. */ if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn, - VIR_DRV_FEATURE_MIGRATION_V1) && + VIR_DRV_FEATURE_MIGRATION_V3) && VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn, - VIR_DRV_FEATURE_MIGRATION_V1)) - ddomain = virDomainMigrateVersion1(domain, dconn, flags, dname, uri, bandwidth); - else if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn, - VIR_DRV_FEATURE_MIGRATION_V2) && - VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn, - VIR_DRV_FEATURE_MIGRATION_V2)) + VIR_DRV_FEATURE_MIGRATION_V3)) { + VIR_DEBUG0("Using migration protocol 3"); + ddomain = virDomainMigrateVersion3(domain, dconn, flags, dname, uri, bandwidth); + } else if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn, + VIR_DRV_FEATURE_MIGRATION_V2) && + VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn, + VIR_DRV_FEATURE_MIGRATION_V2)) { + VIR_DEBUG0("Using migration protocol 2"); ddomain = virDomainMigrateVersion2(domain, dconn, flags, dname, uri, bandwidth); - else { + } else if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn, + VIR_DRV_FEATURE_MIGRATION_V1) && + VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn, + VIR_DRV_FEATURE_MIGRATION_V1)) { + VIR_DEBUG0("Using migration protocol 1"); + ddomain = virDomainMigrateVersion1(domain, dconn, flags, dname, uri, bandwidth); + } else { /* This driver does not support any migration method */ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); goto error; @@ -4144,6 +4360,330 @@ error: return -1; } +/* + * Not for public use. This function is part of the internal + * implementation of migration in the remote case. + */ +char * +virDomainMigrateBegin3(virDomainPtr domain, + char **cookieout, + int *cookieoutlen, + unsigned long flags, + const char *dname, + unsigned long bandwidth) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "cookieout=%p, cookieoutlen=%p, " + "flags=%lu, dname=%s, bandwidth=%lu", + cookieout, cookieoutlen, flags, + NULLSTR(dname), bandwidth); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN (domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return NULL; + } + conn = domain->conn; + + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainMigrateBegin3) { + char *xml; + xml = conn->driver->domainMigrateBegin3(domain, + cookieout, cookieoutlen, + flags, dname, bandwidth); + VIR_DEBUG("xml %s", NULLSTR(xml)); + if (!xml) + goto error; + return xml; + } + + virLibDomainError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return NULL; +} + + +/* + * Not for public use. This function is part of the internal + * implementation of migration in the remote case. + */ +int +virDomainMigratePrepare3(virConnectPtr dconn, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri_in, + char **uri_out, + unsigned long flags, + const char *dname, + unsigned long bandwidth, + const char *dom_xml) +{ + VIR_DEBUG("dconn=%p, cookiein=%p, cookieinlen=%d, cookieout=%p, cookieoutlen=%p," + "uri_in=%s, uri_out=%p, flags=%lu, dname=%s, bandwidth=%lu, dom_xml=%s", + dconn, cookiein, cookieinlen, cookieout, cookieoutlen, uri_in, uri_out, + flags, NULLSTR(dname), bandwidth, dom_xml); + + virResetLastError(); + + if (!VIR_IS_CONNECT (dconn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (dconn->flags & VIR_CONNECT_RO) { + virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (dconn->driver->domainMigratePrepare3) { + int ret; + ret = dconn->driver->domainMigratePrepare3(dconn, + cookiein, cookieinlen, + cookieout, cookieoutlen, + uri_in, uri_out, + flags, dname, bandwidth, + dom_xml); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(dconn); + return -1; +} + +/* + * Not for public use. This function is part of the internal + * implementation of migration in the remote case. + */ +int +virDomainMigratePrepareTunnel3(virConnectPtr conn, + virStreamPtr st, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + unsigned long flags, + const char *dname, + unsigned long bandwidth, + const char *dom_xml) + +{ + VIR_DEBUG("conn=%p, stream=%p, cookiein=%p, cookieinlen=%d, cookieout=%p," + " cookieoutlen=%p, flags=%lu, dname=%s, bandwidth=%lu, dom_xml=%s", + conn, st, cookiein, cookieinlen, cookieout, cookieoutlen, flags, + NULLSTR(dname), bandwidth, dom_xml); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn != st->conn) { + virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->driver->domainMigratePrepareTunnel3) { + int rv = conn->driver->domainMigratePrepareTunnel3(conn, st, + cookiein, cookieinlen, + cookieout, cookieoutlen, + flags, dname, + bandwidth, dom_xml); + if (rv < 0) + goto error; + return rv; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return -1; +} + + +/* + * Not for public use. This function is part of the internal + * implementation of migration in the remote case. + */ +int +virDomainMigratePerform3(virDomainPtr domain, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri, + unsigned long flags, + const char *dname, + unsigned long bandwidth) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "cookiein=%p, cookieinlen=%d, cookieout=%p, cookieoutlen=%p," + "uri=%s, flags=%lu, dname=%s, bandwidth=%lu", + cookiein, cookieinlen, cookieout, cookieoutlen, + uri, flags, NULLSTR(dname), bandwidth); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN (domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + conn = domain->conn; + + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainMigratePerform3) { + int ret; + ret = conn->driver->domainMigratePerform3(domain, + cookiein, cookieinlen, + cookieout, cookieoutlen, + uri, + flags, dname, bandwidth); + if (ret < 0) + goto error; + return ret; + } + + virLibDomainError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} + + +/* + * Not for public use. This function is part of the internal + * implementation of migration in the remote case. + */ +int +virDomainMigrateFinish3(virConnectPtr dconn, + const char *dname, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri, + unsigned long flags, + int cancelled, + virDomainPtr *newdom) +{ + VIR_DEBUG("dconn=%p, dname=%s, cookiein=%p, cookieinlen=%d, cookieout=%p," + "cookieoutlen=%p, uri=%s, flags=%lu, retcode=%d newdom=%p", + dconn, NULLSTR(dname), cookiein, cookieinlen, cookieout, + cookieoutlen, uri, flags, cancelled, newdom); + + virResetLastError(); + + if (!VIR_IS_CONNECT (dconn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (dconn->flags & VIR_CONNECT_RO) { + virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (dconn->driver->domainMigrateFinish3) { + int ret; + ret = dconn->driver->domainMigrateFinish3(dconn, dname, + cookiein, cookieinlen, + cookieout, cookieoutlen, + uri, flags, + cancelled, + newdom); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(dconn); + return -1; +} + + +/* + * Not for public use. This function is part of the internal + * implementation of migration in the remote case. + */ +int +virDomainMigrateConfirm3(virDomainPtr domain, + const char *cookiein, + int cookieinlen, + unsigned long flags, + int cancelled) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "cookiein=%p, cookieinlen=%d, flags=%lu, cancelled=%d", + cookiein, cookieinlen, flags, cancelled); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN (domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + conn = domain->conn; + + if (domain->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainMigrateConfirm3) { + int ret; + ret = conn->driver->domainMigrateConfirm3(domain, + cookiein, cookieinlen, + flags, cancelled); + if (ret < 0) + goto error; + return ret; + } + + virLibDomainError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} + /** * virNodeGetInfo: diff --git a/src/libvirt_internal.h b/src/libvirt_internal.h index 1c4fa4f..81d0c56 100644 --- a/src/libvirt_internal.h +++ b/src/libvirt_internal.h @@ -66,6 +66,13 @@ enum { * perform step is used. */ VIR_DRV_FEATURE_MIGRATION_DIRECT = 5, + + /* + * Driver supports V3-style virDomainMigrate, ie domainMigrateBegin3/ + * domainMigratePrepare3/domainMigratePerform3/domainMigrateFinish3/ + * domainMigrateConfirm3. + */ + VIR_DRV_FEATURE_MIGRATION_V3 = 6, }; @@ -115,4 +122,63 @@ int virDomainMigratePrepareTunnel(virConnectPtr dconn, unsigned long resource, const char *dom_xml); + +char *virDomainMigrateBegin3(virDomainPtr domain, + char **cookieout, + int *cookieoutlen, + unsigned long flags, + const char *dname, + unsigned long resource); + +int virDomainMigratePrepare3(virConnectPtr dconn, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri_in, + char **uri_out, + unsigned long flags, + const char *dname, + unsigned long resource, + const char *dom_xml); + +int virDomainMigratePrepareTunnel3(virConnectPtr dconn, + virStreamPtr st, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + unsigned long flags, + const char *dname, + unsigned long resource, + const char *dom_xml); + + +int virDomainMigratePerform3(virDomainPtr dom, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri, + unsigned long flags, + const char *dname, + unsigned long resource); + +int virDomainMigrateFinish3(virConnectPtr dconn, + const char *dname, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri, + unsigned long flags, + int cancelled, /* Kill the dst VM */ + virDomainPtr *newdom); + +int virDomainMigrateConfirm3(virDomainPtr domain, + const char *cookiein, + int cookieinlen, + unsigned long flags, + int restart); /* Restart the src VM */ + #endif diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ba7739d..7471e25 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -547,6 +547,12 @@ virDomainMigratePerform; virDomainMigratePrepare2; virDomainMigratePrepare; virDomainMigratePrepareTunnel; +virDomainMigrateBegin3; +virDomainMigratePrepare3; +virDomainMigratePrepareTunnel3; +virDomainMigratePerform3; +virDomainMigrateFinish3; +virDomainMigrateConfirm3; virDrvSupportsFeature; virRegisterDeviceMonitor; virRegisterDriver; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e905302..ea1cbdc 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2906,6 +2906,12 @@ static virDriver lxcDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ lxcDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainMigrateBegin3 */ + NULL, /* domainMigratePrepare3 */ + NULL, /* domainMigratePrepareTunnel3 */ + NULL, /* domainMigratePerform3 */ + NULL, /* domainMigrateFinish3 */ + NULL, /* domainMigrateConfirm3 */ }; static virStateDriver lxcStateDriver = { diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 4af28e9..ca78dc2 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1667,6 +1667,12 @@ static virDriver openvzDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainMigrateBegin3 */ + NULL, /* domainMigratePrepare3 */ + NULL, /* domainMigratePrepareTunnel3 */ + NULL, /* domainMigratePerform3 */ + NULL, /* domainMigrateFinish3 */ + NULL, /* domainMigrateConfirm3 */ }; int openvzRegister(void) { diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index ebd4a8a..03554df 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -3828,6 +3828,12 @@ static virDriver phypDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainMigrateBegin3 */ + NULL, /* domainMigratePrepare3 */ + NULL, /* domainMigratePrepareTunnel3 */ + NULL, /* domainMigratePerform3 */ + NULL, /* domainMigrateFinish3 */ + NULL, /* domainMigrateConfirm3 */ }; static virStorageDriver phypStorageDriver = { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f6e503a..e6c7599 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7031,6 +7031,12 @@ static virDriver qemuDriver = { qemuDomainSnapshotDelete, /* domainSnapshotDelete */ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ qemuDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainMigrateBegin3 */ + NULL, /* domainMigratePrepare3 */ + NULL, /* domainMigratePrepareTunnel3 */ + NULL, /* domainMigratePerform3 */ + NULL, /* domainMigrateFinish3 */ + NULL, /* domainMigrateConfirm3 */ }; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index e30780c..0d7c144 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -11298,6 +11298,12 @@ static virDriver remote_driver = { remoteDomainSnapshotDelete, /* domainSnapshotDelete */ remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ remoteDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainMigrateBegin3 */ + NULL, /* domainMigratePrepare3 */ + NULL, /* domainMigratePrepareTunnel3 */ + NULL, /* domainMigratePerform3 */ + NULL, /* domainMigrateFinish3 */ + NULL, /* domainMigrateConfirm3 */ }; static virNetworkDriver network_driver = { diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 0978214..bfa4578 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5447,6 +5447,12 @@ static virDriver testDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainMigrateBegin3 */ + NULL, /* domainMigratePrepare3 */ + NULL, /* domainMigratePrepareTunnel3 */ + NULL, /* domainMigratePerform3 */ + NULL, /* domainMigrateFinish3 */ + NULL, /* domainMigrateConfirm3 */ }; static virNetworkDriver testNetworkDriver = { diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 33849a0..12587b7 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2253,6 +2253,12 @@ static virDriver umlDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ umlDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainMigrateBegin3 */ + NULL, /* domainMigratePrepare3 */ + NULL, /* domainMigratePrepareTunnel3 */ + NULL, /* domainMigratePerform3 */ + NULL, /* domainMigrateFinish3 */ + NULL, /* domainMigrateConfirm3 */ }; static int diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 8241d34..f203d81 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8652,6 +8652,12 @@ virDriver NAME(Driver) = { vboxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainMigrateBegin3 */ + NULL, /* domainMigratePrepare3 */ + NULL, /* domainMigratePrepareTunnel3 */ + NULL, /* domainMigratePerform3 */ + NULL, /* domainMigrateFinish3 */ + NULL, /* domainMigrateConfirm3 */ }; virNetworkDriver NAME(NetworkDriver) = { diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index bbfb1a4..16c5205 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -1007,6 +1007,12 @@ static virDriver vmwareDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainMigrateBegin3 */ + NULL, /* domainMigratePrepare3 */ + NULL, /* domainMigratePrepareTunnel3 */ + NULL, /* domainMigratePerform3 */ + NULL, /* domainMigrateFinish3 */ + NULL, /* domainMigrateConfirm3 */ }; int diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 2a07b7b..bdaa504 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2141,6 +2141,12 @@ static virDriver xenUnifiedDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ xenUnifiedDomainOpenConsole, /* domainOpenConsole */ + NULL, /* domainMigrateBegin3 */ + NULL, /* domainMigratePrepare3 */ + NULL, /* domainMigratePrepareTunnel3 */ + NULL, /* domainMigratePerform3 */ + NULL, /* domainMigrateFinish3 */ + NULL, /* domainMigrateConfirm3 */ }; /** diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 3fbdcc6..05e9c7b 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1889,6 +1889,12 @@ static virDriver xenapiDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ NULL, /* domainOpenConsole */ + NULL, /* domainMigrateBegin3 */ + NULL, /* domainMigratePrepare3 */ + NULL, /* domainMigratePrepareTunnel3 */ + NULL, /* domainMigratePerform3 */ + NULL, /* domainMigrateFinish3 */ + NULL, /* domainMigrateConfirm3 */ }; /** -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:42 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:42 +0100 Subject: [libvirt] [PATCH 03/16] Remote driver implementation of new migration API In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-4-git-send-email-berrange@redhat.com> * src/remote/remote_protocol.x: Define wire protocol for migration protocol v3 * daemon/remote.c: Server side dispatch * src/remote/remote_driver.c: Client side serialization * src/remote/remote_protocol.c, src/remote/remote_protocol.h, daemon/remote_dispatch_args.h, daemon/remote_dispatch_prototypes.h, daemon/remote_dispatch_ret.h, daemon/remote_dispatch_table.h: Re-generate files * src/remote_protocol-structs: Declare new ABIs --- daemon/remote.c | 315 +++++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 6 + daemon/remote_dispatch_prototypes.h | 48 +++++ daemon/remote_dispatch_ret.h | 5 + daemon/remote_dispatch_table.h | 30 +++ src/remote/remote_driver.c | 371 ++++++++++++++++++++++++++++++++++- src/remote/remote_protocol.c | 163 +++++++++++++++ src/remote/remote_protocol.h | 140 +++++++++++++ src/remote/remote_protocol.x | 79 ++++++++- src/remote_protocol-structs | 90 +++++++++ 10 files changed, 1240 insertions(+), 7 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 54fef64..98de0a7 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -76,6 +76,7 @@ static virStorageVolPtr get_nonnull_storage_vol(virConnectPtr conn, remote_nonnu static virSecretPtr get_nonnull_secret(virConnectPtr conn, remote_nonnull_secret secret); static virNWFilterPtr get_nonnull_nwfilter(virConnectPtr conn, remote_nonnull_nwfilter nwfilter); static virDomainSnapshotPtr get_nonnull_domain_snapshot(virDomainPtr dom, remote_nonnull_domain_snapshot snapshot); +static int make_domain(remote_domain *dom_dst, virDomainPtr dom_src); static void make_nonnull_domain(remote_nonnull_domain *dom_dst, virDomainPtr dom_src); static void make_nonnull_network(remote_nonnull_network *net_dst, virNetworkPtr net_src); static void make_nonnull_interface(remote_nonnull_interface *interface_dst, virInterfacePtr interface_src); @@ -8736,6 +8737,305 @@ cleanup: } +static int +remoteDispatchDomainMigrateBegin3(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_migrate_begin3_args *args, + remote_domain_migrate_begin3_ret *ret) +{ + char *xml = NULL; + virDomainPtr dom = NULL; + char *dname; + char *cookieout = NULL; + int cookieoutlen = 0; + int rv = -1; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + dname = args->dname == NULL ? NULL : *args->dname; + + if (!(xml = virDomainMigrateBegin3(dom, + &cookieout, &cookieoutlen, + args->flags, dname, args->resource))) + goto cleanup; + + /* remoteDispatchClientRequest will free cookie and + * the xml string if there is one. + */ + ret->cookie_out.cookie_out_len = cookieoutlen; + ret->cookie_out.cookie_out_val = cookieout; + ret->xml = xml; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + + +static int +remoteDispatchDomainMigratePrepare3(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_migrate_prepare3_args *args, + remote_domain_migrate_prepare3_ret *ret) +{ + char *cookieout = NULL; + int cookieoutlen = 0; + char *uri_in; + char **uri_out; + char *dname; + int rv = -1; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + uri_in = args->uri_in == NULL ? NULL : *args->uri_in; + dname = args->dname == NULL ? NULL : *args->dname; + + /* Wacky world of XDR ... */ + if (VIR_ALLOC(uri_out) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virDomainMigratePrepare3(conn, + args->cookie_in.cookie_in_val, + args->cookie_in.cookie_in_len, + &cookieout, &cookieoutlen, + uri_in, uri_out, + args->flags, dname, args->resource, + args->dom_xml) < 0) + goto cleanup; + + /* remoteDispatchClientRequest will free cookie, uri_out and + * the string if there is one. + */ + ret->cookie_out.cookie_out_len = cookieoutlen; + ret->cookie_out.cookie_out_val = cookieout; + ret->uri_out = *uri_out == NULL ? NULL : uri_out; + + rv = 0; + +cleanup: + if (rv < 0) { + remoteDispatchError(rerr); + VIR_FREE(uri_out); + } + return rv; +} + +static int +remoteDispatchDomainMigratePrepareTunnel3(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *rerr, + remote_domain_migrate_prepare_tunnel3_args *args, + remote_domain_migrate_prepare_tunnel3_ret *ret) +{ + char *dname; + char *cookieout = NULL; + int cookieoutlen = 0; + struct qemud_client_stream *stream = NULL; + int rv = -1; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + dname = args->dname == NULL ? NULL : *args->dname; + + if (!(stream = remoteCreateClientStream(conn, hdr))) { + virReportOOMError(); + goto cleanup; + } + + if (virDomainMigratePrepareTunnel3(conn, stream->st, + args->cookie_in.cookie_in_val, + args->cookie_in.cookie_in_len, + &cookieout, &cookieoutlen, + args->flags, dname, args->resource, + args->dom_xml) < 0) + goto cleanup; + + if (remoteAddClientStream(client, stream, 0) < 0) + goto cleanup; + + /* remoteDispatchClientRequest will free cookie + */ + ret->cookie_out.cookie_out_len = cookieoutlen; + ret->cookie_out.cookie_out_val = cookieout; + + rv = 0; + +cleanup: + if (rv < 0) { + remoteDispatchError(rerr); + VIR_FREE(cookieout); + } + if (stream && rv < 0) { + virStreamAbort(stream->st); + remoteFreeClientStream(client, stream); + } + return rv; +} + +static int +remoteDispatchDomainMigratePerform3(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_migrate_perform3_args *args, + remote_domain_migrate_perform3_ret *ret) +{ + virDomainPtr dom = NULL; + char *dname; + char *cookieout = NULL; + int cookieoutlen = 0; + int rv = -1; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + dname = args->dname == NULL ? NULL : *args->dname; + + if (virDomainMigratePerform3(dom, + args->cookie_in.cookie_in_val, + args->cookie_in.cookie_in_len, + &cookieout, &cookieoutlen, + args->uri, + args->flags, dname, args->resource) < 0) + goto cleanup; + + /* remoteDispatchClientRequest will free cookie + */ + ret->cookie_out.cookie_out_len = cookieoutlen; + ret->cookie_out.cookie_out_val = cookieout; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + + +static int +remoteDispatchDomainMigrateFinish3(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_migrate_finish3_args *args, + remote_domain_migrate_finish3_ret *ret) +{ + virDomainPtr dom = NULL; + char *cookieout = NULL; + int cookieoutlen = 0; + int rv = -1; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (virDomainMigrateFinish3(conn, args->dname, + args->cookie_in.cookie_in_val, + args->cookie_in.cookie_in_len, + &cookieout, &cookieoutlen, + args->uri, + args->flags, + args->cancelled, + &dom) < 0) + goto cleanup; + + if (dom && + make_domain(&ret->ddom, dom) < 0) + goto cleanup; + + /* remoteDispatchClientRequest will free cookie + */ + ret->cookie_out.cookie_out_len = cookieoutlen; + ret->cookie_out.cookie_out_val = cookieout; + + rv = 0; + +cleanup: + if (rv < 0) { + remoteDispatchError(rerr); + VIR_FREE(cookieout); + } + if (dom) + virDomainFree(dom); + return rv; +} + + +static int +remoteDispatchDomainMigrateConfirm3(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_migrate_confirm3_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virDomainPtr dom = NULL; + int rv = -1; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainMigrateConfirm3(dom, + args->cookie_in.cookie_in_val, + args->cookie_in.cookie_in_len, + args->flags, args->cancelled) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + + /*----- Helpers. -----*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire @@ -8801,6 +9101,21 @@ get_nonnull_domain_snapshot(virDomainPtr dom, remote_nonnull_domain_snapshot sna } /* Make remote_nonnull_domain and remote_nonnull_network. */ +static int +make_domain(remote_domain *dom_dst, virDomainPtr dom_src) +{ + remote_domain rdom; + if (VIR_ALLOC(rdom) < 0) + return -1; + + rdom->id = dom_src->id; + rdom->name = strdup(dom_src->name); + memcpy(rdom->uuid, dom_src->uuid, VIR_UUID_BUFLEN); + + *dom_dst = rdom; + return 0; +} + static void make_nonnull_domain(remote_nonnull_domain *dom_dst, virDomainPtr dom_src) { diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index f9537d7..07c666e 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -178,3 +178,9 @@ remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; remote_storage_vol_upload_args val_remote_storage_vol_upload_args; remote_storage_vol_download_args val_remote_storage_vol_download_args; + remote_domain_migrate_begin3_args val_remote_domain_migrate_begin3_args; + remote_domain_migrate_prepare3_args val_remote_domain_migrate_prepare3_args; + remote_domain_migrate_prepare_tunnel3_args val_remote_domain_migrate_prepare_tunnel3_args; + remote_domain_migrate_perform3_args val_remote_domain_migrate_perform3_args; + remote_domain_migrate_finish3_args val_remote_domain_migrate_finish3_args; + remote_domain_migrate_confirm3_args val_remote_domain_migrate_confirm3_args; diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 18bf41d..3dceb74 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -426,6 +426,22 @@ static int remoteDispatchDomainMemoryStats( remote_error *err, remote_domain_memory_stats_args *args, remote_domain_memory_stats_ret *ret); +static int remoteDispatchDomainMigrateBegin3( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_migrate_begin3_args *args, + remote_domain_migrate_begin3_ret *ret); +static int remoteDispatchDomainMigrateConfirm3( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_migrate_confirm3_args *args, + void *ret); static int remoteDispatchDomainMigrateFinish( struct qemud_server *server, struct qemud_client *client, @@ -442,6 +458,14 @@ static int remoteDispatchDomainMigrateFinish2( remote_error *err, remote_domain_migrate_finish2_args *args, remote_domain_migrate_finish2_ret *ret); +static int remoteDispatchDomainMigrateFinish3( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_migrate_finish3_args *args, + remote_domain_migrate_finish3_ret *ret); static int remoteDispatchDomainMigratePerform( struct qemud_server *server, struct qemud_client *client, @@ -450,6 +474,14 @@ static int remoteDispatchDomainMigratePerform( remote_error *err, remote_domain_migrate_perform_args *args, void *ret); +static int remoteDispatchDomainMigratePerform3( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_migrate_perform3_args *args, + remote_domain_migrate_perform3_ret *ret); static int remoteDispatchDomainMigratePrepare( struct qemud_server *server, struct qemud_client *client, @@ -466,6 +498,14 @@ static int remoteDispatchDomainMigratePrepare2( remote_error *err, remote_domain_migrate_prepare2_args *args, remote_domain_migrate_prepare2_ret *ret); +static int remoteDispatchDomainMigratePrepare3( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_migrate_prepare3_args *args, + remote_domain_migrate_prepare3_ret *ret); static int remoteDispatchDomainMigratePrepareTunnel( struct qemud_server *server, struct qemud_client *client, @@ -474,6 +514,14 @@ static int remoteDispatchDomainMigratePrepareTunnel( remote_error *err, remote_domain_migrate_prepare_tunnel_args *args, void *ret); +static int remoteDispatchDomainMigratePrepareTunnel3( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_migrate_prepare_tunnel3_args *args, + remote_domain_migrate_prepare_tunnel3_ret *ret); static int remoteDispatchDomainMigrateSetMaxDowntime( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_ret.h b/daemon/remote_dispatch_ret.h index 114e832..6e5049a 100644 --- a/daemon/remote_dispatch_ret.h +++ b/daemon/remote_dispatch_ret.h @@ -140,3 +140,8 @@ remote_domain_is_updated_ret val_remote_domain_is_updated_ret; remote_get_sysinfo_ret val_remote_get_sysinfo_ret; remote_domain_get_blkio_parameters_ret val_remote_domain_get_blkio_parameters_ret; + remote_domain_migrate_begin3_ret val_remote_domain_migrate_begin3_ret; + remote_domain_migrate_prepare3_ret val_remote_domain_migrate_prepare3_ret; + remote_domain_migrate_prepare_tunnel3_ret val_remote_domain_migrate_prepare_tunnel3_ret; + remote_domain_migrate_perform3_ret val_remote_domain_migrate_perform3_ret; + remote_domain_migrate_finish3_ret val_remote_domain_migrate_finish3_ret; diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index b39f7c2..a76eccb 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1052,3 +1052,33 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* DomainMigrateBegin3 => 210 */ + .fn = (dispatch_fn) remoteDispatchDomainMigrateBegin3, + .args_filter = (xdrproc_t) xdr_remote_domain_migrate_begin3_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_migrate_begin3_ret, +}, +{ /* DomainMigratePrepare3 => 211 */ + .fn = (dispatch_fn) remoteDispatchDomainMigratePrepare3, + .args_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare3_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare3_ret, +}, +{ /* DomainMigratePrepareTunnel3 => 212 */ + .fn = (dispatch_fn) remoteDispatchDomainMigratePrepareTunnel3, + .args_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel3_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel3_ret, +}, +{ /* DomainMigratePerform3 => 213 */ + .fn = (dispatch_fn) remoteDispatchDomainMigratePerform3, + .args_filter = (xdrproc_t) xdr_remote_domain_migrate_perform3_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_migrate_perform3_ret, +}, +{ /* DomainMigrateFinish3 => 214 */ + .fn = (dispatch_fn) remoteDispatchDomainMigrateFinish3, + .args_filter = (xdrproc_t) xdr_remote_domain_migrate_finish3_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_migrate_finish3_ret, +}, +{ /* DomainMigrateConfirm3 => 215 */ + .fn = (dispatch_fn) remoteDispatchDomainMigrateConfirm3, + .args_filter = (xdrproc_t) xdr_remote_domain_migrate_confirm3_args, + .ret_filter = (xdrproc_t) xdr_void, +}, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 0d7c144..bed6a15 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -245,6 +245,7 @@ static int remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int virReportErrorHelper(VIR_FROM_REMOTE, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) +static virDomainPtr get_domain (virConnectPtr conn, remote_domain domain); static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain); static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network); static virNWFilterPtr get_nonnull_nwfilter (virConnectPtr conn, remote_nonnull_nwfilter nwfilter); @@ -3480,6 +3481,7 @@ error: goto done; } + static virDomainPtr remoteDomainMigrateFinish2 (virConnectPtr dconn, const char *dname, @@ -3517,6 +3519,7 @@ done: return ddom; } + static int remoteListDefinedDomains (virConnectPtr conn, char **const names, int maxnames) { @@ -9770,6 +9773,346 @@ done: return rv; } + +static char * +remoteDomainMigrateBegin3(virDomainPtr domain, + char **cookieout, + int *cookieoutlen, + unsigned long flags, + const char *dname, + unsigned long resource) +{ + char *rv = NULL; + remote_domain_migrate_begin3_args args; + remote_domain_migrate_begin3_ret ret; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + memset(&args, 0, sizeof(args)); + memset(&ret, 0, sizeof(ret)); + + make_nonnull_domain (&args.dom, domain); + args.flags = flags; + args.dname = dname == NULL ? NULL : (char **) &dname; + args.resource = resource; + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_BEGIN3, + (xdrproc_t) xdr_remote_domain_migrate_begin3_args, (char *) &args, + (xdrproc_t) xdr_remote_domain_migrate_begin3_ret, (char *) &ret) == -1) + goto done; + + if (ret.cookie_out.cookie_out_len > 0) { + if (!cookieout || !cookieoutlen) { + remoteError(VIR_ERR_INTERNAL_ERROR, "%s", + _("caller ignores cookieout or cookieoutlen")); + goto error; + } + *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */ + *cookieoutlen = ret.cookie_out.cookie_out_len; + } + + rv = ret.xml; /* caller frees */ + +done: + remoteDriverUnlock(priv); + return rv; + +error: + VIR_FREE(ret.cookie_out.cookie_out_val); + goto done; +} + + +static int +remoteDomainMigratePrepare3(virConnectPtr dconn, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri_in, + char **uri_out, + unsigned long flags, + const char *dname, + unsigned long resource, + const char *dom_xml) +{ + int rv = -1; + remote_domain_migrate_prepare3_args args; + remote_domain_migrate_prepare3_ret ret; + struct private_data *priv = dconn->privateData; + + remoteDriverLock(priv); + + memset(&args, 0, sizeof(args)); + memset(&ret, 0, sizeof(ret)); + + args.cookie_in.cookie_in_val = (char *)cookiein; + args.cookie_in.cookie_in_len = cookieinlen; + args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in; + args.flags = flags; + args.dname = dname == NULL ? NULL : (char **) &dname; + args.resource = resource; + args.dom_xml = (char *) dom_xml; + + memset (&ret, 0, sizeof ret); + if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE3, + (xdrproc_t) xdr_remote_domain_migrate_prepare3_args, (char *) &args, + (xdrproc_t) xdr_remote_domain_migrate_prepare3_ret, (char *) &ret) == -1) + goto done; + + if (ret.cookie_out.cookie_out_len > 0) { + if (!cookieout || !cookieoutlen) { + remoteError(VIR_ERR_INTERNAL_ERROR, "%s", + _("caller ignores cookieout or cookieoutlen")); + goto error; + } + *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */ + *cookieoutlen = ret.cookie_out.cookie_out_len; + } + if (ret.uri_out) { + if (!uri_out) { + remoteError(VIR_ERR_INTERNAL_ERROR, "%s", + _("caller ignores uri_out")); + goto error; + } + *uri_out = *ret.uri_out; /* Caller frees. */ + } + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +error: + VIR_FREE(ret.cookie_out.cookie_out_val); + if (ret.uri_out) + VIR_FREE(*ret.uri_out); + goto done; +} + + +static int +remoteDomainMigratePrepareTunnel3(virConnectPtr dconn, + virStreamPtr st, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + unsigned long flags, + const char *dname, + unsigned long resource, + const char *dom_xml) +{ + struct private_data *priv = dconn->privateData; + struct private_stream_data *privst = NULL; + int rv = -1; + remote_domain_migrate_prepare_tunnel3_args args; + remote_domain_migrate_prepare_tunnel3_ret ret; + + remoteDriverLock(priv); + + memset(&args, 0, sizeof(args)); + memset(&ret, 0, sizeof(ret)); + + if (!(privst = remoteStreamOpen(st, + REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3, + priv->counter))) + goto done; + + st->driver = &remoteStreamDrv; + st->privateData = privst; + + args.cookie_in.cookie_in_val = (char *)cookiein; + args.cookie_in.cookie_in_len = cookieinlen; + args.flags = flags; + args.dname = dname == NULL ? NULL : (char **) &dname; + args.resource = resource; + args.dom_xml = (char *) dom_xml; + + if (call(dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3, + (xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel3_args, (char *) &args, + (xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel3_ret, (char *) &ret) == -1) { + remoteStreamRelease(st); + goto done; + } + + if (ret.cookie_out.cookie_out_len > 0) { + if (!cookieout || !cookieoutlen) { + remoteError(VIR_ERR_INTERNAL_ERROR, "%s", + _("caller ignores cookieout or cookieoutlen")); + goto error; + } + *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */ + *cookieoutlen = ret.cookie_out.cookie_out_len; + } + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; + +error: + VIR_FREE(ret.cookie_out.cookie_out_val); + goto done; +} + + +static int +remoteDomainMigratePerform3(virDomainPtr dom, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri, + unsigned long flags, + const char *dname, + unsigned long resource) +{ + int rv = -1; + remote_domain_migrate_perform3_args args; + remote_domain_migrate_perform3_ret ret; + struct private_data *priv = dom->conn->privateData; + + remoteDriverLock(priv); + + memset(&args, 0, sizeof(args)); + memset(&ret, 0, sizeof(ret)); + + make_nonnull_domain(&args.dom, dom); + + args.cookie_in.cookie_in_val = (char *)cookiein; + args.cookie_in.cookie_in_len = cookieinlen; + args.uri = (char *) uri; + args.flags = flags; + args.dname = dname == NULL ? NULL : (char **) &dname; + args.resource = resource; + + if (call (dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PERFORM3, + (xdrproc_t) xdr_remote_domain_migrate_perform3_args, (char *) &args, + (xdrproc_t) xdr_remote_domain_migrate_perform3_ret, (char *) &ret) == -1) + goto done; + + if (ret.cookie_out.cookie_out_len > 0) { + if (!cookieout || !cookieoutlen) { + remoteError(VIR_ERR_INTERNAL_ERROR, "%s", + _("caller ignores cookieout or cookieoutlen")); + goto error; + } + *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */ + *cookieoutlen = ret.cookie_out.cookie_out_len; + } + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; + +error: + VIR_FREE(ret.cookie_out.cookie_out_val); + goto done; +} + + +static int +remoteDomainMigrateFinish3(virConnectPtr dconn, + const char *dname, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri, + unsigned long flags, + int cancelled, + virDomainPtr *ddom) +{ + remote_domain_migrate_finish3_args args; + remote_domain_migrate_finish3_ret ret; + struct private_data *priv = dconn->privateData; + int rv = -1; + + remoteDriverLock(priv); + + *ddom = NULL; + memset(&args, 0, sizeof(args)); + memset(&ret, 0, sizeof(ret)); + + args.cookie_in.cookie_in_val = (char *)cookiein; + args.cookie_in.cookie_in_len = cookieinlen; + args.dname = (char *) dname; + args.uri = (char *) uri; + args.flags = flags; + args.cancelled = cancelled; + + if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH3, + (xdrproc_t) xdr_remote_domain_migrate_finish3_args, (char *) &args, + (xdrproc_t) xdr_remote_domain_migrate_finish3_ret, (char *) &ret) == -1) + goto done; + + *ddom = get_domain(dconn, ret.ddom); + + if (ret.cookie_out.cookie_out_len > 0) { + if (!cookieout || !cookieoutlen) { + remoteError(VIR_ERR_INTERNAL_ERROR, "%s", + _("caller ignores cookieout or cookieoutlen")); + goto error; + } + *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */ + *cookieoutlen = ret.cookie_out.cookie_out_len; + ret.cookie_out.cookie_out_val = NULL; + ret.cookie_out.cookie_out_len = 0; + } + + xdr_free ((xdrproc_t) &xdr_remote_domain_migrate_finish3_ret, (char *) &ret); + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; + +error: + VIR_FREE(ret.cookie_out.cookie_out_val); + goto done; +} + + +static int +remoteDomainMigrateConfirm3(virDomainPtr domain, + const char *cookiein, + int cookieinlen, + unsigned long flags, + int cancelled) +{ + int rv = -1; + remote_domain_migrate_confirm3_args args; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + memset(&args, 0, sizeof(args)); + + make_nonnull_domain (&args.dom, domain); + args.cookie_in.cookie_in_len = cookieinlen; + args.cookie_in.cookie_in_val = (char *) cookiein; + args.flags = flags; + args.cancelled = cancelled; + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3, + (xdrproc_t) xdr_remote_domain_migrate_confirm3_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + + /*----------------------------------------------------------------------*/ static struct remote_thread_call * @@ -11062,6 +11405,22 @@ remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque) * but if they do then virterror_internal.has been set. */ static virDomainPtr +get_domain (virConnectPtr conn, remote_domain domain) +{ + virDomainPtr dom = NULL; + if (domain) { + dom = virGetDomain (conn, domain->name, BAD_CAST domain->uuid); + if (dom) dom->id = domain->id; + } + return dom; +} + +/* get_nonnull_domain and get_nonnull_network turn an on-wire + * (name, uuid) pair into virDomainPtr or virNetworkPtr object. + * These can return NULL if underlying memory allocations fail, + * but if they do then virterror_internal.has been set. + */ +static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain) { virDomainPtr dom; @@ -11298,12 +11657,12 @@ static virDriver remote_driver = { remoteDomainSnapshotDelete, /* domainSnapshotDelete */ remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ remoteDomainOpenConsole, /* domainOpenConsole */ - NULL, /* domainMigrateBegin3 */ - NULL, /* domainMigratePrepare3 */ - NULL, /* domainMigratePrepareTunnel3 */ - NULL, /* domainMigratePerform3 */ - NULL, /* domainMigrateFinish3 */ - NULL, /* domainMigrateConfirm3 */ + remoteDomainMigrateBegin3, /* domainMigrateBegin3 */ + remoteDomainMigratePrepare3, /* domainMigratePrepare3 */ + remoteDomainMigratePrepareTunnel3, /* domainMigratePrepareTunnel3 */ + remoteDomainMigratePerform3, /* domainMigratePerform3 */ + remoteDomainMigrateFinish3, /* domainMigrateFinish3 */ + remoteDomainMigrateConfirm3, /* domainMigrateConfirm3 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 5604371..21f7e47 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -3902,6 +3902,169 @@ xdr_remote_storage_vol_download_args (XDR *xdrs, remote_storage_vol_download_arg } bool_t +xdr_remote_domain_migrate_begin3_args (XDR *xdrs, remote_domain_migrate_begin3_args *objp) +{ + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->flags)) + return FALSE; + if (!xdr_remote_string (xdrs, &objp->dname)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->resource)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_migrate_begin3_ret (XDR *xdrs, remote_domain_migrate_begin3_ret *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->cookie_out.cookie_out_val; + + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cookie_out.cookie_out_len, REMOTE_MIGRATE_COOKIE_MAX)) + return FALSE; + if (!xdr_remote_nonnull_string (xdrs, &objp->xml)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_migrate_prepare3_args (XDR *xdrs, remote_domain_migrate_prepare3_args *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->cookie_in.cookie_in_val; + + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cookie_in.cookie_in_len, REMOTE_MIGRATE_COOKIE_MAX)) + return FALSE; + if (!xdr_remote_string (xdrs, &objp->uri_in)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->flags)) + return FALSE; + if (!xdr_remote_string (xdrs, &objp->dname)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->resource)) + return FALSE; + if (!xdr_remote_nonnull_string (xdrs, &objp->dom_xml)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_migrate_prepare3_ret (XDR *xdrs, remote_domain_migrate_prepare3_ret *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->cookie_out.cookie_out_val; + + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cookie_out.cookie_out_len, REMOTE_MIGRATE_COOKIE_MAX)) + return FALSE; + if (!xdr_remote_string (xdrs, &objp->uri_out)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_migrate_prepare_tunnel3_args (XDR *xdrs, remote_domain_migrate_prepare_tunnel3_args *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->cookie_in.cookie_in_val; + + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cookie_in.cookie_in_len, REMOTE_MIGRATE_COOKIE_MAX)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->flags)) + return FALSE; + if (!xdr_remote_string (xdrs, &objp->dname)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->resource)) + return FALSE; + if (!xdr_remote_nonnull_string (xdrs, &objp->dom_xml)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_migrate_prepare_tunnel3_ret (XDR *xdrs, remote_domain_migrate_prepare_tunnel3_ret *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->cookie_out.cookie_out_val; + + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cookie_out.cookie_out_len, REMOTE_MIGRATE_COOKIE_MAX)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_migrate_perform3_args (XDR *xdrs, remote_domain_migrate_perform3_args *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->cookie_in.cookie_in_val; + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cookie_in.cookie_in_len, REMOTE_MIGRATE_COOKIE_MAX)) + return FALSE; + if (!xdr_remote_nonnull_string (xdrs, &objp->uri)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->flags)) + return FALSE; + if (!xdr_remote_string (xdrs, &objp->dname)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->resource)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_migrate_perform3_ret (XDR *xdrs, remote_domain_migrate_perform3_ret *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->cookie_out.cookie_out_val; + + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cookie_out.cookie_out_len, REMOTE_MIGRATE_COOKIE_MAX)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_migrate_finish3_args (XDR *xdrs, remote_domain_migrate_finish3_args *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->cookie_in.cookie_in_val; + + if (!xdr_remote_nonnull_string (xdrs, &objp->dname)) + return FALSE; + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cookie_in.cookie_in_len, REMOTE_MIGRATE_COOKIE_MAX)) + return FALSE; + if (!xdr_remote_nonnull_string (xdrs, &objp->uri)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->flags)) + return FALSE; + if (!xdr_int (xdrs, &objp->cancelled)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_migrate_finish3_ret (XDR *xdrs, remote_domain_migrate_finish3_ret *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->cookie_out.cookie_out_val; + + if (!xdr_remote_domain (xdrs, &objp->ddom)) + return FALSE; + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cookie_out.cookie_out_len, REMOTE_MIGRATE_COOKIE_MAX)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_domain_migrate_confirm3_args (XDR *xdrs, remote_domain_migrate_confirm3_args *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->cookie_in.cookie_in_val; + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cookie_in.cookie_in_len, REMOTE_MIGRATE_COOKIE_MAX)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->flags)) + return FALSE; + if (!xdr_int (xdrs, &objp->cancelled)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_procedure (XDR *xdrs, remote_procedure *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index d9bf151..385d431 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -2200,6 +2200,118 @@ struct remote_storage_vol_download_args { u_int flags; }; typedef struct remote_storage_vol_download_args remote_storage_vol_download_args; + +struct remote_domain_migrate_begin3_args { + remote_nonnull_domain dom; + uint64_t flags; + remote_string dname; + uint64_t resource; +}; +typedef struct remote_domain_migrate_begin3_args remote_domain_migrate_begin3_args; + +struct remote_domain_migrate_begin3_ret { + struct { + u_int cookie_out_len; + char *cookie_out_val; + } cookie_out; + remote_nonnull_string xml; +}; +typedef struct remote_domain_migrate_begin3_ret remote_domain_migrate_begin3_ret; + +struct remote_domain_migrate_prepare3_args { + struct { + u_int cookie_in_len; + char *cookie_in_val; + } cookie_in; + remote_string uri_in; + uint64_t flags; + remote_string dname; + uint64_t resource; + remote_nonnull_string dom_xml; +}; +typedef struct remote_domain_migrate_prepare3_args remote_domain_migrate_prepare3_args; + +struct remote_domain_migrate_prepare3_ret { + struct { + u_int cookie_out_len; + char *cookie_out_val; + } cookie_out; + remote_string uri_out; +}; +typedef struct remote_domain_migrate_prepare3_ret remote_domain_migrate_prepare3_ret; + +struct remote_domain_migrate_prepare_tunnel3_args { + struct { + u_int cookie_in_len; + char *cookie_in_val; + } cookie_in; + uint64_t flags; + remote_string dname; + uint64_t resource; + remote_nonnull_string dom_xml; +}; +typedef struct remote_domain_migrate_prepare_tunnel3_args remote_domain_migrate_prepare_tunnel3_args; + +struct remote_domain_migrate_prepare_tunnel3_ret { + struct { + u_int cookie_out_len; + char *cookie_out_val; + } cookie_out; +}; +typedef struct remote_domain_migrate_prepare_tunnel3_ret remote_domain_migrate_prepare_tunnel3_ret; + +struct remote_domain_migrate_perform3_args { + remote_nonnull_domain dom; + struct { + u_int cookie_in_len; + char *cookie_in_val; + } cookie_in; + remote_nonnull_string uri; + uint64_t flags; + remote_string dname; + uint64_t resource; +}; +typedef struct remote_domain_migrate_perform3_args remote_domain_migrate_perform3_args; + +struct remote_domain_migrate_perform3_ret { + struct { + u_int cookie_out_len; + char *cookie_out_val; + } cookie_out; +}; +typedef struct remote_domain_migrate_perform3_ret remote_domain_migrate_perform3_ret; + +struct remote_domain_migrate_finish3_args { + remote_nonnull_string dname; + struct { + u_int cookie_in_len; + char *cookie_in_val; + } cookie_in; + remote_nonnull_string uri; + uint64_t flags; + int cancelled; +}; +typedef struct remote_domain_migrate_finish3_args remote_domain_migrate_finish3_args; + +struct remote_domain_migrate_finish3_ret { + remote_domain ddom; + struct { + u_int cookie_out_len; + char *cookie_out_val; + } cookie_out; +}; +typedef struct remote_domain_migrate_finish3_ret remote_domain_migrate_finish3_ret; + +struct remote_domain_migrate_confirm3_args { + remote_nonnull_domain dom; + struct { + u_int cookie_in_len; + char *cookie_in_val; + } cookie_in; + uint64_t flags; + int cancelled; +}; +typedef struct remote_domain_migrate_confirm3_args remote_domain_migrate_confirm3_args; #define REMOTE_PROGRAM 0x20008086 #define REMOTE_PROTOCOL_VERSION 1 @@ -2413,6 +2525,12 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_MIGRATE_BEGIN3 = 210, + REMOTE_PROC_DOMAIN_MIGRATE_PREPARE3 = 211, + REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3 = 212, + REMOTE_PROC_DOMAIN_MIGRATE_PERFORM3 = 213, + REMOTE_PROC_DOMAIN_MIGRATE_FINISH3 = 214, + REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3 = 215, }; typedef enum remote_procedure remote_procedure; @@ -2796,6 +2914,17 @@ extern bool_t xdr_remote_domain_snapshot_delete_args (XDR *, remote_domain_snap extern bool_t xdr_remote_domain_open_console_args (XDR *, remote_domain_open_console_args*); extern bool_t xdr_remote_storage_vol_upload_args (XDR *, remote_storage_vol_upload_args*); extern bool_t xdr_remote_storage_vol_download_args (XDR *, remote_storage_vol_download_args*); +extern bool_t xdr_remote_domain_migrate_begin3_args (XDR *, remote_domain_migrate_begin3_args*); +extern bool_t xdr_remote_domain_migrate_begin3_ret (XDR *, remote_domain_migrate_begin3_ret*); +extern bool_t xdr_remote_domain_migrate_prepare3_args (XDR *, remote_domain_migrate_prepare3_args*); +extern bool_t xdr_remote_domain_migrate_prepare3_ret (XDR *, remote_domain_migrate_prepare3_ret*); +extern bool_t xdr_remote_domain_migrate_prepare_tunnel3_args (XDR *, remote_domain_migrate_prepare_tunnel3_args*); +extern bool_t xdr_remote_domain_migrate_prepare_tunnel3_ret (XDR *, remote_domain_migrate_prepare_tunnel3_ret*); +extern bool_t xdr_remote_domain_migrate_perform3_args (XDR *, remote_domain_migrate_perform3_args*); +extern bool_t xdr_remote_domain_migrate_perform3_ret (XDR *, remote_domain_migrate_perform3_ret*); +extern bool_t xdr_remote_domain_migrate_finish3_args (XDR *, remote_domain_migrate_finish3_args*); +extern bool_t xdr_remote_domain_migrate_finish3_ret (XDR *, remote_domain_migrate_finish3_ret*); +extern bool_t xdr_remote_domain_migrate_confirm3_args (XDR *, remote_domain_migrate_confirm3_args*); extern bool_t xdr_remote_procedure (XDR *, remote_procedure*); extern bool_t xdr_remote_message_type (XDR *, remote_message_type*); extern bool_t xdr_remote_message_status (XDR *, remote_message_status*); @@ -3153,6 +3282,17 @@ extern bool_t xdr_remote_domain_snapshot_delete_args (); extern bool_t xdr_remote_domain_open_console_args (); extern bool_t xdr_remote_storage_vol_upload_args (); extern bool_t xdr_remote_storage_vol_download_args (); +extern bool_t xdr_remote_domain_migrate_begin3_args (); +extern bool_t xdr_remote_domain_migrate_begin3_ret (); +extern bool_t xdr_remote_domain_migrate_prepare3_args (); +extern bool_t xdr_remote_domain_migrate_prepare3_ret (); +extern bool_t xdr_remote_domain_migrate_prepare_tunnel3_args (); +extern bool_t xdr_remote_domain_migrate_prepare_tunnel3_ret (); +extern bool_t xdr_remote_domain_migrate_perform3_args (); +extern bool_t xdr_remote_domain_migrate_perform3_ret (); +extern bool_t xdr_remote_domain_migrate_finish3_args (); +extern bool_t xdr_remote_domain_migrate_finish3_ret (); +extern bool_t xdr_remote_domain_migrate_confirm3_args (); extern bool_t xdr_remote_procedure (); extern bool_t xdr_remote_message_type (); extern bool_t xdr_remote_message_status (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 675eccd..a5d6fb2 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -1940,6 +1940,76 @@ struct remote_storage_vol_download_args { unsigned int flags; }; +struct remote_domain_migrate_begin3_args { + remote_nonnull_domain dom; + unsigned hyper flags; + remote_string dname; + unsigned hyper resource; +}; + +struct remote_domain_migrate_begin3_ret { + opaque cookie_out; + remote_nonnull_string xml; +}; + +struct remote_domain_migrate_prepare3_args { + opaque cookie_in; + remote_string uri_in; + unsigned hyper flags; + remote_string dname; + unsigned hyper resource; + remote_nonnull_string dom_xml; +}; + +struct remote_domain_migrate_prepare3_ret { + opaque cookie_out; + remote_string uri_out; +}; + +struct remote_domain_migrate_prepare_tunnel3_args { + opaque cookie_in; + unsigned hyper flags; + remote_string dname; + unsigned hyper resource; + remote_nonnull_string dom_xml; +}; + +struct remote_domain_migrate_prepare_tunnel3_ret { + opaque cookie_out; +}; + +struct remote_domain_migrate_perform3_args { + remote_nonnull_domain dom; + opaque cookie_in; + remote_nonnull_string uri; + unsigned hyper flags; + remote_string dname; + unsigned hyper resource; +}; + +struct remote_domain_migrate_perform3_ret { + opaque cookie_out; +}; + +struct remote_domain_migrate_finish3_args { + remote_nonnull_string dname; + opaque cookie_in; + remote_nonnull_string uri; + unsigned hyper flags; + int cancelled; +}; + +struct remote_domain_migrate_finish3_ret { + remote_domain ddom; + opaque cookie_out; +}; + +struct remote_domain_migrate_confirm3_args { + remote_nonnull_domain dom; + opaque cookie_in; + unsigned hyper flags; + int cancelled; +}; /*----- Protocol. -----*/ @@ -2176,7 +2246,14 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_MIGRATE_BEGIN3 = 210, + + REMOTE_PROC_DOMAIN_MIGRATE_PREPARE3 = 211, + REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3 = 212, + REMOTE_PROC_DOMAIN_MIGRATE_PERFORM3 = 213, + REMOTE_PROC_DOMAIN_MIGRATE_FINISH3 = 214, + REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3 = 215 /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 944553c..0c2317a 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1427,6 +1427,96 @@ struct remote_storage_vol_download_args { uint64_t length; u_int flags; }; +struct remote_domain_migrate_begin3_args { + remote_nonnull_domain dom; + uint64_t flags; + remote_string dname; + uint64_t resource; +}; +struct remote_domain_migrate_begin3_ret { + struct { + u_int cookie_out_len; + char * cookie_out_val; + } cookie_out; + remote_nonnull_string xml; +}; +struct remote_domain_migrate_prepare3_args { + struct { + u_int cookie_in_len; + char * cookie_in_val; + } cookie_in; + remote_string uri_in; + uint64_t flags; + remote_string dname; + uint64_t resource; + remote_nonnull_string dom_xml; +}; +struct remote_domain_migrate_prepare3_ret { + struct { + u_int cookie_out_len; + char * cookie_out_val; + } cookie_out; + remote_string uri_out; +}; +struct remote_domain_migrate_prepare_tunnel3_args { + struct { + u_int cookie_in_len; + char * cookie_in_val; + } cookie_in; + uint64_t flags; + remote_string dname; + uint64_t resource; + remote_nonnull_string dom_xml; +}; +struct remote_domain_migrate_prepare_tunnel3_ret { + struct { + u_int cookie_out_len; + char * cookie_out_val; + } cookie_out; +}; +struct remote_domain_migrate_perform3_args { + remote_nonnull_domain dom; + struct { + u_int cookie_in_len; + char * cookie_in_val; + } cookie_in; + remote_nonnull_string uri; + uint64_t flags; + remote_string dname; + uint64_t resource; +}; +struct remote_domain_migrate_perform3_ret { + struct { + u_int cookie_out_len; + char * cookie_out_val; + } cookie_out; +}; +struct remote_domain_migrate_finish3_args { + remote_nonnull_string dname; + struct { + u_int cookie_in_len; + char * cookie_in_val; + } cookie_in; + remote_nonnull_string uri; + uint64_t flags; + int cancelled; +}; +struct remote_domain_migrate_finish3_ret { + remote_domain ddom; + struct { + u_int cookie_out_len; + char * cookie_out_val; + } cookie_out; +}; +struct remote_domain_migrate_confirm3_args { + remote_nonnull_domain dom; + struct { + u_int cookie_in_len; + char * cookie_in_val; + } cookie_in; + uint64_t flags; + int cancelled; +}; struct remote_message_header { u_int prog; u_int vers; -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:43 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:43 +0100 Subject: [libvirt] [PATCH 04/16] Introduce migration cookies to QEMU driver In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-5-git-send-email-berrange@redhat.com> The migration protocol has support for a 'cookie' parameter which is an opaque array of bytes as far as libvirt is concerned. Drivers may use this for passing around arbitrary extra data they might need during migration. The QEMU driver needs todo a few things: - Pass hostname/uuid to allow strict protection against localhost migration attempts - Pass SPICE/VNC server port from the target back to the source to allow seemless relocation of client sessions - Pass lock driver state from source to destination This patch introduces the basic glue for handling cookies but only includes the host/guest UUID & name. * src/libvirt_private.syms: Export virXMLParseStrHelper * src/qemu/qemu_migration.c, src/qemu/qemu_migration.h: Parsing and formatting of migration cookies * src/qemu/qemu_driver.c: Pass in cookie parameters where possible * src/remote/remote_protocol.h, src/remote/remote_protocol.x: Change cookie max length to 16384 bytes --- cfg.mk | 1 + src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 20 ++- src/qemu/qemu_migration.c | 351 +++++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_migration.h | 16 ++ src/remote/remote_protocol.h | 2 +- src/remote/remote_protocol.x | 2 +- 7 files changed, 378 insertions(+), 15 deletions(-) diff --git a/cfg.mk b/cfg.mk index 72dd69c..92974a9 100644 --- a/cfg.mk +++ b/cfg.mk @@ -72,6 +72,7 @@ VC_LIST_ALWAYS_EXCLUDE_REGEX = ^(HACKING|docs/news\.html\.in)$$ useless_free_options = \ --name=VIR_FREE \ --name=qemuCapsFree \ + --name=qemuMigrationCookieFree \ --name=sexpr_free \ --name=virBitmapFree \ --name=virCPUDefFree \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 7471e25..b787811 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -994,6 +994,7 @@ virStrerror; # xml.h +virXMLParseStrHelper; virXMLPropString; virXPathBoolean; virXPathInt; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e6c7599..f382a24 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5452,8 +5452,9 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn, } qemuDriverLock(driver); - ret = qemuMigrationPrepareTunnel(driver, dconn, st, - dname, dom_xml); + ret = qemuMigrationPrepareTunnel(driver, dconn, + NULL, 0, NULL, NULL, /* No cookies in v2 */ + st, dname, dom_xml); qemuDriverUnlock(driver); cleanup: @@ -5466,8 +5467,8 @@ cleanup: */ static int ATTRIBUTE_NONNULL (5) qemudDomainMigratePrepare2 (virConnectPtr dconn, - char **cookie ATTRIBUTE_UNUSED, - int *cookielen ATTRIBUTE_UNUSED, + char **cookie, + int *cookielen, const char *uri_in, char **uri_out, unsigned long flags, @@ -5506,6 +5507,8 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, } ret = qemuMigrationPrepareDirect(driver, dconn, + NULL, 0, /* No input cookies in v2 */ + cookie, cookielen, uri_in, uri_out, dname, dom_xml); @@ -5549,8 +5552,9 @@ qemudDomainMigratePerform (virDomainPtr dom, } ret = qemuMigrationPerform(driver, dom->conn, vm, - uri, flags, - dname, resource); + uri, cookie, cookielen, + NULL, NULL, /* No output cookies in v2 */ + flags, dname, resource); cleanup: qemuDriverUnlock(driver); @@ -5593,7 +5597,9 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn, goto cleanup; } - dom = qemuMigrationFinish(driver, dconn, vm, flags, retcode); + dom = qemuMigrationFinish(driver, dconn, vm, + NULL, 0, NULL, NULL, /* No cookies in v2 */ + flags, retcode); cleanup: if (orig_err) { diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 7f4b111..98773c0 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -22,6 +22,8 @@ #include #include +#include +#include #include "qemu_migration.h" #include "qemu_monitor.h" @@ -38,11 +40,271 @@ #include "files.h" #include "datatypes.h" #include "fdstream.h" +#include "uuid.h" + #define VIR_FROM_THIS VIR_FROM_QEMU #define timeval_to_ms(tv) (((tv).tv_sec * 1000ull) + ((tv).tv_usec / 1000)) +typedef struct _qemuMigrationCookie qemuMigrationCookie; +typedef qemuMigrationCookie *qemuMigrationCookiePtr; +struct _qemuMigrationCookie { + int flags; + + /* Host properties */ + unsigned char hostuuid[VIR_UUID_BUFLEN]; + char *hostname; + + /* Guest properties */ + unsigned char uuid[VIR_UUID_BUFLEN]; + char *name; +}; + + +static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig) +{ + if (!mig) + return; + + VIR_FREE(mig->hostname); + VIR_FREE(mig->name); + VIR_FREE(mig); +} + + +static qemuMigrationCookiePtr +qemuMigrationCookieNew(virDomainObjPtr dom) +{ + qemuMigrationCookiePtr mig = NULL; + + if (VIR_ALLOC(mig) < 0) + goto no_memory; + + if (!(mig->name = strdup(dom->def->name))) + goto no_memory; + memcpy(mig->uuid, dom->def->uuid, VIR_UUID_BUFLEN); + + if (!(mig->hostname = virGetHostname(NULL))) + goto no_memory; + if (virGetHostUUID(mig->hostuuid) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to obtain host UUID")); + goto error; + } + + return mig; + +no_memory: + virReportOOMError(); +error: + qemuMigrationCookieFree(mig); + return NULL; +} + + +static void qemuMigrationCookieXMLFormat(virBufferPtr buf, + qemuMigrationCookiePtr mig) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + char hostuuidstr[VIR_UUID_STRING_BUFLEN]; + + virUUIDFormat(mig->uuid, uuidstr); + virUUIDFormat(mig->hostuuid, hostuuidstr); + + virBufferVSprintf(buf, "\n"); + virBufferEscapeString(buf, " %s\n", mig->name); + virBufferVSprintf(buf, " %s\n", uuidstr); + virBufferEscapeString(buf, " %s\n", mig->hostname); + virBufferVSprintf(buf, " %s\n", hostuuidstr); + virBufferAddLit(buf, "\n"); +} + + +static char *qemuMigrationCookieXMLFormatStr(qemuMigrationCookiePtr mig) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + + qemuMigrationCookieXMLFormat(&buf, mig); + + if (virBufferError(&buf)) { + virReportOOMError(); + return NULL; + } + + return virBufferContentAndReset(&buf); +} + + +static int +qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, + xmlXPathContextPtr ctxt, + int flags ATTRIBUTE_UNUSED) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + char *tmp; + + /* We don't store the uuid, name, hostname, or hostuuid + * values. We just compare them to local data todo some + * sanity checking on migration operation + */ + + /* Extract domain name */ + if (!(tmp = virXPathString("string(./name[1])", ctxt))) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("missing name element in migration data")); + goto error; + } + if (STRNEQ(tmp, mig->name)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Incoming cookie data had unexpected name %s vs %s"), + tmp, mig->name); + goto error; + } + VIR_FREE(tmp); + + /* Extract domain uuid */ + tmp = virXPathString("string(./uuid[1])", ctxt); + if (!tmp) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("missing uuid element in migration data")); + goto error; + } + virUUIDFormat(mig->uuid, uuidstr); + if (STRNEQ(tmp, uuidstr)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Incoming cookie data had unexpected UUID %s vs %s"), + tmp, uuidstr); + } + VIR_FREE(tmp); + + /* Check & forbid "localhost" migration */ + if (!(tmp = virXPathString("string(./hostname[1])", ctxt))) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("missing hostname element in migration data")); + goto error; + } + if (STREQ(tmp, mig->hostname)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Attempt to migrate guest to the same host %s"), + tmp); + goto error; + } + VIR_FREE(tmp); + + if (!(tmp = virXPathString("string(./hostuuid[1])", ctxt))) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("missing hostuuid element in migration data")); + goto error; + } + virUUIDFormat(mig->hostuuid, uuidstr); + if (STREQ(tmp, uuidstr)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Attempt to migrate guest to the same host %s"), + tmp); + goto error; + } + VIR_FREE(tmp); + + return 0; + +error: + VIR_FREE(tmp); + return -1; +} + + +static int +qemuMigrationCookieXMLParseStr(qemuMigrationCookiePtr mig, + const char *xml, + int flags) +{ + xmlDocPtr doc = NULL; + xmlXPathContextPtr ctxt = NULL; + int ret; + + VIR_DEBUG("xml=%s", NULLSTR(xml)); + + if (!(doc = virXMLParseString(xml, "qemumigration.xml"))) + goto cleanup; + + if ((ctxt = xmlXPathNewContext(doc)) == NULL) { + virReportOOMError(); + goto cleanup; + } + + ctxt->node = xmlDocGetRootElement(doc); + + ret = qemuMigrationCookieXMLParse(mig, ctxt, flags); + +cleanup: + xmlXPathFreeContext(ctxt); + xmlFreeDoc(doc); + + return ret; +} + + +static int +qemuMigrationBakeCookie(qemuMigrationCookiePtr mig, + struct qemud_driver *driver ATTRIBUTE_UNUSED, + virDomainObjPtr dom ATTRIBUTE_UNUSED, + char **cookieout, + int *cookieoutlen, + int flags ATTRIBUTE_UNUSED) +{ + if (!cookieout || !cookieoutlen) { + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing migration cookie data")); + return -1; + } + + *cookieoutlen = 0; + + if (!(*cookieout = qemuMigrationCookieXMLFormatStr(mig))) + return -1; + + *cookieoutlen = strlen(*cookieout) + 1; + + VIR_DEBUG("cookielen=%d cookie=%s", *cookieoutlen, *cookieout); + + return 0; +} + + +static qemuMigrationCookiePtr +qemuMigrationEatCookie(virDomainObjPtr dom, + const char *cookiein, + int cookieinlen, + int flags) +{ + qemuMigrationCookiePtr mig = NULL; + + /* Parse & validate incoming cookie (if any) */ + if (cookiein && cookieinlen && + cookiein[cookieinlen-1] != '\0') { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Migration cookie was not NULL terminated")); + goto error; + } + + VIR_DEBUG("cookielen=%d cookie='%s'", cookieinlen, NULLSTR(cookiein)); + + if (!(mig = qemuMigrationCookieNew(dom))) + return NULL; + + if (cookiein && cookieinlen && + qemuMigrationCookieXMLParseStr(mig, + cookiein, + flags) < 0) + goto error; + + return mig; + +error: + qemuMigrationCookieFree(mig); + return NULL; +} bool qemuMigrationIsAllowed(virDomainDefPtr def) @@ -245,6 +507,10 @@ cleanup: int qemuMigrationPrepareTunnel(struct qemud_driver *driver, virConnectPtr dconn, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, virStreamPtr st, const char *dname, const char *dom_xml) @@ -258,6 +524,7 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, virBitmapPtr qemuCaps = NULL; qemuDomainObjPrivatePtr priv = NULL; struct timeval now; + qemuMigrationCookiePtr mig = NULL; if (gettimeofday(&now, NULL) < 0) { virReportSystemError(errno, "%s", @@ -293,6 +560,9 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, def = NULL; priv = vm->privateData; + if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0))) + goto cleanup; + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; priv->jobActive = QEMU_JOB_MIGRATION_OUT; @@ -351,6 +621,15 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_MIGRATED); + + if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0) { + /* We could tear down the whole guest here, but + * cookie data is (so far) non-critical, so that + * seems a little harsh. We'll just warn for now.. + */ + VIR_WARN0("Unable to encode migration cookie"); + } + ret = 0; endjob: @@ -379,7 +658,7 @@ cleanup: virDomainObjUnlock(vm); if (event) qemuDomainEventQueue(driver, event); - qemuDriverUnlock(driver); + qemuMigrationCookieFree(mig); return ret; } @@ -387,6 +666,10 @@ cleanup: int qemuMigrationPrepareDirect(struct qemud_driver *driver, virConnectPtr dconn, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, const char *uri_in, char **uri_out, const char *dname, @@ -404,6 +687,7 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver, int internalret; qemuDomainObjPrivatePtr priv = NULL; struct timeval now; + qemuMigrationCookiePtr mig = NULL; if (gettimeofday(&now, NULL) < 0) { virReportSystemError(errno, "%s", @@ -513,6 +797,9 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver, def = NULL; priv = vm->privateData; + if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0))) + goto cleanup; + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; priv->jobActive = QEMU_JOB_MIGRATION_OUT; @@ -538,6 +825,14 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver, goto endjob; } + if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0) { + /* We could tear down the whole guest here, but + * cookie data is (so far) non-critical, so that + * seems a little harsh. We'll just warn for now.. + */ + VIR_WARN0("Unable to encode migration cookie"); + } + qemuAuditDomainStart(vm, "migrated", true); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, @@ -570,6 +865,7 @@ cleanup: virDomainObjUnlock(vm); if (event) qemuDomainEventQueue(driver, event); + qemuMigrationCookieFree(mig); return ret; } @@ -580,6 +876,10 @@ cleanup: static int doNativeMigrate(struct qemud_driver *driver, virDomainObjPtr vm, const char *uri, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, unsigned int flags, const char *dname ATTRIBUTE_UNUSED, unsigned long resource) @@ -588,6 +888,10 @@ static int doNativeMigrate(struct qemud_driver *driver, xmlURIPtr uribits = NULL; qemuDomainObjPrivatePtr priv = vm->privateData; unsigned int background_flags = QEMU_MONITOR_MIGRATE_BACKGROUND; + qemuMigrationCookiePtr mig = NULL; + + if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0))) + goto cleanup; /* Issue the migrate command. */ if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://")) { @@ -631,9 +935,13 @@ static int doNativeMigrate(struct qemud_driver *driver, if (qemuMigrationWaitForCompletion(driver, vm) < 0) goto cleanup; + if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0) + VIR_WARN0("Unable to encode migration cookie"); + ret = 0; cleanup: + qemuMigrationCookieFree(mig); xmlFreeURI(uribits); return ret; } @@ -921,14 +1229,16 @@ static int doNonTunnelMigrate(struct qemud_driver *driver, virDomainPtr ddomain = NULL; int retval = -1; char *uri_out = NULL; + char *cookie = NULL; + int cookielen = 0; int rc; qemuDomainObjEnterRemoteWithDriver(driver, vm); /* NB we don't pass 'uri' into this, since that's the libvirtd * URI in this context - so we let dest pick it */ rc = dconn->driver->domainMigratePrepare2(dconn, - NULL, /* cookie */ - 0, /* cookielen */ + &cookie, + &cookielen, NULL, /* uri */ &uri_out, flags, dname, @@ -953,7 +1263,10 @@ static int doNonTunnelMigrate(struct qemud_driver *driver, goto cleanup; } - if (doNativeMigrate(driver, vm, uri_out, flags, dname, resource) < 0) + if (doNativeMigrate(driver, vm, uri_out, + cookie, cookielen, + NULL, NULL, /* No out cookie with v2 migration */ + flags, dname, resource) < 0) goto finish; retval = 0; @@ -962,13 +1275,14 @@ finish: dname = dname ? dname : vm->def->name; qemuDomainObjEnterRemoteWithDriver(driver, vm); ddomain = dconn->driver->domainMigrateFinish2 - (dconn, dname, NULL, 0, uri_out, flags, retval); + (dconn, dname, cookie, cookielen, uri_out, flags, retval); qemuDomainObjExitRemoteWithDriver(driver, vm); if (ddomain) virUnrefDomain(ddomain); cleanup: + VIR_FREE(cookie); return retval; } @@ -1044,6 +1358,10 @@ int qemuMigrationPerform(struct qemud_driver *driver, virConnectPtr conn, virDomainObjPtr vm, const char *uri, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, unsigned long flags, const char *dname, unsigned long resource) @@ -1073,11 +1391,19 @@ int qemuMigrationPerform(struct qemud_driver *driver, } if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) { + if (cookieinlen) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("received unexpected cookie with P2P migration")); + goto endjob; + } + if (doPeer2PeerMigrate(driver, vm, uri, flags, dname, resource) < 0) /* doPeer2PeerMigrate already set the error, so just get out */ goto endjob; } else { - if (doNativeMigrate(driver, vm, uri, flags, dname, resource) < 0) + if (doNativeMigrate(driver, vm, uri, cookiein, cookieinlen, + cookieout, cookieoutlen, + flags, dname, resource) < 0) goto endjob; } @@ -1095,6 +1421,7 @@ int qemuMigrationPerform(struct qemud_driver *driver, virDomainRemoveInactive(&driver->domains, vm); vm = NULL; } + ret = 0; endjob: @@ -1171,6 +1498,10 @@ virDomainPtr qemuMigrationFinish(struct qemud_driver *driver, virConnectPtr dconn, virDomainObjPtr vm, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, unsigned long flags, int retcode) { @@ -1178,6 +1509,7 @@ qemuMigrationFinish(struct qemud_driver *driver, virDomainEventPtr event = NULL; int newVM = 1; qemuDomainObjPrivatePtr priv = NULL; + qemuMigrationCookiePtr mig = NULL; priv = vm->privateData; if (priv->jobActive != QEMU_JOB_MIGRATION_IN) { @@ -1188,6 +1520,9 @@ qemuMigrationFinish(struct qemud_driver *driver, priv->jobActive = QEMU_JOB_NONE; memset(&priv->jobInfo, 0, sizeof(priv->jobInfo)); + if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0))) + goto cleanup; + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; @@ -1273,6 +1608,9 @@ qemuMigrationFinish(struct qemud_driver *driver, } } + if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0) + VIR_WARN0("Unable to encode migration cookie"); + endjob: if (vm && qemuDomainObjEndJob(vm) == 0) @@ -1283,6 +1621,7 @@ cleanup: virDomainObjUnlock(vm); if (event) qemuDomainEventQueue(driver, event); + qemuMigrationCookieFree(mig); return dom; } diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index db16ce4..11571e7 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -34,12 +34,20 @@ int qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr int qemuMigrationPrepareTunnel(struct qemud_driver *driver, virConnectPtr dconn, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, virStreamPtr st, const char *dname, const char *dom_xml); int qemuMigrationPrepareDirect(struct qemud_driver *driver, virConnectPtr dconn, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, const char *uri_in, char **uri_out, const char *dname, @@ -49,6 +57,10 @@ int qemuMigrationPerform(struct qemud_driver *driver, virConnectPtr conn, virDomainObjPtr vm, const char *uri, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, unsigned long flags, const char *dname, unsigned long resource); @@ -56,6 +68,10 @@ int qemuMigrationPerform(struct qemud_driver *driver, virDomainPtr qemuMigrationFinish(struct qemud_driver *driver, virConnectPtr dconn, virDomainObjPtr vm, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, unsigned long flags, int retcode); diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index 385d431..0cd8601 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -43,7 +43,7 @@ typedef remote_nonnull_string *remote_string; #define REMOTE_CPUMAP_MAX 256 #define REMOTE_VCPUINFO_MAX 2048 #define REMOTE_CPUMAPS_MAX 16384 -#define REMOTE_MIGRATE_COOKIE_MAX 256 +#define REMOTE_MIGRATE_COOKIE_MAX 16384 #define REMOTE_NETWORK_NAME_LIST_MAX 256 #define REMOTE_INTERFACE_NAME_LIST_MAX 256 #define REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX 256 diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index a5d6fb2..2d7487e 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -99,7 +99,7 @@ const REMOTE_VCPUINFO_MAX = 2048; const REMOTE_CPUMAPS_MAX = 16384; /* Upper limit on migrate cookie. */ -const REMOTE_MIGRATE_COOKIE_MAX = 256; +const REMOTE_MIGRATE_COOKIE_MAX = 16384; /* Upper limit on lists of network names. */ const REMOTE_NETWORK_NAME_LIST_MAX = 256; -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:44 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:44 +0100 Subject: [libvirt] [PATCH 05/16] Pass graphics setup from dst back to src via migration cookies In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-6-git-send-email-berrange@redhat.com> Extend the QEMU migration cookie structure to allow information about the destination host graphics setup to be passed by to the source host. This will enable seamless migration of any connected graphics clients * src/qemu/qemu_migration.c: Add graphics info to migration cookies * daemon/libvirtd.c: Always initialize gnutls to enable x509 cert parsing in QEMU --- cfg.mk | 1 + daemon/libvirtd.c | 8 +- src/qemu/qemu_migration.c | 264 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 261 insertions(+), 12 deletions(-) diff --git a/cfg.mk b/cfg.mk index 92974a9..f414ea6 100644 --- a/cfg.mk +++ b/cfg.mk @@ -73,6 +73,7 @@ useless_free_options = \ --name=VIR_FREE \ --name=qemuCapsFree \ --name=qemuMigrationCookieFree \ + --name=qemuMigrationCookieGraphicsFree \ --name=sexpr_free \ --name=virBitmapFree \ --name=virCPUDefFree \ diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 42cbe5d..ae04078 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -317,9 +317,6 @@ remoteInitializeGnuTLS (void) { int err; - /* Initialise GnuTLS. */ - gnutls_global_init (); - err = gnutls_certificate_allocate_credentials (&x509_cred); if (err) { VIR_ERROR(_("gnutls_certificate_allocate_credentials: %s"), @@ -3310,6 +3307,11 @@ int main(int argc, char **argv) { goto error; } + /* Initialise GnuTLS. Required even if we don't use TLS + * for libvirtd, because QEMU driver needs to be able to + * parse x590 certificates for seemless migration */ + gnutls_global_init(); + if (!(server = qemudInitialize())) { ret = VIR_DAEMON_ERR_INIT; goto error; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 98773c0..3bc7ed8 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -47,6 +47,20 @@ #define timeval_to_ms(tv) (((tv).tv_sec * 1000ull) + ((tv).tv_usec / 1000)) +enum qemuMigrationCookieFlags { + QEMU_MIGRATION_COOKIE_GRAPHICS = (1 << 0), +}; + +typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics; +typedef qemuMigrationCookieGraphics *qemuMigrationCookieGraphicsPtr; +struct _qemuMigrationCookieGraphics { + int type; + int port; + int tlsPort; + char *listen; + char *tlsSubject; +}; + typedef struct _qemuMigrationCookie qemuMigrationCookie; typedef qemuMigrationCookie *qemuMigrationCookiePtr; struct _qemuMigrationCookie { @@ -59,20 +73,142 @@ struct _qemuMigrationCookie { /* Guest properties */ unsigned char uuid[VIR_UUID_BUFLEN]; char *name; + + /* If (flags & QEMU_MIGRATION_COOKIE_GRAPHICS) */ + qemuMigrationCookieGraphicsPtr graphics; }; +static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap) +{ + if (!grap) + return; + VIR_FREE(grap->listen); + VIR_FREE(grap->tlsSubject); + VIR_FREE(grap); +} + static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig) { if (!mig) return; + if (mig->flags & QEMU_MIGRATION_COOKIE_GRAPHICS) + qemuMigrationCookieGraphicsFree(mig->graphics); + VIR_FREE(mig->hostname); VIR_FREE(mig->name); VIR_FREE(mig); } +static char * +qemuDomainExtractTLSSubject(const char *certdir) +{ + char *certfile = NULL; + char *subject = NULL; + char *pemdata = NULL; + gnutls_datum_t pemdatum; + gnutls_x509_crt_t cert; + int ret; + size_t subjectlen; + + if (virAsprintf(&certfile, "%s/server-cert.pem", certdir) < 0) + goto no_memory; + + if (virFileReadAll(certfile, 8192, &pemdata) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("unable to read server cert %s"), certfile); + goto error; + } + + ret = gnutls_x509_crt_init(&cert); + if (ret < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot initialize cert object: %s"), + gnutls_strerror(ret)); + goto error; + } + + pemdatum.data = (unsigned char *)pemdata; + pemdatum.size = strlen(pemdata); + + ret = gnutls_x509_crt_import(cert, &pemdatum, GNUTLS_X509_FMT_PEM); + if (ret < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot load cert data from %s: %s"), + certfile, gnutls_strerror(ret)); + goto error; + } + + subjectlen = 1024; + if (VIR_ALLOC_N(subject, subjectlen+1) < 0) + goto no_memory; + + gnutls_x509_crt_get_dn(cert, subject, &subjectlen); + subject[subjectlen] = '\0'; + + VIR_FREE(certfile); + VIR_FREE(pemdata); + + return subject; + +no_memory: + virReportOOMError(); +error: + VIR_FREE(certfile); + VIR_FREE(pemdata); + return NULL; +} + + +static qemuMigrationCookieGraphicsPtr +qemuMigrationCookieGraphicsAlloc(struct qemud_driver *driver, + virDomainGraphicsDefPtr def) +{ + qemuMigrationCookieGraphicsPtr mig = NULL; + const char *listenAddr; + + if (VIR_ALLOC(mig) < 0) + goto no_memory; + + mig->type = def->type; + if (mig->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { + mig->port = def->data.vnc.port; + listenAddr = def->data.vnc.listenAddr; + if (!listenAddr) + listenAddr = driver->vncListen; + + if (driver->vncTLS && + !(mig->tlsSubject = qemuDomainExtractTLSSubject(driver->vncTLSx509certdir))) + goto error; + } else { + mig->port = def->data.spice.port; + if (driver->spiceTLS) + mig->tlsPort = def->data.spice.tlsPort; + else + mig->tlsPort = -1; + listenAddr = def->data.spice.listenAddr; + if (!listenAddr) + listenAddr = driver->spiceListen; + + if (driver->spiceTLS && + !(mig->tlsSubject = qemuDomainExtractTLSSubject(driver->spiceTLSx509certdir))) + goto error; + } + if (!(mig->listen = strdup(listenAddr))) + goto no_memory; + + return mig; + +no_memory: + virReportOOMError(); +error: + qemuMigrationCookieGraphicsFree(mig); + return NULL; +} + + static qemuMigrationCookiePtr qemuMigrationCookieNew(virDomainObjPtr dom) { @@ -103,6 +239,47 @@ error: } +static int +qemuMigrationCookieAddGraphics(qemuMigrationCookiePtr mig, + struct qemud_driver *driver, + virDomainObjPtr dom) +{ + if (mig->flags & QEMU_MIGRATION_COOKIE_GRAPHICS) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Migration graphics data already present")); + return -1; + } + + if (dom->def->ngraphics == 1 && + (dom->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC || + dom->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) && + !(mig->graphics = qemuMigrationCookieGraphicsAlloc(driver, dom->def->graphics[0]))) + return -1; + + mig->flags |= QEMU_MIGRATION_COOKIE_GRAPHICS; + + return 0; +} + + +static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf, + qemuMigrationCookieGraphicsPtr grap) +{ + virBufferVSprintf(buf, " type), + grap->port, grap->listen); + if (grap->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) + virBufferVSprintf(buf, " tlsPort='%d'", grap->tlsPort); + if (grap->tlsSubject) { + virBufferVSprintf(buf, ">\n"); + virBufferEscapeString(buf, " \n", grap->tlsSubject); + virBufferVSprintf(buf, " \n"); + } else { + virBufferVSprintf(buf, "/>\n"); + } +} + + static void qemuMigrationCookieXMLFormat(virBufferPtr buf, qemuMigrationCookiePtr mig) { @@ -117,6 +294,10 @@ static void qemuMigrationCookieXMLFormat(virBufferPtr buf, virBufferVSprintf(buf, " %s\n", uuidstr); virBufferEscapeString(buf, " %s\n", mig->hostname); virBufferVSprintf(buf, " %s\n", hostuuidstr); + + if (mig->flags & QEMU_MIGRATION_COOKIE_GRAPHICS) + qemuMigrationCookieGraphicsXMLFormat(buf, mig->graphics); + virBufferAddLit(buf, "\n"); } @@ -136,10 +317,61 @@ static char *qemuMigrationCookieXMLFormatStr(qemuMigrationCookiePtr mig) } +static qemuMigrationCookieGraphicsPtr +qemuMigrationCookieGraphicsXMLParse(xmlXPathContextPtr ctxt) +{ + qemuMigrationCookieGraphicsPtr grap; + char *tmp; + + if (VIR_ALLOC(grap) < 0) + goto no_memory; + + if (!(tmp = virXPathString("string(./graphics/@type)", ctxt))) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("missing type attribute in migration data")); + goto error; + } + if ((grap->type = virDomainGraphicsTypeFromString(tmp)) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown graphics type %s"), tmp); + VIR_FREE(tmp); + goto error; + } + if (virXPathInt("string(./graphics/@port)", ctxt, &grap->port) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("missing port attribute in migration data")); + goto error; + } + if (grap->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { + if (virXPathInt("string(./graphics/@tlsPort)", ctxt, &grap->tlsPort) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("missing tlsPort attribute in migration data")); + goto error; + } + } + if (!(grap->listen = virXPathString("string(./graphics/@listen)", ctxt))) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("missing listen attribute in migration data")); + goto error; + } + /* Optional */ + grap->tlsSubject = virXPathString("string(./graphics/cert[ info='subject']/@value)", ctxt); + + + return grap; + +no_memory: + virReportOOMError(); +error: + qemuMigrationCookieGraphicsFree(grap); + return NULL; +} + + static int qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, xmlXPathContextPtr ctxt, - int flags ATTRIBUTE_UNUSED) + int flags) { char uuidstr[VIR_UUID_STRING_BUFLEN]; char *tmp; @@ -206,6 +438,11 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, } VIR_FREE(tmp); + if ((flags & QEMU_MIGRATION_COOKIE_GRAPHICS) && + virXPathBoolean("count(./graphics) > 0", ctxt) && + (!(mig->graphics = qemuMigrationCookieGraphicsXMLParse(ctxt)))) + goto error; + return 0; error: @@ -247,11 +484,11 @@ cleanup: static int qemuMigrationBakeCookie(qemuMigrationCookiePtr mig, - struct qemud_driver *driver ATTRIBUTE_UNUSED, - virDomainObjPtr dom ATTRIBUTE_UNUSED, + struct qemud_driver *driver, + virDomainObjPtr dom, char **cookieout, int *cookieoutlen, - int flags ATTRIBUTE_UNUSED) + int flags) { if (!cookieout || !cookieoutlen) { qemuReportError(VIR_ERR_INVALID_ARG, "%s", @@ -261,6 +498,10 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig, *cookieoutlen = 0; + if (flags & QEMU_MIGRATION_COOKIE_GRAPHICS && + qemuMigrationCookieAddGraphics(mig, driver, dom) < 0) + return -1; + if (!(*cookieout = qemuMigrationCookieXMLFormatStr(mig))) return -1; @@ -560,7 +801,8 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, def = NULL; priv = vm->privateData; - if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0))) + if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, + QEMU_MIGRATION_COOKIE_GRAPHICS))) goto cleanup; if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) @@ -622,7 +864,8 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_MIGRATED); - if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0) { + if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, + QEMU_MIGRATION_COOKIE_GRAPHICS) < 0) { /* We could tear down the whole guest here, but * cookie data is (so far) non-critical, so that * seems a little harsh. We'll just warn for now.. @@ -797,7 +1040,8 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver, def = NULL; priv = vm->privateData; - if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0))) + if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, + QEMU_MIGRATION_COOKIE_GRAPHICS))) goto cleanup; if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) @@ -825,7 +1069,8 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver, goto endjob; } - if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0) { + if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, + QEMU_MIGRATION_COOKIE_GRAPHICS) < 0) { /* We could tear down the whole guest here, but * cookie data is (so far) non-critical, so that * seems a little harsh. We'll just warn for now.. @@ -890,7 +1135,8 @@ static int doNativeMigrate(struct qemud_driver *driver, unsigned int background_flags = QEMU_MONITOR_MIGRATE_BACKGROUND; qemuMigrationCookiePtr mig = NULL; - if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0))) + if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, + QEMU_MIGRATION_COOKIE_GRAPHICS))) goto cleanup; /* Issue the migrate command. */ -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:45 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:45 +0100 Subject: [libvirt] [PATCH 06/16] Wire up SPICE client relocation with QEMU migration In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-7-git-send-email-berrange@redhat.com> Use the graphics information from the QEMU migration cookie to issue a 'client_migrate_info' monitor command to QEMU. This causes the SPICE client to automatically reconnect to the target host when migration completes * src/qemu/qemu_migration.c: Set data for SPICE client relocation before starting migration on src * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, src/qemu/qemu_monitor_json.c, src/qemu/qemu_monitor_json.h, src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h: Add new qemuMonitorGraphicsRelocate() command --- src/qemu/qemu_migration.c | 39 +++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 31 +++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.h | 6 ++++++ src/qemu/qemu_monitor_json.c | 32 ++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 7 +++++++ src/qemu/qemu_monitor_text.c | 31 +++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 7 +++++++ 7 files changed, 153 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 3bc7ed8..57265b3 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -740,6 +740,39 @@ cleanup: } +static int +qemuDomainMigrateGraphicsRelocate(struct qemud_driver *driver, + virDomainObjPtr vm, + qemuMigrationCookiePtr cookie) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + int ret; + + if (!cookie) + return 0; + + if (!cookie->graphics) + return 0; + + /* QEMU doesnt' support VNC relocation yet, so + * skip it to avoid generating an error + */ + if (cookie->graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE) + return 0; + + qemuDomainObjEnterMonitorWithDriver(driver, vm); + ret = qemuMonitorGraphicsRelocate(priv->mon, + cookie->graphics->type, + cookie->hostname, + cookie->graphics->port, + cookie->graphics->tlsPort, + cookie->graphics->tlsSubject); + qemuDomainObjExitMonitorWithDriver(driver, vm); + + return ret; +} + + /* Prepare is the first step, and it runs on the destination host. * * This version starts an empty VM listening on a localhost TCP port, and @@ -1139,6 +1172,9 @@ static int doNativeMigrate(struct qemud_driver *driver, QEMU_MIGRATION_COOKIE_GRAPHICS))) goto cleanup; + if (qemuDomainMigrateGraphicsRelocate(driver, vm, mig) < 0) + VIR_WARN0("unable to provide data for graphics client relocation"); + /* Issue the migrate command. */ if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://")) { /* HACK: source host generates bogus URIs, so fix them up */ @@ -1272,6 +1308,9 @@ static int doTunnelMigrate(struct qemud_driver *driver, * 3. start migration on source */ + /* + * XXX need to support migration cookies + */ /* Stage 1. setup local support infrastructure */ diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 2d28f8d..7d400c3 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1620,6 +1620,37 @@ int qemuMonitorMigrateCancel(qemuMonitorPtr mon) return ret; } + +int qemuMonitorGraphicsRelocate(qemuMonitorPtr mon, + int type, + const char *hostname, + int port, + int tlsPort, + const char *tlsSubject) +{ + int ret; + VIR_DEBUG("mon=%p type=%d hostname=%s port=%d tlsPort=%d tlsSubject=%s", + mon, type, hostname, port, tlsPort, NULLSTR(tlsSubject)); + + if (mon->json) + ret = qemuMonitorJSONGraphicsRelocate(mon, + type, + hostname, + port, + tlsPort, + tlsSubject); + else + ret = qemuMonitorTextGraphicsRelocate(mon, + type, + hostname, + port, + tlsPort, + tlsSubject); + + return ret; +} + + int qemuMonitorAddUSBDisk(qemuMonitorPtr mon, const char *path) { diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c90219b..b07a0d7 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -304,6 +304,12 @@ int qemuMonitorMigrateToUnix(qemuMonitorPtr mon, int qemuMonitorMigrateCancel(qemuMonitorPtr mon); +int qemuMonitorGraphicsRelocate(qemuMonitorPtr mon, + int type, + const char *hostname, + int port, + int tlsPort, + const char *tlsSubject); /* XXX disk driver type eg, qcow/etc. * XXX cache mode diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 20a78e1..3656ad1 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -1820,6 +1820,38 @@ int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon) } +int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon, + int type, + const char *hostname, + int port, + int tlsPort, + const char *tlsSubject) +{ + int ret = -1; + virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("client_migrate_info", + "s:protocol", + (type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE ? "spice" : "vnc"), + "s:hostname", hostname, + "i:port", port, + "i:tls-port", tlsPort, + (tlsSubject ? "s:cert-subject" : NULL), + (tlsSubject ? tlsSubject : NULL), + NULL); + virJSONValuePtr reply = NULL; + if (!cmd) + return -1; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + + int qemuMonitorJSONAddUSBDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED, const char *path ATTRIBUTE_UNUSED) { diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 086f0e1..308f622 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -117,6 +117,13 @@ int qemuMonitorJSONMigrate(qemuMonitorPtr mon, int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon); +int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon, + int type, + const char *hostname, + int port, + int tlsPort, + const char *tlsSubject); + int qemuMonitorJSONAddUSBDisk(qemuMonitorPtr mon, const char *path); diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 53781c8..720987a 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1282,6 +1282,37 @@ int qemuMonitorTextMigrateCancel(qemuMonitorPtr mon) return 0; } + +int qemuMonitorTextGraphicsRelocate(qemuMonitorPtr mon, + int type, + const char *hostname, + int port, + int tlsPort, + const char *tlsSubject) +{ + char *cmd; + char *info = NULL; + + if (virAsprintf(&cmd, "client_migrate_info %s %s %d %d %s", + type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE ? "spice" : "vnc", + hostname, port, tlsPort, tlsSubject ? tlsSubject : "") < 0) { + virReportOOMError(); + return -1; + } + + if (qemuMonitorHMPCommand(mon, cmd, &info) < 0) { + VIR_FREE(cmd); + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot run monitor command to relocate graphics client")); + return -1; + } + VIR_FREE(cmd); + VIR_FREE(info); + + return 0; +} + + int qemuMonitorTextAddUSBDisk(qemuMonitorPtr mon, const char *path) { diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 0838a2b..79bd4fe 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -113,6 +113,13 @@ int qemuMonitorTextMigrate(qemuMonitorPtr mon, int qemuMonitorTextMigrateCancel(qemuMonitorPtr mon); +int qemuMonitorTextGraphicsRelocate(qemuMonitorPtr mon, + int type, + const char *hostname, + int port, + int tlsPort, + const char *tlsSubject); + int qemuMonitorTextAddUSBDisk(qemuMonitorPtr mon, const char *path); -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:46 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:46 +0100 Subject: [libvirt] [PATCH 07/16] Refactor tunnelled migration methods In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-8-git-send-email-berrange@redhat.com> To facilitate the introduction of the v3 migration protocol, the doTunnelMigrate method is refactored into two pieces. One piece is intended to mirror the flow of virDomainMigrateVersion2, while the other is the helper for setting up sockets and processing the data. Previously socket setup would be done before the 'prepare' step, so errors could be dealt with immediately, avoiding need to shut off the destination QEMU. In the new split, socket setup is done after the 'prepare' step. This is not a serious problem, since the control flow already requires calling 'finish' to tear down the destination QEMU upon several errors. * src/qemu/qemu_migration.c: --- src/qemu/qemu_migration.c | 178 ++++++++++++++++++++++---------------------- 1 files changed, 89 insertions(+), 89 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 57265b3..7a17dfc 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1274,45 +1274,32 @@ static int doTunnelSendAll(virStreamPtr st, return 0; } + static int doTunnelMigrate(struct qemud_driver *driver, - virConnectPtr dconn, virDomainObjPtr vm, - const char *dom_xml, - const char *uri, + virStreamPtr st, + virBitmapPtr qemuCaps, unsigned long flags, - const char *dname, - unsigned long resource) + unsigned long resource ATTRIBUTE_UNUSED) { qemuDomainObjPrivatePtr priv = vm->privateData; int client_sock = -1; int qemu_sock = -1; struct sockaddr_un sa_qemu, sa_client; socklen_t addrlen; - virDomainPtr ddomain = NULL; - int retval = -1; - virStreamPtr st = NULL; - char *unixfile = NULL; - int internalret; - virBitmapPtr qemuCaps = NULL; int status; unsigned long long transferred, remaining, total; + char *unixfile = NULL; unsigned int background_flags = QEMU_MONITOR_MIGRATE_BACKGROUND; + int ret = -1; - /* - * The order of operations is important here to avoid touching - * the source VM until we are very sure we can successfully - * start the migration operation. - * - * 1. setup local support infrastructure (eg sockets) - * 2. setup destination fully - * 3. start migration on source - */ - - /* - * XXX need to support migration cookies - */ + if (!qemuCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_UNIX) && + !qemuCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_EXEC)) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("Source qemu is too old to support tunnelled migration")); + goto cleanup; + } - /* Stage 1. setup local support infrastructure */ if (virAsprintf(&unixfile, "%s/qemu.tunnelmigrate.src.%s", driver->libDir, vm->def->name) < 0) { @@ -1356,43 +1343,6 @@ static int doTunnelMigrate(struct qemud_driver *driver, goto cleanup; } - /* check that this qemu version supports the unix migration */ - if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch, - NULL, &qemuCaps) < 0) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - _("Cannot extract Qemu version from '%s'"), - vm->def->emulator); - goto cleanup; - } - - if (!qemuCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_UNIX) && - !qemuCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_EXEC)) { - qemuReportError(VIR_ERR_OPERATION_FAILED, - "%s", _("Source qemu is too old to support tunnelled migration")); - goto cleanup; - } - - - /* Stage 2. setup destination fully - * - * Once stage 2 has completed successfully, we *must* call finish - * to cleanup the target whether we succeed or fail - */ - st = virStreamNew(dconn, 0); - if (st == NULL) - /* virStreamNew only fails on OOM, and it reports the error itself */ - goto cleanup; - - qemuDomainObjEnterRemoteWithDriver(driver, vm); - internalret = dconn->driver->domainMigratePrepareTunnel(dconn, st, - flags, dname, - resource, dom_xml); - qemuDomainObjExitRemoteWithDriver(driver, vm); - - if (internalret < 0) - /* domainMigratePrepareTunnel sets the error for us */ - goto cleanup; - /* the domain may have shutdown or crashed while we had the locks dropped * in qemuDomainObjEnterRemoteWithDriver, so check again */ @@ -1404,26 +1354,28 @@ static int doTunnelMigrate(struct qemud_driver *driver, /* 3. start migration on source */ qemuDomainObjEnterMonitorWithDriver(driver, vm); + if (flags & VIR_MIGRATE_NON_SHARED_DISK) background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK; if (flags & VIR_MIGRATE_NON_SHARED_INC) background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_INC; + if (qemuCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_UNIX)) { - internalret = qemuMonitorMigrateToUnix(priv->mon, background_flags, + ret = qemuMonitorMigrateToUnix(priv->mon, background_flags, unixfile); - } - else if (qemuCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_EXEC)) { + } else if (qemuCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_EXEC)) { const char *args[] = { "nc", "-U", unixfile, NULL }; - internalret = qemuMonitorMigrateToCommand(priv->mon, QEMU_MONITOR_MIGRATE_BACKGROUND, args); + ret = qemuMonitorMigrateToCommand(priv->mon, QEMU_MONITOR_MIGRATE_BACKGROUND, args); } else { - internalret = -1; + ret = -1; } qemuDomainObjExitMonitorWithDriver(driver, vm); - if (internalret < 0) { + if (ret < 0) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("tunnelled migration monitor command failed")); - goto finish; + goto cleanup; } + ret = -1; if (!virDomainObjIsActive(vm)) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -1463,16 +1415,71 @@ static int doTunnelMigrate(struct qemud_driver *driver, goto cancel; } - retval = doTunnelSendAll(st, client_sock); + ret = doTunnelSendAll(st, client_sock); cancel: - if (retval != 0 && virDomainObjIsActive(vm)) { + if (ret != 0 && virDomainObjIsActive(vm)) { qemuDomainObjEnterMonitorWithDriver(driver, vm); qemuMonitorMigrateCancel(priv->mon); qemuDomainObjExitMonitorWithDriver(driver, vm); } -finish: +cleanup: + VIR_FORCE_CLOSE(client_sock); + VIR_FORCE_CLOSE(qemu_sock); + if (unixfile) { + unlink(unixfile); + VIR_FREE(unixfile); + } + + return ret; +} + + +static int doTunnelMigrate2(struct qemud_driver *driver, + virConnectPtr dconn, + virDomainObjPtr vm, + const char *dom_xml, + const char *uri, + unsigned long flags, + const char *dname, + unsigned long resource) +{ + virDomainPtr ddomain = NULL; + int retval = -1; + virStreamPtr st = NULL; + int internalret; + virBitmapPtr qemuCaps = NULL; + + /* + * Tunnelled Migrate Version 2 does not support cookies + * due to missing parameters in the prepareTunnel() API. + */ + + /* check that this qemu version supports the unix migration */ + if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch, + NULL, &qemuCaps) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Cannot extract Qemu version from '%s'"), + vm->def->emulator); + goto cleanup; + } + + if (!(st = virStreamNew(dconn, 0))) + goto cleanup; + + qemuDomainObjEnterRemoteWithDriver(driver, vm); + internalret = dconn->driver->domainMigratePrepareTunnel(dconn, st, + flags, dname, + resource, dom_xml); + qemuDomainObjExitRemoteWithDriver(driver, vm); + + if (internalret < 0) + /* domainMigratePrepareTunnel sets the error for us */ + goto cleanup; + + retval = doTunnelMigrate(driver, vm, st, qemuCaps, flags, resource); + dname = dname ? dname : vm->def->name; qemuDomainObjEnterRemoteWithDriver(driver, vm); ddomain = dconn->driver->domainMigrateFinish2 @@ -1480,18 +1487,11 @@ finish: qemuDomainObjExitRemoteWithDriver(driver, vm); cleanup: - VIR_FORCE_CLOSE(client_sock); - VIR_FORCE_CLOSE(qemu_sock); qemuCapsFree(qemuCaps); if (ddomain) virUnrefDomain(ddomain); - if (unixfile) { - unlink(unixfile); - VIR_FREE(unixfile); - } - if (st) /* don't call virStreamFree(), because that resets any pending errors */ virUnrefStream(st); @@ -1502,14 +1502,14 @@ cleanup: /* This is essentially a simplified re-impl of * virDomainMigrateVersion2 from libvirt.c, but running in source * libvirtd context, instead of client app context */ -static int doNonTunnelMigrate(struct qemud_driver *driver, - virConnectPtr dconn, - virDomainObjPtr vm, - const char *dom_xml, - const char *uri ATTRIBUTE_UNUSED, - unsigned long flags, - const char *dname, - unsigned long resource) +static int doNonTunnelMigrate2(struct qemud_driver *driver, + virConnectPtr dconn, + virDomainObjPtr vm, + const char *dom_xml, + const char *uri ATTRIBUTE_UNUSED, + unsigned long flags, + const char *dname, + unsigned long resource) { virDomainPtr ddomain = NULL; int retval = -1; @@ -1624,9 +1624,9 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver, } if (flags & VIR_MIGRATE_TUNNELLED) - ret = doTunnelMigrate(driver, dconn, vm, dom_xml, uri, flags, dname, resource); + ret = doTunnelMigrate2(driver, dconn, vm, dom_xml, uri, flags, dname, resource); else - ret = doNonTunnelMigrate(driver, dconn, vm, dom_xml, uri, flags, dname, resource); + ret = doNonTunnelMigrate2(driver, dconn, vm, dom_xml, uri, flags, dname, resource); cleanup: VIR_FREE(dom_xml); -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:47 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:47 +0100 Subject: [libvirt] [PATCH 08/16] Fix VM teardown if prepare returns invalid URI in v2 migration In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-9-git-send-email-berrange@redhat.com> The v2 migration protocol was accidentally missing out the finish step, when prepare succeeded, but returned an invalid URI * src/libvirt.c: Teardown VM if prepare returns invalid URI --- src/libvirt.c | 16 +++++++++++++--- 1 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 5389df7..40dd2ae 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3443,6 +3443,7 @@ virDomainMigrateVersion2 (virDomainPtr domain, int cookielen = 0, ret; virDomainInfo info; virErrorPtr orig_err = NULL; + int cancelled; /* Prepare the migration. * @@ -3488,7 +3489,8 @@ virDomainMigrateVersion2 (virDomainPtr domain, virLibConnError(VIR_ERR_INTERNAL_ERROR, _("domainMigratePrepare2 did not set uri")); virDispatchError(domain->conn); - goto done; + cancelled = 1; + goto finish; } if (uri_out) uri = uri_out; /* Did domainMigratePrepare2 change URI? */ @@ -3504,6 +3506,12 @@ virDomainMigrateVersion2 (virDomainPtr domain, if (ret < 0) orig_err = virSaveLastError(); + /* If Perform returns < 0, then we need to cancel the VM + * startup on the destination + */ + cancelled = ret < 0 ? 1 : 0; + +finish: /* In version 2 of the migration protocol, we pass the * status code from the sender to the destination host, * so it can do any cleanup if the migration failed. @@ -3511,7 +3519,7 @@ virDomainMigrateVersion2 (virDomainPtr domain, dname = dname ? dname : domain->name; VIR_DEBUG("Finish2 %p ret=%d", dconn, ret); ddomain = dconn->driver->domainMigrateFinish2 - (dconn, dname, cookie, cookielen, uri, flags, ret); + (dconn, dname, cookie, cookielen, uri, flags, cancelled); done: if (orig_err) { @@ -3606,7 +3614,8 @@ virDomainMigrateVersion3(virDomainPtr domain, virLibConnError(VIR_ERR_INTERNAL_ERROR, _("domainMigratePrepare3 did not set uri")); virDispatchError(domain->conn); - goto done; + cancelled = 1; + goto finish; } if (uri_out) uri = uri_out; /* Did domainMigratePrepare3 change URI? */ @@ -3635,6 +3644,7 @@ virDomainMigrateVersion3(virDomainPtr domain, */ cancelled = ret < 0 ? 1 : 0; +finish: /* * The status code from the source is passed to the destination. * The dest can cleanup if the source indicated it failed to -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:48 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:48 +0100 Subject: [libvirt] [PATCH 09/16] Merge tunnel & non-tunnel migration impl into one In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-10-git-send-email-berrange@redhat.com> Merge the doNonTunnelMigrate2 and doTunnelMigrate2 methods into one doPeer2PeerMigrate2 method, since they are substantially the same. With the introduction of v3 migration, this will be even more important, to avoid massive code duplication. * src/qemu/qemu_migration.c: Merge tunnel & non-tunnel migration --- src/qemu/qemu_migration.c | 210 ++++++++++++++++++++++----------------------- 1 files changed, 103 insertions(+), 107 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 7a17dfc..884e26d 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1436,25 +1436,28 @@ cleanup: } -static int doTunnelMigrate2(struct qemud_driver *driver, - virConnectPtr dconn, - virDomainObjPtr vm, - const char *dom_xml, - const char *uri, - unsigned long flags, - const char *dname, - unsigned long resource) +/* This is essentially a re-impl of virDomainMigrateVersion2 + * from libvirt.c, but running in source libvirtd context, + * instead of client app context & also adding in tunnel + * handling */ +static int doPeer2PeerMigrate2(struct qemud_driver *driver, + virConnectPtr sconn, + virConnectPtr dconn, + virDomainObjPtr vm, + const char *uri, + unsigned long flags, + const char *dname, + unsigned long resource) { virDomainPtr ddomain = NULL; - int retval = -1; - virStreamPtr st = NULL; - int internalret; + char *uri_out = NULL; + char *cookie = NULL; + char *dom_xml = NULL; + int cookielen = 0, ret; + virErrorPtr orig_err = NULL; + int cancelled; virBitmapPtr qemuCaps = NULL; - - /* - * Tunnelled Migrate Version 2 does not support cookies - * due to missing parameters in the prepareTunnel() API. - */ + virStreamPtr st = NULL; /* check that this qemu version supports the unix migration */ if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch, @@ -1462,75 +1465,45 @@ static int doTunnelMigrate2(struct qemud_driver *driver, qemuReportError(VIR_ERR_INTERNAL_ERROR, _("Cannot extract Qemu version from '%s'"), vm->def->emulator); - goto cleanup; + return -1; } - if (!(st = virStreamNew(dconn, 0))) - goto cleanup; - - qemuDomainObjEnterRemoteWithDriver(driver, vm); - internalret = dconn->driver->domainMigratePrepareTunnel(dconn, st, - flags, dname, - resource, dom_xml); - qemuDomainObjExitRemoteWithDriver(driver, vm); - - if (internalret < 0) - /* domainMigratePrepareTunnel sets the error for us */ - goto cleanup; - - retval = doTunnelMigrate(driver, vm, st, qemuCaps, flags, resource); - dname = dname ? dname : vm->def->name; - qemuDomainObjEnterRemoteWithDriver(driver, vm); - ddomain = dconn->driver->domainMigrateFinish2 - (dconn, dname, NULL, 0, uri, flags, retval); - qemuDomainObjExitRemoteWithDriver(driver, vm); - -cleanup: - qemuCapsFree(qemuCaps); + /* In version 2 of the protocol, the prepare step is slightly + * different. We fetch the domain XML of the source domain + * and pass it to Prepare2. + */ + if (!(dom_xml = qemuDomainFormatXML(driver, vm, + VIR_DOMAIN_XML_SECURE | + VIR_DOMAIN_XML_UPDATE_CPU))) + return -1; - if (ddomain) - virUnrefDomain(ddomain); - - if (st) - /* don't call virStreamFree(), because that resets any pending errors */ - virUnrefStream(st); - return retval; -} + if (vm->state == VIR_DOMAIN_PAUSED) + flags |= VIR_MIGRATE_PAUSED; + VIR_DEBUG("Prepare2 %p", dconn); + if (flags & VIR_MIGRATE_TUNNELLED) { + /* + * Tunnelled Migrate Version 2 does not support cookies + * due to missing parameters in the prepareTunnel() API. + */ -/* This is essentially a simplified re-impl of - * virDomainMigrateVersion2 from libvirt.c, but running in source - * libvirtd context, instead of client app context */ -static int doNonTunnelMigrate2(struct qemud_driver *driver, - virConnectPtr dconn, - virDomainObjPtr vm, - const char *dom_xml, - const char *uri ATTRIBUTE_UNUSED, - unsigned long flags, - const char *dname, - unsigned long resource) -{ - virDomainPtr ddomain = NULL; - int retval = -1; - char *uri_out = NULL; - char *cookie = NULL; - int cookielen = 0; - int rc; + if (!(st = virStreamNew(dconn, 0))) + goto cleanup; - qemuDomainObjEnterRemoteWithDriver(driver, vm); - /* NB we don't pass 'uri' into this, since that's the libvirtd - * URI in this context - so we let dest pick it */ - rc = dconn->driver->domainMigratePrepare2(dconn, - &cookie, - &cookielen, - NULL, /* uri */ - &uri_out, - flags, dname, - resource, dom_xml); - qemuDomainObjExitRemoteWithDriver(driver, vm); - if (rc < 0) - /* domainMigratePrepare2 sets the error for us */ + qemuDomainObjEnterRemoteWithDriver(driver, vm); + ret = dconn->driver->domainMigratePrepareTunnel + (dconn, st, flags, dname, resource, dom_xml); + qemuDomainObjExitRemoteWithDriver(driver, vm); + } else { + qemuDomainObjEnterRemoteWithDriver(driver, vm); + ret = dconn->driver->domainMigratePrepare2 + (dconn, &cookie, &cookielen, NULL, &uri_out, + flags, dname, resource, dom_xml); + qemuDomainObjExitRemoteWithDriver(driver, vm); + } + VIR_FREE(dom_xml); + if (ret == -1) goto cleanup; /* the domain may have shutdown or crashed while we had the locks dropped @@ -1542,37 +1515,73 @@ static int doNonTunnelMigrate2(struct qemud_driver *driver, goto cleanup; } - if (uri_out == NULL) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + if (!(flags & VIR_MIGRATE_TUNNELLED) && + (uri_out == NULL)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, _("domainMigratePrepare2 did not set uri")); - goto cleanup; + cancelled = 1; + goto finish; } - if (doNativeMigrate(driver, vm, uri_out, - cookie, cookielen, - NULL, NULL, /* No out cookie with v2 migration */ - flags, dname, resource) < 0) - goto finish; + /* Perform the migration. The driver isn't supposed to return + * until the migration is complete. + */ + VIR_DEBUG("Perform %p", sconn); + if (flags & VIR_MIGRATE_TUNNELLED) + ret = doTunnelMigrate(driver, vm, st, qemuCaps, flags, resource); + else + ret = doNativeMigrate(driver, vm, uri_out, + cookie, cookielen, + NULL, NULL, /* No out cookie with v2 migration */ + flags, dname, resource); - retval = 0; + /* Perform failed. Make sure Finish doesn't overwrite the error */ + if (ret < 0) + orig_err = virSaveLastError(); + + /* If Perform returns < 0, then we need to cancel the VM + * startup on the destination + */ + cancelled = ret < 0 ? 1 : 0; finish: + /* In version 2 of the migration protocol, we pass the + * status code from the sender to the destination host, + * so it can do any cleanup if the migration failed. + */ dname = dname ? dname : vm->def->name; + VIR_DEBUG("Finish2 %p ret=%d", dconn, ret); qemuDomainObjEnterRemoteWithDriver(driver, vm); ddomain = dconn->driver->domainMigrateFinish2 - (dconn, dname, cookie, cookielen, uri_out, flags, retval); + (dconn, dname, cookie, cookielen, + uri_out ? uri_out : uri, flags, cancelled); qemuDomainObjExitRemoteWithDriver(driver, vm); - if (ddomain) +cleanup: + if (ddomain) { virUnrefDomain(ddomain); + ret = 0; + } else { + ret = -1; + } + qemuCapsFree(qemuCaps); -cleanup: + if (st) + virUnrefStream(st); + + if (orig_err) { + virSetError(orig_err); + virFreeError(orig_err); + } + VIR_FREE(uri_out); VIR_FREE(cookie); - return retval; + + return ret; } static int doPeer2PeerMigrate(struct qemud_driver *driver, + virConnectPtr sconn, virDomainObjPtr vm, const char *uri, unsigned long flags, @@ -1581,7 +1590,6 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver, { int ret = -1; virConnectPtr dconn = NULL; - char *dom_xml; bool p2p; /* the order of operations is important here; we make sure the @@ -1614,22 +1622,10 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver, goto cleanup; } - dom_xml = qemuDomainFormatXML(driver, vm, - VIR_DOMAIN_XML_SECURE | - VIR_DOMAIN_XML_UPDATE_CPU); - if (!dom_xml) { - qemuReportError(VIR_ERR_OPERATION_FAILED, - "%s", _("failed to get domain xml")); - goto cleanup; - } - - if (flags & VIR_MIGRATE_TUNNELLED) - ret = doTunnelMigrate2(driver, dconn, vm, dom_xml, uri, flags, dname, resource); - else - ret = doNonTunnelMigrate2(driver, dconn, vm, dom_xml, uri, flags, dname, resource); + ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm, + uri, flags, dname, resource); cleanup: - VIR_FREE(dom_xml); /* don't call virConnectClose(), because that resets any pending errors */ qemuDomainObjEnterRemoteWithDriver(driver, vm); virUnrefConnect(dconn); @@ -1682,7 +1678,7 @@ int qemuMigrationPerform(struct qemud_driver *driver, goto endjob; } - if (doPeer2PeerMigrate(driver, vm, uri, flags, dname, resource) < 0) + if (doPeer2PeerMigrate(driver, conn, vm, uri, flags, dname, resource) < 0) /* doPeer2PeerMigrate already set the error, so just get out */ goto endjob; } else { -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:49 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:49 +0100 Subject: [libvirt] [PATCH 10/16] Implement migration v3 protocol in QEMU driver In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-11-git-send-email-berrange@redhat.com> Implement the v3 migration protocol, which has two extra steps, 'begin' on the source host and 'confirm' on the source host. All other methods also gain both input and output cookies to allow bi-directional data passing at all stages. The QEMU peer2peer migration method gains another impl to provide the v3 migration. This finally allows migration cookies to work with tunnelled migration, which is required for Spice seemless migration & the lock manager transfer * src/qemu/qemu_driver.c: Wire up migrate v3 APIs * src/qemu/qemu_migration.c, src/qemu/qemu_migration.h: Add begin & confirm methods, and peer2peer impl of v3 --- src/qemu/qemu_driver.c | 318 ++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_migration.c | 364 +++++++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_migration.h | 17 ++- 3 files changed, 675 insertions(+), 24 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f382a24..10e8b91 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -870,6 +870,7 @@ qemudSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature) { switch (feature) { case VIR_DRV_FEATURE_MIGRATION_V2: + case VIR_DRV_FEATURE_MIGRATION_V3: case VIR_DRV_FEATURE_MIGRATION_P2P: return 1; default: @@ -5417,7 +5418,9 @@ qemuDomainEventDeregisterAny(virConnectPtr conn, } -/* Migration support. */ +/******************************************************************* + * Migration Protocol Version 2 + *******************************************************************/ /* Prepare is the first step, and it runs on the destination host. * @@ -5435,6 +5438,15 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn, struct qemud_driver *driver = dconn->privateData; int ret = -1; + virCheckFlags(VIR_MIGRATE_LIVE | + VIR_MIGRATE_PEER2PEER | + VIR_MIGRATE_TUNNELLED | + VIR_MIGRATE_PERSIST_DEST | + VIR_MIGRATE_UNDEFINE_SOURCE | + VIR_MIGRATE_PAUSED | + VIR_MIGRATE_NON_SHARED_DISK | + VIR_MIGRATE_NON_SHARED_INC, -1); + if (!dom_xml) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no domain XML passed")); @@ -5554,7 +5566,7 @@ qemudDomainMigratePerform (virDomainPtr dom, ret = qemuMigrationPerform(driver, dom->conn, vm, uri, cookie, cookielen, NULL, NULL, /* No output cookies in v2 */ - flags, dname, resource); + flags, dname, resource, true); cleanup: qemuDriverUnlock(driver); @@ -5611,6 +5623,296 @@ cleanup: } +/******************************************************************* + * Migration Protocol Version 3 + *******************************************************************/ + +static char * +qemuDomainMigrateBegin3(virDomainPtr domain, + char **cookieout, + int *cookieoutlen, + unsigned long flags, + const char *dname ATTRIBUTE_UNUSED, + unsigned long resource ATTRIBUTE_UNUSED) +{ + struct qemud_driver *driver = domain->conn->privateData; + virDomainObjPtr vm; + char *xml = NULL; + + virCheckFlags(VIR_MIGRATE_LIVE | + VIR_MIGRATE_PEER2PEER | + VIR_MIGRATE_TUNNELLED | + VIR_MIGRATE_PERSIST_DEST | + VIR_MIGRATE_UNDEFINE_SOURCE | + VIR_MIGRATE_PAUSED | + VIR_MIGRATE_NON_SHARED_DISK | + VIR_MIGRATE_NON_SHARED_INC, NULL); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, domain->uuid); + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(domain->uuid, uuidstr); + qemuReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + xml = qemuMigrationBegin(driver, vm, + cookieout, cookieoutlen); + +cleanup: + qemuDriverUnlock(driver); + return xml; +} + +static int +qemuDomainMigratePrepare3(virConnectPtr dconn, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri_in, + char **uri_out, + unsigned long flags, + const char *dname, + unsigned long resource ATTRIBUTE_UNUSED, + const char *dom_xml) +{ + struct qemud_driver *driver = dconn->privateData; + int ret = -1; + + virCheckFlags(VIR_MIGRATE_LIVE | + VIR_MIGRATE_PEER2PEER | + VIR_MIGRATE_TUNNELLED | + VIR_MIGRATE_PERSIST_DEST | + VIR_MIGRATE_UNDEFINE_SOURCE | + VIR_MIGRATE_PAUSED | + VIR_MIGRATE_NON_SHARED_DISK | + VIR_MIGRATE_NON_SHARED_INC, -1); + + *uri_out = NULL; + + qemuDriverLock(driver); + if (flags & VIR_MIGRATE_TUNNELLED) { + /* this is a logical error; we never should have gotten here with + * VIR_MIGRATE_TUNNELLED set + */ + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Tunnelled migration requested but invalid RPC method called")); + goto cleanup; + } + + if (!dom_xml) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("no domain XML passed")); + goto cleanup; + } + + ret = qemuMigrationPrepareDirect(driver, dconn, + cookiein, cookieinlen, + cookieout, cookieoutlen, + uri_in, uri_out, + dname, dom_xml); + +cleanup: + qemuDriverUnlock(driver); + return ret; +} + + +static int +qemuDomainMigratePrepareTunnel3(virConnectPtr dconn, + virStreamPtr st, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + unsigned long flags, + const char *dname, + unsigned long resource ATTRIBUTE_UNUSED, + const char *dom_xml) +{ + struct qemud_driver *driver = dconn->privateData; + int ret = -1; + + virCheckFlags(VIR_MIGRATE_LIVE | + VIR_MIGRATE_PEER2PEER | + VIR_MIGRATE_TUNNELLED | + VIR_MIGRATE_PERSIST_DEST | + VIR_MIGRATE_UNDEFINE_SOURCE | + VIR_MIGRATE_PAUSED | + VIR_MIGRATE_NON_SHARED_DISK | + VIR_MIGRATE_NON_SHARED_INC, -1); + + if (!dom_xml) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("no domain XML passed")); + goto cleanup; + } + if (!(flags & VIR_MIGRATE_TUNNELLED)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("PrepareTunnel called but no TUNNELLED flag set")); + goto cleanup; + } + if (st == NULL) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("tunnelled migration requested but NULL stream passed")); + goto cleanup; + } + + qemuDriverLock(driver); + ret = qemuMigrationPrepareTunnel(driver, dconn, + cookiein, cookieinlen, + cookieout, cookieoutlen, + st, dname, dom_xml); + qemuDriverUnlock(driver); + +cleanup: + return ret; +} + + +static int +qemuDomainMigratePerform3(virDomainPtr dom, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri, + unsigned long flags, + const char *dname, + unsigned long resource) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(VIR_MIGRATE_LIVE | + VIR_MIGRATE_PEER2PEER | + VIR_MIGRATE_TUNNELLED | + VIR_MIGRATE_PERSIST_DEST | + VIR_MIGRATE_UNDEFINE_SOURCE | + VIR_MIGRATE_PAUSED | + VIR_MIGRATE_NON_SHARED_DISK | + VIR_MIGRATE_NON_SHARED_INC, -1); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + 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; + } + + ret = qemuMigrationPerform(driver, dom->conn, vm, + uri, cookiein, cookieinlen, + cookieout, cookieoutlen, + flags, dname, resource, false); + +cleanup: + qemuDriverUnlock(driver); + return ret; +} + + +static int +qemuDomainMigrateFinish3(virConnectPtr dconn, + const char *dname, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri ATTRIBUTE_UNUSED, + unsigned long flags, + int cancelled, + virDomainPtr *newdom) +{ + struct qemud_driver *driver = dconn->privateData; + virDomainObjPtr vm; + virErrorPtr orig_err; + int ret = -1; + + virCheckFlags(VIR_MIGRATE_LIVE | + VIR_MIGRATE_PEER2PEER | + VIR_MIGRATE_TUNNELLED | + VIR_MIGRATE_PERSIST_DEST | + VIR_MIGRATE_UNDEFINE_SOURCE | + VIR_MIGRATE_PAUSED | + VIR_MIGRATE_NON_SHARED_DISK | + VIR_MIGRATE_NON_SHARED_INC, -1); + + /* Migration failed. Save the current error so nothing squashes it */ + orig_err = virSaveLastError(); + + qemuDriverLock(driver); + vm = virDomainFindByName(&driver->domains, dname); + if (!vm) { + qemuReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching name '%s'"), dname); + goto cleanup; + } + + *newdom = qemuMigrationFinish(driver, dconn, vm, + cookiein, cookieinlen, + cookieout, cookieoutlen, + flags, cancelled); + + ret = 0; + +cleanup: + if (orig_err) { + virSetError(orig_err); + virFreeError(orig_err); + } + qemuDriverUnlock(driver); + return ret; +} + +static int +qemuDomainMigrateConfirm3(virDomainPtr domain, + const char *cookiein, + int cookieinlen, + unsigned long flags, + int cancelled) +{ + struct qemud_driver *driver = domain->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(VIR_MIGRATE_LIVE | + VIR_MIGRATE_PEER2PEER | + VIR_MIGRATE_TUNNELLED | + VIR_MIGRATE_PERSIST_DEST | + VIR_MIGRATE_UNDEFINE_SOURCE | + VIR_MIGRATE_PAUSED | + VIR_MIGRATE_NON_SHARED_DISK | + VIR_MIGRATE_NON_SHARED_INC, -1); + + /* Migration failed. Save the current error so nothing squashes it */ + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, domain->uuid); + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(domain->uuid, uuidstr); + qemuReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + ret = qemuMigrationConfirm(driver, domain->conn, vm, + cookiein, cookieinlen, + flags, cancelled, false); + +cleanup: + qemuDriverUnlock(driver); + return ret; +} + + static int qemudNodeDeviceGetPciInfo (virNodeDevicePtr dev, unsigned *domain, @@ -7037,12 +7339,12 @@ static virDriver qemuDriver = { qemuDomainSnapshotDelete, /* domainSnapshotDelete */ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ qemuDomainOpenConsole, /* domainOpenConsole */ - NULL, /* domainMigrateBegin3 */ - NULL, /* domainMigratePrepare3 */ - NULL, /* domainMigratePrepareTunnel3 */ - NULL, /* domainMigratePerform3 */ - NULL, /* domainMigrateFinish3 */ - NULL, /* domainMigrateConfirm3 */ + qemuDomainMigrateBegin3, /* domainMigrateBegin3 */ + qemuDomainMigratePrepare3, /* domainMigratePrepare3 */ + qemuDomainMigratePrepareTunnel3, /* domainMigratePrepareTunnel3 */ + qemuDomainMigratePerform3, /* domainMigratePerform3 */ + qemuDomainMigrateFinish3, /* domainMigrateFinish3 */ + qemuDomainMigrateConfirm3, /* domainMigrateConfirm3 */ }; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 884e26d..fc32a9e 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -773,6 +773,42 @@ qemuDomainMigrateGraphicsRelocate(struct qemud_driver *driver, } +char *qemuMigrationBegin(struct qemud_driver *driver, + virDomainObjPtr vm, + char **cookieout, + int *cookieoutlen) +{ + char *rv = NULL; + qemuMigrationCookiePtr mig = NULL; + + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto cleanup; + } + + if (!qemuMigrationIsAllowed(vm->def)) + goto cleanup; + + if (!(mig = qemuMigrationEatCookie(vm, NULL, 0, 0))) + goto cleanup; + + if (qemuMigrationBakeCookie(mig, driver, vm, + cookieout, cookieoutlen, + 0) < 0) + goto cleanup; + + rv = qemuDomainFormatXML(driver, vm, + VIR_DOMAIN_XML_SECURE | + VIR_DOMAIN_XML_UPDATE_CPU); + +cleanup: + virDomainObjUnlock(vm); + qemuMigrationCookieFree(mig); + return rv; +} + + /* Prepare is the first step, and it runs on the destination host. * * This version starts an empty VM listening on a localhost TCP port, and @@ -1279,6 +1315,10 @@ static int doTunnelMigrate(struct qemud_driver *driver, virDomainObjPtr vm, virStreamPtr st, virBitmapPtr qemuCaps, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, unsigned long flags, unsigned long resource ATTRIBUTE_UNUSED) { @@ -1292,6 +1332,7 @@ static int doTunnelMigrate(struct qemud_driver *driver, char *unixfile = NULL; unsigned int background_flags = QEMU_MONITOR_MIGRATE_BACKGROUND; int ret = -1; + qemuMigrationCookiePtr mig = NULL; if (!qemuCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_UNIX) && !qemuCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_EXEC)) { @@ -1352,6 +1393,13 @@ static int doTunnelMigrate(struct qemud_driver *driver, goto cleanup; } + if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, + QEMU_MIGRATION_COOKIE_GRAPHICS))) + goto cleanup; + + if (qemuDomainMigrateGraphicsRelocate(driver, vm, mig) < 0) + VIR_WARN0("unable to provide data for graphics client relocation"); + /* 3. start migration on source */ qemuDomainObjEnterMonitorWithDriver(driver, vm); @@ -1417,6 +1465,10 @@ static int doTunnelMigrate(struct qemud_driver *driver, ret = doTunnelSendAll(st, client_sock); + if (ret == 0 && + qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0) + VIR_WARN0("Unable to encode migration cookie"); + cancel: if (ret != 0 && virDomainObjIsActive(vm)) { qemuDomainObjEnterMonitorWithDriver(driver, vm); @@ -1425,6 +1477,7 @@ cancel: } cleanup: + qemuMigrationCookieFree(mig); VIR_FORCE_CLOSE(client_sock); VIR_FORCE_CLOSE(qemu_sock); if (unixfile) { @@ -1528,7 +1581,9 @@ static int doPeer2PeerMigrate2(struct qemud_driver *driver, */ VIR_DEBUG("Perform %p", sconn); if (flags & VIR_MIGRATE_TUNNELLED) - ret = doTunnelMigrate(driver, vm, st, qemuCaps, flags, resource); + ret = doTunnelMigrate(driver, vm, st, qemuCaps, + NULL, 0, NULL, NULL, + flags, resource); else ret = doNativeMigrate(driver, vm, uri_out, cookie, cookielen, @@ -1580,6 +1635,191 @@ cleanup: } +/* This is essentially a re-impl of virDomainMigrateVersion3 + * from libvirt.c, but running in source libvirtd context, + * instead of client app context & also adding in tunnel + * handling */ +static int doPeer2PeerMigrate3(struct qemud_driver *driver, + virConnectPtr sconn, + virConnectPtr dconn, + virDomainObjPtr vm, + const char *uri, + unsigned long flags, + const char *dname, + unsigned long resource) +{ + virDomainPtr ddomain = NULL; + char *uri_out = NULL; + char *cookiein = NULL; + char *cookieout = NULL; + char *dom_xml = NULL; + int cookieinlen = 0; + int cookieoutlen = 0; + int ret = -1; + virErrorPtr orig_err = NULL; + int cancelled; + virBitmapPtr qemuCaps = NULL; + virStreamPtr st = NULL; + + /* check that this qemu version supports the unix migration */ + if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch, + NULL, &qemuCaps) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("Cannot extract Qemu version from '%s'"), + vm->def->emulator); + return -1; + } + + VIR_DEBUG("Begin3 %p", sconn); + dom_xml = qemuMigrationBegin(driver, vm, + &cookieout, &cookieoutlen); + if (!dom_xml) + goto cleanup; + + if (vm->state == VIR_DOMAIN_PAUSED) + flags |= VIR_MIGRATE_PAUSED; + + VIR_DEBUG("Prepare3 %p", dconn); + cookiein = cookieout; + cookieinlen = cookieoutlen; + cookieout = NULL; + cookieoutlen = 0; + if (flags & VIR_MIGRATE_TUNNELLED) { + /* + * Tunnelled Migrate Version 2 does not support cookies + * due to missing parameters in the prepareTunnel() API. + */ + + if (!(st = virStreamNew(dconn, 0))) + goto cleanup; + + qemuDomainObjEnterRemoteWithDriver(driver, vm); + ret = dconn->driver->domainMigratePrepareTunnel3 + (dconn, st, cookiein, cookieinlen, + &cookieout, &cookieoutlen, + flags, dname, resource, dom_xml); + qemuDomainObjExitRemoteWithDriver(driver, vm); + } else { + qemuDomainObjEnterRemoteWithDriver(driver, vm); + ret = dconn->driver->domainMigratePrepare3 + (dconn, cookiein, cookieinlen, &cookieout, &cookieoutlen, + NULL, &uri_out, flags, dname, resource, dom_xml); + qemuDomainObjExitRemoteWithDriver(driver, vm); + } + VIR_FREE(dom_xml); + if (ret == -1) + goto cleanup; + + if (!(flags & VIR_MIGRATE_TUNNELLED) && + (uri_out == NULL)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("domainMigratePrepare3 did not set uri")); + cancelled = 1; + goto finish; + } + + /* Perform the migration. The driver isn't supposed to return + * until the migration is complete. The src VM should remain + * running, but in paused state until the destination can + * confirm migration completion. + */ + VIR_DEBUG("Perform3 %p uri=%s", sconn, uri_out); + VIR_FREE(cookiein); + cookiein = cookieout; + cookieinlen = cookieoutlen; + cookieout = NULL; + cookieoutlen = 0; + if (flags & VIR_MIGRATE_TUNNELLED) + ret = doTunnelMigrate(driver, vm, st, qemuCaps, + cookiein, cookieinlen, + &cookieout, &cookieoutlen, + flags, resource); + else + ret = doNativeMigrate(driver, vm, uri_out, + cookiein, cookieinlen, + &cookieout, &cookieoutlen, + flags, dname, resource); + + /* Perform failed. Make sure Finish doesn't overwrite the error */ + if (ret < 0) + orig_err = virSaveLastError(); + + /* If Perform returns < 0, then we need to cancel the VM + * startup on the destination + */ + cancelled = ret < 0 ? 1 : 0; + +finish: + /* + * The status code from the source is passed to the destination. + * The dest can cleanup in the source indicated it failed to + * send all migration data. Returns NULL for ddomain if + * the dest was unable to complete migration. + */ + VIR_DEBUG("Finish3 %p ret=%d", dconn, ret); + VIR_FREE(cookiein); + cookiein = cookieout; + cookieinlen = cookieoutlen; + cookieout = NULL; + cookieoutlen = 0; + dname = dname ? dname : vm->def->name; + qemuDomainObjEnterRemoteWithDriver(driver, vm); + ret = dconn->driver->domainMigrateFinish3 + (dconn, dname, cookiein, cookieinlen, &cookieout, &cookieoutlen, + uri_out ? uri_out : uri, flags, cancelled, &ddomain); + qemuDomainObjExitRemoteWithDriver(driver, vm); + + /* If ret is 0 then 'ddomain' indicates whether the VM is + * running on the dest. If not running, we can restart + * the source. If ret is -1, we can't be sure what happened + * to the VM on the dest, thus the only safe option is to + * kill the VM on the source, even though that may leave + * no VM at all on either host. + */ + cancelled = ret == 0 && ddomain == NULL ? 1 : 0; + + /* + * If cancelled, then src VM will be restarted, else + * it will be killed + */ + VIR_DEBUG("Confirm3 %p ret=%d vm=%p", sconn, ret, vm); + VIR_FREE(cookiein); + cookiein = cookieout; + cookieinlen = cookieoutlen; + cookieout = NULL; + cookieoutlen = 0; + ret = qemuMigrationConfirm(driver, sconn, vm, + cookiein, cookieinlen, + flags, cancelled, true); + /* If Confirm3 returns -1, there's nothing more we can + * do, but fortunately worst case is that there is a + * domain left in 'paused' state on source. + */ + + cleanup: + if (ddomain) { + virUnrefDomain(ddomain); + ret = 0; + } else { + ret = -1; + } + qemuCapsFree(qemuCaps); + + if (st) + virUnrefStream(st); + + if (orig_err) { + virSetError(orig_err); + virFreeError(orig_err); + } + VIR_FREE(uri_out); + VIR_FREE(cookiein); + VIR_FREE(cookieout); + + return ret; +} + + static int doPeer2PeerMigrate(struct qemud_driver *driver, virConnectPtr sconn, virDomainObjPtr vm, @@ -1591,6 +1831,7 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver, int ret = -1; virConnectPtr dconn = NULL; bool p2p; + bool v3; /* the order of operations is important here; we make sure the * destination side is completely setup before we touch the source @@ -1608,7 +1849,10 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver, qemuDomainObjEnterRemoteWithDriver(driver, vm); p2p = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn, VIR_DRV_FEATURE_MIGRATION_P2P); + v3 = VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn, + VIR_DRV_FEATURE_MIGRATION_V3); qemuDomainObjExitRemoteWithDriver(driver, vm); + if (!p2p) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Destination libvirt does not support peer-to-peer migration protocol")); @@ -1622,8 +1866,12 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver, goto cleanup; } - ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm, - uri, flags, dname, resource); + if (v3) + ret = doPeer2PeerMigrate3(driver, sconn, dconn, vm, + uri, flags, dname, resource); + else + ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm, + uri, flags, dname, resource); cleanup: /* don't call virConnectClose(), because that resets any pending errors */ @@ -1645,7 +1893,8 @@ int qemuMigrationPerform(struct qemud_driver *driver, int *cookieoutlen, unsigned long flags, const char *dname, - unsigned long resource) + unsigned long resource, + bool killOnFinish) { virDomainEventPtr event = NULL; int ret = -1; @@ -1689,18 +1938,20 @@ int qemuMigrationPerform(struct qemud_driver *driver, } /* Clean up the source domain. */ - qemuProcessStop(driver, vm, 1); - qemuAuditDomainStop(vm, "migrated"); - resume = 0; + if (killOnFinish) { + qemuProcessStop(driver, vm, 1); + qemuAuditDomainStop(vm, "migrated"); + resume = 0; - event = virDomainEventNewFromObj(vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_MIGRATED); - if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) { - virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm); - if (qemuDomainObjEndJob(vm) > 0) - virDomainRemoveInactive(&driver->domains, vm); - vm = NULL; + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_MIGRATED); + if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) { + virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm); + if (qemuDomainObjEndJob(vm) > 0) + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } } ret = 0; @@ -1906,6 +2157,89 @@ cleanup: return dom; } + +int qemuMigrationConfirm(struct qemud_driver *driver, + virConnectPtr conn, + virDomainObjPtr vm, + const char *cookiein, + int cookieinlen, + unsigned int flags, + int retcode, + bool skipJob) +{ + qemuMigrationCookiePtr mig; + virDomainEventPtr event = NULL; + int rv = -1; + + if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0))) + return -1; + + if (!skipJob && + qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + goto endjob; + } + + /* Did the migration go as planned? If yes, kill off the + * domain object, but if no, resume CPUs + */ + if (retcode == 0) { + qemuProcessStop(driver, vm, 1); + qemuAuditDomainStop(vm, "migrated"); + + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_MIGRATED); + if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) { + virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm); + if (qemuDomainObjEndJob(vm) > 0) + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + } else { + + /* run 'cont' on the destination, which allows migration on qemu + * >= 0.10.6 to work properly. This isn't strictly necessary on + * older qemu's, but it also doesn't hurt anything there + */ + if (qemuProcessStartCPUs(driver, vm, conn) < 0) { + if (virGetLastError() == NULL) + qemuReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("resume operation failed")); + goto endjob; + } + + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_RESUMED, + VIR_DOMAIN_EVENT_RESUMED_MIGRATED); + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) { + VIR_WARN("Failed to save status on vm %s", vm->def->name); + goto endjob; + } + } + + qemuMigrationCookieFree(mig); + rv = 0; + +endjob: + if (vm && + !skipJob && + qemuDomainObjEndJob(vm) == 0) + vm = NULL; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); + return rv; +} + + /* Helper function called while driver lock is held and vm is active. */ int qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm, diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index 11571e7..42d8a42 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -32,6 +32,11 @@ int qemuMigrationSetOffline(struct qemud_driver *driver, int qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm); +char *qemuMigrationBegin(struct qemud_driver *driver, + virDomainObjPtr vm, + char **cookieout, + int *cookieoutlen); + int qemuMigrationPrepareTunnel(struct qemud_driver *driver, virConnectPtr dconn, const char *cookiein, @@ -63,7 +68,8 @@ int qemuMigrationPerform(struct qemud_driver *driver, int *cookieoutlen, unsigned long flags, const char *dname, - unsigned long resource); + unsigned long resource, + bool killOnFinish); virDomainPtr qemuMigrationFinish(struct qemud_driver *driver, virConnectPtr dconn, @@ -75,6 +81,15 @@ virDomainPtr qemuMigrationFinish(struct qemud_driver *driver, unsigned long flags, int retcode); +int qemuMigrationConfirm(struct qemud_driver *driver, + virConnectPtr conn, + virDomainObjPtr vm, + const char *cookiein, + int cookieinlen, + unsigned int flags, + int retcode, + bool skipJob); + int qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm, virBitmapPtr qemuCaps, -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:50 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:50 +0100 Subject: [libvirt] [PATCH 11/16] Refactor migration completion loop to allow code reuse In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-12-git-send-email-berrange@redhat.com> The qemuMigrationWaitForCompletion method contains a loop which repeatedly queries QEMU to check migration progress, and also processes job signals (pause, setspeed, setbandwidth, cancel). The tunnelled migration loop does not currently support this functionality, but should. Refactor the code to allow it to be used with tunnelled migration. --- src/qemu/qemu_migration.c | 252 +++++++++++++++++++++++++-------------------- 1 files changed, 142 insertions(+), 110 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index fc32a9e..3cff4d7 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -583,14 +583,148 @@ qemuMigrationSetOffline(struct qemud_driver *driver, } -int -qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) +static int +qemuMigrationProcessJobSignals(struct qemud_driver *driver, + virDomainObjPtr vm, + const char *job) { + qemuDomainObjPrivatePtr priv = vm->privateData; + int ret = -1; + + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, _("%s: %s"), + job, _("guest unexpectedly quit")); + return -1; + } + + if (priv->jobSignals & QEMU_JOB_SIGNAL_CANCEL) { + priv->jobSignals ^= QEMU_JOB_SIGNAL_CANCEL; + VIR_DEBUG0("Cancelling job at client request"); + qemuDomainObjEnterMonitorWithDriver(driver, vm); + ret = qemuMonitorMigrateCancel(priv->mon); + qemuDomainObjExitMonitorWithDriver(driver, vm); + if (ret < 0) { + VIR_WARN0("Unable to cancel job"); + } + } else if (priv->jobSignals & QEMU_JOB_SIGNAL_SUSPEND) { + priv->jobSignals ^= QEMU_JOB_SIGNAL_SUSPEND; + VIR_DEBUG0("Pausing domain for non-live migration"); + if (qemuMigrationSetOffline(driver, vm) < 0) + VIR_WARN0("Unable to pause domain"); + } else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME) { + unsigned long long ms = priv->jobSignalsData.migrateDowntime; + + priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME; + priv->jobSignalsData.migrateDowntime = 0; + VIR_DEBUG("Setting migration downtime to %llums", ms); + qemuDomainObjEnterMonitorWithDriver(driver, vm); + ret = qemuMonitorSetMigrationDowntime(priv->mon, ms); + qemuDomainObjExitMonitorWithDriver(driver, vm); + if (ret < 0) + VIR_WARN0("Unable to set migration downtime"); + } else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_SPEED) { + unsigned long bandwidth = priv->jobSignalsData.migrateBandwidth; + + priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_SPEED; + priv->jobSignalsData.migrateBandwidth = 0; + VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth); + qemuDomainObjEnterMonitorWithDriver(driver, vm); + ret = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth); + qemuDomainObjExitMonitorWithDriver(driver, vm); + if (ret < 0) + VIR_WARN0("Unable to set migration speed"); + } else { + ret = 0; + } + + return ret; +} + + +static int +qemuMigrationUpdateJobStatus(struct qemud_driver *driver, + virDomainObjPtr vm, + const char *job) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; int ret = -1; int status; unsigned long long memProcessed; unsigned long long memRemaining; unsigned long long memTotal; + struct timeval now; + + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, _("%s: %s"), + job, _("guest unexpectedly quit")); + return -1; + } + + qemuDomainObjEnterMonitorWithDriver(driver, vm); + ret = qemuMonitorGetMigrationStatus(priv->mon, + &status, + &memProcessed, + &memRemaining, + &memTotal); + qemuDomainObjExitMonitorWithDriver(driver, vm); + + if (ret < 0) { + priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; + return -1; + } + + if (gettimeofday(&now, NULL) < 0) { + priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; + virReportSystemError(errno, "%s", + _("cannot get time of day")); + return -1; + } + priv->jobInfo.timeElapsed = timeval_to_ms(now) - priv->jobStart; + + switch (status) { + case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE: + priv->jobInfo.type = VIR_DOMAIN_JOB_NONE; + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("%s: %s"), job, _("is not active")); + break; + + case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE: + priv->jobInfo.dataTotal = memTotal; + priv->jobInfo.dataRemaining = memRemaining; + priv->jobInfo.dataProcessed = memProcessed; + + priv->jobInfo.memTotal = memTotal; + priv->jobInfo.memRemaining = memRemaining; + priv->jobInfo.memProcessed = memProcessed; + + ret = 0; + break; + + case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED: + priv->jobInfo.type = VIR_DOMAIN_JOB_COMPLETED; + ret = 0; + break; + + case QEMU_MONITOR_MIGRATION_STATUS_ERROR: + priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("%s: %s"), job, _("unexpectedly failed")); + break; + + case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED: + priv->jobInfo.type = VIR_DOMAIN_JOB_CANCELLED; + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("%s: %s"), job, _("canceled by client")); + break; + } + + return ret; +} + + +int +qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) +{ qemuDomainObjPrivatePtr priv = vm->privateData; priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED; @@ -598,8 +732,6 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) while (priv->jobInfo.type == VIR_DOMAIN_JOB_UNBOUNDED) { /* Poll every 50ms for progress & to allow cancellation */ struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull }; - struct timeval now; - int rc; const char *job; switch (priv->jobActive) { @@ -616,115 +748,12 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) job = _("job"); } - - if (!virDomainObjIsActive(vm)) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, _("%s: %s"), - job, _("guest unexpectedly quit")); - goto cleanup; - } - - if (priv->jobSignals & QEMU_JOB_SIGNAL_CANCEL) { - priv->jobSignals ^= QEMU_JOB_SIGNAL_CANCEL; - VIR_DEBUG0("Cancelling job at client request"); - qemuDomainObjEnterMonitorWithDriver(driver, vm); - rc = qemuMonitorMigrateCancel(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); - if (rc < 0) { - VIR_WARN0("Unable to cancel job"); - } - } else if (priv->jobSignals & QEMU_JOB_SIGNAL_SUSPEND) { - priv->jobSignals ^= QEMU_JOB_SIGNAL_SUSPEND; - VIR_DEBUG0("Pausing domain for non-live migration"); - if (qemuMigrationSetOffline(driver, vm) < 0) - VIR_WARN0("Unable to pause domain"); - } else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME) { - unsigned long long ms = priv->jobSignalsData.migrateDowntime; - - priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME; - priv->jobSignalsData.migrateDowntime = 0; - VIR_DEBUG("Setting migration downtime to %llums", ms); - qemuDomainObjEnterMonitorWithDriver(driver, vm); - rc = qemuMonitorSetMigrationDowntime(priv->mon, ms); - qemuDomainObjExitMonitorWithDriver(driver, vm); - if (rc < 0) - VIR_WARN0("Unable to set migration downtime"); - } else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_SPEED) { - unsigned long bandwidth = priv->jobSignalsData.migrateBandwidth; - - priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_SPEED; - priv->jobSignalsData.migrateBandwidth = 0; - VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth); - qemuDomainObjEnterMonitorWithDriver(driver, vm); - rc = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth); - qemuDomainObjExitMonitorWithDriver(driver, vm); - if (rc < 0) - VIR_WARN0("Unable to set migration speed"); - } - - /* Repeat check because the job signals might have caused - * guest to die - */ - if (!virDomainObjIsActive(vm)) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, _("%s: %s"), - job, _("guest unexpectedly quit")); + if (qemuMigrationProcessJobSignals(driver, vm, job) < 0) goto cleanup; - } - qemuDomainObjEnterMonitorWithDriver(driver, vm); - rc = qemuMonitorGetMigrationStatus(priv->mon, - &status, - &memProcessed, - &memRemaining, - &memTotal); - qemuDomainObjExitMonitorWithDriver(driver, vm); - - if (rc < 0) { - priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; + if (qemuMigrationUpdateJobStatus(driver, vm, job) < 0) goto cleanup; - } - - if (gettimeofday(&now, NULL) < 0) { - priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; - virReportSystemError(errno, "%s", - _("cannot get time of day")); - goto cleanup; - } - priv->jobInfo.timeElapsed = timeval_to_ms(now) - priv->jobStart; - - switch (status) { - case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE: - priv->jobInfo.type = VIR_DOMAIN_JOB_NONE; - qemuReportError(VIR_ERR_OPERATION_FAILED, - _("%s: %s"), job, _("is not active")); - break; - case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE: - priv->jobInfo.dataTotal = memTotal; - priv->jobInfo.dataRemaining = memRemaining; - priv->jobInfo.dataProcessed = memProcessed; - - priv->jobInfo.memTotal = memTotal; - priv->jobInfo.memRemaining = memRemaining; - priv->jobInfo.memProcessed = memProcessed; - break; - - case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED: - priv->jobInfo.type = VIR_DOMAIN_JOB_COMPLETED; - ret = 0; - break; - - case QEMU_MONITOR_MIGRATION_STATUS_ERROR: - priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; - qemuReportError(VIR_ERR_OPERATION_FAILED, - _("%s: %s"), job, _("unexpectedly failed")); - break; - - case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED: - priv->jobInfo.type = VIR_DOMAIN_JOB_CANCELLED; - qemuReportError(VIR_ERR_OPERATION_FAILED, - _("%s: %s"), job, _("canceled by client")); - break; - } virDomainObjUnlock(vm); qemuDriverUnlock(driver); @@ -736,7 +765,10 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) } cleanup: - return ret; + if (priv->jobInfo.type == VIR_DOMAIN_JOB_COMPLETED) + return 0; + else + return -1; } -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:51 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:51 +0100 Subject: [libvirt] [PATCH 12/16] Make tunnelled migration honour job signals & update job status In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-13-git-send-email-berrange@redhat.com> Rewrite the doTunnelSendAll method so that it will process job signals, and periodically ask QEMU for updated job status * src/qemu/qemu_migration.c: Honour job signals/status during tunnelled migration --- src/qemu/qemu_migration.c | 72 +++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 3cff4d7..4fb4c83 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1299,11 +1299,16 @@ cleanup: #define TUNNEL_SEND_BUF_SIZE 65536 -static int doTunnelSendAll(virStreamPtr st, +static int doTunnelSendAll(struct qemud_driver *driver, + virDomainObjPtr vm, + virStreamPtr st, int sock) { + qemuDomainObjPrivatePtr priv = vm->privateData; char *buffer; int nbytes = TUNNEL_SEND_BUF_SIZE; + struct timeval now, then; + unsigned long long delta; if (VIR_ALLOC_N(buffer, TUNNEL_SEND_BUF_SIZE) < 0) { virReportOOMError(); @@ -1311,13 +1316,28 @@ static int doTunnelSendAll(virStreamPtr st, return -1; } - /* XXX should honour the 'resource' parameter here */ - for (;;) { + if (gettimeofday(&then, NULL) < 0) { + virReportSystemError(errno, "%s", + _("cannot get time of day")); + virStreamAbort(st); + return -1; + } + + priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED; + + while (priv->jobInfo.type == VIR_DOMAIN_JOB_UNBOUNDED) { + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); nbytes = saferead(sock, buffer, nbytes); + qemuDriverLock(driver); + virDomainObjLock(vm); + if (nbytes < 0) { virReportSystemError(errno, "%s", _("tunnelled migration failed to read from qemu")); + qemuDomainObjEnterRemoteWithDriver(driver, vm); virStreamAbort(st); + qemuDomainObjExitRemoteWithDriver(driver, vm); VIR_FREE(buffer); return -1; } @@ -1325,19 +1345,56 @@ static int doTunnelSendAll(virStreamPtr st, /* EOF; get out of here */ break; + qemuDomainObjEnterRemoteWithDriver(driver, vm); if (virStreamSend(st, buffer, nbytes) < 0) { + qemuDomainObjExitRemoteWithDriver(driver, vm); qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Failed to write migration data to remote libvirtd")); VIR_FREE(buffer); return -1; } + qemuDomainObjExitRemoteWithDriver(driver, vm); + + /* Process job signals on every loop */ + if (qemuMigrationProcessJobSignals(driver, vm, "migration job") < 0) { + virStreamAbort(st); + return -1; + } + + + if (gettimeofday(&now, NULL) < 0) { + priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; + virReportSystemError(errno, "%s", + _("cannot get time of day")); + virStreamAbort(st); + return -1; + } + + delta = ((now.tv_sec * 1000ull) + (now.tv_usec / 1000ull)) - + ((then.tv_sec * 1000ull) + (then.tv_usec / 1000ull)); + + /* Only update QEMU monitor status once a second, since we + * detect failure quickly enough already, via the EOF on the + * pipe we're reading from */ + if (delta > 1000) { + then = now; + + if (qemuMigrationUpdateJobStatus(driver, vm, "migration job") < 0) { + virStreamAbort(st); + return -1; + } + } } VIR_FREE(buffer); - if (virStreamFinish(st) < 0) + qemuDomainObjEnterRemoteWithDriver(driver, vm); + if (virStreamFinish(st) < 0) { + qemuDomainObjExitRemoteWithDriver(driver, vm); /* virStreamFinish set the error for us */ return -1; + } + qemuDomainObjExitRemoteWithDriver(driver, vm); return 0; } @@ -1434,6 +1491,11 @@ static int doTunnelMigrate(struct qemud_driver *driver, /* 3. start migration on source */ qemuDomainObjEnterMonitorWithDriver(driver, vm); + if (resource > 0 && + qemuMonitorSetMigrationSpeed(priv->mon, resource) < 0) { + qemuDomainObjExitMonitorWithDriver(driver, vm); + goto cleanup; + } if (flags & VIR_MIGRATE_NON_SHARED_DISK) background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK; @@ -1495,7 +1557,7 @@ static int doTunnelMigrate(struct qemud_driver *driver, goto cancel; } - ret = doTunnelSendAll(st, client_sock); + ret = doTunnelSendAll(driver, vm, st, client_sock); if (ret == 0 && qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0) -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:52 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:52 +0100 Subject: [libvirt] [PATCH 13/16] Ensure we always read a full buffer in tunnelled migration In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-14-git-send-email-berrange@redhat.com> The 'nbytes' variable was not re-initialized to the buffer size on each iteration of the tunnelled migration loop. While saferead() will ensure a full read, except on EOF, it is clearer to use the real buffer size * src/qemu/qemu_migration.c: Always read full buffer of data --- src/qemu/qemu_migration.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 4fb4c83..dd19e55 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1328,7 +1328,7 @@ static int doTunnelSendAll(struct qemud_driver *driver, while (priv->jobInfo.type == VIR_DOMAIN_JOB_UNBOUNDED) { virDomainObjUnlock(vm); qemuDriverUnlock(driver); - nbytes = saferead(sock, buffer, nbytes); + nbytes = saferead(sock, buffer, TUNNEL_SEND_BUF_SIZE); qemuDriverLock(driver); virDomainObjLock(vm); -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:53 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:53 +0100 Subject: [libvirt] [PATCH 14/16] Close all sockets before cancelling QEMU migration In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-15-git-send-email-berrange@redhat.com> Cancelling the QEMU migration may cause QEMU to flush pending data on the migration socket. This may in turn block QEMU if nothing reads from the other end of the socket. Closing the socket before cancelling QEMU migration avoids this possible deadlock. * src/qemu/qemu_migration.c: Close sockets before cancelling migration on failure --- src/qemu/qemu_migration.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index dd19e55..39b3749 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1565,6 +1565,8 @@ static int doTunnelMigrate(struct qemud_driver *driver, cancel: if (ret != 0 && virDomainObjIsActive(vm)) { + VIR_FORCE_CLOSE(client_sock); + VIR_FORCE_CLOSE(qemu_sock); qemuDomainObjEnterMonitorWithDriver(driver, vm); qemuMonitorMigrateCancel(priv->mon); qemuDomainObjExitMonitorWithDriver(driver, vm); -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:54 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:54 +0100 Subject: [libvirt] [PATCH 15/16] Don't overwrite error when stream send fails In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-16-git-send-email-berrange@redhat.com> virStreamSend already sets an error message, so don't overwrite it * src/qemu/qemu_migration.c: Remove bogus error report --- src/qemu/qemu_migration.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 39b3749..4791bd4 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1348,8 +1348,6 @@ static int doTunnelSendAll(struct qemud_driver *driver, qemuDomainObjEnterRemoteWithDriver(driver, vm); if (virStreamSend(st, buffer, nbytes) < 0) { qemuDomainObjExitRemoteWithDriver(driver, vm); - qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("Failed to write migration data to remote libvirtd")); VIR_FREE(buffer); return -1; } -- 1.7.4.4 From berrange at redhat.com Thu Apr 21 16:32:55 2011 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 21 Apr 2011 17:32:55 +0100 Subject: [libvirt] [PATCH 16/16] Improve error message when XDR marshalling fails In-Reply-To: <1303403575-20220-1-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> Message-ID: <1303403575-20220-17-git-send-email-berrange@redhat.com> When failing to marshall an XDR message, include the full program/version/status/proc/type info, to allow easier debugging & diagnosis of the problem. * src/remote/remote_driver.c: Improve error when marshalling fails --- src/remote/remote_driver.c | 12 +++++++++--- 1 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index bed6a15..118be3a 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -10166,7 +10166,9 @@ prepareCall(struct private_data *priv, } if (!(*args_filter) (&xdr, args)) { - remoteError(VIR_ERR_RPC, "%s", _("marshalling args")); + remoteError(VIR_ERR_RPC, + _("Unable to marshall arguments for program %d version %d procedure %d type %d status %d"), + hdr.prog, hdr.vers, hdr.proc, hdr.type, hdr.status); goto error; } @@ -10622,7 +10624,9 @@ processCallDispatchReply(virConnectPtr conn ATTRIBUTE_UNUSED, switch (hdr->status) { case REMOTE_OK: if (!(*thecall->ret_filter) (xdr, thecall->ret)) { - remoteError(VIR_ERR_RPC, "%s", _("unmarshalling ret")); + remoteError(VIR_ERR_RPC, + _("Unable to marshall reply for program %d version %d procedure %d type %d status %d"), + hdr->prog, hdr->vers, hdr->proc, hdr->type, hdr->status); return -1; } thecall->mode = REMOTE_MODE_COMPLETE; @@ -10631,7 +10635,9 @@ processCallDispatchReply(virConnectPtr conn ATTRIBUTE_UNUSED, case REMOTE_ERROR: memset (&thecall->err, 0, sizeof thecall->err); if (!xdr_remote_error (xdr, &thecall->err)) { - remoteError(VIR_ERR_RPC, "%s", _("unmarshalling remote_error")); + remoteError(VIR_ERR_RPC, + _("Unable to marshall error for program %d version %d procedure %d type %d status %d"), + hdr->prog, hdr->vers, hdr->proc, hdr->type, hdr->status); return -1; } thecall->mode = REMOTE_MODE_ERROR; -- 1.7.4.4 From eblake at redhat.com Thu Apr 21 16:47:30 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 21 Apr 2011 10:47:30 -0600 Subject: [libvirt] [PATCH 01/16] Remove bogus assert() from migration code In-Reply-To: <1303403575-20220-2-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> <1303403575-20220-2-git-send-email-berrange@redhat.com> Message-ID: <4DB05FA2.3050206@redhat.com> On 04/21/2011 10:32 AM, Daniel P. Berrange wrote: > assert() is forbidden in libvirt code, and these two cases would > in fact never execute due to earlier error checks. > > * src/libvirt.c: Remove assert() usage > --- > src/libvirt.c | 3 --- > 1 files changed, 0 insertions(+), 3 deletions(-) ACK. Should we add a filter in cfg.mk to have 'make syntax-check' enforce this point? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From benve at cisco.com Thu Apr 21 18:16:30 2011 From: benve at cisco.com (Christian Benvenuti (benve)) Date: Thu, 21 Apr 2011 13:16:30 -0500 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <20110421114358.GC25985@redhat.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com> <1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> <4DAF665B.2070500@linux.vnet.ibm.com> <184D23435BECB444AB6B9D4630C8EC830190B4BE@XMB-RCD-303.cisco.com> <4DB016FA.7070509@linux.vnet.ibm.com> <20110421114358.GC25985@redhat.com> Message-ID: <184D23435BECB444AB6B9D4630C8EC830190B671@XMB-RCD-303.cisco.com> > -----Original Message----- > From: Daniel P. Berrange [mailto:berrange at redhat.com] > Sent: Thursday, April 21, 2011 4:44 AM > To: Stefan Berger > Cc: Christian Benvenuti (benve); eblake at redhat.com; laine at laine.org; > chrisw at redhat.com; libvir-list at redhat.com; David Wang (dwang2); Roopa > Prabhu (roprabhu); Gerhard Stenzel; Jens Osterkamp; Anthony Liguori > Subject: Re: [libvirt] [PATCH 3/6] Introduce yet another migration > version in API. > > On Thu, Apr 21, 2011 at 07:37:30AM -0400, Stefan Berger wrote: > > On 04/20/2011 11:38 PM, Christian Benvenuti (benve) wrote: > > >>On 04/20/2011 05:28 PM, Christian Benvenuti (benve) wrote: > > >>>Daniel, > > >>> I looked at the patch-set you sent out on the 2/9/11 > > >>> > > >>> [libvirt] [PATCH 0/6] Introduce a new migration protocol > > >>> to QEMU driver > > >>> http://www.mail-archive.com/libvir- > list at redhat.com/msg33223.html > > >>> > > >>>What is the status of this new migration protocol? > > >>>Is there any pending issue blocking its integration? > > >>> > > >>>I would like to propose an RFC enhancement to the migration > > >>>algorithm. > > >>> > > >>>Here is a quick summary of the proposal/idea. > > >>> > > >>>- finer control on migration result > > >>> > > >>> - possibility of specifying what features cannot fail > > >>> their initialization on the dst host during migration. > > >>> Migration should not succeed if any of them fails. > > >>> - optional: each one of those features should be able to > > >>> provide a deinit function to cleanup resources > > >>> on the dst host if migration fails. > > >>> > > >>>This functionality would come useful for the (NIC) set port > > >>>profile feature VDP (802.1Qbg/1Qbh), but what I propose is > > >>>a generic config option / API that can be used by any feature. > > >>> > > >>>And now the details. > > >>> > > >>>---------------------------------------------- > > >>>enhancement: finer control on migration result > > >>>---------------------------------------------- > > >>> > > >>>There are different reasons why a VM may need (or be forced) to > > >>>migrate. > > >>>You can classify the types of the migrations also based on > > >>>different semantics. > > >>>For simplicity I'll classify them into two categories, based on > > >>>how important it is for the VM to migrate as fast as possible: > > >>> > > >>>(1) It IS important > > >>> > > >>> In this case, whether the VM will not be able to (temporary) > > >>> make use of certain resources (for example the network) on > the > > >>> dst host, is not that important, because the completion of > the > > >>> migration is considered higher priority. > > >>> A possible scenario could be a server that must migrate ASAP > > >>> because of a disaster/emergency. > > >>> > > >>>(2) It IS NOT important > > >>> > > >>> I can think of a VM whose applications/servers need a network > > >>> connection in order to work properly. Loosing such network > > >>> connectivity as a consequence of a migration would not be > > >>> acceptable (or highly undesirable). > > >>> > > >>>Given the case (2) above, I have a comment about the Finish > > >>>step, with regards to the port profile (VDP) codepath. > > >>> > > >>>The call to > > >>> > > >>> qemuMigrationVPAssociatePortProfile > > >>> > > >>>in > > >>> qemuMigrationFinish > > >>> > > >>>can fail, but its result (success or failure) does not influence > > >>>the result of the migration Finish step (it was already like this > > >>>in migration V2). > > >>I *believe* the underlying problem is Qemu's switch-over. Once Qemu > > >>decides that the migration was successful, Qemu on the source side > > >dies > > >>and continues running on the destination side. I don't think there > are > > >>more handshakes foreseen with higher layers that this could be > > >reversed > > >>or the switch-over delayed, but correct me if I am wrong... > > >Actually I think this is not what happens in migration V3. > > >My understanding is this: > > > > > >- the qemu cmdline built by Libvirt on the dst host during Prepare3 > > > includes the "-S" option (ie no autostart) > > > > > >- the VM on the dst host does not start running until libvirt > > > calls qemuProcessStartCPUs in the Finish3 step. > > > This fn simply sends the "-cont" cmd to the monitor to > > > start the VM/CPUs. > > That's correct, but it's doing this already in v2. The non-autostart > > (-S) corresponds to Qemu's autostart here (migration.c): > > > > void process_incoming_migration(QEMUFile *f) > > { > > if (qemu_loadvm_state(f) < 0) { > > fprintf(stderr, "load of migration failed\n"); > > exit(0); > > } > > qemu_announce_self(); > > DPRINTF("successfully loaded vm state\n"); > > > > incoming_expected = false; > > > > if (autostart) > > vm_start(); > > } > > > > and simply doesn't start the VM. After this function is called all > > sockets are closed and the communication with the source host is > > cut. I don't think it allows for fall-back at this point. > > Sure it does. As long as the destination QEMU CPUs have not been > started, you can fallback by simply killing the dest QEMU and > restarting CPUs on the src QEMU. > > > Rather we may need a 'wait' option for migration and before the > > > > qemu_put_byte(f, QEMU_VM_EOF); > > > > in qemu_savevm_state_complete() sync with the monitor and either > > wait for something like migrate_finish or migrate_cancel. > > The real problem, is that while we can tell from 'info migrate' > on the src, when the src has finished sending all data, there is > no way to ask the dest QEMU when it has finished receiving all > data. > > So libvirt assumes that 'src finished sending' == success, and > will attempt to start the dst QEMU CPUs. As raised many times > in the past, we need 'info migrate' to work on the destination > too, in order to query success/fail. And ideally need async > events emitted when migration completes, so we don't have to > poll on 'info migrate' every 50ms What is the reason why this point ('info migrate' on dst host) was raised many times in the past but it was never implemented? Is there any technical reason? Assuming the interval between the moment src host finishes sending and the dst host finishes receiving is not too big (which is a fair assumption I guess), libvirt on the dst host could block on that condition (ie wait for 'info migrate' to say "rx all" in the dst host) at the beginning of Finish3. Is it doable? /Christian From benve at cisco.com Thu Apr 21 18:18:43 2011 From: benve at cisco.com (Christian Benvenuti (benve)) Date: Thu, 21 Apr 2011 13:18:43 -0500 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <20110421120132.GE25985@redhat.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com> <1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> <20110421120132.GE25985@redhat.com> Message-ID: <184D23435BECB444AB6B9D4630C8EC830190B677@XMB-RCD-303.cisco.com> > -----Original Message----- > From: Daniel P. Berrange [mailto:berrange at redhat.com] > Sent: Thursday, April 21, 2011 5:02 AM > To: Christian Benvenuti (benve) > Cc: eblake at redhat.com; stefanb at linux.vnet.ibm.com; laine at laine.org; > chrisw at redhat.com; libvir-list at redhat.com; David Wang (dwang2); Roopa > Prabhu (roprabhu) > Subject: Re: [libvirt] [PATCH 3/6] Introduce yet another migration > version in API. > > On Wed, Apr 20, 2011 at 04:28:12PM -0500, Christian Benvenuti (benve) > wrote: > > Daniel, > > I looked at the patch-set you sent out on the 2/9/11 > > > > [libvirt] [PATCH 0/6] Introduce a new migration protocol > > to QEMU driver > > http://www.mail-archive.com/libvir-list at redhat.com/msg33223.html > > > > What is the status of this new migration protocol? > > Is there any pending issue blocking its integration? > > > > I would like to propose an RFC enhancement to the migration > > algorithm. > > > > Here is a quick summary of the proposal/idea. > > > > - finer control on migration result > > > > - possibility of specifying what features cannot fail > > their initialization on the dst host during migration. > > Migration should not succeed if any of them fails. > > - optional: each one of those features should be able to > > provide a deinit function to cleanup resources > > on the dst host if migration fails. > > I'm not really very convinced that allowing things to fail > during migration is useful, not least from the POV of the > app determining just what worked vs failed. IMHO, migration > should be atomic and only succeed, if everything related to > the guest succeeds. I agree, the migration should be atomic ... in most cases. However, the scenario I was referring to is different: in that scenario you want the migration to complete as fast as possible. Because of that, blocking on operations (such as net config) which may need several seconds to complete and that could be taken care in a second moment would not be desirable. In such a scenario you would be choosing between these two results: 1) you may lose the VM because the migration does not complete fast enough 2) you have more chances of successfully moving the VM, but you may lose something like network connectivity. This loss may be acceptable (or less of a problem compared to the loss of the VM run-time state) in the sense that mgmt can re-try initializing it. > If we want to support a case where the dst can't connect to > the same network, then we should add an API that lets us > change the network backend on the fly. 'on the fly' when/where? On the dst host at the end of the migration? > NB, this is different > from NIC hotplug/unplug, in that the guest device never > changes. We merely change how the guest is connected to the > host. > So, if you have a guest with a NIC configureed using VEPA, > then you can re-configure it to use a 'no op' (aka /dev/null) > NIC backend, and then perform the migration. Wouldn't it be better to let the migration try to migrate the net connection too, and, in case it failed, let mgmt re-try if configured to do so, based for example on a configuration policy (ie, "net persistent re-try 10s")? > > ---------------------------------------------- > > enhancement: finer control on migration result > > ---------------------------------------------- > > > > There are different reasons why a VM may need (or be forced) to > > migrate. > > You can classify the types of the migrations also based on > > different semantics. > > For simplicity I'll classify them into two categories, based on > > how important it is for the VM to migrate as fast as possible: > > > > (1) It IS important > > > > In this case, whether the VM will not be able to (temporary) > > make use of certain resources (for example the network) on the > > dst host, is not that important, because the completion of the > > migration is considered higher priority. > > A possible scenario could be a server that must migrate ASAP > > because of a disaster/emergency. > > > > (2) It IS NOT important > > > > I can think of a VM whose applications/servers need a network > > connection in order to work properly. Loosing such network > > connectivity as a consequence of a migration would not be > > acceptable (or highly undesirable). > > > > Given the case (2) above, I have a comment about the Finish > > step, with regards to the port profile (VDP) codepath. > > > > The call to > > > > qemuMigrationVPAssociatePortProfile > > > > in > > qemuMigrationFinish > > > > can fail, but its result (success or failure) does not influence > > the result of the migration Finish step (it was already like this > > in migration V2). > > It is therefore possible for a VM to lose its network connectivity > > after a (successful) migration. > > That is a clear bug in our code - something that can fail during > migration, should be causing migration to abort, leaving the guest > on the original host unchanged. I agree. However I believe there may be corner cases (like emergency scenarios) where it can make sense to relax this policy. /Christian > > BTW, would the new functionality being discussed in this 3D > > > > "RFC: virInterface change transaction API" > > http://www.redhat.com/archives/libvir-list/2011-April/msg00499.html > > > > be able to provide the same configuration "atomicity" (ie, rollback > > in case of migration failure)? > > My understanding is that: > > > > - Such new framework would apply to (host) network config only. > > Even though it may cover the VDP (port profile) use case I > > mentioned above, it would not apply to other features that > > may need some kind of rollback after a migration failure. > > Host NIC configuration from virInterface isn't really tied into > the migration at all. It is something the mgmt app has to do on > the source & dest hosts, before setting up any VMs, let alone > getting to migration. > > Regards, > Daniel > -- > |: http://berrange.com -o- > http://www.flickr.com/photos/dberrange/ :| > |: http://libvirt.org -o- http://virt- > manager.org :| > |: http://autobuild.org -o- > http://search.cpan.org/~danberr/ :| > |: http://entangle-photo.org -o- http://live.gnome.org/gtk- > vnc :| From eblake at redhat.com Thu Apr 21 18:54:14 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 21 Apr 2011 12:54:14 -0600 Subject: [libvirt] [PATCHv11 0/6] libvirt/qemu - persistent modification of devices In-Reply-To: <20110421161918.6075c95a.kamezawa.hiroyu@jp.fujitsu.com> References: <20110421161918.6075c95a.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4DB07D56.2060303@redhat.com> I'm assuming you meant for this to go to libvir-list rather than libvirt-users; all my subsequent mails will swap the list reply. On 04/21/2011 01:19 AM, KAMEZAWA Hiroyuki wrote: > > Here is v11. Fixed comments/bugs and updated against the latest libvirt.git. > > Changes v10->v11: > - fixed comments on each patches > - fixed cgroup handling in patch 3. > - fixed MODIFY_CURRENT handling in patch 4. > > most of diff comes from refactoring qemu/qemu_driver.c > -- > conf/domain_conf.c | 40 ++ > conf/domain_conf.h | 5 > libvirt_private.syms | 3 > qemu/qemu_driver.c | 727 +++++++++++++++++++++++++++++++-------------------- > 4 files changed, 500 insertions(+), 275 deletions(-) > > > Thanks, > -Kame > > -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 21 19:19:29 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 21 Apr 2011 13:19:29 -0600 Subject: [libvirt] [PATCHv11 1/6] libvirt/qemu - Centralize device modification in the more flexible APIs In-Reply-To: <20110421162230.676d194f.kamezawa.hiroyu@jp.fujitsu.com> References: <20110421161918.6075c95a.kamezawa.hiroyu@jp.fujitsu.com> <20110421162230.676d194f.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4DB08341.5020306@redhat.com> On 04/21/2011 01:22 AM, KAMEZAWA Hiroyuki wrote: > > Centralize device modification in the more flexible APIs, to allow future > honoring of additional flags. Explicitly reject the > VIR_DOMAIN_DEVICE_MODIFY_FORCE flag on attach/detach. > > Based on Eric Blake's work. > > From: Eric Blake > Signed-off-by: KAMEZAWA Hiroyuki > > * src/qemu/qemu_driver.c > (qemudDomainAttachDevice)(qemudDomainAttachDeviceFlags): Swap bodies,rename... Where's the rename? > (qemudDomainDetachDevice, qemudDomainDetachDeviceFlags): Likewise. > --- > src/qemu/qemu_driver.c | 53 ++++++++++++++++++++++++++--------------------- > 1 files changed, 29 insertions(+), 24 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index f6e503a..a8f3849 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -3786,8 +3786,8 @@ cleanup: > } > > > -static int qemudDomainAttachDevice(virDomainPtr dom, > - const char *xml) > +static int qemudDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, > + unsigned int flags) I adjusted this to do s/qemud/qemu/ for the lines of code actually touched in this patch, plus fallout. ACK and pushed with this squashed in. diff --git c/src/qemu/qemu_driver.c w/src/qemu/qemu_driver.c index a8f3849..1f5a899 100644 --- c/src/qemu/qemu_driver.c +++ w/src/qemu/qemu_driver.c @@ -3786,8 +3786,8 @@ cleanup: } -static int qemudDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) +static int qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; @@ -3951,10 +3951,10 @@ cleanup: return ret; } -static int qemudDomainAttachDevice(virDomainPtr dom, const char *xml) +static int qemuDomainAttachDevice(virDomainPtr dom, const char *xml) { - return qemudDomainAttachDeviceFlags(dom, xml, - VIR_DOMAIN_DEVICE_MODIFY_LIVE); + return qemuDomainAttachDeviceFlags(dom, xml, + VIR_DOMAIN_DEVICE_MODIFY_LIVE); } @@ -4080,8 +4080,8 @@ cleanup: } -static int qemudDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) +static int qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; @@ -4175,10 +4175,10 @@ cleanup: return ret; } -static int qemudDomainDetachDevice(virDomainPtr dom, const char *xml) +static int qemuDomainDetachDevice(virDomainPtr dom, const char *xml) { - return qemudDomainDetachDeviceFlags(dom, xml, - VIR_DOMAIN_DEVICE_MODIFY_LIVE); + return qemuDomainDetachDeviceFlags(dom, xml, + VIR_DOMAIN_DEVICE_MODIFY_LIVE); } static int qemudDomainGetAutostart(virDomainPtr dom, @@ -6980,10 +6980,10 @@ static virDriver qemuDriver = { qemudDomainStartWithFlags, /* domainCreateWithFlags */ qemudDomainDefine, /* domainDefineXML */ qemudDomainUndefine, /* domainUndefine */ - qemudDomainAttachDevice, /* domainAttachDevice */ - qemudDomainAttachDeviceFlags, /* domainAttachDeviceFlags */ - qemudDomainDetachDevice, /* domainDetachDevice */ - qemudDomainDetachDeviceFlags, /* domainDetachDeviceFlags */ + qemuDomainAttachDevice, /* domainAttachDevice */ + qemuDomainAttachDeviceFlags, /* domainAttachDeviceFlags */ + qemuDomainDetachDevice, /* domainDetachDevice */ + qemuDomainDetachDeviceFlags, /* domainDetachDeviceFlags */ qemuDomainUpdateDeviceFlags, /* domainUpdateDeviceFlags */ qemudDomainGetAutostart, /* domainGetAutostart */ qemudDomainSetAutostart, /* domainSetAutostart */ -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 21 20:27:23 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 21 Apr 2011 14:27:23 -0600 Subject: [libvirt] [PATCHv11 2/6] libvirt/qemu - clean up At(De)tachDeviceFlags() for consolidation. In-Reply-To: <20110421162348.5ca6a3d4.kamezawa.hiroyu@jp.fujitsu.com> References: <20110421161918.6075c95a.kamezawa.hiroyu@jp.fujitsu.com> <20110421162348.5ca6a3d4.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4DB0932B.6050304@redhat.com> On 04/21/2011 01:23 AM, KAMEZAWA Hiroyuki wrote: > clean up At(De)tachDeviceFlags() for consolidation. > > qemudDomainAttachDeviceFlags()/qemudDomainDetachFlags()/ > qemudDomainUpdateDeviceFlags() has similar logics and copied codes. > > This patch series tries to unify them to use shared code when it can. > At first, clean up At(De)tachDeviceFlags() and devide it into functions. > > By this, this patch pulls out shared components between functions. > Based on patch series by Eric Blake, I added some modification as > switch-case with QEMUD_DEVICE_ATTACH, QEMUD_DEVICE_DETACH, QEMUD_DEVICE_UPDATE I kind of liked my callback function pointers, but your switch statement isn't too many more lines of code and arguably a tiny bit more readable. I want this series in before 0.9.1, so I'm not going to reject the patch just because of a difference in approach :) > > +static int qemudDomainAttachDeviceDiskLive(struct qemud_driver *driver, The prefix qemud is a misnomer (it dates back to when we were running a daemon just for qemu and directly calling into xen; but now that the code has evolved, the daemon is named libvirtd and is independent of qemu, and the qemu code is independent of the daemon and no longer needs the 'd'). New code should use just 'qemu'. Yes, I know that changing it now means more merge conflicts to resolve later in the series. Oh well. > +static int qemudDomainDetachDeviceDiskLive(struct qemud_driver *driver, > + virDomainObjPtr vm, > + virDomainDeviceDefPtr dev, > + virBitmapPtr qemuCaps) > +{ > + virDomainDiskDefPtr disk = dev->data.disk; > + int ret = -1; > + > + switch (disk->device) { > + case VIR_DOMAIN_DISK_DEVICE_DISK: > + if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) > + ret = qemuDomainDetachPciDiskDevice(driver, vm, dev, qemuCaps); > + else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) > + ret = qemuDomainDetachDiskDevice(driver, vm, dev, qemuCaps); > + else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) > + ret = qemuDomainDetachDiskDevice(driver, vm, dev, qemuCaps); > + else > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("This type of disk cannot be hot unplugged")); > + break; > + default: > + break; Oops, no error message on that path. > + > +enum { > + QEMUD_DEVICE_ATTACH, QEMUD_DEVICE_DETACH, QEMUD_DEVICE_UPDATE, I flattened these out to one-per-line as part of renaming to QEMU_*. > + * update domain status forcibly because the domain status may be changed > * even if we attach the device failed. For example, a new controller may > * be created. > */ > - if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) > + if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) This change violates the comment right before it. I undid it. ACK with those nits fixed, so I pushed a modified version (shoot; I've lost an easy way to have git show my incremental diffs, due to the merge conflict resolution from the renames). -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 21 21:17:01 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 21 Apr 2011 15:17:01 -0600 Subject: [libvirt] [PATCHv2] build: use gnulib passfd for simpler SCM_RIGHTS code In-Reply-To: <1303330531-25818-1-git-send-email-eblake@redhat.com> References: <1303330531-25818-1-git-send-email-eblake@redhat.com> Message-ID: <1303420621-25090-1-git-send-email-eblake@redhat.com> * .gnulib: Update to latest for passfd fixes. * bootstrap.conf (gnulib_modules): Add passfd. * src/util/util.c (virFileOpenAs): Simplify. --- Now that the mingw side of passfd is fixed in gnulib, I can resubmit this patch. v2: update .gnulib, no other changes .gnulib | 2 +- bootstrap.conf | 1 + src/util/util.c | 38 ++++++++------------------------------ 3 files changed, 10 insertions(+), 31 deletions(-) diff --git a/.gnulib b/.gnulib index fb79969..5a9e46a 160000 --- a/.gnulib +++ b/.gnulib @@ -1 +1 @@ -Subproject commit fb799692f5bb43310424977e0ca15599fc68d776 +Subproject commit 5a9e46ab46042f007426c1e06b836cf5608d8d4a diff --git a/bootstrap.conf b/bootstrap.conf index 293f86e..3b3a90f 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -52,6 +52,7 @@ mkstemps mktempd netdb nonblocking +passfd perror physmem pipe-posix diff --git a/src/util/util.c b/src/util/util.c index d4d2610..de4e3b3 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -78,6 +78,7 @@ #include "files.h" #include "command.h" #include "nonblocking.h" +#include "passfd.h" #ifndef NSIG # define NSIG 32 @@ -1480,11 +1481,6 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, int waitret, status, ret = 0; int fd = -1; int pair[2] = { -1, -1 }; - struct msghdr msg; - struct cmsghdr *cmsg; - char buf[CMSG_SPACE(sizeof(fd))]; - char dummy = 0; - struct iovec iov; int forkRet; if ((!(flags & VIR_FILE_OPEN_AS_UID)) @@ -1506,18 +1502,6 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, return ret; } - memset(&msg, 0, sizeof(msg)); - iov.iov_base = &dummy; - iov.iov_len = 1; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = buf; - msg.msg_controllen = sizeof(buf); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); - forkRet = virFork(&pid); if (pid < 0) { @@ -1529,26 +1513,20 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, VIR_FORCE_CLOSE(pair[1]); do { - ret = recvmsg(pair[0], &msg, 0); + ret = recvfd(pair[0], 0); } while (ret < 0 && errno == EINTR); - if (ret < 0) { + if (ret < 0 && errno != EACCES) { ret = -errno; VIR_FORCE_CLOSE(pair[0]); while ((waitret = waitpid(pid, NULL, 0) == -1) && (errno == EINTR)); goto parenterror; + } else { + fd = ret; } VIR_FORCE_CLOSE(pair[0]); - /* See if fd was transferred. */ - cmsg = CMSG_FIRSTHDR(&msg); - if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(fd)) && - cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_RIGHTS) { - memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); - } - /* wait for child to complete, and retrieve its exit code */ while ((waitret = waitpid(pid, &status, 0) == -1) && (errno == EINTR)); @@ -1557,12 +1535,14 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, virReportSystemError(errno, _("failed to wait for child creating '%s'"), path); + VIR_FORCE_CLOSE(fd); goto parenterror; } if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == -EACCES || fd == -1) { /* fall back to the simpler method, which works better in * some cases */ + VIR_FORCE_CLOSE(fd); return virFileOpenAsNoFork(path, openflags, mode, uid, gid, flags); } if (!ret) @@ -1627,10 +1607,9 @@ parenterror: path, mode); goto childerror; } - memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); do { - ret = sendmsg(pair[1], &msg, 0); + ret = sendfd(pair[1], fd); } while (ret < 0 && errno == EINTR); if (ret < 0) { @@ -1638,7 +1617,6 @@ parenterror: goto childerror; } - ret = 0; childerror: /* ret tracks -errno on failure, but exit value must be positive. * If the child exits with EACCES, then the parent tries again. */ -- 1.7.4.4 From eblake at redhat.com Thu Apr 21 21:31:20 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 21 Apr 2011 15:31:20 -0600 Subject: [libvirt] [PATCH 02/16] Introduce yet another migration version in API. In-Reply-To: <1303403575-20220-3-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> <1303403575-20220-3-git-send-email-berrange@redhat.com> Message-ID: <4DB0A228.1050302@redhat.com> On 04/21/2011 10:32 AM, Daniel P. Berrange wrote: > Migration just seems togo from bad to worse. We already had to s/togo/to go/ > > This patch attempts to introduce a version 3 that uses the > improved 5 step sequence > > * Src: Begin > - Generate XML to pass to dst > - Generate optional cookie to pass to dst > > * Dst: Prepare > - Get ready to accept incoming VM > - Generate optional cookie to pass to src > > * Src: Perform > - Start migration and wait for send completion > - Generate optional cookie to pass to dst > > * Dst: Finish > - Wait for recv completion and check status > - Kill off VM if failed, resume if success > - Generate optional cookie to pass to src > > * Src: Confirm > - Kill off VM if success, resume if failed I think we've covered that this is a reasonable idiom in other threads. At least, I can't think of anything else to add. > > The API is designed to allow both input and output cookies > in all methods where applicable. This lets us pass around > arbitrary extra driver specific data between src & dst during > migration. Combined with the extra 'Begin' method this lets > us pass lease information from source to dst at the start of > migration > > Moving the killing of the source VM out of Perform and > into Confirm, means we can now recover if the dst host > can't successfully Finish receiving migration data. I think this also opens the gate to allowing the destination side gracefully abort the receive job, although I'm not sure if your patch series got to that point, yet. > + * Src: Begin > + * - Generate XML to pass to dst > + * - Generate optional cookie to pass to dst > + * > + * Dst: Prepare > + * - Get ready to accept incoming VM > + * - Generate optional cookie to pass to src > + * > + * Src: Perform > + * - Start migration and wait for send completion > + * - Generate optional cookie to pass to dst > + * > + * Dst: Finish > + * - Wait for recv completion and check status > + * - Kill off VM if failed, resume if success > + * - Generate optional cookie to pass to src > + * > + * Src: Confirm > + * - Kill off VM if success, resume if failed > + * > + */ > > +/* > + * Not for public use. This function is part of the internal > + * implementation of migration in the remote case. > + */ > +char * > +virDomainMigrateBegin3(virDomainPtr domain, > + char **cookieout, > + int *cookieoutlen, > + unsigned long flags, > + const char *dname, > + unsigned long bandwidth) > +{ > + virConnectPtr conn; > + > + VIR_DOMAIN_DEBUG(domain, "cookieout=%p, cookieoutlen=%p, " > + "flags=%lu, dname=%s, bandwidth=%lu", > + cookieout, cookieoutlen, flags, > + NULLSTR(dname), bandwidth); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECTED_DOMAIN (domain)) { I noticed spacing is funny here [s/DOMAIN (/DOMAIN(/]. Didn't look closely for it elsewhere. > +++ b/src/libvirt_private.syms > @@ -547,6 +547,12 @@ virDomainMigratePerform; > virDomainMigratePrepare2; > virDomainMigratePrepare; > virDomainMigratePrepareTunnel; > +virDomainMigrateBegin3; > +virDomainMigratePrepare3; > +virDomainMigratePrepareTunnel3; > +virDomainMigratePerform3; > +virDomainMigrateFinish3; > +virDomainMigrateConfirm3; For consistency, sort these lines alphabetically amongst the other functions. You missed stubs for src/libxl/libxl_driver.c. ACK with those nits fixed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 21 22:12:04 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 21 Apr 2011 16:12:04 -0600 Subject: [libvirt] [PATCH 03/16] Remote driver implementation of new migration API In-Reply-To: <1303403575-20220-4-git-send-email-berrange@redhat.com> References: <1303403575-20220-1-git-send-email-berrange@redhat.com> <1303403575-20220-4-git-send-email-berrange@redhat.com> Message-ID: <4DB0ABB4.7080507@redhat.com> On 04/21/2011 10:32 AM, Daniel P. Berrange wrote: > * src/remote/remote_protocol.x: Define wire protocol for migration > protocol v3 > * daemon/remote.c: Server side dispatch > * src/remote/remote_driver.c: Client side serialization > * src/remote/remote_protocol.c, src/remote/remote_protocol.h, > daemon/remote_dispatch_args.h, daemon/remote_dispatch_prototypes.h, > daemon/remote_dispatch_ret.h, daemon/remote_dispatch_table.h: > Re-generate files > * src/remote_protocol-structs: Declare new ABIs > --- > daemon/remote.c | 315 +++++++++++++++++++++++++++++ > daemon/remote_dispatch_args.h | 6 + > daemon/remote_dispatch_prototypes.h | 48 +++++ > daemon/remote_dispatch_ret.h | 5 + > daemon/remote_dispatch_table.h | 30 +++ > src/remote/remote_driver.c | 371 ++++++++++++++++++++++++++++++++++- > src/remote/remote_protocol.c | 163 +++++++++++++++ > src/remote/remote_protocol.h | 140 +++++++++++++ > src/remote/remote_protocol.x | 79 ++++++++- > src/remote_protocol-structs | 90 +++++++++ > 10 files changed, 1240 insertions(+), 7 deletions(-) Lots of new code, but mostly mechanical. And now that you've got your first round of remote.c cleanups already committed to the tree, hopefully some of the worst rebasing is behind us for when you get to the rest of the RPC series. > /*----------------------------------------------------------------------*/ > > static struct remote_thread_call * > @@ -11062,6 +11405,22 @@ remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque) > * but if they do then virterror_internal.has been set. Odd punctuation... > */ > static virDomainPtr > +get_domain (virConnectPtr conn, remote_domain domain) > +{ > + virDomainPtr dom = NULL; > + if (domain) { > + dom = virGetDomain (conn, domain->name, BAD_CAST domain->uuid); > + if (dom) dom->id = domain->id; Formatting is a bit inconsistent here [" (" instead of "(" in two places]. > + } > + return dom; > +} > + > +/* get_nonnull_domain and get_nonnull_network turn an on-wire > + * (name, uuid) pair into virDomainPtr or virNetworkPtr object. > + * These can return NULL if underlying memory allocations fail, > + * but if they do then virterror_internal.has been set. ...copied here again. ACK with nits fixed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From kamezawa.hiroyu at jp.fujitsu.com Thu Apr 21 23:51:41 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 22 Apr 2011 08:51:41 +0900 Subject: [libvirt] [PATCHv11 0/6] libvirt/qemu - persistent modification of devices In-Reply-To: <4DB07D56.2060303@redhat.com> References: <20110421161918.6075c95a.kamezawa.hiroyu@jp.fujitsu.com> <4DB07D56.2060303@redhat.com> Message-ID: <20110422085141.eb96ba30.kamezawa.hiroyu@jp.fujitsu.com> On Thu, 21 Apr 2011 12:54:14 -0600 Eric Blake wrote: > I'm assuming you meant for this to go to libvir-list rather than > libvirt-users; all my subsequent mails will swap the list reply. > Ouch....thanks. -Kame > On 04/21/2011 01:19 AM, KAMEZAWA Hiroyuki wrote: > > > > Here is v11. Fixed comments/bugs and updated against the latest libvirt.git. > > > > Changes v10->v11: > > - fixed comments on each patches > > - fixed cgroup handling in patch 3. > > - fixed MODIFY_CURRENT handling in patch 4. > > > > most of diff comes from refactoring qemu/qemu_driver.c > > -- > > conf/domain_conf.c | 40 ++ > > conf/domain_conf.h | 5 > > libvirt_private.syms | 3 > > qemu/qemu_driver.c | 727 +++++++++++++++++++++++++++++++-------------------- > > 4 files changed, 500 insertions(+), 275 deletions(-) > > > > > > Thanks, > > -Kame > > > > > > -- > Eric Blake eblake at redhat.com +1-801-349-2682 > Libvirt virtualization library http://libvirt.org > From kamezawa.hiroyu at jp.fujitsu.com Thu Apr 21 23:53:22 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 22 Apr 2011 08:53:22 +0900 Subject: [libvirt] [PATCHv11 1/6] libvirt/qemu - Centralize device modification in the more flexible APIs In-Reply-To: <4DB08341.5020306@redhat.com> References: <20110421161918.6075c95a.kamezawa.hiroyu@jp.fujitsu.com> <20110421162230.676d194f.kamezawa.hiroyu@jp.fujitsu.com> <4DB08341.5020306@redhat.com> Message-ID: <20110422085322.cd28a54d.kamezawa.hiroyu@jp.fujitsu.com> On Thu, 21 Apr 2011 13:19:29 -0600 Eric Blake wrote: > On 04/21/2011 01:22 AM, KAMEZAWA Hiroyuki wrote: > > > > Centralize device modification in the more flexible APIs, to allow future > > honoring of additional flags. Explicitly reject the > > VIR_DOMAIN_DEVICE_MODIFY_FORCE flag on attach/detach. > > > > Based on Eric Blake's work. > > > > From: Eric Blake > > Signed-off-by: KAMEZAWA Hiroyuki > > > > * src/qemu/qemu_driver.c > > (qemudDomainAttachDevice)(qemudDomainAttachDeviceFlags): Swap bodies,rename... > > Where's the rename? > > > (qemudDomainDetachDevice, qemudDomainDetachDeviceFlags): Likewise. > > --- > > src/qemu/qemu_driver.c | 53 ++++++++++++++++++++++++++--------------------- > > 1 files changed, 29 insertions(+), 24 deletions(-) > > > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > > index f6e503a..a8f3849 100644 > > --- a/src/qemu/qemu_driver.c > > +++ b/src/qemu/qemu_driver.c > > @@ -3786,8 +3786,8 @@ cleanup: > > } > > > > > > -static int qemudDomainAttachDevice(virDomainPtr dom, > > - const char *xml) > > +static int qemudDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, > > + unsigned int flags) > > I adjusted this to do s/qemud/qemu/ for the lines of code actually > touched in this patch, plus fallout. > > ACK and pushed with this squashed in. > Thank you. -Kame From kamezawa.hiroyu at jp.fujitsu.com Thu Apr 21 23:55:37 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 22 Apr 2011 08:55:37 +0900 Subject: [libvirt] [PATCHv11 2/6] libvirt/qemu - clean up At(De)tachDeviceFlags() for consolidation. In-Reply-To: <4DB0932B.6050304@redhat.com> References: <20110421161918.6075c95a.kamezawa.hiroyu@jp.fujitsu.com> <20110421162348.5ca6a3d4.kamezawa.hiroyu@jp.fujitsu.com> <4DB0932B.6050304@redhat.com> Message-ID: <20110422085537.c7db96c7.kamezawa.hiroyu@jp.fujitsu.com> On Thu, 21 Apr 2011 14:27:23 -0600 Eric Blake wrote: > On 04/21/2011 01:23 AM, KAMEZAWA Hiroyuki wrote: > > clean up At(De)tachDeviceFlags() for consolidation. > > > > qemudDomainAttachDeviceFlags()/qemudDomainDetachFlags()/ > > qemudDomainUpdateDeviceFlags() has similar logics and copied codes. > > > > This patch series tries to unify them to use shared code when it can. > > At first, clean up At(De)tachDeviceFlags() and devide it into functions. > > > > By this, this patch pulls out shared components between functions. > > Based on patch series by Eric Blake, I added some modification as > > switch-case with QEMUD_DEVICE_ATTACH, QEMUD_DEVICE_DETACH, QEMUD_DEVICE_UPDATE > > I kind of liked my callback function pointers, but your switch statement > isn't too many more lines of code and arguably a tiny bit more readable. > I want this series in before 0.9.1, so I'm not going to reject the > patch just because of a difference in approach :) > > > > > +static int qemudDomainAttachDeviceDiskLive(struct qemud_driver *driver, > > The prefix qemud is a misnomer (it dates back to when we were running a > daemon just for qemu and directly calling into xen; but now that the > code has evolved, the daemon is named libvirtd and is independent of > qemu, and the qemu code is independent of the daemon and no longer needs > the 'd'). New code should use just 'qemu'. > I see. > Yes, I know that changing it now means more merge conflicts to resolve > later in the series. Oh well. > > > +static int qemudDomainDetachDeviceDiskLive(struct qemud_driver *driver, > > + virDomainObjPtr vm, > > + virDomainDeviceDefPtr dev, > > + virBitmapPtr qemuCaps) > > +{ > > + virDomainDiskDefPtr disk = dev->data.disk; > > + int ret = -1; > > + > > + switch (disk->device) { > > + case VIR_DOMAIN_DISK_DEVICE_DISK: > > + if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) > > + ret = qemuDomainDetachPciDiskDevice(driver, vm, dev, qemuCaps); > > + else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) > > + ret = qemuDomainDetachDiskDevice(driver, vm, dev, qemuCaps); > > + else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) > > + ret = qemuDomainDetachDiskDevice(driver, vm, dev, qemuCaps); > > + else > > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > > + _("This type of disk cannot be hot unplugged")); > > + break; > > + default: > > + break; > > Oops, no error message on that path. > Ah, yes. > > + > > +enum { > > + QEMUD_DEVICE_ATTACH, QEMUD_DEVICE_DETACH, QEMUD_DEVICE_UPDATE, > > I flattened these out to one-per-line as part of renaming to QEMU_*. > Sure. > > + * update domain status forcibly because the domain status may be changed > > * even if we attach the device failed. For example, a new controller may > > * be created. > > */ > > - if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) > > + if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) > > This change violates the comment right before it. I undid it. > > ACK with those nits fixed, so I pushed a modified version (shoot; I've > lost an easy way to have git show my incremental diffs, due to the merge > conflict resolution from the renames). Thank you. -kame From benve at cisco.com Fri Apr 22 01:34:58 2011 From: benve at cisco.com (Christian Benvenuti (benve)) Date: Thu, 21 Apr 2011 20:34:58 -0500 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <4DB03236.7000005@linux.vnet.ibm.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com> <1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> <4DAF665B.2070500@linux.vnet.ibm.com> <184D23435BECB444AB6B9D4630C8EC830190B4BE@XMB-RCD-303.cisco.com> <4DB016FA.7070509@linux.vnet.ibm.com> <20110421114358.GC25985@redhat.com> <4DB03236.7000005@linux.vnet.ibm.com> Message-ID: <184D23435BECB444AB6B9D4630C8EC830190B7DA@XMB-RCD-303.cisco.com> > -----Original Message----- > From: Stefan Berger [mailto:stefanb at linux.vnet.ibm.com] > Sent: Thursday, April 21, 2011 6:34 AM > To: Daniel P. Berrange > Cc: Christian Benvenuti (benve); eblake at redhat.com; laine at laine.org; > chrisw at redhat.com; libvir-list at redhat.com; David Wang (dwang2); Roopa > Prabhu (roprabhu); Gerhard Stenzel; Jens Osterkamp; Anthony Liguori > Subject: Re: [libvirt] [PATCH 3/6] Introduce yet another migration > version in API. > > On 04/21/2011 07:43 AM, Daniel P. Berrange wrote: > > On Thu, Apr 21, 2011 at 07:37:30AM -0400, Stefan Berger wrote: > >> > >> and simply doesn't start the VM. After this function is called all > >> sockets are closed and the communication with the source host is > >> cut. I don't think it allows for fall-back at this point. > > Sure it does. As long as the destination QEMU CPUs have not been > > started, you can fallback by simply killing the dest QEMU and > > restarting CPUs on the src QEMU. > > > FWIW, I did a test and disabled the starting of the CPUs on the > destination side and > did a sleep() instead. Before the sleep() was over the Qemu on the > source side had already disappeared. Did you test this with migration V2 or migration V3? I think what you describe is V2 (V3 now is different): - Migration V2 SRC HOST DST HOST | |- dump XML | | (PREPARE) +------------------------------>Start empty VM | |(PERFORM) |- migrate cmd to monitor |- kill VM | | (FINISH) +------------------------------->Start CPU - Migration V3 SRC HOST DST HOST | |(BEGIN) |- dumpxml | (PREPARE) +------------------------------>Start empty VM | |(PERFORM) |- migrate cmd to monitor | (src CPU is now paused) | | (FINISH) +------------------------------->Start CPU | |(CONFIRM) |- if FINISH succeeded: Kill src VM |- if FINISH failed : Run src VM /Christian From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 22 03:07:56 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 22 Apr 2011 12:07:56 +0900 Subject: [libvirt] [PATCHv12 1/3] libvirt/qemu - support persistent modification of devices Message-ID: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> Rebased ont the latest git tree, which makes this work easier. This series adds support for attach/detach/update disks of domain config. == This patch adds functions for modify domain's persistent definition. To do error recovery in easy way, we use a copy of vmdef and update it. The whole sequence will be: make a copy of domain definition. if (flags & MODIFY_CONFIG) update copied domain definition if (flags & MODIF_LIVE) do hotplug. if (no error) save copied one to the file and update cached definition. else discard copied definition. This patch is mixuture of Eric Blake's work and mine. From: Eric Blake Signed-off-by: KAMEZAWA Hiroyuki Changelog: v11 -> v12 - rebased and fixed hunks. - renamed qemudDomain....to qemuDomain... (virDomainObjCopyPersistentDef): make a copy of persistent vm definition (qemuDomainAttach/Detach/UpdateDeviceConfig) : callbacks. now empty (qemuDomainModifyDeviceFlags): add support for MODIFY_CONFIG and MODIFY_CURRENT --- src/conf/domain_conf.c | 18 ++++++ src/conf/domain_conf.h | 3 + src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 147 ++++++++++++++++++++++++++++++++++++---------- 4 files changed, 137 insertions(+), 32 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 381e692..6c1098a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9509,3 +9509,21 @@ cleanup: return ret; } + + +virDomainDefPtr +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom) +{ + char *xml; + virDomainDefPtr cur, ret; + + cur = virDomainObjGetPersistentDef(caps, dom); + + xml = virDomainDefFormat(cur, VIR_DOMAIN_XML_WRITE_FLAGS); + if (!xml) + return NULL; + + ret = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS); + + return ret; +} diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6ea30b9..ddf111a 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1288,6 +1288,9 @@ int virDomainObjSetDefTransient(virCapsPtr caps, virDomainDefPtr virDomainObjGetPersistentDef(virCapsPtr caps, virDomainObjPtr domain); +virDomainDefPtr +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom); + void virDomainRemoveInactive(virDomainObjListPtr doms, virDomainObjPtr dom); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ba7739d..f732431 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -287,6 +287,7 @@ virDomainMemballoonModelTypeToString; virDomainNetDefFree; virDomainNetTypeToString; virDomainObjAssignDef; +virDomainObjCopyPersistentDef; virDomainObjSetDefTransient; virDomainObjGetPersistentDef; virDomainObjIsDuplicate; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 771678e..fd85c8a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4073,6 +4073,46 @@ qemuDomainUpdateDeviceLive(virDomainObjPtr vm, return ret; } +static int +qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev) +{ + switch (dev->type) { + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("persistent attach of device is not supported")); + return -1; + } + return 0; +} + + +static int +qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev) +{ + switch (dev->type) { + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("persistent detach of device is not supported")); + return -1; + } + return 0; +} + +static int +qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev) +{ + switch (dev->type) { + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("persistent update of device is not supported")); + return -1; + } + return 0; +} + /* Actions for qemuDomainModifyDeviceFlags */ enum { QEMU_DEVICE_ATTACH, @@ -4088,6 +4128,7 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, struct qemud_driver *driver = dom->conn->privateData; virBitmapPtr qemuCaps = NULL; virDomainObjPtr vm = NULL; + virDomainDefPtr vmdef = NULL; virDomainDeviceDefPtr dev = NULL; bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; int ret = -1; @@ -4097,12 +4138,6 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, (action == QEMU_DEVICE_UPDATE ? VIR_DOMAIN_DEVICE_MODIFY_FORCE : 0), -1); - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot modify the persistent configuration of a domain")); - return -1; - } - qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { @@ -4116,12 +4151,27 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; - if (!virDomainObjIsActive(vm)) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot attach device on inactive domain")); - goto endjob; + if (virDomainObjIsActive(vm)) { + if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT) + flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE; + } else { + if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT) + flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG; + /* check consistency between flags and the vm state */ + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", + _("cannot do live update a device on " + "inactive domain")); + goto endjob; + } } + if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot modify device on transient domain")); + goto endjob; + } dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, VIR_DOMAIN_XML_INACTIVE); if (dev == NULL) @@ -4132,35 +4182,68 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, &qemuCaps) < 0) goto endjob; - switch (action) { - case QEMU_DEVICE_ATTACH: - ret = qemuDomainAttachDeviceLive(vm, dev, dom, qemuCaps); - break; - case QEMU_DEVICE_DETACH: - ret = qemuDomainDetachDeviceLive(vm, dev, dom, qemuCaps); - break; - case QEMU_DEVICE_UPDATE: - ret = qemuDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force); - break; - default: - qemuReportError(VIR_ERR_INTERNAL_ERROR, - _("unknown domain modify action %d"), action); - break; - } + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { + /* Make a copy for updated domain. */ + vmdef = virDomainObjCopyPersistentDef(driver->caps, vm); + if (!vmdef) + goto endjob; + switch (action) { + case QEMU_DEVICE_ATTACH: + ret = qemuDomainAttachDeviceConfig(vmdef, dev); + break; + case QEMU_DEVICE_DETACH: + ret = qemuDomainDetachDeviceConfig(vmdef, dev); + break; + case QEMU_DEVICE_UPDATE: + ret = qemuDomainUpdateDeviceConfig(vmdef, dev); + break; + default: + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown domain modify action %d"), action); + break; + } + } else + ret = 0; - /* - * update domain status forcibly because the domain status may be changed - * even if we attach the device failed. For example, a new controller may - * be created. - */ - if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) - ret = -1; + if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE)) { + switch (action) { + case QEMU_DEVICE_ATTACH: + ret = qemuDomainAttachDeviceLive(vm, dev, dom, qemuCaps); + break; + case QEMU_DEVICE_DETACH: + ret = qemuDomainDetachDeviceLive(vm, dev, dom, qemuCaps); + break; + case QEMU_DEVICE_UPDATE: + ret = qemuDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force); + break; + default: + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown domain modify action %d"), action); + break; + } + /* + * update domain status forcibly because the domain status may be + * changed even if we attach the device failed. For example, a + * For example, a new controller may be created. + */ + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) + ret = -1; + } + /* Finally, if no error until here, we can save config. */ + if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) { + ret = virDomainSaveConfig(driver->configDir, vmdef); + if (!ret) { + virDomainObjAssignDef(vm, vmdef, false); + vmdef = NULL; + } + } endjob: if (qemuDomainObjEndJob(vm) == 0) vm = NULL; cleanup: + virDomainDefFree(vmdef); virDomainDeviceDefFree(dev); if (vm) virDomainObjUnlock(vm); -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 22 03:09:32 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 22 Apr 2011 12:09:32 +0900 Subject: [libvirt] [PATCHv12 2/3] libvirt/qemu - support persistent attach/detach disks In-Reply-To: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> References: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110422120932.0a2ed23c.kamezawa.hiroyu@jp.fujitsu.com> Support changes of disks by MODIFY_CONFIG for qemu. This patch includes patches for qemu's disk to support virDomainAt(De)tachDeviceFlags with VIR_DOMAIN_DEVICE_MODIFY_CONFIG. Other devices can be added inrecemtaly. Signed-off-by: KAMEZAWA Hiroyuki Changelog: v11->v12 - rebased. (qemud... -> qemu...) * /src/conf/domain_conf.c (virDomainDiskIndexByName): returns array index of disk in vmdef. (virDomainDiskRemoveByName): removes a disk which has the name in vmdef. * src/qemu/qemu_driver.c (qemuDomainAttachDeviceConfig): add support for Disks. (qemuDomainDetachDeviceConfig): add support for Disks. --- src/conf/domain_conf.c | 22 ++++++++++++++++++++++ src/conf/domain_conf.h | 2 ++ src/libvirt_private.syms | 2 ++ src/qemu/qemu_driver.c | 36 ++++++++++++++++++++++++++++++++++-- 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6c1098a..d4fac87 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -5006,6 +5006,19 @@ virVirtualPortProfileFormat(virBufferPtr buf, virBufferVSprintf(buf, "%s\n", indent); } +int virDomainDiskIndexByName(virDomainDefPtr def, const char *name) +{ + virDomainDiskDefPtr vdisk; + int i; + + for (i = 0; i < def->ndisks; i++) { + vdisk = def->disks[i]; + if (STREQ(vdisk->dst, name)) + return i; + } + return -1; +} + int virDomainDiskInsert(virDomainDefPtr def, virDomainDiskDefPtr disk) { @@ -5077,6 +5090,15 @@ void virDomainDiskRemove(virDomainDefPtr def, size_t i) } } +int virDomainDiskRemoveByName(virDomainDefPtr def, const char *name) +{ + int i = virDomainDiskIndexByName(def, name); + if (i < 0) + return -1; + virDomainDiskRemove(def, i); + return 0; +} + int virDomainControllerInsert(virDomainDefPtr def, virDomainControllerDefPtr controller) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ddf111a..1dadf98 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1329,6 +1329,7 @@ int virDomainVcpupinAdd(virDomainDefPtr def, int maplen, int vcpu); +int virDomainDiskIndexByName(virDomainDefPtr def, const char *name); int virDomainDiskInsert(virDomainDefPtr def, virDomainDiskDefPtr disk); void virDomainDiskInsertPreAlloced(virDomainDefPtr def, @@ -1336,6 +1337,7 @@ void virDomainDiskInsertPreAlloced(virDomainDefPtr def, int virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def); void virDomainDiskRemove(virDomainDefPtr def, size_t i); +int virDomainDiskRemoveByName(virDomainDefPtr def, const char *name); int virDomainControllerInsert(virDomainDefPtr def, virDomainControllerDefPtr controller); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f732431..c469259 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -246,11 +246,13 @@ virDomainDiskDefFree; virDomainDiskDeviceTypeToString; virDomainDiskErrorPolicyTypeFromString; virDomainDiskErrorPolicyTypeToString; +virDomainDiskIndexByName; virDomainDiskInsert; virDomainDiskInsertPreAlloced; virDomainDiskIoTypeFromString; virDomainDiskIoTypeToString; virDomainDiskRemove; +virDomainDiskRemoveByName; virDomainDiskTypeFromString; virDomainDiskTypeToString; virDomainFSDefFree; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index fd85c8a..3f21e28 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4074,10 +4074,32 @@ qemuDomainUpdateDeviceLive(virDomainObjPtr vm, } static int -qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, +qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { + virDomainDiskDefPtr disk; + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + disk = dev->data.disk; + if (virDomainDiskIndexByName(vmdef, disk->dst) >= 0) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("target %s already exists."), disk->dst); + return -1; + } + if (virDomainDiskInsert(vmdef, disk)) { + virReportOOMError(); + return -1; + } + /* vmdef has the pointer. Generic codes for vmdef will do all jobs */ + dev->data.disk = NULL; + if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO) + if (virDomainDefAddImplicitControllers(vmdef) < 0) + return -1; + if (qemuDomainAssignPCIAddresses(vmdef) < 0) + return -1; + break; + default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent attach of device is not supported")); @@ -4088,10 +4110,20 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, static int -qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, +qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { + virDomainDiskDefPtr disk; + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + disk = dev->data.disk; + if (virDomainDiskRemoveByName(vmdef, disk->dst)) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("no target device %s"), disk->dst); + return -1; + } + break; default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent detach of device is not supported")); -- 1.7.4.1 From kamezawa.hiroyu at jp.fujitsu.com Fri Apr 22 03:10:28 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Fri, 22 Apr 2011 12:10:28 +0900 Subject: [libvirt] [PATCHv12 3/3] libvirt/qemu - support persistent update of disks In-Reply-To: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> References: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110422121028.8037cfa2.kamezawa.hiroyu@jp.fujitsu.com> Support update of disks by MODIFY_CONFIG This patch includes changes for qemu's disk to support virDomainUpdateDeviceFlags() with VIR_DOMAIN_DEVICE_MODIFY_CONFIG. This patch adds support for CDROM/foppy disk types. Signed-off-by: KAMEZAWA Hiroyuki Changelog: v11->v12 - rebased.(qemud->qemu) * src/qemu/qemu_driver.c (qemuDomainUpdateDeviceConfig): support cdrom/floppy. --- src/qemu/qemu_driver.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 39 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3f21e28..f3cfa3e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4133,10 +4133,48 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, } static int -qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, +qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { + virDomainDiskDefPtr orig, disk; + int pos; + switch (dev->type) { + case VIR_DOMAIN_DEVICE_DISK: + disk = dev->data.disk; + pos = virDomainDiskIndexByName(vmdef, disk->dst); + if (pos < 0) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("target %s doesn't exists."), disk->dst); + return -1; + } + orig = vmdef->disks[pos]; + if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM) && + !(orig->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("this disk doesn't support update")); + return -1; + } + /* + * Update 'orig' + * We allow updating src/type//driverType/cachemode/ + */ + VIR_FREE(orig->src); + orig->src = disk->src; + orig->type = disk->type; + orig->cachemode = disk->cachemode; + if (disk->driverName) { + VIR_FREE(orig->driverName); + orig->driverName = disk->driverName; + disk->driverName = NULL; + } + if (disk->driverType) { + VIR_FREE(orig->driverType); + orig->driverType = disk->driverType; + disk->driverType = NULL; + } + disk->src = NULL; + break; default: qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent update of device is not supported")); -- 1.7.4.1 From stefanb at linux.vnet.ibm.com Thu Apr 21 20:00:03 2011 From: stefanb at linux.vnet.ibm.com (Stefan Berger) Date: Thu, 21 Apr 2011 16:00:03 -0400 Subject: [libvirt] [PATCH 3/6] Introduce yet another migration version in API. In-Reply-To: <20110421142431.GG25985@redhat.com> References: <1297270705-8709-1-git-send-email-berrange@redhat.com> <1297270705-8709-4-git-send-email-berrange@redhat.com> <4DA4DC52.8010509@redhat.com> <184D23435BECB444AB6B9D4630C8EC830190B407@XMB-RCD-303.cisco.com> <4DAF665B.2070500@linux.vnet.ibm.com> <184D23435BECB444AB6B9D4630C8EC830190B4BE@XMB-RCD-303.cisco.com> <4DB016FA.7070509@linux.vnet.ibm.com> <20110421114358.GC25985@redhat.com> <4DB03236.7000005@linux.vnet.ibm.com> <20110421142431.GG25985@redhat.com> Message-ID: <4DB08CC3.70502@linux.vnet.ibm.com> On 04/21/2011 10:24 AM, Daniel P. Berrange wrote: > On Thu, Apr 21, 2011 at 09:33:42AM -0400, Stefan Berger wrote: >> On 04/21/2011 07:43 AM, Daniel P. Berrange wrote: >>> On Thu, Apr 21, 2011 at 07:37:30AM -0400, Stefan Berger wrote: >>>> and simply doesn't start the VM. After this function is called all >>>> sockets are closed and the communication with the source host is >>>> cut. I don't think it allows for fall-back at this point. >>> Sure it does. As long as the destination QEMU CPUs have not been >>> started, you can fallback by simply killing the dest QEMU and >>> restarting CPUs on the src QEMU. >>> >> FWIW, I did a test and disabled the starting of the CPUs on the >> destination side and >> did a sleep() instead. Before the sleep() was over the Qemu on the >> source side had already disappeared. > That is with the old v2 migration protocol. In the new v3 protocol > that has changed to work as I described. Hm... From what I see in the Qemu code and from the tracing I have done Qemu goes right from sending out the last byte in qemu_savevm_state_complete() to closing the sockets in migrate_fd_cleanups() with this sequence in migrate_fd_put_ready(). Also the receiving side attempts to receive all bytes in process_incoming_migration() and then goes straight to closing the sockets with this sequence in tcp_accept_incoming_migration(). This means that once migration has completely sent or received all bytes, the connection between the two Qemus is cut and there is no waiting for starting the CPUs or something like that. If relative to the Qemu migration the association of profiles returns a negative result after Qemu has sent all bytes, it's too late to kill the destination and fall back to the source. Stefan > > Daniel From mprivozn at redhat.com Fri Apr 22 07:15:46 2011 From: mprivozn at redhat.com (=?ISO-8859-1?Q?Michal_Pr=EDvozn=EDk?=) Date: Fri, 22 Apr 2011 09:15:46 +0200 Subject: [libvirt] [PATCH] Add support for s390(x) cpu options parsing In-Reply-To: <4DB0567E.7000808@redhat.com> References: <1303399660-21831-1-git-send-email-mprivozn@redhat.com> <4DB0567E.7000808@redhat.com> Message-ID: <4DB12B22.3020003@redhat.com> On 04/21/2011 06:08 PM, Eric Blake wrote: > On 04/21/2011 09:27 AM, Michal Privoznik wrote: >> Up to now we missed parser for cpuinfo on x390(x) machines. Those machines >> have only 1 thread, core, socket. What is missing is information about >> CPU frequency. >> --- >> src/nodeinfo.c | 29 +++++++++++++++++++++++++++-- >> 1 files changed, 27 insertions(+), 2 deletions(-) > > ACK. > Thanks. From mprivozn at redhat.com Fri Apr 22 07:58:38 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Fri, 22 Apr 2011 09:58:38 +0200 Subject: [libvirt] [PATCH] Fix disability to run on systems with no PCI bus Message-ID: <1303459118-21943-1-git-send-email-mprivozn@redhat.com> The patch which moved libpciaccess initialization to one place caused regression - we were not able to run on system with no PCI bus, like s390(x). This patch fix it. --- src/node_device/node_device_udev.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index 2139ef3..b6335ff 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -1603,7 +1603,13 @@ static int udevDeviceMonitorStartup(int privileged) char ebuf[256]; VIR_ERROR(_("Failed to initialize libpciaccess: %s"), virStrerror(pciret, ebuf, sizeof ebuf)); +#if defined __s390__ || defined __s390x_ + /* On x390(x) system there is no PCI bus. + * Therefore we do not want to return error here */ + ret = 0; +#else ret = -1; +#endif goto out; } } -- 1.7.4.4 From jdenemar at redhat.com Fri Apr 22 08:19:25 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Fri, 22 Apr 2011 10:19:25 +0200 Subject: [libvirt] [PATCH] Fix disability to run on systems with no PCI bus In-Reply-To: <1303459118-21943-1-git-send-email-mprivozn@redhat.com> References: <1303459118-21943-1-git-send-email-mprivozn@redhat.com> Message-ID: <20110422081924.GJ1245361@orkuz.home> On Fri, Apr 22, 2011 at 09:58:38 +0200, Michal Privoznik wrote: > The patch which moved libpciaccess initialization to one place caused > regression - we were not able to run on system with no PCI bus, like > s390(x). This patch fix it. > --- > src/node_device/node_device_udev.c | 6 ++++++ > 1 files changed, 6 insertions(+), 0 deletions(-) > > diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c > index 2139ef3..b6335ff 100644 > --- a/src/node_device/node_device_udev.c > +++ b/src/node_device/node_device_udev.c > @@ -1603,7 +1603,13 @@ static int udevDeviceMonitorStartup(int privileged) > char ebuf[256]; > VIR_ERROR(_("Failed to initialize libpciaccess: %s"), > virStrerror(pciret, ebuf, sizeof ebuf)); > +#if defined __s390__ || defined __s390x_ > + /* On x390(x) system there is no PCI bus. > + * Therefore we do not want to return error here */ > + ret = 0; > +#else > ret = -1; > +#endif > goto out; > } > } Why do we try to initialize libpciaccess if we know it won't succeed? What about just completely dropping libpciaccess dependency on s390(x)? Jirka From mprivozn at redhat.com Fri Apr 22 09:00:03 2011 From: mprivozn at redhat.com (=?ISO-8859-1?Q?Michal_Pr=EDvozn=EDk?=) Date: Fri, 22 Apr 2011 11:00:03 +0200 Subject: [libvirt] [PATCH] Fix disability to run on systems with no PCI bus In-Reply-To: <20110422081924.GJ1245361@orkuz.home> References: <1303459118-21943-1-git-send-email-mprivozn@redhat.com> <20110422081924.GJ1245361@orkuz.home> Message-ID: <4DB14393.2010406@redhat.com> On 04/22/2011 10:19 AM, Jiri Denemark wrote: > On Fri, Apr 22, 2011 at 09:58:38 +0200, Michal Privoznik wrote: >> The patch which moved libpciaccess initialization to one place caused >> regression - we were not able to run on system with no PCI bus, like >> s390(x). This patch fix it. >> --- >> src/node_device/node_device_udev.c | 6 ++++++ >> 1 files changed, 6 insertions(+), 0 deletions(-) >> >> diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c >> index 2139ef3..b6335ff 100644 >> --- a/src/node_device/node_device_udev.c >> +++ b/src/node_device/node_device_udev.c >> @@ -1603,7 +1603,13 @@ static int udevDeviceMonitorStartup(int privileged) >> char ebuf[256]; >> VIR_ERROR(_("Failed to initialize libpciaccess: %s"), >> virStrerror(pciret, ebuf, sizeof ebuf)); >> +#if defined __s390__ || defined __s390x_ >> + /* On x390(x) system there is no PCI bus. >> + * Therefore we do not want to return error here */ >> + ret = 0; >> +#else >> ret = -1; >> +#endif >> goto out; >> } >> } > > Why do we try to initialize libpciaccess if we know it won't succeed? What > about just completely dropping libpciaccess dependency on s390(x)? > > Jirka Well, although investigation on the internet shows there is at least PCI-like bus, linux kernel doesn't know how to use it (see arch/s390/include/asm/pci.h) which is the most important. so NAK and prepare v2. Michal From dwu at redhat.com Fri Apr 22 09:19:14 2011 From: dwu at redhat.com (Mark Wu) Date: Fri, 22 Apr 2011 17:19:14 +0800 Subject: [libvirt] [PATCH] Make the options "--crash" and "--live" of "virsh dump" mutually exclusive Message-ID: <4DB14812.2020509@redhat.com> This patch makes the options "--crash" and "--live" of "virsh dump" mutually exclusive diff --git a/tools/virsh.c b/tools/virsh.c index 2e35021..ef77d7f 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1869,14 +1869,19 @@ cmdDump(vshControl *ctl, const vshCmd *cmd) flags |= VIR_DUMP_LIVE; if (vshCommandOptBool (cmd, "crash")) flags |= VIR_DUMP_CRASH; - + if ((flags& VIR_DUMP_CRASH)&& (flags& VIR_DUMP_CRASH)) { + vshError(ctl, "%s", _("--crash and --live are mutually exclusive. " + "Please choose only one.")); + ret = FALSE; + goto cleanup; + } if (virDomainCoreDump(dom, to, flags) == 0) { vshPrint(ctl, _("Domain %s dumped to %s\n"), name, to); } else { vshError(ctl, _("Failed to core dump domain %s to %s"), name, to); ret = FALSE; } - +cleanup: virDomainFree(dom); return ret; } From jdenemar at redhat.com Fri Apr 22 09:57:10 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Fri, 22 Apr 2011 11:57:10 +0200 Subject: [libvirt] [PATCH] Make the options "--crash" and "--live" of "virsh dump" mutually exclusive In-Reply-To: <4DB14812.2020509@redhat.com> References: <4DB14812.2020509@redhat.com> Message-ID: <20110422095709.GK1245361@orkuz.home> > This patch makes the options "--crash" and "--live" of "virsh dump" mutually exclusive > > diff --git a/tools/virsh.c b/tools/virsh.c > index 2e35021..ef77d7f 100644 > --- a/tools/virsh.c > +++ b/tools/virsh.c > @@ -1869,14 +1869,19 @@ cmdDump(vshControl *ctl, const vshCmd *cmd) > flags |= VIR_DUMP_LIVE; > if (vshCommandOptBool (cmd, "crash")) > flags |= VIR_DUMP_CRASH; > - > + if ((flags& VIR_DUMP_CRASH)&& (flags& VIR_DUMP_CRASH)) { > + vshError(ctl, "%s", _("--crash and --live are mutually exclusive. " > + "Please choose only one.")); > + ret = FALSE; > + goto cleanup; > + } > if (virDomainCoreDump(dom, to, flags) == 0) { > vshPrint(ctl, _("Domain %s dumped to %s\n"), name, to); > } else { > vshError(ctl, _("Failed to core dump domain %s to %s"), name, to); > ret = FALSE; > } > - > +cleanup: > virDomainFree(dom); > return ret; > } Looks like thunderbird showed his best again and exchanged '&' and ' '. Also there is a typo in the condition (checking for CRASH twice) and make syntax-check forbids use of TABs for indentation. Moreover, this would only protect virsh. It's better to have this check in virDomainCoreDump() so that all users can get the error. The following patch should fix these issues. Jirka >From 42385de4db211a372c2db6d6a2b14cfcaa0cd511 Mon Sep 17 00:00:00 2001 Message-Id: <42385de4db211a372c2db6d6a2b14cfcaa0cd511.1303466112.git.jdenemar at redhat.com> From: Mark Wu Date: Fri, 22 Apr 2011 11:45:33 +0200 Subject: [PATCH] Make crash and live flags mutually exclusive in virDomainCoreDump Mail-Followup-To: libvir-list at redhat.com They don't make any sense when used together. --- src/libvirt.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 10c3cdf..2d56b77 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -2379,6 +2379,12 @@ virDomainCoreDump(virDomainPtr domain, const char *to, int flags) goto error; } + if ((flags & VIR_DUMP_CRASH) && (flags & VIR_DUMP_LIVE)) { + virLibDomainError(VIR_ERR_INVALID_ARG, + _("crash and live flags are mutually exclusive")); + goto error; + } + if (conn->driver->domainCoreDump) { int ret; char *absolute_to; -- 1.7.5.rc1 From jdenemar at redhat.com Fri Apr 22 10:03:19 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Fri, 22 Apr 2011 12:03:19 +0200 Subject: [libvirt] [PATCH] qemu: Add flags checking in DomainCoreDump Message-ID: --- src/qemu/qemu_driver.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f6e503a..f35616d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2345,7 +2345,8 @@ getCompressionType(struct qemud_driver *driver) static int qemudDomainCoreDump(virDomainPtr dom, const char *path, - int flags ATTRIBUTE_UNUSED) { + int flags) +{ struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; int resume = 0, paused = 0; @@ -2353,6 +2354,8 @@ static int qemudDomainCoreDump(virDomainPtr dom, virDomainEventPtr event = NULL; qemuDomainObjPrivatePtr priv; + virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1); + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); -- 1.7.5.rc1 From patrick.siegl at student.uni-tuebingen.de Fri Apr 22 10:05:29 2011 From: patrick.siegl at student.uni-tuebingen.de (Patrick Siegl) Date: Fri, 22 Apr 2011 12:05:29 +0200 Subject: [libvirt] [PATCH] Fix disability to run on systems with no PCI bus In-Reply-To: <4DB14393.2010406@redhat.com> References: <1303459118-21943-1-git-send-email-mprivozn@redhat.com> <20110422081924.GJ1245361@orkuz.home> <4DB14393.2010406@redhat.com> Message-ID: <4DB152E9.4050600@student.uni-tuebingen.de> Hello there, I wrote in February this year following: boromir:/ # qemu-system-s390x --enable-kvm -monitor stdio VNC server running on `::1:5900' QEMU 0.12.50 monitor - type 'help' for more information (qemu) info qtree bus: main-system-bus type System dev: s390-virtio-bridge, id "" bus: s390-virtio type s390-virtio dev: virtio-serial-s390, id "" dev-prop: max_ports = 31 bus: virtio-serial-bus.0 type virtio-serial-bus dev: virtconsole, id "" dev-prop: is_console = 1 dev-prop: chardev = virtcon0 dev-prop: name = dev-prop-int: id: 0 dev-prop-int: guest_connected: 1 dev-prop-int: host_connected: 1 dev: virtio-net-s390, id "" dev-prop: mac = 52:54:00:12:34:56 dev-prop: vlan = 0 dev-prop: netdev = (qemu) quit You can see that on s390 there is a Bus called 's390-virtio'. This works also on our s390x (z9) Machine. Regards Patrick Siegl Am 22.04.2011 11:00, schrieb Michal Pr?vozn?k: > On 04/22/2011 10:19 AM, Jiri Denemark wrote: >> On Fri, Apr 22, 2011 at 09:58:38 +0200, Michal Privoznik wrote: >>> The patch which moved libpciaccess initialization to one place caused >>> regression - we were not able to run on system with no PCI bus, like >>> s390(x). This patch fix it. >>> --- >>> src/node_device/node_device_udev.c | 6 ++++++ >>> 1 files changed, 6 insertions(+), 0 deletions(-) >>> >>> diff --git a/src/node_device/node_device_udev.c >>> b/src/node_device/node_device_udev.c >>> index 2139ef3..b6335ff 100644 >>> --- a/src/node_device/node_device_udev.c >>> +++ b/src/node_device/node_device_udev.c >>> @@ -1603,7 +1603,13 @@ static int udevDeviceMonitorStartup(int >>> privileged) >>> char ebuf[256]; >>> VIR_ERROR(_("Failed to initialize libpciaccess: %s"), >>> virStrerror(pciret, ebuf, sizeof ebuf)); >>> +#if defined __s390__ || defined __s390x_ >>> + /* On x390(x) system there is no PCI bus. >>> + * Therefore we do not want to return error here */ >>> + ret = 0; >>> +#else >>> ret = -1; >>> +#endif >>> goto out; >>> } >>> } >> >> Why do we try to initialize libpciaccess if we know it won't succeed? >> What >> about just completely dropping libpciaccess dependency on s390(x)? >> >> Jirka > > Well, > although investigation on the internet shows there is at least > PCI-like bus, linux kernel doesn't know how to use it (see > arch/s390/include/asm/pci.h) which is the most important. so NAK and > prepare v2. > > Michal > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list From mprivozn at redhat.com Fri Apr 22 12:24:54 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Fri, 22 Apr 2011 14:24:54 +0200 Subject: [libvirt] [PATCH v2] Fix disability to run on systems with no PCI bus Message-ID: <1303475094-13229-1-git-send-email-mprivozn@redhat.com> The patch which moved libpciaccess initialization to one place caused regression - we were not able to run on system with no PCI bus, like s390(x). --- src/node_device/node_device_udev.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index 2139ef3..fcff252 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -1421,8 +1421,12 @@ static int udevDeviceMonitorShutdown(void) ret = -1; } +#if defined __s390__ || defined __s390x_ + /* Nothing was initialized, nothing needs to be cleaned up */ +#else /* pci_system_cleanup returns void */ pci_system_cleanup(); +#endif return ret; } @@ -1595,6 +1599,10 @@ static int udevDeviceMonitorStartup(int privileged) int ret = 0; int pciret; +#if defined __s390__ || defined __s390x_ + /* On x390(x) system there is no PCI bus. + * Therefore there is nothing to initialize here. */ +#else if ((pciret = pci_system_init()) != 0) { /* Ignore failure as non-root; udev is not as helpful in that * situation, but a non-privileged user won't benefit much @@ -1607,6 +1615,7 @@ static int udevDeviceMonitorStartup(int privileged) goto out; } } +#endif if (VIR_ALLOC(priv) < 0) { virReportOOMError(); -- 1.7.4.4 From flameeyes at gmail.com Fri Apr 22 14:34:07 2011 From: flameeyes at gmail.com (Diego Elio =?ISO-8859-1?Q?Petten=F2?=) Date: Fri, 22 Apr 2011 16:34:07 +0200 Subject: [libvirt] [PATCH v2] Fix disability to run on systems with no PCI bus In-Reply-To: <1303475094-13229-1-git-send-email-mprivozn@redhat.com> References: <1303475094-13229-1-git-send-email-mprivozn@redhat.com> Message-ID: <1303482847.2367.8.camel@raven.home.flameeyes.eu> Il giorno ven, 22/04/2011 alle 14.24 +0200, Michal Privoznik ha scritto: > + /* On x390(x) system there is no PCI bus. > Looks like a typo? -- Diego Elio Petten? ? Flameeyes http://blog.flameeyes.eu/ From eblake at redhat.com Fri Apr 22 15:54:03 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 22 Apr 2011 09:54:03 -0600 Subject: [libvirt] [PATCH] qemu: Add flags checking in DomainCoreDump In-Reply-To: References: Message-ID: <4DB1A49B.8030107@redhat.com> On 04/22/2011 04:03 AM, Jiri Denemark wrote: > --- > src/qemu/qemu_driver.c | 5 ++++- > 1 files changed, 4 insertions(+), 1 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index f6e503a..f35616d 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -2345,7 +2345,8 @@ getCompressionType(struct qemud_driver *driver) > > static int qemudDomainCoreDump(virDomainPtr dom, > const char *path, > - int flags ATTRIBUTE_UNUSED) { > + int flags) > +{ > struct qemud_driver *driver = dom->conn->privateData; > virDomainObjPtr vm; > int resume = 0, paused = 0; > @@ -2353,6 +2354,8 @@ static int qemudDomainCoreDump(virDomainPtr dom, > virDomainEventPtr event = NULL; > qemuDomainObjPrivatePtr priv; > > + virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1); > + ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 22 15:57:46 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 22 Apr 2011 09:57:46 -0600 Subject: [libvirt] [PATCH] Make the options "--crash" and "--live" of "virsh dump" mutually exclusive In-Reply-To: <20110422095709.GK1245361@orkuz.home> References: <4DB14812.2020509@redhat.com> <20110422095709.GK1245361@orkuz.home> Message-ID: <4DB1A57A.1010202@redhat.com> On 04/22/2011 03:57 AM, Jiri Denemark wrote: >> This patch makes the options "--crash" and "--live" of "virsh dump" mutually exclusive > Moreover, this would only protect virsh. It's better to have this check in > virDomainCoreDump() so that all users can get the error. Agreed. > > The following patch should fix these issues. > > Subject: [PATCH] Make crash and live flags mutually exclusive in > virDomainCoreDump > Mail-Followup-To: libvir-list at redhat.com > > They don't make any sense when used together. > --- > src/libvirt.c | 6 ++++++ > 1 files changed, 6 insertions(+), 0 deletions(-) > > diff --git a/src/libvirt.c b/src/libvirt.c > index 10c3cdf..2d56b77 100644 > --- a/src/libvirt.c > +++ b/src/libvirt.c > @@ -2379,6 +2379,12 @@ virDomainCoreDump(virDomainPtr domain, const char *to, int flags) > goto error; > } > > + if ((flags & VIR_DUMP_CRASH) && (flags & VIR_DUMP_LIVE)) { > + virLibDomainError(VIR_ERR_INVALID_ARG, > + _("crash and live flags are mutually exclusive")); ACK, but incomplete. A few lines earlier, the documentation states: * @flags: extra flags, currently unused * * This method will dump the core of a domain on a given file for analysis. It would be a wise time to update the docs at the same time :) -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Fri Apr 22 16:11:16 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 22 Apr 2011 18:11:16 +0200 Subject: [libvirt] [PATCH] daemon: Honor error variable name change in the generator Message-ID: <20110422161116.GA19599@sbox> Commit 36b652138be renamed err to rerr, do the same in the generator. --- daemon/qemu_dispatch_prototypes.h | 2 +- daemon/remote_dispatch_prototypes.h | 404 +++++++++++++++++----------------- daemon/remote_generate_stubs.pl | 2 +- 3 files changed, 204 insertions(+), 204 deletions(-) diff --git a/daemon/qemu_dispatch_prototypes.h b/daemon/qemu_dispatch_prototypes.h index e6c83ba..4ec1ab4 100644 --- a/daemon/qemu_dispatch_prototypes.h +++ b/daemon/qemu_dispatch_prototypes.h @@ -7,6 +7,6 @@ static int qemuDispatchMonitorCommand( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, qemu_monitor_command_args *args, qemu_monitor_command_ret *ret); diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 18bf41d..cf2f38c 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -7,7 +7,7 @@ static int remoteDispatchAuthList( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_auth_list_ret *ret); static int remoteDispatchAuthPolkit( @@ -15,7 +15,7 @@ static int remoteDispatchAuthPolkit( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_auth_polkit_ret *ret); static int remoteDispatchAuthSaslInit( @@ -23,7 +23,7 @@ static int remoteDispatchAuthSaslInit( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_auth_sasl_init_ret *ret); static int remoteDispatchAuthSaslStart( @@ -31,7 +31,7 @@ static int remoteDispatchAuthSaslStart( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_auth_sasl_start_args *args, remote_auth_sasl_start_ret *ret); static int remoteDispatchAuthSaslStep( @@ -39,7 +39,7 @@ static int remoteDispatchAuthSaslStep( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_auth_sasl_step_args *args, remote_auth_sasl_step_ret *ret); static int remoteDispatchClose( @@ -47,7 +47,7 @@ static int remoteDispatchClose( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, void *ret); static int remoteDispatchCpuBaseline( @@ -55,7 +55,7 @@ static int remoteDispatchCpuBaseline( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_cpu_baseline_args *args, remote_cpu_baseline_ret *ret); static int remoteDispatchCpuCompare( @@ -63,7 +63,7 @@ static int remoteDispatchCpuCompare( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_cpu_compare_args *args, remote_cpu_compare_ret *ret); static int remoteDispatchDomainAbortJob( @@ -71,7 +71,7 @@ static int remoteDispatchDomainAbortJob( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_abort_job_args *args, void *ret); static int remoteDispatchDomainAttachDevice( @@ -79,7 +79,7 @@ static int remoteDispatchDomainAttachDevice( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_attach_device_args *args, void *ret); static int remoteDispatchDomainAttachDeviceFlags( @@ -87,7 +87,7 @@ static int remoteDispatchDomainAttachDeviceFlags( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_attach_device_flags_args *args, void *ret); static int remoteDispatchDomainBlockPeek( @@ -95,7 +95,7 @@ static int remoteDispatchDomainBlockPeek( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_block_peek_args *args, remote_domain_block_peek_ret *ret); static int remoteDispatchDomainBlockStats( @@ -103,7 +103,7 @@ static int remoteDispatchDomainBlockStats( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_block_stats_args *args, remote_domain_block_stats_ret *ret); static int remoteDispatchDomainCoreDump( @@ -111,7 +111,7 @@ static int remoteDispatchDomainCoreDump( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_core_dump_args *args, void *ret); static int remoteDispatchDomainCreate( @@ -119,7 +119,7 @@ static int remoteDispatchDomainCreate( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_create_args *args, void *ret); static int remoteDispatchDomainCreateWithFlags( @@ -127,7 +127,7 @@ static int remoteDispatchDomainCreateWithFlags( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_create_with_flags_args *args, remote_domain_create_with_flags_ret *ret); static int remoteDispatchDomainCreateXml( @@ -135,7 +135,7 @@ static int remoteDispatchDomainCreateXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_create_xml_args *args, remote_domain_create_xml_ret *ret); static int remoteDispatchDomainDefineXml( @@ -143,7 +143,7 @@ static int remoteDispatchDomainDefineXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_define_xml_args *args, remote_domain_define_xml_ret *ret); static int remoteDispatchDomainDestroy( @@ -151,7 +151,7 @@ static int remoteDispatchDomainDestroy( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_destroy_args *args, void *ret); static int remoteDispatchDomainDetachDevice( @@ -159,7 +159,7 @@ static int remoteDispatchDomainDetachDevice( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_detach_device_args *args, void *ret); static int remoteDispatchDomainDetachDeviceFlags( @@ -167,7 +167,7 @@ static int remoteDispatchDomainDetachDeviceFlags( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_detach_device_flags_args *args, void *ret); static int remoteDispatchDomainDumpXml( @@ -175,7 +175,7 @@ static int remoteDispatchDomainDumpXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_dump_xml_args *args, remote_domain_dump_xml_ret *ret); static int remoteDispatchDomainEventsDeregister( @@ -183,7 +183,7 @@ static int remoteDispatchDomainEventsDeregister( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_domain_events_deregister_ret *ret); static int remoteDispatchDomainEventsDeregisterAny( @@ -191,7 +191,7 @@ static int remoteDispatchDomainEventsDeregisterAny( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_events_deregister_any_args *args, void *ret); static int remoteDispatchDomainEventsRegister( @@ -199,7 +199,7 @@ static int remoteDispatchDomainEventsRegister( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_domain_events_register_ret *ret); static int remoteDispatchDomainEventsRegisterAny( @@ -207,7 +207,7 @@ static int remoteDispatchDomainEventsRegisterAny( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_events_register_any_args *args, void *ret); static int remoteDispatchDomainGetAutostart( @@ -215,7 +215,7 @@ static int remoteDispatchDomainGetAutostart( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_autostart_args *args, remote_domain_get_autostart_ret *ret); static int remoteDispatchDomainGetBlkioParameters( @@ -223,7 +223,7 @@ static int remoteDispatchDomainGetBlkioParameters( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_blkio_parameters_args *args, remote_domain_get_blkio_parameters_ret *ret); static int remoteDispatchDomainGetBlockInfo( @@ -231,7 +231,7 @@ static int remoteDispatchDomainGetBlockInfo( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_block_info_args *args, remote_domain_get_block_info_ret *ret); static int remoteDispatchDomainGetInfo( @@ -239,7 +239,7 @@ static int remoteDispatchDomainGetInfo( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_info_args *args, remote_domain_get_info_ret *ret); static int remoteDispatchDomainGetJobInfo( @@ -247,7 +247,7 @@ static int remoteDispatchDomainGetJobInfo( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_job_info_args *args, remote_domain_get_job_info_ret *ret); static int remoteDispatchDomainGetMaxMemory( @@ -255,7 +255,7 @@ static int remoteDispatchDomainGetMaxMemory( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_max_memory_args *args, remote_domain_get_max_memory_ret *ret); static int remoteDispatchDomainGetMaxVcpus( @@ -263,7 +263,7 @@ static int remoteDispatchDomainGetMaxVcpus( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_max_vcpus_args *args, remote_domain_get_max_vcpus_ret *ret); static int remoteDispatchDomainGetMemoryParameters( @@ -271,7 +271,7 @@ static int remoteDispatchDomainGetMemoryParameters( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_memory_parameters_args *args, remote_domain_get_memory_parameters_ret *ret); static int remoteDispatchDomainGetOsType( @@ -279,7 +279,7 @@ static int remoteDispatchDomainGetOsType( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_os_type_args *args, remote_domain_get_os_type_ret *ret); static int remoteDispatchDomainGetSchedulerParameters( @@ -287,7 +287,7 @@ static int remoteDispatchDomainGetSchedulerParameters( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_scheduler_parameters_args *args, remote_domain_get_scheduler_parameters_ret *ret); static int remoteDispatchDomainGetSchedulerType( @@ -295,7 +295,7 @@ static int remoteDispatchDomainGetSchedulerType( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_scheduler_type_args *args, remote_domain_get_scheduler_type_ret *ret); static int remoteDispatchDomainGetSecurityLabel( @@ -303,7 +303,7 @@ static int remoteDispatchDomainGetSecurityLabel( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_security_label_args *args, remote_domain_get_security_label_ret *ret); static int remoteDispatchDomainGetVcpus( @@ -311,7 +311,7 @@ static int remoteDispatchDomainGetVcpus( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_vcpus_args *args, remote_domain_get_vcpus_ret *ret); static int remoteDispatchDomainGetVcpusFlags( @@ -319,7 +319,7 @@ static int remoteDispatchDomainGetVcpusFlags( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_get_vcpus_flags_args *args, remote_domain_get_vcpus_flags_ret *ret); static int remoteDispatchDomainHasCurrentSnapshot( @@ -327,7 +327,7 @@ static int remoteDispatchDomainHasCurrentSnapshot( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_has_current_snapshot_args *args, remote_domain_has_current_snapshot_ret *ret); static int remoteDispatchDomainHasManagedSaveImage( @@ -335,7 +335,7 @@ static int remoteDispatchDomainHasManagedSaveImage( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_has_managed_save_image_args *args, remote_domain_has_managed_save_image_ret *ret); static int remoteDispatchDomainInterfaceStats( @@ -343,7 +343,7 @@ static int remoteDispatchDomainInterfaceStats( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_interface_stats_args *args, remote_domain_interface_stats_ret *ret); static int remoteDispatchDomainIsActive( @@ -351,7 +351,7 @@ static int remoteDispatchDomainIsActive( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_is_active_args *args, remote_domain_is_active_ret *ret); static int remoteDispatchDomainIsPersistent( @@ -359,7 +359,7 @@ static int remoteDispatchDomainIsPersistent( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_is_persistent_args *args, remote_domain_is_persistent_ret *ret); static int remoteDispatchDomainIsUpdated( @@ -367,7 +367,7 @@ static int remoteDispatchDomainIsUpdated( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_is_updated_args *args, remote_domain_is_updated_ret *ret); static int remoteDispatchDomainLookupById( @@ -375,7 +375,7 @@ static int remoteDispatchDomainLookupById( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_lookup_by_id_args *args, remote_domain_lookup_by_id_ret *ret); static int remoteDispatchDomainLookupByName( @@ -383,7 +383,7 @@ static int remoteDispatchDomainLookupByName( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_lookup_by_name_args *args, remote_domain_lookup_by_name_ret *ret); static int remoteDispatchDomainLookupByUuid( @@ -391,7 +391,7 @@ static int remoteDispatchDomainLookupByUuid( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_lookup_by_uuid_args *args, remote_domain_lookup_by_uuid_ret *ret); static int remoteDispatchDomainManagedSave( @@ -399,7 +399,7 @@ static int remoteDispatchDomainManagedSave( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_managed_save_args *args, void *ret); static int remoteDispatchDomainManagedSaveRemove( @@ -407,7 +407,7 @@ static int remoteDispatchDomainManagedSaveRemove( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_managed_save_remove_args *args, void *ret); static int remoteDispatchDomainMemoryPeek( @@ -415,7 +415,7 @@ static int remoteDispatchDomainMemoryPeek( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_memory_peek_args *args, remote_domain_memory_peek_ret *ret); static int remoteDispatchDomainMemoryStats( @@ -423,7 +423,7 @@ static int remoteDispatchDomainMemoryStats( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_memory_stats_args *args, remote_domain_memory_stats_ret *ret); static int remoteDispatchDomainMigrateFinish( @@ -431,7 +431,7 @@ static int remoteDispatchDomainMigrateFinish( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_migrate_finish_args *args, remote_domain_migrate_finish_ret *ret); static int remoteDispatchDomainMigrateFinish2( @@ -439,7 +439,7 @@ static int remoteDispatchDomainMigrateFinish2( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_migrate_finish2_args *args, remote_domain_migrate_finish2_ret *ret); static int remoteDispatchDomainMigratePerform( @@ -447,7 +447,7 @@ static int remoteDispatchDomainMigratePerform( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_migrate_perform_args *args, void *ret); static int remoteDispatchDomainMigratePrepare( @@ -455,7 +455,7 @@ static int remoteDispatchDomainMigratePrepare( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_migrate_prepare_args *args, remote_domain_migrate_prepare_ret *ret); static int remoteDispatchDomainMigratePrepare2( @@ -463,7 +463,7 @@ static int remoteDispatchDomainMigratePrepare2( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_migrate_prepare2_args *args, remote_domain_migrate_prepare2_ret *ret); static int remoteDispatchDomainMigratePrepareTunnel( @@ -471,7 +471,7 @@ static int remoteDispatchDomainMigratePrepareTunnel( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_migrate_prepare_tunnel_args *args, void *ret); static int remoteDispatchDomainMigrateSetMaxDowntime( @@ -479,7 +479,7 @@ static int remoteDispatchDomainMigrateSetMaxDowntime( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_migrate_set_max_downtime_args *args, void *ret); static int remoteDispatchDomainMigrateSetMaxSpeed( @@ -487,7 +487,7 @@ static int remoteDispatchDomainMigrateSetMaxSpeed( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_migrate_set_max_speed_args *args, void *ret); static int remoteDispatchDomainOpenConsole( @@ -495,7 +495,7 @@ static int remoteDispatchDomainOpenConsole( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_open_console_args *args, void *ret); static int remoteDispatchDomainPinVcpu( @@ -503,7 +503,7 @@ static int remoteDispatchDomainPinVcpu( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_pin_vcpu_args *args, void *ret); static int remoteDispatchDomainReboot( @@ -511,7 +511,7 @@ static int remoteDispatchDomainReboot( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_reboot_args *args, void *ret); static int remoteDispatchDomainRestore( @@ -519,7 +519,7 @@ static int remoteDispatchDomainRestore( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_restore_args *args, void *ret); static int remoteDispatchDomainResume( @@ -527,7 +527,7 @@ static int remoteDispatchDomainResume( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_resume_args *args, void *ret); static int remoteDispatchDomainRevertToSnapshot( @@ -535,7 +535,7 @@ static int remoteDispatchDomainRevertToSnapshot( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_revert_to_snapshot_args *args, void *ret); static int remoteDispatchDomainSave( @@ -543,7 +543,7 @@ static int remoteDispatchDomainSave( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_save_args *args, void *ret); static int remoteDispatchDomainSetAutostart( @@ -551,7 +551,7 @@ static int remoteDispatchDomainSetAutostart( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_set_autostart_args *args, void *ret); static int remoteDispatchDomainSetBlkioParameters( @@ -559,7 +559,7 @@ static int remoteDispatchDomainSetBlkioParameters( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_set_blkio_parameters_args *args, void *ret); static int remoteDispatchDomainSetMaxMemory( @@ -567,7 +567,7 @@ static int remoteDispatchDomainSetMaxMemory( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_set_max_memory_args *args, void *ret); static int remoteDispatchDomainSetMemory( @@ -575,7 +575,7 @@ static int remoteDispatchDomainSetMemory( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_set_memory_args *args, void *ret); static int remoteDispatchDomainSetMemoryFlags( @@ -583,7 +583,7 @@ static int remoteDispatchDomainSetMemoryFlags( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_set_memory_flags_args *args, void *ret); static int remoteDispatchDomainSetMemoryParameters( @@ -591,7 +591,7 @@ static int remoteDispatchDomainSetMemoryParameters( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_set_memory_parameters_args *args, void *ret); static int remoteDispatchDomainSetSchedulerParameters( @@ -599,7 +599,7 @@ static int remoteDispatchDomainSetSchedulerParameters( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_set_scheduler_parameters_args *args, void *ret); static int remoteDispatchDomainSetVcpus( @@ -607,7 +607,7 @@ static int remoteDispatchDomainSetVcpus( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_set_vcpus_args *args, void *ret); static int remoteDispatchDomainSetVcpusFlags( @@ -615,7 +615,7 @@ static int remoteDispatchDomainSetVcpusFlags( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_set_vcpus_flags_args *args, void *ret); static int remoteDispatchDomainShutdown( @@ -623,7 +623,7 @@ static int remoteDispatchDomainShutdown( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_shutdown_args *args, void *ret); static int remoteDispatchDomainSnapshotCreateXml( @@ -631,7 +631,7 @@ static int remoteDispatchDomainSnapshotCreateXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_snapshot_create_xml_args *args, remote_domain_snapshot_create_xml_ret *ret); static int remoteDispatchDomainSnapshotCurrent( @@ -639,7 +639,7 @@ static int remoteDispatchDomainSnapshotCurrent( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_snapshot_current_args *args, remote_domain_snapshot_current_ret *ret); static int remoteDispatchDomainSnapshotDelete( @@ -647,7 +647,7 @@ static int remoteDispatchDomainSnapshotDelete( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_snapshot_delete_args *args, void *ret); static int remoteDispatchDomainSnapshotDumpXml( @@ -655,7 +655,7 @@ static int remoteDispatchDomainSnapshotDumpXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_snapshot_dump_xml_args *args, remote_domain_snapshot_dump_xml_ret *ret); static int remoteDispatchDomainSnapshotListNames( @@ -663,7 +663,7 @@ static int remoteDispatchDomainSnapshotListNames( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_snapshot_list_names_args *args, remote_domain_snapshot_list_names_ret *ret); static int remoteDispatchDomainSnapshotLookupByName( @@ -671,7 +671,7 @@ static int remoteDispatchDomainSnapshotLookupByName( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_snapshot_lookup_by_name_args *args, remote_domain_snapshot_lookup_by_name_ret *ret); static int remoteDispatchDomainSnapshotNum( @@ -679,7 +679,7 @@ static int remoteDispatchDomainSnapshotNum( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_snapshot_num_args *args, remote_domain_snapshot_num_ret *ret); static int remoteDispatchDomainSuspend( @@ -687,7 +687,7 @@ static int remoteDispatchDomainSuspend( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_suspend_args *args, void *ret); static int remoteDispatchDomainUndefine( @@ -695,7 +695,7 @@ static int remoteDispatchDomainUndefine( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_undefine_args *args, void *ret); static int remoteDispatchDomainUpdateDeviceFlags( @@ -703,7 +703,7 @@ static int remoteDispatchDomainUpdateDeviceFlags( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_update_device_flags_args *args, void *ret); static int remoteDispatchDomainXmlFromNative( @@ -711,7 +711,7 @@ static int remoteDispatchDomainXmlFromNative( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_xml_from_native_args *args, remote_domain_xml_from_native_ret *ret); static int remoteDispatchDomainXmlToNative( @@ -719,7 +719,7 @@ static int remoteDispatchDomainXmlToNative( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_domain_xml_to_native_args *args, remote_domain_xml_to_native_ret *ret); static int remoteDispatchFindStoragePoolSources( @@ -727,7 +727,7 @@ static int remoteDispatchFindStoragePoolSources( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_find_storage_pool_sources_args *args, remote_find_storage_pool_sources_ret *ret); static int remoteDispatchGetCapabilities( @@ -735,7 +735,7 @@ static int remoteDispatchGetCapabilities( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_get_capabilities_ret *ret); static int remoteDispatchGetHostname( @@ -743,7 +743,7 @@ static int remoteDispatchGetHostname( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_get_hostname_ret *ret); static int remoteDispatchGetLibVersion( @@ -751,7 +751,7 @@ static int remoteDispatchGetLibVersion( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_get_lib_version_ret *ret); static int remoteDispatchGetMaxVcpus( @@ -759,7 +759,7 @@ static int remoteDispatchGetMaxVcpus( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_get_max_vcpus_args *args, remote_get_max_vcpus_ret *ret); static int remoteDispatchGetSysinfo( @@ -767,7 +767,7 @@ static int remoteDispatchGetSysinfo( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_get_sysinfo_args *args, remote_get_sysinfo_ret *ret); static int remoteDispatchGetType( @@ -775,7 +775,7 @@ static int remoteDispatchGetType( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_get_type_ret *ret); static int remoteDispatchGetUri( @@ -783,7 +783,7 @@ static int remoteDispatchGetUri( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_get_uri_ret *ret); static int remoteDispatchGetVersion( @@ -791,7 +791,7 @@ static int remoteDispatchGetVersion( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_get_version_ret *ret); static int remoteDispatchInterfaceCreate( @@ -799,7 +799,7 @@ static int remoteDispatchInterfaceCreate( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_interface_create_args *args, void *ret); static int remoteDispatchInterfaceDefineXml( @@ -807,7 +807,7 @@ static int remoteDispatchInterfaceDefineXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_interface_define_xml_args *args, remote_interface_define_xml_ret *ret); static int remoteDispatchInterfaceDestroy( @@ -815,7 +815,7 @@ static int remoteDispatchInterfaceDestroy( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_interface_destroy_args *args, void *ret); static int remoteDispatchInterfaceGetXmlDesc( @@ -823,7 +823,7 @@ static int remoteDispatchInterfaceGetXmlDesc( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_interface_get_xml_desc_args *args, remote_interface_get_xml_desc_ret *ret); static int remoteDispatchInterfaceIsActive( @@ -831,7 +831,7 @@ static int remoteDispatchInterfaceIsActive( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_interface_is_active_args *args, remote_interface_is_active_ret *ret); static int remoteDispatchInterfaceLookupByMacString( @@ -839,7 +839,7 @@ static int remoteDispatchInterfaceLookupByMacString( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_interface_lookup_by_mac_string_args *args, remote_interface_lookup_by_mac_string_ret *ret); static int remoteDispatchInterfaceLookupByName( @@ -847,7 +847,7 @@ static int remoteDispatchInterfaceLookupByName( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_interface_lookup_by_name_args *args, remote_interface_lookup_by_name_ret *ret); static int remoteDispatchInterfaceUndefine( @@ -855,7 +855,7 @@ static int remoteDispatchInterfaceUndefine( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_interface_undefine_args *args, void *ret); static int remoteDispatchIsSecure( @@ -863,7 +863,7 @@ static int remoteDispatchIsSecure( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_is_secure_ret *ret); static int remoteDispatchListDefinedDomains( @@ -871,7 +871,7 @@ static int remoteDispatchListDefinedDomains( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_list_defined_domains_args *args, remote_list_defined_domains_ret *ret); static int remoteDispatchListDefinedInterfaces( @@ -879,7 +879,7 @@ static int remoteDispatchListDefinedInterfaces( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_list_defined_interfaces_args *args, remote_list_defined_interfaces_ret *ret); static int remoteDispatchListDefinedNetworks( @@ -887,7 +887,7 @@ static int remoteDispatchListDefinedNetworks( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_list_defined_networks_args *args, remote_list_defined_networks_ret *ret); static int remoteDispatchListDefinedStoragePools( @@ -895,7 +895,7 @@ static int remoteDispatchListDefinedStoragePools( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_list_defined_storage_pools_args *args, remote_list_defined_storage_pools_ret *ret); static int remoteDispatchListDomains( @@ -903,7 +903,7 @@ static int remoteDispatchListDomains( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_list_domains_args *args, remote_list_domains_ret *ret); static int remoteDispatchListInterfaces( @@ -911,7 +911,7 @@ static int remoteDispatchListInterfaces( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_list_interfaces_args *args, remote_list_interfaces_ret *ret); static int remoteDispatchListNetworks( @@ -919,7 +919,7 @@ static int remoteDispatchListNetworks( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_list_networks_args *args, remote_list_networks_ret *ret); static int remoteDispatchListNwfilters( @@ -927,7 +927,7 @@ static int remoteDispatchListNwfilters( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_list_nwfilters_args *args, remote_list_nwfilters_ret *ret); static int remoteDispatchListSecrets( @@ -935,7 +935,7 @@ static int remoteDispatchListSecrets( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_list_secrets_args *args, remote_list_secrets_ret *ret); static int remoteDispatchListStoragePools( @@ -943,7 +943,7 @@ static int remoteDispatchListStoragePools( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_list_storage_pools_args *args, remote_list_storage_pools_ret *ret); static int remoteDispatchNetworkCreate( @@ -951,7 +951,7 @@ static int remoteDispatchNetworkCreate( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_create_args *args, void *ret); static int remoteDispatchNetworkCreateXml( @@ -959,7 +959,7 @@ static int remoteDispatchNetworkCreateXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_create_xml_args *args, remote_network_create_xml_ret *ret); static int remoteDispatchNetworkDefineXml( @@ -967,7 +967,7 @@ static int remoteDispatchNetworkDefineXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_define_xml_args *args, remote_network_define_xml_ret *ret); static int remoteDispatchNetworkDestroy( @@ -975,7 +975,7 @@ static int remoteDispatchNetworkDestroy( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_destroy_args *args, void *ret); static int remoteDispatchNetworkDumpXml( @@ -983,7 +983,7 @@ static int remoteDispatchNetworkDumpXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_dump_xml_args *args, remote_network_dump_xml_ret *ret); static int remoteDispatchNetworkGetAutostart( @@ -991,7 +991,7 @@ static int remoteDispatchNetworkGetAutostart( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_get_autostart_args *args, remote_network_get_autostart_ret *ret); static int remoteDispatchNetworkGetBridgeName( @@ -999,7 +999,7 @@ static int remoteDispatchNetworkGetBridgeName( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_get_bridge_name_args *args, remote_network_get_bridge_name_ret *ret); static int remoteDispatchNetworkIsActive( @@ -1007,7 +1007,7 @@ static int remoteDispatchNetworkIsActive( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_is_active_args *args, remote_network_is_active_ret *ret); static int remoteDispatchNetworkIsPersistent( @@ -1015,7 +1015,7 @@ static int remoteDispatchNetworkIsPersistent( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_is_persistent_args *args, remote_network_is_persistent_ret *ret); static int remoteDispatchNetworkLookupByName( @@ -1023,7 +1023,7 @@ static int remoteDispatchNetworkLookupByName( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_lookup_by_name_args *args, remote_network_lookup_by_name_ret *ret); static int remoteDispatchNetworkLookupByUuid( @@ -1031,7 +1031,7 @@ static int remoteDispatchNetworkLookupByUuid( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_lookup_by_uuid_args *args, remote_network_lookup_by_uuid_ret *ret); static int remoteDispatchNetworkSetAutostart( @@ -1039,7 +1039,7 @@ static int remoteDispatchNetworkSetAutostart( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_set_autostart_args *args, void *ret); static int remoteDispatchNetworkUndefine( @@ -1047,7 +1047,7 @@ static int remoteDispatchNetworkUndefine( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_network_undefine_args *args, void *ret); static int remoteDispatchNodeDeviceCreateXml( @@ -1055,7 +1055,7 @@ static int remoteDispatchNodeDeviceCreateXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_device_create_xml_args *args, remote_node_device_create_xml_ret *ret); static int remoteDispatchNodeDeviceDestroy( @@ -1063,7 +1063,7 @@ static int remoteDispatchNodeDeviceDestroy( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_device_destroy_args *args, void *ret); static int remoteDispatchNodeDeviceDettach( @@ -1071,7 +1071,7 @@ static int remoteDispatchNodeDeviceDettach( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_device_dettach_args *args, void *ret); static int remoteDispatchNodeDeviceDumpXml( @@ -1079,7 +1079,7 @@ static int remoteDispatchNodeDeviceDumpXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_device_dump_xml_args *args, remote_node_device_dump_xml_ret *ret); static int remoteDispatchNodeDeviceGetParent( @@ -1087,7 +1087,7 @@ static int remoteDispatchNodeDeviceGetParent( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_device_get_parent_args *args, remote_node_device_get_parent_ret *ret); static int remoteDispatchNodeDeviceListCaps( @@ -1095,7 +1095,7 @@ static int remoteDispatchNodeDeviceListCaps( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_device_list_caps_args *args, remote_node_device_list_caps_ret *ret); static int remoteDispatchNodeDeviceLookupByName( @@ -1103,7 +1103,7 @@ static int remoteDispatchNodeDeviceLookupByName( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_device_lookup_by_name_args *args, remote_node_device_lookup_by_name_ret *ret); static int remoteDispatchNodeDeviceNumOfCaps( @@ -1111,7 +1111,7 @@ static int remoteDispatchNodeDeviceNumOfCaps( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_device_num_of_caps_args *args, remote_node_device_num_of_caps_ret *ret); static int remoteDispatchNodeDeviceReAttach( @@ -1119,7 +1119,7 @@ static int remoteDispatchNodeDeviceReAttach( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_device_re_attach_args *args, void *ret); static int remoteDispatchNodeDeviceReset( @@ -1127,7 +1127,7 @@ static int remoteDispatchNodeDeviceReset( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_device_reset_args *args, void *ret); static int remoteDispatchNodeGetCellsFreeMemory( @@ -1135,7 +1135,7 @@ static int remoteDispatchNodeGetCellsFreeMemory( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_get_cells_free_memory_args *args, remote_node_get_cells_free_memory_ret *ret); static int remoteDispatchNodeGetFreeMemory( @@ -1143,7 +1143,7 @@ static int remoteDispatchNodeGetFreeMemory( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_node_get_free_memory_ret *ret); static int remoteDispatchNodeGetInfo( @@ -1151,7 +1151,7 @@ static int remoteDispatchNodeGetInfo( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_node_get_info_ret *ret); static int remoteDispatchNodeGetSecurityModel( @@ -1159,7 +1159,7 @@ static int remoteDispatchNodeGetSecurityModel( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_node_get_security_model_ret *ret); static int remoteDispatchNodeListDevices( @@ -1167,7 +1167,7 @@ static int remoteDispatchNodeListDevices( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_list_devices_args *args, remote_node_list_devices_ret *ret); static int remoteDispatchNodeNumOfDevices( @@ -1175,7 +1175,7 @@ static int remoteDispatchNodeNumOfDevices( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_node_num_of_devices_args *args, remote_node_num_of_devices_ret *ret); static int remoteDispatchNumOfDefinedDomains( @@ -1183,7 +1183,7 @@ static int remoteDispatchNumOfDefinedDomains( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_num_of_defined_domains_ret *ret); static int remoteDispatchNumOfDefinedInterfaces( @@ -1191,7 +1191,7 @@ static int remoteDispatchNumOfDefinedInterfaces( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_num_of_defined_interfaces_ret *ret); static int remoteDispatchNumOfDefinedNetworks( @@ -1199,7 +1199,7 @@ static int remoteDispatchNumOfDefinedNetworks( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_num_of_defined_networks_ret *ret); static int remoteDispatchNumOfDefinedStoragePools( @@ -1207,7 +1207,7 @@ static int remoteDispatchNumOfDefinedStoragePools( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_num_of_defined_storage_pools_ret *ret); static int remoteDispatchNumOfDomains( @@ -1215,7 +1215,7 @@ static int remoteDispatchNumOfDomains( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_num_of_domains_ret *ret); static int remoteDispatchNumOfInterfaces( @@ -1223,7 +1223,7 @@ static int remoteDispatchNumOfInterfaces( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_num_of_interfaces_ret *ret); static int remoteDispatchNumOfNetworks( @@ -1231,7 +1231,7 @@ static int remoteDispatchNumOfNetworks( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_num_of_networks_ret *ret); static int remoteDispatchNumOfNwfilters( @@ -1239,7 +1239,7 @@ static int remoteDispatchNumOfNwfilters( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_num_of_nwfilters_ret *ret); static int remoteDispatchNumOfSecrets( @@ -1247,7 +1247,7 @@ static int remoteDispatchNumOfSecrets( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_num_of_secrets_ret *ret); static int remoteDispatchNumOfStoragePools( @@ -1255,7 +1255,7 @@ static int remoteDispatchNumOfStoragePools( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, void *args, remote_num_of_storage_pools_ret *ret); static int remoteDispatchNwfilterDefineXml( @@ -1263,7 +1263,7 @@ static int remoteDispatchNwfilterDefineXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_nwfilter_define_xml_args *args, remote_nwfilter_define_xml_ret *ret); static int remoteDispatchNwfilterGetXmlDesc( @@ -1271,7 +1271,7 @@ static int remoteDispatchNwfilterGetXmlDesc( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_nwfilter_get_xml_desc_args *args, remote_nwfilter_get_xml_desc_ret *ret); static int remoteDispatchNwfilterLookupByName( @@ -1279,7 +1279,7 @@ static int remoteDispatchNwfilterLookupByName( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_nwfilter_lookup_by_name_args *args, remote_nwfilter_lookup_by_name_ret *ret); static int remoteDispatchNwfilterLookupByUuid( @@ -1287,7 +1287,7 @@ static int remoteDispatchNwfilterLookupByUuid( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_nwfilter_lookup_by_uuid_args *args, remote_nwfilter_lookup_by_uuid_ret *ret); static int remoteDispatchNwfilterUndefine( @@ -1295,7 +1295,7 @@ static int remoteDispatchNwfilterUndefine( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_nwfilter_undefine_args *args, void *ret); static int remoteDispatchOpen( @@ -1303,7 +1303,7 @@ static int remoteDispatchOpen( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_open_args *args, void *ret); static int remoteDispatchSecretDefineXml( @@ -1311,7 +1311,7 @@ static int remoteDispatchSecretDefineXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_secret_define_xml_args *args, remote_secret_define_xml_ret *ret); static int remoteDispatchSecretGetValue( @@ -1319,7 +1319,7 @@ static int remoteDispatchSecretGetValue( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_secret_get_value_args *args, remote_secret_get_value_ret *ret); static int remoteDispatchSecretGetXmlDesc( @@ -1327,7 +1327,7 @@ static int remoteDispatchSecretGetXmlDesc( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_secret_get_xml_desc_args *args, remote_secret_get_xml_desc_ret *ret); static int remoteDispatchSecretLookupByUsage( @@ -1335,7 +1335,7 @@ static int remoteDispatchSecretLookupByUsage( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_secret_lookup_by_usage_args *args, remote_secret_lookup_by_usage_ret *ret); static int remoteDispatchSecretLookupByUuid( @@ -1343,7 +1343,7 @@ static int remoteDispatchSecretLookupByUuid( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_secret_lookup_by_uuid_args *args, remote_secret_lookup_by_uuid_ret *ret); static int remoteDispatchSecretSetValue( @@ -1351,7 +1351,7 @@ static int remoteDispatchSecretSetValue( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_secret_set_value_args *args, void *ret); static int remoteDispatchSecretUndefine( @@ -1359,7 +1359,7 @@ static int remoteDispatchSecretUndefine( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_secret_undefine_args *args, void *ret); static int remoteDispatchStoragePoolBuild( @@ -1367,7 +1367,7 @@ static int remoteDispatchStoragePoolBuild( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_build_args *args, void *ret); static int remoteDispatchStoragePoolCreate( @@ -1375,7 +1375,7 @@ static int remoteDispatchStoragePoolCreate( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_create_args *args, void *ret); static int remoteDispatchStoragePoolCreateXml( @@ -1383,7 +1383,7 @@ static int remoteDispatchStoragePoolCreateXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_create_xml_args *args, remote_storage_pool_create_xml_ret *ret); static int remoteDispatchStoragePoolDefineXml( @@ -1391,7 +1391,7 @@ static int remoteDispatchStoragePoolDefineXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_define_xml_args *args, remote_storage_pool_define_xml_ret *ret); static int remoteDispatchStoragePoolDelete( @@ -1399,7 +1399,7 @@ static int remoteDispatchStoragePoolDelete( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_delete_args *args, void *ret); static int remoteDispatchStoragePoolDestroy( @@ -1407,7 +1407,7 @@ static int remoteDispatchStoragePoolDestroy( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_destroy_args *args, void *ret); static int remoteDispatchStoragePoolDumpXml( @@ -1415,7 +1415,7 @@ static int remoteDispatchStoragePoolDumpXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_dump_xml_args *args, remote_storage_pool_dump_xml_ret *ret); static int remoteDispatchStoragePoolGetAutostart( @@ -1423,7 +1423,7 @@ static int remoteDispatchStoragePoolGetAutostart( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_get_autostart_args *args, remote_storage_pool_get_autostart_ret *ret); static int remoteDispatchStoragePoolGetInfo( @@ -1431,7 +1431,7 @@ static int remoteDispatchStoragePoolGetInfo( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_get_info_args *args, remote_storage_pool_get_info_ret *ret); static int remoteDispatchStoragePoolIsActive( @@ -1439,7 +1439,7 @@ static int remoteDispatchStoragePoolIsActive( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_is_active_args *args, remote_storage_pool_is_active_ret *ret); static int remoteDispatchStoragePoolIsPersistent( @@ -1447,7 +1447,7 @@ static int remoteDispatchStoragePoolIsPersistent( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_is_persistent_args *args, remote_storage_pool_is_persistent_ret *ret); static int remoteDispatchStoragePoolListVolumes( @@ -1455,7 +1455,7 @@ static int remoteDispatchStoragePoolListVolumes( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_list_volumes_args *args, remote_storage_pool_list_volumes_ret *ret); static int remoteDispatchStoragePoolLookupByName( @@ -1463,7 +1463,7 @@ static int remoteDispatchStoragePoolLookupByName( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_lookup_by_name_args *args, remote_storage_pool_lookup_by_name_ret *ret); static int remoteDispatchStoragePoolLookupByUuid( @@ -1471,7 +1471,7 @@ static int remoteDispatchStoragePoolLookupByUuid( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_lookup_by_uuid_args *args, remote_storage_pool_lookup_by_uuid_ret *ret); static int remoteDispatchStoragePoolLookupByVolume( @@ -1479,7 +1479,7 @@ static int remoteDispatchStoragePoolLookupByVolume( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_lookup_by_volume_args *args, remote_storage_pool_lookup_by_volume_ret *ret); static int remoteDispatchStoragePoolNumOfVolumes( @@ -1487,7 +1487,7 @@ static int remoteDispatchStoragePoolNumOfVolumes( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_num_of_volumes_args *args, remote_storage_pool_num_of_volumes_ret *ret); static int remoteDispatchStoragePoolRefresh( @@ -1495,7 +1495,7 @@ static int remoteDispatchStoragePoolRefresh( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_refresh_args *args, void *ret); static int remoteDispatchStoragePoolSetAutostart( @@ -1503,7 +1503,7 @@ static int remoteDispatchStoragePoolSetAutostart( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_set_autostart_args *args, void *ret); static int remoteDispatchStoragePoolUndefine( @@ -1511,7 +1511,7 @@ static int remoteDispatchStoragePoolUndefine( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_pool_undefine_args *args, void *ret); static int remoteDispatchStorageVolCreateXml( @@ -1519,7 +1519,7 @@ static int remoteDispatchStorageVolCreateXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_vol_create_xml_args *args, remote_storage_vol_create_xml_ret *ret); static int remoteDispatchStorageVolCreateXmlFrom( @@ -1527,7 +1527,7 @@ static int remoteDispatchStorageVolCreateXmlFrom( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_vol_create_xml_from_args *args, remote_storage_vol_create_xml_from_ret *ret); static int remoteDispatchStorageVolDelete( @@ -1535,7 +1535,7 @@ static int remoteDispatchStorageVolDelete( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_vol_delete_args *args, void *ret); static int remoteDispatchStorageVolDownload( @@ -1543,7 +1543,7 @@ static int remoteDispatchStorageVolDownload( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_vol_download_args *args, void *ret); static int remoteDispatchStorageVolDumpXml( @@ -1551,7 +1551,7 @@ static int remoteDispatchStorageVolDumpXml( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_vol_dump_xml_args *args, remote_storage_vol_dump_xml_ret *ret); static int remoteDispatchStorageVolGetInfo( @@ -1559,7 +1559,7 @@ static int remoteDispatchStorageVolGetInfo( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_vol_get_info_args *args, remote_storage_vol_get_info_ret *ret); static int remoteDispatchStorageVolGetPath( @@ -1567,7 +1567,7 @@ static int remoteDispatchStorageVolGetPath( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_vol_get_path_args *args, remote_storage_vol_get_path_ret *ret); static int remoteDispatchStorageVolLookupByKey( @@ -1575,7 +1575,7 @@ static int remoteDispatchStorageVolLookupByKey( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_vol_lookup_by_key_args *args, remote_storage_vol_lookup_by_key_ret *ret); static int remoteDispatchStorageVolLookupByName( @@ -1583,7 +1583,7 @@ static int remoteDispatchStorageVolLookupByName( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_vol_lookup_by_name_args *args, remote_storage_vol_lookup_by_name_ret *ret); static int remoteDispatchStorageVolLookupByPath( @@ -1591,7 +1591,7 @@ static int remoteDispatchStorageVolLookupByPath( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_vol_lookup_by_path_args *args, remote_storage_vol_lookup_by_path_ret *ret); static int remoteDispatchStorageVolUpload( @@ -1599,7 +1599,7 @@ static int remoteDispatchStorageVolUpload( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_vol_upload_args *args, void *ret); static int remoteDispatchStorageVolWipe( @@ -1607,7 +1607,7 @@ static int remoteDispatchStorageVolWipe( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_storage_vol_wipe_args *args, void *ret); static int remoteDispatchSupportsFeature( @@ -1615,6 +1615,6 @@ static int remoteDispatchSupportsFeature( struct qemud_client *client, virConnectPtr conn, remote_message_header *hdr, - remote_error *err, + remote_error *rerr, remote_supports_feature_args *args, remote_supports_feature_ret *ret); diff --git a/daemon/remote_generate_stubs.pl b/daemon/remote_generate_stubs.pl index a8c4e6d..dbde7da 100755 --- a/daemon/remote_generate_stubs.pl +++ b/daemon/remote_generate_stubs.pl @@ -132,7 +132,7 @@ elsif ($opt_p) { print " struct qemud_client *client,\n"; print " virConnectPtr conn,\n"; print " remote_message_header *hdr,\n"; - print " remote_error *err,\n"; + print " remote_error *rerr,\n"; print " $calls{$_}->{args} *args,\n"; print " $calls{$_}->{ret} *ret);\n"; } -- 1.7.0.4 From matthias.bolte at googlemail.com Fri Apr 22 16:11:54 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 22 Apr 2011 18:11:54 +0200 Subject: [libvirt] [PATCH] daemon: Don't try to free an unsigned int in error paths Message-ID: <20110422161154.GA20436@sbox> --- daemon/remote.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 54fef64..1c98bba 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -3681,7 +3681,7 @@ remoteDispatchListNetworks(struct qemud_server *server ATTRIBUTE_UNUSED, cleanup: if (rv < 0) { remoteDispatchError(rerr); - VIR_FREE(ret->names.names_len); + VIR_FREE(ret->names.names_val); } return rv; } @@ -4200,7 +4200,7 @@ remoteDispatchListInterfaces(struct qemud_server *server ATTRIBUTE_UNUSED, cleanup: if (rv < 0) { remoteDispatchError(rerr); - VIR_FREE(ret->names.names_len); + VIR_FREE(ret->names.names_val); } return rv; } @@ -4275,7 +4275,7 @@ remoteDispatchListDefinedInterfaces(struct qemud_server *server ATTRIBUTE_UNUSED cleanup: if (rv < 0) { remoteDispatchError(rerr); - VIR_FREE(ret->names.names_len); + VIR_FREE(ret->names.names_val); } return rv; } @@ -8544,7 +8544,7 @@ remoteDispatchListNwfilters(struct qemud_server *server ATTRIBUTE_UNUSED, cleanup: if (rv < 0) { remoteDispatchError(rerr); - VIR_FREE(ret->names.names_len); + VIR_FREE(ret->names.names_val); } return rv; } -- 1.7.0.4 From eblake at redhat.com Fri Apr 22 16:16:20 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 22 Apr 2011 10:16:20 -0600 Subject: [libvirt] [PATCH] daemon: Honor error variable name change in the generator In-Reply-To: <20110422161116.GA19599@sbox> References: <20110422161116.GA19599@sbox> Message-ID: <4DB1A9D4.8050609@redhat.com> On 04/22/2011 10:11 AM, Matthias Bolte wrote: > Commit 36b652138be renamed err to rerr, do the same in the generator. > --- > daemon/qemu_dispatch_prototypes.h | 2 +- > daemon/remote_dispatch_prototypes.h | 404 +++++++++++++++++----------------- > daemon/remote_generate_stubs.pl | 2 +- > 3 files changed, 204 insertions(+), 204 deletions(-) > > diff --git a/daemon/qemu_dispatch_prototypes.h b/daemon/qemu_dispatch_prototypes.h > index e6c83ba..4ec1ab4 100644 > --- a/daemon/qemu_dispatch_prototypes.h > +++ b/daemon/qemu_dispatch_prototypes.h > @@ -7,6 +7,6 @@ static int qemuDispatchMonitorCommand( > struct qemud_client *client, > virConnectPtr conn, > remote_message_header *hdr, > - remote_error *err, > + remote_error *rerr, Mechanical, and didn't spot any problems. ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 22 16:17:01 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 22 Apr 2011 10:17:01 -0600 Subject: [libvirt] [PATCH] daemon: Don't try to free an unsigned int in error paths In-Reply-To: <20110422161154.GA20436@sbox> References: <20110422161154.GA20436@sbox> Message-ID: <4DB1A9FD.6040200@redhat.com> On 04/22/2011 10:11 AM, Matthias Bolte wrote: > --- > daemon/remote.c | 8 ++++---- > 1 files changed, 4 insertions(+), 4 deletions(-) > > diff --git a/daemon/remote.c b/daemon/remote.c > index 54fef64..1c98bba 100644 > --- a/daemon/remote.c > +++ b/daemon/remote.c > @@ -3681,7 +3681,7 @@ remoteDispatchListNetworks(struct qemud_server *server ATTRIBUTE_UNUSED, > cleanup: > if (rv < 0) { > remoteDispatchError(rerr); > - VIR_FREE(ret->names.names_len); > + VIR_FREE(ret->names.names_val); And to think I missed those in the huge patch. Oops. ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From cfergeau at redhat.com Fri Apr 22 16:31:25 2011 From: cfergeau at redhat.com (Christophe Fergeau) Date: Fri, 22 Apr 2011 18:31:25 +0200 Subject: [libvirt] [PATCH] daemon: Don't try to free an unsigned int in error paths In-Reply-To: <4DB1A9FD.6040200@redhat.com> References: <20110422161154.GA20436@sbox> <4DB1A9FD.6040200@redhat.com> Message-ID: <20110422163125.GA3219@teriyaki.redhat.com> On Fri, Apr 22, 2011 at 10:17:01AM -0600, Eric Blake wrote: > On 04/22/2011 10:11 AM, Matthias Bolte wrote: > > remoteDispatchError(rerr); > > - VIR_FREE(ret->names.names_len); > > + VIR_FREE(ret->names.names_val); > > And to think I missed those in the huge patch. Oops. Maybe VIR_FREE should be changed to something like -# define VIR_FREE(ptr) virFree(&(ptr)) +# define VIR_FREE(ptr) \ + do { void *check_type = (ptr); virFree(&(check_type)); } while (0) so that the compiler can warn about such issues? With this change, I get remote.c: In function 'remoteDispatchListInterfaces': remote.c:3978:33: warning: initialization makes pointer from integer without a cast [enabled by default] I also get more warnings about casting from const to non-const, this can be avoided by making check_type const void *, but maybe these warnings indicate that something that shouldn't be freed is freed. Christophe -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 198 bytes Desc: not available URL: From eblake at redhat.com Fri Apr 22 16:55:04 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 22 Apr 2011 10:55:04 -0600 Subject: [libvirt] [PATCH] daemon: Don't try to free an unsigned int in error paths In-Reply-To: <20110422163125.GA3219@teriyaki.redhat.com> References: <20110422161154.GA20436@sbox> <4DB1A9FD.6040200@redhat.com> <20110422163125.GA3219@teriyaki.redhat.com> Message-ID: <4DB1B2E8.3030004@redhat.com> On 04/22/2011 10:31 AM, Christophe Fergeau wrote: > On Fri, Apr 22, 2011 at 10:17:01AM -0600, Eric Blake wrote: >> On 04/22/2011 10:11 AM, Matthias Bolte wrote: >>> remoteDispatchError(rerr); >>> - VIR_FREE(ret->names.names_len); >>> + VIR_FREE(ret->names.names_val); >> >> And to think I missed those in the huge patch. Oops. > > Maybe VIR_FREE should be changed to something like > > -# define VIR_FREE(ptr) virFree(&(ptr)) > +# define VIR_FREE(ptr) \ > + do { void *check_type = (ptr); virFree(&(check_type)); } while (0) Not quite. That assigns check_type to NULL, rather than the intended assignment of ptr. But the idea has merit; I'll see if I can come up with a variant that still evaluates ptr only once, by wrapping the type check in a sizeof hack. > I also get more warnings about casting from const to non-const, this can > be avoided by making check_type const void *, but maybe these warnings > indicate that something that shouldn't be freed is freed. How many warnings? If it's only a handful, we should start investigating; if it's lots, then I'm not sure how much it buys us. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Fri Apr 22 17:04:14 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 22 Apr 2011 19:04:14 +0200 Subject: [libvirt] [PATCH] daemon: Honor error variable name change in the generator In-Reply-To: <4DB1A9D4.8050609@redhat.com> References: <20110422161116.GA19599@sbox> <4DB1A9D4.8050609@redhat.com> Message-ID: 2011/4/22 Eric Blake : > On 04/22/2011 10:11 AM, Matthias Bolte wrote: >> Commit 36b652138be renamed err to rerr, do the same in the generator. >> --- >> ?daemon/qemu_dispatch_prototypes.h ? | ? ?2 +- >> ?daemon/remote_dispatch_prototypes.h | ?404 +++++++++++++++++----------------- >> ?daemon/remote_generate_stubs.pl ? ? | ? ?2 +- >> ?3 files changed, 204 insertions(+), 204 deletions(-) >> >> diff --git a/daemon/qemu_dispatch_prototypes.h b/daemon/qemu_dispatch_prototypes.h >> index e6c83ba..4ec1ab4 100644 >> --- a/daemon/qemu_dispatch_prototypes.h >> +++ b/daemon/qemu_dispatch_prototypes.h >> @@ -7,6 +7,6 @@ static int qemuDispatchMonitorCommand( >> ? ? ?struct qemud_client *client, >> ? ? ?virConnectPtr conn, >> ? ? ?remote_message_header *hdr, >> - ? ?remote_error *err, >> + ? ?remote_error *rerr, > > Mechanical, and didn't spot any problems. Actually the change in the generator was the only manual one, the rest was done by the generator :) > > ACK. > Thanks, pushed. Matthias From cfergeau at redhat.com Fri Apr 22 17:04:14 2011 From: cfergeau at redhat.com (Christophe Fergeau) Date: Fri, 22 Apr 2011 19:04:14 +0200 Subject: [libvirt] [PATCH] daemon: Don't try to free an unsigned int in error paths In-Reply-To: <4DB1B2E8.3030004@redhat.com> References: <20110422161154.GA20436@sbox> <4DB1A9FD.6040200@redhat.com> <20110422163125.GA3219@teriyaki.redhat.com> <4DB1B2E8.3030004@redhat.com> Message-ID: <20110422170413.GC3219@teriyaki.redhat.com> On Fri, Apr 22, 2011 at 10:55:04AM -0600, Eric Blake wrote: > On 04/22/2011 10:31 AM, Christophe Fergeau wrote: > > -# define VIR_FREE(ptr) virFree(&(ptr)) > > +# define VIR_FREE(ptr) \ > > + do { void *check_type = (ptr); virFree(&(check_type)); } while (0) > > Not quite. That assigns check_type to NULL, rather than the intended > assignment of ptr. Ooops, indeed. Initially, I didn't change the parameter of virFree, but got "unused variable 'check_type'" warnings from gcc, so I went this way. Using ATTRIBUTE_UNUSED and not changing virFree parameter will indeed work better ;) > > I also get more warnings about casting from const to non-const, this can > > be avoided by making check_type const void *, but maybe these warnings > > indicate that something that shouldn't be freed is freed. > > How many warnings? If it's only a handful, we should start > investigating; if it's lots, then I'm not sure how much it buys us. I get 93 such warnings on a test build, I'll look at a few ones at random and report if that shows real bugs. Christophe -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 198 bytes Desc: not available URL: From matthias.bolte at googlemail.com Fri Apr 22 17:04:48 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 22 Apr 2011 19:04:48 +0200 Subject: [libvirt] [PATCH] daemon: Don't try to free an unsigned int in error paths In-Reply-To: <4DB1A9FD.6040200@redhat.com> References: <20110422161154.GA20436@sbox> <4DB1A9FD.6040200@redhat.com> Message-ID: 2011/4/22 Eric Blake : > On 04/22/2011 10:11 AM, Matthias Bolte wrote: >> --- >> ?daemon/remote.c | ? ?8 ++++---- >> ?1 files changed, 4 insertions(+), 4 deletions(-) >> >> diff --git a/daemon/remote.c b/daemon/remote.c >> index 54fef64..1c98bba 100644 >> --- a/daemon/remote.c >> +++ b/daemon/remote.c >> @@ -3681,7 +3681,7 @@ remoteDispatchListNetworks(struct qemud_server *server ATTRIBUTE_UNUSED, >> ?cleanup: >> ? ? ?if (rv < 0) { >> ? ? ? ? ?remoteDispatchError(rerr); >> - ? ? ? ?VIR_FREE(ret->names.names_len); >> + ? ? ? ?VIR_FREE(ret->names.names_val); > > And to think I missed those in the huge patch. ?Oops. > > ACK. > Thanks, pushed. Matthias From matthias.bolte at googlemail.com Fri Apr 22 17:06:18 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 22 Apr 2011 19:06:18 +0200 Subject: [libvirt] [PATCH] daemon: Don't try to free an unsigned int in error paths In-Reply-To: <4DB1B2E8.3030004@redhat.com> References: <20110422161154.GA20436@sbox> <4DB1A9FD.6040200@redhat.com> <20110422163125.GA3219@teriyaki.redhat.com> <4DB1B2E8.3030004@redhat.com> Message-ID: 2011/4/22 Eric Blake : > On 04/22/2011 10:31 AM, Christophe Fergeau wrote: >> On Fri, Apr 22, 2011 at 10:17:01AM -0600, Eric Blake wrote: >>> On 04/22/2011 10:11 AM, Matthias Bolte wrote: >>>> ? ? ? ? ?remoteDispatchError(rerr); >>>> - ? ? ? ?VIR_FREE(ret->names.names_len); >>>> + ? ? ? ?VIR_FREE(ret->names.names_val); >>> >>> And to think I missed those in the huge patch. ?Oops. >> >> Maybe VIR_FREE should be changed to something like >> >> -# define VIR_FREE(ptr) virFree(&(ptr)) >> +# define VIR_FREE(ptr) \ >> + ? ?do { void *check_type = (ptr); virFree(&(check_type)); } while (0) > > Not quite. ?That assigns check_type to NULL, rather than the intended > assignment of ptr. > > But the idea has merit; I'll see if I can come up with a variant that > still evaluates ptr only once, by wrapping the type check in a sizeof hack. > >> I also get more warnings about casting from const to non-const, this can >> be avoided by making check_type const void *, but maybe these warnings >> indicate that something that shouldn't be freed is freed. > > How many warnings? ?If it's only a handful, we should start > investigating; if it's lots, then I'm not sure how much it buys us. > I just took a look at it and the first instances are mostly const char* used for allocated strings. I didn't spot a real error yet. But I'll leaf this one to you and finish my generator series instead :) Matthias From cfergeau at redhat.com Fri Apr 22 17:17:32 2011 From: cfergeau at redhat.com (Christophe Fergeau) Date: Fri, 22 Apr 2011 19:17:32 +0200 Subject: [libvirt] [PATCH] daemon: Don't try to free an unsigned int in error paths In-Reply-To: References: <20110422161154.GA20436@sbox> <4DB1A9FD.6040200@redhat.com> <20110422163125.GA3219@teriyaki.redhat.com> <4DB1B2E8.3030004@redhat.com> Message-ID: <20110422171732.GD3219@teriyaki.redhat.com> On Fri, Apr 22, 2011 at 07:06:18PM +0200, Matthias Bolte wrote: > I just took a look at it and the first instances are mostly const > char* used for allocated strings. I didn't spot a real error yet. Same here, looked at a dozen of these warnings, and just const char * being used for allocated strings, no error. It's probably better not to warn on this since it happens quite often and is harmless. Christophe -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 198 bytes Desc: not available URL: From eblake at redhat.com Fri Apr 22 17:51:23 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 22 Apr 2011 11:51:23 -0600 Subject: [libvirt] [PATCH] esx: Move CURL handling code to it's own type In-Reply-To: <20110410133929.GA28461@sbox> References: <20110410133929.GA28461@sbox> Message-ID: <4DB1C01B.3010209@redhat.com> On 04/10/2011 07:39 AM, Matthias Bolte wrote: > --- > src/esx/esx_driver.c | 4 +- > src/esx/esx_vi.c | 348 ++++++++++++++++++++++++++------------------------ > src/esx/esx_vi.h | 29 +++- > 3 files changed, 205 insertions(+), 176 deletions(-) > > +++ b/src/esx/esx_vi.h > @@ -82,6 +82,7 @@ typedef enum _esxVI_APIVersion esxVI_APIVersion; > typedef enum _esxVI_ProductVersion esxVI_ProductVersion; > typedef enum _esxVI_Occurrence esxVI_Occurrence; > typedef struct _esxVI_ParsedHostCpuIdInfo esxVI_ParsedHostCpuIdInfo; > +typedef struct _esxVI_CURL esxVI_CURL; > typedef struct _esxVI_Context esxVI_Context; > typedef struct _esxVI_Response esxVI_Response; > typedef struct _esxVI_Enumeration esxVI_Enumeration; > @@ -142,16 +143,32 @@ struct _esxVI_ParsedHostCpuIdInfo { > > > /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > + * CURL > + */ > + > +struct _esxVI_CURL { > + CURL *handle; > + virMutex lock; > + struct curl_slist *headers; > + char error[CURL_ERROR_SIZE]; > +}; > + > +int esxVI_CURL_Alloc(esxVI_CURL **curl); > +void esxVI_CURL_Free(esxVI_CURL **curl); > +int esxVI_CURL_Connect(esxVI_CURL *curl, esxUtil_ParsedUri *parsedUri); > +int esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content); > +int esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content); A new type... > + > + > + > +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * > * Context > */ > > struct _esxVI_Context { > + esxVI_CURL *curl; > char *url; > char *ipAddress; > - CURL *curl_handle; > - struct curl_slist *curl_headers; > - char curl_error[CURL_ERROR_SIZE]; > - virMutex curl_lock; > char *username; extracted from several fields of a larger type, and the rest of the patch looks like mechanical fallout to the different naming to get to the same fields. Looks like a reasonable refactoring, and nothing really caught my eye as suspicious. ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From cfergeau at redhat.com Fri Apr 22 18:21:24 2011 From: cfergeau at redhat.com (Christophe Fergeau) Date: Fri, 22 Apr 2011 20:21:24 +0200 Subject: [libvirt] [PATCH] util: warn when passing a non-pointer to VIR_FREE In-Reply-To: <20110422170413.GC3219@teriyaki.redhat.com> References: <20110422170413.GC3219@teriyaki.redhat.com> Message-ID: <1303496484-17313-1-git-send-email-cfergeau@redhat.com> There were recently some bugs where VIR_FREE was called with an int parameter. Try to affect the value passed to VIR_FREE to a const void* so that the compiler gets a chance to emit a warning if we didn't pass a pointer to VIR_FREE. --- src/util/memory.h | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/src/util/memory.h b/src/util/memory.h index 66b4c42..fab425d 100644 --- a/src/util/memory.h +++ b/src/util/memory.h @@ -197,7 +197,11 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); * Free the memory stored in 'ptr' and update to point * to NULL. */ -# define VIR_FREE(ptr) virFree(&(ptr)) +# define VIR_FREE(ptr) \ + do { \ + ATTRIBUTE_UNUSED const void *check_type = (ptr); \ + virFree(&(ptr)); \ + } while (0) # if TEST_OOM -- 1.7.4.4 From cfergeau at redhat.com Fri Apr 22 18:25:28 2011 From: cfergeau at redhat.com (Christophe Fergeau) Date: Fri, 22 Apr 2011 20:25:28 +0200 Subject: [libvirt] [PATCH] util: warn when passing a non-pointer to VIR_FREE In-Reply-To: <1303496484-17313-1-git-send-email-cfergeau@redhat.com> References: <20110422170413.GC3219@teriyaki.redhat.com> <1303496484-17313-1-git-send-email-cfergeau@redhat.com> Message-ID: <20110422182527.GE3219@teriyaki.redhat.com> On Fri, Apr 22, 2011 at 08:21:24PM +0200, Christophe Fergeau wrote: > There were recently some bugs where VIR_FREE was called with an > int parameter. Try to affect the value passed to VIR_FREE to > a const void* so that the compiler gets a chance to emit a warning > if we didn't pass a pointer to VIR_FREE. With this patch, I don't get any warnings except for the remote.c: In function ?remoteDispatchListNetworks?: remote.c:3517:67: attention : initialization makes pointer from integer without a cast [enabled by default] which were just fixed. Christophe -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 198 bytes Desc: not available URL: From eblake at redhat.com Fri Apr 22 23:36:25 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 22 Apr 2011 17:36:25 -0600 Subject: [libvirt] [PATCH] util: warn when passing a non-pointer to VIR_FREE In-Reply-To: <1303496484-17313-1-git-send-email-cfergeau@redhat.com> References: <20110422170413.GC3219@teriyaki.redhat.com> <1303496484-17313-1-git-send-email-cfergeau@redhat.com> Message-ID: <4DB210F9.5040503@redhat.com> On 04/22/2011 12:21 PM, Christophe Fergeau wrote: > There were recently some bugs where VIR_FREE was called with an > int parameter. Try to affect the value passed to VIR_FREE to > a const void* so that the compiler gets a chance to emit a warning > if we didn't pass a pointer to VIR_FREE. > --- > src/util/memory.h | 6 +++++- > 1 files changed, 5 insertions(+), 1 deletions(-) > > diff --git a/src/util/memory.h b/src/util/memory.h > index 66b4c42..fab425d 100644 > --- a/src/util/memory.h > +++ b/src/util/memory.h > @@ -197,7 +197,11 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); > * Free the memory stored in 'ptr' and update to point > * to NULL. > */ > -# define VIR_FREE(ptr) virFree(&(ptr)) > +# define VIR_FREE(ptr) \ > + do { \ > + ATTRIBUTE_UNUSED const void *check_type = (ptr); \ > + virFree(&(ptr)); \ > + } while (0) That evaluates ptr twice. We can do better, by exploiting that the ternary operator can be used to determine the type of an expression without evaluating it. Gcc allows 1?(void*)expr:pointer (the resulting type is void*), but hates 1?(void*)expr:int (promoting to int provokes a warning): cc1: warnings being treated as errors remote.c: In function 'remoteDispatchListNetworks': remote.c:3684:70: error: pointer/integer type mismatch in conditional expression So how about: diff --git i/src/util/memory.h w/src/util/memory.h index 66b4c42..d77a295 100644 --- i/src/util/memory.h +++ w/src/util/memory.h @@ -1,7 +1,7 @@ /* * memory.c: safer memory allocation * - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 Red Hat, Inc. * Copyright (C) 2008 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -197,7 +197,11 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); * Free the memory stored in 'ptr' and update to point * to NULL. */ -# define VIR_FREE(ptr) virFree(&(ptr)) +/* The ternary ensures that ptr is a pointer and not an integer type, + * while evaluating ptr only once. For now, we intentionally cast + * away const, since a number of callers safely pass const char *. + */ +# define VIR_FREE(ptr) virFree((void *) (1 ? (const void *) &(ptr) : (ptr))) # if TEST_OOM -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Sat Apr 23 03:38:28 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 22 Apr 2011 21:38:28 -0600 Subject: [libvirt] [PATCHv2] threads: add one-time initialization support In-Reply-To: <1303339419-13159-1-git-send-email-eblake@redhat.com> References: <1303339419-13159-1-git-send-email-eblake@redhat.com> Message-ID: <1303529908-32330-1-git-send-email-eblake@redhat.com> mingw lacks the counterpart to PTHREAD_MUTEX_INITIALIZER, so the best we can do is portably expose once-only runtime initialization. * src/util/threads.h (virOnceControlPtr): New opaque type. (virOnceFunc): New callback type. (virOnce): New prototype. * src/util/threads-pthread.h (virOnceControl): Declare. (VIR_ONCE_CONTROL_INITIALIZER): Define. * src/util/threads-win32.h (virOnceControl) (VIR_ONCE_CONTROL_INITIALIZER): Likewise. * src/util/threads-pthread.c (virOnce): Implement in pthreads. * src/util/threads-win32.c (virOnce): Implement in WIN32. * src/libvirt_private.syms: Export it. --- v2: change WIN32 implementation to use lower-level primitives available to mingw and older windows, rather than higher level but newer INIT_ONCE. Meanwhile, I noticed that gnulib has an LGPLv2+ 'lock' module that provides a lot of multi-threading primitives for both pthreads, pth, and mingw; maybe we should think about rewriting threads.c in terms of gnulib and only have one implementation, rather than maintaining pthread and mingw in parallel? src/libvirt_private.syms | 1 + src/util/threads-pthread.c | 5 +++++ src/util/threads-pthread.h | 11 ++++++++++- src/util/threads-win32.c | 23 ++++++++++++++++++++++- src/util/threads-win32.h | 9 ++++++++- src/util/threads.h | 21 ++++++++++++++++++++- 6 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ba7739d..cb67861 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -866,6 +866,7 @@ virMutexInit; virMutexInitRecursive; virMutexLock; virMutexUnlock; +virOnce; virThreadCreate; virThreadID; virThreadIsSelf; diff --git a/src/util/threads-pthread.c b/src/util/threads-pthread.c index 898c4d4..82ce5c6 100644 --- a/src/util/threads-pthread.c +++ b/src/util/threads-pthread.c @@ -40,6 +40,11 @@ void virThreadOnExit(void) { } +int virOnce(virOnceControlPtr once, virOnceFunc init) +{ + return pthread_once(&once->once, init); +} + int virMutexInit(virMutexPtr m) { diff --git a/src/util/threads-pthread.h b/src/util/threads-pthread.h index b25d0c2..dcaacb7 100644 --- a/src/util/threads-pthread.h +++ b/src/util/threads-pthread.h @@ -1,7 +1,7 @@ /* * threads.c: basic thread synchronization primitives * - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009, 2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -38,3 +38,12 @@ struct virThread { struct virThreadLocal { pthread_key_t key; }; + +struct virOnceControl { + pthread_once_t once; +}; + +#define VIR_ONCE_CONTROL_INITIALIZER \ +{ \ + .once = PTHREAD_ONCE_INIT \ +} diff --git a/src/util/threads-win32.c b/src/util/threads-win32.c index 5661437..63f699b 100644 --- a/src/util/threads-win32.c +++ b/src/util/threads-win32.c @@ -1,7 +1,7 @@ /* * threads-win32.c: basic thread synchronization primitives * - * Copyright (C) 2009-2010 Red Hat, Inc. + * Copyright (C) 2009-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -69,6 +69,27 @@ void virThreadOnExit(void) virMutexUnlock(&virThreadLocalLock); } +int virOnce(virOnceControlPtr once, virOnceFunc func) +{ + if (!once->complete) { + if (InterlockedIncrement(&once->init) == 1) { + /* We're the first thread. */ + func(); + once->complete = 1; + } else { + /* We're a later thread. Decrement the init counter back + * to avoid overflow, then yield until the first thread + * marks that the function is complete. It is rare that + * multiple threads will be waiting here, and since each + * thread is yielding except the first, we should get out + * soon enough. */ + InterlockedDecrement(&once->init); + while (!once->complete) + Sleep(0); + } + } + return 0; +} int virMutexInit(virMutexPtr m) { diff --git a/src/util/threads-win32.h b/src/util/threads-win32.h index bb7c455..29580b8 100644 --- a/src/util/threads-win32.h +++ b/src/util/threads-win32.h @@ -1,7 +1,7 @@ /* * threads-win32.h basic thread synchronization primitives * - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009, 2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -41,3 +41,10 @@ struct virThread { struct virThreadLocal { DWORD key; }; + +struct virOnceControl { + long init; /* 0 at startup, > 0 if init has started */ + volatile long complete; /* 0 until first thread completes callback */ +}; + +#define VIR_ONCE_CONTROL_INITIALIZER { 0, 0 } diff --git a/src/util/threads.h b/src/util/threads.h index c129301..b72610c 100644 --- a/src/util/threads.h +++ b/src/util/threads.h @@ -1,7 +1,7 @@ /* * threads.h: basic thread synchronization primitives * - * Copyright (C) 2009-2010 Red Hat, Inc. + * Copyright (C) 2009-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -36,6 +36,10 @@ typedef virThreadLocal *virThreadLocalPtr; typedef struct virThread virThread; typedef virThread *virThreadPtr; +typedef struct virOnceControl virOnceControl; +typedef virOnceControl *virOnceControlPtr; + +typedef void (*virOnceFunc)(void); int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK; void virThreadOnExit(void); @@ -57,6 +61,21 @@ void virThreadJoin(virThreadPtr thread); int virThreadSelfID(void); int virThreadID(virThreadPtr thread); +/* Static initialization of mutexes is not possible, so we instead + * provide for guaranteed one-time initialization via a callback + * function. Usage: + * static virOnceControl once = VIR_ONCE_CONTROL_INITIALIZER; + * static void initializer(void) { ... } + * void myfunc() + * { + * if (virOnce(&once, initializer) < 0) + * goto error; + * ...now guaranteed that initializer has completed exactly once + * } + */ +int virOnce(virOnceControlPtr once, virOnceFunc init) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; + int virMutexInit(virMutexPtr m) ATTRIBUTE_RETURN_CHECK; int virMutexInitRecursive(virMutexPtr m) ATTRIBUTE_RETURN_CHECK; void virMutexDestroy(virMutexPtr m); -- 1.7.4.4 From agx at sigxcpu.org Sun Apr 24 08:02:23 2011 From: agx at sigxcpu.org (Guido =?iso-8859-1?Q?G=FCnther?=) Date: Sun, 24 Apr 2011 10:02:23 +0200 Subject: [libvirt] [PATCH] Make sure DNSMASQ_STATE_DIR exists Message-ID: <20110424080223.GA5669@bogon.sigxcpu.org> Hi, otherwise the directory returned by networkDnsmasqLeaseFileName will not be created if ipdef->nhosts == 0 in networkBuildDnsmasqArgv. O.k. to apply? Cheers, -- Guido --- src/network/bridge_driver.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 8b5c1b6..ed78710 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -662,6 +662,13 @@ networkStartDhcpDaemon(virNetworkObjPtr network) goto cleanup; } + if ((err = virFileMakePath(DNSMASQ_STATE_DIR)) != 0) { + virReportSystemError(err, + _("cannot create directory %s"), + DNSMASQ_STATE_DIR); + goto cleanup; + } + cmd = virCommandNew(DNSMASQ); if (networkBuildDnsmasqArgv(network, ipdef, pidfile, cmd) < 0) { goto cleanup; -- 1.7.4.1 From matthias.bolte at googlemail.com Sun Apr 24 09:13:47 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:47 +0200 Subject: [libvirt] [PATCH 00/22] Extend remote generator to generate function bodies too Message-ID: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Richard W.M. Jones suggested [1] that the code that directly deals with the XDR protocol should be generated. The remote_generate_stubs.pl script already generates all the headers, just the bodies in the daemon and remote driver are manually written. But most of the functions just follow simple patterns. So I extended the generator to exploit this patterns and move 11 kLOC code from manually written to generated code. During this I came a cross many small variations and problems in the XDR protocol. For example, NWFilterDefineXML has a flags parameter in the public API, but it's not transferred in the XDR protocol. Another things is the variations in the usage of unsigned VS signed types. This comes in two forms. public API VS XDR procotol and in between different functions. For example, some functions use int for the flags paramater and some use unsigned int. This results in quite a lot of special case handling in the generator. cfg.mk | 10 +- daemon/Makefile.am | 46 +- daemon/qemu_dispatch_args.h | 2 +- daemon/qemu_dispatch_bodies.c | 6 + daemon/qemu_dispatch_prototypes.h | 2 +- daemon/qemu_dispatch_ret.h | 2 +- daemon/qemu_dispatch_table.h | 2 +- daemon/remote.c | 5765 +---------------------------------- daemon/remote_dispatch_args.h | 2 +- daemon/remote_dispatch_bodies.c | 5933 +++++++++++++++++++++++++++++++++++ daemon/remote_dispatch_prototypes.h | 80 +- daemon/remote_dispatch_ret.h | 2 +- daemon/remote_dispatch_table.h | 158 +- daemon/remote_generate_stubs.pl | 195 -- daemon/remote_generator.pl | 1198 +++++++ po/POTFILES.in | 1 + src/Makefile.am | 13 +- src/remote/qemu_client_bodies.c | 4 + src/remote/qemu_protocol.c | 2 +- src/remote/qemu_protocol.h | 2 +- src/remote/qemu_protocol.x | 2 +- src/remote/remote_client_bodies.c | 4664 +++++++++++++++++++++++++++ src/remote/remote_driver.c | 4907 +---------------------------- src/remote/remote_protocol.c | 26 +- src/remote/remote_protocol.h | 26 +- src/remote/remote_protocol.x | 34 +- src/remote_protocol-structs | 26 +- 27 files changed, 12093 insertions(+), 11017 deletions(-) [1] https://www.redhat.com/archives/libvir-list/2011-April/msg00884.html Matthias From matthias.bolte at googlemail.com Sun Apr 24 09:13:50 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:50 +0200 Subject: [libvirt] [PATCH 03/22] remote: Replace 'domain' with 'dom' in the XDR protocol In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-4-git-send-email-matthias.bolte@googlemail.com> This simplifies the remote protocol code generator. Also rename 'ret' to 'result' to resolve a naming conflict in the generator. --- daemon/remote.c | 22 +++++++++++----------- daemon/remote_dispatch_bodies.c | 4 ++-- daemon/remote_generator.pl | 2 +- src/remote/qemu_protocol.c | 2 +- src/remote/qemu_protocol.h | 2 +- src/remote/qemu_protocol.x | 2 +- src/remote/remote_driver.c | 20 ++++++++++---------- src/remote/remote_protocol.c | 18 +++++++++--------- src/remote/remote_protocol.h | 18 +++++++++--------- src/remote/remote_protocol.x | 18 +++++++++--------- src/remote_protocol-structs | 18 +++++++++--------- 11 files changed, 63 insertions(+), 63 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 676c99a..48dbcc5 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -2875,7 +2875,7 @@ remoteDispatchDomainHasManagedSaveImage(struct qemud_server *server ATTRIBUTE_UN if (!(dom = get_nonnull_domain(conn, args->dom))) goto cleanup; - if ((ret->ret = virDomainHasManagedSaveImage(dom, args->flags)) < 0) + if ((ret->result = virDomainHasManagedSaveImage(dom, args->flags)) < 0) goto cleanup; rv = 0; @@ -6361,7 +6361,7 @@ remoteDispatchDomainSnapshotCreateXml(struct qemud_server *server ATTRIBUTE_UNUS goto cleanup; } - if (!(dom = get_nonnull_domain(conn, args->domain))) + if (!(dom = get_nonnull_domain(conn, args->dom))) goto cleanup; if (!(snapshot = virDomainSnapshotCreateXML(dom, args->xml_desc, args->flags))) @@ -6399,7 +6399,7 @@ remoteDispatchDomainSnapshotDumpXml(struct qemud_server *server ATTRIBUTE_UNUSED goto cleanup; } - if (!(dom = get_nonnull_domain(conn, args->snap.domain))) + if (!(dom = get_nonnull_domain(conn, args->snap.dom))) goto cleanup; if (!(snapshot = get_nonnull_domain_snapshot(dom, args->snap))) @@ -6438,7 +6438,7 @@ remoteDispatchDomainSnapshotNum(struct qemud_server *server ATTRIBUTE_UNUSED, goto cleanup; } - if (!(dom = get_nonnull_domain(conn, args->domain))) + if (!(dom = get_nonnull_domain(conn, args->dom))) goto cleanup; if ((ret->num = virDomainSnapshotNum(dom, args->flags)) < 0) @@ -6478,7 +6478,7 @@ remoteDispatchDomainSnapshotListNames(struct qemud_server *server ATTRIBUTE_UNUS goto cleanup; } - if (!(dom = get_nonnull_domain(conn, args->domain))) + if (!(dom = get_nonnull_domain(conn, args->dom))) goto cleanup; /* Allocate return buffer. */ @@ -6525,7 +6525,7 @@ remoteDispatchDomainSnapshotLookupByName(struct qemud_server *server ATTRIBUTE_U goto cleanup; } - if (!(dom = get_nonnull_domain(conn, args->domain))) + if (!(dom = get_nonnull_domain(conn, args->dom))) goto cleanup; if (!(snapshot = virDomainSnapshotLookupByName(dom, args->name, args->flags))) @@ -6563,7 +6563,7 @@ remoteDispatchDomainHasCurrentSnapshot(struct qemud_server *server ATTRIBUTE_UNU goto cleanup; } - if (!(dom = get_nonnull_domain(conn, args->domain))) + if (!(dom = get_nonnull_domain(conn, args->dom))) goto cleanup; result = virDomainHasCurrentSnapshot(dom, args->flags); @@ -6600,7 +6600,7 @@ remoteDispatchDomainSnapshotCurrent(struct qemud_server *server ATTRIBUTE_UNUSED goto cleanup; } - if (!(dom = get_nonnull_domain(conn, args->domain))) + if (!(dom = get_nonnull_domain(conn, args->dom))) goto cleanup; if (!(snapshot = virDomainSnapshotCurrent(dom, args->flags))) @@ -6969,7 +6969,7 @@ qemuDispatchMonitorCommand(struct qemud_server *server ATTRIBUTE_UNUSED, goto cleanup; } - if (!(dom = get_nonnull_domain(conn, args->domain))) + if (!(dom = get_nonnull_domain(conn, args->dom))) goto cleanup; if (virDomainQemuMonitorCommand(dom, args->cmd, &ret->result, @@ -7005,7 +7005,7 @@ remoteDispatchDomainOpenConsole(struct qemud_server *server ATTRIBUTE_UNUSED, goto cleanup; } - if (!(dom = get_nonnull_domain(conn, args->domain))) + if (!(dom = get_nonnull_domain(conn, args->dom))) goto cleanup; if (!(stream = remoteCreateClientStream(conn, hdr))) { @@ -7168,5 +7168,5 @@ static void make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src) { snapshot_dst->name = strdup(snapshot_src->name); - make_nonnull_domain(&snapshot_dst->domain, snapshot_src->domain); + make_nonnull_domain(&snapshot_dst->dom, snapshot_src->domain); } diff --git a/daemon/remote_dispatch_bodies.c b/daemon/remote_dispatch_bodies.c index 962b12a..a3360c5 100644 --- a/daemon/remote_dispatch_bodies.c +++ b/daemon/remote_dispatch_bodies.c @@ -629,7 +629,7 @@ remoteDispatchDomainRevertToSnapshot( goto cleanup; } - if (!(dom = get_nonnull_domain(conn, args->snap.domain))) + if (!(dom = get_nonnull_domain(conn, args->snap.dom))) goto cleanup; if (!(snapshot = get_nonnull_domain_snapshot(dom, args->snap))) @@ -951,7 +951,7 @@ remoteDispatchDomainSnapshotDelete( goto cleanup; } - if (!(dom = get_nonnull_domain(conn, args->snap.domain))) + if (!(dom = get_nonnull_domain(conn, args->snap.dom))) goto cleanup; if (!(snapshot = get_nonnull_domain_snapshot(dom, args->snap))) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index bf971e2..8ad6d0d 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -367,7 +367,7 @@ elsif ($opt_b) { push(@vars_list, "virDomainPtr dom = NULL"); push(@vars_list, "virDomainSnapshotPtr snapshot = NULL"); push(@getters_list, - " if (!(dom = get_nonnull_domain(conn, args->snap.domain)))\n" . + " if (!(dom = get_nonnull_domain(conn, args->snap.dom)))\n" . " goto cleanup;\n" . "\n" . " if (!(snapshot = get_nonnull_domain_snapshot(dom, args->snap)))\n" . diff --git a/src/remote/qemu_protocol.c b/src/remote/qemu_protocol.c index 81916ed..3480c54 100644 --- a/src/remote/qemu_protocol.c +++ b/src/remote/qemu_protocol.c @@ -13,7 +13,7 @@ bool_t xdr_qemu_monitor_command_args (XDR *xdrs, qemu_monitor_command_args *objp) { - if (!xdr_remote_nonnull_domain (xdrs, &objp->domain)) + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) return FALSE; if (!xdr_remote_nonnull_string (xdrs, &objp->cmd)) return FALSE; diff --git a/src/remote/qemu_protocol.h b/src/remote/qemu_protocol.h index b822187..c2501c7 100644 --- a/src/remote/qemu_protocol.h +++ b/src/remote/qemu_protocol.h @@ -18,7 +18,7 @@ extern "C" { #include struct qemu_monitor_command_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; remote_nonnull_string cmd; int flags; }; diff --git a/src/remote/qemu_protocol.x b/src/remote/qemu_protocol.x index 1d07895..9eed73f 100644 --- a/src/remote/qemu_protocol.x +++ b/src/remote/qemu_protocol.x @@ -28,7 +28,7 @@ /*----- Protocol. -----*/ struct qemu_monitor_command_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; remote_nonnull_string cmd; int flags; }; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index e30780c..9d6056b 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -4352,7 +4352,7 @@ remoteDomainHasManagedSaveImage (virDomainPtr domain, unsigned int flags) (xdrproc_t) xdr_remote_domain_has_managed_save_image_ret, (char *) &ret) == -1) goto done; - rv = ret.ret; + rv = ret.result; done: remoteDriverUnlock(priv); @@ -9236,7 +9236,7 @@ remoteDomainSnapshotCreateXML(virDomainPtr domain, remoteDriverLock(priv); - make_nonnull_domain (&args.domain, domain); + make_nonnull_domain (&args.dom, domain); args.xml_desc = (char *) xmlDesc; args.flags = flags; @@ -9293,7 +9293,7 @@ remoteDomainSnapshotNum (virDomainPtr domain, unsigned int flags) remoteDriverLock(priv); - make_nonnull_domain (&args.domain, domain); + make_nonnull_domain (&args.dom, domain); args.flags = flags; memset (&ret, 0, sizeof ret); @@ -9329,7 +9329,7 @@ remoteDomainSnapshotListNames (virDomainPtr domain, char **const names, goto done; } - make_nonnull_domain(&args.domain, domain); + make_nonnull_domain(&args.dom, domain); args.nameslen = nameslen; args.flags = flags; @@ -9385,7 +9385,7 @@ remoteDomainSnapshotLookupByName (virDomainPtr domain, const char *name, remoteDriverLock(priv); - make_nonnull_domain(&args.domain, domain); + make_nonnull_domain(&args.dom, domain); args.name = (char *) name; args.flags = flags; @@ -9414,7 +9414,7 @@ remoteDomainHasCurrentSnapshot(virDomainPtr domain, unsigned int flags) remoteDriverLock(priv); - make_nonnull_domain(&args.domain, domain); + make_nonnull_domain(&args.dom, domain); args.flags = flags; if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_HAS_CURRENT_SNAPSHOT, @@ -9441,7 +9441,7 @@ remoteDomainSnapshotCurrent(virDomainPtr domain, remoteDriverLock(priv); - make_nonnull_domain(&args.domain, domain); + make_nonnull_domain(&args.dom, domain); args.flags = flags; memset(&ret, 0, sizeof ret); @@ -9709,7 +9709,7 @@ remoteDomainOpenConsole(virDomainPtr dom, st->driver = &remoteStreamDrv; st->privateData = privst; - make_nonnull_domain (&args.domain, dom); + make_nonnull_domain (&args.dom, dom); args.devname = devname ? (char **)&devname : NULL; args.flags = flags; @@ -9743,7 +9743,7 @@ remoteQemuDomainMonitorCommand (virDomainPtr domain, const char *cmd, remoteDriverLock(priv); - make_nonnull_domain(&args.domain, domain); + make_nonnull_domain(&args.dom, domain); args.cmd = (char *)cmd; args.flags = flags; @@ -11177,7 +11177,7 @@ static void make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src) { snapshot_dst->name = snapshot_src->name; - make_nonnull_domain(&snapshot_dst->domain, snapshot_src->domain); + make_nonnull_domain(&snapshot_dst->dom, snapshot_src->domain); } /*----------------------------------------------------------------------*/ diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 5604371..e85f607 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -148,7 +148,7 @@ xdr_remote_nonnull_domain_snapshot (XDR *xdrs, remote_nonnull_domain_snapshot *o if (!xdr_remote_nonnull_string (xdrs, &objp->name)) return FALSE; - if (!xdr_remote_nonnull_domain (xdrs, &objp->domain)) + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) return FALSE; return TRUE; } @@ -3672,7 +3672,7 @@ bool_t xdr_remote_domain_has_managed_save_image_ret (XDR *xdrs, remote_domain_has_managed_save_image_ret *objp) { - if (!xdr_int (xdrs, &objp->ret)) + if (!xdr_int (xdrs, &objp->result)) return FALSE; return TRUE; } @@ -3692,7 +3692,7 @@ bool_t xdr_remote_domain_snapshot_create_xml_args (XDR *xdrs, remote_domain_snapshot_create_xml_args *objp) { - if (!xdr_remote_nonnull_domain (xdrs, &objp->domain)) + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) return FALSE; if (!xdr_remote_nonnull_string (xdrs, &objp->xml_desc)) return FALSE; @@ -3734,7 +3734,7 @@ bool_t xdr_remote_domain_snapshot_num_args (XDR *xdrs, remote_domain_snapshot_num_args *objp) { - if (!xdr_remote_nonnull_domain (xdrs, &objp->domain)) + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) return FALSE; if (!xdr_int (xdrs, &objp->flags)) return FALSE; @@ -3754,7 +3754,7 @@ bool_t xdr_remote_domain_snapshot_list_names_args (XDR *xdrs, remote_domain_snapshot_list_names_args *objp) { - if (!xdr_remote_nonnull_domain (xdrs, &objp->domain)) + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) return FALSE; if (!xdr_int (xdrs, &objp->nameslen)) return FALSE; @@ -3778,7 +3778,7 @@ bool_t xdr_remote_domain_snapshot_lookup_by_name_args (XDR *xdrs, remote_domain_snapshot_lookup_by_name_args *objp) { - if (!xdr_remote_nonnull_domain (xdrs, &objp->domain)) + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) return FALSE; if (!xdr_remote_nonnull_string (xdrs, &objp->name)) return FALSE; @@ -3800,7 +3800,7 @@ bool_t xdr_remote_domain_has_current_snapshot_args (XDR *xdrs, remote_domain_has_current_snapshot_args *objp) { - if (!xdr_remote_nonnull_domain (xdrs, &objp->domain)) + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) return FALSE; if (!xdr_int (xdrs, &objp->flags)) return FALSE; @@ -3820,7 +3820,7 @@ bool_t xdr_remote_domain_snapshot_current_args (XDR *xdrs, remote_domain_snapshot_current_args *objp) { - if (!xdr_remote_nonnull_domain (xdrs, &objp->domain)) + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) return FALSE; if (!xdr_int (xdrs, &objp->flags)) return FALSE; @@ -3862,7 +3862,7 @@ bool_t xdr_remote_domain_open_console_args (XDR *xdrs, remote_domain_open_console_args *objp) { - if (!xdr_remote_nonnull_domain (xdrs, &objp->domain)) + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) return FALSE; if (!xdr_remote_string (xdrs, &objp->devname)) return FALSE; diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index d9bf151..82d0981 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -123,7 +123,7 @@ typedef struct remote_nonnull_secret remote_nonnull_secret; struct remote_nonnull_domain_snapshot { remote_nonnull_string name; - remote_nonnull_domain domain; + remote_nonnull_domain dom; }; typedef struct remote_nonnull_domain_snapshot remote_nonnull_domain_snapshot; @@ -2073,7 +2073,7 @@ struct remote_domain_has_managed_save_image_args { typedef struct remote_domain_has_managed_save_image_args remote_domain_has_managed_save_image_args; struct remote_domain_has_managed_save_image_ret { - int ret; + int result; }; typedef struct remote_domain_has_managed_save_image_ret remote_domain_has_managed_save_image_ret; @@ -2084,7 +2084,7 @@ struct remote_domain_managed_save_remove_args { typedef struct remote_domain_managed_save_remove_args remote_domain_managed_save_remove_args; struct remote_domain_snapshot_create_xml_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; remote_nonnull_string xml_desc; int flags; }; @@ -2107,7 +2107,7 @@ struct remote_domain_snapshot_dump_xml_ret { typedef struct remote_domain_snapshot_dump_xml_ret remote_domain_snapshot_dump_xml_ret; struct remote_domain_snapshot_num_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; int flags; }; typedef struct remote_domain_snapshot_num_args remote_domain_snapshot_num_args; @@ -2118,7 +2118,7 @@ struct remote_domain_snapshot_num_ret { typedef struct remote_domain_snapshot_num_ret remote_domain_snapshot_num_ret; struct remote_domain_snapshot_list_names_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; int nameslen; int flags; }; @@ -2133,7 +2133,7 @@ struct remote_domain_snapshot_list_names_ret { typedef struct remote_domain_snapshot_list_names_ret remote_domain_snapshot_list_names_ret; struct remote_domain_snapshot_lookup_by_name_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; remote_nonnull_string name; int flags; }; @@ -2145,7 +2145,7 @@ struct remote_domain_snapshot_lookup_by_name_ret { typedef struct remote_domain_snapshot_lookup_by_name_ret remote_domain_snapshot_lookup_by_name_ret; struct remote_domain_has_current_snapshot_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; int flags; }; typedef struct remote_domain_has_current_snapshot_args remote_domain_has_current_snapshot_args; @@ -2156,7 +2156,7 @@ struct remote_domain_has_current_snapshot_ret { typedef struct remote_domain_has_current_snapshot_ret remote_domain_has_current_snapshot_ret; struct remote_domain_snapshot_current_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; int flags; }; typedef struct remote_domain_snapshot_current_args remote_domain_snapshot_current_args; @@ -2179,7 +2179,7 @@ struct remote_domain_snapshot_delete_args { typedef struct remote_domain_snapshot_delete_args remote_domain_snapshot_delete_args; struct remote_domain_open_console_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; remote_string devname; u_int flags; }; diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index b02f082..0422c7b 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -247,7 +247,7 @@ struct remote_nonnull_secret { /* A snapshot which may not be NULL. */ struct remote_nonnull_domain_snapshot { remote_nonnull_string name; - remote_nonnull_domain domain; + remote_nonnull_domain dom; }; /* A domain or network which may be NULL. */ @@ -1836,7 +1836,7 @@ struct remote_domain_has_managed_save_image_args { }; struct remote_domain_has_managed_save_image_ret { - int ret; + int result; }; struct remote_domain_managed_save_remove_args { @@ -1845,7 +1845,7 @@ struct remote_domain_managed_save_remove_args { }; struct remote_domain_snapshot_create_xml_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; remote_nonnull_string xml_desc; int flags; }; @@ -1864,7 +1864,7 @@ struct remote_domain_snapshot_dump_xml_ret { }; struct remote_domain_snapshot_num_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; int flags; }; @@ -1873,7 +1873,7 @@ struct remote_domain_snapshot_num_ret { }; struct remote_domain_snapshot_list_names_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; int nameslen; int flags; }; @@ -1883,7 +1883,7 @@ struct remote_domain_snapshot_list_names_ret { }; struct remote_domain_snapshot_lookup_by_name_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; remote_nonnull_string name; int flags; }; @@ -1893,7 +1893,7 @@ struct remote_domain_snapshot_lookup_by_name_ret { }; struct remote_domain_has_current_snapshot_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; int flags; }; @@ -1902,7 +1902,7 @@ struct remote_domain_has_current_snapshot_ret { }; struct remote_domain_snapshot_current_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; int flags; }; @@ -1921,7 +1921,7 @@ struct remote_domain_snapshot_delete_args { }; struct remote_domain_open_console_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; remote_string devname; unsigned int flags; }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 944553c..73c7202 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -35,7 +35,7 @@ struct remote_nonnull_secret { }; struct remote_nonnull_domain_snapshot { remote_nonnull_string name; - remote_nonnull_domain domain; + remote_nonnull_domain dom; }; struct remote_error { int code; @@ -1341,14 +1341,14 @@ struct remote_domain_has_managed_save_image_args { u_int flags; }; struct remote_domain_has_managed_save_image_ret { - int ret; + int result; }; struct remote_domain_managed_save_remove_args { remote_nonnull_domain dom; u_int flags; }; struct remote_domain_snapshot_create_xml_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; remote_nonnull_string xml_desc; int flags; }; @@ -1363,14 +1363,14 @@ struct remote_domain_snapshot_dump_xml_ret { remote_nonnull_string xml; }; struct remote_domain_snapshot_num_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; int flags; }; struct remote_domain_snapshot_num_ret { int num; }; struct remote_domain_snapshot_list_names_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; int nameslen; int flags; }; @@ -1381,7 +1381,7 @@ struct remote_domain_snapshot_list_names_ret { } names; }; struct remote_domain_snapshot_lookup_by_name_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; remote_nonnull_string name; int flags; }; @@ -1389,14 +1389,14 @@ struct remote_domain_snapshot_lookup_by_name_ret { remote_nonnull_domain_snapshot snap; }; struct remote_domain_has_current_snapshot_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; int flags; }; struct remote_domain_has_current_snapshot_ret { int result; }; struct remote_domain_snapshot_current_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; int flags; }; struct remote_domain_snapshot_current_ret { @@ -1411,7 +1411,7 @@ struct remote_domain_snapshot_delete_args { int flags; }; struct remote_domain_open_console_args { - remote_nonnull_domain domain; + remote_nonnull_domain dom; remote_string devname; u_int flags; }; -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:13:48 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:48 +0200 Subject: [libvirt] [PATCH 01/22] remote generator: Replace tabs with spaces and rename file In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-2-git-send-email-matthias.bolte@googlemail.com> No functional change included, just a whitespace change. --- daemon/Makefile.am | 34 +++--- daemon/qemu_dispatch_args.h | 2 +- daemon/qemu_dispatch_prototypes.h | 2 +- daemon/qemu_dispatch_ret.h | 2 +- daemon/qemu_dispatch_table.h | 2 +- daemon/remote_dispatch_args.h | 2 +- daemon/remote_dispatch_prototypes.h | 2 +- daemon/remote_dispatch_ret.h | 2 +- daemon/remote_dispatch_table.h | 2 +- daemon/remote_generate_stubs.pl | 195 ----------------------------------- daemon/remote_generator.pl | 195 +++++++++++++++++++++++++++++++++++ src/remote/remote_protocol.x | 2 +- 12 files changed, 221 insertions(+), 221 deletions(-) delete mode 100755 daemon/remote_generate_stubs.pl create mode 100755 daemon/remote_generator.pl diff --git a/daemon/Makefile.am b/daemon/Makefile.am index af71188..14088bc 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -23,7 +23,7 @@ AVAHI_SOURCES = \ DISTCLEANFILES = EXTRA_DIST = \ - remote_generate_stubs.pl \ + remote_generator.pl \ libvirtd.conf \ libvirtd.init.in \ libvirtd.upstart \ @@ -216,29 +216,29 @@ remote.h: \ REMOTE_PROTOCOL = $(top_srcdir)/src/remote/remote_protocol.x QEMU_PROTOCOL = $(top_srcdir)/src/remote/qemu_protocol.x -remote_dispatch_prototypes.h: $(srcdir)/remote_generate_stubs.pl $(REMOTE_PROTOCOL) - $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -c -p remote $(REMOTE_PROTOCOL) > $@ +remote_dispatch_prototypes.h: $(srcdir)/remote_generator.pl $(REMOTE_PROTOCOL) + $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -c -p remote $(REMOTE_PROTOCOL) > $@ -remote_dispatch_table.h: $(srcdir)/remote_generate_stubs.pl $(REMOTE_PROTOCOL) - $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -c -t remote $(REMOTE_PROTOCOL) > $@ +remote_dispatch_table.h: $(srcdir)/remote_generator.pl $(REMOTE_PROTOCOL) + $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -c -t remote $(REMOTE_PROTOCOL) > $@ -remote_dispatch_args.h: $(srcdir)/remote_generate_stubs.pl $(REMOTE_PROTOCOL) - $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -c -a remote $(REMOTE_PROTOCOL) > $@ +remote_dispatch_args.h: $(srcdir)/remote_generator.pl $(REMOTE_PROTOCOL) + $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -c -a remote $(REMOTE_PROTOCOL) > $@ -remote_dispatch_ret.h: $(srcdir)/remote_generate_stubs.pl $(REMOTE_PROTOCOL) - $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -c -r remote $(REMOTE_PROTOCOL) > $@ +remote_dispatch_ret.h: $(srcdir)/remote_generator.pl $(REMOTE_PROTOCOL) + $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -c -r remote $(REMOTE_PROTOCOL) > $@ -qemu_dispatch_prototypes.h: $(srcdir)/remote_generate_stubs.pl $(QEMU_PROTOCOL) - $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -p qemu $(QEMU_PROTOCOL) > $@ +qemu_dispatch_prototypes.h: $(srcdir)/remote_generator.pl $(QEMU_PROTOCOL) + $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -p qemu $(QEMU_PROTOCOL) > $@ -qemu_dispatch_table.h: $(srcdir)/remote_generate_stubs.pl $(QEMU_PROTOCOL) - $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -t qemu $(QEMU_PROTOCOL) > $@ +qemu_dispatch_table.h: $(srcdir)/remote_generator.pl $(QEMU_PROTOCOL) + $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -t qemu $(QEMU_PROTOCOL) > $@ -qemu_dispatch_args.h: $(srcdir)/remote_generate_stubs.pl $(QEMU_PROTOCOL) - $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -a qemu $(QEMU_PROTOCOL) > $@ +qemu_dispatch_args.h: $(srcdir)/remote_generator.pl $(QEMU_PROTOCOL) + $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -a qemu $(QEMU_PROTOCOL) > $@ -qemu_dispatch_ret.h: $(srcdir)/remote_generate_stubs.pl $(QEMU_PROTOCOL) - $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -r qemu $(QEMU_PROTOCOL) > $@ +qemu_dispatch_ret.h: $(srcdir)/remote_generator.pl $(QEMU_PROTOCOL) + $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -r qemu $(QEMU_PROTOCOL) > $@ LOGROTATE_CONFS = libvirtd.qemu.logrotate libvirtd.lxc.logrotate \ libvirtd.uml.logrotate libvirtd.logrotate diff --git a/daemon/qemu_dispatch_args.h b/daemon/qemu_dispatch_args.h index e278fa4..81623bc 100644 --- a/daemon/qemu_dispatch_args.h +++ b/daemon/qemu_dispatch_args.h @@ -1,4 +1,4 @@ -/* Automatically generated by remote_generate_stubs.pl. +/* Automatically generated by remote_generator.pl. * Do not edit this file. Any changes you make will be lost. */ diff --git a/daemon/qemu_dispatch_prototypes.h b/daemon/qemu_dispatch_prototypes.h index 4ec1ab4..031ae38 100644 --- a/daemon/qemu_dispatch_prototypes.h +++ b/daemon/qemu_dispatch_prototypes.h @@ -1,4 +1,4 @@ -/* Automatically generated by remote_generate_stubs.pl. +/* Automatically generated by remote_generator.pl. * Do not edit this file. Any changes you make will be lost. */ diff --git a/daemon/qemu_dispatch_ret.h b/daemon/qemu_dispatch_ret.h index 492dcf9..4dcab6c 100644 --- a/daemon/qemu_dispatch_ret.h +++ b/daemon/qemu_dispatch_ret.h @@ -1,4 +1,4 @@ -/* Automatically generated by remote_generate_stubs.pl. +/* Automatically generated by remote_generator.pl. * Do not edit this file. Any changes you make will be lost. */ diff --git a/daemon/qemu_dispatch_table.h b/daemon/qemu_dispatch_table.h index c196a3c..d8eebd0 100644 --- a/daemon/qemu_dispatch_table.h +++ b/daemon/qemu_dispatch_table.h @@ -1,4 +1,4 @@ -/* Automatically generated by remote_generate_stubs.pl. +/* Automatically generated by remote_generator.pl. * Do not edit this file. Any changes you make will be lost. */ diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index f9537d7..31c02c7 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -1,4 +1,4 @@ -/* Automatically generated by remote_generate_stubs.pl. +/* Automatically generated by remote_generator.pl. * Do not edit this file. Any changes you make will be lost. */ diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index cf2f38c..a029b85 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -1,4 +1,4 @@ -/* Automatically generated by remote_generate_stubs.pl. +/* Automatically generated by remote_generator.pl. * Do not edit this file. Any changes you make will be lost. */ diff --git a/daemon/remote_dispatch_ret.h b/daemon/remote_dispatch_ret.h index 114e832..cf63657 100644 --- a/daemon/remote_dispatch_ret.h +++ b/daemon/remote_dispatch_ret.h @@ -1,4 +1,4 @@ -/* Automatically generated by remote_generate_stubs.pl. +/* Automatically generated by remote_generator.pl. * Do not edit this file. Any changes you make will be lost. */ diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index b39f7c2..d2ce08c 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1,4 +1,4 @@ -/* Automatically generated by remote_generate_stubs.pl. +/* Automatically generated by remote_generator.pl. * Do not edit this file. Any changes you make will be lost. */ diff --git a/daemon/remote_generate_stubs.pl b/daemon/remote_generate_stubs.pl deleted file mode 100755 index dbde7da..0000000 --- a/daemon/remote_generate_stubs.pl +++ /dev/null @@ -1,195 +0,0 @@ -#!/usr/bin/perl -w -# -# This script parses remote_protocol.x or qemu_protocol.x and produces lots of -# boilerplate code for both ends of the remote connection. -# -# The first non-option argument specifies the prefix to be searched for, and -# output to, the boilerplate code. The second non-option argument is the -# file you want to operate on. For instance, to generate the dispatch table -# for both remote_protocol.x and qemu_protocol.x, you would run the -# following: -# -# remote_generate_stubs.pl -c -t remote ../src/remote/remote_protocol.x -# remote_generate_stubs.pl -t qemu ../src/remote/qemu_protocol.x -# -# By Richard Jones - -use strict; - -use Getopt::Std; - -# Command line options. -our ($opt_p, $opt_t, $opt_a, $opt_r, $opt_d, $opt_c); -getopts ('ptardc'); - -my $structprefix = $ARGV[0]; -my $procprefix = uc $structprefix; -shift; - -# Convert name_of_call to NameOfCall. -sub name_to_ProcName { - my $name = shift; - my @elems = split /_/, $name; - @elems = map ucfirst, @elems; - join "", @elems -} - -# Read the input file (usually remote_protocol.x) and form an -# opinion about the name, args and return type of each RPC. -my ($name, $ProcName, $id, %calls, @calls); - -# only generate a close method if -c was passed -if ($opt_c) { - # REMOTE_PROC_CLOSE has no args or ret. - $calls{close} = { - name => "close", - ProcName => "Close", - UC_NAME => "CLOSE", - args => "void", - ret => "void", - }; -} - -while (<>) { - if (/^struct ${structprefix}_(.*)_args/) { - $name = $1; - $ProcName = name_to_ProcName ($name); - - die "duplicate definition of ${structprefix}_${name}_args" - if exists $calls{$name}; - - $calls{$name} = { - name => $name, - ProcName => $ProcName, - UC_NAME => uc $name, - args => "${structprefix}_${name}_args", - ret => "void", - }; - - } elsif (/^struct ${structprefix}_(.*)_ret/) { - $name = $1; - $ProcName = name_to_ProcName ($name); - - if (exists $calls{$name}) { - $calls{$name}->{ret} = "${structprefix}_${name}_ret"; - } else { - $calls{$name} = { - name => $name, - ProcName => $ProcName, - UC_NAME => uc $name, - args => "void", - ret => "${structprefix}_${name}_ret" - } - } - } elsif (/^struct ${structprefix}_(.*)_msg/) { - $name = $1; - $ProcName = name_to_ProcName ($name); - - $calls{$name} = { - name => $name, - ProcName => $ProcName, - UC_NAME => uc $name, - msg => "${structprefix}_${name}_msg" - } - } elsif (/^\s*${procprefix}_PROC_(.*?)\s+=\s+(\d+),?$/) { - $name = lc $1; - $id = $2; - $ProcName = name_to_ProcName ($name); - - $calls[$id] = $calls{$name}; - } -} - -#---------------------------------------------------------------------- -# Output - -print <<__EOF__; -/* Automatically generated by remote_generate_stubs.pl. - * Do not edit this file. Any changes you make will be lost. - */ - -__EOF__ - -# Debugging. -if ($opt_d) { - my @keys = sort (keys %calls); - foreach (@keys) { - print "$_:\n"; - print " name $calls{$_}->{name} ($calls{$_}->{ProcName})\n"; - print " $calls{$_}->{args} -> $calls{$_}->{ret}\n"; - } -} - -# Prototypes for dispatch functions ("remote_dispatch_prototypes.h"). -elsif ($opt_p) { - my @keys = sort (keys %calls); - foreach (@keys) { - # Skip things which are REMOTE_MESSAGE - next if $calls{$_}->{msg}; - - print "static int ${structprefix}Dispatch$calls{$_}->{ProcName}(\n"; - print " struct qemud_server *server,\n"; - print " struct qemud_client *client,\n"; - print " virConnectPtr conn,\n"; - print " remote_message_header *hdr,\n"; - print " remote_error *rerr,\n"; - print " $calls{$_}->{args} *args,\n"; - print " $calls{$_}->{ret} *ret);\n"; - } -} - -# Union of all arg types -# ("remote_dispatch_args.h"). -elsif ($opt_a) { - for ($id = 0 ; $id <= $#calls ; $id++) { - if (defined $calls[$id] && - !$calls[$id]->{msg} && - $calls[$id]->{args} ne "void") { - print " $calls[$id]->{args} val_$calls[$id]->{args};\n"; - } - } -} - -# Union of all arg types -# ("remote_dispatch_ret.h"). -elsif ($opt_r) { - for ($id = 0 ; $id <= $#calls ; $id++) { - if (defined $calls[$id] && - !$calls[$id]->{msg} && - $calls[$id]->{ret} ne "void") { - print " $calls[$id]->{ret} val_$calls[$id]->{ret};\n"; - } - } -} - -# Inside the switch statement, prepare the 'fn', 'args_filter', etc -# ("remote_dispatch_table.h"). -elsif ($opt_t) { - for ($id = 0 ; $id <= $#calls ; $id++) { - if (defined $calls[$id] && !$calls[$id]->{msg}) { - print "{ /* $calls[$id]->{ProcName} => $id */\n"; - print " .fn = (dispatch_fn) ${structprefix}Dispatch$calls[$id]->{ProcName},\n"; - if ($calls[$id]->{args} ne "void") { - print " .args_filter = (xdrproc_t) xdr_$calls[$id]->{args},\n"; - } else { - print " .args_filter = (xdrproc_t) xdr_void,\n"; - } - if ($calls[$id]->{ret} ne "void") { - print " .ret_filter = (xdrproc_t) xdr_$calls[$id]->{ret},\n"; - } else { - print " .ret_filter = (xdrproc_t) xdr_void,\n"; - } - print "},\n"; - } else { - if ($calls[$id]->{msg}) { - print "{ /* Async event $calls[$id]->{ProcName} => $id */\n"; - } else { - print "{ /* (unused) => $id */\n"; - } - print " .fn = NULL,\n"; - print " .args_filter = (xdrproc_t) xdr_void,\n"; - print " .ret_filter = (xdrproc_t) xdr_void,\n"; - print "},\n"; - } - } -} diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl new file mode 100755 index 0000000..e4cade6 --- /dev/null +++ b/daemon/remote_generator.pl @@ -0,0 +1,195 @@ +#!/usr/bin/perl -w +# +# This script parses remote_protocol.x or qemu_protocol.x and produces lots of +# boilerplate code for both ends of the remote connection. +# +# The first non-option argument specifies the prefix to be searched for, and +# output to, the boilerplate code. The second non-option argument is the +# file you want to operate on. For instance, to generate the dispatch table +# for both remote_protocol.x and qemu_protocol.x, you would run the +# following: +# +# remote_generator.pl -c -t remote ../src/remote/remote_protocol.x +# remote_generator.pl -t qemu ../src/remote/qemu_protocol.x +# +# By Richard Jones + +use strict; + +use Getopt::Std; + +# Command line options. +our ($opt_p, $opt_t, $opt_a, $opt_r, $opt_d, $opt_c); +getopts ('ptardc'); + +my $structprefix = $ARGV[0]; +my $procprefix = uc $structprefix; +shift; + +# Convert name_of_call to NameOfCall. +sub name_to_ProcName { + my $name = shift; + my @elems = split /_/, $name; + @elems = map ucfirst, @elems; + join "", @elems +} + +# Read the input file (usually remote_protocol.x) and form an +# opinion about the name, args and return type of each RPC. +my ($name, $ProcName, $id, %calls, @calls); + +# only generate a close method if -c was passed +if ($opt_c) { + # REMOTE_PROC_CLOSE has no args or ret. + $calls{close} = { + name => "close", + ProcName => "Close", + UC_NAME => "CLOSE", + args => "void", + ret => "void", + }; +} + +while (<>) { + if (/^struct ${structprefix}_(.*)_args/) { + $name = $1; + $ProcName = name_to_ProcName ($name); + + die "duplicate definition of ${structprefix}_${name}_args" + if exists $calls{$name}; + + $calls{$name} = { + name => $name, + ProcName => $ProcName, + UC_NAME => uc $name, + args => "${structprefix}_${name}_args", + ret => "void", + }; + + } elsif (/^struct ${structprefix}_(.*)_ret/) { + $name = $1; + $ProcName = name_to_ProcName ($name); + + if (exists $calls{$name}) { + $calls{$name}->{ret} = "${structprefix}_${name}_ret"; + } else { + $calls{$name} = { + name => $name, + ProcName => $ProcName, + UC_NAME => uc $name, + args => "void", + ret => "${structprefix}_${name}_ret" + } + } + } elsif (/^struct ${structprefix}_(.*)_msg/) { + $name = $1; + $ProcName = name_to_ProcName ($name); + + $calls{$name} = { + name => $name, + ProcName => $ProcName, + UC_NAME => uc $name, + msg => "${structprefix}_${name}_msg" + } + } elsif (/^\s*${procprefix}_PROC_(.*?)\s+=\s+(\d+),?$/) { + $name = lc $1; + $id = $2; + $ProcName = name_to_ProcName ($name); + + $calls[$id] = $calls{$name}; + } +} + +#---------------------------------------------------------------------- +# Output + +print <<__EOF__; +/* Automatically generated by remote_generator.pl. + * Do not edit this file. Any changes you make will be lost. + */ + +__EOF__ + +# Debugging. +if ($opt_d) { + my @keys = sort (keys %calls); + foreach (@keys) { + print "$_:\n"; + print " name $calls{$_}->{name} ($calls{$_}->{ProcName})\n"; + print " $calls{$_}->{args} -> $calls{$_}->{ret}\n"; + } +} + +# Prototypes for dispatch functions ("remote_dispatch_prototypes.h"). +elsif ($opt_p) { + my @keys = sort (keys %calls); + foreach (@keys) { + # Skip things which are REMOTE_MESSAGE + next if $calls{$_}->{msg}; + + print "static int ${structprefix}Dispatch$calls{$_}->{ProcName}(\n"; + print " struct qemud_server *server,\n"; + print " struct qemud_client *client,\n"; + print " virConnectPtr conn,\n"; + print " remote_message_header *hdr,\n"; + print " remote_error *rerr,\n"; + print " $calls{$_}->{args} *args,\n"; + print " $calls{$_}->{ret} *ret);\n"; + } +} + +# Union of all arg types +# ("remote_dispatch_args.h"). +elsif ($opt_a) { + for ($id = 0 ; $id <= $#calls ; $id++) { + if (defined $calls[$id] && + !$calls[$id]->{msg} && + $calls[$id]->{args} ne "void") { + print " $calls[$id]->{args} val_$calls[$id]->{args};\n"; + } + } +} + +# Union of all arg types +# ("remote_dispatch_ret.h"). +elsif ($opt_r) { + for ($id = 0 ; $id <= $#calls ; $id++) { + if (defined $calls[$id] && + !$calls[$id]->{msg} && + $calls[$id]->{ret} ne "void") { + print " $calls[$id]->{ret} val_$calls[$id]->{ret};\n"; + } + } +} + +# Inside the switch statement, prepare the 'fn', 'args_filter', etc +# ("remote_dispatch_table.h"). +elsif ($opt_t) { + for ($id = 0 ; $id <= $#calls ; $id++) { + if (defined $calls[$id] && !$calls[$id]->{msg}) { + print "{ /* $calls[$id]->{ProcName} => $id */\n"; + print " .fn = (dispatch_fn) ${structprefix}Dispatch$calls[$id]->{ProcName},\n"; + if ($calls[$id]->{args} ne "void") { + print " .args_filter = (xdrproc_t) xdr_$calls[$id]->{args},\n"; + } else { + print " .args_filter = (xdrproc_t) xdr_void,\n"; + } + if ($calls[$id]->{ret} ne "void") { + print " .ret_filter = (xdrproc_t) xdr_$calls[$id]->{ret},\n"; + } else { + print " .ret_filter = (xdrproc_t) xdr_void,\n"; + } + print "},\n"; + } else { + if ($calls[$id]->{msg}) { + print "{ /* Async event $calls[$id]->{ProcName} => $id */\n"; + } else { + print "{ /* (unused) => $id */\n"; + } + print " .fn = NULL,\n"; + print " .args_filter = (xdrproc_t) xdr_void,\n"; + print " .ret_filter = (xdrproc_t) xdr_void,\n"; + print "},\n"; + } + } +} diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 675eccd..b9f1bc7 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -367,7 +367,7 @@ struct remote_memory_param { * connection). Errors are returned implicitly in the RPC protocol. * * Please follow the naming convention carefully - this file is - * parsed by 'remote_generate_stubs.pl'. + * parsed by 'remote_generator.pl'. */ struct remote_open_args { -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:13:51 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:51 +0200 Subject: [libvirt] [PATCH 04/22] remote generator, daemon: Change capitalization of some words In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-5-git-send-email-matthias.bolte@googlemail.com> Again this will simplify the generator, due to less special case handling. --- daemon/remote.c | 64 +++++++++--------- daemon/remote_dispatch_bodies.c | 64 +++++++++--------- daemon/remote_dispatch_prototypes.h | 64 +++++++++--------- daemon/remote_dispatch_table.h | 128 +++++++++++++++++----------------- daemon/remote_generator.pl | 3 +- 5 files changed, 162 insertions(+), 161 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 48dbcc5..5057cfc 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -607,7 +607,7 @@ cleanup: } static int -remoteDispatchGetUri(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchGetURI(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -1320,7 +1320,7 @@ cleanup: } static int -remoteDispatchDomainCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchDomainCreateXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -1352,7 +1352,7 @@ cleanup: } static int -remoteDispatchDomainDefineXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchDomainDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -1384,7 +1384,7 @@ cleanup: } static int -remoteDispatchDomainDumpXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchDomainDumpXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -1418,7 +1418,7 @@ cleanup: } static int -remoteDispatchDomainXmlFromNative(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchDomainXMLFromNative(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -1449,7 +1449,7 @@ cleanup: } static int -remoteDispatchDomainXmlToNative(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchDomainXMLToNative(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -2235,7 +2235,7 @@ cleanup: } static int -remoteDispatchDomainLookupByUuid(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchDomainLookupByUUID(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -2934,7 +2934,7 @@ cleanup: } static int -remoteDispatchNetworkCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNetworkCreateXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -2966,7 +2966,7 @@ cleanup: } static int -remoteDispatchNetworkDefineXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNetworkDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -2998,7 +2998,7 @@ cleanup: } static int -remoteDispatchNetworkDumpXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNetworkDumpXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -3131,7 +3131,7 @@ cleanup: } static int -remoteDispatchNetworkLookupByUuid(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNetworkLookupByUUID(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -3460,7 +3460,7 @@ cleanup: } static int -remoteDispatchInterfaceGetXmlDesc(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchInterfaceGetXMLDesc(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -3494,7 +3494,7 @@ cleanup: } static int -remoteDispatchInterfaceDefineXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchInterfaceDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -4452,7 +4452,7 @@ cleanup: } static int -remoteDispatchStoragePoolCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchStoragePoolCreateXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -4484,7 +4484,7 @@ cleanup: } static int -remoteDispatchStoragePoolDefineXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchStoragePoolDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -4555,7 +4555,7 @@ cleanup: } static int -remoteDispatchStoragePoolDumpXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchStoragePoolDumpXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -4655,7 +4655,7 @@ cleanup: } static int -remoteDispatchStoragePoolLookupByUuid(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchStoragePoolLookupByUUID(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -4871,7 +4871,7 @@ cleanup: static int -remoteDispatchStorageVolCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchStorageVolCreateXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -4908,7 +4908,7 @@ cleanup: } static int -remoteDispatchStorageVolCreateXmlFrom(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchStorageVolCreateXMLFrom(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -4990,7 +4990,7 @@ cleanup: } static int -remoteDispatchStorageVolDumpXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchStorageVolDumpXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -5278,7 +5278,7 @@ cleanup: static int -remoteDispatchNodeDeviceDumpXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNodeDeviceDumpXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -5449,7 +5449,7 @@ cleanup: } static int -remoteDispatchNodeDeviceCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNodeDeviceCreateXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -5783,7 +5783,7 @@ cleanup: } static int -remoteDispatchSecretDefineXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchSecretDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -5852,7 +5852,7 @@ cleanup: } static int -remoteDispatchSecretGetXmlDesc(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchSecretGetXMLDesc(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -5884,7 +5884,7 @@ cleanup: } static int -remoteDispatchSecretLookupByUuid(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchSecretLookupByUUID(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -6344,7 +6344,7 @@ cleanup: } static int -remoteDispatchDomainSnapshotCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchDomainSnapshotCreateXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -6382,7 +6382,7 @@ cleanup: } static int -remoteDispatchDomainSnapshotDumpXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchDomainSnapshotDumpXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -6741,7 +6741,7 @@ cleanup: } static int -remoteDispatchNWFilterLookupByUuid(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNWFilterLookupByUUID(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -6774,7 +6774,7 @@ cleanup: static int -remoteDispatchNWFilterDefineXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNWFilterDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -6806,7 +6806,7 @@ cleanup: } static int -remoteDispatchListNwfilters(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchListNWFilters(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -6852,7 +6852,7 @@ cleanup: static int -remoteDispatchNWFilterGetXmlDesc(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNWFilterGetXMLDesc(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -6887,7 +6887,7 @@ cleanup: static int -remoteDispatchNumOfNwfilters(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNumOfNWFilters(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, diff --git a/daemon/remote_dispatch_bodies.c b/daemon/remote_dispatch_bodies.c index a3360c5..6b4abec 100644 --- a/daemon/remote_dispatch_bodies.c +++ b/daemon/remote_dispatch_bodies.c @@ -194,9 +194,9 @@ cleanup: /* remoteDispatchDomainCreateWithFlags has to be implemented manually */ -/* remoteDispatchDomainCreateXml has to be implemented manually */ +/* remoteDispatchDomainCreateXML has to be implemented manually */ -/* remoteDispatchDomainDefineXml has to be implemented manually */ +/* remoteDispatchDomainDefineXML has to be implemented manually */ static int remoteDispatchDomainDestroy( @@ -300,7 +300,7 @@ cleanup: return rv; } -/* remoteDispatchDomainDumpXml has to be implemented manually */ +/* remoteDispatchDomainDumpXML has to be implemented manually */ /* remoteDispatchDomainEventsDeregister has to be implemented manually */ @@ -354,7 +354,7 @@ cleanup: /* remoteDispatchDomainLookupByName has to be implemented manually */ -/* remoteDispatchDomainLookupByUuid has to be implemented manually */ +/* remoteDispatchDomainLookupByUUID has to be implemented manually */ static int remoteDispatchDomainManagedSave( @@ -928,7 +928,7 @@ cleanup: return rv; } -/* remoteDispatchDomainSnapshotCreateXml has to be implemented manually */ +/* remoteDispatchDomainSnapshotCreateXML has to be implemented manually */ /* remoteDispatchDomainSnapshotCurrent has to be implemented manually */ @@ -972,7 +972,7 @@ cleanup: return rv; } -/* remoteDispatchDomainSnapshotDumpXml has to be implemented manually */ +/* remoteDispatchDomainSnapshotDumpXML has to be implemented manually */ /* remoteDispatchDomainSnapshotListNames has to be implemented manually */ @@ -1082,9 +1082,9 @@ cleanup: return rv; } -/* remoteDispatchDomainXmlFromNative has to be implemented manually */ +/* remoteDispatchDomainXMLFromNative has to be implemented manually */ -/* remoteDispatchDomainXmlToNative has to be implemented manually */ +/* remoteDispatchDomainXMLToNative has to be implemented manually */ /* remoteDispatchFindStoragePoolSources has to be implemented manually */ @@ -1100,7 +1100,7 @@ cleanup: /* remoteDispatchGetType has to be implemented manually */ -/* remoteDispatchGetUri has to be implemented manually */ +/* remoteDispatchGetURI has to be implemented manually */ /* remoteDispatchGetVersion has to be implemented manually */ @@ -1138,7 +1138,7 @@ cleanup: return rv; } -/* remoteDispatchInterfaceDefineXml has to be implemented manually */ +/* remoteDispatchInterfaceDefineXML has to be implemented manually */ static int remoteDispatchInterfaceDestroy( @@ -1174,7 +1174,7 @@ cleanup: return rv; } -/* remoteDispatchInterfaceGetXmlDesc has to be implemented manually */ +/* remoteDispatchInterfaceGetXMLDesc has to be implemented manually */ /* remoteDispatchInterfaceIsActive has to be implemented manually */ @@ -1232,7 +1232,7 @@ cleanup: /* remoteDispatchListNetworks has to be implemented manually */ -/* remoteDispatchListNwfilters has to be implemented manually */ +/* remoteDispatchListNWFilters has to be implemented manually */ /* remoteDispatchListSecrets has to be implemented manually */ @@ -1272,9 +1272,9 @@ cleanup: return rv; } -/* remoteDispatchNetworkCreateXml has to be implemented manually */ +/* remoteDispatchNetworkCreateXML has to be implemented manually */ -/* remoteDispatchNetworkDefineXml has to be implemented manually */ +/* remoteDispatchNetworkDefineXML has to be implemented manually */ static int remoteDispatchNetworkDestroy( @@ -1310,7 +1310,7 @@ cleanup: return rv; } -/* remoteDispatchNetworkDumpXml has to be implemented manually */ +/* remoteDispatchNetworkDumpXML has to be implemented manually */ /* remoteDispatchNetworkGetAutostart has to be implemented manually */ @@ -1322,7 +1322,7 @@ cleanup: /* remoteDispatchNetworkLookupByName has to be implemented manually */ -/* remoteDispatchNetworkLookupByUuid has to be implemented manually */ +/* remoteDispatchNetworkLookupByUUID has to be implemented manually */ static int remoteDispatchNetworkSetAutostart( @@ -1392,7 +1392,7 @@ cleanup: return rv; } -/* remoteDispatchNodeDeviceCreateXml has to be implemented manually */ +/* remoteDispatchNodeDeviceCreateXML has to be implemented manually */ static int remoteDispatchNodeDeviceDestroy( @@ -1462,7 +1462,7 @@ cleanup: return rv; } -/* remoteDispatchNodeDeviceDumpXml has to be implemented manually */ +/* remoteDispatchNodeDeviceDumpXML has to be implemented manually */ /* remoteDispatchNodeDeviceGetParent has to be implemented manually */ @@ -1566,19 +1566,19 @@ cleanup: /* remoteDispatchNumOfNetworks has to be implemented manually */ -/* remoteDispatchNumOfNwfilters has to be implemented manually */ +/* remoteDispatchNumOfNWFilters has to be implemented manually */ /* remoteDispatchNumOfSecrets has to be implemented manually */ /* remoteDispatchNumOfStoragePools has to be implemented manually */ -/* remoteDispatchNWFilterDefineXml has to be implemented manually */ +/* remoteDispatchNWFilterDefineXML has to be implemented manually */ -/* remoteDispatchNWFilterGetXmlDesc has to be implemented manually */ +/* remoteDispatchNWFilterGetXMLDesc has to be implemented manually */ /* remoteDispatchNWFilterLookupByName has to be implemented manually */ -/* remoteDispatchNWFilterLookupByUuid has to be implemented manually */ +/* remoteDispatchNWFilterLookupByUUID has to be implemented manually */ static int remoteDispatchNWFilterUndefine( @@ -1616,15 +1616,15 @@ cleanup: /* remoteDispatchOpen has to be implemented manually */ -/* remoteDispatchSecretDefineXml has to be implemented manually */ +/* remoteDispatchSecretDefineXML has to be implemented manually */ /* remoteDispatchSecretGetValue has to be implemented manually */ -/* remoteDispatchSecretGetXmlDesc has to be implemented manually */ +/* remoteDispatchSecretGetXMLDesc has to be implemented manually */ /* remoteDispatchSecretLookupByUsage has to be implemented manually */ -/* remoteDispatchSecretLookupByUuid has to be implemented manually */ +/* remoteDispatchSecretLookupByUUID has to be implemented manually */ static int remoteDispatchSecretSetValue( @@ -1762,9 +1762,9 @@ cleanup: return rv; } -/* remoteDispatchStoragePoolCreateXml has to be implemented manually */ +/* remoteDispatchStoragePoolCreateXML has to be implemented manually */ -/* remoteDispatchStoragePoolDefineXml has to be implemented manually */ +/* remoteDispatchStoragePoolDefineXML has to be implemented manually */ static int remoteDispatchStoragePoolDelete( @@ -1834,7 +1834,7 @@ cleanup: return rv; } -/* remoteDispatchStoragePoolDumpXml has to be implemented manually */ +/* remoteDispatchStoragePoolDumpXML has to be implemented manually */ /* remoteDispatchStoragePoolGetAutostart has to be implemented manually */ @@ -1848,7 +1848,7 @@ cleanup: /* remoteDispatchStoragePoolLookupByName has to be implemented manually */ -/* remoteDispatchStoragePoolLookupByUuid has to be implemented manually */ +/* remoteDispatchStoragePoolLookupByUUID has to be implemented manually */ /* remoteDispatchStoragePoolLookupByVolume has to be implemented manually */ @@ -1956,9 +1956,9 @@ cleanup: return rv; } -/* remoteDispatchStorageVolCreateXml has to be implemented manually */ +/* remoteDispatchStorageVolCreateXML has to be implemented manually */ -/* remoteDispatchStorageVolCreateXmlFrom has to be implemented manually */ +/* remoteDispatchStorageVolCreateXMLFrom has to be implemented manually */ static int remoteDispatchStorageVolDelete( @@ -1996,7 +1996,7 @@ cleanup: /* remoteDispatchStorageVolDownload has to be implemented manually */ -/* remoteDispatchStorageVolDumpXml has to be implemented manually */ +/* remoteDispatchStorageVolDumpXML has to be implemented manually */ /* remoteDispatchStorageVolGetInfo has to be implemented manually */ diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 29ae5ba..dff84d7 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -130,7 +130,7 @@ static int remoteDispatchDomainCreateWithFlags( remote_error *rerr, remote_domain_create_with_flags_args *args, remote_domain_create_with_flags_ret *ret); -static int remoteDispatchDomainCreateXml( +static int remoteDispatchDomainCreateXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -138,7 +138,7 @@ static int remoteDispatchDomainCreateXml( remote_error *rerr, remote_domain_create_xml_args *args, remote_domain_create_xml_ret *ret); -static int remoteDispatchDomainDefineXml( +static int remoteDispatchDomainDefineXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -170,7 +170,7 @@ static int remoteDispatchDomainDetachDeviceFlags( remote_error *rerr, remote_domain_detach_device_flags_args *args, void *ret); -static int remoteDispatchDomainDumpXml( +static int remoteDispatchDomainDumpXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -386,7 +386,7 @@ static int remoteDispatchDomainLookupByName( remote_error *rerr, remote_domain_lookup_by_name_args *args, remote_domain_lookup_by_name_ret *ret); -static int remoteDispatchDomainLookupByUuid( +static int remoteDispatchDomainLookupByUUID( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -626,7 +626,7 @@ static int remoteDispatchDomainShutdown( remote_error *rerr, remote_domain_shutdown_args *args, void *ret); -static int remoteDispatchDomainSnapshotCreateXml( +static int remoteDispatchDomainSnapshotCreateXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -650,7 +650,7 @@ static int remoteDispatchDomainSnapshotDelete( remote_error *rerr, remote_domain_snapshot_delete_args *args, void *ret); -static int remoteDispatchDomainSnapshotDumpXml( +static int remoteDispatchDomainSnapshotDumpXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -706,7 +706,7 @@ static int remoteDispatchDomainUpdateDeviceFlags( remote_error *rerr, remote_domain_update_device_flags_args *args, void *ret); -static int remoteDispatchDomainXmlFromNative( +static int remoteDispatchDomainXMLFromNative( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -714,7 +714,7 @@ static int remoteDispatchDomainXmlFromNative( remote_error *rerr, remote_domain_xml_from_native_args *args, remote_domain_xml_from_native_ret *ret); -static int remoteDispatchDomainXmlToNative( +static int remoteDispatchDomainXMLToNative( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -778,7 +778,7 @@ static int remoteDispatchGetType( remote_error *rerr, void *args, remote_get_type_ret *ret); -static int remoteDispatchGetUri( +static int remoteDispatchGetURI( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -802,7 +802,7 @@ static int remoteDispatchInterfaceCreate( remote_error *rerr, remote_interface_create_args *args, void *ret); -static int remoteDispatchInterfaceDefineXml( +static int remoteDispatchInterfaceDefineXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -818,7 +818,7 @@ static int remoteDispatchInterfaceDestroy( remote_error *rerr, remote_interface_destroy_args *args, void *ret); -static int remoteDispatchInterfaceGetXmlDesc( +static int remoteDispatchInterfaceGetXMLDesc( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -922,7 +922,7 @@ static int remoteDispatchListNetworks( remote_error *rerr, remote_list_networks_args *args, remote_list_networks_ret *ret); -static int remoteDispatchListNwfilters( +static int remoteDispatchListNWFilters( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -954,7 +954,7 @@ static int remoteDispatchNetworkCreate( remote_error *rerr, remote_network_create_args *args, void *ret); -static int remoteDispatchNetworkCreateXml( +static int remoteDispatchNetworkCreateXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -962,7 +962,7 @@ static int remoteDispatchNetworkCreateXml( remote_error *rerr, remote_network_create_xml_args *args, remote_network_create_xml_ret *ret); -static int remoteDispatchNetworkDefineXml( +static int remoteDispatchNetworkDefineXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -978,7 +978,7 @@ static int remoteDispatchNetworkDestroy( remote_error *rerr, remote_network_destroy_args *args, void *ret); -static int remoteDispatchNetworkDumpXml( +static int remoteDispatchNetworkDumpXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1026,7 +1026,7 @@ static int remoteDispatchNetworkLookupByName( remote_error *rerr, remote_network_lookup_by_name_args *args, remote_network_lookup_by_name_ret *ret); -static int remoteDispatchNetworkLookupByUuid( +static int remoteDispatchNetworkLookupByUUID( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1050,7 +1050,7 @@ static int remoteDispatchNetworkUndefine( remote_error *rerr, remote_network_undefine_args *args, void *ret); -static int remoteDispatchNodeDeviceCreateXml( +static int remoteDispatchNodeDeviceCreateXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1074,7 +1074,7 @@ static int remoteDispatchNodeDeviceDettach( remote_error *rerr, remote_node_device_dettach_args *args, void *ret); -static int remoteDispatchNodeDeviceDumpXml( +static int remoteDispatchNodeDeviceDumpXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1234,7 +1234,7 @@ static int remoteDispatchNumOfNetworks( remote_error *rerr, void *args, remote_num_of_networks_ret *ret); -static int remoteDispatchNumOfNwfilters( +static int remoteDispatchNumOfNWFilters( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1258,7 +1258,7 @@ static int remoteDispatchNumOfStoragePools( remote_error *rerr, void *args, remote_num_of_storage_pools_ret *ret); -static int remoteDispatchNWFilterDefineXml( +static int remoteDispatchNWFilterDefineXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1266,7 +1266,7 @@ static int remoteDispatchNWFilterDefineXml( remote_error *rerr, remote_nwfilter_define_xml_args *args, remote_nwfilter_define_xml_ret *ret); -static int remoteDispatchNWFilterGetXmlDesc( +static int remoteDispatchNWFilterGetXMLDesc( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1282,7 +1282,7 @@ static int remoteDispatchNWFilterLookupByName( remote_error *rerr, remote_nwfilter_lookup_by_name_args *args, remote_nwfilter_lookup_by_name_ret *ret); -static int remoteDispatchNWFilterLookupByUuid( +static int remoteDispatchNWFilterLookupByUUID( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1306,7 +1306,7 @@ static int remoteDispatchOpen( remote_error *rerr, remote_open_args *args, void *ret); -static int remoteDispatchSecretDefineXml( +static int remoteDispatchSecretDefineXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1322,7 +1322,7 @@ static int remoteDispatchSecretGetValue( remote_error *rerr, remote_secret_get_value_args *args, remote_secret_get_value_ret *ret); -static int remoteDispatchSecretGetXmlDesc( +static int remoteDispatchSecretGetXMLDesc( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1338,7 +1338,7 @@ static int remoteDispatchSecretLookupByUsage( remote_error *rerr, remote_secret_lookup_by_usage_args *args, remote_secret_lookup_by_usage_ret *ret); -static int remoteDispatchSecretLookupByUuid( +static int remoteDispatchSecretLookupByUUID( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1378,7 +1378,7 @@ static int remoteDispatchStoragePoolCreate( remote_error *rerr, remote_storage_pool_create_args *args, void *ret); -static int remoteDispatchStoragePoolCreateXml( +static int remoteDispatchStoragePoolCreateXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1386,7 +1386,7 @@ static int remoteDispatchStoragePoolCreateXml( remote_error *rerr, remote_storage_pool_create_xml_args *args, remote_storage_pool_create_xml_ret *ret); -static int remoteDispatchStoragePoolDefineXml( +static int remoteDispatchStoragePoolDefineXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1410,7 +1410,7 @@ static int remoteDispatchStoragePoolDestroy( remote_error *rerr, remote_storage_pool_destroy_args *args, void *ret); -static int remoteDispatchStoragePoolDumpXml( +static int remoteDispatchStoragePoolDumpXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1466,7 +1466,7 @@ static int remoteDispatchStoragePoolLookupByName( remote_error *rerr, remote_storage_pool_lookup_by_name_args *args, remote_storage_pool_lookup_by_name_ret *ret); -static int remoteDispatchStoragePoolLookupByUuid( +static int remoteDispatchStoragePoolLookupByUUID( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1514,7 +1514,7 @@ static int remoteDispatchStoragePoolUndefine( remote_error *rerr, remote_storage_pool_undefine_args *args, void *ret); -static int remoteDispatchStorageVolCreateXml( +static int remoteDispatchStorageVolCreateXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1522,7 +1522,7 @@ static int remoteDispatchStorageVolCreateXml( remote_error *rerr, remote_storage_vol_create_xml_args *args, remote_storage_vol_create_xml_ret *ret); -static int remoteDispatchStorageVolCreateXmlFrom( +static int remoteDispatchStorageVolCreateXMLFrom( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1546,7 +1546,7 @@ static int remoteDispatchStorageVolDownload( remote_error *rerr, remote_storage_vol_download_args *args, void *ret); -static int remoteDispatchStorageVolDumpXml( +static int remoteDispatchStorageVolDumpXML( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index d711abc..627331e 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -52,13 +52,13 @@ .args_filter = (xdrproc_t) xdr_remote_domain_create_args, .ret_filter = (xdrproc_t) xdr_void, }, -{ /* DomainCreateXml => 10 */ - .fn = (dispatch_fn) remoteDispatchDomainCreateXml, +{ /* DomainCreateXML => 10 */ + .fn = (dispatch_fn) remoteDispatchDomainCreateXML, .args_filter = (xdrproc_t) xdr_remote_domain_create_xml_args, .ret_filter = (xdrproc_t) xdr_remote_domain_create_xml_ret, }, -{ /* DomainDefineXml => 11 */ - .fn = (dispatch_fn) remoteDispatchDomainDefineXml, +{ /* DomainDefineXML => 11 */ + .fn = (dispatch_fn) remoteDispatchDomainDefineXML, .args_filter = (xdrproc_t) xdr_remote_domain_define_xml_args, .ret_filter = (xdrproc_t) xdr_remote_domain_define_xml_ret, }, @@ -72,8 +72,8 @@ .args_filter = (xdrproc_t) xdr_remote_domain_detach_device_args, .ret_filter = (xdrproc_t) xdr_void, }, -{ /* DomainDumpXml => 14 */ - .fn = (dispatch_fn) remoteDispatchDomainDumpXml, +{ /* DomainDumpXML => 14 */ + .fn = (dispatch_fn) remoteDispatchDomainDumpXML, .args_filter = (xdrproc_t) xdr_remote_domain_dump_xml_args, .ret_filter = (xdrproc_t) xdr_remote_domain_dump_xml_ret, }, @@ -122,8 +122,8 @@ .args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_name_args, .ret_filter = (xdrproc_t) xdr_remote_domain_lookup_by_name_ret, }, -{ /* DomainLookupByUuid => 24 */ - .fn = (dispatch_fn) remoteDispatchDomainLookupByUuid, +{ /* DomainLookupByUUID => 24 */ + .fn = (dispatch_fn) remoteDispatchDomainLookupByUUID, .args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_uuid_args, .ret_filter = (xdrproc_t) xdr_remote_domain_lookup_by_uuid_ret, }, @@ -202,13 +202,13 @@ .args_filter = (xdrproc_t) xdr_remote_network_create_args, .ret_filter = (xdrproc_t) xdr_void, }, -{ /* NetworkCreateXml => 40 */ - .fn = (dispatch_fn) remoteDispatchNetworkCreateXml, +{ /* NetworkCreateXML => 40 */ + .fn = (dispatch_fn) remoteDispatchNetworkCreateXML, .args_filter = (xdrproc_t) xdr_remote_network_create_xml_args, .ret_filter = (xdrproc_t) xdr_remote_network_create_xml_ret, }, -{ /* NetworkDefineXml => 41 */ - .fn = (dispatch_fn) remoteDispatchNetworkDefineXml, +{ /* NetworkDefineXML => 41 */ + .fn = (dispatch_fn) remoteDispatchNetworkDefineXML, .args_filter = (xdrproc_t) xdr_remote_network_define_xml_args, .ret_filter = (xdrproc_t) xdr_remote_network_define_xml_ret, }, @@ -217,8 +217,8 @@ .args_filter = (xdrproc_t) xdr_remote_network_destroy_args, .ret_filter = (xdrproc_t) xdr_void, }, -{ /* NetworkDumpXml => 43 */ - .fn = (dispatch_fn) remoteDispatchNetworkDumpXml, +{ /* NetworkDumpXML => 43 */ + .fn = (dispatch_fn) remoteDispatchNetworkDumpXML, .args_filter = (xdrproc_t) xdr_remote_network_dump_xml_args, .ret_filter = (xdrproc_t) xdr_remote_network_dump_xml_ret, }, @@ -237,8 +237,8 @@ .args_filter = (xdrproc_t) xdr_remote_network_lookup_by_name_args, .ret_filter = (xdrproc_t) xdr_remote_network_lookup_by_name_ret, }, -{ /* NetworkLookupByUuid => 47 */ - .fn = (dispatch_fn) remoteDispatchNetworkLookupByUuid, +{ /* NetworkLookupByUUID => 47 */ + .fn = (dispatch_fn) remoteDispatchNetworkLookupByUUID, .args_filter = (xdrproc_t) xdr_remote_network_lookup_by_uuid_args, .ret_filter = (xdrproc_t) xdr_remote_network_lookup_by_uuid_ret, }, @@ -382,13 +382,13 @@ .args_filter = (xdrproc_t) xdr_remote_find_storage_pool_sources_args, .ret_filter = (xdrproc_t) xdr_remote_find_storage_pool_sources_ret, }, -{ /* StoragePoolCreateXml => 76 */ - .fn = (dispatch_fn) remoteDispatchStoragePoolCreateXml, +{ /* StoragePoolCreateXML => 76 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolCreateXML, .args_filter = (xdrproc_t) xdr_remote_storage_pool_create_xml_args, .ret_filter = (xdrproc_t) xdr_remote_storage_pool_create_xml_ret, }, -{ /* StoragePoolDefineXml => 77 */ - .fn = (dispatch_fn) remoteDispatchStoragePoolDefineXml, +{ /* StoragePoolDefineXML => 77 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolDefineXML, .args_filter = (xdrproc_t) xdr_remote_storage_pool_define_xml_args, .ret_filter = (xdrproc_t) xdr_remote_storage_pool_define_xml_ret, }, @@ -427,8 +427,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_args, .ret_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_ret, }, -{ /* StoragePoolLookupByUuid => 85 */ - .fn = (dispatch_fn) remoteDispatchStoragePoolLookupByUuid, +{ /* StoragePoolLookupByUUID => 85 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolLookupByUUID, .args_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_args, .ret_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_ret, }, @@ -442,8 +442,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_pool_get_info_args, .ret_filter = (xdrproc_t) xdr_remote_storage_pool_get_info_ret, }, -{ /* StoragePoolDumpXml => 88 */ - .fn = (dispatch_fn) remoteDispatchStoragePoolDumpXml, +{ /* StoragePoolDumpXML => 88 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolDumpXML, .args_filter = (xdrproc_t) xdr_remote_storage_pool_dump_xml_args, .ret_filter = (xdrproc_t) xdr_remote_storage_pool_dump_xml_ret, }, @@ -467,8 +467,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_pool_list_volumes_args, .ret_filter = (xdrproc_t) xdr_remote_storage_pool_list_volumes_ret, }, -{ /* StorageVolCreateXml => 93 */ - .fn = (dispatch_fn) remoteDispatchStorageVolCreateXml, +{ /* StorageVolCreateXML => 93 */ + .fn = (dispatch_fn) remoteDispatchStorageVolCreateXML, .args_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_args, .ret_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_ret, }, @@ -497,8 +497,8 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_get_info_args, .ret_filter = (xdrproc_t) xdr_remote_storage_vol_get_info_ret, }, -{ /* StorageVolDumpXml => 99 */ - .fn = (dispatch_fn) remoteDispatchStorageVolDumpXml, +{ /* StorageVolDumpXML => 99 */ + .fn = (dispatch_fn) remoteDispatchStorageVolDumpXML, .args_filter = (xdrproc_t) xdr_remote_storage_vol_dump_xml_args, .ret_filter = (xdrproc_t) xdr_remote_storage_vol_dump_xml_ret, }, @@ -552,8 +552,8 @@ .args_filter = (xdrproc_t) xdr_remote_domain_migrate_finish2_args, .ret_filter = (xdrproc_t) xdr_remote_domain_migrate_finish2_ret, }, -{ /* GetUri => 110 */ - .fn = (dispatch_fn) remoteDispatchGetUri, +{ /* GetURI => 110 */ + .fn = (dispatch_fn) remoteDispatchGetURI, .args_filter = (xdrproc_t) xdr_void, .ret_filter = (xdrproc_t) xdr_remote_get_uri_ret, }, @@ -572,8 +572,8 @@ .args_filter = (xdrproc_t) xdr_remote_node_device_lookup_by_name_args, .ret_filter = (xdrproc_t) xdr_remote_node_device_lookup_by_name_ret, }, -{ /* NodeDeviceDumpXml => 114 */ - .fn = (dispatch_fn) remoteDispatchNodeDeviceDumpXml, +{ /* NodeDeviceDumpXML => 114 */ + .fn = (dispatch_fn) remoteDispatchNodeDeviceDumpXML, .args_filter = (xdrproc_t) xdr_remote_node_device_dump_xml_args, .ret_filter = (xdrproc_t) xdr_remote_node_device_dump_xml_ret, }, @@ -617,8 +617,8 @@ .args_filter = (xdrproc_t) xdr_void, .ret_filter = (xdrproc_t) xdr_remote_node_get_security_model_ret, }, -{ /* NodeDeviceCreateXml => 123 */ - .fn = (dispatch_fn) remoteDispatchNodeDeviceCreateXml, +{ /* NodeDeviceCreateXML => 123 */ + .fn = (dispatch_fn) remoteDispatchNodeDeviceCreateXML, .args_filter = (xdrproc_t) xdr_remote_node_device_create_xml_args, .ret_filter = (xdrproc_t) xdr_remote_node_device_create_xml_ret, }, @@ -627,8 +627,8 @@ .args_filter = (xdrproc_t) xdr_remote_node_device_destroy_args, .ret_filter = (xdrproc_t) xdr_void, }, -{ /* StorageVolCreateXmlFrom => 125 */ - .fn = (dispatch_fn) remoteDispatchStorageVolCreateXmlFrom, +{ /* StorageVolCreateXMLFrom => 125 */ + .fn = (dispatch_fn) remoteDispatchStorageVolCreateXMLFrom, .args_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_from_args, .ret_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_from_ret, }, @@ -652,13 +652,13 @@ .args_filter = (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_args, .ret_filter = (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_ret, }, -{ /* InterfaceGetXmlDesc => 130 */ - .fn = (dispatch_fn) remoteDispatchInterfaceGetXmlDesc, +{ /* InterfaceGetXMLDesc => 130 */ + .fn = (dispatch_fn) remoteDispatchInterfaceGetXMLDesc, .args_filter = (xdrproc_t) xdr_remote_interface_get_xml_desc_args, .ret_filter = (xdrproc_t) xdr_remote_interface_get_xml_desc_ret, }, -{ /* InterfaceDefineXml => 131 */ - .fn = (dispatch_fn) remoteDispatchInterfaceDefineXml, +{ /* InterfaceDefineXML => 131 */ + .fn = (dispatch_fn) remoteDispatchInterfaceDefineXML, .args_filter = (xdrproc_t) xdr_remote_interface_define_xml_args, .ret_filter = (xdrproc_t) xdr_remote_interface_define_xml_ret, }, @@ -677,13 +677,13 @@ .args_filter = (xdrproc_t) xdr_remote_interface_destroy_args, .ret_filter = (xdrproc_t) xdr_void, }, -{ /* DomainXmlFromNative => 135 */ - .fn = (dispatch_fn) remoteDispatchDomainXmlFromNative, +{ /* DomainXMLFromNative => 135 */ + .fn = (dispatch_fn) remoteDispatchDomainXMLFromNative, .args_filter = (xdrproc_t) xdr_remote_domain_xml_from_native_args, .ret_filter = (xdrproc_t) xdr_remote_domain_xml_from_native_ret, }, -{ /* DomainXmlToNative => 136 */ - .fn = (dispatch_fn) remoteDispatchDomainXmlToNative, +{ /* DomainXMLToNative => 136 */ + .fn = (dispatch_fn) remoteDispatchDomainXMLToNative, .args_filter = (xdrproc_t) xdr_remote_domain_xml_to_native_args, .ret_filter = (xdrproc_t) xdr_remote_domain_xml_to_native_ret, }, @@ -707,18 +707,18 @@ .args_filter = (xdrproc_t) xdr_remote_list_secrets_args, .ret_filter = (xdrproc_t) xdr_remote_list_secrets_ret, }, -{ /* SecretLookupByUuid => 141 */ - .fn = (dispatch_fn) remoteDispatchSecretLookupByUuid, +{ /* SecretLookupByUUID => 141 */ + .fn = (dispatch_fn) remoteDispatchSecretLookupByUUID, .args_filter = (xdrproc_t) xdr_remote_secret_lookup_by_uuid_args, .ret_filter = (xdrproc_t) xdr_remote_secret_lookup_by_uuid_ret, }, -{ /* SecretDefineXml => 142 */ - .fn = (dispatch_fn) remoteDispatchSecretDefineXml, +{ /* SecretDefineXML => 142 */ + .fn = (dispatch_fn) remoteDispatchSecretDefineXML, .args_filter = (xdrproc_t) xdr_remote_secret_define_xml_args, .ret_filter = (xdrproc_t) xdr_remote_secret_define_xml_ret, }, -{ /* SecretGetXmlDesc => 143 */ - .fn = (dispatch_fn) remoteDispatchSecretGetXmlDesc, +{ /* SecretGetXMLDesc => 143 */ + .fn = (dispatch_fn) remoteDispatchSecretGetXMLDesc, .args_filter = (xdrproc_t) xdr_remote_secret_get_xml_desc_args, .ret_filter = (xdrproc_t) xdr_remote_secret_get_xml_desc_ret, }, @@ -882,28 +882,28 @@ .args_filter = (xdrproc_t) xdr_remote_nwfilter_lookup_by_name_args, .ret_filter = (xdrproc_t) xdr_remote_nwfilter_lookup_by_name_ret, }, -{ /* NWFilterLookupByUuid => 176 */ - .fn = (dispatch_fn) remoteDispatchNWFilterLookupByUuid, +{ /* NWFilterLookupByUUID => 176 */ + .fn = (dispatch_fn) remoteDispatchNWFilterLookupByUUID, .args_filter = (xdrproc_t) xdr_remote_nwfilter_lookup_by_uuid_args, .ret_filter = (xdrproc_t) xdr_remote_nwfilter_lookup_by_uuid_ret, }, -{ /* NWFilterGetXmlDesc => 177 */ - .fn = (dispatch_fn) remoteDispatchNWFilterGetXmlDesc, +{ /* NWFilterGetXMLDesc => 177 */ + .fn = (dispatch_fn) remoteDispatchNWFilterGetXMLDesc, .args_filter = (xdrproc_t) xdr_remote_nwfilter_get_xml_desc_args, .ret_filter = (xdrproc_t) xdr_remote_nwfilter_get_xml_desc_ret, }, -{ /* NumOfNwfilters => 178 */ - .fn = (dispatch_fn) remoteDispatchNumOfNwfilters, +{ /* NumOfNWFilters => 178 */ + .fn = (dispatch_fn) remoteDispatchNumOfNWFilters, .args_filter = (xdrproc_t) xdr_void, .ret_filter = (xdrproc_t) xdr_remote_num_of_nwfilters_ret, }, -{ /* ListNwfilters => 179 */ - .fn = (dispatch_fn) remoteDispatchListNwfilters, +{ /* ListNWFilters => 179 */ + .fn = (dispatch_fn) remoteDispatchListNWFilters, .args_filter = (xdrproc_t) xdr_remote_list_nwfilters_args, .ret_filter = (xdrproc_t) xdr_remote_list_nwfilters_ret, }, -{ /* NWFilterDefineXml => 180 */ - .fn = (dispatch_fn) remoteDispatchNWFilterDefineXml, +{ /* NWFilterDefineXML => 180 */ + .fn = (dispatch_fn) remoteDispatchNWFilterDefineXML, .args_filter = (xdrproc_t) xdr_remote_nwfilter_define_xml_args, .ret_filter = (xdrproc_t) xdr_remote_nwfilter_define_xml_ret, }, @@ -927,13 +927,13 @@ .args_filter = (xdrproc_t) xdr_remote_domain_managed_save_remove_args, .ret_filter = (xdrproc_t) xdr_void, }, -{ /* DomainSnapshotCreateXml => 185 */ - .fn = (dispatch_fn) remoteDispatchDomainSnapshotCreateXml, +{ /* DomainSnapshotCreateXML => 185 */ + .fn = (dispatch_fn) remoteDispatchDomainSnapshotCreateXML, .args_filter = (xdrproc_t) xdr_remote_domain_snapshot_create_xml_args, .ret_filter = (xdrproc_t) xdr_remote_domain_snapshot_create_xml_ret, }, -{ /* DomainSnapshotDumpXml => 186 */ - .fn = (dispatch_fn) remoteDispatchDomainSnapshotDumpXml, +{ /* DomainSnapshotDumpXML => 186 */ + .fn = (dispatch_fn) remoteDispatchDomainSnapshotDumpXML, .args_filter = (xdrproc_t) xdr_remote_domain_snapshot_dump_xml_args, .ret_filter = (xdrproc_t) xdr_remote_domain_snapshot_dump_xml_ret, }, diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 8ad6d0d..31af8b6 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -32,7 +32,8 @@ sub name_to_ProcName { my $name = shift; my @elems = split /_/, $name; @elems = map ucfirst, @elems; - @elems = map { $_ eq "Nwfilter" ? "NWFilter" : $_ } @elems; + @elems = map { $_ =~ s/Nwfilter/NWFilter/; $_ =~ s/Xml/XML/; + $_ =~ s/Uri/URI/; $_ =~ s/Uuid/UUID/; $_ } @elems; join "", @elems } -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:13:52 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:52 +0200 Subject: [libvirt] [PATCH 05/22] remote generator, daemon: Handle simple-return-value functions In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-6-git-send-email-matthias.bolte@googlemail.com> --- daemon/remote.c | 1616 ------------------------------------ daemon/remote_dispatch_bodies.c | 1724 +++++++++++++++++++++++++++++++++++++-- daemon/remote_generator.pl | 215 +++++- 3 files changed, 1880 insertions(+), 1675 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 5057cfc..a588a08 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -459,32 +459,6 @@ remoteDispatchClose(struct qemud_server *server ATTRIBUTE_UNUSED, } static int -remoteDispatchSupportsFeature(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_supports_feature_args *args, remote_supports_feature_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((ret->supported = virDrvSupportsFeature(conn, args->feature)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int remoteDispatchGetType(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -520,153 +494,6 @@ cleanup: } static int -remoteDispatchGetVersion(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_get_version_ret *ret) -{ - unsigned long hvVer; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (virConnectGetVersion(conn, &hvVer) < 0) - goto cleanup; - - ret->hv_ver = hvVer; - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int -remoteDispatchGetLibVersion(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_get_lib_version_ret *ret) -{ - unsigned long libVer; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (virConnectGetLibVersion(conn, &libVer) < 0) - goto cleanup; - - ret->lib_ver = libVer; - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int -remoteDispatchGetHostname(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_get_hostname_ret *ret) -{ - char *hostname; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(hostname = virConnectGetHostname(conn))) - goto cleanup; - - ret->hostname = hostname; - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int -remoteDispatchGetURI(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_get_uri_ret *ret) -{ - char *uri; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(uri = virConnectGetURI(conn))) - goto cleanup; - - ret->uri = uri; - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int -remoteDispatchGetSysinfo(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_get_sysinfo_args *args, - remote_get_sysinfo_ret *ret) -{ - unsigned int flags; - char *sysinfo; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - flags = args->flags; - if (!(sysinfo = virConnectGetSysinfo(conn, flags))) - goto cleanup; - - ret->sysinfo = sysinfo; - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int remoteDispatchGetMaxVcpus(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -733,35 +560,6 @@ cleanup: } static int -remoteDispatchGetCapabilities(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_get_capabilities_ret *ret) -{ - char *caps; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(caps = virConnectGetCapabilities(conn))) - goto cleanup; - - ret->capabilities = caps; - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int remoteDispatchNodeGetCellsFreeMemory(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -1384,136 +1182,6 @@ cleanup: } static int -remoteDispatchDomainDumpXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_dump_xml_args *args, - remote_domain_dump_xml_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - /* remoteDispatchClientRequest will free this. */ - if (!(ret->xml = virDomainGetXMLDesc(dom, args->flags))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainXMLFromNative(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_xml_from_native_args *args, - remote_domain_xml_from_native_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - /* remoteDispatchClientRequest will free this. */ - if (!(ret->domainXml = virConnectDomainXMLFromNative(conn, - args->nativeFormat, - args->nativeConfig, - args->flags))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int -remoteDispatchDomainXMLToNative(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_xml_to_native_args *args, - remote_domain_xml_to_native_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - /* remoteDispatchClientRequest will free this. */ - if (!(ret->nativeConfig = virConnectDomainXMLToNative(conn, - args->nativeFormat, - args->domainXml, - args->flags))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - - -static int -remoteDispatchDomainGetAutostart(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_get_autostart_args *args, - remote_domain_get_autostart_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainGetAutostart(dom, &ret->autostart) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -1554,72 +1222,6 @@ cleanup: } static int -remoteDispatchDomainGetMaxMemory(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_get_max_memory_args *args, - remote_domain_get_max_memory_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if ((ret->memory = virDomainGetMaxMemory(dom)) == 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainGetMaxVcpus(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_get_max_vcpus_args *args, - remote_domain_get_max_vcpus_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if ((ret->num = virDomainGetMaxVcpus(dom)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainGetSecurityLabel(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -1711,40 +1313,6 @@ cleanup: } static int -remoteDispatchDomainGetOsType(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_get_os_type_args *args, - remote_domain_get_os_type_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - /* remoteDispatchClientRequest will free this */ - if (!(ret->type = virDomainGetOSType(dom))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainGetVcpus(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -1828,39 +1396,6 @@ no_memory: } static int -remoteDispatchDomainGetVcpusFlags(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_get_vcpus_flags_args *args, - remote_domain_get_vcpus_flags_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if ((ret->num = virDomainGetVcpusFlags(dom, args->flags)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainMigratePrepare(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -2267,33 +1802,6 @@ cleanup: } static int -remoteDispatchNumOfDefinedDomains(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_num_of_defined_domains_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((ret->num = virConnectNumOfDefinedDomains(conn)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int remoteDispatchDomainPinVcpu(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -2856,39 +2364,6 @@ cleanup: } static int -remoteDispatchDomainHasManagedSaveImage(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_has_managed_save_image_args *args, - remote_domain_has_managed_save_image_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if ((ret->result = virDomainHasManagedSaveImage(dom, args->flags)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchListNetworks(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -2998,107 +2473,6 @@ cleanup: } static int -remoteDispatchNetworkDumpXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_dump_xml_args *args, - remote_network_dump_xml_ret *ret) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = get_nonnull_network(conn, args->net))) - goto cleanup; - - /* remoteDispatchClientRequest will free this. */ - if (!(ret->xml = virNetworkGetXMLDesc(net, args->flags))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - -static int -remoteDispatchNetworkGetAutostart(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_get_autostart_args *args, - remote_network_get_autostart_ret *ret) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = get_nonnull_network(conn, args->net))) - goto cleanup; - - if (virNetworkGetAutostart(net, &ret->autostart) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - -static int -remoteDispatchNetworkGetBridgeName(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_get_bridge_name_args *args, - remote_network_get_bridge_name_ret *ret) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = get_nonnull_network(conn, args->net))) - goto cleanup; - - /* remoteDispatchClientRequest will free this. */ - if (!(ret->name = virNetworkGetBridgeName(net))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - -static int remoteDispatchNetworkLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3162,118 +2536,7 @@ cleanup: return rv; } -static int -remoteDispatchNumOfDefinedNetworks(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_num_of_defined_networks_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - len = virConnectNumOfDefinedNetworks(conn); - if (len < 0) - goto cleanup; - ret->num = len; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int -remoteDispatchNumOfDomains(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_num_of_domains_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((ret->num = virConnectNumOfDomains(conn)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int -remoteDispatchNumOfNetworks(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_num_of_networks_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((ret->num = virConnectNumOfNetworks(conn)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - - /*-------------------------------------------------------------*/ -static int -remoteDispatchNumOfInterfaces(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_num_of_interfaces_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((ret->num = virConnectNumOfInterfaces(conn)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} static int remoteDispatchListInterfaces(struct qemud_server *server ATTRIBUTE_UNUSED, @@ -3321,36 +2584,6 @@ cleanup: } static int -remoteDispatchNumOfDefinedInterfaces(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_num_of_defined_interfaces_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - len = virConnectNumOfDefinedInterfaces(conn); - if (len < 0) - goto cleanup; - ret->num = len; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int remoteDispatchListDefinedInterfaces(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3460,40 +2693,6 @@ cleanup: } static int -remoteDispatchInterfaceGetXMLDesc(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_interface_get_xml_desc_args *args, - remote_interface_get_xml_desc_ret *ret) -{ - virInterfacePtr iface = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(iface = get_nonnull_interface(conn, args->iface))) - goto cleanup; - - /* remoteDispatchClientRequest will free this. */ - if (!(ret->xml = virInterfaceGetXMLDesc(iface, args->flags))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (iface) - virInterfaceFree(iface); - return rv; -} - -static int remoteDispatchInterfaceDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -4555,74 +3754,6 @@ cleanup: } static int -remoteDispatchStoragePoolDumpXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_dump_xml_args *args, - remote_storage_pool_dump_xml_ret *ret) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - /* remoteDispatchClientRequest will free this. */ - if (!(ret->xml = virStoragePoolGetXMLDesc(pool, args->flags))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -static int -remoteDispatchStoragePoolGetAutostart(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_get_autostart_args *args, - remote_storage_pool_get_autostart_ret *ret) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if (virStoragePoolGetAutostart(pool, &ret->autostart) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - - -static int remoteDispatchStoragePoolLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -4725,60 +3856,6 @@ cleanup: } static int -remoteDispatchNumOfStoragePools(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_num_of_storage_pools_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((ret->num = virConnectNumOfStoragePools(conn)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int -remoteDispatchNumOfDefinedStoragePools(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_num_of_defined_storage_pools_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((ret->num = virConnectNumOfDefinedStoragePools(conn)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int remoteDispatchStoragePoolListVolumes(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -4830,40 +3907,6 @@ cleanup: } -static int -remoteDispatchStoragePoolNumOfVolumes(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_num_of_volumes_args *args, - remote_storage_pool_num_of_volumes_ret *ret) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if ((ret->num = virStoragePoolNumOfVolumes(pool)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - - /*************************************************************** * STORAGE VOL APIS ***************************************************************/ @@ -4990,76 +4033,6 @@ cleanup: } static int -remoteDispatchStorageVolDumpXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_vol_dump_xml_args *args, - remote_storage_vol_dump_xml_ret *ret) -{ - virStorageVolPtr vol = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(vol = get_nonnull_storage_vol(conn, args->vol))) - goto cleanup; - - /* remoteDispatchClientRequest will free this. */ - if (!(ret->xml = virStorageVolGetXMLDesc(vol, args->flags))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (vol) - virStorageVolFree(vol); - return rv; -} - - -static int -remoteDispatchStorageVolGetPath(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_vol_get_path_args *args, - remote_storage_vol_get_path_ret *ret) -{ - virStorageVolPtr vol = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(vol = get_nonnull_storage_vol(conn, args->vol))) - goto cleanup; - - /* remoteDispatchClientRequest will free this. */ - if (!(ret->name = virStorageVolGetPath(vol))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (vol) - virStorageVolFree(vol); - return rv; -} - - -static int remoteDispatchStorageVolLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -5276,42 +4249,6 @@ cleanup: return rv; } - -static int -remoteDispatchNodeDeviceDumpXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_node_device_dump_xml_args *args, - remote_node_device_dump_xml_ret *ret) -{ - virNodeDevicePtr dev = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dev = virNodeDeviceLookupByName(conn, args->name))) - goto cleanup; - - /* remoteDispatchClientRequest will free this. */ - if (!(ret->xml = virNodeDeviceGetXMLDesc(dev, args->flags))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dev) - virNodeDeviceFree(dev); - return rv; -} - - static int remoteDispatchNodeDeviceGetParent(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, @@ -5362,41 +4299,6 @@ cleanup: return rv; } - -static int -remoteDispatchNodeDeviceNumOfCaps(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_node_device_num_of_caps_args *args, - remote_node_device_num_of_caps_ret *ret) -{ - virNodeDevicePtr dev = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dev = virNodeDeviceLookupByName(conn, args->name))) - goto cleanup; - - if ((ret->num = virNodeDeviceNumOfCaps(dev)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dev) - virNodeDeviceFree(dev); - return rv; -} - - static int remoteDispatchNodeDeviceListCaps(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, @@ -5712,33 +4614,6 @@ cleanup: } static int -remoteDispatchNumOfSecrets(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_num_of_secrets_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((ret->num = virConnectNumOfSecrets(conn)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int remoteDispatchListSecrets(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -5852,38 +4727,6 @@ cleanup: } static int -remoteDispatchSecretGetXMLDesc(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_secret_get_xml_desc_args *args, - remote_secret_get_xml_desc_ret *ret) -{ - virSecretPtr secret = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(secret = get_nonnull_secret(conn, args->secret))) - goto cleanup; - if (!(ret->xml = virSecretGetXMLDesc(secret, args->flags))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (secret) - virSecretFree(secret); - return rv; -} - -static int remoteDispatchSecretLookupByUUID(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -5947,291 +4790,6 @@ cleanup: return rv; } - -static int remoteDispatchDomainIsActive(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_is_active_args *args, - remote_domain_is_active_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if ((ret->active = virDomainIsActive(dom)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainIsPersistent(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_is_persistent_args *args, - remote_domain_is_persistent_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if ((ret->persistent = virDomainIsPersistent(dom)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainIsUpdated(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_is_updated_args *args, - remote_domain_is_updated_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if ((ret->updated = virDomainIsUpdated(dom)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchInterfaceIsActive(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_interface_is_active_args *args, - remote_interface_is_active_ret *ret) -{ - virInterfacePtr iface = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(iface = get_nonnull_interface(conn, args->iface))) - goto cleanup; - - if ((ret->active = virInterfaceIsActive(iface)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (iface) - virInterfaceFree(iface); - return rv; -} - -static int remoteDispatchNetworkIsActive(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_is_active_args *args, - remote_network_is_active_ret *ret) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = get_nonnull_network(conn, args->net))) - goto cleanup; - - if ((ret->active = virNetworkIsActive(net)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - -static int remoteDispatchNetworkIsPersistent(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_is_persistent_args *args, - remote_network_is_persistent_ret *ret) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = get_nonnull_network(conn, args->net))) - goto cleanup; - - if ((ret->persistent = virNetworkIsPersistent(net)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - -static int remoteDispatchStoragePoolIsActive(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_is_active_args *args, - remote_storage_pool_is_active_ret *ret) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if ((ret->active = virStoragePoolIsActive(pool)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -static int remoteDispatchStoragePoolIsPersistent(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_is_persistent_args *args, - remote_storage_pool_is_persistent_ret *ret) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if ((ret->persistent = virStoragePoolIsPersistent(pool)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - - -static int remoteDispatchIsSecure(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_is_secure_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((ret->secure = virConnectIsSecure(conn)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - - static int remoteDispatchCpuCompare(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, @@ -6382,79 +4940,6 @@ cleanup: } static int -remoteDispatchDomainSnapshotDumpXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_snapshot_dump_xml_args *args, - remote_domain_snapshot_dump_xml_ret *ret) -{ - virDomainPtr dom = NULL; - virDomainSnapshotPtr snapshot = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->snap.dom))) - goto cleanup; - - if (!(snapshot = get_nonnull_domain_snapshot(dom, args->snap))) - goto cleanup; - - /* remoteDispatchClientRequest will free this. */ - if (!(ret->xml = virDomainSnapshotGetXMLDesc(snapshot, args->flags))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (snapshot) - virDomainSnapshotFree(snapshot); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainSnapshotNum(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_snapshot_num_args *args, - remote_domain_snapshot_num_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if ((ret->num = virDomainSnapshotNum(dom, args->flags)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainSnapshotListNames(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -6546,43 +5031,6 @@ cleanup: } static int -remoteDispatchDomainHasCurrentSnapshot(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_has_current_snapshot_args *args, - remote_domain_has_current_snapshot_ret *ret) -{ - virDomainPtr dom = NULL; - int result; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - result = virDomainHasCurrentSnapshot(dom, args->flags); - if (result < 0) - goto cleanup; - - ret->result = result; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainSnapshotCurrent(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -6850,70 +5298,6 @@ cleanup: return rv; } - -static int -remoteDispatchNWFilterGetXMLDesc(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_nwfilter_get_xml_desc_args *args, - remote_nwfilter_get_xml_desc_ret *ret) -{ - virNWFilterPtr nwfilter = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(nwfilter = get_nonnull_nwfilter(conn, args->nwfilter))) - goto cleanup; - - /* remoteDispatchClientRequest will free this. */ - if (!(ret->xml = virNWFilterGetXMLDesc(nwfilter, args->flags))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (nwfilter) - virNWFilterFree(nwfilter); - return rv; -} - - -static int -remoteDispatchNumOfNWFilters(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_num_of_nwfilters_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((ret->num = virConnectNumOfNWFilters(conn)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - - static int remoteDispatchDomainGetBlockInfo(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, diff --git a/daemon/remote_dispatch_bodies.c b/daemon/remote_dispatch_bodies.c index 6b4abec..c1959b6 100644 --- a/daemon/remote_dispatch_bodies.c +++ b/daemon/remote_dispatch_bodies.c @@ -300,7 +300,41 @@ cleanup: return rv; } -/* remoteDispatchDomainDumpXML has to be implemented manually */ +static int +remoteDispatchDomainDumpXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_dump_xml_args *args, + remote_domain_dump_xml_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + char *xml; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((xml = virDomainGetXMLDesc(dom, args->flags)) == NULL) + goto cleanup; + + ret->xml = xml; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} /* remoteDispatchDomainEventsDeregister has to be implemented manually */ @@ -310,7 +344,41 @@ cleanup: /* remoteDispatchDomainEventsRegisterAny has to be implemented manually */ -/* remoteDispatchDomainGetAutostart has to be implemented manually */ +static int +remoteDispatchDomainGetAutostart( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_get_autostart_args *args, + remote_domain_get_autostart_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + int autostart; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainGetAutostart(dom, &autostart) < 0) + goto cleanup; + + ret->autostart = autostart; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} /* remoteDispatchDomainGetBlkioParameters has to be implemented manually */ @@ -320,13 +388,115 @@ cleanup: /* remoteDispatchDomainGetJobInfo has to be implemented manually */ -/* remoteDispatchDomainGetMaxMemory has to be implemented manually */ +static int +remoteDispatchDomainGetMaxMemory( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_get_max_memory_args *args, + remote_domain_get_max_memory_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + unsigned long memory; -/* remoteDispatchDomainGetMaxVcpus has to be implemented manually */ + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((memory = virDomainGetMaxMemory(dom)) == 0) + goto cleanup; + + ret->memory = memory; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainGetMaxVcpus( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_get_max_vcpus_args *args, + remote_domain_get_max_vcpus_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((num = virDomainGetMaxVcpus(dom)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} /* remoteDispatchDomainGetMemoryParameters has to be implemented manually */ -/* remoteDispatchDomainGetOsType has to be implemented manually */ +static int +remoteDispatchDomainGetOsType( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_get_os_type_args *args, + remote_domain_get_os_type_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + char *type; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((type = virDomainGetOSType(dom)) == NULL) + goto cleanup; + + ret->type = type; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} /* remoteDispatchDomainGetSchedulerParameters has to be implemented manually */ @@ -336,19 +506,223 @@ cleanup: /* remoteDispatchDomainGetVcpus has to be implemented manually */ -/* remoteDispatchDomainGetVcpusFlags has to be implemented manually */ +static int +remoteDispatchDomainGetVcpusFlags( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_get_vcpus_flags_args *args, + remote_domain_get_vcpus_flags_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((num = virDomainGetVcpusFlags(dom, args->flags)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainHasCurrentSnapshot( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_has_current_snapshot_args *args, + remote_domain_has_current_snapshot_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + int result; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((result = virDomainHasCurrentSnapshot(dom, args->flags)) < 0) + goto cleanup; + + ret->result = result; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainHasManagedSaveImage( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_has_managed_save_image_args *args, + remote_domain_has_managed_save_image_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + int result; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } -/* remoteDispatchDomainHasCurrentSnapshot has to be implemented manually */ + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((result = virDomainHasManagedSaveImage(dom, args->flags)) < 0) + goto cleanup; + + ret->result = result; + rv = 0; -/* remoteDispatchDomainHasManagedSaveImage has to be implemented manually */ +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} /* remoteDispatchDomainInterfaceStats has to be implemented manually */ -/* remoteDispatchDomainIsActive has to be implemented manually */ +static int +remoteDispatchDomainIsActive( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_is_active_args *args, + remote_domain_is_active_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + int active; -/* remoteDispatchDomainIsPersistent has to be implemented manually */ + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } -/* remoteDispatchDomainIsUpdated has to be implemented manually */ + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((active = virDomainIsActive(dom)) < 0) + goto cleanup; + + ret->active = active; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainIsPersistent( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_is_persistent_args *args, + remote_domain_is_persistent_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + int persistent; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((persistent = virDomainIsPersistent(dom)) < 0) + goto cleanup; + + ret->persistent = persistent; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainIsUpdated( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_is_updated_args *args, + remote_domain_is_updated_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + int updated; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((updated = virDomainIsUpdated(dom)) < 0) + goto cleanup; + + ret->updated = updated; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} /* remoteDispatchDomainLookupById has to be implemented manually */ @@ -563,7 +937,6 @@ remoteDispatchDomainRestore( goto cleanup; } - if (virDomainRestore(conn, args->from) < 0) goto cleanup; @@ -572,7 +945,6 @@ remoteDispatchDomainRestore( cleanup: if (rv < 0) remoteDispatchError(rerr); - return rv; } @@ -972,13 +1344,87 @@ cleanup: return rv; } -/* remoteDispatchDomainSnapshotDumpXML has to be implemented manually */ +static int +remoteDispatchDomainSnapshotDumpXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_snapshot_dump_xml_args *args, + remote_domain_snapshot_dump_xml_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + virDomainSnapshotPtr snapshot = NULL; + char *xml; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->snap.dom))) + goto cleanup; + + if (!(snapshot = get_nonnull_domain_snapshot(dom, args->snap))) + goto cleanup; + + if ((xml = virDomainSnapshotGetXMLDesc(snapshot, args->flags)) == NULL) + goto cleanup; + + ret->xml = xml; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (snapshot) + virDomainSnapshotFree(snapshot); + if (dom) + virDomainFree(dom); + return rv; +} /* remoteDispatchDomainSnapshotListNames has to be implemented manually */ /* remoteDispatchDomainSnapshotLookupByName has to be implemented manually */ -/* remoteDispatchDomainSnapshotNum has to be implemented manually */ +static int +remoteDispatchDomainSnapshotNum( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_snapshot_num_args *args, + remote_domain_snapshot_num_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((num = virDomainSnapshotNum(dom, args->flags)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} static int remoteDispatchDomainSuspend( @@ -1082,27 +1528,251 @@ cleanup: return rv; } -/* remoteDispatchDomainXMLFromNative has to be implemented manually */ +static int +remoteDispatchDomainXMLFromNative( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_xml_from_native_args *args, + remote_domain_xml_from_native_ret *ret) +{ + int rv = -1; + char *domainXml; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((domainXml = virConnectDomainXMLFromNative(conn, args->nativeFormat, args->nativeConfig, args->flags)) == NULL) + goto cleanup; + + ret->domainXml = domainXml; + rv = 0; -/* remoteDispatchDomainXMLToNative has to be implemented manually */ +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchDomainXMLToNative( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_xml_to_native_args *args, + remote_domain_xml_to_native_ret *ret) +{ + int rv = -1; + char *nativeConfig; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((nativeConfig = virConnectDomainXMLToNative(conn, args->nativeFormat, args->domainXml, args->flags)) == NULL) + goto cleanup; + + ret->nativeConfig = nativeConfig; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} /* remoteDispatchFindStoragePoolSources has to be implemented manually */ -/* remoteDispatchGetCapabilities has to be implemented manually */ +static int +remoteDispatchGetCapabilities( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_get_capabilities_ret *ret) +{ + int rv = -1; + char *capabilities; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } -/* remoteDispatchGetHostname has to be implemented manually */ + if ((capabilities = virConnectGetCapabilities(conn)) == NULL) + goto cleanup; -/* remoteDispatchGetLibVersion has to be implemented manually */ + ret->capabilities = capabilities; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchGetHostname( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_get_hostname_ret *ret) +{ + int rv = -1; + char *hostname; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((hostname = virConnectGetHostname(conn)) == NULL) + goto cleanup; + + ret->hostname = hostname; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchGetLibVersion( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_get_lib_version_ret *ret) +{ + int rv = -1; + unsigned long lib_ver; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (virConnectGetLibVersion(conn, &lib_ver) < 0) + goto cleanup; + + ret->lib_ver = lib_ver; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} /* remoteDispatchGetMaxVcpus has to be implemented manually */ -/* remoteDispatchGetSysinfo has to be implemented manually */ +static int +remoteDispatchGetSysinfo( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_get_sysinfo_args *args, + remote_get_sysinfo_ret *ret) +{ + int rv = -1; + char *sysinfo; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((sysinfo = virConnectGetSysinfo(conn, args->flags)) == NULL) + goto cleanup; + + ret->sysinfo = sysinfo; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} /* remoteDispatchGetType has to be implemented manually */ -/* remoteDispatchGetURI has to be implemented manually */ +static int +remoteDispatchGetURI( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_get_uri_ret *ret) +{ + int rv = -1; + char *uri; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((uri = virConnectGetURI(conn)) == NULL) + goto cleanup; + + ret->uri = uri; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchGetVersion( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_get_version_ret *ret) +{ + int rv = -1; + unsigned long hv_ver; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (virConnectGetVersion(conn, &hv_ver) < 0) + goto cleanup; -/* remoteDispatchGetVersion has to be implemented manually */ + ret->hv_ver = hv_ver; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} static int remoteDispatchInterfaceCreate( @@ -1174,9 +1844,77 @@ cleanup: return rv; } -/* remoteDispatchInterfaceGetXMLDesc has to be implemented manually */ +static int +remoteDispatchInterfaceGetXMLDesc( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_interface_get_xml_desc_args *args, + remote_interface_get_xml_desc_ret *ret) +{ + int rv = -1; + virInterfacePtr iface = NULL; + char *xml; -/* remoteDispatchInterfaceIsActive has to be implemented manually */ + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(iface = get_nonnull_interface(conn, args->iface))) + goto cleanup; + + if ((xml = virInterfaceGetXMLDesc(iface, args->flags)) == NULL) + goto cleanup; + + ret->xml = xml; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (iface) + virInterfaceFree(iface); + return rv; +} + +static int +remoteDispatchInterfaceIsActive( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_interface_is_active_args *args, + remote_interface_is_active_ret *ret) +{ + int rv = -1; + virInterfacePtr iface = NULL; + int active; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(iface = get_nonnull_interface(conn, args->iface))) + goto cleanup; + + if ((active = virInterfaceIsActive(iface)) < 0) + goto cleanup; + + ret->active = active; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (iface) + virInterfaceFree(iface); + return rv; +} /* remoteDispatchInterfaceLookupByMacString has to be implemented manually */ @@ -1216,7 +1954,35 @@ cleanup: return rv; } -/* remoteDispatchIsSecure has to be implemented manually */ +static int +remoteDispatchIsSecure( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_is_secure_ret *ret) +{ + int rv = -1; + int secure; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((secure = virConnectIsSecure(conn)) < 0) + goto cleanup; + + ret->secure = secure; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} /* remoteDispatchListDefinedDomains has to be implemented manually */ @@ -1310,15 +2076,185 @@ cleanup: return rv; } -/* remoteDispatchNetworkDumpXML has to be implemented manually */ +static int +remoteDispatchNetworkDumpXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_dump_xml_args *args, + remote_network_dump_xml_ret *ret) +{ + int rv = -1; + virNetworkPtr net = NULL; + char *xml; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } -/* remoteDispatchNetworkGetAutostart has to be implemented manually */ + if (!(net = get_nonnull_network(conn, args->net))) + goto cleanup; -/* remoteDispatchNetworkGetBridgeName has to be implemented manually */ + if ((xml = virNetworkGetXMLDesc(net, args->flags)) == NULL) + goto cleanup; -/* remoteDispatchNetworkIsActive has to be implemented manually */ + ret->xml = xml; + rv = 0; -/* remoteDispatchNetworkIsPersistent has to be implemented manually */ +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} + +static int +remoteDispatchNetworkGetAutostart( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_get_autostart_args *args, + remote_network_get_autostart_ret *ret) +{ + int rv = -1; + virNetworkPtr net = NULL; + int autostart; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(net = get_nonnull_network(conn, args->net))) + goto cleanup; + + if (virNetworkGetAutostart(net, &autostart) < 0) + goto cleanup; + + ret->autostart = autostart; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} + +static int +remoteDispatchNetworkGetBridgeName( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_get_bridge_name_args *args, + remote_network_get_bridge_name_ret *ret) +{ + int rv = -1; + virNetworkPtr net = NULL; + char *name; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(net = get_nonnull_network(conn, args->net))) + goto cleanup; + + if ((name = virNetworkGetBridgeName(net)) == NULL) + goto cleanup; + + ret->name = name; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} + +static int +remoteDispatchNetworkIsActive( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_is_active_args *args, + remote_network_is_active_ret *ret) +{ + int rv = -1; + virNetworkPtr net = NULL; + int active; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(net = get_nonnull_network(conn, args->net))) + goto cleanup; + + if ((active = virNetworkIsActive(net)) < 0) + goto cleanup; + + ret->active = active; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} + +static int +remoteDispatchNetworkIsPersistent( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_is_persistent_args *args, + remote_network_is_persistent_ret *ret) +{ + int rv = -1; + virNetworkPtr net = NULL; + int persistent; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(net = get_nonnull_network(conn, args->net))) + goto cleanup; + + if ((persistent = virNetworkIsPersistent(net)) < 0) + goto cleanup; + + ret->persistent = persistent; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} /* remoteDispatchNetworkLookupByName has to be implemented manually */ @@ -1462,7 +2398,41 @@ cleanup: return rv; } -/* remoteDispatchNodeDeviceDumpXML has to be implemented manually */ +static int +remoteDispatchNodeDeviceDumpXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_device_dump_xml_args *args, + remote_node_device_dump_xml_ret *ret) +{ + int rv = -1; + virNodeDevicePtr dev = NULL; + char *xml; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dev = virNodeDeviceLookupByName(conn, args->name))) + goto cleanup; + + if ((xml = virNodeDeviceGetXMLDesc(dev, args->flags)) == NULL) + goto cleanup; + + ret->xml = xml; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dev) + virNodeDeviceFree(dev); + return rv; +} /* remoteDispatchNodeDeviceGetParent has to be implemented manually */ @@ -1470,7 +2440,41 @@ cleanup: /* remoteDispatchNodeDeviceLookupByName has to be implemented manually */ -/* remoteDispatchNodeDeviceNumOfCaps has to be implemented manually */ +static int +remoteDispatchNodeDeviceNumOfCaps( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_device_num_of_caps_args *args, + remote_node_device_num_of_caps_ret *ret) +{ + int rv = -1; + virNodeDevicePtr dev = NULL; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dev = virNodeDeviceLookupByName(conn, args->name))) + goto cleanup; + + if ((num = virNodeDeviceNumOfCaps(dev)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dev) + virNodeDeviceFree(dev); + return rv; +} static int remoteDispatchNodeDeviceReAttach( @@ -1552,29 +2556,343 @@ cleanup: /* remoteDispatchNodeNumOfDevices has to be implemented manually */ -/* remoteDispatchNumOfDefinedDomains has to be implemented manually */ +static int +remoteDispatchNumOfDefinedDomains( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_num_of_defined_domains_ret *ret) +{ + int rv = -1; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((num = virConnectNumOfDefinedDomains(conn)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchNumOfDefinedInterfaces( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_num_of_defined_interfaces_ret *ret) +{ + int rv = -1; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((num = virConnectNumOfDefinedInterfaces(conn)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchNumOfDefinedNetworks( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_num_of_defined_networks_ret *ret) +{ + int rv = -1; + int num; -/* remoteDispatchNumOfDefinedInterfaces has to be implemented manually */ + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } -/* remoteDispatchNumOfDefinedNetworks has to be implemented manually */ + if ((num = virConnectNumOfDefinedNetworks(conn)) < 0) + goto cleanup; -/* remoteDispatchNumOfDefinedStoragePools has to be implemented manually */ + ret->num = num; + rv = 0; -/* remoteDispatchNumOfDomains has to be implemented manually */ +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} -/* remoteDispatchNumOfInterfaces has to be implemented manually */ +static int +remoteDispatchNumOfDefinedStoragePools( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_num_of_defined_storage_pools_ret *ret) +{ + int rv = -1; + int num; -/* remoteDispatchNumOfNetworks has to be implemented manually */ + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } -/* remoteDispatchNumOfNWFilters has to be implemented manually */ + if ((num = virConnectNumOfDefinedStoragePools(conn)) < 0) + goto cleanup; -/* remoteDispatchNumOfSecrets has to be implemented manually */ + ret->num = num; + rv = 0; -/* remoteDispatchNumOfStoragePools has to be implemented manually */ +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchNumOfDomains( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_num_of_domains_ret *ret) +{ + int rv = -1; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((num = virConnectNumOfDomains(conn)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchNumOfInterfaces( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_num_of_interfaces_ret *ret) +{ + int rv = -1; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((num = virConnectNumOfInterfaces(conn)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchNumOfNetworks( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_num_of_networks_ret *ret) +{ + int rv = -1; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((num = virConnectNumOfNetworks(conn)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchNumOfNWFilters( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_num_of_nwfilters_ret *ret) +{ + int rv = -1; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((num = virConnectNumOfNWFilters(conn)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchNumOfSecrets( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_num_of_secrets_ret *ret) +{ + int rv = -1; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((num = virConnectNumOfSecrets(conn)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchNumOfStoragePools( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_num_of_storage_pools_ret *ret) +{ + int rv = -1; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((num = virConnectNumOfStoragePools(conn)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} /* remoteDispatchNWFilterDefineXML has to be implemented manually */ -/* remoteDispatchNWFilterGetXMLDesc has to be implemented manually */ +static int +remoteDispatchNWFilterGetXMLDesc( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_nwfilter_get_xml_desc_args *args, + remote_nwfilter_get_xml_desc_ret *ret) +{ + int rv = -1; + virNWFilterPtr nwfilter = NULL; + char *xml; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(nwfilter = get_nonnull_nwfilter(conn, args->nwfilter))) + goto cleanup; + + if ((xml = virNWFilterGetXMLDesc(nwfilter, args->flags)) == NULL) + goto cleanup; + + ret->xml = xml; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (nwfilter) + virNWFilterFree(nwfilter); + return rv; +} /* remoteDispatchNWFilterLookupByName has to be implemented manually */ @@ -1620,7 +2938,41 @@ cleanup: /* remoteDispatchSecretGetValue has to be implemented manually */ -/* remoteDispatchSecretGetXMLDesc has to be implemented manually */ +static int +remoteDispatchSecretGetXMLDesc( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_secret_get_xml_desc_args *args, + remote_secret_get_xml_desc_ret *ret) +{ + int rv = -1; + virSecretPtr secret = NULL; + char *xml; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(secret = get_nonnull_secret(conn, args->secret))) + goto cleanup; + + if ((xml = virSecretGetXMLDesc(secret, args->flags)) == NULL) + goto cleanup; + + ret->xml = xml; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (secret) + virSecretFree(secret); + return rv; +} /* remoteDispatchSecretLookupByUsage has to be implemented manually */ @@ -1834,15 +3186,151 @@ cleanup: return rv; } -/* remoteDispatchStoragePoolDumpXML has to be implemented manually */ +static int +remoteDispatchStoragePoolDumpXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_dump_xml_args *args, + remote_storage_pool_dump_xml_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + char *xml; -/* remoteDispatchStoragePoolGetAutostart has to be implemented manually */ + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if ((xml = virStoragePoolGetXMLDesc(pool, args->flags)) == NULL) + goto cleanup; + + ret->xml = xml; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} + +static int +remoteDispatchStoragePoolGetAutostart( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_get_autostart_args *args, + remote_storage_pool_get_autostart_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + int autostart; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if (virStoragePoolGetAutostart(pool, &autostart) < 0) + goto cleanup; + + ret->autostart = autostart; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} /* remoteDispatchStoragePoolGetInfo has to be implemented manually */ -/* remoteDispatchStoragePoolIsActive has to be implemented manually */ +static int +remoteDispatchStoragePoolIsActive( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_is_active_args *args, + remote_storage_pool_is_active_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + int active; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } -/* remoteDispatchStoragePoolIsPersistent has to be implemented manually */ + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if ((active = virStoragePoolIsActive(pool)) < 0) + goto cleanup; + + ret->active = active; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} + +static int +remoteDispatchStoragePoolIsPersistent( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_is_persistent_args *args, + remote_storage_pool_is_persistent_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + int persistent; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if ((persistent = virStoragePoolIsPersistent(pool)) < 0) + goto cleanup; + + ret->persistent = persistent; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} /* remoteDispatchStoragePoolListVolumes has to be implemented manually */ @@ -1852,7 +3340,41 @@ cleanup: /* remoteDispatchStoragePoolLookupByVolume has to be implemented manually */ -/* remoteDispatchStoragePoolNumOfVolumes has to be implemented manually */ +static int +remoteDispatchStoragePoolNumOfVolumes( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_num_of_volumes_args *args, + remote_storage_pool_num_of_volumes_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if ((num = virStoragePoolNumOfVolumes(pool)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} static int remoteDispatchStoragePoolRefresh( @@ -1996,11 +3518,79 @@ cleanup: /* remoteDispatchStorageVolDownload has to be implemented manually */ -/* remoteDispatchStorageVolDumpXML has to be implemented manually */ +static int +remoteDispatchStorageVolDumpXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_vol_dump_xml_args *args, + remote_storage_vol_dump_xml_ret *ret) +{ + int rv = -1; + virStorageVolPtr vol = NULL; + char *xml; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(vol = get_nonnull_storage_vol(conn, args->vol))) + goto cleanup; + + if ((xml = virStorageVolGetXMLDesc(vol, args->flags)) == NULL) + goto cleanup; + + ret->xml = xml; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (vol) + virStorageVolFree(vol); + return rv; +} /* remoteDispatchStorageVolGetInfo has to be implemented manually */ -/* remoteDispatchStorageVolGetPath has to be implemented manually */ +static int +remoteDispatchStorageVolGetPath( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_vol_get_path_args *args, + remote_storage_vol_get_path_ret *ret) +{ + int rv = -1; + virStorageVolPtr vol = NULL; + char *name; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(vol = get_nonnull_storage_vol(conn, args->vol))) + goto cleanup; + + if ((name = virStorageVolGetPath(vol)) == NULL) + goto cleanup; + + ret->name = name; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (vol) + virStorageVolFree(vol); + return rv; +} /* remoteDispatchStorageVolLookupByKey has to be implemented manually */ @@ -2044,5 +3634,33 @@ cleanup: return rv; } -/* remoteDispatchSupportsFeature has to be implemented manually */ +static int +remoteDispatchSupportsFeature( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_supports_feature_args *args, + remote_supports_feature_ret *ret) +{ + int rv = -1; + int supported; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((supported = virDrvSupportsFeature(conn, args->feature)) < 0) + goto cleanup; + + ret->supported = supported; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 31af8b6..0901649 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -54,6 +54,7 @@ if ($opt_c) { } my $collect_args_members = 0; +my $collect_ret_members = 0; my $last_name; while (<>) { @@ -63,6 +64,12 @@ while (<>) { } elsif ($_ =~ m/^\s*(.*\S)\s*$/) { push(@{$calls{$name}->{args_members}}, $1); } + } elsif ($collect_ret_members) { + if (/^};/) { + $collect_ret_members = 0; + } elsif ($_ =~ m/^\s*(.*\S)\s*$/) { + push(@{$calls{$name}->{ret_members}}, $1); + } } elsif (/^struct ${structprefix}_(.*)_args/) { $name = $1; $ProcName = name_to_ProcName ($name); @@ -80,6 +87,7 @@ while (<>) { }; $collect_args_members = 1; + $collect_ret_members = 0; $last_name = $name; } elsif (/^struct ${structprefix}_(.*)_ret/) { $name = $1; @@ -93,11 +101,14 @@ while (<>) { ProcName => $ProcName, UC_NAME => uc $name, args => "void", - ret => "${structprefix}_${name}_ret" + ret => "${structprefix}_${name}_ret", + ret_members => [] } } $collect_args_members = 0; + $collect_ret_members = 1; + $last_name = $name; } elsif (/^struct ${structprefix}_(.*)_msg/) { $name = $1; $ProcName = name_to_ProcName ($name); @@ -110,6 +121,7 @@ while (<>) { }; $collect_args_members = 0; + $collect_ret_members = 0; } elsif (/^\s*${procprefix}_PROC_(.*?)\s+=\s+(\d+),?$/) { $name = lc $1; $id = $2; @@ -118,8 +130,10 @@ while (<>) { $calls[$id] = $calls{$name}; $collect_args_members = 0; + $collect_ret_members = 0; } else { $collect_args_members = 0; + $collect_ret_members = 0; } } @@ -235,7 +249,96 @@ elsif ($opt_b) { "DomainSetBlkioParameters", "Open", "StorageVolUpload", - "StorageVolDownload"); + "StorageVolDownload", + + "AuthList", + "AuthSaslInit", + "AuthSaslStart", + "AuthSaslStep", + "AuthPolkit", + + "CpuBaseline", + "CpuCompare", + "DomainBlockPeek", + "DomainBlockStats", + "DomainCreateWithFlags", + "DomainCreateXML", + "DomainDefineXML", + "DomainEventsDeregister", + "DomainEventsRegister", + "DomainGetBlkioParameters", + "DomainGetBlockInfo", + "DomainGetInfo", + "DomainGetJobInfo", + "DomainGetMemoryParameters", + "DomainGetSchedulerParameters", + "DomainGetSchedulerType", + "DomainGetSecurityLabel", + "DomainGetVcpus", + "DomainInterfaceStats", + "DomainLookupById", + "DomainLookupByName", + "DomainLookupByUUID", + "DomainMemoryPeek", + "DomainMemoryStats", + "DomainMigrateFinish", + "DomainMigrateFinish2", + "DomainMigratePrepare", + "DomainMigratePrepare2", + "DomainSnapshotCreateXML", + "DomainSnapshotCurrent", + "DomainSnapshotListNames", + "DomainSnapshotLookupByName", + "FindStoragePoolSources", + "GetMaxVcpus", + "GetType", + "InterfaceLookupByMacString", + "InterfaceLookupByName", + "InterfaceDefineXML", + "ListDefinedDomains", + "ListDefinedInterfaces", + "ListDefinedNetworks", + "ListDefinedStoragePools", + "ListDomains", + "ListInterfaces", + "ListNetworks", + "ListNWFilters", + "ListSecrets", + "ListStoragePools", + "NetworkLookupByName", + "NetworkLookupByUUID", + "NodeDeviceCreateXML", + "NetworkCreateXML", + "NodeDeviceGetParent", + "NodeDeviceListCaps", + "NodeDeviceLookupByName", + "NodeGetCellsFreeMemory", + "NodeGetFreeMemory", + "NodeGetInfo", + "NodeGetSecurityModel", + "NetworkDefineXML", + "NodeListDevices", + "NodeNumOfDevices", + "NWFilterLookupByName", + "NWFilterLookupByUUID", + "SecretDefineXML", + "SecretGetValue", + "NWFilterDefineXML", + "SecretLookupByUsage", + "SecretLookupByUUID", + "StoragePoolCreateXML", + "StoragePoolDefineXML", + "StoragePoolGetInfo", + "StoragePoolListVolumes", + "StoragePoolLookupByName", + "StoragePoolLookupByUUID", + "StoragePoolLookupByVolume", + "StorageVolCreateXML", + "StorageVolCreateXMLFrom", + "StorageVolGetInfo", + "StorageVolLookupByKey", + "StorageVolLookupByName", + "StorageVolLookupByPath"); } elsif ($structprefix eq "qemu") { @ungeneratable = ("MonitorCommand"); } @@ -248,8 +351,9 @@ elsif ($opt_b) { next if $calls{$_}->{msg}; # FIXME: skip functions with explicit return value for now - if ($calls{$_}->{ret} ne "void" or exists($ug{$calls{$_}->{ProcName}})) { - print "/* ${structprefix}Dispatch$calls{$_}->{ProcName} has to be implemented manually */\n\n"; + if (exists($ug{$calls{$_}->{ProcName}})) { + print "/* ${structprefix}Dispatch$calls{$_}->{ProcName} has to " . + "be implemented manually */\n\n"; next; } @@ -281,6 +385,7 @@ elsif ($opt_b) { my @vars_list = (); my @getters_list = (); my @args_list = (); + my @ret_list = (); my @free_list = (); if ($calls{$_}->{args} ne "void") { @@ -401,6 +506,49 @@ elsif ($opt_b) { } } + my $single_ret_var = "undefined"; + my $single_ret_by_ref = 0; + my $single_ret_check = " == undefined"; + + if ($calls{$_}->{ret} ne "void") { + foreach my $ret_member (@{$calls{$_}->{ret_members}}) { + if ($ret_member =~ m/(\S+)<\S+>;/) { + push(@ret_list, "ret->$1.$1_val"); + push(@ret_list, "ret->$1.$1_len"); + } elsif ($ret_member =~ m/remote_nonnull_string (\S+);/) { + push(@vars_list, "char *$1"); + push(@ret_list, "ret->$1 = $1;"); + $single_ret_var = $1; + $single_ret_by_ref = 0; + $single_ret_check = " == NULL"; + } elsif ($ret_member =~ m/int (\S+);/) { + push(@vars_list, "int $1"); + push(@ret_list, "ret->$1 = $1;"); + $single_ret_var = $1; + + if ($calls{$_}->{ProcName} eq "DomainGetAutostart" or + $calls{$_}->{ProcName} eq "NetworkGetAutostart" or + $calls{$_}->{ProcName} eq "StoragePoolGetAutostart") { + $single_ret_by_ref = 1; + } else { + $single_ret_by_ref = 0; + $single_ret_check = " < 0"; + } + } elsif ($ret_member =~ m/hyper (\S+);/) { + push(@vars_list, "unsigned long $1"); + push(@ret_list, "ret->$1 = $1;"); + $single_ret_var = $1; + + if ($calls{$_}->{ProcName} eq "DomainGetMaxMemory") { + $single_ret_by_ref = 0; + $single_ret_check = " == 0"; + } else { + $single_ret_by_ref = 1; + } + } + } + } + foreach my $var (@vars_list) { print " $var;\n"; } @@ -414,7 +562,9 @@ elsif ($opt_b) { print join("\n", @getters_list); - print "\n"; + if (@getters_list) { + print "\n"; + } if ($calls{$_}->{ret} eq "void") { print " if (vir$calls{$_}->{ProcName}("; @@ -422,6 +572,56 @@ elsif ($opt_b) { print ") < 0)\n"; print " goto cleanup;\n"; print "\n"; + } elsif (scalar(@{$calls{$_}->{ret_members}}) == 1) { + my $prefix = ""; + my $proc_name = $calls{$_}->{ProcName}; + + if (! @args_list) { + push(@args_list, "conn"); + $prefix = "Connect" + } + + if ($calls{$_}->{ProcName} eq "GetSysinfo" or + $calls{$_}->{ProcName} eq "DomainXMLFromNative" or + $calls{$_}->{ProcName} eq "DomainXMLToNative") { + $prefix = "Connect" + } elsif ($calls{$_}->{ProcName} eq "SupportsFeature") { + $prefix = "Drv" + } elsif ($calls{$_}->{ProcName} eq "DomainDumpXML") { + $proc_name = "DomainGetXMLDesc" + } elsif ($calls{$_}->{ProcName} eq "NetworkDumpXML") { + $proc_name = "NetworkGetXMLDesc" + } elsif ($calls{$_}->{ProcName} eq "StoragePoolDumpXML") { + $proc_name = "StoragePoolGetXMLDesc" + } elsif ($calls{$_}->{ProcName} eq "StorageVolDumpXML") { + $proc_name = "StorageVolGetXMLDesc" + } elsif ($calls{$_}->{ProcName} eq "NodeDeviceDumpXML") { + $proc_name = "NodeDeviceGetXMLDesc" + } elsif ($calls{$_}->{ProcName} eq "DomainSnapshotDumpXML") { + $proc_name = "DomainSnapshotGetXMLDesc" + } elsif ($calls{$_}->{ProcName} eq "DomainGetOsType") { + $proc_name = "DomainGetOSType" + } + + if ($single_ret_by_ref) { + print " if (vir$prefix$proc_name("; + print join(', ', @args_list); + print ", &$single_ret_var) < 0)\n"; + } else { + print " if (($single_ret_var = vir$prefix$proc_name("; + print join(', ', @args_list); + print "))$single_ret_check)\n"; + } + + print " goto cleanup;\n"; + print "\n"; + + if (@ret_list) { + print " "; + } + + print join(" \n", @ret_list); + print "\n"; } print " rv = 0;\n"; @@ -432,7 +632,10 @@ elsif ($opt_b) { print join("\n", @free_list); - print "\n"; + if (@free_list) { + print "\n"; + } + print " return rv;\n"; print "}\n"; print "\n"; -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:13:55 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:55 +0200 Subject: [libvirt] [PATCH 08/22] remote: Rename 'nameslen' to the common 'maxnames' In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-9-git-send-email-matthias.bolte@googlemail.com> Avoids special case handling in the remote generator. --- daemon/remote.c | 8 ++++---- src/remote/remote_driver.c | 12 ++++++------ src/remote/remote_protocol.c | 2 +- src/remote/remote_protocol.h | 2 +- src/remote/remote_protocol.x | 2 +- src/remote_protocol-structs | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 0c7173a..f42e2db 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -3790,9 +3790,9 @@ remoteDispatchDomainSnapshotListNames(struct qemud_server *server ATTRIBUTE_UNUS goto cleanup; } - if (args->nameslen > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) { + if (args->maxnames > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) { virNetError(VIR_ERR_INTERNAL_ERROR, "%s", - _("nameslen > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX")); + _("maxnames > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX")); goto cleanup; } @@ -3800,14 +3800,14 @@ remoteDispatchDomainSnapshotListNames(struct qemud_server *server ATTRIBUTE_UNUS goto cleanup; /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->nameslen) < 0) { + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { virReportOOMError(); goto cleanup; } len = virDomainSnapshotListNames(dom, ret->names.names_val, - args->nameslen, + args->maxnames, args->flags); if (len < 0) goto cleanup; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 9d6056b..935f321 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -9312,7 +9312,7 @@ done: static int remoteDomainSnapshotListNames (virDomainPtr domain, char **const names, - int nameslen, unsigned int flags) + int maxnames, unsigned int flags) { int rv = -1; int i; @@ -9322,15 +9322,15 @@ remoteDomainSnapshotListNames (virDomainPtr domain, char **const names, remoteDriverLock(priv); - if (nameslen > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) { + if (maxnames > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) { remoteError(VIR_ERR_RPC, _("too many remote domain snapshot names: %d > %d"), - nameslen, REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX); + maxnames, REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX); goto done; } make_nonnull_domain(&args.dom, domain); - args.nameslen = nameslen; + args.maxnames = maxnames; args.flags = flags; memset (&ret, 0, sizeof ret); @@ -9339,10 +9339,10 @@ remoteDomainSnapshotListNames (virDomainPtr domain, char **const names, (xdrproc_t) xdr_remote_domain_snapshot_list_names_ret, (char *) &ret) == -1) goto done; - if (ret.names.names_len > nameslen) { + if (ret.names.names_len > maxnames) { remoteError(VIR_ERR_RPC, _("too many remote domain snapshots: %d > %d"), - ret.names.names_len, nameslen); + ret.names.names_len, maxnames); goto cleanup; } diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index e85f607..1bdd79e 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -3756,7 +3756,7 @@ xdr_remote_domain_snapshot_list_names_args (XDR *xdrs, remote_domain_snapshot_li if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) return FALSE; - if (!xdr_int (xdrs, &objp->nameslen)) + if (!xdr_int (xdrs, &objp->maxnames)) return FALSE; if (!xdr_int (xdrs, &objp->flags)) return FALSE; diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index 82d0981..ff6903c 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -2119,7 +2119,7 @@ typedef struct remote_domain_snapshot_num_ret remote_domain_snapshot_num_ret; struct remote_domain_snapshot_list_names_args { remote_nonnull_domain dom; - int nameslen; + int maxnames; int flags; }; typedef struct remote_domain_snapshot_list_names_args remote_domain_snapshot_list_names_args; diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 0422c7b..0858096 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -1874,7 +1874,7 @@ struct remote_domain_snapshot_num_ret { struct remote_domain_snapshot_list_names_args { remote_nonnull_domain dom; - int nameslen; + int maxnames; int flags; }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 73c7202..d433f6b 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1371,7 +1371,7 @@ struct remote_domain_snapshot_num_ret { }; struct remote_domain_snapshot_list_names_args { remote_nonnull_domain dom; - int nameslen; + int maxnames; int flags; }; struct remote_domain_snapshot_list_names_ret { -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:13:53 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:53 +0200 Subject: [libvirt] [PATCH 06/22] remote generator, daemon: Handle more functions In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-7-git-send-email-matthias.bolte@googlemail.com> This covers functions that return single wrapped objects and don't involve complexer code in the body. --- daemon/remote.c | 1212 ----------------------------------- daemon/remote_dispatch_bodies.c | 1198 +++++++++++++++++++++++++++++++++- daemon/remote_dispatch_prototypes.h | 4 +- daemon/remote_dispatch_table.h | 8 +- daemon/remote_generator.pl | 227 ++++--- 5 files changed, 1309 insertions(+), 1340 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index a588a08..2b0e0dc 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -606,36 +606,6 @@ cleanup: return rv; } - -static int -remoteDispatchNodeGetFreeMemory(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_node_get_free_memory_ret *ret) -{ - unsigned long long freeMem; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((freeMem = virNodeGetFreeMemory(conn)) == 0) - goto cleanup; - ret->freeMem = freeMem; - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - - static int remoteDispatchDomainGetSchedulerType(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, @@ -1118,70 +1088,6 @@ cleanup: } static int -remoteDispatchDomainCreateXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_create_xml_args *args, - remote_domain_create_xml_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = virDomainCreateXML(conn, args->xml_desc, args->flags))) - goto cleanup; - - make_nonnull_domain(&ret->dom, dom); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_define_xml_args *args, - remote_domain_define_xml_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = virDomainDefineXML(conn, args->xml))) - goto cleanup; - - make_nonnull_domain(&ret->dom, dom); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -1492,41 +1398,6 @@ cleanup: } static int -remoteDispatchDomainMigrateFinish(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_migrate_finish_args *args, - remote_domain_migrate_finish_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = virDomainMigrateFinish(conn, args->dname, - args->cookie.cookie_val, - args->cookie.cookie_len, - args->uri, - args->flags))) - goto cleanup; - - make_nonnull_domain(&ret->ddom, dom); - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainMigratePrepare2(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -1578,43 +1449,6 @@ cleanup: } static int -remoteDispatchDomainMigrateFinish2(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_migrate_finish2_args *args, - remote_domain_migrate_finish2_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = virDomainMigrateFinish2(conn, args->dname, - args->cookie.cookie_val, - args->cookie.cookie_len, - args->uri, - args->flags, - args->retcode))) - goto cleanup; - - make_nonnull_domain(&ret->ddom, dom); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainMigratePrepareTunnel(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, virConnectPtr conn, @@ -1706,102 +1540,6 @@ cleanup: } static int -remoteDispatchDomainLookupById(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_lookup_by_id_args *args, - remote_domain_lookup_by_id_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = virDomainLookupByID(conn, args->id))) - goto cleanup; - - make_nonnull_domain(&ret->dom, dom); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_lookup_by_name_args *args, - remote_domain_lookup_by_name_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = virDomainLookupByName(conn, args->name))) - goto cleanup; - - make_nonnull_domain(&ret->dom, dom); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainLookupByUUID(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_lookup_by_uuid_args *args, - remote_domain_lookup_by_uuid_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = virDomainLookupByUUID(conn, (unsigned char *) args->uuid))) - goto cleanup; - - make_nonnull_domain(&ret->dom, dom); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainPinVcpu(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -2408,134 +2146,6 @@ cleanup: return rv; } -static int -remoteDispatchNetworkCreateXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_create_xml_args *args, - remote_network_create_xml_ret *ret) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = virNetworkCreateXML(conn, args->xml))) - goto cleanup; - - make_nonnull_network(&ret->net, net); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - -static int -remoteDispatchNetworkDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_define_xml_args *args, - remote_network_define_xml_ret *ret) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = virNetworkDefineXML(conn, args->xml))) - goto cleanup; - - make_nonnull_network(&ret->net, net); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - -static int -remoteDispatchNetworkLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_lookup_by_name_args *args, - remote_network_lookup_by_name_ret *ret) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = virNetworkLookupByName(conn, args->name))) - goto cleanup; - - make_nonnull_network(&ret->net, net); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - -static int -remoteDispatchNetworkLookupByUUID(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_lookup_by_uuid_args *args, - remote_network_lookup_by_uuid_ret *ret) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = virNetworkLookupByUUID(conn, (unsigned char *) args->uuid))) - goto cleanup; - - make_nonnull_network(&ret->net, net); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - /*-------------------------------------------------------------*/ static int @@ -2628,102 +2238,6 @@ cleanup: return rv; } -static int -remoteDispatchInterfaceLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_interface_lookup_by_name_args *args, - remote_interface_lookup_by_name_ret *ret) -{ - virInterfacePtr iface = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(iface = virInterfaceLookupByName(conn, args->name))) - goto cleanup; - - make_nonnull_interface(&ret->iface, iface); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (iface) - virInterfaceFree(iface); - return rv; -} - -static int -remoteDispatchInterfaceLookupByMacString(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_interface_lookup_by_mac_string_args *args, - remote_interface_lookup_by_mac_string_ret *ret) -{ - virInterfacePtr iface = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(iface = virInterfaceLookupByMACString(conn, args->mac))) - goto cleanup; - - make_nonnull_interface(&ret->iface, iface); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (iface) - virInterfaceFree(iface); - return rv; -} - -static int -remoteDispatchInterfaceDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_interface_define_xml_args *args, - remote_interface_define_xml_ret *ret) -{ - virInterfacePtr iface = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(iface = virInterfaceDefineXML(conn, args->xml, args->flags))) - goto cleanup; - - make_nonnull_interface(&ret->iface, iface); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (iface) - virInterfaceFree(iface); - return rv; -} - /*-------------------------------------------------------------*/ static int @@ -3651,70 +3165,6 @@ cleanup: } static int -remoteDispatchStoragePoolCreateXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_create_xml_args *args, - remote_storage_pool_create_xml_ret *ret) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = virStoragePoolCreateXML(conn, args->xml, args->flags))) - goto cleanup; - - make_nonnull_storage_pool(&ret->pool, pool); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -static int -remoteDispatchStoragePoolDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_define_xml_args *args, - remote_storage_pool_define_xml_ret *ret) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = virStoragePoolDefineXML(conn, args->xml, args->flags))) - goto cleanup; - - make_nonnull_storage_pool(&ret->pool, pool); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -static int remoteDispatchStoragePoolGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3754,108 +3204,6 @@ cleanup: } static int -remoteDispatchStoragePoolLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_lookup_by_name_args *args, - remote_storage_pool_lookup_by_name_ret *ret) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = virStoragePoolLookupByName(conn, args->name))) - goto cleanup; - - make_nonnull_storage_pool(&ret->pool, pool); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -static int -remoteDispatchStoragePoolLookupByUUID(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_lookup_by_uuid_args *args, - remote_storage_pool_lookup_by_uuid_ret *ret) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = virStoragePoolLookupByUUID(conn, (unsigned char *) args->uuid))) - goto cleanup; - - make_nonnull_storage_pool(&ret->pool, pool); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -static int -remoteDispatchStoragePoolLookupByVolume(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_lookup_by_volume_args *args, - remote_storage_pool_lookup_by_volume_ret *ret) -{ - virStoragePoolPtr pool = NULL; - virStorageVolPtr vol = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(vol = get_nonnull_storage_vol(conn, args->vol))) - goto cleanup; - - if (!(pool = virStoragePoolLookupByVolume(vol))) - goto cleanup; - - make_nonnull_storage_pool(&ret->pool, pool); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (vol) - virStorageVolFree(vol); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -static int remoteDispatchStoragePoolListVolumes(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3911,89 +3259,6 @@ cleanup: * STORAGE VOL APIS ***************************************************************/ - - -static int -remoteDispatchStorageVolCreateXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_vol_create_xml_args *args, - remote_storage_vol_create_xml_ret *ret) -{ - virStoragePoolPtr pool = NULL; - virStorageVolPtr vol = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if (!(vol = virStorageVolCreateXML(pool, args->xml, args->flags))) - goto cleanup; - - make_nonnull_storage_vol(&ret->vol, vol); - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - if (vol) - virStorageVolFree(vol); - return rv; -} - -static int -remoteDispatchStorageVolCreateXMLFrom(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_vol_create_xml_from_args *args, - remote_storage_vol_create_xml_from_ret *ret) -{ - virStoragePoolPtr pool = NULL; - virStorageVolPtr clonevol = NULL; - virStorageVolPtr newvol = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if (!(clonevol = get_nonnull_storage_vol(conn, args->clonevol))) - goto cleanup; - - if (!(newvol = virStorageVolCreateXMLFrom(pool, args->xml, clonevol, - args->flags))) - goto cleanup; - - make_nonnull_storage_vol(&ret->vol, newvol); - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (newvol) - virStorageVolFree(newvol); - if (clonevol) - virStorageVolFree(clonevol); - if (pool) - virStoragePoolFree(pool); - return rv; -} - static int remoteDispatchStorageVolGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, @@ -4032,110 +3297,6 @@ cleanup: return rv; } -static int -remoteDispatchStorageVolLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_vol_lookup_by_name_args *args, - remote_storage_vol_lookup_by_name_ret *ret) -{ - virStoragePoolPtr pool = NULL; - virStorageVolPtr vol = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if (!(vol = virStorageVolLookupByName(pool, args->name))) - goto cleanup; - - make_nonnull_storage_vol(&ret->vol, vol); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - if (vol) - virStorageVolFree(vol); - return rv; -} - -static int -remoteDispatchStorageVolLookupByKey(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_vol_lookup_by_key_args *args, - remote_storage_vol_lookup_by_key_ret *ret) -{ - virStorageVolPtr vol = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(vol = virStorageVolLookupByKey(conn, args->key))) - goto cleanup; - - make_nonnull_storage_vol(&ret->vol, vol); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (vol) - virStorageVolFree(vol); - return rv; -} - - -static int -remoteDispatchStorageVolLookupByPath(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_vol_lookup_by_path_args *args, - remote_storage_vol_lookup_by_path_ret *ret) -{ - virStorageVolPtr vol = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(vol = virStorageVolLookupByPath(conn, args->path))) - goto cleanup; - - make_nonnull_storage_vol(&ret->vol, vol); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (vol) - virStorageVolFree(vol); - return rv; -} - - /*************************************************************** * NODE INFO APIS **************************************************************/ @@ -4216,39 +3377,6 @@ cleanup: return rv; } - -static int -remoteDispatchNodeDeviceLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_node_device_lookup_by_name_args *args, - remote_node_device_lookup_by_name_ret *ret) -{ - virNodeDevicePtr dev = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dev = virNodeDeviceLookupByName(conn, args->name))) - goto cleanup; - - make_nonnull_node_device(&ret->dev, dev); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dev) - virNodeDeviceFree(dev); - return rv; -} - static int remoteDispatchNodeDeviceGetParent(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, @@ -4350,38 +3478,6 @@ cleanup: return rv; } -static int -remoteDispatchNodeDeviceCreateXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_node_device_create_xml_args *args, - remote_node_device_create_xml_ret *ret) -{ - virNodeDevicePtr dev = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dev = virNodeDeviceCreateXML(conn, args->xml_desc, args->flags))) - goto cleanup; - - make_nonnull_node_device(&ret->dev, dev); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dev) - virNodeDeviceFree(dev); - return rv; -} - static int remoteDispatchStorageVolUpload(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, virConnectPtr conn, @@ -4658,37 +3754,6 @@ cleanup: } static int -remoteDispatchSecretDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_secret_define_xml_args *args, - remote_secret_define_xml_ret *ret) -{ - virSecretPtr secret = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(secret = virSecretDefineXML(conn, args->xml, args->flags))) - goto cleanup; - - make_nonnull_secret(&ret->secret, secret); - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (secret) - virSecretFree(secret); - return rv; -} - -static int remoteDispatchSecretGetValue(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -4727,70 +3792,6 @@ cleanup: } static int -remoteDispatchSecretLookupByUUID(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_secret_lookup_by_uuid_args *args, - remote_secret_lookup_by_uuid_ret *ret) -{ - virSecretPtr secret = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(secret = virSecretLookupByUUID(conn, (unsigned char *)args->uuid))) - goto cleanup; - - make_nonnull_secret(&ret->secret, secret); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (secret) - virSecretFree(secret); - return rv; -} - -static int -remoteDispatchSecretLookupByUsage(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_secret_lookup_by_usage_args *args, - remote_secret_lookup_by_usage_ret *ret) -{ - virSecretPtr secret = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(secret = virSecretLookupByUsage(conn, args->usageType, args->usageID))) - goto cleanup; - - make_nonnull_secret(&ret->secret, secret); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (secret) - virSecretFree(secret); - return rv; -} - -static int remoteDispatchCpuCompare(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -4902,44 +3903,6 @@ cleanup: } static int -remoteDispatchDomainSnapshotCreateXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_snapshot_create_xml_args *args, - remote_domain_snapshot_create_xml_ret *ret) -{ - virDomainSnapshotPtr snapshot = NULL; - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (!(snapshot = virDomainSnapshotCreateXML(dom, args->xml_desc, args->flags))) - goto cleanup; - - make_nonnull_domain_snapshot(&ret->snap, snapshot); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (snapshot) - virDomainSnapshotFree(snapshot); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainSnapshotListNames(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -4993,82 +3956,6 @@ cleanup: } static int -remoteDispatchDomainSnapshotLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_snapshot_lookup_by_name_args *args, - remote_domain_snapshot_lookup_by_name_ret *ret) -{ - virDomainSnapshotPtr snapshot = NULL; - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (!(snapshot = virDomainSnapshotLookupByName(dom, args->name, args->flags))) - goto cleanup; - - make_nonnull_domain_snapshot(&ret->snap, snapshot); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (snapshot) - virDomainSnapshotFree(snapshot); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainSnapshotCurrent(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_snapshot_current_args *args, - remote_domain_snapshot_current_ret *ret) -{ - virDomainSnapshotPtr snapshot = NULL; - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (!(snapshot = virDomainSnapshotCurrent(dom, args->flags))) - goto cleanup; - - make_nonnull_domain_snapshot(&ret->snap, snapshot); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (snapshot) - virDomainSnapshotFree(snapshot); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainEventsRegisterAny(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -5154,105 +4041,6 @@ cleanup: return rv; } - - -static int -remoteDispatchNWFilterLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_nwfilter_lookup_by_name_args *args, - remote_nwfilter_lookup_by_name_ret *ret) -{ - virNWFilterPtr nwfilter = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(nwfilter = virNWFilterLookupByName(conn, args->name))) - goto cleanup; - - make_nonnull_nwfilter(&ret->nwfilter, nwfilter); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (nwfilter) - virNWFilterFree(nwfilter); - return rv; -} - -static int -remoteDispatchNWFilterLookupByUUID(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_nwfilter_lookup_by_uuid_args *args, - remote_nwfilter_lookup_by_uuid_ret *ret) -{ - virNWFilterPtr nwfilter = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(nwfilter = virNWFilterLookupByUUID(conn, (unsigned char *) args->uuid))) - goto cleanup; - - make_nonnull_nwfilter(&ret->nwfilter, nwfilter); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (nwfilter) - virNWFilterFree(nwfilter); - return rv; -} - - -static int -remoteDispatchNWFilterDefineXML(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_nwfilter_define_xml_args *args, - remote_nwfilter_define_xml_ret *ret) -{ - virNWFilterPtr nwfilter = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(nwfilter = virNWFilterDefineXML(conn, args->xml))) - goto cleanup; - - make_nonnull_nwfilter(&ret->nwfilter, nwfilter); - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (nwfilter) - virNWFilterFree(nwfilter); - return rv; -} - static int remoteDispatchListNWFilters(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, diff --git a/daemon/remote_dispatch_bodies.c b/daemon/remote_dispatch_bodies.c index c1959b6..bd7cddd 100644 --- a/daemon/remote_dispatch_bodies.c +++ b/daemon/remote_dispatch_bodies.c @@ -194,9 +194,69 @@ cleanup: /* remoteDispatchDomainCreateWithFlags has to be implemented manually */ -/* remoteDispatchDomainCreateXML has to be implemented manually */ +static int +remoteDispatchDomainCreateXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_create_xml_args *args, + remote_domain_create_xml_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } -/* remoteDispatchDomainDefineXML has to be implemented manually */ + if ((dom = virDomainCreateXML(conn, args->xml_desc, args->flags)) == NULL) + goto cleanup; + + make_nonnull_domain(&ret->dom, dom); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainDefineXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_define_xml_args *args, + remote_domain_define_xml_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((dom = virDomainDefineXML(conn, args->xml)) == NULL) + goto cleanup; + + make_nonnull_domain(&ret->dom, dom); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} static int remoteDispatchDomainDestroy( @@ -724,11 +784,101 @@ cleanup: return rv; } -/* remoteDispatchDomainLookupById has to be implemented manually */ +static int +remoteDispatchDomainLookupByID( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_lookup_by_id_args *args, + remote_domain_lookup_by_id_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; -/* remoteDispatchDomainLookupByName has to be implemented manually */ + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((dom = virDomainLookupByID(conn, args->id)) == NULL) + goto cleanup; + + make_nonnull_domain(&ret->dom, dom); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainLookupByName( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_lookup_by_name_args *args, + remote_domain_lookup_by_name_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((dom = virDomainLookupByName(conn, args->name)) == NULL) + goto cleanup; -/* remoteDispatchDomainLookupByUUID has to be implemented manually */ + make_nonnull_domain(&ret->dom, dom); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainLookupByUUID( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_lookup_by_uuid_args *args, + remote_domain_lookup_by_uuid_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((dom = virDomainLookupByUUID(conn, (unsigned char *) args->uuid)) == NULL) + goto cleanup; + + make_nonnull_domain(&ret->dom, dom); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} static int remoteDispatchDomainManagedSave( @@ -802,9 +952,69 @@ cleanup: /* remoteDispatchDomainMemoryStats has to be implemented manually */ -/* remoteDispatchDomainMigrateFinish has to be implemented manually */ +static int +remoteDispatchDomainMigrateFinish( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_migrate_finish_args *args, + remote_domain_migrate_finish_ret *ret) +{ + int rv = -1; + virDomainPtr ddom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((ddom = virDomainMigrateFinish(conn, args->dname, args->cookie.cookie_val, args->cookie.cookie_len, args->uri, args->flags)) == NULL) + goto cleanup; + + make_nonnull_domain(&ret->ddom, ddom); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (ddom) + virDomainFree(ddom); + return rv; +} + +static int +remoteDispatchDomainMigrateFinish2( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_migrate_finish2_args *args, + remote_domain_migrate_finish2_ret *ret) +{ + int rv = -1; + virDomainPtr ddom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((ddom = virDomainMigrateFinish2(conn, args->dname, args->cookie.cookie_val, args->cookie.cookie_len, args->uri, args->flags, args->retcode)) == NULL) + goto cleanup; -/* remoteDispatchDomainMigrateFinish2 has to be implemented manually */ + make_nonnull_domain(&ret->ddom, ddom); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (ddom) + virDomainFree(ddom); + return rv; +} /* remoteDispatchDomainMigratePerform has to be implemented manually */ @@ -1300,9 +1510,81 @@ cleanup: return rv; } -/* remoteDispatchDomainSnapshotCreateXML has to be implemented manually */ +static int +remoteDispatchDomainSnapshotCreateXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_snapshot_create_xml_args *args, + remote_domain_snapshot_create_xml_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + virDomainSnapshotPtr snap = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((snap = virDomainSnapshotCreateXML(dom, args->xml_desc, args->flags)) == NULL) + goto cleanup; + + make_nonnull_domain_snapshot(&ret->snap, snap); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + if (snap) + virDomainSnapshotFree(snap); + return rv; +} + +static int +remoteDispatchDomainSnapshotCurrent( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_snapshot_current_args *args, + remote_domain_snapshot_current_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + virDomainSnapshotPtr snap = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((snap = virDomainSnapshotCurrent(dom, args->flags)) == NULL) + goto cleanup; + + make_nonnull_domain_snapshot(&ret->snap, snap); + rv = 0; -/* remoteDispatchDomainSnapshotCurrent has to be implemented manually */ +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + if (snap) + virDomainSnapshotFree(snap); + return rv; +} static int remoteDispatchDomainSnapshotDelete( @@ -1388,7 +1670,43 @@ cleanup: /* remoteDispatchDomainSnapshotListNames has to be implemented manually */ -/* remoteDispatchDomainSnapshotLookupByName has to be implemented manually */ +static int +remoteDispatchDomainSnapshotLookupByName( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_snapshot_lookup_by_name_args *args, + remote_domain_snapshot_lookup_by_name_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + virDomainSnapshotPtr snap = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if ((snap = virDomainSnapshotLookupByName(dom, args->name, args->flags)) == NULL) + goto cleanup; + + make_nonnull_domain_snapshot(&ret->snap, snap); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + if (snap) + virDomainSnapshotFree(snap); + return rv; +} static int remoteDispatchDomainSnapshotNum( @@ -1808,7 +2126,37 @@ cleanup: return rv; } -/* remoteDispatchInterfaceDefineXML has to be implemented manually */ +static int +remoteDispatchInterfaceDefineXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_interface_define_xml_args *args, + remote_interface_define_xml_ret *ret) +{ + int rv = -1; + virInterfacePtr iface = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((iface = virInterfaceDefineXML(conn, args->xml, args->flags)) == NULL) + goto cleanup; + + make_nonnull_interface(&ret->iface, iface); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (iface) + virInterfaceFree(iface); + return rv; +} static int remoteDispatchInterfaceDestroy( @@ -1916,9 +2264,69 @@ cleanup: return rv; } -/* remoteDispatchInterfaceLookupByMacString has to be implemented manually */ +static int +remoteDispatchInterfaceLookupByMACString( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_interface_lookup_by_mac_string_args *args, + remote_interface_lookup_by_mac_string_ret *ret) +{ + int rv = -1; + virInterfacePtr iface = NULL; -/* remoteDispatchInterfaceLookupByName has to be implemented manually */ + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((iface = virInterfaceLookupByMACString(conn, args->mac)) == NULL) + goto cleanup; + + make_nonnull_interface(&ret->iface, iface); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (iface) + virInterfaceFree(iface); + return rv; +} + +static int +remoteDispatchInterfaceLookupByName( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_interface_lookup_by_name_args *args, + remote_interface_lookup_by_name_ret *ret) +{ + int rv = -1; + virInterfacePtr iface = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((iface = virInterfaceLookupByName(conn, args->name)) == NULL) + goto cleanup; + + make_nonnull_interface(&ret->iface, iface); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (iface) + virInterfaceFree(iface); + return rv; +} static int remoteDispatchInterfaceUndefine( @@ -2038,9 +2446,69 @@ cleanup: return rv; } -/* remoteDispatchNetworkCreateXML has to be implemented manually */ +static int +remoteDispatchNetworkCreateXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_create_xml_args *args, + remote_network_create_xml_ret *ret) +{ + int rv = -1; + virNetworkPtr net = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } -/* remoteDispatchNetworkDefineXML has to be implemented manually */ + if ((net = virNetworkCreateXML(conn, args->xml)) == NULL) + goto cleanup; + + make_nonnull_network(&ret->net, net); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} + +static int +remoteDispatchNetworkDefineXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_define_xml_args *args, + remote_network_define_xml_ret *ret) +{ + int rv = -1; + virNetworkPtr net = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((net = virNetworkDefineXML(conn, args->xml)) == NULL) + goto cleanup; + + make_nonnull_network(&ret->net, net); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} static int remoteDispatchNetworkDestroy( @@ -2256,9 +2724,69 @@ cleanup: return rv; } -/* remoteDispatchNetworkLookupByName has to be implemented manually */ +static int +remoteDispatchNetworkLookupByName( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_lookup_by_name_args *args, + remote_network_lookup_by_name_ret *ret) +{ + int rv = -1; + virNetworkPtr net = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((net = virNetworkLookupByName(conn, args->name)) == NULL) + goto cleanup; + + make_nonnull_network(&ret->net, net); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} + +static int +remoteDispatchNetworkLookupByUUID( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_lookup_by_uuid_args *args, + remote_network_lookup_by_uuid_ret *ret) +{ + int rv = -1; + virNetworkPtr net = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((net = virNetworkLookupByUUID(conn, (unsigned char *) args->uuid)) == NULL) + goto cleanup; + + make_nonnull_network(&ret->net, net); + rv = 0; -/* remoteDispatchNetworkLookupByUUID has to be implemented manually */ +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} static int remoteDispatchNetworkSetAutostart( @@ -2328,7 +2856,37 @@ cleanup: return rv; } -/* remoteDispatchNodeDeviceCreateXML has to be implemented manually */ +static int +remoteDispatchNodeDeviceCreateXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_device_create_xml_args *args, + remote_node_device_create_xml_ret *ret) +{ + int rv = -1; + virNodeDevicePtr dev = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((dev = virNodeDeviceCreateXML(conn, args->xml_desc, args->flags)) == NULL) + goto cleanup; + + make_nonnull_node_device(&ret->dev, dev); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dev) + virNodeDeviceFree(dev); + return rv; +} static int remoteDispatchNodeDeviceDestroy( @@ -2438,7 +2996,37 @@ cleanup: /* remoteDispatchNodeDeviceListCaps has to be implemented manually */ -/* remoteDispatchNodeDeviceLookupByName has to be implemented manually */ +static int +remoteDispatchNodeDeviceLookupByName( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_device_lookup_by_name_args *args, + remote_node_device_lookup_by_name_ret *ret) +{ + int rv = -1; + virNodeDevicePtr dev = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((dev = virNodeDeviceLookupByName(conn, args->name)) == NULL) + goto cleanup; + + make_nonnull_node_device(&ret->dev, dev); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dev) + virNodeDeviceFree(dev); + return rv; +} static int remoteDispatchNodeDeviceNumOfCaps( @@ -2546,7 +3134,35 @@ cleanup: /* remoteDispatchNodeGetCellsFreeMemory has to be implemented manually */ -/* remoteDispatchNodeGetFreeMemory has to be implemented manually */ +static int +remoteDispatchNodeGetFreeMemory( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_node_get_free_memory_ret *ret) +{ + int rv = -1; + unsigned long freeMem; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((freeMem = virNodeGetFreeMemory(conn)) == 0) + goto cleanup; + + ret->freeMem = freeMem; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} /* remoteDispatchNodeGetInfo has to be implemented manually */ @@ -2856,7 +3472,37 @@ cleanup: return rv; } -/* remoteDispatchNWFilterDefineXML has to be implemented manually */ +static int +remoteDispatchNWFilterDefineXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_nwfilter_define_xml_args *args, + remote_nwfilter_define_xml_ret *ret) +{ + int rv = -1; + virNWFilterPtr nwfilter = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((nwfilter = virNWFilterDefineXML(conn, args->xml)) == NULL) + goto cleanup; + + make_nonnull_nwfilter(&ret->nwfilter, nwfilter); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (nwfilter) + virNWFilterFree(nwfilter); + return rv; +} static int remoteDispatchNWFilterGetXMLDesc( @@ -2894,9 +3540,69 @@ cleanup: return rv; } -/* remoteDispatchNWFilterLookupByName has to be implemented manually */ +static int +remoteDispatchNWFilterLookupByName( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_nwfilter_lookup_by_name_args *args, + remote_nwfilter_lookup_by_name_ret *ret) +{ + int rv = -1; + virNWFilterPtr nwfilter = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((nwfilter = virNWFilterLookupByName(conn, args->name)) == NULL) + goto cleanup; + + make_nonnull_nwfilter(&ret->nwfilter, nwfilter); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (nwfilter) + virNWFilterFree(nwfilter); + return rv; +} + +static int +remoteDispatchNWFilterLookupByUUID( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_nwfilter_lookup_by_uuid_args *args, + remote_nwfilter_lookup_by_uuid_ret *ret) +{ + int rv = -1; + virNWFilterPtr nwfilter = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((nwfilter = virNWFilterLookupByUUID(conn, (unsigned char *) args->uuid)) == NULL) + goto cleanup; -/* remoteDispatchNWFilterLookupByUUID has to be implemented manually */ + make_nonnull_nwfilter(&ret->nwfilter, nwfilter); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (nwfilter) + virNWFilterFree(nwfilter); + return rv; +} static int remoteDispatchNWFilterUndefine( @@ -2934,7 +3640,37 @@ cleanup: /* remoteDispatchOpen has to be implemented manually */ -/* remoteDispatchSecretDefineXML has to be implemented manually */ +static int +remoteDispatchSecretDefineXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_secret_define_xml_args *args, + remote_secret_define_xml_ret *ret) +{ + int rv = -1; + virSecretPtr secret = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((secret = virSecretDefineXML(conn, args->xml, args->flags)) == NULL) + goto cleanup; + + make_nonnull_secret(&ret->secret, secret); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (secret) + virSecretFree(secret); + return rv; +} /* remoteDispatchSecretGetValue has to be implemented manually */ @@ -2974,9 +3710,69 @@ cleanup: return rv; } -/* remoteDispatchSecretLookupByUsage has to be implemented manually */ +static int +remoteDispatchSecretLookupByUsage( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_secret_lookup_by_usage_args *args, + remote_secret_lookup_by_usage_ret *ret) +{ + int rv = -1; + virSecretPtr secret = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((secret = virSecretLookupByUsage(conn, args->usageType, args->usageID)) == NULL) + goto cleanup; + + make_nonnull_secret(&ret->secret, secret); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (secret) + virSecretFree(secret); + return rv; +} + +static int +remoteDispatchSecretLookupByUUID( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_secret_lookup_by_uuid_args *args, + remote_secret_lookup_by_uuid_ret *ret) +{ + int rv = -1; + virSecretPtr secret = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((secret = virSecretLookupByUUID(conn, (unsigned char *) args->uuid)) == NULL) + goto cleanup; -/* remoteDispatchSecretLookupByUUID has to be implemented manually */ + make_nonnull_secret(&ret->secret, secret); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (secret) + virSecretFree(secret); + return rv; +} static int remoteDispatchSecretSetValue( @@ -3114,9 +3910,69 @@ cleanup: return rv; } -/* remoteDispatchStoragePoolCreateXML has to be implemented manually */ +static int +remoteDispatchStoragePoolCreateXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_create_xml_args *args, + remote_storage_pool_create_xml_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((pool = virStoragePoolCreateXML(conn, args->xml, args->flags)) == NULL) + goto cleanup; + + make_nonnull_storage_pool(&ret->pool, pool); + rv = 0; -/* remoteDispatchStoragePoolDefineXML has to be implemented manually */ +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} + +static int +remoteDispatchStoragePoolDefineXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_define_xml_args *args, + remote_storage_pool_define_xml_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((pool = virStoragePoolDefineXML(conn, args->xml, args->flags)) == NULL) + goto cleanup; + + make_nonnull_storage_pool(&ret->pool, pool); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} static int remoteDispatchStoragePoolDelete( @@ -3334,11 +4190,107 @@ cleanup: /* remoteDispatchStoragePoolListVolumes has to be implemented manually */ -/* remoteDispatchStoragePoolLookupByName has to be implemented manually */ +static int +remoteDispatchStoragePoolLookupByName( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_lookup_by_name_args *args, + remote_storage_pool_lookup_by_name_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((pool = virStoragePoolLookupByName(conn, args->name)) == NULL) + goto cleanup; + + make_nonnull_storage_pool(&ret->pool, pool); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} + +static int +remoteDispatchStoragePoolLookupByUUID( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_lookup_by_uuid_args *args, + remote_storage_pool_lookup_by_uuid_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((pool = virStoragePoolLookupByUUID(conn, (unsigned char *) args->uuid)) == NULL) + goto cleanup; + + make_nonnull_storage_pool(&ret->pool, pool); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} + +static int +remoteDispatchStoragePoolLookupByVolume( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_lookup_by_volume_args *args, + remote_storage_pool_lookup_by_volume_ret *ret) +{ + int rv = -1; + virStorageVolPtr vol = NULL; + virStoragePoolPtr pool = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } -/* remoteDispatchStoragePoolLookupByUUID has to be implemented manually */ + if (!(vol = get_nonnull_storage_vol(conn, args->vol))) + goto cleanup; + + if ((pool = virStoragePoolLookupByVolume(vol)) == NULL) + goto cleanup; -/* remoteDispatchStoragePoolLookupByVolume has to be implemented manually */ + make_nonnull_storage_pool(&ret->pool, pool); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (vol) + virStorageVolFree(vol); + if (pool) + virStoragePoolFree(pool); + return rv; +} static int remoteDispatchStoragePoolNumOfVolumes( @@ -3478,9 +4430,87 @@ cleanup: return rv; } -/* remoteDispatchStorageVolCreateXML has to be implemented manually */ +static int +remoteDispatchStorageVolCreateXML( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_vol_create_xml_args *args, + remote_storage_vol_create_xml_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + virStorageVolPtr vol = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if ((vol = virStorageVolCreateXML(pool, args->xml, args->flags)) == NULL) + goto cleanup; + + make_nonnull_storage_vol(&ret->vol, vol); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + if (vol) + virStorageVolFree(vol); + return rv; +} + +static int +remoteDispatchStorageVolCreateXMLFrom( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_vol_create_xml_from_args *args, + remote_storage_vol_create_xml_from_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + virStorageVolPtr clonevol = NULL; + virStorageVolPtr vol = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if (!(clonevol = get_nonnull_storage_vol(conn, args->clonevol))) + goto cleanup; -/* remoteDispatchStorageVolCreateXMLFrom has to be implemented manually */ + if ((vol = virStorageVolCreateXMLFrom(pool, args->xml, clonevol, args->flags)) == NULL) + goto cleanup; + + make_nonnull_storage_vol(&ret->vol, vol); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + if (clonevol) + virStorageVolFree(clonevol); + if (vol) + virStorageVolFree(vol); + return rv; +} static int remoteDispatchStorageVolDelete( @@ -3592,11 +4622,107 @@ cleanup: return rv; } -/* remoteDispatchStorageVolLookupByKey has to be implemented manually */ +static int +remoteDispatchStorageVolLookupByKey( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_vol_lookup_by_key_args *args, + remote_storage_vol_lookup_by_key_ret *ret) +{ + int rv = -1; + virStorageVolPtr vol = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((vol = virStorageVolLookupByKey(conn, args->key)) == NULL) + goto cleanup; + + make_nonnull_storage_vol(&ret->vol, vol); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (vol) + virStorageVolFree(vol); + return rv; +} + +static int +remoteDispatchStorageVolLookupByName( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_vol_lookup_by_name_args *args, + remote_storage_vol_lookup_by_name_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + virStorageVolPtr vol = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if ((vol = virStorageVolLookupByName(pool, args->name)) == NULL) + goto cleanup; + + make_nonnull_storage_vol(&ret->vol, vol); + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + if (vol) + virStorageVolFree(vol); + return rv; +} + +static int +remoteDispatchStorageVolLookupByPath( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_vol_lookup_by_path_args *args, + remote_storage_vol_lookup_by_path_ret *ret) +{ + int rv = -1; + virStorageVolPtr vol = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((vol = virStorageVolLookupByPath(conn, args->path)) == NULL) + goto cleanup; -/* remoteDispatchStorageVolLookupByName has to be implemented manually */ + make_nonnull_storage_vol(&ret->vol, vol); + rv = 0; -/* remoteDispatchStorageVolLookupByPath has to be implemented manually */ +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (vol) + virStorageVolFree(vol); + return rv; +} /* remoteDispatchStorageVolUpload has to be implemented manually */ diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index dff84d7..1e3be48 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -370,7 +370,7 @@ static int remoteDispatchDomainIsUpdated( remote_error *rerr, remote_domain_is_updated_args *args, remote_domain_is_updated_ret *ret); -static int remoteDispatchDomainLookupById( +static int remoteDispatchDomainLookupByID( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -834,7 +834,7 @@ static int remoteDispatchInterfaceIsActive( remote_error *rerr, remote_interface_is_active_args *args, remote_interface_is_active_ret *ret); -static int remoteDispatchInterfaceLookupByMacString( +static int remoteDispatchInterfaceLookupByMACString( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index 627331e..357d1de 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -112,8 +112,8 @@ .args_filter = (xdrproc_t) xdr_remote_list_defined_domains_args, .ret_filter = (xdrproc_t) xdr_remote_list_defined_domains_ret, }, -{ /* DomainLookupById => 22 */ - .fn = (dispatch_fn) remoteDispatchDomainLookupById, +{ /* DomainLookupByID => 22 */ + .fn = (dispatch_fn) remoteDispatchDomainLookupByID, .args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_id_args, .ret_filter = (xdrproc_t) xdr_remote_domain_lookup_by_id_ret, }, @@ -647,8 +647,8 @@ .args_filter = (xdrproc_t) xdr_remote_interface_lookup_by_name_args, .ret_filter = (xdrproc_t) xdr_remote_interface_lookup_by_name_ret, }, -{ /* InterfaceLookupByMacString => 129 */ - .fn = (dispatch_fn) remoteDispatchInterfaceLookupByMacString, +{ /* InterfaceLookupByMACString => 129 */ + .fn = (dispatch_fn) remoteDispatchInterfaceLookupByMACString, .args_filter = (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_args, .ret_filter = (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_ret, }, diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 0901649..1b83d52 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -33,7 +33,8 @@ sub name_to_ProcName { my @elems = split /_/, $name; @elems = map ucfirst, @elems; @elems = map { $_ =~ s/Nwfilter/NWFilter/; $_ =~ s/Xml/XML/; - $_ =~ s/Uri/URI/; $_ =~ s/Uuid/UUID/; $_ } @elems; + $_ =~ s/Uri/URI/; $_ =~ s/Uuid/UUID/; $_ =~ s/Id/ID/; + $_ =~ s/Mac/MAC/; $_ } @elems; join "", @elems } @@ -262,8 +263,6 @@ elsif ($opt_b) { "DomainBlockPeek", "DomainBlockStats", "DomainCreateWithFlags", - "DomainCreateXML", - "DomainDefineXML", "DomainEventsDeregister", "DomainEventsRegister", "DomainGetBlkioParameters", @@ -276,25 +275,14 @@ elsif ($opt_b) { "DomainGetSecurityLabel", "DomainGetVcpus", "DomainInterfaceStats", - "DomainLookupById", - "DomainLookupByName", - "DomainLookupByUUID", "DomainMemoryPeek", "DomainMemoryStats", - "DomainMigrateFinish", - "DomainMigrateFinish2", "DomainMigratePrepare", "DomainMigratePrepare2", - "DomainSnapshotCreateXML", - "DomainSnapshotCurrent", "DomainSnapshotListNames", - "DomainSnapshotLookupByName", "FindStoragePoolSources", "GetMaxVcpus", "GetType", - "InterfaceLookupByMacString", - "InterfaceLookupByName", - "InterfaceDefineXML", "ListDefinedDomains", "ListDefinedInterfaces", "ListDefinedNetworks", @@ -305,40 +293,17 @@ elsif ($opt_b) { "ListNWFilters", "ListSecrets", "ListStoragePools", - "NetworkLookupByName", - "NetworkLookupByUUID", - "NodeDeviceCreateXML", - "NetworkCreateXML", "NodeDeviceGetParent", "NodeDeviceListCaps", - "NodeDeviceLookupByName", "NodeGetCellsFreeMemory", - "NodeGetFreeMemory", "NodeGetInfo", "NodeGetSecurityModel", - "NetworkDefineXML", "NodeListDevices", "NodeNumOfDevices", - "NWFilterLookupByName", - "NWFilterLookupByUUID", - "SecretDefineXML", "SecretGetValue", - "NWFilterDefineXML", - "SecretLookupByUsage", - "SecretLookupByUUID", - "StoragePoolCreateXML", - "StoragePoolDefineXML", "StoragePoolGetInfo", "StoragePoolListVolumes", - "StoragePoolLookupByName", - "StoragePoolLookupByUUID", - "StoragePoolLookupByVolume", - "StorageVolCreateXML", - "StorageVolCreateXMLFrom", - "StorageVolGetInfo", - "StorageVolLookupByKey", - "StorageVolLookupByName", - "StorageVolLookupByPath"); + "StorageVolGetInfo"); } elsif ($structprefix eq "qemu") { @ungeneratable = ("MonitorCommand"); } @@ -350,7 +315,6 @@ elsif ($opt_b) { # skip things which are REMOTE_MESSAGE next if $calls{$_}->{msg}; - # FIXME: skip functions with explicit return value for now if (exists($ug{$calls{$_}->{ProcName}})) { print "/* ${structprefix}Dispatch$calls{$_}->{ProcName} has to " . "be implemented manually */\n\n"; @@ -390,7 +354,9 @@ elsif ($opt_b) { if ($calls{$_}->{args} ne "void") { # node device is special, as it's identified by name - if ($calls{$_}->{args} =~ m/^remote_node_device/) { + if ($calls{$_}->{args} =~ m/^remote_node_device_/ and + !($calls{$_}->{args} =~ m/^remote_node_device_lookup_by_name_/) and + !($calls{$_}->{args} =~ m/^remote_node_device_create_xml_/)) { $has_node_device = 1; push(@vars_list, "virNodeDevicePtr dev = NULL"); push(@getters_list, @@ -406,69 +372,69 @@ elsif ($opt_b) { if ($args_member =~ m/^remote_nonnull_string name;/ and $has_node_device) { # ignore the name arg for node devices next - } elsif ($args_member =~ m/^remote_nonnull_domain /) { - push(@vars_list, "virDomainPtr dom = NULL"); + } elsif ($args_member =~ m/^remote_nonnull_domain (\S+);/) { + push(@vars_list, "virDomainPtr $1 = NULL"); push(@getters_list, - " if (!(dom = get_nonnull_domain(conn, args->dom)))\n" . + " if (!($1 = get_nonnull_domain(conn, args->$1)))\n" . " goto cleanup;\n"); - push(@args_list, "dom"); + push(@args_list, "$1"); push(@free_list, - " if (dom)\n" . - " virDomainFree(dom);"); - } elsif ($args_member =~ m/^remote_nonnull_network /) { - push(@vars_list, "virNetworkPtr net = NULL"); + " if ($1)\n" . + " virDomainFree($1);"); + } elsif ($args_member =~ m/^remote_nonnull_network (\S+);/) { + push(@vars_list, "virNetworkPtr $1 = NULL"); push(@getters_list, - " if (!(net = get_nonnull_network(conn, args->net)))\n" . + " if (!($1 = get_nonnull_network(conn, args->$1)))\n" . " goto cleanup;\n"); - push(@args_list, "net"); + push(@args_list, "$1"); push(@free_list, - " if (net)\n" . - " virNetworkFree(net);"); - } elsif ($args_member =~ m/^remote_nonnull_storage_pool /) { - push(@vars_list, "virStoragePoolPtr pool = NULL"); + " if ($1)\n" . + " virNetworkFree($1);"); + } elsif ($args_member =~ m/^remote_nonnull_storage_pool (\S+);/) { + push(@vars_list, "virStoragePoolPtr $1 = NULL"); push(@getters_list, - " if (!(pool = get_nonnull_storage_pool(conn, args->pool)))\n" . + " if (!($1 = get_nonnull_storage_pool(conn, args->$1)))\n" . " goto cleanup;\n"); - push(@args_list, "pool"); + push(@args_list, "$1"); push(@free_list, - " if (pool)\n" . - " virStoragePoolFree(pool);"); - } elsif ($args_member =~ m/^remote_nonnull_storage_vol /) { - push(@vars_list, "virStorageVolPtr vol = NULL"); + " if ($1)\n" . + " virStoragePoolFree($1);"); + } elsif ($args_member =~ m/^remote_nonnull_storage_vol (\S+);/) { + push(@vars_list, "virStorageVolPtr $1 = NULL"); push(@getters_list, - " if (!(vol = get_nonnull_storage_vol(conn, args->vol)))\n" . + " if (!($1 = get_nonnull_storage_vol(conn, args->$1)))\n" . " goto cleanup;\n"); - push(@args_list, "vol"); + push(@args_list, "$1"); push(@free_list, - " if (vol)\n" . - " virStorageVolFree(vol);"); - } elsif ($args_member =~ m/^remote_nonnull_interface /) { - push(@vars_list, "virInterfacePtr iface = NULL"); + " if ($1)\n" . + " virStorageVolFree($1);"); + } elsif ($args_member =~ m/^remote_nonnull_interface (\S+);/) { + push(@vars_list, "virInterfacePtr $1 = NULL"); push(@getters_list, - " if (!(iface = get_nonnull_interface(conn, args->iface)))\n" . + " if (!($1 = get_nonnull_interface(conn, args->$1)))\n" . " goto cleanup;\n"); - push(@args_list, "iface"); + push(@args_list, "$1"); push(@free_list, - " if (iface)\n" . - " virInterfaceFree(iface);"); - } elsif ($args_member =~ m/^remote_nonnull_secret /) { - push(@vars_list, "virSecretPtr secret = NULL"); + " if ($1)\n" . + " virInterfaceFree($1);"); + } elsif ($args_member =~ m/^remote_nonnull_secret (\S+);/) { + push(@vars_list, "virSecretPtr $1 = NULL"); push(@getters_list, - " if (!(secret = get_nonnull_secret(conn, args->secret)))\n" . + " if (!($1 = get_nonnull_secret(conn, args->$1)))\n" . " goto cleanup;\n"); - push(@args_list, "secret"); + push(@args_list, "$1"); push(@free_list, - " if (secret)\n" . - " virSecretFree(secret);"); - } elsif ($args_member =~ m/^remote_nonnull_nwfilter /) { - push(@vars_list, "virNWFilterPtr nwfilter = NULL"); + " if ($1)\n" . + " virSecretFree($1);"); + } elsif ($args_member =~ m/^remote_nonnull_nwfilter (\S+);/) { + push(@vars_list, "virNWFilterPtr $1 = NULL"); push(@getters_list, - " if (!(nwfilter = get_nonnull_nwfilter(conn, args->nwfilter)))\n" . + " if (!($1 = get_nonnull_nwfilter(conn, args->$1)))\n" . " goto cleanup;\n"); - push(@args_list, "nwfilter"); + push(@args_list, "$1"); push(@free_list, - " if (nwfilter)\n" . - " virNWFilterFree(nwfilter);"); + " if ($1)\n" . + " virNWFilterFree($1);"); } elsif ($args_member =~ m/^remote_nonnull_domain_snapshot /) { push(@vars_list, "virDomainPtr dom = NULL"); push(@vars_list, "virDomainSnapshotPtr snapshot = NULL"); @@ -496,12 +462,16 @@ elsif ($opt_b) { } push(@args_list, "args->$1.$1_len"); - } elsif ($args_member =~ m/.* (\S+);/) { + } elsif ($args_member =~ m/(\S+) (\S+);/) { if (! @args_list) { push(@args_list, "conn"); } - push(@args_list, "args->$1"); + if ($1 eq "remote_uuid") { + push(@args_list, "(unsigned char *) args->$2"); + } else { + push(@args_list, "args->$2"); + } } } } @@ -521,6 +491,87 @@ elsif ($opt_b) { $single_ret_var = $1; $single_ret_by_ref = 0; $single_ret_check = " == NULL"; + } elsif ($ret_member =~ m/remote_nonnull_domain (\S+);/) { + push(@vars_list, "virDomainPtr $1 = NULL"); + push(@ret_list, "make_nonnull_domain(&ret->$1, $1);"); + push(@free_list, + " if ($1)\n" . + " virDomainFree($1);"); + $single_ret_var = $1; + $single_ret_by_ref = 0; + $single_ret_check = " == NULL"; + } elsif ($ret_member =~ m/remote_nonnull_network (\S+);/) { + push(@vars_list, "virNetworkPtr $1 = NULL"); + push(@ret_list, "make_nonnull_network(&ret->$1, $1);"); + push(@free_list, + " if ($1)\n" . + " virNetworkFree($1);"); + $single_ret_var = $1; + $single_ret_by_ref = 0; + $single_ret_check = " == NULL"; + } elsif ($ret_member =~ m/remote_nonnull_storage_pool (\S+);/) { + push(@vars_list, "virStoragePoolPtr $1 = NULL"); + push(@ret_list, "make_nonnull_storage_pool(&ret->$1, $1);"); + push(@free_list, + " if ($1)\n" . + " virStoragePoolFree($1);"); + $single_ret_var = $1; + $single_ret_by_ref = 0; + $single_ret_check = " == NULL"; + } elsif ($ret_member =~ m/remote_nonnull_storage_vol (\S+);/) { + push(@vars_list, "virStorageVolPtr $1 = NULL"); + push(@ret_list, "make_nonnull_storage_vol(&ret->$1, $1);"); + push(@free_list, + " if ($1)\n" . + " virStorageVolFree($1);"); + $single_ret_var = $1; + $single_ret_by_ref = 0; + $single_ret_check = " == NULL"; + } elsif ($ret_member =~ m/remote_nonnull_interface (\S+);/) { + push(@vars_list, "virInterfacePtr $1 = NULL"); + push(@ret_list, "make_nonnull_interface(&ret->$1, $1);"); + push(@free_list, + " if ($1)\n" . + " virInterfaceFree($1);"); + $single_ret_var = $1; + $single_ret_by_ref = 0; + $single_ret_check = " == NULL"; + } elsif ($ret_member =~ m/remote_nonnull_node_device (\S+);/) { + push(@vars_list, "virNodeDevicePtr $1 = NULL"); + push(@ret_list, "make_nonnull_node_device(&ret->$1, $1);"); + push(@free_list, + " if ($1)\n" . + " virNodeDeviceFree($1);"); + $single_ret_var = $1; + $single_ret_by_ref = 0; + $single_ret_check = " == NULL"; + } elsif ($ret_member =~ m/remote_nonnull_secret (\S+);/) { + push(@vars_list, "virSecretPtr $1 = NULL"); + push(@ret_list, "make_nonnull_secret(&ret->$1, $1);"); + push(@free_list, + " if ($1)\n" . + " virSecretFree($1);"); + $single_ret_var = $1; + $single_ret_by_ref = 0; + $single_ret_check = " == NULL"; + } elsif ($ret_member =~ m/remote_nonnull_nwfilter (\S+);/) { + push(@vars_list, "virNWFilterPtr $1 = NULL"); + push(@ret_list, "make_nonnull_nwfilter(&ret->$1, $1);"); + push(@free_list, + " if ($1)\n" . + " virNWFilterFree($1);"); + $single_ret_var = $1; + $single_ret_by_ref = 0; + $single_ret_check = " == NULL"; + } elsif ($ret_member =~ m/remote_nonnull_domain_snapshot (\S+);/) { + push(@vars_list, "virDomainSnapshotPtr $1 = NULL"); + push(@ret_list, "make_nonnull_domain_snapshot(&ret->$1, $1);"); + push(@free_list, + " if ($1)\n" . + " virDomainSnapshotFree($1);"); + $single_ret_var = $1; + $single_ret_by_ref = 0; + $single_ret_check = " == NULL"; } elsif ($ret_member =~ m/int (\S+);/) { push(@vars_list, "int $1"); push(@ret_list, "ret->$1 = $1;"); @@ -539,7 +590,8 @@ elsif ($opt_b) { push(@ret_list, "ret->$1 = $1;"); $single_ret_var = $1; - if ($calls{$_}->{ProcName} eq "DomainGetMaxMemory") { + if ($calls{$_}->{ProcName} eq "DomainGetMaxMemory" or + $calls{$_}->{ProcName} eq "NodeGetFreeMemory") { $single_ret_by_ref = 0; $single_ret_check = " == 0"; } else { @@ -578,7 +630,10 @@ elsif ($opt_b) { if (! @args_list) { push(@args_list, "conn"); - $prefix = "Connect" + + if ($calls{$_}->{ProcName} ne "NodeGetFreeMemory") { + $prefix = "Connect" + } } if ($calls{$_}->{ProcName} eq "GetSysinfo" or -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:13:54 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:54 +0200 Subject: [libvirt] [PATCH 07/22] remote generator, daemon: Handle functions with optional arguments In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-8-git-send-email-matthias.bolte@googlemail.com> --- daemon/remote.c | 130 ------------------------------------- daemon/remote_dispatch_bodies.c | 136 +++++++++++++++++++++++++++++++++++++- daemon/remote_generator.pl | 21 +++++-- 3 files changed, 148 insertions(+), 139 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 2b0e0dc..0c7173a 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -494,35 +494,6 @@ cleanup: } static int -remoteDispatchGetMaxVcpus(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_get_max_vcpus_args *args, - remote_get_max_vcpus_ret *ret) -{ - char *type; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - type = args->type ? *args->type : NULL; - if ((ret->max_vcpus = virConnectGetMaxVcpus(conn, type)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int remoteDispatchNodeGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -1358,46 +1329,6 @@ cleanup: } static int -remoteDispatchDomainMigratePerform(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_migrate_perform_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - char *dname; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - dname = args->dname == NULL ? NULL : *args->dname; - - if (virDomainMigratePerform(dom, - args->cookie.cookie_val, - args->cookie.cookie_len, - args->uri, - args->flags, dname, args->resource) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainMigratePrepare2(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3134,37 +3065,6 @@ cleanup: } static int -remoteDispatchFindStoragePoolSources(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_find_storage_pool_sources_args *args, - remote_find_storage_pool_sources_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(ret->xml = - virConnectFindStoragePoolSources(conn, - args->type, - args->srcSpec ? *args->srcSpec : NULL, - args->flags))) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int remoteDispatchStoragePoolGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3302,36 +3202,6 @@ cleanup: **************************************************************/ static int -remoteDispatchNodeNumOfDevices(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_node_num_of_devices_args *args, - remote_node_num_of_devices_ret *ret) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((ret->num = virNodeNumOfDevices(conn, - args->cap ? *args->cap : NULL, - args->flags)) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - - -static int remoteDispatchNodeListDevices(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_bodies.c b/daemon/remote_dispatch_bodies.c index bd7cddd..77b7db4 100644 --- a/daemon/remote_dispatch_bodies.c +++ b/daemon/remote_dispatch_bodies.c @@ -1016,7 +1016,42 @@ cleanup: return rv; } -/* remoteDispatchDomainMigratePerform has to be implemented manually */ +static int +remoteDispatchDomainMigratePerform( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_migrate_perform_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + char *dname; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + dname = args->dname ? *args->dname : NULL; + + if (virDomainMigratePerform(dom, args->cookie.cookie_val, args->cookie.cookie_len, args->uri, args->flags, dname, args->resource) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} /* remoteDispatchDomainMigratePrepare has to be implemented manually */ @@ -1906,7 +1941,38 @@ cleanup: return rv; } -/* remoteDispatchFindStoragePoolSources has to be implemented manually */ +static int +remoteDispatchFindStoragePoolSources( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_find_storage_pool_sources_args *args, + remote_find_storage_pool_sources_ret *ret) +{ + int rv = -1; + char *srcSpec; + char *xml; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + srcSpec = args->srcSpec ? *args->srcSpec : NULL; + + if ((xml = virConnectFindStoragePoolSources(conn, args->type, srcSpec, args->flags)) == NULL) + goto cleanup; + + ret->xml = xml; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} static int remoteDispatchGetCapabilities( @@ -1998,7 +2064,38 @@ cleanup: return rv; } -/* remoteDispatchGetMaxVcpus has to be implemented manually */ +static int +remoteDispatchGetMaxVcpus( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_get_max_vcpus_args *args, + remote_get_max_vcpus_ret *ret) +{ + int rv = -1; + char *type; + int max_vcpus; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + type = args->type ? *args->type : NULL; + + if ((max_vcpus = virConnectGetMaxVcpus(conn, type)) < 0) + goto cleanup; + + ret->max_vcpus = max_vcpus; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} static int remoteDispatchGetSysinfo( @@ -3170,7 +3267,38 @@ cleanup: /* remoteDispatchNodeListDevices has to be implemented manually */ -/* remoteDispatchNodeNumOfDevices has to be implemented manually */ +static int +remoteDispatchNodeNumOfDevices( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_num_of_devices_args *args, + remote_node_num_of_devices_ret *ret) +{ + int rv = -1; + char *cap; + int num; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + cap = args->cap ? *args->cap : NULL; + + if ((num = virNodeNumOfDevices(conn, cap, args->flags)) < 0) + goto cleanup; + + ret->num = num; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} static int remoteDispatchNumOfDefinedDomains( diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 1b83d52..b3cb9b5 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -241,7 +241,6 @@ elsif ($opt_b) { @ungeneratable = ("Close", "DomainEventsDeregisterAny", "DomainEventsRegisterAny", - "DomainMigratePerform", "DomainMigratePrepareTunnel", "DomainOpenConsole", "DomainPinVcpu", @@ -280,8 +279,6 @@ elsif ($opt_b) { "DomainMigratePrepare", "DomainMigratePrepare2", "DomainSnapshotListNames", - "FindStoragePoolSources", - "GetMaxVcpus", "GetType", "ListDefinedDomains", "ListDefinedInterfaces", @@ -299,7 +296,6 @@ elsif ($opt_b) { "NodeGetInfo", "NodeGetSecurityModel", "NodeListDevices", - "NodeNumOfDevices", "SecretGetValue", "StoragePoolGetInfo", "StoragePoolListVolumes", @@ -347,6 +343,7 @@ elsif ($opt_b) { my $has_node_device = 0; my @vars_list = (); + my @optionals_list = (); my @getters_list = (); my @args_list = (); my @ret_list = (); @@ -469,6 +466,10 @@ elsif ($opt_b) { if ($1 eq "remote_uuid") { push(@args_list, "(unsigned char *) args->$2"); + } elsif ($1 eq "remote_string") { + push(@vars_list, "char *$2"); + push(@optionals_list, "$2"); + push(@args_list, "$2"); } else { push(@args_list, "args->$2"); } @@ -618,6 +619,14 @@ elsif ($opt_b) { print "\n"; } + foreach my $optional (@optionals_list) { + print " $optional = args->$optional ? *args->$optional : NULL;\n"; + } + + if (@optionals_list) { + print "\n"; + } + if ($calls{$_}->{ret} eq "void") { print " if (vir$calls{$_}->{ProcName}("; print join(', ', @args_list); @@ -637,8 +646,10 @@ elsif ($opt_b) { } if ($calls{$_}->{ProcName} eq "GetSysinfo" or + $calls{$_}->{ProcName} eq "GetMaxVcpus" or $calls{$_}->{ProcName} eq "DomainXMLFromNative" or - $calls{$_}->{ProcName} eq "DomainXMLToNative") { + $calls{$_}->{ProcName} eq "DomainXMLToNative" or + $calls{$_}->{ProcName} eq "FindStoragePoolSources") { $prefix = "Connect" } elsif ($calls{$_}->{ProcName} eq "SupportsFeature") { $prefix = "Drv" -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:13:58 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:58 +0200 Subject: [libvirt] [PATCH 11/22] remote generator, daemon: Handle the CPU functions In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-12-git-send-email-matthias.bolte@googlemail.com> They require additional special cases. --- daemon/remote.c | 64 ----------------------------------- daemon/remote_dispatch_bodies.c | 62 ++++++++++++++++++++++++++++++++-- daemon/remote_dispatch_prototypes.h | 6 ++-- daemon/remote_dispatch_table.h | 12 +++--- daemon/remote_generator.pl | 20 ++++++++--- 5 files changed, 82 insertions(+), 82 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 4c05567..f70c445 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -3059,70 +3059,6 @@ cleanup: } static int -remoteDispatchCpuCompare(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_cpu_compare_args *args, - remote_cpu_compare_ret *ret) -{ - int result; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if ((result = virConnectCompareCPU(conn, args->xml, args->flags)) == VIR_CPU_COMPARE_ERROR) - goto cleanup; - - ret->result = result; - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - - -static int -remoteDispatchCpuBaseline(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_cpu_baseline_args *args, - remote_cpu_baseline_ret *ret) -{ - char *cpu; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(cpu = virConnectBaselineCPU(conn, - (const char **) args->xmlCPUs.xmlCPUs_val, - args->xmlCPUs.xmlCPUs_len, - args->flags))) - goto cleanup; - - ret->cpu = cpu; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - - -static int remoteDispatchDomainGetJobInfo(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_bodies.c b/daemon/remote_dispatch_bodies.c index d12988e..89f0bc4 100644 --- a/daemon/remote_dispatch_bodies.c +++ b/daemon/remote_dispatch_bodies.c @@ -14,9 +14,65 @@ /* remoteDispatchClose has to be implemented manually */ -/* remoteDispatchCpuBaseline has to be implemented manually */ +static int +remoteDispatchCPUBaseline( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_cpu_baseline_args *args, + remote_cpu_baseline_ret *ret) +{ + int rv = -1; + char *cpu; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((cpu = virConnectBaselineCPU(conn, (const char **)args->xmlCPUs.xmlCPUs_val, args->xmlCPUs.xmlCPUs_len, args->flags)) == NULL) + goto cleanup; + + ret->cpu = cpu; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} + +static int +remoteDispatchCPUCompare( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_cpu_compare_args *args, + remote_cpu_compare_ret *ret) +{ + int rv = -1; + int result; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if ((result = virConnectCompareCPU(conn, args->xml, args->flags)) == VIR_CPU_COMPARE_ERROR) + goto cleanup; + + ret->result = result; + rv = 0; -/* remoteDispatchCpuCompare has to be implemented manually */ +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} static int remoteDispatchDomainAbortJob( @@ -523,7 +579,7 @@ cleanup: /* remoteDispatchDomainGetMemoryParameters has to be implemented manually */ static int -remoteDispatchDomainGetOsType( +remoteDispatchDomainGetOSType( struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 1e3be48..b6819c0 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -50,7 +50,7 @@ static int remoteDispatchClose( remote_error *rerr, void *args, void *ret); -static int remoteDispatchCpuBaseline( +static int remoteDispatchCPUBaseline( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -58,7 +58,7 @@ static int remoteDispatchCpuBaseline( remote_error *rerr, remote_cpu_baseline_args *args, remote_cpu_baseline_ret *ret); -static int remoteDispatchCpuCompare( +static int remoteDispatchCPUCompare( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -274,7 +274,7 @@ static int remoteDispatchDomainGetMemoryParameters( remote_error *rerr, remote_domain_get_memory_parameters_args *args, remote_domain_get_memory_parameters_ret *ret); -static int remoteDispatchDomainGetOsType( +static int remoteDispatchDomainGetOSType( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index 357d1de..c140341 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -97,8 +97,8 @@ .args_filter = (xdrproc_t) xdr_remote_domain_get_max_vcpus_args, .ret_filter = (xdrproc_t) xdr_remote_domain_get_max_vcpus_ret, }, -{ /* DomainGetOsType => 19 */ - .fn = (dispatch_fn) remoteDispatchDomainGetOsType, +{ /* DomainGetOSType => 19 */ + .fn = (dispatch_fn) remoteDispatchDomainGetOSType, .args_filter = (xdrproc_t) xdr_remote_domain_get_os_type_args, .ret_filter = (xdrproc_t) xdr_remote_domain_get_os_type_ret, }, @@ -792,8 +792,8 @@ .args_filter = (xdrproc_t) xdr_void, .ret_filter = (xdrproc_t) xdr_remote_get_lib_version_ret, }, -{ /* CpuCompare => 158 */ - .fn = (dispatch_fn) remoteDispatchCpuCompare, +{ /* CPUCompare => 158 */ + .fn = (dispatch_fn) remoteDispatchCPUCompare, .args_filter = (xdrproc_t) xdr_remote_cpu_compare_args, .ret_filter = (xdrproc_t) xdr_remote_cpu_compare_ret, }, @@ -812,8 +812,8 @@ .args_filter = (xdrproc_t) xdr_remote_domain_detach_device_flags_args, .ret_filter = (xdrproc_t) xdr_void, }, -{ /* CpuBaseline => 162 */ - .fn = (dispatch_fn) remoteDispatchCpuBaseline, +{ /* CPUBaseline => 162 */ + .fn = (dispatch_fn) remoteDispatchCPUBaseline, .args_filter = (xdrproc_t) xdr_remote_cpu_baseline_args, .ret_filter = (xdrproc_t) xdr_remote_cpu_baseline_ret, }, diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 585cf67..2ddfdc0 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -34,7 +34,8 @@ sub name_to_ProcName { @elems = map ucfirst, @elems; @elems = map { $_ =~ s/Nwfilter/NWFilter/; $_ =~ s/Xml/XML/; $_ =~ s/Uri/URI/; $_ =~ s/Uuid/UUID/; $_ =~ s/Id/ID/; - $_ =~ s/Mac/MAC/; $_ } @elems; + $_ =~ s/Mac/MAC/; $_ =~ s/Cpu/CPU/; $_ =~ s/Os/OS/; + $_ } @elems; join "", @elems } @@ -257,8 +258,6 @@ elsif ($opt_b) { "AuthSaslStep", "AuthPolkit", - "CpuBaseline", - "CpuCompare", "DomainBlockPeek", "DomainBlockStats", "DomainCreateWithFlags", @@ -387,6 +386,8 @@ elsif ($opt_b) { if ($calls{$_}->{ProcName} eq "SecretSetValue") { push(@args_list, "(const unsigned char *)args->$1.$1_val"); + } elsif ($calls{$_}->{ProcName} eq "CPUBaseline") { + push(@args_list, "(const char **)args->$1.$1_val"); } else { push(@args_list, "args->$1.$1_val"); } @@ -490,7 +491,12 @@ elsif ($opt_b) { $single_ret_by_ref = 1; } else { $single_ret_by_ref = 0; - $single_ret_check = " < 0"; + + if ($calls{$_}->{ProcName} eq "CPUCompare") { + $single_ret_check = " == VIR_CPU_COMPARE_ERROR"; + } else { + $single_ret_check = " < 0"; + } } } elsif ($ret_member =~ m/hyper (\S+)<(\S+)>;/) { push(@vars_list, "int len"); @@ -596,8 +602,10 @@ elsif ($opt_b) { $prefix = "Drv" } elsif ($calls{$_}->{ProcName} =~ m/^(\S+)DumpXML$/) { $proc_name = "${1}GetXMLDesc" - } elsif ($calls{$_}->{ProcName} eq "DomainGetOsType") { - $proc_name = "DomainGetOSType" + } elsif ($calls{$_}->{ProcName} eq "CPUBaseline") { + $proc_name = "ConnectBaselineCPU" + } elsif ($calls{$_}->{ProcName} eq "CPUCompare") { + $proc_name = "ConnectCompareCPU" } if ($single_ret_as_list) { -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:13:56 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:56 +0200 Subject: [libvirt] [PATCH 09/22] remote generator, daemon: Handle functions that return lists In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-10-git-send-email-matthias.bolte@googlemail.com> --- daemon/remote.c | 701 --------------------------------------- daemon/remote_dispatch_bodies.c | 681 +++++++++++++++++++++++++++++++++++++- daemon/remote_generator.pl | 111 +++++- 3 files changed, 758 insertions(+), 735 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index f42e2db..4c05567 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -531,53 +531,6 @@ cleanup: } static int -remoteDispatchNodeGetCellsFreeMemory(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_node_get_cells_free_memory_args *args, - remote_node_get_cells_free_memory_ret *ret) -{ - int len; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxCells > REMOTE_NODE_MAX_CELLS) { - virNetError(VIR_ERR_INTERNAL_ERROR, - "%s", _("maxCells > REMOTE_NODE_MAX_CELLS")); - goto cleanup; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->freeMems.freeMems_val, args->maxCells) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virNodeGetCellsFreeMemory(conn, - (unsigned long long *)ret->freeMems.freeMems_val, - args->startCell, - args->maxCells); - if (len <= 0) - goto cleanup; - ret->freeMems.freeMems_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->freeMems.freeMems_val); - } - return rv; -} - -static int remoteDispatchDomainGetSchedulerType(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -1426,51 +1379,6 @@ cleanup: } static int -remoteDispatchListDefinedDomains(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_list_defined_domains_args *args, - remote_list_defined_domains_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, - "%s", _("maxnames > REMOTE_DOMAIN_NAME_LIST_MAX")); - goto cleanup; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virConnectListDefinedDomains(conn, - ret->names.names_val, args->maxnames); - if (len < 0) - goto cleanup; - ret->names.names_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->names.names_val); - } - return rv; -} - -static int remoteDispatchDomainPinVcpu(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -1942,233 +1850,6 @@ no_memory: goto cleanup; } -static int -remoteDispatchListDefinedNetworks(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_list_defined_networks_args *args, - remote_list_defined_networks_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, - "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX")); - goto cleanup; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virConnectListDefinedNetworks(conn, - ret->names.names_val, args->maxnames); - if (len < 0) - goto cleanup; - ret->names.names_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->names.names_val); - } - return rv; -} - -static int -remoteDispatchListDomains(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_list_domains_args *args, - remote_list_domains_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxids > REMOTE_DOMAIN_ID_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, - "%s", _("maxids > REMOTE_DOMAIN_ID_LIST_MAX")); - goto cleanup; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->ids.ids_val, args->maxids) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virConnectListDomains(conn, - ret->ids.ids_val, args->maxids); - if (len < 0) - goto cleanup; - ret->ids.ids_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->ids.ids_val); - } - return rv; -} - -static int -remoteDispatchListNetworks(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_list_networks_args *args, - remote_list_networks_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, - "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX")); - goto cleanup; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virConnectListNetworks(conn, - ret->names.names_val, args->maxnames); - if (len < 0) - goto cleanup; - ret->names.names_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->names.names_val); - } - return rv; -} - -/*-------------------------------------------------------------*/ - -static int -remoteDispatchListInterfaces(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_list_interfaces_args *args, - remote_list_interfaces_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxnames > REMOTE_INTERFACE_NAME_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, - "%s", _("maxnames > REMOTE_INTERFACE_NAME_LIST_MAX")); - goto cleanup; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virConnectListInterfaces(conn, - ret->names.names_val, args->maxnames); - if (len < 0) - goto cleanup; - ret->names.names_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->names.names_val); - } - return rv; -} - -static int -remoteDispatchListDefinedInterfaces(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_list_defined_interfaces_args *args, - remote_list_defined_interfaces_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxnames > REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, - "%s", _("maxnames > REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX")); - goto cleanup; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virConnectListDefinedInterfaces(conn, - ret->names.names_val, args->maxnames); - if (len < 0) - goto cleanup; - ret->names.names_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->names.names_val); - } - return rv; -} - /*-------------------------------------------------------------*/ static int @@ -2973,97 +2654,6 @@ remoteDispatchAuthPolkit(struct qemud_server *server ATTRIBUTE_UNUSED, * STORAGE POOL APIS ***************************************************************/ - -static int -remoteDispatchListDefinedStoragePools(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_list_defined_storage_pools_args *args, - remote_list_defined_storage_pools_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", - _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX")); - goto cleanup; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virConnectListDefinedStoragePools(conn, - ret->names.names_val, args->maxnames); - if (len < 0) - goto cleanup; - ret->names.names_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->names.names_val); - } - return rv; -} - -static int -remoteDispatchListStoragePools(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_list_storage_pools_args *args, - remote_list_storage_pools_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, - "%s", _("maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX")); - goto cleanup; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virConnectListStoragePools(conn, - ret->names.names_val, args->maxnames); - if (len < 0) - goto cleanup; - ret->names.names_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->names.names_val); - } - return rv; -} - static int remoteDispatchStoragePoolGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, @@ -3103,58 +2693,6 @@ cleanup: return rv; } -static int -remoteDispatchStoragePoolListVolumes(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_list_volumes_args *args, - remote_storage_pool_list_volumes_ret *ret) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, - "%s", _("maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virStoragePoolListVolumes(pool, - ret->names.names_val, args->maxnames); - if (len < 0) - goto cleanup; - ret->names.names_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->names.names_val); - } - if (pool) - virStoragePoolFree(pool); - return rv; -} - - /*************************************************************** * STORAGE VOL APIS ***************************************************************/ @@ -3202,52 +2740,6 @@ cleanup: **************************************************************/ static int -remoteDispatchNodeListDevices(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_node_list_devices_args *args, - remote_node_list_devices_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, - "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX")); - goto cleanup; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virNodeListDevices(conn, - args->cap ? *args->cap : NULL, - ret->names.names_val, args->maxnames, args->flags); - if (len < 0) - goto cleanup; - ret->names.names_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->names.names_val); - } - return rv; -} - -static int remoteDispatchNodeDeviceGetParent(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3297,57 +2789,6 @@ cleanup: return rv; } -static int -remoteDispatchNodeDeviceListCaps(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_node_device_list_caps_args *args, - remote_node_device_list_caps_ret *ret) -{ - virNodeDevicePtr dev = NULL; - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dev = virNodeDeviceLookupByName(conn, args->name))) - goto cleanup; - - if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, - "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX")); - goto cleanup; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virNodeDeviceListCaps(dev, ret->names.names_val, - args->maxnames); - if (len < 0) - goto cleanup; - ret->names.names_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->names.names_val); - } - if (dev) - virNodeDeviceFree(dev); - return rv; -} - static int remoteDispatchStorageVolUpload(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, virConnectPtr conn, @@ -3580,50 +3021,6 @@ cleanup: } static int -remoteDispatchListSecrets(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_list_secrets_args *args, - remote_list_secrets_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxuuids > REMOTE_SECRET_UUID_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", - _("maxuuids > REMOTE_SECRET_UUID_LIST_MAX")); - goto cleanup; - } - - if (VIR_ALLOC_N(ret->uuids.uuids_val, args->maxuuids) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virConnectListSecrets(conn, ret->uuids.uuids_val, - args->maxuuids); - if (len < 0) - goto cleanup; - ret->uuids.uuids_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->uuids.uuids_val); - } - return rv; -} - -static int remoteDispatchSecretGetValue(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3773,59 +3170,6 @@ cleanup: } static int -remoteDispatchDomainSnapshotListNames(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_snapshot_list_names_args *args, - remote_domain_snapshot_list_names_ret *ret) -{ - virDomainPtr dom = NULL; - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxnames > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", - _("maxnames > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virDomainSnapshotListNames(dom, - ret->names.names_val, - args->maxnames, - args->flags); - if (len < 0) - goto cleanup; - ret->names.names_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->names.names_val); - } - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainEventsRegisterAny(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3912,51 +3256,6 @@ cleanup: } static int -remoteDispatchListNWFilters(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_list_nwfilters_args *args, - remote_list_nwfilters_ret *ret) -{ - int rv = -1; - int len; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (args->maxnames > REMOTE_NWFILTER_NAME_LIST_MAX) { - virNetError(VIR_ERR_INTERNAL_ERROR, - "%s", _("maxnames > REMOTE_NWFILTER_NAME_LIST_MAX")); - goto cleanup; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virReportOOMError(); - goto cleanup; - } - - len = virConnectListNWFilters(conn, - ret->names.names_val, args->maxnames); - if (len < 0) - goto cleanup; - ret->names.names_len = len; - - rv = 0; - -cleanup: - if (rv < 0) { - remoteDispatchError(rerr); - VIR_FREE(ret->names.names_val); - } - return rv; -} - -static int remoteDispatchDomainGetBlockInfo(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_bodies.c b/daemon/remote_dispatch_bodies.c index 77b7db4..d12988e 100644 --- a/daemon/remote_dispatch_bodies.c +++ b/daemon/remote_dispatch_bodies.c @@ -1703,7 +1703,55 @@ cleanup: return rv; } -/* remoteDispatchDomainSnapshotListNames has to be implemented manually */ +static int +remoteDispatchDomainSnapshotListNames( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_snapshot_list_names_args *args, + remote_domain_snapshot_list_names_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxnames > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxnames > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virDomainSnapshotListNames(dom, ret->names.names_val, args->maxnames, args->flags)) < 0) + goto cleanup; + + ret->names.names_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + if (rv < 0) + VIR_FREE(ret->names.names_val); + return rv; +} static int remoteDispatchDomainSnapshotLookupByName( @@ -2489,25 +2537,445 @@ cleanup: return rv; } -/* remoteDispatchListDefinedDomains has to be implemented manually */ +static int +remoteDispatchListDefinedDomains( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_list_defined_domains_args *args, + remote_list_defined_domains_ret *ret) +{ + int rv = -1; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxnames > REMOTE_DOMAIN_NAME_LIST_MAX")); + goto cleanup; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virConnectListDefinedDomains(conn, ret->names.names_val, args->maxnames)) < 0) + goto cleanup; + + ret->names.names_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (rv < 0) + VIR_FREE(ret->names.names_val); + return rv; +} + +static int +remoteDispatchListDefinedInterfaces( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_list_defined_interfaces_args *args, + remote_list_defined_interfaces_ret *ret) +{ + int rv = -1; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxnames > REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxnames > REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX")); + goto cleanup; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virConnectListDefinedInterfaces(conn, ret->names.names_val, args->maxnames)) < 0) + goto cleanup; + + ret->names.names_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (rv < 0) + VIR_FREE(ret->names.names_val); + return rv; +} + +static int +remoteDispatchListDefinedNetworks( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_list_defined_networks_args *args, + remote_list_defined_networks_ret *ret) +{ + int rv = -1; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX")); + goto cleanup; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virConnectListDefinedNetworks(conn, ret->names.names_val, args->maxnames)) < 0) + goto cleanup; + + ret->names.names_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (rv < 0) + VIR_FREE(ret->names.names_val); + return rv; +} + +static int +remoteDispatchListDefinedStoragePools( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_list_defined_storage_pools_args *args, + remote_list_defined_storage_pools_ret *ret) +{ + int rv = -1; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX")); + goto cleanup; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virConnectListDefinedStoragePools(conn, ret->names.names_val, args->maxnames)) < 0) + goto cleanup; + + ret->names.names_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (rv < 0) + VIR_FREE(ret->names.names_val); + return rv; +} + +static int +remoteDispatchListDomains( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_list_domains_args *args, + remote_list_domains_ret *ret) +{ + int rv = -1; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxids > REMOTE_DOMAIN_ID_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxids > REMOTE_DOMAIN_ID_LIST_MAX")); + goto cleanup; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->ids.ids_val, args->maxids) < 0) { + virReportOOMError(); + goto cleanup; + } -/* remoteDispatchListDefinedInterfaces has to be implemented manually */ + if ((len = virConnectListDomains(conn, ret->ids.ids_val, args->maxids)) < 0) + goto cleanup; -/* remoteDispatchListDefinedNetworks has to be implemented manually */ + ret->ids.ids_len = len; + rv = 0; -/* remoteDispatchListDefinedStoragePools has to be implemented manually */ +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (rv < 0) + VIR_FREE(ret->ids.ids_val); + return rv; +} -/* remoteDispatchListDomains has to be implemented manually */ +static int +remoteDispatchListInterfaces( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_list_interfaces_args *args, + remote_list_interfaces_ret *ret) +{ + int rv = -1; + int len; -/* remoteDispatchListInterfaces has to be implemented manually */ + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } -/* remoteDispatchListNetworks has to be implemented manually */ + if (args->maxnames > REMOTE_INTERFACE_NAME_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxnames > REMOTE_INTERFACE_NAME_LIST_MAX")); + goto cleanup; + } -/* remoteDispatchListNWFilters has to be implemented manually */ + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virReportOOMError(); + goto cleanup; + } -/* remoteDispatchListSecrets has to be implemented manually */ + if ((len = virConnectListInterfaces(conn, ret->names.names_val, args->maxnames)) < 0) + goto cleanup; -/* remoteDispatchListStoragePools has to be implemented manually */ + ret->names.names_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (rv < 0) + VIR_FREE(ret->names.names_val); + return rv; +} + +static int +remoteDispatchListNetworks( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_list_networks_args *args, + remote_list_networks_ret *ret) +{ + int rv = -1; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX")); + goto cleanup; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virConnectListNetworks(conn, ret->names.names_val, args->maxnames)) < 0) + goto cleanup; + + ret->names.names_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (rv < 0) + VIR_FREE(ret->names.names_val); + return rv; +} + +static int +remoteDispatchListNWFilters( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_list_nwfilters_args *args, + remote_list_nwfilters_ret *ret) +{ + int rv = -1; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxnames > REMOTE_NWFILTER_NAME_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxnames > REMOTE_NWFILTER_NAME_LIST_MAX")); + goto cleanup; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virConnectListNWFilters(conn, ret->names.names_val, args->maxnames)) < 0) + goto cleanup; + + ret->names.names_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (rv < 0) + VIR_FREE(ret->names.names_val); + return rv; +} + +static int +remoteDispatchListSecrets( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_list_secrets_args *args, + remote_list_secrets_ret *ret) +{ + int rv = -1; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxuuids > REMOTE_SECRET_UUID_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxuuids > REMOTE_SECRET_UUID_LIST_MAX")); + goto cleanup; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->uuids.uuids_val, args->maxuuids) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virConnectListSecrets(conn, ret->uuids.uuids_val, args->maxuuids)) < 0) + goto cleanup; + + ret->uuids.uuids_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (rv < 0) + VIR_FREE(ret->uuids.uuids_val); + return rv; +} + +static int +remoteDispatchListStoragePools( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_list_storage_pools_args *args, + remote_list_storage_pools_ret *ret) +{ + int rv = -1; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX")); + goto cleanup; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virConnectListStoragePools(conn, ret->names.names_val, args->maxnames)) < 0) + goto cleanup; + + ret->names.names_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (rv < 0) + VIR_FREE(ret->names.names_val); + return rv; +} static int remoteDispatchNetworkCreate( @@ -3091,7 +3559,55 @@ cleanup: /* remoteDispatchNodeDeviceGetParent has to be implemented manually */ -/* remoteDispatchNodeDeviceListCaps has to be implemented manually */ +static int +remoteDispatchNodeDeviceListCaps( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_device_list_caps_args *args, + remote_node_device_list_caps_ret *ret) +{ + int rv = -1; + virNodeDevicePtr dev = NULL; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxnames > REMOTE_NODE_DEVICE_CAPS_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxnames > REMOTE_NODE_DEVICE_CAPS_LIST_MAX")); + goto cleanup; + } + + if (!(dev = virNodeDeviceLookupByName(conn, args->name))) + goto cleanup; + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virNodeDeviceListCaps(dev, ret->names.names_val, args->maxnames)) < 0) + goto cleanup; + + ret->names.names_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dev) + virNodeDeviceFree(dev); + if (rv < 0) + VIR_FREE(ret->names.names_val); + return rv; +} static int remoteDispatchNodeDeviceLookupByName( @@ -3229,7 +3745,49 @@ cleanup: return rv; } -/* remoteDispatchNodeGetCellsFreeMemory has to be implemented manually */ +static int +remoteDispatchNodeGetCellsFreeMemory( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_get_cells_free_memory_args *args, + remote_node_get_cells_free_memory_ret *ret) +{ + int rv = -1; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxCells > REMOTE_NODE_MAX_CELLS) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxfreeMems > REMOTE_NODE_MAX_CELLS")); + goto cleanup; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->freeMems.freeMems_val, args->maxCells) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virNodeGetCellsFreeMemory(conn, (unsigned long long *)ret->freeMems.freeMems_val, args->startCell, args->maxCells)) <= 0) + goto cleanup; + + ret->freeMems.freeMems_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (rv < 0) + VIR_FREE(ret->freeMems.freeMems_val); + return rv; +} static int remoteDispatchNodeGetFreeMemory( @@ -3265,7 +3823,52 @@ cleanup: /* remoteDispatchNodeGetSecurityModel has to be implemented manually */ -/* remoteDispatchNodeListDevices has to be implemented manually */ +static int +remoteDispatchNodeListDevices( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_list_devices_args *args, + remote_node_list_devices_ret *ret) +{ + int rv = -1; + char *cap; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX")); + goto cleanup; + } + + cap = args->cap ? *args->cap : NULL; + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virNodeListDevices(conn, cap, ret->names.names_val, args->maxnames, args->flags)) < 0) + goto cleanup; + + ret->names.names_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (rv < 0) + VIR_FREE(ret->names.names_val); + return rv; +} static int remoteDispatchNodeNumOfDevices( @@ -4316,7 +4919,55 @@ cleanup: return rv; } -/* remoteDispatchStoragePoolListVolumes has to be implemented manually */ +static int +remoteDispatchStoragePoolListVolumes( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_list_volumes_args *args, + remote_storage_pool_list_volumes_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + int len; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, + "%s", _("maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virStoragePoolListVolumes(pool, ret->names.names_val, args->maxnames)) < 0) + goto cleanup; + + ret->names.names_len = len; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + if (rv < 0) + VIR_FREE(ret->names.names_val); + return rv; +} static int remoteDispatchStoragePoolLookupByName( diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index b3cb9b5..e9a60bc 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -278,27 +278,12 @@ elsif ($opt_b) { "DomainMemoryStats", "DomainMigratePrepare", "DomainMigratePrepare2", - "DomainSnapshotListNames", "GetType", - "ListDefinedDomains", - "ListDefinedInterfaces", - "ListDefinedNetworks", - "ListDefinedStoragePools", - "ListDomains", - "ListInterfaces", - "ListNetworks", - "ListNWFilters", - "ListSecrets", - "ListStoragePools", "NodeDeviceGetParent", - "NodeDeviceListCaps", - "NodeGetCellsFreeMemory", "NodeGetInfo", "NodeGetSecurityModel", - "NodeListDevices", "SecretGetValue", "StoragePoolGetInfo", - "StoragePoolListVolumes", "StorageVolGetInfo"); } elsif ($structprefix eq "qemu") { @ungeneratable = ("MonitorCommand"); @@ -480,12 +465,38 @@ elsif ($opt_b) { my $single_ret_var = "undefined"; my $single_ret_by_ref = 0; my $single_ret_check = " == undefined"; + my $single_ret_as_list = 0; + my $single_ret_list_name = "undefined"; + my $single_ret_list_max_var = "undefined"; + my $single_ret_list_max_define = "undefined"; if ($calls{$_}->{ret} ne "void") { foreach my $ret_member (@{$calls{$_}->{ret_members}}) { - if ($ret_member =~ m/(\S+)<\S+>;/) { - push(@ret_list, "ret->$1.$1_val"); - push(@ret_list, "ret->$1.$1_len"); + if ($ret_member =~ m/remote_nonnull_string (\S+)<(\S+)>;/) { + push(@vars_list, "int len"); + push(@ret_list, "ret->$1.$1_len = len;"); + push(@free_list, + " if (rv < 0)\n" . + " VIR_FREE(ret->$1.$1_val);"); + $single_ret_var = "len"; + $single_ret_by_ref = 0; + $single_ret_check = " < 0"; + $single_ret_as_list = 1; + $single_ret_list_name = $1; + $single_ret_list_max_var = "max$1"; + $single_ret_list_max_define = $2; + + if ($calls{$_}->{ProcName} eq "NodeListDevices") { + my $conn = shift(@args_list); + my $cap = shift(@args_list); + unshift(@args_list, "ret->$1.$1_val"); + unshift(@args_list, $cap); + unshift(@args_list, $conn); + } else { + my $conn = shift(@args_list); + unshift(@args_list, "ret->$1.$1_val"); + unshift(@args_list, $conn); + } } elsif ($ret_member =~ m/remote_nonnull_string (\S+);/) { push(@vars_list, "char *$1"); push(@ret_list, "ret->$1 = $1;"); @@ -573,6 +584,23 @@ elsif ($opt_b) { $single_ret_var = $1; $single_ret_by_ref = 0; $single_ret_check = " == NULL"; + } elsif ($ret_member =~ m/int (\S+)<(\S+)>;/) { + push(@vars_list, "int len"); + push(@ret_list, "ret->$1.$1_len = len;"); + push(@free_list, + " if (rv < 0)\n" . + " VIR_FREE(ret->$1.$1_val);"); + $single_ret_var = "len"; + $single_ret_by_ref = 0; + $single_ret_check = " < 0"; + $single_ret_as_list = 1; + $single_ret_list_name = $1; + $single_ret_list_max_var = "max$1"; + $single_ret_list_max_define = $2; + + my $conn = shift(@args_list); + unshift(@args_list, "ret->$1.$1_val"); + unshift(@args_list, $conn); } elsif ($ret_member =~ m/int (\S+);/) { push(@vars_list, "int $1"); push(@ret_list, "ret->$1 = $1;"); @@ -586,6 +614,31 @@ elsif ($opt_b) { $single_ret_by_ref = 0; $single_ret_check = " < 0"; } + } elsif ($ret_member =~ m/hyper (\S+)<(\S+)>;/) { + push(@vars_list, "int len"); + push(@ret_list, "ret->$1.$1_len = len;"); + push(@free_list, + " if (rv < 0)\n" . + " VIR_FREE(ret->$1.$1_val);"); + $single_ret_var = "len"; + $single_ret_by_ref = 0; + $single_ret_as_list = 1; + $single_ret_list_name = $1; + $single_ret_list_max_define = $2; + + my $conn = shift(@args_list); + + if ($calls{$_}->{ProcName} eq "NodeGetCellsFreeMemory") { + $single_ret_check = " <= 0"; + $single_ret_list_max_var = "maxCells"; + unshift(@args_list, "(unsigned long long *)ret->$1.$1_val"); + } else { + $single_ret_check = " < 0"; + $single_ret_list_max_var = "max$1"; + unshift(@args_list, "ret->$1.$1_val"); + } + + unshift(@args_list, $conn); } elsif ($ret_member =~ m/hyper (\S+);/) { push(@vars_list, "unsigned long $1"); push(@ret_list, "ret->$1 = $1;"); @@ -613,6 +666,15 @@ elsif ($opt_b) { print " }\n"; print "\n"; + if ($single_ret_as_list) { + print " if (args->$single_ret_list_max_var > $single_ret_list_max_define) {\n"; + print " virNetError(VIR_ERR_INTERNAL_ERROR,\n"; + print " \"%s\", _(\"max$single_ret_list_name > $single_ret_list_max_define\"));\n"; + print " goto cleanup;\n"; + print " }\n"; + print "\n"; + } + print join("\n", @getters_list); if (@getters_list) { @@ -649,7 +711,8 @@ elsif ($opt_b) { $calls{$_}->{ProcName} eq "GetMaxVcpus" or $calls{$_}->{ProcName} eq "DomainXMLFromNative" or $calls{$_}->{ProcName} eq "DomainXMLToNative" or - $calls{$_}->{ProcName} eq "FindStoragePoolSources") { + $calls{$_}->{ProcName} eq "FindStoragePoolSources" or + $calls{$_}->{ProcName} =~ m/^List/) { $prefix = "Connect" } elsif ($calls{$_}->{ProcName} eq "SupportsFeature") { $prefix = "Drv" @@ -669,6 +732,16 @@ elsif ($opt_b) { $proc_name = "DomainGetOSType" } + if ($single_ret_as_list) { + print " /* Allocate return buffer. */\n"; + print " if (VIR_ALLOC_N(ret->$single_ret_list_name.${single_ret_list_name}_val," . + " args->$single_ret_list_max_var) < 0) {\n"; + print " virReportOOMError();\n"; + print " goto cleanup;\n"; + print " }\n"; + print "\n"; + } + if ($single_ret_by_ref) { print " if (vir$prefix$proc_name("; print join(', ', @args_list); -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:13:59 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:59 +0200 Subject: [libvirt] [PATCH 12/22] remote generator, daemon: Combine multiple ifs in the generated code In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-13-git-send-email-matthias.bolte@googlemail.com> --- daemon/remote_dispatch_bodies.c | 66 +++++++++++++++++++------------------- daemon/remote_generator.pl | 28 ++++++++++------ 2 files changed, 50 insertions(+), 44 deletions(-) diff --git a/daemon/remote_dispatch_bodies.c b/daemon/remote_dispatch_bodies.c index 89f0bc4..50432f9 100644 --- a/daemon/remote_dispatch_bodies.c +++ b/daemon/remote_dispatch_bodies.c @@ -1800,12 +1800,12 @@ remoteDispatchDomainSnapshotListNames( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); + VIR_FREE(ret->names.names_val); + } if (dom) virDomainFree(dom); - if (rv < 0) - VIR_FREE(ret->names.names_val); return rv; } @@ -2630,10 +2630,10 @@ remoteDispatchListDefinedDomains( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); - if (rv < 0) VIR_FREE(ret->names.names_val); + } return rv; } @@ -2674,10 +2674,10 @@ remoteDispatchListDefinedInterfaces( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); - if (rv < 0) VIR_FREE(ret->names.names_val); + } return rv; } @@ -2718,10 +2718,10 @@ remoteDispatchListDefinedNetworks( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); - if (rv < 0) VIR_FREE(ret->names.names_val); + } return rv; } @@ -2762,10 +2762,10 @@ remoteDispatchListDefinedStoragePools( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); - if (rv < 0) VIR_FREE(ret->names.names_val); + } return rv; } @@ -2806,10 +2806,10 @@ remoteDispatchListDomains( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); - if (rv < 0) VIR_FREE(ret->ids.ids_val); + } return rv; } @@ -2850,10 +2850,10 @@ remoteDispatchListInterfaces( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); - if (rv < 0) VIR_FREE(ret->names.names_val); + } return rv; } @@ -2894,10 +2894,10 @@ remoteDispatchListNetworks( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); - if (rv < 0) VIR_FREE(ret->names.names_val); + } return rv; } @@ -2938,10 +2938,10 @@ remoteDispatchListNWFilters( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); - if (rv < 0) VIR_FREE(ret->names.names_val); + } return rv; } @@ -2982,10 +2982,10 @@ remoteDispatchListSecrets( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); - if (rv < 0) VIR_FREE(ret->uuids.uuids_val); + } return rv; } @@ -3026,10 +3026,10 @@ remoteDispatchListStoragePools( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); - if (rv < 0) VIR_FREE(ret->names.names_val); + } return rv; } @@ -3656,12 +3656,12 @@ remoteDispatchNodeDeviceListCaps( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); + VIR_FREE(ret->names.names_val); + } if (dev) virNodeDeviceFree(dev); - if (rv < 0) - VIR_FREE(ret->names.names_val); return rv; } @@ -3838,10 +3838,10 @@ remoteDispatchNodeGetCellsFreeMemory( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); - if (rv < 0) VIR_FREE(ret->freeMems.freeMems_val); + } return rv; } @@ -3919,10 +3919,10 @@ remoteDispatchNodeListDevices( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); - if (rv < 0) VIR_FREE(ret->names.names_val); + } return rv; } @@ -5016,12 +5016,12 @@ remoteDispatchStoragePoolListVolumes( rv = 0; cleanup: - if (rv < 0) + if (rv < 0) { remoteDispatchError(rerr); + VIR_FREE(ret->names.names_val); + } if (pool) virStoragePoolFree(pool); - if (rv < 0) - VIR_FREE(ret->names.names_val); return rv; } diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 2ddfdc0..1fd4627 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -332,6 +332,7 @@ elsif ($opt_b) { my @args_list = (); my @ret_list = (); my @free_list = (); + my @free_list_on_error = ("remoteDispatchError(rerr);"); if ($calls{$_}->{args} ne "void") { # node device is special, as it's identified by name @@ -424,9 +425,7 @@ elsif ($opt_b) { if ($ret_member =~ m/remote_nonnull_string (\S+)<(\S+)>;/) { push(@vars_list, "int len"); push(@ret_list, "ret->$1.$1_len = len;"); - push(@free_list, - " if (rv < 0)\n" . - " VIR_FREE(ret->$1.$1_val);"); + push(@free_list_on_error, "VIR_FREE(ret->$1.$1_val);"); $single_ret_var = "len"; $single_ret_by_ref = 0; $single_ret_check = " < 0"; @@ -466,9 +465,7 @@ elsif ($opt_b) { } elsif ($ret_member =~ m/int (\S+)<(\S+)>;/) { push(@vars_list, "int len"); push(@ret_list, "ret->$1.$1_len = len;"); - push(@free_list, - " if (rv < 0)\n" . - " VIR_FREE(ret->$1.$1_val);"); + push(@free_list_on_error, "VIR_FREE(ret->$1.$1_val);"); $single_ret_var = "len"; $single_ret_by_ref = 0; $single_ret_check = " < 0"; @@ -501,9 +498,7 @@ elsif ($opt_b) { } elsif ($ret_member =~ m/hyper (\S+)<(\S+)>;/) { push(@vars_list, "int len"); push(@ret_list, "ret->$1.$1_len = len;"); - push(@free_list, - " if (rv < 0)\n" . - " VIR_FREE(ret->$1.$1_val);"); + push(@free_list_on_error, "VIR_FREE(ret->$1.$1_val);"); $single_ret_var = "len"; $single_ret_by_ref = 0; $single_ret_as_list = 1; @@ -642,8 +637,19 @@ elsif ($opt_b) { print " rv = 0;\n"; print "\n"; print "cleanup:\n"; - print " if (rv < 0)\n"; - print " remoteDispatchError(rerr);\n"; + print " if (rv < 0)"; + + if (scalar(@free_list_on_error) > 1) { + print " {"; + } + + print "\n "; + print join("\n ", @free_list_on_error); + print "\n"; + + if (scalar(@free_list_on_error) > 1) { + print " }\n"; + } print join("\n", @free_list); -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:13:57 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:57 +0200 Subject: [libvirt] [PATCH 10/22] remote generator: Refactor duplicate code In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-11-git-send-email-matthias.bolte@googlemail.com> --- daemon/remote_generator.pl | 168 +++++--------------------------------------- 1 files changed, 18 insertions(+), 150 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index e9a60bc..585cf67 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -354,69 +354,17 @@ elsif ($opt_b) { if ($args_member =~ m/^remote_nonnull_string name;/ and $has_node_device) { # ignore the name arg for node devices next - } elsif ($args_member =~ m/^remote_nonnull_domain (\S+);/) { - push(@vars_list, "virDomainPtr $1 = NULL"); - push(@getters_list, - " if (!($1 = get_nonnull_domain(conn, args->$1)))\n" . - " goto cleanup;\n"); - push(@args_list, "$1"); - push(@free_list, - " if ($1)\n" . - " virDomainFree($1);"); - } elsif ($args_member =~ m/^remote_nonnull_network (\S+);/) { - push(@vars_list, "virNetworkPtr $1 = NULL"); - push(@getters_list, - " if (!($1 = get_nonnull_network(conn, args->$1)))\n" . - " goto cleanup;\n"); - push(@args_list, "$1"); - push(@free_list, - " if ($1)\n" . - " virNetworkFree($1);"); - } elsif ($args_member =~ m/^remote_nonnull_storage_pool (\S+);/) { - push(@vars_list, "virStoragePoolPtr $1 = NULL"); - push(@getters_list, - " if (!($1 = get_nonnull_storage_pool(conn, args->$1)))\n" . - " goto cleanup;\n"); - push(@args_list, "$1"); - push(@free_list, - " if ($1)\n" . - " virStoragePoolFree($1);"); - } elsif ($args_member =~ m/^remote_nonnull_storage_vol (\S+);/) { - push(@vars_list, "virStorageVolPtr $1 = NULL"); - push(@getters_list, - " if (!($1 = get_nonnull_storage_vol(conn, args->$1)))\n" . - " goto cleanup;\n"); - push(@args_list, "$1"); - push(@free_list, - " if ($1)\n" . - " virStorageVolFree($1);"); - } elsif ($args_member =~ m/^remote_nonnull_interface (\S+);/) { - push(@vars_list, "virInterfacePtr $1 = NULL"); - push(@getters_list, - " if (!($1 = get_nonnull_interface(conn, args->$1)))\n" . - " goto cleanup;\n"); - push(@args_list, "$1"); - push(@free_list, - " if ($1)\n" . - " virInterfaceFree($1);"); - } elsif ($args_member =~ m/^remote_nonnull_secret (\S+);/) { - push(@vars_list, "virSecretPtr $1 = NULL"); - push(@getters_list, - " if (!($1 = get_nonnull_secret(conn, args->$1)))\n" . - " goto cleanup;\n"); - push(@args_list, "$1"); - push(@free_list, - " if ($1)\n" . - " virSecretFree($1);"); - } elsif ($args_member =~ m/^remote_nonnull_nwfilter (\S+);/) { - push(@vars_list, "virNWFilterPtr $1 = NULL"); + } elsif ($args_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|secret|nwfilter) (\S+);/) { + my $type_name = name_to_ProcName($1); + + push(@vars_list, "vir${type_name}Ptr $2 = NULL"); push(@getters_list, - " if (!($1 = get_nonnull_nwfilter(conn, args->$1)))\n" . + " if (!($2 = get_nonnull_$1(conn, args->$2)))\n" . " goto cleanup;\n"); - push(@args_list, "$1"); + push(@args_list, "$2"); push(@free_list, - " if ($1)\n" . - " virNWFilterFree($1);"); + " if ($2)\n" . + " vir${type_name}Free($2);"); } elsif ($args_member =~ m/^remote_nonnull_domain_snapshot /) { push(@vars_list, "virDomainPtr dom = NULL"); push(@vars_list, "virDomainSnapshotPtr snapshot = NULL"); @@ -503,85 +451,15 @@ elsif ($opt_b) { $single_ret_var = $1; $single_ret_by_ref = 0; $single_ret_check = " == NULL"; - } elsif ($ret_member =~ m/remote_nonnull_domain (\S+);/) { - push(@vars_list, "virDomainPtr $1 = NULL"); - push(@ret_list, "make_nonnull_domain(&ret->$1, $1);"); - push(@free_list, - " if ($1)\n" . - " virDomainFree($1);"); - $single_ret_var = $1; - $single_ret_by_ref = 0; - $single_ret_check = " == NULL"; - } elsif ($ret_member =~ m/remote_nonnull_network (\S+);/) { - push(@vars_list, "virNetworkPtr $1 = NULL"); - push(@ret_list, "make_nonnull_network(&ret->$1, $1);"); - push(@free_list, - " if ($1)\n" . - " virNetworkFree($1);"); - $single_ret_var = $1; - $single_ret_by_ref = 0; - $single_ret_check = " == NULL"; - } elsif ($ret_member =~ m/remote_nonnull_storage_pool (\S+);/) { - push(@vars_list, "virStoragePoolPtr $1 = NULL"); - push(@ret_list, "make_nonnull_storage_pool(&ret->$1, $1);"); - push(@free_list, - " if ($1)\n" . - " virStoragePoolFree($1);"); - $single_ret_var = $1; - $single_ret_by_ref = 0; - $single_ret_check = " == NULL"; - } elsif ($ret_member =~ m/remote_nonnull_storage_vol (\S+);/) { - push(@vars_list, "virStorageVolPtr $1 = NULL"); - push(@ret_list, "make_nonnull_storage_vol(&ret->$1, $1);"); - push(@free_list, - " if ($1)\n" . - " virStorageVolFree($1);"); - $single_ret_var = $1; - $single_ret_by_ref = 0; - $single_ret_check = " == NULL"; - } elsif ($ret_member =~ m/remote_nonnull_interface (\S+);/) { - push(@vars_list, "virInterfacePtr $1 = NULL"); - push(@ret_list, "make_nonnull_interface(&ret->$1, $1);"); - push(@free_list, - " if ($1)\n" . - " virInterfaceFree($1);"); - $single_ret_var = $1; - $single_ret_by_ref = 0; - $single_ret_check = " == NULL"; - } elsif ($ret_member =~ m/remote_nonnull_node_device (\S+);/) { - push(@vars_list, "virNodeDevicePtr $1 = NULL"); - push(@ret_list, "make_nonnull_node_device(&ret->$1, $1);"); - push(@free_list, - " if ($1)\n" . - " virNodeDeviceFree($1);"); - $single_ret_var = $1; - $single_ret_by_ref = 0; - $single_ret_check = " == NULL"; - } elsif ($ret_member =~ m/remote_nonnull_secret (\S+);/) { - push(@vars_list, "virSecretPtr $1 = NULL"); - push(@ret_list, "make_nonnull_secret(&ret->$1, $1);"); - push(@free_list, - " if ($1)\n" . - " virSecretFree($1);"); - $single_ret_var = $1; - $single_ret_by_ref = 0; - $single_ret_check = " == NULL"; - } elsif ($ret_member =~ m/remote_nonnull_nwfilter (\S+);/) { - push(@vars_list, "virNWFilterPtr $1 = NULL"); - push(@ret_list, "make_nonnull_nwfilter(&ret->$1, $1);"); - push(@free_list, - " if ($1)\n" . - " virNWFilterFree($1);"); - $single_ret_var = $1; - $single_ret_by_ref = 0; - $single_ret_check = " == NULL"; - } elsif ($ret_member =~ m/remote_nonnull_domain_snapshot (\S+);/) { - push(@vars_list, "virDomainSnapshotPtr $1 = NULL"); - push(@ret_list, "make_nonnull_domain_snapshot(&ret->$1, $1);"); + } elsif ($ret_member =~ m/remote_nonnull_(domain|network|storage_pool|storage_vol|interface|node_device|secret|nwfilter|domain_snapshot) (\S+);/) { + my $type_name = name_to_ProcName($1); + + push(@vars_list, "vir${type_name}Ptr $2 = NULL"); + push(@ret_list, "make_nonnull_$1(&ret->$2, $2);"); push(@free_list, - " if ($1)\n" . - " virDomainSnapshotFree($1);"); - $single_ret_var = $1; + " if ($2)\n" . + " vir${type_name}Free($2);"); + $single_ret_var = $2; $single_ret_by_ref = 0; $single_ret_check = " == NULL"; } elsif ($ret_member =~ m/int (\S+)<(\S+)>;/) { @@ -716,18 +594,8 @@ elsif ($opt_b) { $prefix = "Connect" } elsif ($calls{$_}->{ProcName} eq "SupportsFeature") { $prefix = "Drv" - } elsif ($calls{$_}->{ProcName} eq "DomainDumpXML") { - $proc_name = "DomainGetXMLDesc" - } elsif ($calls{$_}->{ProcName} eq "NetworkDumpXML") { - $proc_name = "NetworkGetXMLDesc" - } elsif ($calls{$_}->{ProcName} eq "StoragePoolDumpXML") { - $proc_name = "StoragePoolGetXMLDesc" - } elsif ($calls{$_}->{ProcName} eq "StorageVolDumpXML") { - $proc_name = "StorageVolGetXMLDesc" - } elsif ($calls{$_}->{ProcName} eq "NodeDeviceDumpXML") { - $proc_name = "NodeDeviceGetXMLDesc" - } elsif ($calls{$_}->{ProcName} eq "DomainSnapshotDumpXML") { - $proc_name = "DomainSnapshotGetXMLDesc" + } elsif ($calls{$_}->{ProcName} =~ m/^(\S+)DumpXML$/) { + $proc_name = "${1}GetXMLDesc" } elsif ($calls{$_}->{ProcName} eq "DomainGetOsType") { $proc_name = "DomainGetOSType" } -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:14:00 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:14:00 +0200 Subject: [libvirt] [PATCH 13/22] remote generator, daemon: Handle functions with multiple return values In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-14-git-send-email-matthias.bolte@googlemail.com> Once again rename members in the XDR definitions to avoid special case code in the generator. --- daemon/remote.c | 334 --------------------------------------- daemon/remote_dispatch_bodies.c | 322 ++++++++++++++++++++++++++++++++++++- daemon/remote_generator.pl | 80 ++++++++-- src/remote/remote_driver.c | 6 +- src/remote/remote_protocol.c | 6 +- src/remote/remote_protocol.h | 6 +- src/remote/remote_protocol.x | 6 +- src/remote_protocol-structs | 6 +- 8 files changed, 397 insertions(+), 369 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index f70c445..e0fb1f8 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -494,43 +494,6 @@ cleanup: } static int -remoteDispatchNodeGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - void *args ATTRIBUTE_UNUSED, - remote_node_get_info_ret *ret) -{ - virNodeInfo info; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (virNodeGetInfo(conn, &info) < 0) - goto cleanup; - - memcpy(ret->model, info.model, sizeof ret->model); - ret->memory = info.memory; - ret->cpus = info.cpus; - ret->mhz = info.mhz; - ret->nodes = info.nodes; - ret->sockets = info.sockets; - ret->cores = info.cores; - ret->threads = info.threads; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int remoteDispatchDomainGetSchedulerType(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -722,93 +685,6 @@ cleanup: } static int -remoteDispatchDomainBlockStats(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_block_stats_args *args, - remote_domain_block_stats_ret *ret) -{ - virDomainPtr dom = NULL; - char *path; - struct _virDomainBlockStats stats; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - path = args->path; - - if (virDomainBlockStats(dom, path, &stats, sizeof stats) < 0) - goto cleanup; - - ret->rd_req = stats.rd_req; - ret->rd_bytes = stats.rd_bytes; - ret->wr_req = stats.wr_req; - ret->wr_bytes = stats.wr_bytes; - ret->errs = stats.errs; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainInterfaceStats(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_interface_stats_args *args, - remote_domain_interface_stats_ret *ret) -{ - virDomainPtr dom = NULL; - char *path; - struct _virDomainInterfaceStats stats; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - path = args->path; - - if (virDomainInterfaceStats(dom, path, &stats, sizeof stats) < 0) - goto cleanup; - - ret->rx_bytes = stats.rx_bytes; - ret->rx_packets = stats.rx_packets; - ret->rx_errs = stats.rx_errs; - ret->rx_drop = stats.rx_drop; - ret->tx_bytes = stats.tx_bytes; - ret->tx_packets = stats.tx_packets; - ret->tx_errs = stats.tx_errs; - ret->tx_drop = stats.tx_drop; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainMemoryStats(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -1012,46 +888,6 @@ cleanup: } static int -remoteDispatchDomainGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_get_info_args *args, - remote_domain_get_info_ret *ret) -{ - virDomainPtr dom = NULL; - virDomainInfo info; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainGetInfo(dom, &info) < 0) - goto cleanup; - - ret->state = info.state; - ret->max_mem = info.maxMem; - ret->memory = info.memory; - ret->nr_virt_cpu = info.nrVirtCpu; - ret->cpu_time = info.cpuTime; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainGetSecurityLabel(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -2651,91 +2487,6 @@ remoteDispatchAuthPolkit(struct qemud_server *server ATTRIBUTE_UNUSED, /*************************************************************** - * STORAGE POOL APIS - ***************************************************************/ - -static int -remoteDispatchStoragePoolGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_get_info_args *args, - remote_storage_pool_get_info_ret *ret) -{ - virStoragePoolPtr pool = NULL; - virStoragePoolInfo info; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if (virStoragePoolGetInfo(pool, &info) < 0) - goto cleanup; - - ret->state = info.state; - ret->capacity = info.capacity; - ret->allocation = info.allocation; - ret->available = info.available; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -/*************************************************************** - * STORAGE VOL APIS - ***************************************************************/ - -static int -remoteDispatchStorageVolGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_vol_get_info_args *args, - remote_storage_vol_get_info_ret *ret) -{ - virStorageVolPtr vol = NULL; - virStorageVolInfo info; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(vol = get_nonnull_storage_vol(conn, args->vol))) - goto cleanup; - - if (virStorageVolGetInfo(vol, &info) < 0) - goto cleanup; - - ret->type = info.type; - ret->capacity = info.capacity; - ret->allocation = info.allocation; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (vol) - virStorageVolFree(vol); - return rv; -} - -/*************************************************************** * NODE INFO APIS **************************************************************/ @@ -3059,53 +2810,6 @@ cleanup: } static int -remoteDispatchDomainGetJobInfo(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_get_job_info_args *args, - remote_domain_get_job_info_ret *ret) -{ - virDomainPtr dom = NULL; - virDomainJobInfo info; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainGetJobInfo(dom, &info) < 0) - goto cleanup; - - ret->type = info.type; - ret->timeElapsed = info.timeElapsed; - ret->timeRemaining = info.timeRemaining; - ret->dataTotal = info.dataTotal; - ret->dataProcessed = info.dataProcessed; - ret->dataRemaining = info.dataRemaining; - ret->memTotal = info.memTotal; - ret->memProcessed = info.memProcessed; - ret->memRemaining = info.memRemaining; - ret->fileTotal = info.fileTotal; - ret->fileProcessed = info.fileProcessed; - ret->fileRemaining = info.fileRemaining; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainEventsRegisterAny(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3192,44 +2896,6 @@ cleanup: } static int -remoteDispatchDomainGetBlockInfo(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_get_block_info_args *args, - remote_domain_get_block_info_ret *ret) -{ - virDomainPtr dom = NULL; - virDomainBlockInfo info; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainGetBlockInfo(dom, args->path, &info, args->flags) < 0) - goto cleanup; - - ret->capacity = info.capacity; - ret->allocation = info.allocation; - ret->physical = info.physical; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int qemuDispatchMonitorCommand(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_bodies.c b/daemon/remote_dispatch_bodies.c index 50432f9..43bfc6d 100644 --- a/daemon/remote_dispatch_bodies.c +++ b/daemon/remote_dispatch_bodies.c @@ -178,7 +178,45 @@ cleanup: /* remoteDispatchDomainBlockPeek has to be implemented manually */ -/* remoteDispatchDomainBlockStats has to be implemented manually */ +static int +remoteDispatchDomainBlockStats( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_block_stats_args *args, + remote_domain_block_stats_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + virDomainBlockStatsStruct tmp; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainBlockStats(dom, args->path, &tmp, sizeof tmp) < 0) + goto cleanup; + + ret->rd_req = tmp.rd_req; + ret->rd_bytes = tmp.rd_bytes; + ret->wr_req = tmp.wr_req; + ret->wr_bytes = tmp.wr_bytes; + ret->errs = tmp.errs; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} static int remoteDispatchDomainCoreDump( @@ -498,11 +536,130 @@ cleanup: /* remoteDispatchDomainGetBlkioParameters has to be implemented manually */ -/* remoteDispatchDomainGetBlockInfo has to be implemented manually */ +static int +remoteDispatchDomainGetBlockInfo( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_get_block_info_args *args, + remote_domain_get_block_info_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + virDomainBlockInfo tmp; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainGetBlockInfo(dom, args->path, &tmp, args->flags) < 0) + goto cleanup; + + ret->allocation = tmp.allocation; + ret->capacity = tmp.capacity; + ret->physical = tmp.physical; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainGetInfo( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_get_info_args *args, + remote_domain_get_info_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + virDomainInfo tmp; -/* remoteDispatchDomainGetInfo has to be implemented manually */ + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } -/* remoteDispatchDomainGetJobInfo has to be implemented manually */ + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainGetInfo(dom, &tmp) < 0) + goto cleanup; + + ret->state = tmp.state; + ret->maxMem = tmp.maxMem; + ret->memory = tmp.memory; + ret->nrVirtCpu = tmp.nrVirtCpu; + ret->cpuTime = tmp.cpuTime; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainGetJobInfo( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_get_job_info_args *args, + remote_domain_get_job_info_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + virDomainJobInfo tmp; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainGetJobInfo(dom, &tmp) < 0) + goto cleanup; + + ret->type = tmp.type; + ret->timeElapsed = tmp.timeElapsed; + ret->timeRemaining = tmp.timeRemaining; + ret->dataTotal = tmp.dataTotal; + ret->dataProcessed = tmp.dataProcessed; + ret->dataRemaining = tmp.dataRemaining; + ret->memTotal = tmp.memTotal; + ret->memProcessed = tmp.memProcessed; + ret->memRemaining = tmp.memRemaining; + ret->fileTotal = tmp.fileTotal; + ret->fileProcessed = tmp.fileProcessed; + ret->fileRemaining = tmp.fileRemaining; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} static int remoteDispatchDomainGetMaxMemory( @@ -730,7 +887,48 @@ cleanup: return rv; } -/* remoteDispatchDomainInterfaceStats has to be implemented manually */ +static int +remoteDispatchDomainInterfaceStats( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_interface_stats_args *args, + remote_domain_interface_stats_ret *ret) +{ + int rv = -1; + virDomainPtr dom = NULL; + virDomainInterfaceStatsStruct tmp; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainInterfaceStats(dom, args->path, &tmp, sizeof tmp) < 0) + goto cleanup; + + ret->rx_bytes = tmp.rx_bytes; + ret->rx_packets = tmp.rx_packets; + ret->rx_errs = tmp.rx_errs; + ret->rx_drop = tmp.rx_drop; + ret->tx_bytes = tmp.tx_bytes; + ret->tx_packets = tmp.tx_packets; + ret->tx_errs = tmp.tx_errs; + ret->tx_drop = tmp.tx_drop; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} static int remoteDispatchDomainIsActive( @@ -3875,7 +4073,42 @@ cleanup: return rv; } -/* remoteDispatchNodeGetInfo has to be implemented manually */ +static int +remoteDispatchNodeGetInfo( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_node_get_info_ret *ret) +{ + int rv = -1; + virNodeInfo tmp; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (virNodeGetInfo(conn, &tmp) < 0) + goto cleanup; + + memcpy(ret->model, tmp.model, sizeof ret->model); + ret->memory = tmp.memory; + ret->cpus = tmp.cpus; + ret->mhz = tmp.mhz; + ret->nodes = tmp.nodes; + ret->sockets = tmp.sockets; + ret->cores = tmp.cores; + ret->threads = tmp.threads; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + return rv; +} /* remoteDispatchNodeGetSecurityModel has to be implemented manually */ @@ -4901,7 +5134,44 @@ cleanup: return rv; } -/* remoteDispatchStoragePoolGetInfo has to be implemented manually */ +static int +remoteDispatchStoragePoolGetInfo( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_get_info_args *args, + remote_storage_pool_get_info_ret *ret) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + virStoragePoolInfo tmp; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if (virStoragePoolGetInfo(pool, &tmp) < 0) + goto cleanup; + + ret->state = tmp.state; + ret->capacity = tmp.capacity; + ret->allocation = tmp.allocation; + ret->available = tmp.available; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} static int remoteDispatchStoragePoolIsActive( @@ -5419,7 +5689,43 @@ cleanup: return rv; } -/* remoteDispatchStorageVolGetInfo has to be implemented manually */ +static int +remoteDispatchStorageVolGetInfo( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_vol_get_info_args *args, + remote_storage_vol_get_info_ret *ret) +{ + int rv = -1; + virStorageVolPtr vol = NULL; + virStorageVolInfo tmp; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(vol = get_nonnull_storage_vol(conn, args->vol))) + goto cleanup; + + if (virStorageVolGetInfo(vol, &tmp) < 0) + goto cleanup; + + ret->type = tmp.type; + ret->capacity = tmp.capacity; + ret->allocation = tmp.allocation; + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (vol) + virStorageVolFree(vol); + return rv; +} static int remoteDispatchStorageVolGetPath( diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 1fd4627..1aaeaae 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -259,31 +259,23 @@ elsif ($opt_b) { "AuthPolkit", "DomainBlockPeek", - "DomainBlockStats", "DomainCreateWithFlags", "DomainEventsDeregister", "DomainEventsRegister", "DomainGetBlkioParameters", - "DomainGetBlockInfo", - "DomainGetInfo", - "DomainGetJobInfo", "DomainGetMemoryParameters", "DomainGetSchedulerParameters", "DomainGetSchedulerType", "DomainGetSecurityLabel", "DomainGetVcpus", - "DomainInterfaceStats", "DomainMemoryPeek", "DomainMemoryStats", "DomainMigratePrepare", "DomainMigratePrepare2", "GetType", "NodeDeviceGetParent", - "NodeGetInfo", "NodeGetSecurityModel", - "SecretGetValue", - "StoragePoolGetInfo", - "StorageVolGetInfo"); + "SecretGetValue"); } elsif ($structprefix eq "qemu") { @ungeneratable = ("MonitorCommand"); } @@ -408,6 +400,10 @@ elsif ($opt_b) { } else { push(@args_list, "args->$2"); } + } elsif ($args_member =~ m/^\/*/) { + # ignore comments + } else { + die "unhandled type for argument value: $args_member"; } } } @@ -419,10 +415,27 @@ elsif ($opt_b) { my $single_ret_list_name = "undefined"; my $single_ret_list_max_var = "undefined"; my $single_ret_list_max_define = "undefined"; + my $multi_ret = 0; + + if ($calls{$_}->{ret} ne "void" and + scalar(@{$calls{$_}->{ret_members}}) > 1) { + $multi_ret = 1; + } if ($calls{$_}->{ret} ne "void") { foreach my $ret_member (@{$calls{$_}->{ret_members}}) { - if ($ret_member =~ m/remote_nonnull_string (\S+)<(\S+)>;/) { + if ($multi_ret) { + if ($ret_member =~ m/(char|short|int|hyper) (\S+)\[\S+\];/) { + push(@ret_list, "memcpy(ret->$2, tmp.$2, sizeof ret->$2);"); + } elsif ($ret_member =~ m/char (\S+);/ or + $ret_member =~ m/short (\S+);/ or + $ret_member =~ m/int (\S+);/ or + $ret_member =~ m/hyper (\S+);/) { + push(@ret_list, "ret->$1 = tmp.$1;"); + } else { + die "unhandled type for multi-return-value: $ret_member"; + } + } elsif ($ret_member =~ m/remote_nonnull_string (\S+)<(\S+)>;/) { push(@vars_list, "int len"); push(@ret_list, "ret->$1.$1_len = len;"); push(@free_list_on_error, "VIR_FREE(ret->$1.$1_val);"); @@ -530,10 +543,39 @@ elsif ($opt_b) { } else { $single_ret_by_ref = 1; } + } else { + die "unhandled type for return value: $ret_member"; } } } + if ($multi_ret) { + if (! @args_list) { + push(@args_list, "conn"); + } + + my $struct_name = $calls{$_}->{ProcName}; + $struct_name =~ s/Get//; + + if ($calls{$_}->{ProcName} eq "DomainGetBlockInfo") { + my $flags = pop(@args_list); + push(@args_list, "&tmp"); + push(@args_list, $flags); + } elsif ($calls{$_}->{ProcName} eq "DomainBlockStats") { + $struct_name .= "Struct"; + push(@args_list, "&tmp"); + push(@args_list, "sizeof tmp"); + } elsif ($calls{$_}->{ProcName} eq "DomainInterfaceStats") { + $struct_name .= "Struct"; + push(@args_list, "&tmp"); + push(@args_list, "sizeof tmp"); + } else { + push(@args_list, "&tmp"); + } + + push(@vars_list, "vir$struct_name tmp"); + } + foreach my $var (@vars_list) { print " $var;\n"; } @@ -574,7 +616,7 @@ elsif ($opt_b) { print ") < 0)\n"; print " goto cleanup;\n"; print "\n"; - } elsif (scalar(@{$calls{$_}->{ret_members}}) == 1) { + } elsif (!$multi_ret) { my $prefix = ""; my $proc_name = $calls{$_}->{ProcName}; @@ -630,7 +672,21 @@ elsif ($opt_b) { print " "; } - print join(" \n", @ret_list); + print join("\n ", @ret_list); + print "\n"; + } else { + print " if (vir$calls{$_}->{ProcName}("; + print join(', ', @args_list); + print ") < 0)\n"; + + print " goto cleanup;\n"; + print "\n"; + + if (@ret_list) { + print " "; + } + + print join("\n ", @ret_list); print "\n"; } diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 935f321..934fdda 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2848,10 +2848,10 @@ remoteDomainGetInfo (virDomainPtr domain, virDomainInfoPtr info) goto done; info->state = ret.state; - info->maxMem = ret.max_mem; + info->maxMem = ret.maxMem; info->memory = ret.memory; - info->nrVirtCpu = ret.nr_virt_cpu; - info->cpuTime = ret.cpu_time; + info->nrVirtCpu = ret.nrVirtCpu; + info->cpuTime = ret.cpuTime; rv = 0; diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 1bdd79e..301ffbf 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -1185,13 +1185,13 @@ xdr_remote_domain_get_info_ret (XDR *xdrs, remote_domain_get_info_ret *objp) if (!xdr_u_char (xdrs, &objp->state)) return FALSE; - if (!xdr_uint64_t (xdrs, &objp->max_mem)) + if (!xdr_uint64_t (xdrs, &objp->maxMem)) return FALSE; if (!xdr_uint64_t (xdrs, &objp->memory)) return FALSE; - if (!xdr_u_short (xdrs, &objp->nr_virt_cpu)) + if (!xdr_u_short (xdrs, &objp->nrVirtCpu)) return FALSE; - if (!xdr_uint64_t (xdrs, &objp->cpu_time)) + if (!xdr_uint64_t (xdrs, &objp->cpuTime)) return FALSE; return TRUE; } diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index ff6903c..8942646 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -641,10 +641,10 @@ typedef struct remote_domain_get_info_args remote_domain_get_info_args; struct remote_domain_get_info_ret { u_char state; - uint64_t max_mem; + uint64_t maxMem; uint64_t memory; - u_short nr_virt_cpu; - uint64_t cpu_time; + u_short nrVirtCpu; + uint64_t cpuTime; }; typedef struct remote_domain_get_info_ret remote_domain_get_info_ret; diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 0858096..c706c36 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -693,10 +693,10 @@ struct remote_domain_get_info_args { struct remote_domain_get_info_ret { unsigned char state; - unsigned hyper max_mem; + unsigned hyper maxMem; unsigned hyper memory; - unsigned short nr_virt_cpu; - unsigned hyper cpu_time; + unsigned short nrVirtCpu; + unsigned hyper cpuTime; }; struct remote_domain_save_args { diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index d433f6b..f904c4d 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -386,10 +386,10 @@ struct remote_domain_get_info_args { }; struct remote_domain_get_info_ret { u_char state; - uint64_t max_mem; + uint64_t maxMem; uint64_t memory; - u_short nr_virt_cpu; - uint64_t cpu_time; + u_short nrVirtCpu; + uint64_t cpuTime; }; struct remote_domain_save_args { remote_nonnull_domain dom; -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:14:01 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:14:01 +0200 Subject: [libvirt] [PATCH 14/22] remote generator: Reorder into prepare and print section In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-15-git-send-email-matthias.bolte@googlemail.com> --- daemon/remote_generator.pl | 54 ++++++++++++++++++++++++------------------- 1 files changed, 30 insertions(+), 24 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 1aaeaae..9fa3caa 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -293,30 +293,6 @@ elsif ($opt_b) { next; } - print "static int\n"; - print "${structprefix}Dispatch$calls{$_}->{ProcName}(\n"; - print " struct qemud_server *server ATTRIBUTE_UNUSED,\n"; - print " struct qemud_client *client ATTRIBUTE_UNUSED,\n"; - print " virConnectPtr conn,\n"; - print " remote_message_header *hdr ATTRIBUTE_UNUSED,\n"; - print " remote_error *rerr,\n"; - print " $calls{$_}->{args} *args"; - - if ($calls{$_}->{args} eq "void") { - print " ATTRIBUTE_UNUSED" - } - - print ",\n"; - print " $calls{$_}->{ret} *ret"; - - if ($calls{$_}->{ret} eq "void") { - print " ATTRIBUTE_UNUSED" - } - - print ")\n"; - print "{\n"; - print " int rv = -1;\n"; - my $has_node_device = 0; my @vars_list = (); my @optionals_list = (); @@ -326,6 +302,7 @@ elsif ($opt_b) { my @free_list = (); my @free_list_on_error = ("remoteDispatchError(rerr);"); + # handle arguments to the function if ($calls{$_}->{args} ne "void") { # node device is special, as it's identified by name if ($calls{$_}->{args} =~ m/^remote_node_device_/ and @@ -408,6 +385,7 @@ elsif ($opt_b) { } } + # handle return values of the function my $single_ret_var = "undefined"; my $single_ret_by_ref = 0; my $single_ret_check = " == undefined"; @@ -549,6 +527,7 @@ elsif ($opt_b) { } } + # select struct type for multi-return-value functions if ($multi_ret) { if (! @args_list) { push(@args_list, "conn"); @@ -576,6 +555,33 @@ elsif ($opt_b) { push(@vars_list, "vir$struct_name tmp"); } + # print functions signature + print "static int\n"; + print "${structprefix}Dispatch$calls{$_}->{ProcName}(\n"; + print " struct qemud_server *server ATTRIBUTE_UNUSED,\n"; + print " struct qemud_client *client ATTRIBUTE_UNUSED,\n"; + print " virConnectPtr conn,\n"; + print " remote_message_header *hdr ATTRIBUTE_UNUSED,\n"; + print " remote_error *rerr,\n"; + print " $calls{$_}->{args} *args"; + + if ($calls{$_}->{args} eq "void") { + print " ATTRIBUTE_UNUSED" + } + + print ",\n"; + print " $calls{$_}->{ret} *ret"; + + if ($calls{$_}->{ret} eq "void") { + print " ATTRIBUTE_UNUSED" + } + + print ")\n"; + + # print function body + print "{\n"; + print " int rv = -1;\n"; + foreach my $var (@vars_list) { print " $var;\n"; } -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:13:49 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:13:49 +0200 Subject: [libvirt] [PATCH 02/22] remote generator, daemon: Output function bodies too In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-3-git-send-email-matthias.bolte@googlemail.com> This patch just covers the simple functions without explicit return values. There is more to be handled. The generator collects the members of the XDR argument structs and uses this information to generate the function bodies. Exclude the generated files from offending syntax-checks. Suggested by Richard W.M. Jones --- cfg.mk | 8 +- daemon/Makefile.am | 12 +- daemon/qemu_dispatch_bodies.c | 6 + daemon/remote.c | 1710 +----------------------------- daemon/remote_dispatch_bodies.c | 2048 +++++++++++++++++++++++++++++++++++ daemon/remote_dispatch_prototypes.h | 10 +- daemon/remote_dispatch_table.h | 20 +- daemon/remote_generator.pl | 254 +++++- po/POTFILES.in | 1 + src/remote/remote_protocol.x | 6 +- 10 files changed, 2344 insertions(+), 1731 deletions(-) create mode 100644 daemon/qemu_dispatch_bodies.c create mode 100644 daemon/remote_dispatch_bodies.c diff --git a/cfg.mk b/cfg.mk index 72dd69c..a38ea48 100644 --- a/cfg.mk +++ b/cfg.mk @@ -590,7 +590,7 @@ exclude_file_name_regexp--sc_avoid_write = \ exclude_file_name_regexp--sc_bindtextdomain = ^(tests|examples)/ -exclude_file_name_regexp--sc_po_check = ^docs/ +exclude_file_name_regexp--sc_po_check = ^(docs/|daemon/remote_generator.pl$$) exclude_file_name_regexp--sc_prohibit_VIR_ERR_NO_MEMORY = \ ^(include/libvirt/virterror\.h|daemon/dispatch\.c|src/util/virterror\.c)$$ @@ -611,7 +611,7 @@ exclude_file_name_regexp--sc_prohibit_close = \ exclude_file_name_regexp--sc_prohibit_doubled_word = ^po/ exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \ - (^docs/api_extension/|^tests/qemuhelpdata/|\.(gif|ico|png)$$) + (^docs/api_extension/|^tests/qemuhelpdata/|\.(gif|ico|png)$$|daemon/.*_dispatch_bodies.c$$) _src2=src/(util/util|libvirt|lxc/lxc_controller) exclude_file_name_regexp--sc_prohibit_fork_wrappers = \ @@ -633,9 +633,9 @@ exclude_file_name_regexp--sc_prohibit_strncpy = \ exclude_file_name_regexp--sc_prohibit_xmlGetProp = ^src/util/xml\.c$$ -exclude_file_name_regexp--sc_require_config_h = ^examples/ +exclude_file_name_regexp--sc_require_config_h = ^(examples/|daemon/.*_dispatch_bodies.c$$) -exclude_file_name_regexp--sc_require_config_h_first = ^examples/ +exclude_file_name_regexp--sc_require_config_h_first = ^(examples/|daemon/.*_dispatch_bodies.c$$) exclude_file_name_regexp--sc_trailing_blank = (^docs/|\.(fig|gif|ico|png)$$) diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 14088bc..3dec183 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -24,6 +24,8 @@ AVAHI_SOURCES = \ DISTCLEANFILES = EXTRA_DIST = \ remote_generator.pl \ + remote_dispatch_bodies.c \ + qemu_dispatch_bodies.c \ libvirtd.conf \ libvirtd.init.in \ libvirtd.upstart \ @@ -204,8 +206,10 @@ endif remote.c: \ remote_dispatch_prototypes.h \ remote_dispatch_table.h \ + remote_dispatch_bodies.c \ qemu_dispatch_prototypes.h \ - qemu_dispatch_table.h + qemu_dispatch_table.h \ + qemu_dispatch_bodies.c remote.h: \ remote_dispatch_args.h \ @@ -228,6 +232,9 @@ remote_dispatch_args.h: $(srcdir)/remote_generator.pl $(REMOTE_PROTOCOL) remote_dispatch_ret.h: $(srcdir)/remote_generator.pl $(REMOTE_PROTOCOL) $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -c -r remote $(REMOTE_PROTOCOL) > $@ +remote_dispatch_bodies.c: $(srcdir)/remote_generator.pl $(REMOTE_PROTOCOL) + $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -c -b remote $(REMOTE_PROTOCOL) > $@ + qemu_dispatch_prototypes.h: $(srcdir)/remote_generator.pl $(QEMU_PROTOCOL) $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -p qemu $(QEMU_PROTOCOL) > $@ @@ -240,6 +247,9 @@ qemu_dispatch_args.h: $(srcdir)/remote_generator.pl $(QEMU_PROTOCOL) qemu_dispatch_ret.h: $(srcdir)/remote_generator.pl $(QEMU_PROTOCOL) $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -r qemu $(QEMU_PROTOCOL) > $@ +qemu_dispatch_bodies.c: $(srcdir)/remote_generator.pl $(QEMU_PROTOCOL) + $(AM_V_GEN)perl -w $(srcdir)/remote_generator.pl -b qemu $(QEMU_PROTOCOL) > $@ + LOGROTATE_CONFS = libvirtd.qemu.logrotate libvirtd.lxc.logrotate \ libvirtd.uml.logrotate libvirtd.logrotate diff --git a/daemon/qemu_dispatch_bodies.c b/daemon/qemu_dispatch_bodies.c new file mode 100644 index 0000000..98ae2c1 --- /dev/null +++ b/daemon/qemu_dispatch_bodies.c @@ -0,0 +1,6 @@ +/* Automatically generated by remote_generator.pl. + * Do not edit this file. Any changes you make will be lost. + */ + +/* qemuDispatchMonitorCommand has to be implemented manually */ + diff --git a/daemon/remote.c b/daemon/remote.c index 1c98bba..676c99a 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1290,138 +1290,6 @@ cleanup: } static int -remoteDispatchDomainAttachDevice(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_attach_device_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainAttachDevice(dom, args->xml) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainAttachDeviceFlags(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_attach_device_flags_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainAttachDeviceFlags(dom, args->xml, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainUpdateDeviceFlags(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_update_device_flags_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainUpdateDeviceFlags(dom, args->xml, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainCreate(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_create_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainCreate(dom) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainCreateWithFlags(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -1516,105 +1384,6 @@ cleanup: } static int -remoteDispatchDomainDestroy(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_destroy_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainDestroy(dom) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainDetachDevice(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_detach_device_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainDetachDevice(dom, args->xml) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainDetachDeviceFlags(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_detach_device_flags_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainDetachDeviceFlags(dom, args->xml, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainDumpXml(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -2565,297 +2334,6 @@ cleanup: } static int -remoteDispatchDomainReboot(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_reboot_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainReboot(dom, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainRestore(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_restore_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (virDomainRestore(conn, args->from) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - return rv; -} - -static int -remoteDispatchDomainResume(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_resume_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainResume(dom) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainSave(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_save_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainSave(dom, args->to) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainCoreDump(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_core_dump_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainCoreDump(dom, args->to, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainSetAutostart(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_set_autostart_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainSetAutostart(dom, args->autostart) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainSetMaxMemory(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_set_max_memory_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainSetMaxMemory(dom, args->memory) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainSetMemory(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_set_memory_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainSetMemory(dom, args->memory) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainSetMemoryFlags(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_set_memory_flags_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainSetMemoryFlags(dom, args->memory, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainSetMemoryParameters(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client @@ -3288,171 +2766,6 @@ no_memory: } static int -remoteDispatchDomainSetVcpus(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_set_vcpus_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainSetVcpus(dom, args->nvcpus) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainSetVcpusFlags(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_set_vcpus_flags_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainSetVcpusFlags(dom, args->nvcpus, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainShutdown(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_shutdown_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainShutdown(dom) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainSuspend(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_suspend_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainSuspend(dom) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainUndefine(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_undefine_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainUndefine(dom) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchListDefinedNetworks(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3543,39 +2856,6 @@ cleanup: } static int -remoteDispatchDomainManagedSave(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_managed_save_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainManagedSave(dom, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchDomainHasManagedSaveImage(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3609,39 +2889,6 @@ cleanup: } static int -remoteDispatchDomainManagedSaveRemove(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_managed_save_remove_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainManagedSaveRemove(dom, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int remoteDispatchListNetworks(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3687,39 +2934,6 @@ cleanup: } static int -remoteDispatchNetworkCreate(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_create_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = get_nonnull_network(conn, args->net))) - goto cleanup; - - if (virNetworkCreate(net) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - -static int remoteDispatchNetworkCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3784,39 +2998,6 @@ cleanup: } static int -remoteDispatchNetworkDestroy(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_destroy_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = get_nonnull_network(conn, args->net))) - goto cleanup; - - if (virNetworkDestroy(net) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - -static int remoteDispatchNetworkDumpXml(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -3982,72 +3163,6 @@ cleanup: } static int -remoteDispatchNetworkSetAutostart(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_set_autostart_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = get_nonnull_network(conn, args->net))) - goto cleanup; - - if (virNetworkSetAutostart(net, args->autostart) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - -static int -remoteDispatchNetworkUndefine(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_network_undefine_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virNetworkPtr net = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(net = get_nonnull_network(conn, args->net))) - goto cleanup; - - if (virNetworkUndefine(net) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (net) - virNetworkFree(net); - return rv; -} - -static int remoteDispatchNumOfDefinedNetworks(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -4410,105 +3525,6 @@ cleanup: return rv; } -static int -remoteDispatchInterfaceUndefine(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_interface_undefine_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virInterfacePtr iface = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(iface = get_nonnull_interface(conn, args->iface))) - goto cleanup; - - if (virInterfaceUndefine(iface) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (iface) - virInterfaceFree(iface); - return rv; -} - -static int -remoteDispatchInterfaceCreate(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_interface_create_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virInterfacePtr iface = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(iface = get_nonnull_interface(conn, args->iface))) - goto cleanup; - - if (virInterfaceCreate(iface, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (iface) - virInterfaceFree(iface); - return rv; -} - -static int -remoteDispatchInterfaceDestroy(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_interface_destroy_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virInterfacePtr iface = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(iface = get_nonnull_interface(conn, args->iface))) - goto cleanup; - - if (virInterfaceDestroy(iface, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (iface) - virInterfaceFree(iface); - return rv; -} - /*-------------------------------------------------------------*/ static int @@ -5435,40 +4451,6 @@ cleanup: return rv; } - -static int -remoteDispatchStoragePoolCreate(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_create_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if (virStoragePoolCreate(pool, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - static int remoteDispatchStoragePoolCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, @@ -5534,139 +4516,6 @@ cleanup: } static int -remoteDispatchStoragePoolBuild(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_build_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if (virStoragePoolBuild(pool, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - - -static int -remoteDispatchStoragePoolDestroy(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_destroy_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if (virStoragePoolDestroy(pool) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -static int -remoteDispatchStoragePoolDelete(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_delete_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if (virStoragePoolDelete(pool, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -static int -remoteDispatchStoragePoolRefresh(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_refresh_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if (virStoragePoolRefresh(pool, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -static int remoteDispatchStoragePoolGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -5876,72 +4725,6 @@ cleanup: } static int -remoteDispatchStoragePoolSetAutostart(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_set_autostart_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if (virStoragePoolSetAutostart(pool, args->autostart) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -static int -remoteDispatchStoragePoolUndefine(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_pool_undefine_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virStoragePoolPtr pool = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(pool = get_nonnull_storage_pool(conn, args->pool))) - goto cleanup; - - if (virStoragePoolUndefine(pool) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (pool) - virStoragePoolFree(pool); - return rv; -} - -static int remoteDispatchNumOfStoragePools(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -6169,72 +4952,6 @@ cleanup: } static int -remoteDispatchStorageVolDelete(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_vol_delete_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virStorageVolPtr vol = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(vol = get_nonnull_storage_vol(conn, args->vol))) - goto cleanup; - - if (virStorageVolDelete(vol, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (vol) - virStorageVolFree(vol); - return rv; -} - -static int -remoteDispatchStorageVolWipe(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_storage_vol_wipe_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virStorageVolPtr vol = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(vol = get_nonnull_storage_vol(conn, args->vol))) - goto cleanup; - - if (virStorageVolWipe(vol, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (vol) - virStorageVolFree(vol); - return rv; -} - -static int remoteDispatchStorageVolGetInfo(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -6731,109 +5448,6 @@ cleanup: return rv; } - -static int -remoteDispatchNodeDeviceDettach(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_node_device_dettach_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virNodeDevicePtr dev = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dev = virNodeDeviceLookupByName(conn, args->name))) - goto cleanup; - - if (virNodeDeviceDettach(dev) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dev) - virNodeDeviceFree(dev); - return rv; -} - - -static int -remoteDispatchNodeDeviceReAttach(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_node_device_re_attach_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virNodeDevicePtr dev = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dev = virNodeDeviceLookupByName(conn, args->name))) - goto cleanup; - - if (virNodeDeviceReAttach(dev) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dev) - virNodeDeviceFree(dev); - return rv; -} - - -static int -remoteDispatchNodeDeviceReset(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_node_device_reset_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virNodeDevicePtr dev = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dev = virNodeDeviceLookupByName(conn, args->name))) - goto cleanup; - - if (virNodeDeviceReset(dev) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dev) - virNodeDeviceFree(dev); - return rv; -} - - static int remoteDispatchNodeDeviceCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, @@ -6866,40 +5480,6 @@ cleanup: return rv; } - -static int -remoteDispatchNodeDeviceDestroy(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_node_device_destroy_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virNodeDevicePtr dev = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dev = virNodeDeviceLookupByName(conn, args->name))) - goto cleanup; - - if (virNodeDeviceDestroy(dev) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dev) - virNodeDeviceFree(dev); - return rv; -} - static int remoteDispatchStorageVolUpload(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, virConnectPtr conn, @@ -7336,71 +5916,6 @@ cleanup: } static int -remoteDispatchSecretSetValue(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_secret_set_value_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virSecretPtr secret = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(secret = get_nonnull_secret(conn, args->secret))) - goto cleanup; - if (virSecretSetValue(secret, (const unsigned char *)args->value.value_val, - args->value.value_len, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (secret) - virSecretFree(secret); - return rv; -} - -static int -remoteDispatchSecretUndefine(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_secret_undefine_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virSecretPtr secret = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(secret = get_nonnull_secret(conn, args->secret))) - goto cleanup; - if (virSecretUndefine(secret) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (secret) - virSecretFree(secret); - return rv; -} - -static int remoteDispatchSecretLookupByUsage(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -7828,107 +6343,6 @@ cleanup: return rv; } - -static int -remoteDispatchDomainAbortJob(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_abort_job_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainAbortJob(dom) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - - -static int -remoteDispatchDomainMigrateSetMaxDowntime(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_migrate_set_max_downtime_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainMigrateSetMaxDowntime(dom, args->downtime, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainMigrateSetMaxSpeed(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_migrate_set_max_speed_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->dom))) - goto cleanup; - - if (virDomainMigrateSetMaxSpeed(dom, args->bandwidth, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (dom) - virDomainFree(dom); - return rv; -} - static int remoteDispatchDomainSnapshotCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, @@ -8207,85 +6621,6 @@ cleanup: } static int -remoteDispatchDomainRevertToSnapshot(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_revert_to_snapshot_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - virDomainSnapshotPtr snapshot = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->snap.domain))) - goto cleanup; - - if (!(snapshot = get_nonnull_domain_snapshot(dom, args->snap))) - goto cleanup; - - if (virDomainRevertToSnapshot(snapshot, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (snapshot) - virDomainSnapshotFree(snapshot); - if (dom) - virDomainFree(dom); - return rv; -} - -static int -remoteDispatchDomainSnapshotDelete(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_domain_snapshot_delete_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virDomainPtr dom = NULL; - virDomainSnapshotPtr snapshot = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(dom = get_nonnull_domain(conn, args->snap.domain))) - goto cleanup; - - if (!(snapshot = get_nonnull_domain_snapshot(dom, args->snap))) - goto cleanup; - - if (virDomainSnapshotDelete(snapshot, args->flags) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (snapshot) - virDomainSnapshotFree(snapshot); - if (dom) - virDomainFree(dom); - return rv; -} - - -static int remoteDispatchDomainEventsRegisterAny(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, @@ -8374,7 +6709,7 @@ cleanup: static int -remoteDispatchNwfilterLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNWFilterLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -8406,7 +6741,7 @@ cleanup: } static int -remoteDispatchNwfilterLookupByUuid(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNWFilterLookupByUuid(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -8439,7 +6774,7 @@ cleanup: static int -remoteDispatchNwfilterDefineXml(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNWFilterDefineXml(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -8470,40 +6805,6 @@ cleanup: return rv; } - -static int -remoteDispatchNwfilterUndefine(struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client ATTRIBUTE_UNUSED, - virConnectPtr conn, - remote_message_header *hdr ATTRIBUTE_UNUSED, - remote_error *rerr, - remote_nwfilter_undefine_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virNWFilterPtr nwfilter = NULL; - int rv = -1; - - if (!conn) { - virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); - goto cleanup; - } - - if (!(nwfilter = get_nonnull_nwfilter(conn, args->nwfilter))) - goto cleanup; - - if (virNWFilterUndefine(nwfilter) < 0) - goto cleanup; - - rv = 0; - -cleanup: - if (rv < 0) - remoteDispatchError(rerr); - if (nwfilter) - virNWFilterFree(nwfilter); - return rv; -} - static int remoteDispatchListNwfilters(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, @@ -8551,7 +6852,7 @@ cleanup: static int -remoteDispatchNwfilterGetXmlDesc(struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchNWFilterGetXmlDesc(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, remote_message_header *hdr ATTRIBUTE_UNUSED, @@ -8735,6 +7036,9 @@ cleanup: return rv; } +#include "remote_dispatch_bodies.c" +#include "qemu_dispatch_bodies.c" + /*----- Helpers. -----*/ diff --git a/daemon/remote_dispatch_bodies.c b/daemon/remote_dispatch_bodies.c new file mode 100644 index 0000000..962b12a --- /dev/null +++ b/daemon/remote_dispatch_bodies.c @@ -0,0 +1,2048 @@ +/* Automatically generated by remote_generator.pl. + * Do not edit this file. Any changes you make will be lost. + */ + +/* remoteDispatchAuthList has to be implemented manually */ + +/* remoteDispatchAuthPolkit has to be implemented manually */ + +/* remoteDispatchAuthSaslInit has to be implemented manually */ + +/* remoteDispatchAuthSaslStart has to be implemented manually */ + +/* remoteDispatchAuthSaslStep has to be implemented manually */ + +/* remoteDispatchClose has to be implemented manually */ + +/* remoteDispatchCpuBaseline has to be implemented manually */ + +/* remoteDispatchCpuCompare has to be implemented manually */ + +static int +remoteDispatchDomainAbortJob( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_abort_job_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainAbortJob(dom) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainAttachDevice( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_attach_device_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainAttachDevice(dom, args->xml) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainAttachDeviceFlags( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_attach_device_flags_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainAttachDeviceFlags(dom, args->xml, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +/* remoteDispatchDomainBlockPeek has to be implemented manually */ + +/* remoteDispatchDomainBlockStats has to be implemented manually */ + +static int +remoteDispatchDomainCoreDump( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_core_dump_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainCoreDump(dom, args->to, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainCreate( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_create_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainCreate(dom) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +/* remoteDispatchDomainCreateWithFlags has to be implemented manually */ + +/* remoteDispatchDomainCreateXml has to be implemented manually */ + +/* remoteDispatchDomainDefineXml has to be implemented manually */ + +static int +remoteDispatchDomainDestroy( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_destroy_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainDestroy(dom) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainDetachDevice( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_detach_device_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainDetachDevice(dom, args->xml) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainDetachDeviceFlags( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_detach_device_flags_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainDetachDeviceFlags(dom, args->xml, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +/* remoteDispatchDomainDumpXml has to be implemented manually */ + +/* remoteDispatchDomainEventsDeregister has to be implemented manually */ + +/* remoteDispatchDomainEventsDeregisterAny has to be implemented manually */ + +/* remoteDispatchDomainEventsRegister has to be implemented manually */ + +/* remoteDispatchDomainEventsRegisterAny has to be implemented manually */ + +/* remoteDispatchDomainGetAutostart has to be implemented manually */ + +/* remoteDispatchDomainGetBlkioParameters has to be implemented manually */ + +/* remoteDispatchDomainGetBlockInfo has to be implemented manually */ + +/* remoteDispatchDomainGetInfo has to be implemented manually */ + +/* remoteDispatchDomainGetJobInfo has to be implemented manually */ + +/* remoteDispatchDomainGetMaxMemory has to be implemented manually */ + +/* remoteDispatchDomainGetMaxVcpus has to be implemented manually */ + +/* remoteDispatchDomainGetMemoryParameters has to be implemented manually */ + +/* remoteDispatchDomainGetOsType has to be implemented manually */ + +/* remoteDispatchDomainGetSchedulerParameters has to be implemented manually */ + +/* remoteDispatchDomainGetSchedulerType has to be implemented manually */ + +/* remoteDispatchDomainGetSecurityLabel has to be implemented manually */ + +/* remoteDispatchDomainGetVcpus has to be implemented manually */ + +/* remoteDispatchDomainGetVcpusFlags has to be implemented manually */ + +/* remoteDispatchDomainHasCurrentSnapshot has to be implemented manually */ + +/* remoteDispatchDomainHasManagedSaveImage has to be implemented manually */ + +/* remoteDispatchDomainInterfaceStats has to be implemented manually */ + +/* remoteDispatchDomainIsActive has to be implemented manually */ + +/* remoteDispatchDomainIsPersistent has to be implemented manually */ + +/* remoteDispatchDomainIsUpdated has to be implemented manually */ + +/* remoteDispatchDomainLookupById has to be implemented manually */ + +/* remoteDispatchDomainLookupByName has to be implemented manually */ + +/* remoteDispatchDomainLookupByUuid has to be implemented manually */ + +static int +remoteDispatchDomainManagedSave( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_managed_save_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainManagedSave(dom, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainManagedSaveRemove( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_managed_save_remove_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainManagedSaveRemove(dom, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +/* remoteDispatchDomainMemoryPeek has to be implemented manually */ + +/* remoteDispatchDomainMemoryStats has to be implemented manually */ + +/* remoteDispatchDomainMigrateFinish has to be implemented manually */ + +/* remoteDispatchDomainMigrateFinish2 has to be implemented manually */ + +/* remoteDispatchDomainMigratePerform has to be implemented manually */ + +/* remoteDispatchDomainMigratePrepare has to be implemented manually */ + +/* remoteDispatchDomainMigratePrepare2 has to be implemented manually */ + +/* remoteDispatchDomainMigratePrepareTunnel has to be implemented manually */ + +static int +remoteDispatchDomainMigrateSetMaxDowntime( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_migrate_set_max_downtime_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainMigrateSetMaxDowntime(dom, args->downtime, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainMigrateSetMaxSpeed( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_migrate_set_max_speed_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainMigrateSetMaxSpeed(dom, args->bandwidth, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +/* remoteDispatchDomainOpenConsole has to be implemented manually */ + +/* remoteDispatchDomainPinVcpu has to be implemented manually */ + +static int +remoteDispatchDomainReboot( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_reboot_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainReboot(dom, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainRestore( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_restore_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + + if (virDomainRestore(conn, args->from) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + + return rv; +} + +static int +remoteDispatchDomainResume( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_resume_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainResume(dom) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainRevertToSnapshot( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_revert_to_snapshot_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + virDomainSnapshotPtr snapshot = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->snap.domain))) + goto cleanup; + + if (!(snapshot = get_nonnull_domain_snapshot(dom, args->snap))) + goto cleanup; + + if (virDomainRevertToSnapshot(snapshot, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (snapshot) + virDomainSnapshotFree(snapshot); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainSave( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_save_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainSave(dom, args->to) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainSetAutostart( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_set_autostart_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainSetAutostart(dom, args->autostart) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +/* remoteDispatchDomainSetBlkioParameters has to be implemented manually */ + +static int +remoteDispatchDomainSetMaxMemory( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_set_max_memory_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainSetMaxMemory(dom, args->memory) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainSetMemory( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_set_memory_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainSetMemory(dom, args->memory) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainSetMemoryFlags( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_set_memory_flags_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainSetMemoryFlags(dom, args->memory, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +/* remoteDispatchDomainSetMemoryParameters has to be implemented manually */ + +/* remoteDispatchDomainSetSchedulerParameters has to be implemented manually */ + +static int +remoteDispatchDomainSetVcpus( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_set_vcpus_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainSetVcpus(dom, args->nvcpus) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainSetVcpusFlags( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_set_vcpus_flags_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainSetVcpusFlags(dom, args->nvcpus, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainShutdown( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_shutdown_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainShutdown(dom) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +/* remoteDispatchDomainSnapshotCreateXml has to be implemented manually */ + +/* remoteDispatchDomainSnapshotCurrent has to be implemented manually */ + +static int +remoteDispatchDomainSnapshotDelete( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_snapshot_delete_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + virDomainSnapshotPtr snapshot = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->snap.domain))) + goto cleanup; + + if (!(snapshot = get_nonnull_domain_snapshot(dom, args->snap))) + goto cleanup; + + if (virDomainSnapshotDelete(snapshot, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (snapshot) + virDomainSnapshotFree(snapshot); + if (dom) + virDomainFree(dom); + return rv; +} + +/* remoteDispatchDomainSnapshotDumpXml has to be implemented manually */ + +/* remoteDispatchDomainSnapshotListNames has to be implemented manually */ + +/* remoteDispatchDomainSnapshotLookupByName has to be implemented manually */ + +/* remoteDispatchDomainSnapshotNum has to be implemented manually */ + +static int +remoteDispatchDomainSuspend( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_suspend_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainSuspend(dom) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainUndefine( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_undefine_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainUndefine(dom) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int +remoteDispatchDomainUpdateDeviceFlags( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_update_device_flags_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virDomainPtr dom = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainUpdateDeviceFlags(dom, args->xml, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +/* remoteDispatchDomainXmlFromNative has to be implemented manually */ + +/* remoteDispatchDomainXmlToNative has to be implemented manually */ + +/* remoteDispatchFindStoragePoolSources has to be implemented manually */ + +/* remoteDispatchGetCapabilities has to be implemented manually */ + +/* remoteDispatchGetHostname has to be implemented manually */ + +/* remoteDispatchGetLibVersion has to be implemented manually */ + +/* remoteDispatchGetMaxVcpus has to be implemented manually */ + +/* remoteDispatchGetSysinfo has to be implemented manually */ + +/* remoteDispatchGetType has to be implemented manually */ + +/* remoteDispatchGetUri has to be implemented manually */ + +/* remoteDispatchGetVersion has to be implemented manually */ + +static int +remoteDispatchInterfaceCreate( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_interface_create_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virInterfacePtr iface = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(iface = get_nonnull_interface(conn, args->iface))) + goto cleanup; + + if (virInterfaceCreate(iface, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (iface) + virInterfaceFree(iface); + return rv; +} + +/* remoteDispatchInterfaceDefineXml has to be implemented manually */ + +static int +remoteDispatchInterfaceDestroy( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_interface_destroy_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virInterfacePtr iface = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(iface = get_nonnull_interface(conn, args->iface))) + goto cleanup; + + if (virInterfaceDestroy(iface, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (iface) + virInterfaceFree(iface); + return rv; +} + +/* remoteDispatchInterfaceGetXmlDesc has to be implemented manually */ + +/* remoteDispatchInterfaceIsActive has to be implemented manually */ + +/* remoteDispatchInterfaceLookupByMacString has to be implemented manually */ + +/* remoteDispatchInterfaceLookupByName has to be implemented manually */ + +static int +remoteDispatchInterfaceUndefine( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_interface_undefine_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virInterfacePtr iface = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(iface = get_nonnull_interface(conn, args->iface))) + goto cleanup; + + if (virInterfaceUndefine(iface) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (iface) + virInterfaceFree(iface); + return rv; +} + +/* remoteDispatchIsSecure has to be implemented manually */ + +/* remoteDispatchListDefinedDomains has to be implemented manually */ + +/* remoteDispatchListDefinedInterfaces has to be implemented manually */ + +/* remoteDispatchListDefinedNetworks has to be implemented manually */ + +/* remoteDispatchListDefinedStoragePools has to be implemented manually */ + +/* remoteDispatchListDomains has to be implemented manually */ + +/* remoteDispatchListInterfaces has to be implemented manually */ + +/* remoteDispatchListNetworks has to be implemented manually */ + +/* remoteDispatchListNwfilters has to be implemented manually */ + +/* remoteDispatchListSecrets has to be implemented manually */ + +/* remoteDispatchListStoragePools has to be implemented manually */ + +static int +remoteDispatchNetworkCreate( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_create_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virNetworkPtr net = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(net = get_nonnull_network(conn, args->net))) + goto cleanup; + + if (virNetworkCreate(net) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} + +/* remoteDispatchNetworkCreateXml has to be implemented manually */ + +/* remoteDispatchNetworkDefineXml has to be implemented manually */ + +static int +remoteDispatchNetworkDestroy( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_destroy_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virNetworkPtr net = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(net = get_nonnull_network(conn, args->net))) + goto cleanup; + + if (virNetworkDestroy(net) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} + +/* remoteDispatchNetworkDumpXml has to be implemented manually */ + +/* remoteDispatchNetworkGetAutostart has to be implemented manually */ + +/* remoteDispatchNetworkGetBridgeName has to be implemented manually */ + +/* remoteDispatchNetworkIsActive has to be implemented manually */ + +/* remoteDispatchNetworkIsPersistent has to be implemented manually */ + +/* remoteDispatchNetworkLookupByName has to be implemented manually */ + +/* remoteDispatchNetworkLookupByUuid has to be implemented manually */ + +static int +remoteDispatchNetworkSetAutostart( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_set_autostart_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virNetworkPtr net = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(net = get_nonnull_network(conn, args->net))) + goto cleanup; + + if (virNetworkSetAutostart(net, args->autostart) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} + +static int +remoteDispatchNetworkUndefine( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_network_undefine_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virNetworkPtr net = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(net = get_nonnull_network(conn, args->net))) + goto cleanup; + + if (virNetworkUndefine(net) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (net) + virNetworkFree(net); + return rv; +} + +/* remoteDispatchNodeDeviceCreateXml has to be implemented manually */ + +static int +remoteDispatchNodeDeviceDestroy( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_device_destroy_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virNodeDevicePtr dev = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dev = virNodeDeviceLookupByName(conn, args->name))) + goto cleanup; + + if (virNodeDeviceDestroy(dev) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dev) + virNodeDeviceFree(dev); + return rv; +} + +static int +remoteDispatchNodeDeviceDettach( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_device_dettach_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virNodeDevicePtr dev = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dev = virNodeDeviceLookupByName(conn, args->name))) + goto cleanup; + + if (virNodeDeviceDettach(dev) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dev) + virNodeDeviceFree(dev); + return rv; +} + +/* remoteDispatchNodeDeviceDumpXml has to be implemented manually */ + +/* remoteDispatchNodeDeviceGetParent has to be implemented manually */ + +/* remoteDispatchNodeDeviceListCaps has to be implemented manually */ + +/* remoteDispatchNodeDeviceLookupByName has to be implemented manually */ + +/* remoteDispatchNodeDeviceNumOfCaps has to be implemented manually */ + +static int +remoteDispatchNodeDeviceReAttach( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_device_re_attach_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virNodeDevicePtr dev = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dev = virNodeDeviceLookupByName(conn, args->name))) + goto cleanup; + + if (virNodeDeviceReAttach(dev) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dev) + virNodeDeviceFree(dev); + return rv; +} + +static int +remoteDispatchNodeDeviceReset( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_node_device_reset_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virNodeDevicePtr dev = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dev = virNodeDeviceLookupByName(conn, args->name))) + goto cleanup; + + if (virNodeDeviceReset(dev) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dev) + virNodeDeviceFree(dev); + return rv; +} + +/* remoteDispatchNodeGetCellsFreeMemory has to be implemented manually */ + +/* remoteDispatchNodeGetFreeMemory has to be implemented manually */ + +/* remoteDispatchNodeGetInfo has to be implemented manually */ + +/* remoteDispatchNodeGetSecurityModel has to be implemented manually */ + +/* remoteDispatchNodeListDevices has to be implemented manually */ + +/* remoteDispatchNodeNumOfDevices has to be implemented manually */ + +/* remoteDispatchNumOfDefinedDomains has to be implemented manually */ + +/* remoteDispatchNumOfDefinedInterfaces has to be implemented manually */ + +/* remoteDispatchNumOfDefinedNetworks has to be implemented manually */ + +/* remoteDispatchNumOfDefinedStoragePools has to be implemented manually */ + +/* remoteDispatchNumOfDomains has to be implemented manually */ + +/* remoteDispatchNumOfInterfaces has to be implemented manually */ + +/* remoteDispatchNumOfNetworks has to be implemented manually */ + +/* remoteDispatchNumOfNwfilters has to be implemented manually */ + +/* remoteDispatchNumOfSecrets has to be implemented manually */ + +/* remoteDispatchNumOfStoragePools has to be implemented manually */ + +/* remoteDispatchNWFilterDefineXml has to be implemented manually */ + +/* remoteDispatchNWFilterGetXmlDesc has to be implemented manually */ + +/* remoteDispatchNWFilterLookupByName has to be implemented manually */ + +/* remoteDispatchNWFilterLookupByUuid has to be implemented manually */ + +static int +remoteDispatchNWFilterUndefine( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_nwfilter_undefine_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virNWFilterPtr nwfilter = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(nwfilter = get_nonnull_nwfilter(conn, args->nwfilter))) + goto cleanup; + + if (virNWFilterUndefine(nwfilter) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (nwfilter) + virNWFilterFree(nwfilter); + return rv; +} + +/* remoteDispatchOpen has to be implemented manually */ + +/* remoteDispatchSecretDefineXml has to be implemented manually */ + +/* remoteDispatchSecretGetValue has to be implemented manually */ + +/* remoteDispatchSecretGetXmlDesc has to be implemented manually */ + +/* remoteDispatchSecretLookupByUsage has to be implemented manually */ + +/* remoteDispatchSecretLookupByUuid has to be implemented manually */ + +static int +remoteDispatchSecretSetValue( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_secret_set_value_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virSecretPtr secret = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(secret = get_nonnull_secret(conn, args->secret))) + goto cleanup; + + if (virSecretSetValue(secret, (const unsigned char *)args->value.value_val, args->value.value_len, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (secret) + virSecretFree(secret); + return rv; +} + +static int +remoteDispatchSecretUndefine( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_secret_undefine_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virSecretPtr secret = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(secret = get_nonnull_secret(conn, args->secret))) + goto cleanup; + + if (virSecretUndefine(secret) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (secret) + virSecretFree(secret); + return rv; +} + +static int +remoteDispatchStoragePoolBuild( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_build_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if (virStoragePoolBuild(pool, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} + +static int +remoteDispatchStoragePoolCreate( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_create_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if (virStoragePoolCreate(pool, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} + +/* remoteDispatchStoragePoolCreateXml has to be implemented manually */ + +/* remoteDispatchStoragePoolDefineXml has to be implemented manually */ + +static int +remoteDispatchStoragePoolDelete( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_delete_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if (virStoragePoolDelete(pool, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} + +static int +remoteDispatchStoragePoolDestroy( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_destroy_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if (virStoragePoolDestroy(pool) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} + +/* remoteDispatchStoragePoolDumpXml has to be implemented manually */ + +/* remoteDispatchStoragePoolGetAutostart has to be implemented manually */ + +/* remoteDispatchStoragePoolGetInfo has to be implemented manually */ + +/* remoteDispatchStoragePoolIsActive has to be implemented manually */ + +/* remoteDispatchStoragePoolIsPersistent has to be implemented manually */ + +/* remoteDispatchStoragePoolListVolumes has to be implemented manually */ + +/* remoteDispatchStoragePoolLookupByName has to be implemented manually */ + +/* remoteDispatchStoragePoolLookupByUuid has to be implemented manually */ + +/* remoteDispatchStoragePoolLookupByVolume has to be implemented manually */ + +/* remoteDispatchStoragePoolNumOfVolumes has to be implemented manually */ + +static int +remoteDispatchStoragePoolRefresh( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_refresh_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if (virStoragePoolRefresh(pool, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} + +static int +remoteDispatchStoragePoolSetAutostart( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_set_autostart_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if (virStoragePoolSetAutostart(pool, args->autostart) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} + +static int +remoteDispatchStoragePoolUndefine( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_pool_undefine_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virStoragePoolPtr pool = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(pool = get_nonnull_storage_pool(conn, args->pool))) + goto cleanup; + + if (virStoragePoolUndefine(pool) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (pool) + virStoragePoolFree(pool); + return rv; +} + +/* remoteDispatchStorageVolCreateXml has to be implemented manually */ + +/* remoteDispatchStorageVolCreateXmlFrom has to be implemented manually */ + +static int +remoteDispatchStorageVolDelete( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_vol_delete_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virStorageVolPtr vol = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(vol = get_nonnull_storage_vol(conn, args->vol))) + goto cleanup; + + if (virStorageVolDelete(vol, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (vol) + virStorageVolFree(vol); + return rv; +} + +/* remoteDispatchStorageVolDownload has to be implemented manually */ + +/* remoteDispatchStorageVolDumpXml has to be implemented manually */ + +/* remoteDispatchStorageVolGetInfo has to be implemented manually */ + +/* remoteDispatchStorageVolGetPath has to be implemented manually */ + +/* remoteDispatchStorageVolLookupByKey has to be implemented manually */ + +/* remoteDispatchStorageVolLookupByName has to be implemented manually */ + +/* remoteDispatchStorageVolLookupByPath has to be implemented manually */ + +/* remoteDispatchStorageVolUpload has to be implemented manually */ + +static int +remoteDispatchStorageVolWipe( + struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_storage_vol_wipe_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int rv = -1; + virStorageVolPtr vol = NULL; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(vol = get_nonnull_storage_vol(conn, args->vol))) + goto cleanup; + + if (virStorageVolWipe(vol, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (vol) + virStorageVolFree(vol); + return rv; +} + +/* remoteDispatchSupportsFeature has to be implemented manually */ + diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index a029b85..29ae5ba 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -1258,7 +1258,7 @@ static int remoteDispatchNumOfStoragePools( remote_error *rerr, void *args, remote_num_of_storage_pools_ret *ret); -static int remoteDispatchNwfilterDefineXml( +static int remoteDispatchNWFilterDefineXml( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1266,7 +1266,7 @@ static int remoteDispatchNwfilterDefineXml( remote_error *rerr, remote_nwfilter_define_xml_args *args, remote_nwfilter_define_xml_ret *ret); -static int remoteDispatchNwfilterGetXmlDesc( +static int remoteDispatchNWFilterGetXmlDesc( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1274,7 +1274,7 @@ static int remoteDispatchNwfilterGetXmlDesc( remote_error *rerr, remote_nwfilter_get_xml_desc_args *args, remote_nwfilter_get_xml_desc_ret *ret); -static int remoteDispatchNwfilterLookupByName( +static int remoteDispatchNWFilterLookupByName( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1282,7 +1282,7 @@ static int remoteDispatchNwfilterLookupByName( remote_error *rerr, remote_nwfilter_lookup_by_name_args *args, remote_nwfilter_lookup_by_name_ret *ret); -static int remoteDispatchNwfilterLookupByUuid( +static int remoteDispatchNWFilterLookupByUuid( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, @@ -1290,7 +1290,7 @@ static int remoteDispatchNwfilterLookupByUuid( remote_error *rerr, remote_nwfilter_lookup_by_uuid_args *args, remote_nwfilter_lookup_by_uuid_ret *ret); -static int remoteDispatchNwfilterUndefine( +static int remoteDispatchNWFilterUndefine( struct qemud_server *server, struct qemud_client *client, virConnectPtr conn, diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index d2ce08c..d711abc 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -877,18 +877,18 @@ .args_filter = (xdrproc_t) xdr_remote_domain_update_device_flags_args, .ret_filter = (xdrproc_t) xdr_void, }, -{ /* NwfilterLookupByName => 175 */ - .fn = (dispatch_fn) remoteDispatchNwfilterLookupByName, +{ /* NWFilterLookupByName => 175 */ + .fn = (dispatch_fn) remoteDispatchNWFilterLookupByName, .args_filter = (xdrproc_t) xdr_remote_nwfilter_lookup_by_name_args, .ret_filter = (xdrproc_t) xdr_remote_nwfilter_lookup_by_name_ret, }, -{ /* NwfilterLookupByUuid => 176 */ - .fn = (dispatch_fn) remoteDispatchNwfilterLookupByUuid, +{ /* NWFilterLookupByUuid => 176 */ + .fn = (dispatch_fn) remoteDispatchNWFilterLookupByUuid, .args_filter = (xdrproc_t) xdr_remote_nwfilter_lookup_by_uuid_args, .ret_filter = (xdrproc_t) xdr_remote_nwfilter_lookup_by_uuid_ret, }, -{ /* NwfilterGetXmlDesc => 177 */ - .fn = (dispatch_fn) remoteDispatchNwfilterGetXmlDesc, +{ /* NWFilterGetXmlDesc => 177 */ + .fn = (dispatch_fn) remoteDispatchNWFilterGetXmlDesc, .args_filter = (xdrproc_t) xdr_remote_nwfilter_get_xml_desc_args, .ret_filter = (xdrproc_t) xdr_remote_nwfilter_get_xml_desc_ret, }, @@ -902,13 +902,13 @@ .args_filter = (xdrproc_t) xdr_remote_list_nwfilters_args, .ret_filter = (xdrproc_t) xdr_remote_list_nwfilters_ret, }, -{ /* NwfilterDefineXml => 180 */ - .fn = (dispatch_fn) remoteDispatchNwfilterDefineXml, +{ /* NWFilterDefineXml => 180 */ + .fn = (dispatch_fn) remoteDispatchNWFilterDefineXml, .args_filter = (xdrproc_t) xdr_remote_nwfilter_define_xml_args, .ret_filter = (xdrproc_t) xdr_remote_nwfilter_define_xml_ret, }, -{ /* NwfilterUndefine => 181 */ - .fn = (dispatch_fn) remoteDispatchNwfilterUndefine, +{ /* NWFilterUndefine => 181 */ + .fn = (dispatch_fn) remoteDispatchNWFilterUndefine, .args_filter = (xdrproc_t) xdr_remote_nwfilter_undefine_args, .ret_filter = (xdrproc_t) xdr_void, }, diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index e4cade6..bf971e2 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -13,14 +13,15 @@ # remote_generator.pl -t qemu ../src/remote/qemu_protocol.x # # By Richard Jones +# Extended by Matthias Bolte use strict; use Getopt::Std; # Command line options. -our ($opt_p, $opt_t, $opt_a, $opt_r, $opt_d, $opt_c); -getopts ('ptardc'); +our ($opt_p, $opt_t, $opt_a, $opt_r, $opt_d, $opt_c, $opt_b); +getopts ('ptardcb'); my $structprefix = $ARGV[0]; my $procprefix = uc $structprefix; @@ -31,6 +32,7 @@ sub name_to_ProcName { my $name = shift; my @elems = split /_/, $name; @elems = map ucfirst, @elems; + @elems = map { $_ eq "Nwfilter" ? "NWFilter" : $_ } @elems; join "", @elems } @@ -50,8 +52,17 @@ if ($opt_c) { }; } +my $collect_args_members = 0; +my $last_name; + while (<>) { - if (/^struct ${structprefix}_(.*)_args/) { + if ($collect_args_members) { + if (/^};/) { + $collect_args_members = 0; + } elsif ($_ =~ m/^\s*(.*\S)\s*$/) { + push(@{$calls{$name}->{args_members}}, $1); + } + } elsif (/^struct ${structprefix}_(.*)_args/) { $name = $1; $ProcName = name_to_ProcName ($name); @@ -63,9 +74,12 @@ while (<>) { ProcName => $ProcName, UC_NAME => uc $name, args => "${structprefix}_${name}_args", - ret => "void", + args_members => [], + ret => "void" }; + $collect_args_members = 1; + $last_name = $name; } elsif (/^struct ${structprefix}_(.*)_ret/) { $name = $1; $ProcName = name_to_ProcName ($name); @@ -81,6 +95,8 @@ while (<>) { ret => "${structprefix}_${name}_ret" } } + + $collect_args_members = 0; } elsif (/^struct ${structprefix}_(.*)_msg/) { $name = $1; $ProcName = name_to_ProcName ($name); @@ -90,13 +106,19 @@ while (<>) { ProcName => $ProcName, UC_NAME => uc $name, msg => "${structprefix}_${name}_msg" - } + }; + + $collect_args_members = 0; } elsif (/^\s*${procprefix}_PROC_(.*?)\s+=\s+(\d+),?$/) { $name = lc $1; $id = $2; $ProcName = name_to_ProcName ($name); $calls[$id] = $calls{$name}; + + $collect_args_members = 0; + } else { + $collect_args_members = 0; } } @@ -193,3 +215,225 @@ elsif ($opt_t) { } } } + +# Bodies for dispatch functions ("remote_dispatch_bodies.c"). +elsif ($opt_b) { + # list of functions that currently are not generatable + my @ungeneratable; + + if ($structprefix eq "remote") { + @ungeneratable = ("Close", + "DomainEventsDeregisterAny", + "DomainEventsRegisterAny", + "DomainMigratePerform", + "DomainMigratePrepareTunnel", + "DomainOpenConsole", + "DomainPinVcpu", + "DomainSetSchedulerParameters", + "DomainSetMemoryParameters", + "DomainSetBlkioParameters", + "Open", + "StorageVolUpload", + "StorageVolDownload"); + } elsif ($structprefix eq "qemu") { + @ungeneratable = ("MonitorCommand"); + } + + my %ug = map { $_ => 1 } @ungeneratable; + my @keys = sort (keys %calls); + + foreach (@keys) { + # skip things which are REMOTE_MESSAGE + next if $calls{$_}->{msg}; + + # FIXME: skip functions with explicit return value for now + if ($calls{$_}->{ret} ne "void" or exists($ug{$calls{$_}->{ProcName}})) { + print "/* ${structprefix}Dispatch$calls{$_}->{ProcName} has to be implemented manually */\n\n"; + next; + } + + print "static int\n"; + print "${structprefix}Dispatch$calls{$_}->{ProcName}(\n"; + print " struct qemud_server *server ATTRIBUTE_UNUSED,\n"; + print " struct qemud_client *client ATTRIBUTE_UNUSED,\n"; + print " virConnectPtr conn,\n"; + print " remote_message_header *hdr ATTRIBUTE_UNUSED,\n"; + print " remote_error *rerr,\n"; + print " $calls{$_}->{args} *args"; + + if ($calls{$_}->{args} eq "void") { + print " ATTRIBUTE_UNUSED" + } + + print ",\n"; + print " $calls{$_}->{ret} *ret"; + + if ($calls{$_}->{ret} eq "void") { + print " ATTRIBUTE_UNUSED" + } + + print ")\n"; + print "{\n"; + print " int rv = -1;\n"; + + my $has_node_device = 0; + my @vars_list = (); + my @getters_list = (); + my @args_list = (); + my @free_list = (); + + if ($calls{$_}->{args} ne "void") { + # node device is special, as it's identified by name + if ($calls{$_}->{args} =~ m/^remote_node_device/) { + $has_node_device = 1; + push(@vars_list, "virNodeDevicePtr dev = NULL"); + push(@getters_list, + " if (!(dev = virNodeDeviceLookupByName(conn, args->name)))\n" . + " goto cleanup;\n"); + push(@args_list, "dev"); + push(@free_list, + " if (dev)\n" . + " virNodeDeviceFree(dev);"); + } + + foreach my $args_member (@{$calls{$_}->{args_members}}) { + if ($args_member =~ m/^remote_nonnull_string name;/ and $has_node_device) { + # ignore the name arg for node devices + next + } elsif ($args_member =~ m/^remote_nonnull_domain /) { + push(@vars_list, "virDomainPtr dom = NULL"); + push(@getters_list, + " if (!(dom = get_nonnull_domain(conn, args->dom)))\n" . + " goto cleanup;\n"); + push(@args_list, "dom"); + push(@free_list, + " if (dom)\n" . + " virDomainFree(dom);"); + } elsif ($args_member =~ m/^remote_nonnull_network /) { + push(@vars_list, "virNetworkPtr net = NULL"); + push(@getters_list, + " if (!(net = get_nonnull_network(conn, args->net)))\n" . + " goto cleanup;\n"); + push(@args_list, "net"); + push(@free_list, + " if (net)\n" . + " virNetworkFree(net);"); + } elsif ($args_member =~ m/^remote_nonnull_storage_pool /) { + push(@vars_list, "virStoragePoolPtr pool = NULL"); + push(@getters_list, + " if (!(pool = get_nonnull_storage_pool(conn, args->pool)))\n" . + " goto cleanup;\n"); + push(@args_list, "pool"); + push(@free_list, + " if (pool)\n" . + " virStoragePoolFree(pool);"); + } elsif ($args_member =~ m/^remote_nonnull_storage_vol /) { + push(@vars_list, "virStorageVolPtr vol = NULL"); + push(@getters_list, + " if (!(vol = get_nonnull_storage_vol(conn, args->vol)))\n" . + " goto cleanup;\n"); + push(@args_list, "vol"); + push(@free_list, + " if (vol)\n" . + " virStorageVolFree(vol);"); + } elsif ($args_member =~ m/^remote_nonnull_interface /) { + push(@vars_list, "virInterfacePtr iface = NULL"); + push(@getters_list, + " if (!(iface = get_nonnull_interface(conn, args->iface)))\n" . + " goto cleanup;\n"); + push(@args_list, "iface"); + push(@free_list, + " if (iface)\n" . + " virInterfaceFree(iface);"); + } elsif ($args_member =~ m/^remote_nonnull_secret /) { + push(@vars_list, "virSecretPtr secret = NULL"); + push(@getters_list, + " if (!(secret = get_nonnull_secret(conn, args->secret)))\n" . + " goto cleanup;\n"); + push(@args_list, "secret"); + push(@free_list, + " if (secret)\n" . + " virSecretFree(secret);"); + } elsif ($args_member =~ m/^remote_nonnull_nwfilter /) { + push(@vars_list, "virNWFilterPtr nwfilter = NULL"); + push(@getters_list, + " if (!(nwfilter = get_nonnull_nwfilter(conn, args->nwfilter)))\n" . + " goto cleanup;\n"); + push(@args_list, "nwfilter"); + push(@free_list, + " if (nwfilter)\n" . + " virNWFilterFree(nwfilter);"); + } elsif ($args_member =~ m/^remote_nonnull_domain_snapshot /) { + push(@vars_list, "virDomainPtr dom = NULL"); + push(@vars_list, "virDomainSnapshotPtr snapshot = NULL"); + push(@getters_list, + " if (!(dom = get_nonnull_domain(conn, args->snap.domain)))\n" . + " goto cleanup;\n" . + "\n" . + " if (!(snapshot = get_nonnull_domain_snapshot(dom, args->snap)))\n" . + " goto cleanup;\n"); + push(@args_list, "snapshot"); + push(@free_list, + " if (snapshot)\n" . + " virDomainSnapshotFree(snapshot);\n" . + " if (dom)\n" . + " virDomainFree(dom);"); + } elsif ($args_member =~ m/(\S+)<\S+>;/) { + if (! @args_list) { + push(@args_list, "conn"); + } + + if ($calls{$_}->{ProcName} eq "SecretSetValue") { + push(@args_list, "(const unsigned char *)args->$1.$1_val"); + } else { + push(@args_list, "args->$1.$1_val"); + } + + push(@args_list, "args->$1.$1_len"); + } elsif ($args_member =~ m/.* (\S+);/) { + if (! @args_list) { + push(@args_list, "conn"); + } + + push(@args_list, "args->$1"); + } + } + } + + foreach my $var (@vars_list) { + print " $var;\n"; + } + + print "\n"; + print " if (!conn) {\n"; + print " virNetError(VIR_ERR_INTERNAL_ERROR, \"%s\", _(\"connection not open\"));\n"; + print " goto cleanup;\n"; + print " }\n"; + print "\n"; + + print join("\n", @getters_list); + + print "\n"; + + if ($calls{$_}->{ret} eq "void") { + print " if (vir$calls{$_}->{ProcName}("; + print join(', ', @args_list); + print ") < 0)\n"; + print " goto cleanup;\n"; + print "\n"; + } + + print " rv = 0;\n"; + print "\n"; + print "cleanup:\n"; + print " if (rv < 0)\n"; + print " remoteDispatchError(rerr);\n"; + + print join("\n", @free_list); + + print "\n"; + print " return rv;\n"; + print "}\n"; + print "\n"; + } +} diff --git a/po/POTFILES.in b/po/POTFILES.in index 766f8f6..a3347bf 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -2,6 +2,7 @@ daemon/dispatch.c daemon/libvirtd.c daemon/remote.c daemon/stream.c +daemon/remote_dispatch_bodies.c src/conf/cpu_conf.c src/conf/domain_conf.c src/conf/domain_event.c diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index b9f1bc7..b02f082 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -540,9 +540,9 @@ struct remote_domain_interface_stats_ret { }; struct remote_domain_memory_stats_args { - remote_nonnull_domain dom; - u_int maxStats; - u_int flags; + remote_nonnull_domain dom; + u_int maxStats; + u_int flags; }; struct remote_domain_memory_stat { -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:14:02 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:14:02 +0200 Subject: [libvirt] [PATCH 15/22] remote generator, client: Handle simple remote driver functions In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-16-git-send-email-matthias.bolte@googlemail.com> Rename remoteSecretListSecrets to remoteListSecrets to match the normal naming pattern. --- cfg.mk | 8 +- daemon/remote_generator.pl | 335 +++++++++- src/Makefile.am | 13 +- src/remote/qemu_client_bodies.c | 4 + src/remote/remote_client_bodies.c | 1391 +++++++++++++++++++++++++++++++++++++ src/remote/remote_driver.c | 1116 +----------------------------- 6 files changed, 1750 insertions(+), 1117 deletions(-) create mode 100644 src/remote/qemu_client_bodies.c create mode 100644 src/remote/remote_client_bodies.c diff --git a/cfg.mk b/cfg.mk index a38ea48..82759bf 100644 --- a/cfg.mk +++ b/cfg.mk @@ -611,7 +611,7 @@ exclude_file_name_regexp--sc_prohibit_close = \ exclude_file_name_regexp--sc_prohibit_doubled_word = ^po/ exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \ - (^docs/api_extension/|^tests/qemuhelpdata/|\.(gif|ico|png)$$|daemon/.*_dispatch_bodies.c$$) + (^docs/api_extension/|^tests/qemuhelpdata/|\.(gif|ico|png)$$|^daemon/.*_dispatch_bodies.c$$|^src/remote/.*_client_bodies.c$$) _src2=src/(util/util|libvirt|lxc/lxc_controller) exclude_file_name_regexp--sc_prohibit_fork_wrappers = \ @@ -633,9 +633,11 @@ exclude_file_name_regexp--sc_prohibit_strncpy = \ exclude_file_name_regexp--sc_prohibit_xmlGetProp = ^src/util/xml\.c$$ -exclude_file_name_regexp--sc_require_config_h = ^(examples/|daemon/.*_dispatch_bodies.c$$) +exclude_file_name_regexp--sc_require_config_h = \ + ^(examples/|daemon/.*_dispatch_bodies.c$$|src/remote/.*_client_bodies.c$$) -exclude_file_name_regexp--sc_require_config_h_first = ^(examples/|daemon/.*_dispatch_bodies.c$$) +exclude_file_name_regexp--sc_require_config_h_first = \ + ^(examples/|daemon/.*_dispatch_bodies.c$$|src/remote/.*_client_bodies.c$$) exclude_file_name_regexp--sc_trailing_blank = (^docs/|\.(fig|gif|ico|png)$$) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 9fa3caa..73d1596 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -20,8 +20,8 @@ use strict; use Getopt::Std; # Command line options. -our ($opt_p, $opt_t, $opt_a, $opt_r, $opt_d, $opt_c, $opt_b); -getopts ('ptardcb'); +our ($opt_p, $opt_t, $opt_a, $opt_r, $opt_d, $opt_c, $opt_b, $opt_k); +getopts ('ptardcbk'); my $structprefix = $ARGV[0]; my $procprefix = uc $structprefix; @@ -724,3 +724,334 @@ elsif ($opt_b) { print "\n"; } } + +# Bodies for client functions ("remote_client_bodies.c"). +elsif ($opt_k) { + # list of functions that currently are not generatable + my @ungeneratable; + + if ($structprefix eq "remote") { + @ungeneratable = ("Close", + "DomainEventsDeregisterAny", + "DomainEventsRegisterAny", + "DomainMigratePrepareTunnel", + "DomainOpenConsole", + "DomainPinVcpu", + "DomainSetSchedulerParameters", + "DomainSetMemoryParameters", + "DomainSetBlkioParameters", + "Open", + "StorageVolUpload", + "StorageVolDownload", + + "AuthList", + "AuthSaslInit", + "AuthSaslStart", + "AuthSaslStep", + "AuthPolkit", + + "CPUBaseline", + "CPUCompare", + "DomainBlockStats", + "DomainCreate", + "DomainCreateXML", + "DomainDefineXML", + "DomainDestroy", + "DomainDumpXML", + "DomainGetAutostart", + "DomainGetBlockInfo", + "DomainGetInfo", + "StoragePoolLookupByUUID", + "StoragePoolNumOfVolumes", + "NodeDeviceCreateXML", + "DomainGetJobInfo", + "DomainGetMaxMemory", + "DomainGetOSType", + "DomainGetVcpusFlags", + "HasCurrentSnapshot", + "DomainInterfaceStats", + "DomainIsActive", + "DomainIsPersistent", + "DomainIsUpdated", + "DomainLookupByID", + "DomainLookupByName", + "DomainLookupByUIID", + "DomainMigrateFinish", + "DomainGetMaxVcpus", + "DomainHasCurrentSnapshot", + "NWFilterDefineXML", + "NumOfStoragePools", + "NWFilterLookupByName", + "NWFilterLookupByUUID", + "SecretLookupByUUID", + "SecretLookupByUsage", + "StoragePoolCreateXML", + "StoragePoolIsActive", + "DomainHasManagedSaveImage", + "DomainLookupByUUID", + "DomainMigratePerform", + "DomainMigrateFinish2", + "DomainSnapshotCreateXML", + "DomainSnapshotDumpXML", + "DomainSnapshotNum", + "DomainSnapshotCurrent", + "DomainSnapshotListNames", + "GetCapabilities", + "GetHostname", + "GetLibVersion", + "GetMaxVcpus", + "DomainSnapshotLookupByName", + "DomainXMLFromNative", + "FindStoragePoolSources", + "GetSysinfo", + "GetVersion", + "GetLibVersion", + "InterfaceDefineXML", + "InterfaceGetXMLDesc", + "InterfaceLookupByName", + "IsSecure", + "ListDefinedDomains", + "ListDefinedInterfaces", + "ListNWFilters", + "NetworkCreateXML", + "SupportsFeature", + "StorageVolLookupByPath", + "StorageVolGetInfo", + "StorageVolCreateXML", + "StorageVolLookupByName", + "StorageVolLookupByKey", + "StoragePoolIsPersistent", + "StoragePoolGetInfo", + "StorageVolGetPath", + "StorageVolCreateXMLFrom", + "StoragePoolLookupByName", + "SecretGetXMLDesc", + "NWFilterGetXMLDesc", + "NumOfNWFilters", + "NumOfInterfaces", + "NumOfDomains", + "NumOfDefinedStoragePools", + "NodeListDevices", + "NodeGetCellsFreeMemory", + "NodeDeviceDumpXML", + "NetworkIsActive", + "ListDefinedNetworks", + "DomainXMLToNative", + "StorageVolDumpXML", + "StoragePoolListVolumes", + "StoragePoolDumpXML", + "SecretDefineXML", + "NumOfDefinedNetworks", + "InterfaceIsActive", + "ListDomains", + "ListStoragePools", + "NetworkDumpXML", + "NetworkGetAutostart", + "NetworkGetBridgeName", + "StoragePoolLookupByVolume", + "StoragePoolGetAutostart", + "SecretSetValue", + "NumOfDefinedInterfaces", + "StoragePoolDefineXML", + "NodeNumOfDevices", + "NodeGetInfo", + "GetURI", + "InterfaceLookupByMACString", + "ListInterfaces", + "NetworkDefineXML", + "NetworkLookupByName", + "ListDefinedStoragePools", + "NetworkIsPersistent", + "NodeDeviceDettach", + "NodeDeviceLookupByName", + "NodeGetFreeMemory", + "NumOfDefinedDomains", + "ListNetworks", + "NodeDeviceListCaps", + "NodeDeviceReset", + "NumOfNetworks", + "NetworkLookupByUUID", + "NodeDeviceNumOfCaps", + "NumOfSecrets", + "NodeDeviceReAttach", + "ListSecrets", + + "DomainBlockPeek", + "DomainCreateWithFlags", + "DomainEventsDeregister", + "DomainEventsRegister", + "DomainGetBlkioParameters", + "DomainGetMemoryParameters", + "DomainGetSchedulerParameters", + "DomainGetSchedulerType", + "DomainGetSecurityLabel", + "DomainGetVcpus", + "DomainMemoryPeek", + "DomainMemoryStats", + "DomainMigratePrepare", + "DomainMigratePrepare2", + "GetType", + "NodeDeviceGetParent", + "NodeGetSecurityModel", + "SecretGetValue"); + } elsif ($structprefix eq "qemu") { + @ungeneratable = ("MonitorCommand"); + } + + my %ug = map { $_ => 1 } @ungeneratable; + my @keys = sort (keys %calls); + + foreach (@keys) { + my $call = $calls{$_}; + + # skip things which are REMOTE_MESSAGE + next if $call->{msg}; + + if (exists($ug{$call->{ProcName}})) { + print "/* ${structprefix}Dispatch$call->{ProcName} has to " . + "be implemented manually */\n\n"; + next; + } + + my @args_list = (); + my @vars_list = (); + my @setters_list = (); + my $priv_src = "conn"; + my $priv_name = "privateData"; + my $args = "&args"; + my $ret = "&ret"; + + if ($call->{args} eq "void") { + $args = "NULL"; + } else { + push(@vars_list, "$call->{args} args"); + + my $is_first_arg = 1; + my $has_node_device = 0; + + # node device is special + if ($call->{args} =~ m/^remote_node_device_/) { + $has_node_device = 1; + } + + foreach my $args_member (@{$call->{args_members}}) { + if ($args_member =~ m/^remote_nonnull_string name;/ and $has_node_device) { + $priv_src = "dev->conn"; + $priv_name = "devMonPrivateData"; + push(@args_list, "virNodeDevicePtr dev"); + push(@setters_list, "args.name = dev->name;"); + } elsif ($args_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|secret|nwfilter|domain_snapshot) (\S+);/) { + my $name = $1; + my $type_name = name_to_ProcName($name); + + if ($is_first_arg) { + if ($name eq "domain_snapshot") { + $priv_src = "$2->domain->conn"; + } else { + $priv_src = "$2->conn"; + } + + if ($name =~ m/^storage_/) { + $priv_name = "storagePrivateData"; + } elsif (!($name =~ m/^domain/)) { + $priv_name = "${name}PrivateData"; + } + } + + push(@args_list, "vir${type_name}Ptr $2"); + push(@setters_list, "make_nonnull_$1(&args.$2, $2);"); + } elsif ($args_member =~ m/^remote_nonnull_string (\S+);/) { + push(@args_list, "const char *$1"); + push(@setters_list, "args.$1 = (char *)$1;"); + } elsif ($args_member =~ m/(\S+)<\S+>;/) { + # ignored for now + } elsif ($args_member =~ m/^(.*) (\S+);/) { + my $type_name = $1; + my $arg_name = $2; + + $type_name =~ s/hyper/long/; + $type_name =~ s/^unsigned$/unsigned int/; + $type_name =~ s/u_int/unsigned int/; + + if ($type_name eq "int") { + # fix bad decisions in the xdr protocol + if ($arg_name eq "flags" and + $call->{ProcName} ne "DomainCoreDump") { + $type_name = "unsigned int"; + } elsif ($arg_name eq "nvcpus" and + $call->{ProcName} eq "DomainSetVcpus") { + $type_name = "unsigned int"; + } + } + + if ($call->{ProcName} eq "DomainMigrateSetMaxDowntime" and + $arg_name eq "downtime") { + $type_name = "unsigned long long"; + } + + push(@args_list, "$type_name $arg_name"); + push(@setters_list, "args.$arg_name = $arg_name;"); + } elsif ($args_member =~ m/^\/*/) { + # ignore comments + } else { + die "unhandled type for argument value: $args_member"; + } + + if ($is_first_arg and $priv_src eq "conn") { + unshift(@args_list, "virConnectPtr conn"); + } + + $is_first_arg = 0; + } + } + + if ($call->{ret} eq "void") { + $ret = "NULL"; + } else { + push(@vars_list, "$call->{ret} ret"); + } + + # print function + print "static int\n"; + print "remote$call->{ProcName}("; + + print join(", ", @args_list); + + print ")\n"; + print "{\n"; + print " int rv = -1;\n"; + print " struct private_data *priv = $priv_src->$priv_name;\n"; + + foreach my $var (@vars_list) { + print " $var;\n"; + } + + print "\n"; + print " remoteDriverLock(priv);\n"; + print "\n"; + + if (@setters_list) { + print " "; + } + + print join("\n ", @setters_list); + + if (@setters_list) { + print "\n"; + } + + print "\n"; + print " if (call($priv_src, priv, 0, ${procprefix}_PROC_$call->{UC_NAME},\n"; + print " (xdrproc_t)xdr_$call->{args}, (char *)$args,\n"; + print " (xdrproc_t)xdr_$call->{ret}, (char *)$ret) == -1)\n"; + print " goto done;\n"; + print "\n"; + print " rv = 0;\n"; + print "\n"; + print "done:\n"; + print " remoteDriverUnlock(priv);\n"; + print " return rv;\n"; + print "}\n"; + print "\n"; + } +} diff --git a/src/Makefile.am b/src/Makefile.am index 1eaa7d1..8ba176d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -162,8 +162,19 @@ REMOTE_DRIVER_SOURCES = \ remote/qemu_protocol.c \ remote/qemu_protocol.h +remote/remote_driver.c: remote/remote_client_bodies.c remote/qemu_client_bodies.c + +REMOTE_PROTOCOL = $(top_srcdir)/src/remote/remote_protocol.x +QEMU_PROTOCOL = $(top_srcdir)/src/remote/qemu_protocol.x + +remote/remote_client_bodies.c: $(top_srcdir)/daemon/remote_generator.pl $(REMOTE_PROTOCOL) + $(AM_V_GEN)perl -w $(top_srcdir)/daemon/remote_generator.pl -c -k remote $(REMOTE_PROTOCOL) > $@ + +remote/qemu_client_bodies.c: $(top_srcdir)/daemon/remote_generator.pl $(QEMU_PROTOCOL) + $(AM_V_GEN)perl -w $(top_srcdir)/daemon/remote_generator.pl -k remote $(QEMU_PROTOCOL) > $@ + EXTRA_DIST += remote/remote_protocol.x remote/qemu_protocol.x \ - remote/rpcgen_fix.pl + remote/rpcgen_fix.pl remote/remote_client_bodies.c remote/qemu_client_bodies.c # Ensure that we don't change the struct or member names or member ordering # in remote_protocol.x The embedded perl below needs a few comments, and diff --git a/src/remote/qemu_client_bodies.c b/src/remote/qemu_client_bodies.c new file mode 100644 index 0000000..dd66ba3 --- /dev/null +++ b/src/remote/qemu_client_bodies.c @@ -0,0 +1,4 @@ +/* Automatically generated by remote_generator.pl. + * Do not edit this file. Any changes you make will be lost. + */ + diff --git a/src/remote/remote_client_bodies.c b/src/remote/remote_client_bodies.c new file mode 100644 index 0000000..07ddfbf --- /dev/null +++ b/src/remote/remote_client_bodies.c @@ -0,0 +1,1391 @@ +/* Automatically generated by remote_generator.pl. + * Do not edit this file. Any changes you make will be lost. + */ + +/* remoteDispatchAuthList has to be implemented manually */ + +/* remoteDispatchAuthPolkit has to be implemented manually */ + +/* remoteDispatchAuthSaslInit has to be implemented manually */ + +/* remoteDispatchAuthSaslStart has to be implemented manually */ + +/* remoteDispatchAuthSaslStep has to be implemented manually */ + +/* remoteDispatchClose has to be implemented manually */ + +/* remoteDispatchCPUBaseline has to be implemented manually */ + +/* remoteDispatchCPUCompare has to be implemented manually */ + +static int +remoteDomainAbortJob(virDomainPtr dom) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_abort_job_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_ABORT_JOB, + (xdrproc_t)xdr_remote_domain_abort_job_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainAttachDevice(virDomainPtr dom, const char *xml) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_attach_device_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.xml = (char *)xml; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_ATTACH_DEVICE, + (xdrproc_t)xdr_remote_domain_attach_device_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_attach_device_flags_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.xml = (char *)xml; + args.flags = flags; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_ATTACH_DEVICE_FLAGS, + (xdrproc_t)xdr_remote_domain_attach_device_flags_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchDomainBlockPeek has to be implemented manually */ + +/* remoteDispatchDomainBlockStats has to be implemented manually */ + +static int +remoteDomainCoreDump(virDomainPtr dom, const char *to, int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_core_dump_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.to = (char *)to; + args.flags = flags; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_CORE_DUMP, + (xdrproc_t)xdr_remote_domain_core_dump_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchDomainCreate has to be implemented manually */ + +/* remoteDispatchDomainCreateWithFlags has to be implemented manually */ + +/* remoteDispatchDomainCreateXML has to be implemented manually */ + +/* remoteDispatchDomainDefineXML has to be implemented manually */ + +/* remoteDispatchDomainDestroy has to be implemented manually */ + +static int +remoteDomainDetachDevice(virDomainPtr dom, const char *xml) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_detach_device_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.xml = (char *)xml; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_DETACH_DEVICE, + (xdrproc_t)xdr_remote_domain_detach_device_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_detach_device_flags_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.xml = (char *)xml; + args.flags = flags; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_DETACH_DEVICE_FLAGS, + (xdrproc_t)xdr_remote_domain_detach_device_flags_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchDomainDumpXML has to be implemented manually */ + +/* remoteDispatchDomainEventsDeregister has to be implemented manually */ + +/* remoteDispatchDomainEventsDeregisterAny has to be implemented manually */ + +/* remoteDispatchDomainEventsRegister has to be implemented manually */ + +/* remoteDispatchDomainEventsRegisterAny has to be implemented manually */ + +/* remoteDispatchDomainGetAutostart has to be implemented manually */ + +/* remoteDispatchDomainGetBlkioParameters has to be implemented manually */ + +/* remoteDispatchDomainGetBlockInfo has to be implemented manually */ + +/* remoteDispatchDomainGetInfo has to be implemented manually */ + +/* remoteDispatchDomainGetJobInfo has to be implemented manually */ + +/* remoteDispatchDomainGetMaxMemory has to be implemented manually */ + +/* remoteDispatchDomainGetMaxVcpus has to be implemented manually */ + +/* remoteDispatchDomainGetMemoryParameters has to be implemented manually */ + +/* remoteDispatchDomainGetOSType has to be implemented manually */ + +/* remoteDispatchDomainGetSchedulerParameters has to be implemented manually */ + +/* remoteDispatchDomainGetSchedulerType has to be implemented manually */ + +/* remoteDispatchDomainGetSecurityLabel has to be implemented manually */ + +/* remoteDispatchDomainGetVcpus has to be implemented manually */ + +/* remoteDispatchDomainGetVcpusFlags has to be implemented manually */ + +/* remoteDispatchDomainHasCurrentSnapshot has to be implemented manually */ + +/* remoteDispatchDomainHasManagedSaveImage has to be implemented manually */ + +/* remoteDispatchDomainInterfaceStats has to be implemented manually */ + +/* remoteDispatchDomainIsActive has to be implemented manually */ + +/* remoteDispatchDomainIsPersistent has to be implemented manually */ + +/* remoteDispatchDomainIsUpdated has to be implemented manually */ + +/* remoteDispatchDomainLookupByID has to be implemented manually */ + +/* remoteDispatchDomainLookupByName has to be implemented manually */ + +/* remoteDispatchDomainLookupByUUID has to be implemented manually */ + +static int +remoteDomainManagedSave(virDomainPtr dom, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_managed_save_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.flags = flags; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MANAGED_SAVE, + (xdrproc_t)xdr_remote_domain_managed_save_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_managed_save_remove_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.flags = flags; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MANAGED_SAVE_REMOVE, + (xdrproc_t)xdr_remote_domain_managed_save_remove_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchDomainMemoryPeek has to be implemented manually */ + +/* remoteDispatchDomainMemoryStats has to be implemented manually */ + +/* remoteDispatchDomainMigrateFinish has to be implemented manually */ + +/* remoteDispatchDomainMigrateFinish2 has to be implemented manually */ + +/* remoteDispatchDomainMigratePerform has to be implemented manually */ + +/* remoteDispatchDomainMigratePrepare has to be implemented manually */ + +/* remoteDispatchDomainMigratePrepare2 has to be implemented manually */ + +/* remoteDispatchDomainMigratePrepareTunnel has to be implemented manually */ + +static int +remoteDomainMigrateSetMaxDowntime(virDomainPtr dom, unsigned long long downtime, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_migrate_set_max_downtime_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.downtime = downtime; + args.flags = flags; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_DOWNTIME, + (xdrproc_t)xdr_remote_domain_migrate_set_max_downtime_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainMigrateSetMaxSpeed(virDomainPtr dom, unsigned long bandwidth, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_migrate_set_max_speed_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.bandwidth = bandwidth; + args.flags = flags; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED, + (xdrproc_t)xdr_remote_domain_migrate_set_max_speed_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchDomainOpenConsole has to be implemented manually */ + +/* remoteDispatchDomainPinVcpu has to be implemented manually */ + +static int +remoteDomainReboot(virDomainPtr dom, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_reboot_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.flags = flags; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_REBOOT, + (xdrproc_t)xdr_remote_domain_reboot_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainRestore(virConnectPtr conn, const char *from) +{ + int rv = -1; + struct private_data *priv = conn->privateData; + remote_domain_restore_args args; + + remoteDriverLock(priv); + + args.from = (char *)from; + + if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_RESTORE, + (xdrproc_t)xdr_remote_domain_restore_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainResume(virDomainPtr dom) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_resume_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_RESUME, + (xdrproc_t)xdr_remote_domain_resume_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainRevertToSnapshot(virDomainSnapshotPtr snap, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = snap->domain->conn->privateData; + remote_domain_revert_to_snapshot_args args; + + remoteDriverLock(priv); + + make_nonnull_domain_snapshot(&args.snap, snap); + args.flags = flags; + + if (call(snap->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT, + (xdrproc_t)xdr_remote_domain_revert_to_snapshot_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainSave(virDomainPtr dom, const char *to) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_save_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.to = (char *)to; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SAVE, + (xdrproc_t)xdr_remote_domain_save_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainSetAutostart(virDomainPtr dom, int autostart) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_set_autostart_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.autostart = autostart; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_AUTOSTART, + (xdrproc_t)xdr_remote_domain_set_autostart_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchDomainSetBlkioParameters has to be implemented manually */ + +static int +remoteDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_set_max_memory_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.memory = memory; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MAX_MEMORY, + (xdrproc_t)xdr_remote_domain_set_max_memory_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainSetMemory(virDomainPtr dom, unsigned long memory) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_set_memory_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.memory = memory; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MEMORY, + (xdrproc_t)xdr_remote_domain_set_memory_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainSetMemoryFlags(virDomainPtr dom, unsigned long memory, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_set_memory_flags_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.memory = memory; + args.flags = flags; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MEMORY_FLAGS, + (xdrproc_t)xdr_remote_domain_set_memory_flags_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchDomainSetMemoryParameters has to be implemented manually */ + +/* remoteDispatchDomainSetSchedulerParameters has to be implemented manually */ + +static int +remoteDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_set_vcpus_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.nvcpus = nvcpus; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_VCPUS, + (xdrproc_t)xdr_remote_domain_set_vcpus_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_set_vcpus_flags_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.nvcpus = nvcpus; + args.flags = flags; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS, + (xdrproc_t)xdr_remote_domain_set_vcpus_flags_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainShutdown(virDomainPtr dom) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_shutdown_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SHUTDOWN, + (xdrproc_t)xdr_remote_domain_shutdown_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchDomainSnapshotCreateXML has to be implemented manually */ + +/* remoteDispatchDomainSnapshotCurrent has to be implemented manually */ + +static int +remoteDomainSnapshotDelete(virDomainSnapshotPtr snap, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = snap->domain->conn->privateData; + remote_domain_snapshot_delete_args args; + + remoteDriverLock(priv); + + make_nonnull_domain_snapshot(&args.snap, snap); + args.flags = flags; + + if (call(snap->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE, + (xdrproc_t)xdr_remote_domain_snapshot_delete_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchDomainSnapshotDumpXML has to be implemented manually */ + +/* remoteDispatchDomainSnapshotListNames has to be implemented manually */ + +/* remoteDispatchDomainSnapshotLookupByName has to be implemented manually */ + +/* remoteDispatchDomainSnapshotNum has to be implemented manually */ + +static int +remoteDomainSuspend(virDomainPtr dom) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_suspend_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SUSPEND, + (xdrproc_t)xdr_remote_domain_suspend_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainUndefine(virDomainPtr dom) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_undefine_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_UNDEFINE, + (xdrproc_t)xdr_remote_domain_undefine_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_update_device_flags_args args; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.xml = (char *)xml; + args.flags = flags; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_UPDATE_DEVICE_FLAGS, + (xdrproc_t)xdr_remote_domain_update_device_flags_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchDomainXMLFromNative has to be implemented manually */ + +/* remoteDispatchDomainXMLToNative has to be implemented manually */ + +/* remoteDispatchFindStoragePoolSources has to be implemented manually */ + +/* remoteDispatchGetCapabilities has to be implemented manually */ + +/* remoteDispatchGetHostname has to be implemented manually */ + +/* remoteDispatchGetLibVersion has to be implemented manually */ + +/* remoteDispatchGetMaxVcpus has to be implemented manually */ + +/* remoteDispatchGetSysinfo has to be implemented manually */ + +/* remoteDispatchGetType has to be implemented manually */ + +/* remoteDispatchGetURI has to be implemented manually */ + +/* remoteDispatchGetVersion has to be implemented manually */ + +static int +remoteInterfaceCreate(virInterfacePtr iface, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = iface->conn->interfacePrivateData; + remote_interface_create_args args; + + remoteDriverLock(priv); + + make_nonnull_interface(&args.iface, iface); + args.flags = flags; + + if (call(iface->conn, priv, 0, REMOTE_PROC_INTERFACE_CREATE, + (xdrproc_t)xdr_remote_interface_create_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchInterfaceDefineXML has to be implemented manually */ + +static int +remoteInterfaceDestroy(virInterfacePtr iface, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = iface->conn->interfacePrivateData; + remote_interface_destroy_args args; + + remoteDriverLock(priv); + + make_nonnull_interface(&args.iface, iface); + args.flags = flags; + + if (call(iface->conn, priv, 0, REMOTE_PROC_INTERFACE_DESTROY, + (xdrproc_t)xdr_remote_interface_destroy_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchInterfaceGetXMLDesc has to be implemented manually */ + +/* remoteDispatchInterfaceIsActive has to be implemented manually */ + +/* remoteDispatchInterfaceLookupByMACString has to be implemented manually */ + +/* remoteDispatchInterfaceLookupByName has to be implemented manually */ + +static int +remoteInterfaceUndefine(virInterfacePtr iface) +{ + int rv = -1; + struct private_data *priv = iface->conn->interfacePrivateData; + remote_interface_undefine_args args; + + remoteDriverLock(priv); + + make_nonnull_interface(&args.iface, iface); + + if (call(iface->conn, priv, 0, REMOTE_PROC_INTERFACE_UNDEFINE, + (xdrproc_t)xdr_remote_interface_undefine_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchIsSecure has to be implemented manually */ + +/* remoteDispatchListDefinedDomains has to be implemented manually */ + +/* remoteDispatchListDefinedInterfaces has to be implemented manually */ + +/* remoteDispatchListDefinedNetworks has to be implemented manually */ + +/* remoteDispatchListDefinedStoragePools has to be implemented manually */ + +/* remoteDispatchListDomains has to be implemented manually */ + +/* remoteDispatchListInterfaces has to be implemented manually */ + +/* remoteDispatchListNetworks has to be implemented manually */ + +/* remoteDispatchListNWFilters has to be implemented manually */ + +/* remoteDispatchListSecrets has to be implemented manually */ + +/* remoteDispatchListStoragePools has to be implemented manually */ + +static int +remoteNetworkCreate(virNetworkPtr net) +{ + int rv = -1; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_create_args args; + + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_CREATE, + (xdrproc_t)xdr_remote_network_create_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchNetworkCreateXML has to be implemented manually */ + +/* remoteDispatchNetworkDefineXML has to be implemented manually */ + +static int +remoteNetworkDestroy(virNetworkPtr net) +{ + int rv = -1; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_destroy_args args; + + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_DESTROY, + (xdrproc_t)xdr_remote_network_destroy_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchNetworkDumpXML has to be implemented manually */ + +/* remoteDispatchNetworkGetAutostart has to be implemented manually */ + +/* remoteDispatchNetworkGetBridgeName has to be implemented manually */ + +/* remoteDispatchNetworkIsActive has to be implemented manually */ + +/* remoteDispatchNetworkIsPersistent has to be implemented manually */ + +/* remoteDispatchNetworkLookupByName has to be implemented manually */ + +/* remoteDispatchNetworkLookupByUUID has to be implemented manually */ + +static int +remoteNetworkSetAutostart(virNetworkPtr net, int autostart) +{ + int rv = -1; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_set_autostart_args args; + + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + args.autostart = autostart; + + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_SET_AUTOSTART, + (xdrproc_t)xdr_remote_network_set_autostart_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteNetworkUndefine(virNetworkPtr net) +{ + int rv = -1; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_undefine_args args; + + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_UNDEFINE, + (xdrproc_t)xdr_remote_network_undefine_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchNodeDeviceCreateXML has to be implemented manually */ + +static int +remoteNodeDeviceDestroy(virNodeDevicePtr dev) +{ + int rv = -1; + struct private_data *priv = dev->conn->devMonPrivateData; + remote_node_device_destroy_args args; + + remoteDriverLock(priv); + + args.name = dev->name; + + if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DESTROY, + (xdrproc_t)xdr_remote_node_device_destroy_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchNodeDeviceDettach has to be implemented manually */ + +/* remoteDispatchNodeDeviceDumpXML has to be implemented manually */ + +/* remoteDispatchNodeDeviceGetParent has to be implemented manually */ + +/* remoteDispatchNodeDeviceListCaps has to be implemented manually */ + +/* remoteDispatchNodeDeviceLookupByName has to be implemented manually */ + +/* remoteDispatchNodeDeviceNumOfCaps has to be implemented manually */ + +/* remoteDispatchNodeDeviceReAttach has to be implemented manually */ + +/* remoteDispatchNodeDeviceReset has to be implemented manually */ + +/* remoteDispatchNodeGetCellsFreeMemory has to be implemented manually */ + +/* remoteDispatchNodeGetFreeMemory has to be implemented manually */ + +/* remoteDispatchNodeGetInfo has to be implemented manually */ + +/* remoteDispatchNodeGetSecurityModel has to be implemented manually */ + +/* remoteDispatchNodeListDevices has to be implemented manually */ + +/* remoteDispatchNodeNumOfDevices has to be implemented manually */ + +/* remoteDispatchNumOfDefinedDomains has to be implemented manually */ + +/* remoteDispatchNumOfDefinedInterfaces has to be implemented manually */ + +/* remoteDispatchNumOfDefinedNetworks has to be implemented manually */ + +/* remoteDispatchNumOfDefinedStoragePools has to be implemented manually */ + +/* remoteDispatchNumOfDomains has to be implemented manually */ + +/* remoteDispatchNumOfInterfaces has to be implemented manually */ + +/* remoteDispatchNumOfNetworks has to be implemented manually */ + +/* remoteDispatchNumOfNWFilters has to be implemented manually */ + +/* remoteDispatchNumOfSecrets has to be implemented manually */ + +/* remoteDispatchNumOfStoragePools has to be implemented manually */ + +/* remoteDispatchNWFilterDefineXML has to be implemented manually */ + +/* remoteDispatchNWFilterGetXMLDesc has to be implemented manually */ + +/* remoteDispatchNWFilterLookupByName has to be implemented manually */ + +/* remoteDispatchNWFilterLookupByUUID has to be implemented manually */ + +static int +remoteNWFilterUndefine(virNWFilterPtr nwfilter) +{ + int rv = -1; + struct private_data *priv = nwfilter->conn->nwfilterPrivateData; + remote_nwfilter_undefine_args args; + + remoteDriverLock(priv); + + make_nonnull_nwfilter(&args.nwfilter, nwfilter); + + if (call(nwfilter->conn, priv, 0, REMOTE_PROC_NWFILTER_UNDEFINE, + (xdrproc_t)xdr_remote_nwfilter_undefine_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchOpen has to be implemented manually */ + +/* remoteDispatchSecretDefineXML has to be implemented manually */ + +/* remoteDispatchSecretGetValue has to be implemented manually */ + +/* remoteDispatchSecretGetXMLDesc has to be implemented manually */ + +/* remoteDispatchSecretLookupByUsage has to be implemented manually */ + +/* remoteDispatchSecretLookupByUUID has to be implemented manually */ + +/* remoteDispatchSecretSetValue has to be implemented manually */ + +static int +remoteSecretUndefine(virSecretPtr secret) +{ + int rv = -1; + struct private_data *priv = secret->conn->secretPrivateData; + remote_secret_undefine_args args; + + remoteDriverLock(priv); + + make_nonnull_secret(&args.secret, secret); + + if (call(secret->conn, priv, 0, REMOTE_PROC_SECRET_UNDEFINE, + (xdrproc_t)xdr_remote_secret_undefine_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteStoragePoolBuild(virStoragePoolPtr pool, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_build_args args; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + args.flags = flags; + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_BUILD, + (xdrproc_t)xdr_remote_storage_pool_build_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteStoragePoolCreate(virStoragePoolPtr pool, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_create_args args; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + args.flags = flags; + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_CREATE, + (xdrproc_t)xdr_remote_storage_pool_create_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchStoragePoolCreateXML has to be implemented manually */ + +/* remoteDispatchStoragePoolDefineXML has to be implemented manually */ + +static int +remoteStoragePoolDelete(virStoragePoolPtr pool, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_delete_args args; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + args.flags = flags; + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DELETE, + (xdrproc_t)xdr_remote_storage_pool_delete_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteStoragePoolDestroy(virStoragePoolPtr pool) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_destroy_args args; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DESTROY, + (xdrproc_t)xdr_remote_storage_pool_destroy_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchStoragePoolDumpXML has to be implemented manually */ + +/* remoteDispatchStoragePoolGetAutostart has to be implemented manually */ + +/* remoteDispatchStoragePoolGetInfo has to be implemented manually */ + +/* remoteDispatchStoragePoolIsActive has to be implemented manually */ + +/* remoteDispatchStoragePoolIsPersistent has to be implemented manually */ + +/* remoteDispatchStoragePoolListVolumes has to be implemented manually */ + +/* remoteDispatchStoragePoolLookupByName has to be implemented manually */ + +/* remoteDispatchStoragePoolLookupByUUID has to be implemented manually */ + +/* remoteDispatchStoragePoolLookupByVolume has to be implemented manually */ + +/* remoteDispatchStoragePoolNumOfVolumes has to be implemented manually */ + +static int +remoteStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_refresh_args args; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + args.flags = flags; + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_REFRESH, + (xdrproc_t)xdr_remote_storage_pool_refresh_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteStoragePoolSetAutostart(virStoragePoolPtr pool, int autostart) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_set_autostart_args args; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + args.autostart = autostart; + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_SET_AUTOSTART, + (xdrproc_t)xdr_remote_storage_pool_set_autostart_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteStoragePoolUndefine(virStoragePoolPtr pool) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_undefine_args args; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_UNDEFINE, + (xdrproc_t)xdr_remote_storage_pool_undefine_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchStorageVolCreateXML has to be implemented manually */ + +/* remoteDispatchStorageVolCreateXMLFrom has to be implemented manually */ + +static int +remoteStorageVolDelete(virStorageVolPtr vol, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = vol->conn->storagePrivateData; + remote_storage_vol_delete_args args; + + remoteDriverLock(priv); + + make_nonnull_storage_vol(&args.vol, vol); + args.flags = flags; + + if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_DELETE, + (xdrproc_t)xdr_remote_storage_vol_delete_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchStorageVolDownload has to be implemented manually */ + +/* remoteDispatchStorageVolDumpXML has to be implemented manually */ + +/* remoteDispatchStorageVolGetInfo has to be implemented manually */ + +/* remoteDispatchStorageVolGetPath has to be implemented manually */ + +/* remoteDispatchStorageVolLookupByKey has to be implemented manually */ + +/* remoteDispatchStorageVolLookupByName has to be implemented manually */ + +/* remoteDispatchStorageVolLookupByPath has to be implemented manually */ + +/* remoteDispatchStorageVolUpload has to be implemented manually */ + +static int +remoteStorageVolWipe(virStorageVolPtr vol, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = vol->conn->storagePrivateData; + remote_storage_vol_wipe_args args; + + remoteDriverLock(priv); + + make_nonnull_storage_vol(&args.vol, vol); + args.flags = flags; + + if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_WIPE, + (xdrproc_t)xdr_remote_storage_vol_wipe_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +/* remoteDispatchSupportsFeature has to be implemented manually */ + diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 934fdda..bf4d866 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2249,99 +2249,6 @@ done: } static int -remoteDomainSuspend (virDomainPtr domain) -{ - int rv = -1; - remote_domain_suspend_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SUSPEND, - (xdrproc_t) xdr_remote_domain_suspend_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainResume (virDomainPtr domain) -{ - int rv = -1; - remote_domain_resume_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_RESUME, - (xdrproc_t) xdr_remote_domain_resume_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainShutdown (virDomainPtr domain) -{ - int rv = -1; - remote_domain_shutdown_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SHUTDOWN, - (xdrproc_t) xdr_remote_domain_shutdown_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainReboot (virDomainPtr domain, unsigned int flags) -{ - int rv = -1; - remote_domain_reboot_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.flags = flags; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_REBOOT, - (xdrproc_t) xdr_remote_domain_reboot_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteDomainDestroy (virDomainPtr domain) { int rv = -1; @@ -2417,81 +2324,6 @@ done: } static int -remoteDomainSetMaxMemory (virDomainPtr domain, unsigned long memory) -{ - int rv = -1; - remote_domain_set_max_memory_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.memory = memory; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MAX_MEMORY, - (xdrproc_t) xdr_remote_domain_set_max_memory_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainSetMemory (virDomainPtr domain, unsigned long memory) -{ - int rv = -1; - remote_domain_set_memory_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.memory = memory; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MEMORY, - (xdrproc_t) xdr_remote_domain_set_memory_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainSetMemoryFlags (virDomainPtr domain, unsigned long memory, unsigned int flags) -{ - int rv = -1; - remote_domain_set_memory_flags_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.memory = memory; - args.flags = flags; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MEMORY_FLAGS, - (xdrproc_t) xdr_remote_domain_set_memory_flags_args, - (char *) &args, - (xdrproc_t) xdr_void, - (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteDomainSetMemoryParameters (virDomainPtr domain, virMemoryParameterPtr params, int nparams, @@ -2861,129 +2693,6 @@ done: } static int -remoteDomainSave (virDomainPtr domain, const char *to) -{ - int rv = -1; - remote_domain_save_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.to = (char *) to; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SAVE, - (xdrproc_t) xdr_remote_domain_save_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainRestore (virConnectPtr conn, const char *from) -{ - int rv = -1; - remote_domain_restore_args args; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - args.from = (char *) from; - - if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_RESTORE, - (xdrproc_t) xdr_remote_domain_restore_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainCoreDump (virDomainPtr domain, const char *to, int flags) -{ - int rv = -1; - remote_domain_core_dump_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.to = (char *) to; - args.flags = flags; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_CORE_DUMP, - (xdrproc_t) xdr_remote_domain_core_dump_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainSetVcpus (virDomainPtr domain, unsigned int nvcpus) -{ - int rv = -1; - remote_domain_set_vcpus_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.nvcpus = nvcpus; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_VCPUS, - (xdrproc_t) xdr_remote_domain_set_vcpus_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainSetVcpusFlags (virDomainPtr domain, unsigned int nvcpus, - unsigned int flags) -{ - int rv = -1; - remote_domain_set_vcpus_flags_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.nvcpus = nvcpus; - args.flags = flags; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS, - (xdrproc_t) xdr_remote_domain_set_vcpus_flags_args, - (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteDomainGetVcpusFlags (virDomainPtr domain, unsigned int flags) { int rv = -1; @@ -3696,155 +3405,6 @@ done: } static int -remoteDomainUndefine (virDomainPtr domain) -{ - int rv = -1; - remote_domain_undefine_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_UNDEFINE, - (xdrproc_t) xdr_remote_domain_undefine_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainAttachDevice (virDomainPtr domain, const char *xml) -{ - int rv = -1; - remote_domain_attach_device_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.xml = (char *) xml; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_ATTACH_DEVICE, - (xdrproc_t) xdr_remote_domain_attach_device_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainAttachDeviceFlags (virDomainPtr domain, const char *xml, - unsigned int flags) -{ - int rv = -1; - remote_domain_attach_device_flags_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.xml = (char *) xml; - args.flags = flags; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_ATTACH_DEVICE_FLAGS, - (xdrproc_t) xdr_remote_domain_attach_device_flags_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainDetachDevice (virDomainPtr domain, const char *xml) -{ - int rv = -1; - remote_domain_detach_device_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.xml = (char *) xml; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_DETACH_DEVICE, - (xdrproc_t) xdr_remote_domain_detach_device_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainDetachDeviceFlags (virDomainPtr domain, const char *xml, - unsigned int flags) -{ - int rv = -1; - remote_domain_detach_device_flags_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.xml = (char *) xml; - args.flags = flags; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_DETACH_DEVICE_FLAGS, - (xdrproc_t) xdr_remote_domain_detach_device_flags_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainUpdateDeviceFlags (virDomainPtr domain, const char *xml, - unsigned int flags) -{ - int rv = -1; - remote_domain_update_device_flags_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.xml = (char *) xml; - args.flags = flags; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_UPDATE_DEVICE_FLAGS, - (xdrproc_t) xdr_remote_domain_update_device_flags_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteDomainGetAutostart (virDomainPtr domain, int *autostart) { int rv = -1; @@ -3870,30 +3430,6 @@ done: return rv; } -static int -remoteDomainSetAutostart (virDomainPtr domain, int autostart) -{ - int rv = -1; - remote_domain_set_autostart_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.autostart = autostart; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_AUTOSTART, - (xdrproc_t) xdr_remote_domain_set_autostart_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - static char * remoteDomainGetSchedulerType (virDomainPtr domain, int *nparams) { @@ -4311,30 +3847,6 @@ done: } static int -remoteDomainManagedSave (virDomainPtr domain, unsigned int flags) -{ - int rv = -1; - remote_domain_managed_save_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.flags = flags; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MANAGED_SAVE, - (xdrproc_t) xdr_remote_domain_managed_save_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteDomainHasManagedSaveImage (virDomainPtr domain, unsigned int flags) { int rv = -1; @@ -4359,30 +3871,6 @@ done: return rv; } -static int -remoteDomainManagedSaveRemove (virDomainPtr domain, unsigned int flags) -{ - int rv = -1; - remote_domain_managed_save_remove_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.flags = flags; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MANAGED_SAVE_REMOVE, - (xdrproc_t) xdr_remote_domain_managed_save_remove_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -4762,75 +4250,6 @@ done: return net; } -static int -remoteNetworkUndefine (virNetworkPtr network) -{ - int rv = -1; - remote_network_undefine_args args; - struct private_data *priv = network->conn->networkPrivateData; - - remoteDriverLock(priv); - - make_nonnull_network (&args.net, network); - - if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_UNDEFINE, - (xdrproc_t) xdr_remote_network_undefine_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteNetworkCreate (virNetworkPtr network) -{ - int rv = -1; - remote_network_create_args args; - struct private_data *priv = network->conn->networkPrivateData; - - remoteDriverLock(priv); - - make_nonnull_network (&args.net, network); - - if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_CREATE, - (xdrproc_t) xdr_remote_network_create_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteNetworkDestroy (virNetworkPtr network) -{ - int rv = -1; - remote_network_destroy_args args; - struct private_data *priv = network->conn->networkPrivateData; - - remoteDriverLock(priv); - - make_nonnull_network (&args.net, network); - - if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_DESTROY, - (xdrproc_t) xdr_remote_network_destroy_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - static char * remoteNetworkDumpXML (virNetworkPtr network, int flags) { @@ -4911,33 +4330,6 @@ done: return rv; } -static int -remoteNetworkSetAutostart (virNetworkPtr network, int autostart) -{ - int rv = -1; - remote_network_set_autostart_args args; - struct private_data *priv = network->conn->networkPrivateData; - - remoteDriverLock(priv); - - make_nonnull_network (&args.net, network); - args.autostart = autostart; - - if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_SET_AUTOSTART, - (xdrproc_t) xdr_remote_network_set_autostart_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - - - - /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -5299,79 +4691,6 @@ done: return iface; } -static int -remoteInterfaceUndefine (virInterfacePtr iface) -{ - int rv = -1; - remote_interface_undefine_args args; - struct private_data *priv = iface->conn->interfacePrivateData; - - remoteDriverLock(priv); - - make_nonnull_interface (&args.iface, iface); - - if (call (iface->conn, priv, 0, REMOTE_PROC_INTERFACE_UNDEFINE, - (xdrproc_t) xdr_remote_interface_undefine_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteInterfaceCreate (virInterfacePtr iface, - unsigned int flags) -{ - int rv = -1; - remote_interface_create_args args; - struct private_data *priv = iface->conn->interfacePrivateData; - - remoteDriverLock(priv); - - make_nonnull_interface (&args.iface, iface); - args.flags = flags; - - if (call (iface->conn, priv, 0, REMOTE_PROC_INTERFACE_CREATE, - (xdrproc_t) xdr_remote_interface_create_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteInterfaceDestroy (virInterfacePtr iface, - unsigned int flags) -{ - int rv = -1; - remote_interface_destroy_args args; - struct private_data *priv = iface->conn->interfacePrivateData; - - remoteDriverLock(priv); - - make_nonnull_interface (&args.iface, iface); - args.flags = flags; - - if (call (iface->conn, priv, 0, REMOTE_PROC_INTERFACE_DESTROY, - (xdrproc_t) xdr_remote_interface_destroy_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -5826,151 +5145,6 @@ done: } static int -remoteStoragePoolUndefine (virStoragePoolPtr pool) -{ - int rv = -1; - remote_storage_pool_undefine_args args; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_UNDEFINE, - (xdrproc_t) xdr_remote_storage_pool_undefine_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteStoragePoolCreate (virStoragePoolPtr pool, unsigned int flags) -{ - int rv = -1; - remote_storage_pool_create_args args; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - args.flags = flags; - - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_CREATE, - (xdrproc_t) xdr_remote_storage_pool_create_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteStoragePoolBuild (virStoragePoolPtr pool, - unsigned int flags) -{ - int rv = -1; - remote_storage_pool_build_args args; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - args.flags = flags; - - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_BUILD, - (xdrproc_t) xdr_remote_storage_pool_build_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteStoragePoolDestroy (virStoragePoolPtr pool) -{ - int rv = -1; - remote_storage_pool_destroy_args args; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DESTROY, - (xdrproc_t) xdr_remote_storage_pool_destroy_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteStoragePoolDelete (virStoragePoolPtr pool, - unsigned int flags) -{ - int rv = -1; - remote_storage_pool_delete_args args; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - args.flags = flags; - - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DELETE, - (xdrproc_t) xdr_remote_storage_pool_delete_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteStoragePoolRefresh (virStoragePoolPtr pool, - unsigned int flags) -{ - int rv = -1; - remote_storage_pool_refresh_args args; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - args.flags = flags; - - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_REFRESH, - (xdrproc_t) xdr_remote_storage_pool_refresh_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteStoragePoolGetInfo (virStoragePoolPtr pool, virStoragePoolInfoPtr info) { int rv = -1; @@ -6056,31 +5230,6 @@ done: } static int -remoteStoragePoolSetAutostart (virStoragePoolPtr pool, int autostart) -{ - int rv = -1; - remote_storage_pool_set_autostart_args args; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - args.autostart = autostart; - - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_SET_AUTOSTART, - (xdrproc_t) xdr_remote_storage_pool_set_autostart_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - - -static int remoteStoragePoolNumOfVolumes (virStoragePoolPtr pool) { int rv = -1; @@ -6307,57 +5456,6 @@ done: } static int -remoteStorageVolDelete (virStorageVolPtr vol, - unsigned int flags) -{ - int rv = -1; - remote_storage_vol_delete_args args; - struct private_data *priv = vol->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_vol (&args.vol, vol); - args.flags = flags; - - if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_DELETE, - (xdrproc_t) xdr_remote_storage_vol_delete_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteStorageVolWipe(virStorageVolPtr vol, - unsigned int flags) -{ - int rv = -1; - remote_storage_vol_wipe_args args; - struct private_data *priv = vol->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_vol(&args.vol, vol); - args.flags = flags; - - if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_WIPE, - (xdrproc_t) xdr_remote_storage_vol_wipe_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - - -static int remoteStorageVolGetInfo (virStorageVolPtr vol, virStorageVolInfoPtr info) { int rv = -1; @@ -6863,29 +5961,6 @@ done: return dev; } -static int -remoteNodeDeviceDestroy(virNodeDevicePtr dev) -{ - int rv = -1; - remote_node_device_destroy_args args; - struct private_data *priv = dev->conn->devMonPrivateData; - - remoteDriverLock(priv); - - args.name = dev->name; - - if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DESTROY, - (xdrproc_t) xdr_remote_node_device_destroy_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - /* ------------------------------------------------------------- */ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -6999,31 +6074,6 @@ done: return net; } - -static int -remoteNWFilterUndefine (virNWFilterPtr nwfilter) -{ - int rv = -1; - remote_nwfilter_undefine_args args; - struct private_data *priv = nwfilter->conn->nwfilterPrivateData; - - remoteDriverLock(priv); - - make_nonnull_nwfilter (&args.nwfilter, nwfilter); - - if (call (nwfilter->conn, priv, 0, REMOTE_PROC_NWFILTER_UNDEFINE, - (xdrproc_t) xdr_remote_nwfilter_undefine_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - - static int remoteListNWFilters (virConnectPtr conn, char **const names, int maxnames) { @@ -8252,7 +7302,7 @@ done: } static int -remoteSecretListSecrets (virConnectPtr conn, char **uuids, int maxuuids) +remoteListSecrets (virConnectPtr conn, char **uuids, int maxuuids) { int rv = -1; int i; @@ -8472,30 +7522,6 @@ done: return rv; } -static int -remoteSecretUndefine (virSecretPtr secret) -{ - int rv = -1; - remote_secret_undefine_args args; - struct private_data *priv = secret->conn->secretPrivateData; - - remoteDriverLock (priv); - - make_nonnull_secret (&args.secret, secret); - - if (call (secret->conn, priv, 0, REMOTE_PROC_SECRET_UNDEFINE, - (xdrproc_t) xdr_remote_secret_undefine_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock (priv); - return rv; -} - - static struct private_stream_data * remoteStreamOpen(virStreamPtr st, unsigned int proc_nr, @@ -9141,89 +8167,6 @@ done: return rv; } - -static int -remoteDomainAbortJob (virDomainPtr domain) -{ - int rv = -1; - remote_domain_abort_job_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_ABORT_JOB, - (xdrproc_t) xdr_remote_domain_abort_job_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - - -static int -remoteDomainMigrateSetMaxDowntime(virDomainPtr domain, - unsigned long long downtime, - unsigned int flags) -{ - struct private_data *priv = domain->conn->privateData; - remote_domain_migrate_set_max_downtime_args args; - int rv = -1; - - remoteDriverLock(priv); - - make_nonnull_domain(&args.dom, domain); - args.downtime = downtime; - args.flags = flags; - - if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_DOWNTIME, - (xdrproc_t) xdr_remote_domain_migrate_set_max_downtime_args, - (char *) &args, - (xdrproc_t) xdr_void, - (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainMigrateSetMaxSpeed(virDomainPtr domain, - unsigned long bandwidth, - unsigned int flags) -{ - struct private_data *priv = domain->conn->privateData; - remote_domain_migrate_set_max_speed_args args; - int rv = -1; - - remoteDriverLock(priv); - - make_nonnull_domain(&args.dom, domain); - args.bandwidth = bandwidth; - args.flags = flags; - - if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED, - (xdrproc_t) xdr_remote_domain_migrate_set_max_speed_args, - (char *) &args, - (xdrproc_t) xdr_void, - (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - static virDomainSnapshotPtr remoteDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc, @@ -9458,58 +8401,6 @@ done: return snapshot; } - -static int -remoteDomainRevertToSnapshot (virDomainSnapshotPtr snapshot, - unsigned int flags) -{ - int rv = -1; - remote_domain_revert_to_snapshot_args args; - struct private_data *priv = snapshot->domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain_snapshot(&args.snap, snapshot); - args.flags = flags; - - if (call (snapshot->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT, - (xdrproc_t) xdr_remote_domain_revert_to_snapshot_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - - -static int -remoteDomainSnapshotDelete (virDomainSnapshotPtr snapshot, - unsigned int flags) -{ - int rv = -1; - remote_domain_snapshot_delete_args args; - struct private_data *priv = snapshot->domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain_snapshot(&args.snap, snapshot); - args.flags = flags; - - if (call (snapshot->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE, - (xdrproc_t) xdr_remote_domain_snapshot_delete_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID, @@ -9770,6 +8661,9 @@ done: return rv; } +#include "remote_client_bodies.c" +#include "qemu_client_bodies.c" + /*----------------------------------------------------------------------*/ static struct remote_thread_call * @@ -11389,7 +10283,7 @@ static virSecretDriver secret_driver = { .open = remoteSecretOpen, .close = remoteSecretClose, .numOfSecrets = remoteSecretNumOfSecrets, - .listSecrets = remoteSecretListSecrets, + .listSecrets = remoteListSecrets, .lookupByUUID = remoteSecretLookupByUUID, .lookupByUsage = remoteSecretLookupByUsage, .defineXML = remoteSecretDefineXML, -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:14:03 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:14:03 +0200 Subject: [libvirt] [PATCH 16/22] remote generator, client: Handle functions with simple return values In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-17-git-send-email-matthias.bolte@googlemail.com> --- daemon/remote_generator.pl | 122 +++-- src/remote/remote_client_bodies.c | 1097 +++++++++++++++++++++++++++++++++++-- src/remote/remote_driver.c | 1081 +------------------------------------ 3 files changed, 1120 insertions(+), 1180 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 73d1596..a973b21 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -751,63 +751,42 @@ elsif ($opt_k) { "AuthPolkit", "CPUBaseline", - "CPUCompare", "DomainBlockStats", "DomainCreate", "DomainCreateXML", "DomainDefineXML", "DomainDestroy", - "DomainDumpXML", "DomainGetAutostart", "DomainGetBlockInfo", "DomainGetInfo", "StoragePoolLookupByUUID", - "StoragePoolNumOfVolumes", "NodeDeviceCreateXML", "DomainGetJobInfo", - "DomainGetMaxMemory", - "DomainGetOSType", - "DomainGetVcpusFlags", - "HasCurrentSnapshot", "DomainInterfaceStats", - "DomainIsActive", - "DomainIsPersistent", - "DomainIsUpdated", "DomainLookupByID", "DomainLookupByName", "DomainLookupByUIID", "DomainMigrateFinish", - "DomainGetMaxVcpus", - "DomainHasCurrentSnapshot", "NWFilterDefineXML", - "NumOfStoragePools", "NWFilterLookupByName", "NWFilterLookupByUUID", "SecretLookupByUUID", "SecretLookupByUsage", "StoragePoolCreateXML", - "StoragePoolIsActive", - "DomainHasManagedSaveImage", "DomainLookupByUUID", "DomainMigratePerform", "DomainMigrateFinish2", "DomainSnapshotCreateXML", - "DomainSnapshotDumpXML", - "DomainSnapshotNum", "DomainSnapshotCurrent", "DomainSnapshotListNames", - "GetCapabilities", - "GetHostname", "GetLibVersion", "GetMaxVcpus", "DomainSnapshotLookupByName", "DomainXMLFromNative", "FindStoragePoolSources", - "GetSysinfo", "GetVersion", "GetLibVersion", "InterfaceDefineXML", - "InterfaceGetXMLDesc", "InterfaceLookupByName", "IsSecure", "ListDefinedDomains", @@ -820,40 +799,22 @@ elsif ($opt_k) { "StorageVolCreateXML", "StorageVolLookupByName", "StorageVolLookupByKey", - "StoragePoolIsPersistent", "StoragePoolGetInfo", - "StorageVolGetPath", "StorageVolCreateXMLFrom", "StoragePoolLookupByName", - "SecretGetXMLDesc", - "NWFilterGetXMLDesc", - "NumOfNWFilters", - "NumOfInterfaces", - "NumOfDomains", - "NumOfDefinedStoragePools", "NodeListDevices", "NodeGetCellsFreeMemory", - "NodeDeviceDumpXML", - "NetworkIsActive", "ListDefinedNetworks", "DomainXMLToNative", - "StorageVolDumpXML", "StoragePoolListVolumes", - "StoragePoolDumpXML", "SecretDefineXML", - "NumOfDefinedNetworks", - "InterfaceIsActive", "ListDomains", "ListStoragePools", - "NetworkDumpXML", "NetworkGetAutostart", - "NetworkGetBridgeName", "StoragePoolLookupByVolume", "StoragePoolGetAutostart", "SecretSetValue", - "NumOfDefinedInterfaces", "StoragePoolDefineXML", - "NodeNumOfDevices", "NodeGetInfo", "GetURI", "InterfaceLookupByMACString", @@ -861,18 +822,13 @@ elsif ($opt_k) { "NetworkDefineXML", "NetworkLookupByName", "ListDefinedStoragePools", - "NetworkIsPersistent", "NodeDeviceDettach", "NodeDeviceLookupByName", "NodeGetFreeMemory", - "NumOfDefinedDomains", "ListNetworks", "NodeDeviceListCaps", "NodeDeviceReset", - "NumOfNetworks", "NetworkLookupByUUID", - "NodeDeviceNumOfCaps", - "NumOfSecrets", "NodeDeviceReAttach", "ListSecrets", @@ -916,13 +872,16 @@ elsif ($opt_k) { my @args_list = (); my @vars_list = (); my @setters_list = (); + my @ret_list = (); my $priv_src = "conn"; my $priv_name = "privateData"; - my $args = "&args"; - my $ret = "&ret"; + my $call_args = "&args"; + my $call_ret = "&ret"; + my $single_ret_var = "int rv = -1"; + my $single_ret_type = "int"; if ($call->{args} eq "void") { - $args = "NULL"; + $call_args = "NULL"; } else { push(@vars_list, "$call->{args} args"); @@ -930,14 +889,14 @@ elsif ($opt_k) { my $has_node_device = 0; # node device is special - if ($call->{args} =~ m/^remote_node_device_/) { + if ($call->{args} =~ m/^remote_node_/) { $has_node_device = 1; + $priv_name = "devMonPrivateData"; } foreach my $args_member (@{$call->{args_members}}) { if ($args_member =~ m/^remote_nonnull_string name;/ and $has_node_device) { $priv_src = "dev->conn"; - $priv_name = "devMonPrivateData"; push(@args_list, "virNodeDevicePtr dev"); push(@setters_list, "args.name = dev->name;"); } elsif ($args_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|secret|nwfilter|domain_snapshot) (\S+);/) { @@ -960,6 +919,9 @@ elsif ($opt_k) { push(@args_list, "vir${type_name}Ptr $2"); push(@setters_list, "make_nonnull_$1(&args.$2, $2);"); + } elsif ($args_member =~ m/^remote_string (\S+);/) { + push(@args_list, "const char *$1"); + push(@setters_list, "args.$1 = $1 ? (char **)&$1 : NULL;"); } elsif ($args_member =~ m/^remote_nonnull_string (\S+);/) { push(@args_list, "const char *$1"); push(@setters_list, "args.$1 = (char *)$1;"); @@ -976,7 +938,9 @@ elsif ($opt_k) { if ($type_name eq "int") { # fix bad decisions in the xdr protocol if ($arg_name eq "flags" and - $call->{ProcName} ne "DomainCoreDump") { + $call->{ProcName} ne "DomainCoreDump" and + $call->{ProcName} ne "DomainDumpXML" and + $call->{ProcName} ne "NetworkDumpXML") { $type_name = "unsigned int"; } elsif ($arg_name eq "nvcpus" and $call->{ProcName} eq "DomainSetVcpus") { @@ -1005,21 +969,52 @@ elsif ($opt_k) { } } + # fix priv_name for the NumOf* functions + if ($priv_name eq "privateData" and + !($call->{ProcName} =~ m/Domains/) and + $call->{ProcName} =~ m/NumOf(Defined|Domain)*(\S+)s/) { + my $prefix = lc $2; + $prefix =~ s/(pool|vol)$//; + $priv_name = "${prefix}PrivateData"; + } + if ($call->{ret} eq "void") { - $ret = "NULL"; + $call_ret = "NULL"; } else { push(@vars_list, "$call->{ret} ret"); + + foreach my $ret_member (@{$call->{ret_members}}) { + if ($ret_member =~ m/remote_nonnull_string (\S+);/) { + push(@ret_list, "rv = ret.$1;"); + $single_ret_var = "char *rv = NULL"; + $single_ret_type = "char *"; + } elsif ($ret_member =~ m/^int (\S+);/) { + push(@ret_list, "rv = ret.$1;"); + $single_ret_var = "int rv = -1"; + $single_ret_type = "int"; + } elsif ($ret_member =~ m/hyper (\S+);/) { + push(@ret_list, "rv = ret.$1;"); + $single_ret_var = "unsigned long rv = 0"; + $single_ret_type = "unsigned long"; + } else { + die "unhandled type for return value: $ret_member"; + } + } + } + + if (! @args_list) { + push(@args_list, "virConnectPtr conn"); } # print function - print "static int\n"; + print "static $single_ret_type\n"; print "remote$call->{ProcName}("; print join(", ", @args_list); print ")\n"; print "{\n"; - print " int rv = -1;\n"; + print " $single_ret_var;\n"; print " struct private_data *priv = $priv_src->$priv_name;\n"; foreach my $var (@vars_list) { @@ -1028,9 +1023,9 @@ elsif ($opt_k) { print "\n"; print " remoteDriverLock(priv);\n"; - print "\n"; if (@setters_list) { + print "\n"; print " "; } @@ -1040,13 +1035,26 @@ elsif ($opt_k) { print "\n"; } + if ($call->{ret} ne "void") { + print "\n"; + print " memset(&ret, 0, sizeof ret);\n"; + } + print "\n"; print " if (call($priv_src, priv, 0, ${procprefix}_PROC_$call->{UC_NAME},\n"; - print " (xdrproc_t)xdr_$call->{args}, (char *)$args,\n"; - print " (xdrproc_t)xdr_$call->{ret}, (char *)$ret) == -1)\n"; + print " (xdrproc_t)xdr_$call->{args}, (char *)$call_args,\n"; + print " (xdrproc_t)xdr_$call->{ret}, (char *)$call_ret) == -1)\n"; print " goto done;\n"; print "\n"; - print " rv = 0;\n"; + + if (@ret_list) { + print " "; + print join("\n ", @ret_list); + print "\n"; + } else { + print " rv = 0;\n"; + } + print "\n"; print "done:\n"; print " remoteDriverUnlock(priv);\n"; diff --git a/src/remote/remote_client_bodies.c b/src/remote/remote_client_bodies.c index 07ddfbf..b878832 100644 --- a/src/remote/remote_client_bodies.c +++ b/src/remote/remote_client_bodies.c @@ -16,7 +16,32 @@ /* remoteDispatchCPUBaseline has to be implemented manually */ -/* remoteDispatchCPUCompare has to be implemented manually */ +static int +remoteCPUCompare(virConnectPtr conn, const char *xml, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = conn->privateData; + remote_cpu_compare_args args; + remote_cpu_compare_ret ret; + + remoteDriverLock(priv); + + args.xml = (char *)xml; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_CPU_COMPARE, + (xdrproc_t)xdr_remote_cpu_compare_args, (char *)&args, + (xdrproc_t)xdr_remote_cpu_compare_ret, (char *)&ret) == -1) + goto done; + + rv = ret.result; + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteDomainAbortJob(virDomainPtr dom) @@ -178,7 +203,32 @@ done: return rv; } -/* remoteDispatchDomainDumpXML has to be implemented manually */ +static char * +remoteDomainDumpXML(virDomainPtr dom, int flags) +{ + char *rv = NULL; + struct private_data *priv = dom->conn->privateData; + remote_domain_dump_xml_args args; + remote_domain_dump_xml_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_DUMP_XML, + (xdrproc_t)xdr_remote_domain_dump_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_dump_xml_ret, (char *)&ret) == -1) + goto done; + + rv = ret.xml; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchDomainEventsDeregister has to be implemented manually */ @@ -198,13 +248,85 @@ done: /* remoteDispatchDomainGetJobInfo has to be implemented manually */ -/* remoteDispatchDomainGetMaxMemory has to be implemented manually */ +static unsigned long +remoteDomainGetMaxMemory(virDomainPtr dom) +{ + unsigned long rv = 0; + struct private_data *priv = dom->conn->privateData; + remote_domain_get_max_memory_args args; + remote_domain_get_max_memory_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MAX_MEMORY, + (xdrproc_t)xdr_remote_domain_get_max_memory_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_get_max_memory_ret, (char *)&ret) == -1) + goto done; -/* remoteDispatchDomainGetMaxVcpus has to be implemented manually */ + rv = ret.memory; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainGetMaxVcpus(virDomainPtr dom) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_get_max_vcpus_args args; + remote_domain_get_max_vcpus_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MAX_VCPUS, + (xdrproc_t)xdr_remote_domain_get_max_vcpus_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_get_max_vcpus_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchDomainGetMemoryParameters has to be implemented manually */ -/* remoteDispatchDomainGetOSType has to be implemented manually */ +static char * +remoteDomainGetOSType(virDomainPtr dom) +{ + char *rv = NULL; + struct private_data *priv = dom->conn->privateData; + remote_domain_get_os_type_args args; + remote_domain_get_os_type_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_OS_TYPE, + (xdrproc_t)xdr_remote_domain_get_os_type_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_get_os_type_ret, (char *)&ret) == -1) + goto done; + + rv = ret.type; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchDomainGetSchedulerParameters has to be implemented manually */ @@ -214,19 +336,166 @@ done: /* remoteDispatchDomainGetVcpus has to be implemented manually */ -/* remoteDispatchDomainGetVcpusFlags has to be implemented manually */ +static int +remoteDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_get_vcpus_flags_args args; + remote_domain_get_vcpus_flags_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS, + (xdrproc_t)xdr_remote_domain_get_vcpus_flags_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_get_vcpus_flags_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainHasCurrentSnapshot(virDomainPtr dom, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_has_current_snapshot_args args; + remote_domain_has_current_snapshot_ret ret; -/* remoteDispatchDomainHasCurrentSnapshot has to be implemented manually */ + remoteDriverLock(priv); -/* remoteDispatchDomainHasManagedSaveImage has to be implemented manually */ + make_nonnull_domain(&args.dom, dom); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_HAS_CURRENT_SNAPSHOT, + (xdrproc_t)xdr_remote_domain_has_current_snapshot_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_has_current_snapshot_ret, (char *)&ret) == -1) + goto done; + + rv = ret.result; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_has_managed_save_image_args args; + remote_domain_has_managed_save_image_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_HAS_MANAGED_SAVE_IMAGE, + (xdrproc_t)xdr_remote_domain_has_managed_save_image_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_has_managed_save_image_ret, (char *)&ret) == -1) + goto done; + + rv = ret.result; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchDomainInterfaceStats has to be implemented manually */ -/* remoteDispatchDomainIsActive has to be implemented manually */ +static int +remoteDomainIsActive(virDomainPtr dom) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_is_active_args args; + remote_domain_is_active_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_IS_ACTIVE, + (xdrproc_t)xdr_remote_domain_is_active_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_is_active_ret, (char *)&ret) == -1) + goto done; + + rv = ret.active; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainIsPersistent(virDomainPtr dom) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_is_persistent_args args; + remote_domain_is_persistent_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_IS_PERSISTENT, + (xdrproc_t)xdr_remote_domain_is_persistent_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_is_persistent_ret, (char *)&ret) == -1) + goto done; + + rv = ret.persistent; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainIsUpdated(virDomainPtr dom) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_is_updated_args args; + remote_domain_is_updated_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_IS_UPDATED, + (xdrproc_t)xdr_remote_domain_is_updated_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_is_updated_ret, (char *)&ret) == -1) + goto done; -/* remoteDispatchDomainIsPersistent has to be implemented manually */ + rv = ret.updated; -/* remoteDispatchDomainIsUpdated has to be implemented manually */ +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchDomainLookupByID has to be implemented manually */ @@ -673,13 +942,63 @@ done: return rv; } -/* remoteDispatchDomainSnapshotDumpXML has to be implemented manually */ +static char * +remoteDomainSnapshotDumpXML(virDomainSnapshotPtr snap, unsigned int flags) +{ + char *rv = NULL; + struct private_data *priv = snap->domain->conn->privateData; + remote_domain_snapshot_dump_xml_args args; + remote_domain_snapshot_dump_xml_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain_snapshot(&args.snap, snap); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(snap->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_DUMP_XML, + (xdrproc_t)xdr_remote_domain_snapshot_dump_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_snapshot_dump_xml_ret, (char *)&ret) == -1) + goto done; + + rv = ret.xml; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchDomainSnapshotListNames has to be implemented manually */ /* remoteDispatchDomainSnapshotLookupByName has to be implemented manually */ -/* remoteDispatchDomainSnapshotNum has to be implemented manually */ +static int +remoteDomainSnapshotNum(virDomainPtr dom, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_snapshot_num_args args; + remote_domain_snapshot_num_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_NUM, + (xdrproc_t)xdr_remote_domain_snapshot_num_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_snapshot_num_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteDomainSuspend(virDomainPtr dom) @@ -758,15 +1077,81 @@ done: /* remoteDispatchFindStoragePoolSources has to be implemented manually */ -/* remoteDispatchGetCapabilities has to be implemented manually */ +static char * +remoteGetCapabilities(virConnectPtr conn) +{ + char *rv = NULL; + struct private_data *priv = conn->privateData; + remote_get_capabilities_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_GET_CAPABILITIES, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_get_capabilities_ret, (char *)&ret) == -1) + goto done; + + rv = ret.capabilities; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static char * +remoteGetHostname(virConnectPtr conn) +{ + char *rv = NULL; + struct private_data *priv = conn->privateData; + remote_get_hostname_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); -/* remoteDispatchGetHostname has to be implemented manually */ + if (call(conn, priv, 0, REMOTE_PROC_GET_HOSTNAME, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_get_hostname_ret, (char *)&ret) == -1) + goto done; + + rv = ret.hostname; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchGetLibVersion has to be implemented manually */ /* remoteDispatchGetMaxVcpus has to be implemented manually */ -/* remoteDispatchGetSysinfo has to be implemented manually */ +static char * +remoteGetSysinfo(virConnectPtr conn, unsigned int flags) +{ + char *rv = NULL; + struct private_data *priv = conn->privateData; + remote_get_sysinfo_args args; + remote_get_sysinfo_ret ret; + + remoteDriverLock(priv); + + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_GET_SYSINFO, + (xdrproc_t)xdr_remote_get_sysinfo_args, (char *)&args, + (xdrproc_t)xdr_remote_get_sysinfo_ret, (char *)&ret) == -1) + goto done; + + rv = ret.sysinfo; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchGetType has to be implemented manually */ @@ -824,9 +1209,58 @@ done: return rv; } -/* remoteDispatchInterfaceGetXMLDesc has to be implemented manually */ +static char * +remoteInterfaceGetXMLDesc(virInterfacePtr iface, unsigned int flags) +{ + char *rv = NULL; + struct private_data *priv = iface->conn->interfacePrivateData; + remote_interface_get_xml_desc_args args; + remote_interface_get_xml_desc_ret ret; + + remoteDriverLock(priv); + + make_nonnull_interface(&args.iface, iface); + args.flags = flags; + + memset(&ret, 0, sizeof ret); -/* remoteDispatchInterfaceIsActive has to be implemented manually */ + if (call(iface->conn, priv, 0, REMOTE_PROC_INTERFACE_GET_XML_DESC, + (xdrproc_t)xdr_remote_interface_get_xml_desc_args, (char *)&args, + (xdrproc_t)xdr_remote_interface_get_xml_desc_ret, (char *)&ret) == -1) + goto done; + + rv = ret.xml; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteInterfaceIsActive(virInterfacePtr iface) +{ + int rv = -1; + struct private_data *priv = iface->conn->interfacePrivateData; + remote_interface_is_active_args args; + remote_interface_is_active_ret ret; + + remoteDriverLock(priv); + + make_nonnull_interface(&args.iface, iface); + + memset(&ret, 0, sizeof ret); + + if (call(iface->conn, priv, 0, REMOTE_PROC_INTERFACE_IS_ACTIVE, + (xdrproc_t)xdr_remote_interface_is_active_args, (char *)&args, + (xdrproc_t)xdr_remote_interface_is_active_ret, (char *)&ret) == -1) + goto done; + + rv = ret.active; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchInterfaceLookupByMACString has to be implemented manually */ @@ -927,15 +1361,112 @@ done: return rv; } -/* remoteDispatchNetworkDumpXML has to be implemented manually */ +static char * +remoteNetworkDumpXML(virNetworkPtr net, int flags) +{ + char *rv = NULL; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_dump_xml_args args; + remote_network_dump_xml_ret ret; + + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_DUMP_XML, + (xdrproc_t)xdr_remote_network_dump_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_network_dump_xml_ret, (char *)&ret) == -1) + goto done; + + rv = ret.xml; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchNetworkGetAutostart has to be implemented manually */ -/* remoteDispatchNetworkGetBridgeName has to be implemented manually */ +static char * +remoteNetworkGetBridgeName(virNetworkPtr net) +{ + char *rv = NULL; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_get_bridge_name_args args; + remote_network_get_bridge_name_ret ret; + + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + + memset(&ret, 0, sizeof ret); + + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_GET_BRIDGE_NAME, + (xdrproc_t)xdr_remote_network_get_bridge_name_args, (char *)&args, + (xdrproc_t)xdr_remote_network_get_bridge_name_ret, (char *)&ret) == -1) + goto done; + + rv = ret.name; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteNetworkIsActive(virNetworkPtr net) +{ + int rv = -1; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_is_active_args args; + remote_network_is_active_ret ret; + + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + + memset(&ret, 0, sizeof ret); + + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_IS_ACTIVE, + (xdrproc_t)xdr_remote_network_is_active_args, (char *)&args, + (xdrproc_t)xdr_remote_network_is_active_ret, (char *)&ret) == -1) + goto done; + + rv = ret.active; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteNetworkIsPersistent(virNetworkPtr net) +{ + int rv = -1; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_is_persistent_args args; + remote_network_is_persistent_ret ret; + + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + + memset(&ret, 0, sizeof ret); -/* remoteDispatchNetworkIsActive has to be implemented manually */ + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_IS_PERSISTENT, + (xdrproc_t)xdr_remote_network_is_persistent_args, (char *)&args, + (xdrproc_t)xdr_remote_network_is_persistent_ret, (char *)&ret) == -1) + goto done; -/* remoteDispatchNetworkIsPersistent has to be implemented manually */ + rv = ret.persistent; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchNetworkLookupByName has to be implemented manually */ @@ -1015,7 +1546,32 @@ done: /* remoteDispatchNodeDeviceDettach has to be implemented manually */ -/* remoteDispatchNodeDeviceDumpXML has to be implemented manually */ +static char * +remoteNodeDeviceDumpXML(virNodeDevicePtr dev, unsigned int flags) +{ + char *rv = NULL; + struct private_data *priv = dev->conn->devMonPrivateData; + remote_node_device_dump_xml_args args; + remote_node_device_dump_xml_ret ret; + + remoteDriverLock(priv); + + args.name = dev->name; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DUMP_XML, + (xdrproc_t)xdr_remote_node_device_dump_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_node_device_dump_xml_ret, (char *)&ret) == -1) + goto done; + + rv = ret.xml; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchNodeDeviceGetParent has to be implemented manually */ @@ -1023,7 +1579,31 @@ done: /* remoteDispatchNodeDeviceLookupByName has to be implemented manually */ -/* remoteDispatchNodeDeviceNumOfCaps has to be implemented manually */ +static int +remoteNodeDeviceNumOfCaps(virNodeDevicePtr dev) +{ + int rv = -1; + struct private_data *priv = dev->conn->devMonPrivateData; + remote_node_device_num_of_caps_args args; + remote_node_device_num_of_caps_ret ret; + + remoteDriverLock(priv); + + args.name = dev->name; + + memset(&ret, 0, sizeof ret); + + if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS, + (xdrproc_t)xdr_remote_node_device_num_of_caps_args, (char *)&args, + (xdrproc_t)xdr_remote_node_device_num_of_caps_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchNodeDeviceReAttach has to be implemented manually */ @@ -1039,31 +1619,291 @@ done: /* remoteDispatchNodeListDevices has to be implemented manually */ -/* remoteDispatchNodeNumOfDevices has to be implemented manually */ +static int +remoteNodeNumOfDevices(virConnectPtr conn, const char *cap, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = conn->devMonPrivateData; + remote_node_num_of_devices_args args; + remote_node_num_of_devices_ret ret; + + remoteDriverLock(priv); + + args.cap = cap ? (char **)&cap : NULL; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NODE_NUM_OF_DEVICES, + (xdrproc_t)xdr_remote_node_num_of_devices_args, (char *)&args, + (xdrproc_t)xdr_remote_node_num_of_devices_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteNumOfDefinedDomains(virConnectPtr conn) +{ + int rv = -1; + struct private_data *priv = conn->privateData; + remote_num_of_defined_domains_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_DOMAINS, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_num_of_defined_domains_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteNumOfDefinedInterfaces(virConnectPtr conn) +{ + int rv = -1; + struct private_data *priv = conn->interfacePrivateData; + remote_num_of_defined_interfaces_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_INTERFACES, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_num_of_defined_interfaces_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteNumOfDefinedNetworks(virConnectPtr conn) +{ + int rv = -1; + struct private_data *priv = conn->networkPrivateData; + remote_num_of_defined_networks_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_NETWORKS, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_num_of_defined_networks_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteNumOfDefinedStoragePools(virConnectPtr conn) +{ + int rv = -1; + struct private_data *priv = conn->storagePrivateData; + remote_num_of_defined_storage_pools_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_STORAGE_POOLS, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_num_of_defined_storage_pools_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteNumOfDomains(virConnectPtr conn) +{ + int rv = -1; + struct private_data *priv = conn->privateData; + remote_num_of_domains_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NUM_OF_DOMAINS, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_num_of_domains_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteNumOfInterfaces(virConnectPtr conn) +{ + int rv = -1; + struct private_data *priv = conn->interfacePrivateData; + remote_num_of_interfaces_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NUM_OF_INTERFACES, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_num_of_interfaces_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteNumOfNetworks(virConnectPtr conn) +{ + int rv = -1; + struct private_data *priv = conn->networkPrivateData; + remote_num_of_networks_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NUM_OF_NETWORKS, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_num_of_networks_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; -/* remoteDispatchNumOfDefinedDomains has to be implemented manually */ +done: + remoteDriverUnlock(priv); + return rv; +} -/* remoteDispatchNumOfDefinedInterfaces has to be implemented manually */ +static int +remoteNumOfNWFilters(virConnectPtr conn) +{ + int rv = -1; + struct private_data *priv = conn->nwfilterPrivateData; + remote_num_of_nwfilters_ret ret; + + remoteDriverLock(priv); -/* remoteDispatchNumOfDefinedNetworks has to be implemented manually */ + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NUM_OF_NWFILTERS, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_num_of_nwfilters_ret, (char *)&ret) == -1) + goto done; -/* remoteDispatchNumOfDefinedStoragePools has to be implemented manually */ + rv = ret.num; -/* remoteDispatchNumOfDomains has to be implemented manually */ +done: + remoteDriverUnlock(priv); + return rv; +} -/* remoteDispatchNumOfInterfaces has to be implemented manually */ +static int +remoteNumOfSecrets(virConnectPtr conn) +{ + int rv = -1; + struct private_data *priv = conn->secretPrivateData; + remote_num_of_secrets_ret ret; -/* remoteDispatchNumOfNetworks has to be implemented manually */ + remoteDriverLock(priv); -/* remoteDispatchNumOfNWFilters has to be implemented manually */ + memset(&ret, 0, sizeof ret); -/* remoteDispatchNumOfSecrets has to be implemented manually */ + if (call(conn, priv, 0, REMOTE_PROC_NUM_OF_SECRETS, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_num_of_secrets_ret, (char *)&ret) == -1) + goto done; -/* remoteDispatchNumOfStoragePools has to be implemented manually */ + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteNumOfStoragePools(virConnectPtr conn) +{ + int rv = -1; + struct private_data *priv = conn->storagePrivateData; + remote_num_of_storage_pools_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NUM_OF_STORAGE_POOLS, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_num_of_storage_pools_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchNWFilterDefineXML has to be implemented manually */ -/* remoteDispatchNWFilterGetXMLDesc has to be implemented manually */ +static char * +remoteNWFilterGetXMLDesc(virNWFilterPtr nwfilter, unsigned int flags) +{ + char *rv = NULL; + struct private_data *priv = nwfilter->conn->nwfilterPrivateData; + remote_nwfilter_get_xml_desc_args args; + remote_nwfilter_get_xml_desc_ret ret; + + remoteDriverLock(priv); + + make_nonnull_nwfilter(&args.nwfilter, nwfilter); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(nwfilter->conn, priv, 0, REMOTE_PROC_NWFILTER_GET_XML_DESC, + (xdrproc_t)xdr_remote_nwfilter_get_xml_desc_args, (char *)&args, + (xdrproc_t)xdr_remote_nwfilter_get_xml_desc_ret, (char *)&ret) == -1) + goto done; + + rv = ret.xml; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchNWFilterLookupByName has to be implemented manually */ @@ -1098,7 +1938,32 @@ done: /* remoteDispatchSecretGetValue has to be implemented manually */ -/* remoteDispatchSecretGetXMLDesc has to be implemented manually */ +static char * +remoteSecretGetXMLDesc(virSecretPtr secret, unsigned int flags) +{ + char *rv = NULL; + struct private_data *priv = secret->conn->secretPrivateData; + remote_secret_get_xml_desc_args args; + remote_secret_get_xml_desc_ret ret; + + remoteDriverLock(priv); + + make_nonnull_secret(&args.secret, secret); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(secret->conn, priv, 0, REMOTE_PROC_SECRET_GET_XML_DESC, + (xdrproc_t)xdr_remote_secret_get_xml_desc_args, (char *)&args, + (xdrproc_t)xdr_remote_secret_get_xml_desc_ret, (char *)&ret) == -1) + goto done; + + rv = ret.xml; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchSecretLookupByUsage has to be implemented manually */ @@ -1228,15 +2093,88 @@ done: return rv; } -/* remoteDispatchStoragePoolDumpXML has to be implemented manually */ +static char * +remoteStoragePoolDumpXML(virStoragePoolPtr pool, unsigned int flags) +{ + char *rv = NULL; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_dump_xml_args args; + remote_storage_pool_dump_xml_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DUMP_XML, + (xdrproc_t)xdr_remote_storage_pool_dump_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_pool_dump_xml_ret, (char *)&ret) == -1) + goto done; + + rv = ret.xml; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchStoragePoolGetAutostart has to be implemented manually */ /* remoteDispatchStoragePoolGetInfo has to be implemented manually */ -/* remoteDispatchStoragePoolIsActive has to be implemented manually */ +static int +remoteStoragePoolIsActive(virStoragePoolPtr pool) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_is_active_args args; + remote_storage_pool_is_active_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + + memset(&ret, 0, sizeof ret); + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_IS_ACTIVE, + (xdrproc_t)xdr_remote_storage_pool_is_active_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_pool_is_active_ret, (char *)&ret) == -1) + goto done; -/* remoteDispatchStoragePoolIsPersistent has to be implemented manually */ + rv = ret.active; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteStoragePoolIsPersistent(virStoragePoolPtr pool) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_is_persistent_args args; + remote_storage_pool_is_persistent_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + + memset(&ret, 0, sizeof ret); + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_IS_PERSISTENT, + (xdrproc_t)xdr_remote_storage_pool_is_persistent_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_pool_is_persistent_ret, (char *)&ret) == -1) + goto done; + + rv = ret.persistent; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchStoragePoolListVolumes has to be implemented manually */ @@ -1246,7 +2184,31 @@ done: /* remoteDispatchStoragePoolLookupByVolume has to be implemented manually */ -/* remoteDispatchStoragePoolNumOfVolumes has to be implemented manually */ +static int +remoteStoragePoolNumOfVolumes(virStoragePoolPtr pool) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_num_of_volumes_args args; + remote_storage_pool_num_of_volumes_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + + memset(&ret, 0, sizeof ret); + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_NUM_OF_VOLUMES, + (xdrproc_t)xdr_remote_storage_pool_num_of_volumes_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_pool_num_of_volumes_ret, (char *)&ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags) @@ -1349,11 +2311,60 @@ done: /* remoteDispatchStorageVolDownload has to be implemented manually */ -/* remoteDispatchStorageVolDumpXML has to be implemented manually */ +static char * +remoteStorageVolDumpXML(virStorageVolPtr vol, unsigned int flags) +{ + char *rv = NULL; + struct private_data *priv = vol->conn->storagePrivateData; + remote_storage_vol_dump_xml_args args; + remote_storage_vol_dump_xml_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_vol(&args.vol, vol); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_DUMP_XML, + (xdrproc_t)xdr_remote_storage_vol_dump_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_vol_dump_xml_ret, (char *)&ret) == -1) + goto done; + + rv = ret.xml; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchStorageVolGetInfo has to be implemented manually */ -/* remoteDispatchStorageVolGetPath has to be implemented manually */ +static char * +remoteStorageVolGetPath(virStorageVolPtr vol) +{ + char *rv = NULL; + struct private_data *priv = vol->conn->storagePrivateData; + remote_storage_vol_get_path_args args; + remote_storage_vol_get_path_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_vol(&args.vol, vol); + + memset(&ret, 0, sizeof ret); + + if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_PATH, + (xdrproc_t)xdr_remote_storage_vol_get_path_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_vol_get_path_ret, (char *)&ret) == -1) + goto done; + + rv = ret.name; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchStorageVolLookupByKey has to be implemented manually */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index bf4d866..a67f9f6 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1745,54 +1745,6 @@ done: return rv; } -static char * -remoteGetHostname (virConnectPtr conn) -{ - char *rv = NULL; - remote_get_hostname_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_GET_HOSTNAME, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_get_hostname_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees this. */ - rv = ret.hostname; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static char * -remoteGetSysinfo (virConnectPtr conn, unsigned int flags) -{ - char *rv = NULL; - remote_get_sysinfo_args args; - remote_get_sysinfo_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - args.flags = flags; - if (call (conn, priv, 0, REMOTE_PROC_GET_SYSINFO, - (xdrproc_t) xdr_remote_get_sysinfo_args, (char *) &args, - (xdrproc_t) xdr_remote_get_sysinfo_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees this. */ - rv = ret.sysinfo; - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteIsSecure(virConnectPtr conn) { int rv = -1; @@ -1914,29 +1866,6 @@ done: return rv; } -static char * -remoteGetCapabilities (virConnectPtr conn) -{ - char *rv = NULL; - remote_get_capabilities_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_GET_CAPABILITIES, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_get_capabilities_ret, (char *)&ret) == -1) - goto done; - - /* Caller frees this. */ - rv = ret.capabilities; - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems, @@ -2047,100 +1976,6 @@ done: return rv; } -static int -remoteNumOfDomains (virConnectPtr conn) -{ - int rv = -1; - remote_num_of_domains_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DOMAINS, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_num_of_domains_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainIsActive(virDomainPtr domain) -{ - int rv = -1; - remote_domain_is_active_args args; - remote_domain_is_active_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_IS_ACTIVE, - (xdrproc_t) xdr_remote_domain_is_active_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_is_active_ret, (char *) &ret) == -1) - goto done; - - rv = ret.active; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainIsPersistent(virDomainPtr domain) -{ - int rv = -1; - remote_domain_is_persistent_args args; - remote_domain_is_persistent_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_IS_PERSISTENT, - (xdrproc_t) xdr_remote_domain_is_persistent_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_is_persistent_ret, (char *) &ret) == -1) - goto done; - - rv = ret.persistent; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainIsUpdated(virDomainPtr domain) -{ - int rv = -1; - remote_domain_is_updated_args args; - remote_domain_is_updated_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_IS_UPDATED, - (xdrproc_t) xdr_remote_domain_is_updated_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_is_updated_ret, (char *) &ret) == -1) - goto done; - - rv = ret.updated; - -done: - remoteDriverUnlock(priv); - return rv; -} - static virDomainPtr remoteDomainCreateXML (virConnectPtr conn, const char *xmlDesc, @@ -2272,57 +2107,6 @@ done: return rv; } -static char * -remoteDomainGetOSType (virDomainPtr domain) -{ - char *rv = NULL; - remote_domain_get_os_type_args args; - remote_domain_get_os_type_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_OS_TYPE, - (xdrproc_t) xdr_remote_domain_get_os_type_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_get_os_type_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.type; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static unsigned long -remoteDomainGetMaxMemory (virDomainPtr domain) -{ - unsigned long rv = 0; - remote_domain_get_max_memory_args args; - remote_domain_get_max_memory_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MAX_MEMORY, - (xdrproc_t) xdr_remote_domain_get_max_memory_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_get_max_memory_ret, (char *) &ret) == -1) - goto done; - - rv = ret.memory; - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteDomainSetMemoryParameters (virDomainPtr domain, virMemoryParameterPtr params, @@ -2693,32 +2477,6 @@ done: } static int -remoteDomainGetVcpusFlags (virDomainPtr domain, unsigned int flags) -{ - int rv = -1; - remote_domain_get_vcpus_flags_args args; - remote_domain_get_vcpus_flags_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS, - (xdrproc_t) xdr_remote_domain_get_vcpus_flags_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_get_vcpus_flags_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteDomainPinVcpu (virDomainPtr domain, unsigned int vcpu, unsigned char *cpumap, @@ -2829,31 +2587,6 @@ done: } static int -remoteDomainGetMaxVcpus (virDomainPtr domain) -{ - int rv = -1; - remote_domain_get_max_vcpus_args args; - remote_domain_get_max_vcpus_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MAX_VCPUS, - (xdrproc_t) xdr_remote_domain_get_max_vcpus_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_get_max_vcpus_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteDomainGetSecurityLabel (virDomainPtr domain, virSecurityLabelPtr seclabel) { remote_domain_get_security_label_args args; @@ -2934,33 +2667,6 @@ done: } static char * -remoteDomainDumpXML (virDomainPtr domain, int flags) -{ - char *rv = NULL; - remote_domain_dump_xml_args args; - remote_domain_dump_xml_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_DUMP_XML, - (xdrproc_t) xdr_remote_domain_dump_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_dump_xml_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.xml; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static char * remoteDomainXMLFromNative (virConnectPtr conn, const char *format, const char *config, @@ -3286,28 +2992,6 @@ done: } static int -remoteNumOfDefinedDomains (virConnectPtr conn) -{ - int rv = -1; - remote_num_of_defined_domains_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_DOMAINS, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_num_of_defined_domains_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteDomainCreate (virDomainPtr domain) { int rv = -1; @@ -3846,31 +3530,6 @@ done: return rv; } -static int -remoteDomainHasManagedSaveImage (virDomainPtr domain, unsigned int flags) -{ - int rv = -1; - remote_domain_has_managed_save_image_args args; - remote_domain_has_managed_save_image_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.flags = flags; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_HAS_MANAGED_SAVE_IMAGE, - (xdrproc_t) xdr_remote_domain_has_managed_save_image_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_has_managed_save_image_ret, (char *) &ret) == -1) - goto done; - - rv = ret.result; - -done: - remoteDriverUnlock(priv); - return rv; -} - /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -3934,28 +3593,6 @@ remoteNetworkClose (virConnectPtr conn) } static int -remoteNumOfNetworks (virConnectPtr conn) -{ - int rv = -1; - remote_num_of_networks_ret ret; - struct private_data *priv = conn->networkPrivateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_NETWORKS, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_num_of_networks_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteListNetworks (virConnectPtr conn, char **const names, int maxnames) { int rv = -1; @@ -4015,28 +3652,6 @@ done: } static int -remoteNumOfDefinedNetworks (virConnectPtr conn) -{ - int rv = -1; - remote_num_of_defined_networks_ret ret; - struct private_data *priv = conn->networkPrivateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_NETWORKS, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_num_of_defined_networks_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteListDefinedNetworks (virConnectPtr conn, char **const names, int maxnames) { @@ -4150,54 +3765,6 @@ done: return net; } -static int -remoteNetworkIsActive(virNetworkPtr network) -{ - int rv = -1; - remote_network_is_active_args args; - remote_network_is_active_ret ret; - struct private_data *priv = network->conn->networkPrivateData; - - remoteDriverLock(priv); - - make_nonnull_network (&args.net, network); - - if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_IS_ACTIVE, - (xdrproc_t) xdr_remote_network_is_active_args, (char *) &args, - (xdrproc_t) xdr_remote_network_is_active_ret, (char *) &ret) == -1) - goto done; - - rv = ret.active; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteNetworkIsPersistent(virNetworkPtr network) -{ - int rv = -1; - remote_network_is_persistent_args args; - remote_network_is_persistent_ret ret; - struct private_data *priv = network->conn->networkPrivateData; - - remoteDriverLock(priv); - - make_nonnull_network (&args.net, network); - - if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_IS_PERSISTENT, - (xdrproc_t) xdr_remote_network_is_persistent_args, (char *) &args, - (xdrproc_t) xdr_remote_network_is_persistent_ret, (char *) &ret) == -1) - goto done; - - rv = ret.persistent; - -done: - remoteDriverUnlock(priv); - return rv; -} - static virNetworkPtr remoteNetworkCreateXML (virConnectPtr conn, const char *xmlDesc) { @@ -4250,59 +3817,6 @@ done: return net; } -static char * -remoteNetworkDumpXML (virNetworkPtr network, int flags) -{ - char *rv = NULL; - remote_network_dump_xml_args args; - remote_network_dump_xml_ret ret; - struct private_data *priv = network->conn->networkPrivateData; - - remoteDriverLock(priv); - - make_nonnull_network (&args.net, network); - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_DUMP_XML, - (xdrproc_t) xdr_remote_network_dump_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_network_dump_xml_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.xml; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static char * -remoteNetworkGetBridgeName (virNetworkPtr network) -{ - char *rv = NULL; - remote_network_get_bridge_name_args args; - remote_network_get_bridge_name_ret ret; - struct private_data *priv = network->conn->networkPrivateData; - - remoteDriverLock(priv); - - make_nonnull_network (&args.net, network); - - memset (&ret, 0, sizeof ret); - if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_GET_BRIDGE_NAME, - (xdrproc_t) xdr_remote_network_get_bridge_name_args, (char *) &args, - (xdrproc_t) xdr_remote_network_get_bridge_name_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.name; - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteNetworkGetAutostart (virNetworkPtr network, int *autostart) { @@ -4393,28 +3907,6 @@ remoteInterfaceClose (virConnectPtr conn) } static int -remoteNumOfInterfaces (virConnectPtr conn) -{ - int rv = -1; - remote_num_of_interfaces_ret ret; - struct private_data *priv = conn->interfacePrivateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_INTERFACES, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_num_of_interfaces_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteListInterfaces (virConnectPtr conn, char **const names, int maxnames) { int rv = -1; @@ -4474,28 +3966,6 @@ done: } static int -remoteNumOfDefinedInterfaces (virConnectPtr conn) -{ - int rv = -1; - remote_num_of_defined_interfaces_ret ret; - struct private_data *priv = conn->interfacePrivateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_INTERFACES, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_num_of_defined_interfaces_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteListDefinedInterfaces (virConnectPtr conn, char **const names, int maxnames) { int rv = -1; @@ -4608,60 +4078,6 @@ done: return iface; } - -static int -remoteInterfaceIsActive(virInterfacePtr iface) -{ - int rv = -1; - remote_interface_is_active_args args; - remote_interface_is_active_ret ret; - struct private_data *priv = iface->conn->interfacePrivateData; - - remoteDriverLock(priv); - - make_nonnull_interface (&args.iface, iface); - - if (call (iface->conn, priv, 0, REMOTE_PROC_INTERFACE_IS_ACTIVE, - (xdrproc_t) xdr_remote_interface_is_active_args, (char *) &args, - (xdrproc_t) xdr_remote_interface_is_active_ret, (char *) &ret) == -1) - goto done; - - rv = ret.active; - -done: - remoteDriverUnlock(priv); - return rv; -} - - -static char * -remoteInterfaceGetXMLDesc (virInterfacePtr iface, - unsigned int flags) -{ - char *rv = NULL; - remote_interface_get_xml_desc_args args; - remote_interface_get_xml_desc_ret ret; - struct private_data *priv = iface->conn->interfacePrivateData; - - remoteDriverLock(priv); - - make_nonnull_interface (&args.iface, iface); - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (iface->conn, priv, 0, REMOTE_PROC_INTERFACE_GET_XML_DESC, - (xdrproc_t) xdr_remote_interface_get_xml_desc_args, (char *) &args, - (xdrproc_t) xdr_remote_interface_get_xml_desc_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.xml; - -done: - remoteDriverUnlock(priv); - return rv; -} - static virInterfacePtr remoteInterfaceDefineXML (virConnectPtr conn, const char *xmlDesc, @@ -4761,28 +4177,6 @@ remoteStorageClose (virConnectPtr conn) } static int -remoteNumOfStoragePools (virConnectPtr conn) -{ - int rv = -1; - remote_num_of_storage_pools_ret ret; - struct private_data *priv = conn->storagePrivateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_STORAGE_POOLS, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_num_of_storage_pools_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteListStoragePools (virConnectPtr conn, char **const names, int maxnames) { int rv = -1; @@ -4838,28 +4232,6 @@ done: } static int -remoteNumOfDefinedStoragePools (virConnectPtr conn) -{ - int rv = -1; - remote_num_of_defined_storage_pools_ret ret; - struct private_data *priv = conn->storagePrivateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_STORAGE_POOLS, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_num_of_defined_storage_pools_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteListDefinedStoragePools (virConnectPtr conn, char **const names, int maxnames) { @@ -5040,56 +4412,6 @@ done: return pool; } - -static int -remoteStoragePoolIsActive(virStoragePoolPtr pool) -{ - int rv = -1; - remote_storage_pool_is_active_args args; - remote_storage_pool_is_active_ret ret; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_IS_ACTIVE, - (xdrproc_t) xdr_remote_storage_pool_is_active_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_pool_is_active_ret, (char *) &ret) == -1) - goto done; - - rv = ret.active; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteStoragePoolIsPersistent(virStoragePoolPtr pool) -{ - int rv = -1; - remote_storage_pool_is_persistent_args args; - remote_storage_pool_is_persistent_ret ret; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_IS_PERSISTENT, - (xdrproc_t) xdr_remote_storage_pool_is_persistent_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_pool_is_persistent_ret, (char *) &ret) == -1) - goto done; - - rv = ret.persistent; - -done: - remoteDriverUnlock(priv); - return rv; -} - - static virStoragePoolPtr remoteStoragePoolCreateXML (virConnectPtr conn, const char *xmlDesc, unsigned int flags) { @@ -5174,34 +4496,6 @@ done: return rv; } -static char * -remoteStoragePoolDumpXML (virStoragePoolPtr pool, - unsigned int flags) -{ - char *rv = NULL; - remote_storage_pool_dump_xml_args args; - remote_storage_pool_dump_xml_ret ret; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DUMP_XML, - (xdrproc_t) xdr_remote_storage_pool_dump_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_pool_dump_xml_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.xml; - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteStoragePoolGetAutostart (virStoragePoolPtr pool, int *autostart) { @@ -5229,30 +4523,6 @@ done: return rv; } -static int -remoteStoragePoolNumOfVolumes (virStoragePoolPtr pool) -{ - int rv = -1; - remote_storage_pool_num_of_volumes_args args; - remote_storage_pool_num_of_volumes_ret ret; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool(&args.pool, pool); - - memset (&ret, 0, sizeof ret); - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_NUM_OF_VOLUMES, - (xdrproc_t) xdr_remote_storage_pool_num_of_volumes_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_pool_num_of_volumes_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} static int remoteStoragePoolListVolumes (virStoragePoolPtr pool, char **const names, int maxnames) @@ -5484,61 +4754,6 @@ done: return rv; } -static char * -remoteStorageVolDumpXML (virStorageVolPtr vol, - unsigned int flags) -{ - char *rv = NULL; - remote_storage_vol_dump_xml_args args; - remote_storage_vol_dump_xml_ret ret; - struct private_data *priv = vol->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_vol (&args.vol, vol); - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_DUMP_XML, - (xdrproc_t) xdr_remote_storage_vol_dump_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_vol_dump_xml_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.xml; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static char * -remoteStorageVolGetPath (virStorageVolPtr vol) -{ - char *rv = NULL; - remote_storage_vol_get_path_args args; - remote_storage_vol_get_path_ret ret; - struct private_data *priv = vol->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_vol (&args.vol, vol); - - memset (&ret, 0, sizeof ret); - if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_PATH, - (xdrproc_t) xdr_remote_storage_vol_get_path_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_vol_get_path_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.name; - -done: - remoteDriverUnlock(priv); - return rv; -} - - /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -5606,34 +4821,6 @@ static int remoteDevMonClose(virConnectPtr conn) return ret; } -static int remoteNodeNumOfDevices(virConnectPtr conn, - const char *cap, - unsigned int flags) -{ - int rv = -1; - remote_node_num_of_devices_args args; - remote_node_num_of_devices_ret ret; - struct private_data *priv = conn->devMonPrivateData; - - remoteDriverLock(priv); - - args.cap = cap ? (char **)&cap : NULL; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NODE_NUM_OF_DEVICES, - (xdrproc_t) xdr_remote_node_num_of_devices_args, (char *) &args, - (xdrproc_t) xdr_remote_node_num_of_devices_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - - static int remoteNodeListDevices(virConnectPtr conn, const char *cap, char **const names, @@ -5722,33 +4909,6 @@ done: return dev; } -static char *remoteNodeDeviceDumpXML(virNodeDevicePtr dev, - unsigned int flags) -{ - char *rv = NULL; - remote_node_device_dump_xml_args args; - remote_node_device_dump_xml_ret ret; - struct private_data *priv = dev->conn->devMonPrivateData; - - remoteDriverLock(priv); - - args.name = dev->name; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DUMP_XML, - (xdrproc_t) xdr_remote_node_device_dump_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_node_device_dump_xml_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.xml; - -done: - remoteDriverUnlock(priv); - return rv; -} - static char *remoteNodeDeviceGetParent(virNodeDevicePtr dev) { char *rv = NULL; @@ -5775,30 +4935,6 @@ done: return rv; } -static int remoteNodeDeviceNumOfCaps(virNodeDevicePtr dev) -{ - int rv = -1; - remote_node_device_num_of_caps_args args; - remote_node_device_num_of_caps_ret ret; - struct private_data *priv = dev->conn->devMonPrivateData; - - remoteDriverLock(priv); - - args.name = dev->name; - - memset (&ret, 0, sizeof ret); - if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS, - (xdrproc_t) xdr_remote_node_device_num_of_caps_args, (char *) &args, - (xdrproc_t) xdr_remote_node_device_num_of_caps_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames) @@ -6023,30 +5159,6 @@ remoteNWFilterClose (virConnectPtr conn) return rv; } - -static int -remoteNumOfNWFilters (virConnectPtr conn) -{ - int rv = -1; - remote_num_of_nwfilters_ret ret; - struct private_data *priv = conn->nwfilterPrivateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_NWFILTERS, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_num_of_nwfilters_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - - static virNWFilterPtr remoteNWFilterDefineXML (virConnectPtr conn, const char *xmlDesc, unsigned int flags ATTRIBUTE_UNUSED) @@ -6189,35 +5301,6 @@ done: return net; } - -static char * -remoteNWFilterGetXMLDesc (virNWFilterPtr nwfilter, unsigned int flags) -{ - char *rv = NULL; - remote_nwfilter_get_xml_desc_args args; - remote_nwfilter_get_xml_desc_ret ret; - struct private_data *priv = nwfilter->conn->nwfilterPrivateData; - - remoteDriverLock(priv); - - make_nonnull_nwfilter (&args.nwfilter, nwfilter); - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (nwfilter->conn, priv, 0, REMOTE_PROC_NWFILTER_GET_XML_DESC, - (xdrproc_t) xdr_remote_nwfilter_get_xml_desc_args, (char *) &args, - (xdrproc_t) xdr_remote_nwfilter_get_xml_desc_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.xml; - -done: - remoteDriverUnlock(priv); - return rv; -} - - /*----------------------------------------------------------------------*/ static int @@ -7280,28 +6363,6 @@ remoteSecretClose (virConnectPtr conn) } static int -remoteSecretNumOfSecrets (virConnectPtr conn) -{ - int rv = -1; - remote_num_of_secrets_ret ret; - struct private_data *priv = conn->secretPrivateData; - - remoteDriverLock (priv); - - memset (&ret, 0, sizeof (ret)); - if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_SECRETS, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_num_of_secrets_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock (priv); - return rv; -} - -static int remoteListSecrets (virConnectPtr conn, char **uuids, int maxuuids) { int rv = -1; @@ -7440,33 +6501,6 @@ done: return rv; } -static char * -remoteSecretGetXMLDesc (virSecretPtr secret, unsigned int flags) -{ - char *rv = NULL; - remote_secret_get_xml_desc_args args; - remote_secret_get_xml_desc_ret ret; - struct private_data *priv = secret->conn->secretPrivateData; - - remoteDriverLock (priv); - - make_nonnull_secret (&args.secret, secret); - args.flags = flags; - - memset (&ret, 0, sizeof (ret)); - if (call (secret->conn, priv, 0, REMOTE_PROC_SECRET_GET_XML_DESC, - (xdrproc_t) xdr_remote_secret_get_xml_desc_args, (char *) &args, - (xdrproc_t) xdr_remote_secret_get_xml_desc_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.xml; - -done: - remoteDriverUnlock (priv); - return rv; -} - static int remoteSecretSetValue (virSecretPtr secret, const unsigned char *value, size_t value_size, unsigned int flags) @@ -8070,34 +7104,6 @@ done: return rv; } - -static int -remoteCPUCompare(virConnectPtr conn, const char *xmlDesc, - unsigned int flags ATTRIBUTE_UNUSED) -{ - struct private_data *priv = conn->privateData; - remote_cpu_compare_args args; - remote_cpu_compare_ret ret; - int rv = VIR_CPU_COMPARE_ERROR; - - remoteDriverLock(priv); - - args.xml = (char *) xmlDesc; - - memset(&ret, 0, sizeof (ret)); - if (call(conn, priv, 0, REMOTE_PROC_CPU_COMPARE, - (xdrproc_t) xdr_remote_cpu_compare_args, (char *) &args, - (xdrproc_t) xdr_remote_cpu_compare_ret, (char *) &ret) == -1) - goto done; - - rv = ret.result; - -done: - remoteDriverUnlock(priv); - return rv; -} - - static char * remoteCPUBaseline(virConnectPtr conn, const char **xmlCPUs, @@ -8197,62 +7203,6 @@ done: return snapshot; } - -static char * -remoteDomainSnapshotDumpXML(virDomainSnapshotPtr snapshot, unsigned int flags) -{ - char *rv = NULL; - remote_domain_snapshot_dump_xml_args args; - remote_domain_snapshot_dump_xml_ret ret; - struct private_data *priv = snapshot->domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain_snapshot(&args.snap, snapshot); - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (snapshot->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_DUMP_XML, - (xdrproc_t) xdr_remote_domain_snapshot_dump_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_snapshot_dump_xml_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.xml; - -done: - remoteDriverUnlock(priv); - return rv; -} - - -static int -remoteDomainSnapshotNum (virDomainPtr domain, unsigned int flags) -{ - int rv = -1; - remote_domain_snapshot_num_args args; - remote_domain_snapshot_num_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_NUM, - (xdrproc_t) xdr_remote_domain_snapshot_num_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_snapshot_num_ret, (char *) &ret) == -1) - goto done; - - rv = ret.num; - -done: - remoteDriverUnlock(priv); - return rv; -} - - static int remoteDomainSnapshotListNames (virDomainPtr domain, char **const names, int maxnames, unsigned int flags) @@ -8346,33 +7296,6 @@ done: return snapshot; } - -static int -remoteDomainHasCurrentSnapshot(virDomainPtr domain, unsigned int flags) -{ - int rv = -1; - remote_domain_has_current_snapshot_args args; - remote_domain_has_current_snapshot_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain(&args.dom, domain); - args.flags = flags; - - if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_HAS_CURRENT_SNAPSHOT, - (xdrproc_t) xdr_remote_domain_has_current_snapshot_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_has_current_snapshot_ret, (char *) &ret) == -1) - goto done; - - rv = ret.result; - -done: - remoteDriverUnlock(priv); - return rv; -} - - static virDomainSnapshotPtr remoteDomainSnapshotCurrent(virDomainPtr domain, unsigned int flags) @@ -8617,7 +7540,6 @@ done: remoteDriverUnlock(priv); return rv; - } @@ -8646,7 +7568,6 @@ remoteQemuDomainMonitorCommand (virDomainPtr domain, const char *cmd, *result = strdup(ret.result); if (*result == NULL) { - virReportOOMError(); goto cleanup; } @@ -10282,7 +9203,7 @@ static virSecretDriver secret_driver = { .name = "remote", .open = remoteSecretOpen, .close = remoteSecretClose, - .numOfSecrets = remoteSecretNumOfSecrets, + .numOfSecrets = remoteNumOfSecrets, .listSecrets = remoteListSecrets, .lookupByUUID = remoteSecretLookupByUUID, .lookupByUsage = remoteSecretLookupByUsage, -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:14:04 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:14:04 +0200 Subject: [libvirt] [PATCH 17/22] remote generator, client: Handle functions with wrapped return values In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-18-git-send-email-matthias.bolte@googlemail.com> --- daemon/remote_generator.pl | 88 ++-- src/remote/remote_client_bodies.c | 987 +++++++++++++++++++++++++++++++++++-- src/remote/remote_driver.c | 996 ------------------------------------- 3 files changed, 993 insertions(+), 1078 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index a973b21..5045b7f 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -753,82 +753,44 @@ elsif ($opt_k) { "CPUBaseline", "DomainBlockStats", "DomainCreate", - "DomainCreateXML", - "DomainDefineXML", "DomainDestroy", "DomainGetAutostart", "DomainGetBlockInfo", "DomainGetInfo", - "StoragePoolLookupByUUID", - "NodeDeviceCreateXML", "DomainGetJobInfo", "DomainInterfaceStats", - "DomainLookupByID", - "DomainLookupByName", - "DomainLookupByUIID", "DomainMigrateFinish", - "NWFilterDefineXML", - "NWFilterLookupByName", - "NWFilterLookupByUUID", - "SecretLookupByUUID", - "SecretLookupByUsage", - "StoragePoolCreateXML", - "DomainLookupByUUID", + "NWFilterDefineXML", # public API and XDR protocol mismatch "DomainMigratePerform", "DomainMigrateFinish2", - "DomainSnapshotCreateXML", - "DomainSnapshotCurrent", "DomainSnapshotListNames", "GetLibVersion", - "GetMaxVcpus", - "DomainSnapshotLookupByName", - "DomainXMLFromNative", "FindStoragePoolSources", "GetVersion", - "GetLibVersion", - "InterfaceDefineXML", - "InterfaceLookupByName", "IsSecure", "ListDefinedDomains", "ListDefinedInterfaces", "ListNWFilters", - "NetworkCreateXML", "SupportsFeature", - "StorageVolLookupByPath", "StorageVolGetInfo", - "StorageVolCreateXML", - "StorageVolLookupByName", - "StorageVolLookupByKey", "StoragePoolGetInfo", - "StorageVolCreateXMLFrom", - "StoragePoolLookupByName", "NodeListDevices", "NodeGetCellsFreeMemory", "ListDefinedNetworks", - "DomainXMLToNative", "StoragePoolListVolumes", - "SecretDefineXML", "ListDomains", "ListStoragePools", "NetworkGetAutostart", - "StoragePoolLookupByVolume", "StoragePoolGetAutostart", "SecretSetValue", - "StoragePoolDefineXML", "NodeGetInfo", "GetURI", - "InterfaceLookupByMACString", "ListInterfaces", - "NetworkDefineXML", - "NetworkLookupByName", "ListDefinedStoragePools", "NodeDeviceDettach", - "NodeDeviceLookupByName", - "NodeGetFreeMemory", "ListNetworks", "NodeDeviceListCaps", "NodeDeviceReset", - "NetworkLookupByUUID", "NodeDeviceReAttach", "ListSecrets", @@ -889,7 +851,9 @@ elsif ($opt_k) { my $has_node_device = 0; # node device is special - if ($call->{args} =~ m/^remote_node_/) { + if ($call->{args} =~ m/^remote_node_/ and + !($call->{args} =~ m/^remote_node_device_lookup_by_name_/) and + !($call->{args} =~ m/^remote_node_device_create_xml_/)) { $has_node_device = 1; $priv_name = "devMonPrivateData"; } @@ -901,13 +865,14 @@ elsif ($opt_k) { push(@setters_list, "args.name = dev->name;"); } elsif ($args_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|secret|nwfilter|domain_snapshot) (\S+);/) { my $name = $1; + my $arg_name = $2; my $type_name = name_to_ProcName($name); if ($is_first_arg) { if ($name eq "domain_snapshot") { - $priv_src = "$2->domain->conn"; + $priv_src = "$arg_name->domain->conn"; } else { - $priv_src = "$2->conn"; + $priv_src = "$arg_name->conn"; } if ($name =~ m/^storage_/) { @@ -917,8 +882,11 @@ elsif ($opt_k) { } } - push(@args_list, "vir${type_name}Ptr $2"); - push(@setters_list, "make_nonnull_$1(&args.$2, $2);"); + push(@args_list, "vir${type_name}Ptr $arg_name"); + push(@setters_list, "make_nonnull_$1(&args.$arg_name, $arg_name);"); + } elsif ($args_member =~ m/^remote_uuid (\S+);/) { + push(@args_list, "const unsigned char *$1"); + push(@setters_list, "memcpy(args.$1, $1, VIR_UUID_BUFLEN);"); } elsif ($args_member =~ m/^remote_string (\S+);/) { push(@args_list, "const char *$1"); push(@setters_list, "args.$1 = $1 ? (char **)&$1 : NULL;"); @@ -988,14 +956,42 @@ elsif ($opt_k) { push(@ret_list, "rv = ret.$1;"); $single_ret_var = "char *rv = NULL"; $single_ret_type = "char *"; + } elsif ($ret_member =~ m/remote_nonnull_(domain|network|storage_pool|storage_vol|node_device|interface|secret|nwfilter|domain_snapshot) (\S+);/) { + my $name = $1; + my $arg_name = $2; + my $type_name = name_to_ProcName($name); + + if ($name eq "node_device") { + $priv_name = "devMonPrivateData"; + } elsif ($name =~ m/^storage_/) { + $priv_name = "storagePrivateData"; + } elsif (!($name =~ m/^domain/)) { + $priv_name = "${name}PrivateData"; + } + + if ($name eq "domain_snapshot") { + push(@ret_list, "rv = get_nonnull_$name(dom, ret.$arg_name);"); + } else { + push(@ret_list, "rv = get_nonnull_$name($priv_src, ret.$arg_name);"); + } + + push(@ret_list, "xdr_free((xdrproc_t)xdr_$call->{ret}, (char *)&ret);"); + $single_ret_var = "vir${type_name}Ptr rv = NULL"; + $single_ret_type = "vir${type_name}Ptr"; } elsif ($ret_member =~ m/^int (\S+);/) { push(@ret_list, "rv = ret.$1;"); $single_ret_var = "int rv = -1"; $single_ret_type = "int"; } elsif ($ret_member =~ m/hyper (\S+);/) { push(@ret_list, "rv = ret.$1;"); - $single_ret_var = "unsigned long rv = 0"; - $single_ret_type = "unsigned long"; + + if ($call->{ProcName} eq "NodeGetFreeMemory") { + $single_ret_var = "unsigned long long rv = 0"; + $single_ret_type = "unsigned long long"; + } else { + $single_ret_var = "unsigned long rv = 0"; + $single_ret_type = "unsigned long"; + } } else { die "unhandled type for return value: $ret_member"; } diff --git a/src/remote/remote_client_bodies.c b/src/remote/remote_client_bodies.c index b878832..5471c1b 100644 --- a/src/remote/remote_client_bodies.c +++ b/src/remote/remote_client_bodies.c @@ -148,9 +148,60 @@ done: /* remoteDispatchDomainCreateWithFlags has to be implemented manually */ -/* remoteDispatchDomainCreateXML has to be implemented manually */ +static virDomainPtr +remoteDomainCreateXML(virConnectPtr conn, const char *xml_desc, unsigned int flags) +{ + virDomainPtr rv = NULL; + struct private_data *priv = conn->privateData; + remote_domain_create_xml_args args; + remote_domain_create_xml_ret ret; + + remoteDriverLock(priv); + + args.xml_desc = (char *)xml_desc; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_CREATE_XML, + (xdrproc_t)xdr_remote_domain_create_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_create_xml_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_domain(conn, ret.dom); + xdr_free((xdrproc_t)xdr_remote_domain_create_xml_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virDomainPtr +remoteDomainDefineXML(virConnectPtr conn, const char *xml) +{ + virDomainPtr rv = NULL; + struct private_data *priv = conn->privateData; + remote_domain_define_xml_args args; + remote_domain_define_xml_ret ret; + + remoteDriverLock(priv); + + args.xml = (char *)xml; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_DEFINE_XML, + (xdrproc_t)xdr_remote_domain_define_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_define_xml_ret, (char *)&ret) == -1) + goto done; -/* remoteDispatchDomainDefineXML has to be implemented manually */ + rv = get_nonnull_domain(conn, ret.dom); + xdr_free((xdrproc_t)xdr_remote_domain_define_xml_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchDomainDestroy has to be implemented manually */ @@ -497,11 +548,86 @@ done: return rv; } -/* remoteDispatchDomainLookupByID has to be implemented manually */ +static virDomainPtr +remoteDomainLookupByID(virConnectPtr conn, int id) +{ + virDomainPtr rv = NULL; + struct private_data *priv = conn->privateData; + remote_domain_lookup_by_id_args args; + remote_domain_lookup_by_id_ret ret; + + remoteDriverLock(priv); + + args.id = id; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_ID, + (xdrproc_t)xdr_remote_domain_lookup_by_id_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_lookup_by_id_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_domain(conn, ret.dom); + xdr_free((xdrproc_t)xdr_remote_domain_lookup_by_id_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virDomainPtr +remoteDomainLookupByName(virConnectPtr conn, const char *name) +{ + virDomainPtr rv = NULL; + struct private_data *priv = conn->privateData; + remote_domain_lookup_by_name_args args; + remote_domain_lookup_by_name_ret ret; + + remoteDriverLock(priv); + + args.name = (char *)name; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_NAME, + (xdrproc_t)xdr_remote_domain_lookup_by_name_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_lookup_by_name_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_domain(conn, ret.dom); + xdr_free((xdrproc_t)xdr_remote_domain_lookup_by_name_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virDomainPtr +remoteDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) +{ + virDomainPtr rv = NULL; + struct private_data *priv = conn->privateData; + remote_domain_lookup_by_uuid_args args; + remote_domain_lookup_by_uuid_ret ret; + + remoteDriverLock(priv); + + memcpy(args.uuid, uuid, VIR_UUID_BUFLEN); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID, + (xdrproc_t)xdr_remote_domain_lookup_by_uuid_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_lookup_by_uuid_ret, (char *)&ret) == -1) + goto done; -/* remoteDispatchDomainLookupByName has to be implemented manually */ + rv = get_nonnull_domain(conn, ret.dom); + xdr_free((xdrproc_t)xdr_remote_domain_lookup_by_uuid_ret, (char *)&ret); -/* remoteDispatchDomainLookupByUUID has to be implemented manually */ +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteDomainManagedSave(virDomainPtr dom, unsigned int flags) @@ -914,9 +1040,62 @@ done: return rv; } -/* remoteDispatchDomainSnapshotCreateXML has to be implemented manually */ +static virDomainSnapshotPtr +remoteDomainSnapshotCreateXML(virDomainPtr dom, const char *xml_desc, unsigned int flags) +{ + virDomainSnapshotPtr rv = NULL; + struct private_data *priv = dom->conn->privateData; + remote_domain_snapshot_create_xml_args args; + remote_domain_snapshot_create_xml_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.xml_desc = (char *)xml_desc; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML, + (xdrproc_t)xdr_remote_domain_snapshot_create_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_snapshot_create_xml_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_domain_snapshot(dom, ret.snap); + xdr_free((xdrproc_t)xdr_remote_domain_snapshot_create_xml_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virDomainSnapshotPtr +remoteDomainSnapshotCurrent(virDomainPtr dom, unsigned int flags) +{ + virDomainSnapshotPtr rv = NULL; + struct private_data *priv = dom->conn->privateData; + remote_domain_snapshot_current_args args; + remote_domain_snapshot_current_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.flags = flags; + + memset(&ret, 0, sizeof ret); -/* remoteDispatchDomainSnapshotCurrent has to be implemented manually */ + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT, + (xdrproc_t)xdr_remote_domain_snapshot_current_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_snapshot_current_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_domain_snapshot(dom, ret.snap); + xdr_free((xdrproc_t)xdr_remote_domain_snapshot_current_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteDomainSnapshotDelete(virDomainSnapshotPtr snap, unsigned int flags) @@ -971,7 +1150,34 @@ done: /* remoteDispatchDomainSnapshotListNames has to be implemented manually */ -/* remoteDispatchDomainSnapshotLookupByName has to be implemented manually */ +static virDomainSnapshotPtr +remoteDomainSnapshotLookupByName(virDomainPtr dom, const char *name, unsigned int flags) +{ + virDomainSnapshotPtr rv = NULL; + struct private_data *priv = dom->conn->privateData; + remote_domain_snapshot_lookup_by_name_args args; + remote_domain_snapshot_lookup_by_name_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.name = (char *)name; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_LOOKUP_BY_NAME, + (xdrproc_t)xdr_remote_domain_snapshot_lookup_by_name_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_snapshot_lookup_by_name_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_domain_snapshot(dom, ret.snap); + xdr_free((xdrproc_t)xdr_remote_domain_snapshot_lookup_by_name_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteDomainSnapshotNum(virDomainPtr dom, unsigned int flags) @@ -1071,9 +1277,61 @@ done: return rv; } -/* remoteDispatchDomainXMLFromNative has to be implemented manually */ +static char * +remoteDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat, const char *nativeConfig, unsigned int flags) +{ + char *rv = NULL; + struct private_data *priv = conn->privateData; + remote_domain_xml_from_native_args args; + remote_domain_xml_from_native_ret ret; + + remoteDriverLock(priv); + + args.nativeFormat = (char *)nativeFormat; + args.nativeConfig = (char *)nativeConfig; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_XML_FROM_NATIVE, + (xdrproc_t)xdr_remote_domain_xml_from_native_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_xml_from_native_ret, (char *)&ret) == -1) + goto done; + + rv = ret.domainXml; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static char * +remoteDomainXMLToNative(virConnectPtr conn, const char *nativeFormat, const char *domainXml, unsigned int flags) +{ + char *rv = NULL; + struct private_data *priv = conn->privateData; + remote_domain_xml_to_native_args args; + remote_domain_xml_to_native_ret ret; + + remoteDriverLock(priv); + + args.nativeFormat = (char *)nativeFormat; + args.domainXml = (char *)domainXml; + args.flags = flags; -/* remoteDispatchDomainXMLToNative has to be implemented manually */ + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_XML_TO_NATIVE, + (xdrproc_t)xdr_remote_domain_xml_to_native_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_xml_to_native_ret, (char *)&ret) == -1) + goto done; + + rv = ret.nativeConfig; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchFindStoragePoolSources has to be implemented manually */ @@ -1125,7 +1383,31 @@ done: /* remoteDispatchGetLibVersion has to be implemented manually */ -/* remoteDispatchGetMaxVcpus has to be implemented manually */ +static int +remoteGetMaxVcpus(virConnectPtr conn, const char *type) +{ + int rv = -1; + struct private_data *priv = conn->privateData; + remote_get_max_vcpus_args args; + remote_get_max_vcpus_ret ret; + + remoteDriverLock(priv); + + args.type = type ? (char **)&type : NULL; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_GET_MAX_VCPUS, + (xdrproc_t)xdr_remote_get_max_vcpus_args, (char *)&args, + (xdrproc_t)xdr_remote_get_max_vcpus_ret, (char *)&ret) == -1) + goto done; + + rv = ret.max_vcpus; + +done: + remoteDriverUnlock(priv); + return rv; +} static char * remoteGetSysinfo(virConnectPtr conn, unsigned int flags) @@ -1183,7 +1465,33 @@ done: return rv; } -/* remoteDispatchInterfaceDefineXML has to be implemented manually */ +static virInterfacePtr +remoteInterfaceDefineXML(virConnectPtr conn, const char *xml, unsigned int flags) +{ + virInterfacePtr rv = NULL; + struct private_data *priv = conn->interfacePrivateData; + remote_interface_define_xml_args args; + remote_interface_define_xml_ret ret; + + remoteDriverLock(priv); + + args.xml = (char *)xml; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_INTERFACE_DEFINE_XML, + (xdrproc_t)xdr_remote_interface_define_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_interface_define_xml_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_interface(conn, ret.iface); + xdr_free((xdrproc_t)xdr_remote_interface_define_xml_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteInterfaceDestroy(virInterfacePtr iface, unsigned int flags) @@ -1262,9 +1570,59 @@ done: return rv; } -/* remoteDispatchInterfaceLookupByMACString has to be implemented manually */ +static virInterfacePtr +remoteInterfaceLookupByMACString(virConnectPtr conn, const char *mac) +{ + virInterfacePtr rv = NULL; + struct private_data *priv = conn->interfacePrivateData; + remote_interface_lookup_by_mac_string_args args; + remote_interface_lookup_by_mac_string_ret ret; + + remoteDriverLock(priv); + + args.mac = (char *)mac; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING, + (xdrproc_t)xdr_remote_interface_lookup_by_mac_string_args, (char *)&args, + (xdrproc_t)xdr_remote_interface_lookup_by_mac_string_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_interface(conn, ret.iface); + xdr_free((xdrproc_t)xdr_remote_interface_lookup_by_mac_string_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virInterfacePtr +remoteInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + virInterfacePtr rv = NULL; + struct private_data *priv = conn->interfacePrivateData; + remote_interface_lookup_by_name_args args; + remote_interface_lookup_by_name_ret ret; + + remoteDriverLock(priv); + + args.name = (char *)name; + + memset(&ret, 0, sizeof ret); -/* remoteDispatchInterfaceLookupByName has to be implemented manually */ + if (call(conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME, + (xdrproc_t)xdr_remote_interface_lookup_by_name_args, (char *)&args, + (xdrproc_t)xdr_remote_interface_lookup_by_name_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_interface(conn, ret.iface); + xdr_free((xdrproc_t)xdr_remote_interface_lookup_by_name_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteInterfaceUndefine(virInterfacePtr iface) @@ -1334,9 +1692,59 @@ done: return rv; } -/* remoteDispatchNetworkCreateXML has to be implemented manually */ +static virNetworkPtr +remoteNetworkCreateXML(virConnectPtr conn, const char *xml) +{ + virNetworkPtr rv = NULL; + struct private_data *priv = conn->networkPrivateData; + remote_network_create_xml_args args; + remote_network_create_xml_ret ret; + + remoteDriverLock(priv); + + args.xml = (char *)xml; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NETWORK_CREATE_XML, + (xdrproc_t)xdr_remote_network_create_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_network_create_xml_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_network(conn, ret.net); + xdr_free((xdrproc_t)xdr_remote_network_create_xml_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virNetworkPtr +remoteNetworkDefineXML(virConnectPtr conn, const char *xml) +{ + virNetworkPtr rv = NULL; + struct private_data *priv = conn->networkPrivateData; + remote_network_define_xml_args args; + remote_network_define_xml_ret ret; + + remoteDriverLock(priv); + + args.xml = (char *)xml; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NETWORK_DEFINE_XML, + (xdrproc_t)xdr_remote_network_define_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_network_define_xml_ret, (char *)&ret) == -1) + goto done; -/* remoteDispatchNetworkDefineXML has to be implemented manually */ + rv = get_nonnull_network(conn, ret.net); + xdr_free((xdrproc_t)xdr_remote_network_define_xml_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteNetworkDestroy(virNetworkPtr net) @@ -1468,9 +1876,59 @@ done: return rv; } -/* remoteDispatchNetworkLookupByName has to be implemented manually */ +static virNetworkPtr +remoteNetworkLookupByName(virConnectPtr conn, const char *name) +{ + virNetworkPtr rv = NULL; + struct private_data *priv = conn->networkPrivateData; + remote_network_lookup_by_name_args args; + remote_network_lookup_by_name_ret ret; + + remoteDriverLock(priv); + + args.name = (char *)name; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NETWORK_LOOKUP_BY_NAME, + (xdrproc_t)xdr_remote_network_lookup_by_name_args, (char *)&args, + (xdrproc_t)xdr_remote_network_lookup_by_name_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_network(conn, ret.net); + xdr_free((xdrproc_t)xdr_remote_network_lookup_by_name_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virNetworkPtr +remoteNetworkLookupByUUID(virConnectPtr conn, const unsigned char *uuid) +{ + virNetworkPtr rv = NULL; + struct private_data *priv = conn->networkPrivateData; + remote_network_lookup_by_uuid_args args; + remote_network_lookup_by_uuid_ret ret; + + remoteDriverLock(priv); + + memcpy(args.uuid, uuid, VIR_UUID_BUFLEN); -/* remoteDispatchNetworkLookupByUUID has to be implemented manually */ + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NETWORK_LOOKUP_BY_UUID, + (xdrproc_t)xdr_remote_network_lookup_by_uuid_args, (char *)&args, + (xdrproc_t)xdr_remote_network_lookup_by_uuid_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_network(conn, ret.net); + xdr_free((xdrproc_t)xdr_remote_network_lookup_by_uuid_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteNetworkSetAutostart(virNetworkPtr net, int autostart) @@ -1519,7 +1977,33 @@ done: return rv; } -/* remoteDispatchNodeDeviceCreateXML has to be implemented manually */ +static virNodeDevicePtr +remoteNodeDeviceCreateXML(virConnectPtr conn, const char *xml_desc, unsigned int flags) +{ + virNodeDevicePtr rv = NULL; + struct private_data *priv = conn->devMonPrivateData; + remote_node_device_create_xml_args args; + remote_node_device_create_xml_ret ret; + + remoteDriverLock(priv); + + args.xml_desc = (char *)xml_desc; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NODE_DEVICE_CREATE_XML, + (xdrproc_t)xdr_remote_node_device_create_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_node_device_create_xml_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_node_device(conn, ret.dev); + xdr_free((xdrproc_t)xdr_remote_node_device_create_xml_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteNodeDeviceDestroy(virNodeDevicePtr dev) @@ -1577,7 +2061,32 @@ done: /* remoteDispatchNodeDeviceListCaps has to be implemented manually */ -/* remoteDispatchNodeDeviceLookupByName has to be implemented manually */ +static virNodeDevicePtr +remoteNodeDeviceLookupByName(virConnectPtr conn, const char *name) +{ + virNodeDevicePtr rv = NULL; + struct private_data *priv = conn->devMonPrivateData; + remote_node_device_lookup_by_name_args args; + remote_node_device_lookup_by_name_ret ret; + + remoteDriverLock(priv); + + args.name = (char *)name; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME, + (xdrproc_t)xdr_remote_node_device_lookup_by_name_args, (char *)&args, + (xdrproc_t)xdr_remote_node_device_lookup_by_name_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_node_device(conn, ret.dev); + xdr_free((xdrproc_t)xdr_remote_node_device_lookup_by_name_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteNodeDeviceNumOfCaps(virNodeDevicePtr dev) @@ -1611,7 +2120,28 @@ done: /* remoteDispatchNodeGetCellsFreeMemory has to be implemented manually */ -/* remoteDispatchNodeGetFreeMemory has to be implemented manually */ +static unsigned long long +remoteNodeGetFreeMemory(virConnectPtr conn) +{ + unsigned long long rv = 0; + struct private_data *priv = conn->privateData; + remote_node_get_free_memory_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_FREE_MEMORY, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_node_get_free_memory_ret, (char *)&ret) == -1) + goto done; + + rv = ret.freeMem; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchNodeGetInfo has to be implemented manually */ @@ -1905,9 +2435,59 @@ done: return rv; } -/* remoteDispatchNWFilterLookupByName has to be implemented manually */ +static virNWFilterPtr +remoteNWFilterLookupByName(virConnectPtr conn, const char *name) +{ + virNWFilterPtr rv = NULL; + struct private_data *priv = conn->nwfilterPrivateData; + remote_nwfilter_lookup_by_name_args args; + remote_nwfilter_lookup_by_name_ret ret; + + remoteDriverLock(priv); + + args.name = (char *)name; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NWFILTER_LOOKUP_BY_NAME, + (xdrproc_t)xdr_remote_nwfilter_lookup_by_name_args, (char *)&args, + (xdrproc_t)xdr_remote_nwfilter_lookup_by_name_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_nwfilter(conn, ret.nwfilter); + xdr_free((xdrproc_t)xdr_remote_nwfilter_lookup_by_name_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virNWFilterPtr +remoteNWFilterLookupByUUID(virConnectPtr conn, const unsigned char *uuid) +{ + virNWFilterPtr rv = NULL; + struct private_data *priv = conn->nwfilterPrivateData; + remote_nwfilter_lookup_by_uuid_args args; + remote_nwfilter_lookup_by_uuid_ret ret; + + remoteDriverLock(priv); + + memcpy(args.uuid, uuid, VIR_UUID_BUFLEN); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NWFILTER_LOOKUP_BY_UUID, + (xdrproc_t)xdr_remote_nwfilter_lookup_by_uuid_args, (char *)&args, + (xdrproc_t)xdr_remote_nwfilter_lookup_by_uuid_ret, (char *)&ret) == -1) + goto done; -/* remoteDispatchNWFilterLookupByUUID has to be implemented manually */ + rv = get_nonnull_nwfilter(conn, ret.nwfilter); + xdr_free((xdrproc_t)xdr_remote_nwfilter_lookup_by_uuid_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteNWFilterUndefine(virNWFilterPtr nwfilter) @@ -1934,7 +2514,33 @@ done: /* remoteDispatchOpen has to be implemented manually */ -/* remoteDispatchSecretDefineXML has to be implemented manually */ +static virSecretPtr +remoteSecretDefineXML(virConnectPtr conn, const char *xml, unsigned int flags) +{ + virSecretPtr rv = NULL; + struct private_data *priv = conn->secretPrivateData; + remote_secret_define_xml_args args; + remote_secret_define_xml_ret ret; + + remoteDriverLock(priv); + + args.xml = (char *)xml; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_SECRET_DEFINE_XML, + (xdrproc_t)xdr_remote_secret_define_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_secret_define_xml_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_secret(conn, ret.secret); + xdr_free((xdrproc_t)xdr_remote_secret_define_xml_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchSecretGetValue has to be implemented manually */ @@ -1965,9 +2571,60 @@ done: return rv; } -/* remoteDispatchSecretLookupByUsage has to be implemented manually */ +static virSecretPtr +remoteSecretLookupByUsage(virConnectPtr conn, int usageType, const char *usageID) +{ + virSecretPtr rv = NULL; + struct private_data *priv = conn->secretPrivateData; + remote_secret_lookup_by_usage_args args; + remote_secret_lookup_by_usage_ret ret; + + remoteDriverLock(priv); + + args.usageType = usageType; + args.usageID = (char *)usageID; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_SECRET_LOOKUP_BY_USAGE, + (xdrproc_t)xdr_remote_secret_lookup_by_usage_args, (char *)&args, + (xdrproc_t)xdr_remote_secret_lookup_by_usage_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_secret(conn, ret.secret); + xdr_free((xdrproc_t)xdr_remote_secret_lookup_by_usage_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virSecretPtr +remoteSecretLookupByUUID(virConnectPtr conn, const unsigned char *uuid) +{ + virSecretPtr rv = NULL; + struct private_data *priv = conn->secretPrivateData; + remote_secret_lookup_by_uuid_args args; + remote_secret_lookup_by_uuid_ret ret; + + remoteDriverLock(priv); + + memcpy(args.uuid, uuid, VIR_UUID_BUFLEN); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_SECRET_LOOKUP_BY_UUID, + (xdrproc_t)xdr_remote_secret_lookup_by_uuid_args, (char *)&args, + (xdrproc_t)xdr_remote_secret_lookup_by_uuid_ret, (char *)&ret) == -1) + goto done; -/* remoteDispatchSecretLookupByUUID has to be implemented manually */ + rv = get_nonnull_secret(conn, ret.secret); + xdr_free((xdrproc_t)xdr_remote_secret_lookup_by_uuid_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchSecretSetValue has to be implemented manually */ @@ -2042,9 +2699,61 @@ done: return rv; } -/* remoteDispatchStoragePoolCreateXML has to be implemented manually */ +static virStoragePoolPtr +remoteStoragePoolCreateXML(virConnectPtr conn, const char *xml, unsigned int flags) +{ + virStoragePoolPtr rv = NULL; + struct private_data *priv = conn->storagePrivateData; + remote_storage_pool_create_xml_args args; + remote_storage_pool_create_xml_ret ret; + + remoteDriverLock(priv); + + args.xml = (char *)xml; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_STORAGE_POOL_CREATE_XML, + (xdrproc_t)xdr_remote_storage_pool_create_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_pool_create_xml_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_storage_pool(conn, ret.pool); + xdr_free((xdrproc_t)xdr_remote_storage_pool_create_xml_ret, (char *)&ret); -/* remoteDispatchStoragePoolDefineXML has to be implemented manually */ +done: + remoteDriverUnlock(priv); + return rv; +} + +static virStoragePoolPtr +remoteStoragePoolDefineXML(virConnectPtr conn, const char *xml, unsigned int flags) +{ + virStoragePoolPtr rv = NULL; + struct private_data *priv = conn->storagePrivateData; + remote_storage_pool_define_xml_args args; + remote_storage_pool_define_xml_ret ret; + + remoteDriverLock(priv); + + args.xml = (char *)xml; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DEFINE_XML, + (xdrproc_t)xdr_remote_storage_pool_define_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_pool_define_xml_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_storage_pool(conn, ret.pool); + xdr_free((xdrproc_t)xdr_remote_storage_pool_define_xml_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteStoragePoolDelete(virStoragePoolPtr pool, unsigned int flags) @@ -2178,11 +2887,86 @@ done: /* remoteDispatchStoragePoolListVolumes has to be implemented manually */ -/* remoteDispatchStoragePoolLookupByName has to be implemented manually */ +static virStoragePoolPtr +remoteStoragePoolLookupByName(virConnectPtr conn, const char *name) +{ + virStoragePoolPtr rv = NULL; + struct private_data *priv = conn->storagePrivateData; + remote_storage_pool_lookup_by_name_args args; + remote_storage_pool_lookup_by_name_ret ret; + + remoteDriverLock(priv); + + args.name = (char *)name; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_NAME, + (xdrproc_t)xdr_remote_storage_pool_lookup_by_name_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_pool_lookup_by_name_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_storage_pool(conn, ret.pool); + xdr_free((xdrproc_t)xdr_remote_storage_pool_lookup_by_name_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virStoragePoolPtr +remoteStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid) +{ + virStoragePoolPtr rv = NULL; + struct private_data *priv = conn->storagePrivateData; + remote_storage_pool_lookup_by_uuid_args args; + remote_storage_pool_lookup_by_uuid_ret ret; + + remoteDriverLock(priv); + + memcpy(args.uuid, uuid, VIR_UUID_BUFLEN); -/* remoteDispatchStoragePoolLookupByUUID has to be implemented manually */ + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_UUID, + (xdrproc_t)xdr_remote_storage_pool_lookup_by_uuid_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_pool_lookup_by_uuid_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_storage_pool(conn, ret.pool); + xdr_free((xdrproc_t)xdr_remote_storage_pool_lookup_by_uuid_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virStoragePoolPtr +remoteStoragePoolLookupByVolume(virStorageVolPtr vol) +{ + virStoragePoolPtr rv = NULL; + struct private_data *priv = vol->conn->storagePrivateData; + remote_storage_pool_lookup_by_volume_args args; + remote_storage_pool_lookup_by_volume_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_vol(&args.vol, vol); + + memset(&ret, 0, sizeof ret); -/* remoteDispatchStoragePoolLookupByVolume has to be implemented manually */ + if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_VOLUME, + (xdrproc_t)xdr_remote_storage_pool_lookup_by_volume_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_pool_lookup_by_volume_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_storage_pool(vol->conn, ret.pool); + xdr_free((xdrproc_t)xdr_remote_storage_pool_lookup_by_volume_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteStoragePoolNumOfVolumes(virStoragePoolPtr pool) @@ -2281,9 +3065,64 @@ done: return rv; } -/* remoteDispatchStorageVolCreateXML has to be implemented manually */ +static virStorageVolPtr +remoteStorageVolCreateXML(virStoragePoolPtr pool, const char *xml, unsigned int flags) +{ + virStorageVolPtr rv = NULL; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_vol_create_xml_args args; + remote_storage_vol_create_xml_ret ret; + + remoteDriverLock(priv); -/* remoteDispatchStorageVolCreateXMLFrom has to be implemented manually */ + make_nonnull_storage_pool(&args.pool, pool); + args.xml = (char *)xml; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_CREATE_XML, + (xdrproc_t)xdr_remote_storage_vol_create_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_vol_create_xml_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_storage_vol(pool->conn, ret.vol); + xdr_free((xdrproc_t)xdr_remote_storage_vol_create_xml_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virStorageVolPtr +remoteStorageVolCreateXMLFrom(virStoragePoolPtr pool, const char *xml, virStorageVolPtr clonevol, unsigned int flags) +{ + virStorageVolPtr rv = NULL; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_vol_create_xml_from_args args; + remote_storage_vol_create_xml_from_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + args.xml = (char *)xml; + make_nonnull_storage_vol(&args.clonevol, clonevol); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM, + (xdrproc_t)xdr_remote_storage_vol_create_xml_from_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_vol_create_xml_from_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_storage_vol(pool->conn, ret.vol); + xdr_free((xdrproc_t)xdr_remote_storage_vol_create_xml_from_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteStorageVolDelete(virStorageVolPtr vol, unsigned int flags) @@ -2366,11 +3205,87 @@ done: return rv; } -/* remoteDispatchStorageVolLookupByKey has to be implemented manually */ +static virStorageVolPtr +remoteStorageVolLookupByKey(virConnectPtr conn, const char *key) +{ + virStorageVolPtr rv = NULL; + struct private_data *priv = conn->storagePrivateData; + remote_storage_vol_lookup_by_key_args args; + remote_storage_vol_lookup_by_key_ret ret; + + remoteDriverLock(priv); -/* remoteDispatchStorageVolLookupByName has to be implemented manually */ + args.key = (char *)key; -/* remoteDispatchStorageVolLookupByPath has to be implemented manually */ + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_KEY, + (xdrproc_t)xdr_remote_storage_vol_lookup_by_key_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_vol_lookup_by_key_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_storage_vol(conn, ret.vol); + xdr_free((xdrproc_t)xdr_remote_storage_vol_lookup_by_key_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virStorageVolPtr +remoteStorageVolLookupByName(virStoragePoolPtr pool, const char *name) +{ + virStorageVolPtr rv = NULL; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_vol_lookup_by_name_args args; + remote_storage_vol_lookup_by_name_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + args.name = (char *)name; + + memset(&ret, 0, sizeof ret); + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_NAME, + (xdrproc_t)xdr_remote_storage_vol_lookup_by_name_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_vol_lookup_by_name_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_storage_vol(pool->conn, ret.vol); + xdr_free((xdrproc_t)xdr_remote_storage_vol_lookup_by_name_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virStorageVolPtr +remoteStorageVolLookupByPath(virConnectPtr conn, const char *path) +{ + virStorageVolPtr rv = NULL; + struct private_data *priv = conn->storagePrivateData; + remote_storage_vol_lookup_by_path_args args; + remote_storage_vol_lookup_by_path_ret ret; + + remoteDriverLock(priv); + + args.path = (char *)path; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_PATH, + (xdrproc_t)xdr_remote_storage_vol_lookup_by_path_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_vol_lookup_by_path_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_storage_vol(conn, ret.vol); + xdr_free((xdrproc_t)xdr_remote_storage_vol_lookup_by_path_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchStorageVolUpload has to be implemented manually */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index a67f9f6..79ebfb3 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1810,31 +1810,6 @@ done: return rv; } - -static int -remoteGetMaxVcpus (virConnectPtr conn, const char *type) -{ - int rv = -1; - remote_get_max_vcpus_args args; - remote_get_max_vcpus_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - args.type = type == NULL ? NULL : (char **) &type; - if (call (conn, priv, 0, REMOTE_PROC_GET_MAX_VCPUS, - (xdrproc_t) xdr_remote_get_max_vcpus_args, (char *) &args, - (xdrproc_t) xdr_remote_get_max_vcpus_ret, (char *) &ret) == -1) - goto done; - - rv = ret.max_vcpus; - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info) { @@ -1908,29 +1883,6 @@ done: return rv; } -static unsigned long long -remoteNodeGetFreeMemory (virConnectPtr conn) -{ - unsigned long long rv = 0; /* 0 is error value this special function*/ - remote_node_get_free_memory_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_FREE_MEMORY, - (xdrproc_t) xdr_void, NULL, - (xdrproc_t) xdr_remote_node_get_free_memory_ret, (char *)&ret) == -1) - goto done; - - rv = ret.freeMem; - -done: - remoteDriverUnlock(priv); - return rv; -} - - static int remoteListDomains (virConnectPtr conn, int *ids, int maxids) { @@ -1976,113 +1928,6 @@ done: return rv; } -static virDomainPtr -remoteDomainCreateXML (virConnectPtr conn, - const char *xmlDesc, - unsigned int flags) -{ - virDomainPtr dom = NULL; - remote_domain_create_xml_args args; - remote_domain_create_xml_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - args.xml_desc = (char *) xmlDesc; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_CREATE_XML, - (xdrproc_t) xdr_remote_domain_create_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_create_xml_ret, (char *) &ret) == -1) - goto done; - - dom = get_nonnull_domain (conn, ret.dom); - xdr_free ((xdrproc_t) &xdr_remote_domain_create_xml_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return dom; -} - -static virDomainPtr -remoteDomainLookupByID (virConnectPtr conn, int id) -{ - virDomainPtr dom = NULL; - remote_domain_lookup_by_id_args args; - remote_domain_lookup_by_id_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - args.id = id; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_ID, - (xdrproc_t) xdr_remote_domain_lookup_by_id_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_lookup_by_id_ret, (char *) &ret) == -1) - goto done; - - dom = get_nonnull_domain (conn, ret.dom); - xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_id_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return dom; -} - -static virDomainPtr -remoteDomainLookupByUUID (virConnectPtr conn, const unsigned char *uuid) -{ - virDomainPtr dom = NULL; - remote_domain_lookup_by_uuid_args args; - remote_domain_lookup_by_uuid_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - memcpy (args.uuid, uuid, VIR_UUID_BUFLEN); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID, - (xdrproc_t) xdr_remote_domain_lookup_by_uuid_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret) == -1) - goto done; - - dom = get_nonnull_domain (conn, ret.dom); - xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return dom; -} - -static virDomainPtr -remoteDomainLookupByName (virConnectPtr conn, const char *name) -{ - virDomainPtr dom = NULL; - remote_domain_lookup_by_name_args args; - remote_domain_lookup_by_name_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - args.name = (char *) name; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_NAME, - (xdrproc_t) xdr_remote_domain_lookup_by_name_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_lookup_by_name_ret, (char *) &ret) == -1) - goto done; - - dom = get_nonnull_domain (conn, ret.dom); - xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_name_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return dom; -} - static int remoteDomainDestroy (virDomainPtr domain) { @@ -2666,68 +2511,6 @@ done: return rv; } -static char * -remoteDomainXMLFromNative (virConnectPtr conn, - const char *format, - const char *config, - unsigned int flags) -{ - char *rv = NULL; - remote_domain_xml_from_native_args args; - remote_domain_xml_from_native_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - args.nativeFormat = (char *)format; - args.nativeConfig = (char *)config; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_XML_FROM_NATIVE, - (xdrproc_t) xdr_remote_domain_xml_from_native_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_xml_from_native_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.domainXml; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static char * -remoteDomainXMLToNative (virConnectPtr conn, - const char *format, - const char *xml, - unsigned int flags) -{ - char *rv = NULL; - remote_domain_xml_to_native_args args; - remote_domain_xml_to_native_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - args.nativeFormat = (char *)format; - args.domainXml = (char *)xml; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_XML_TO_NATIVE, - (xdrproc_t) xdr_remote_domain_xml_to_native_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_xml_to_native_ret, (char *) &ret) == -1) - goto done; - - /* Caller frees. */ - rv = ret.nativeConfig; - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteDomainMigratePrepare (virConnectPtr dconn, char **cookie, int *cookielen, @@ -3062,32 +2845,6 @@ done: return rv; } -static virDomainPtr -remoteDomainDefineXML (virConnectPtr conn, const char *xml) -{ - virDomainPtr dom = NULL; - remote_domain_define_xml_args args; - remote_domain_define_xml_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - args.xml = (char *) xml; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_DEFINE_XML, - (xdrproc_t) xdr_remote_domain_define_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_define_xml_ret, (char *) &ret) == -1) - goto done; - - dom = get_nonnull_domain (conn, ret.dom); - xdr_free ((xdrproc_t) xdr_remote_domain_define_xml_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return dom; -} - static int remoteDomainGetAutostart (virDomainPtr domain, int *autostart) { @@ -3711,112 +3468,6 @@ done: return rv; } -static virNetworkPtr -remoteNetworkLookupByUUID (virConnectPtr conn, - const unsigned char *uuid) -{ - virNetworkPtr net = NULL; - remote_network_lookup_by_uuid_args args; - remote_network_lookup_by_uuid_ret ret; - struct private_data *priv = conn->networkPrivateData; - - remoteDriverLock(priv); - - memcpy (args.uuid, uuid, VIR_UUID_BUFLEN); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NETWORK_LOOKUP_BY_UUID, - (xdrproc_t) xdr_remote_network_lookup_by_uuid_args, (char *) &args, - (xdrproc_t) xdr_remote_network_lookup_by_uuid_ret, (char *) &ret) == -1) - goto done; - - net = get_nonnull_network (conn, ret.net); - xdr_free ((xdrproc_t) &xdr_remote_network_lookup_by_uuid_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return net; -} - -static virNetworkPtr -remoteNetworkLookupByName (virConnectPtr conn, - const char *name) -{ - virNetworkPtr net = NULL; - remote_network_lookup_by_name_args args; - remote_network_lookup_by_name_ret ret; - struct private_data *priv = conn->networkPrivateData; - - remoteDriverLock(priv); - - args.name = (char *) name; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NETWORK_LOOKUP_BY_NAME, - (xdrproc_t) xdr_remote_network_lookup_by_name_args, (char *) &args, - (xdrproc_t) xdr_remote_network_lookup_by_name_ret, (char *) &ret) == -1) - goto done; - - net = get_nonnull_network (conn, ret.net); - xdr_free ((xdrproc_t) &xdr_remote_network_lookup_by_name_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return net; -} - -static virNetworkPtr -remoteNetworkCreateXML (virConnectPtr conn, const char *xmlDesc) -{ - virNetworkPtr net = NULL; - remote_network_create_xml_args args; - remote_network_create_xml_ret ret; - struct private_data *priv = conn->networkPrivateData; - - remoteDriverLock(priv); - - args.xml = (char *) xmlDesc; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NETWORK_CREATE_XML, - (xdrproc_t) xdr_remote_network_create_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_network_create_xml_ret, (char *) &ret) == -1) - goto done; - - net = get_nonnull_network (conn, ret.net); - xdr_free ((xdrproc_t) &xdr_remote_network_create_xml_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return net; -} - -static virNetworkPtr -remoteNetworkDefineXML (virConnectPtr conn, const char *xml) -{ - virNetworkPtr net = NULL; - remote_network_define_xml_args args; - remote_network_define_xml_ret ret; - struct private_data *priv = conn->networkPrivateData; - - remoteDriverLock(priv); - - args.xml = (char *) xml; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NETWORK_DEFINE_XML, - (xdrproc_t) xdr_remote_network_define_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_network_define_xml_ret, (char *) &ret) == -1) - goto done; - - net = get_nonnull_network (conn, ret.net); - xdr_free ((xdrproc_t) &xdr_remote_network_define_xml_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return net; -} - static int remoteNetworkGetAutostart (virNetworkPtr network, int *autostart) { @@ -4024,89 +3675,6 @@ done: return rv; } -static virInterfacePtr -remoteInterfaceLookupByName (virConnectPtr conn, - const char *name) -{ - virInterfacePtr iface = NULL; - remote_interface_lookup_by_name_args args; - remote_interface_lookup_by_name_ret ret; - struct private_data *priv = conn->interfacePrivateData; - - remoteDriverLock(priv); - - args.name = (char *) name; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME, - (xdrproc_t) xdr_remote_interface_lookup_by_name_args, (char *) &args, - (xdrproc_t) xdr_remote_interface_lookup_by_name_ret, (char *) &ret) == -1) - goto done; - - iface = get_nonnull_interface (conn, ret.iface); - xdr_free ((xdrproc_t) &xdr_remote_interface_lookup_by_name_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return iface; -} - -static virInterfacePtr -remoteInterfaceLookupByMACString (virConnectPtr conn, - const char *mac) -{ - virInterfacePtr iface = NULL; - remote_interface_lookup_by_mac_string_args args; - remote_interface_lookup_by_mac_string_ret ret; - struct private_data *priv = conn->interfacePrivateData; - - remoteDriverLock(priv); - - args.mac = (char *) mac; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING, - (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_args, (char *) &args, - (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_ret, (char *) &ret) == -1) - goto done; - - iface = get_nonnull_interface (conn, ret.iface); - xdr_free ((xdrproc_t) &xdr_remote_interface_lookup_by_mac_string_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return iface; -} - -static virInterfacePtr -remoteInterfaceDefineXML (virConnectPtr conn, - const char *xmlDesc, - unsigned int flags) -{ - virInterfacePtr iface = NULL; - remote_interface_define_xml_args args; - remote_interface_define_xml_ret ret; - struct private_data *priv = conn->interfacePrivateData; - - remoteDriverLock(priv); - - args.xml = (char *) xmlDesc; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_DEFINE_XML, - (xdrproc_t) xdr_remote_interface_define_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_interface_define_xml_ret, (char *) &ret) == -1) - goto done; - - iface = get_nonnull_interface (conn, ret.iface); - xdr_free ((xdrproc_t) &xdr_remote_interface_define_xml_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return iface; -} - /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -4332,140 +3900,6 @@ done: return rv; } -static virStoragePoolPtr -remoteStoragePoolLookupByUUID (virConnectPtr conn, - const unsigned char *uuid) -{ - virStoragePoolPtr pool = NULL; - remote_storage_pool_lookup_by_uuid_args args; - remote_storage_pool_lookup_by_uuid_ret ret; - struct private_data *priv = conn->storagePrivateData; - - remoteDriverLock(priv); - - memcpy (args.uuid, uuid, VIR_UUID_BUFLEN); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_UUID, - (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_ret, (char *) &ret) == -1) - goto done; - - pool = get_nonnull_storage_pool (conn, ret.pool); - xdr_free ((xdrproc_t) &xdr_remote_storage_pool_lookup_by_uuid_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return pool; -} - -static virStoragePoolPtr -remoteStoragePoolLookupByName (virConnectPtr conn, - const char *name) -{ - virStoragePoolPtr pool = NULL; - remote_storage_pool_lookup_by_name_args args; - remote_storage_pool_lookup_by_name_ret ret; - struct private_data *priv = conn->storagePrivateData; - - remoteDriverLock(priv); - - args.name = (char *) name; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_NAME, - (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_ret, (char *) &ret) == -1) - goto done; - - pool = get_nonnull_storage_pool (conn, ret.pool); - xdr_free ((xdrproc_t) &xdr_remote_storage_pool_lookup_by_name_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return pool; -} - -static virStoragePoolPtr -remoteStoragePoolLookupByVolume (virStorageVolPtr vol) -{ - virStoragePoolPtr pool = NULL; - remote_storage_pool_lookup_by_volume_args args; - remote_storage_pool_lookup_by_volume_ret ret; - struct private_data *priv = vol->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_vol (&args.vol, vol); - - memset (&ret, 0, sizeof ret); - if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_VOLUME, - (xdrproc_t) xdr_remote_storage_pool_lookup_by_volume_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_pool_lookup_by_volume_ret, (char *) &ret) == -1) - goto done; - - pool = get_nonnull_storage_pool (vol->conn, ret.pool); - xdr_free ((xdrproc_t) &xdr_remote_storage_pool_lookup_by_volume_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return pool; -} - -static virStoragePoolPtr -remoteStoragePoolCreateXML (virConnectPtr conn, const char *xmlDesc, unsigned int flags) -{ - virStoragePoolPtr pool = NULL; - remote_storage_pool_create_xml_args args; - remote_storage_pool_create_xml_ret ret; - struct private_data *priv = conn->storagePrivateData; - - remoteDriverLock(priv); - - args.xml = (char *) xmlDesc; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_STORAGE_POOL_CREATE_XML, - (xdrproc_t) xdr_remote_storage_pool_create_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_pool_create_xml_ret, (char *) &ret) == -1) - goto done; - - pool = get_nonnull_storage_pool (conn, ret.pool); - xdr_free ((xdrproc_t) &xdr_remote_storage_pool_create_xml_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return pool; -} - -static virStoragePoolPtr -remoteStoragePoolDefineXML (virConnectPtr conn, const char *xml, unsigned int flags) -{ - virStoragePoolPtr pool = NULL; - remote_storage_pool_define_xml_args args; - remote_storage_pool_define_xml_ret ret; - struct private_data *priv = conn->storagePrivateData; - - remoteDriverLock(priv); - - args.xml = (char *) xml; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DEFINE_XML, - (xdrproc_t) xdr_remote_storage_pool_define_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_pool_define_xml_ret, (char *) &ret) == -1) - goto done; - - pool = get_nonnull_storage_pool (conn, ret.pool); - xdr_free ((xdrproc_t) &xdr_remote_storage_pool_define_xml_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return pool; -} - static int remoteStoragePoolGetInfo (virStoragePoolPtr pool, virStoragePoolInfoPtr info) { @@ -4580,151 +4014,6 @@ done: return rv; } - - -static virStorageVolPtr -remoteStorageVolLookupByName (virStoragePoolPtr pool, - const char *name) -{ - virStorageVolPtr vol = NULL; - remote_storage_vol_lookup_by_name_args args; - remote_storage_vol_lookup_by_name_ret ret; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool(&args.pool, pool); - args.name = (char *) name; - - memset (&ret, 0, sizeof ret); - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_NAME, - (xdrproc_t) xdr_remote_storage_vol_lookup_by_name_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_vol_lookup_by_name_ret, (char *) &ret) == -1) - goto done; - - vol = get_nonnull_storage_vol (pool->conn, ret.vol); - xdr_free ((xdrproc_t) &xdr_remote_storage_vol_lookup_by_name_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return vol; -} - -static virStorageVolPtr -remoteStorageVolLookupByKey (virConnectPtr conn, - const char *key) -{ - virStorageVolPtr vol = NULL; - remote_storage_vol_lookup_by_key_args args; - remote_storage_vol_lookup_by_key_ret ret; - struct private_data *priv = conn->storagePrivateData; - - remoteDriverLock(priv); - - args.key = (char *) key; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_KEY, - (xdrproc_t) xdr_remote_storage_vol_lookup_by_key_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_vol_lookup_by_key_ret, (char *) &ret) == -1) - goto done; - - vol = get_nonnull_storage_vol (conn, ret.vol); - xdr_free ((xdrproc_t) &xdr_remote_storage_vol_lookup_by_key_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return vol; -} - -static virStorageVolPtr -remoteStorageVolLookupByPath (virConnectPtr conn, - const char *path) -{ - virStorageVolPtr vol = NULL; - remote_storage_vol_lookup_by_path_args args; - remote_storage_vol_lookup_by_path_ret ret; - struct private_data *priv = conn->storagePrivateData; - - remoteDriverLock(priv); - - args.path = (char *) path; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_PATH, - (xdrproc_t) xdr_remote_storage_vol_lookup_by_path_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_vol_lookup_by_path_ret, (char *) &ret) == -1) - goto done; - - vol = get_nonnull_storage_vol (conn, ret.vol); - xdr_free ((xdrproc_t) &xdr_remote_storage_vol_lookup_by_path_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return vol; -} - -static virStorageVolPtr -remoteStorageVolCreateXML (virStoragePoolPtr pool, const char *xmlDesc, - unsigned int flags) -{ - virStorageVolPtr vol = NULL; - remote_storage_vol_create_xml_args args; - remote_storage_vol_create_xml_ret ret; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - args.xml = (char *) xmlDesc; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_CREATE_XML, - (xdrproc_t) xdr_remote_storage_vol_create_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_vol_create_xml_ret, (char *) &ret) == -1) - goto done; - - vol = get_nonnull_storage_vol (pool->conn, ret.vol); - xdr_free ((xdrproc_t) &xdr_remote_storage_vol_create_xml_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return vol; -} - -static virStorageVolPtr -remoteStorageVolCreateXMLFrom (virStoragePoolPtr pool, - const char *xmlDesc, - virStorageVolPtr clonevol, - unsigned int flags) -{ - virStorageVolPtr newvol = NULL; - remote_storage_vol_create_xml_from_args args; - remote_storage_vol_create_xml_from_ret ret; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - make_nonnull_storage_vol (&args.clonevol, clonevol); - args.xml = (char *) xmlDesc; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM, - (xdrproc_t) xdr_remote_storage_vol_create_xml_from_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_vol_create_xml_from_ret, (char *) &ret) == -1) - goto done; - - newvol = get_nonnull_storage_vol (pool->conn, ret.vol); - xdr_free ((xdrproc_t) &xdr_remote_storage_vol_create_xml_from_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return newvol; -} - static int remoteStorageVolGetInfo (virStorageVolPtr vol, virStorageVolInfoPtr info) { @@ -4881,34 +4170,6 @@ done: return rv; } - -static virNodeDevicePtr remoteNodeDeviceLookupByName(virConnectPtr conn, - const char *name) -{ - remote_node_device_lookup_by_name_args args; - remote_node_device_lookup_by_name_ret ret; - virNodeDevicePtr dev = NULL; - struct private_data *priv = conn->devMonPrivateData; - - remoteDriverLock(priv); - - args.name = (char *)name; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME, - (xdrproc_t) xdr_remote_node_device_lookup_by_name_args, (char *) &args, - (xdrproc_t) xdr_remote_node_device_lookup_by_name_ret, (char *) &ret) == -1) - goto done; - - dev = get_nonnull_node_device(conn, ret.dev); - - xdr_free ((xdrproc_t) xdr_remote_node_device_lookup_by_name_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return dev; -} - static char *remoteNodeDeviceGetParent(virNodeDevicePtr dev) { char *rv = NULL; @@ -5067,36 +4328,6 @@ done: return rv; } - -static virNodeDevicePtr -remoteNodeDeviceCreateXML(virConnectPtr conn, - const char *xmlDesc, - unsigned int flags) -{ - remote_node_device_create_xml_args args; - remote_node_device_create_xml_ret ret; - virNodeDevicePtr dev = NULL; - struct private_data *priv = conn->devMonPrivateData; - - remoteDriverLock(priv); - - memset(&ret, 0, sizeof ret); - args.xml_desc = (char *)xmlDesc; - args.flags = flags; - - if (call(conn, priv, 0, REMOTE_PROC_NODE_DEVICE_CREATE_XML, - (xdrproc_t) xdr_remote_node_device_create_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_node_device_create_xml_ret, (char *) &ret) == -1) - goto done; - - dev = get_nonnull_node_device(conn, ret.dev); - xdr_free ((xdrproc_t) xdr_remote_node_device_create_xml_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return dev; -} - /* ------------------------------------------------------------- */ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -5245,62 +4476,6 @@ done: return rv; } - - -static virNWFilterPtr -remoteNWFilterLookupByUUID (virConnectPtr conn, - const unsigned char *uuid) -{ - virNWFilterPtr net = NULL; - remote_nwfilter_lookup_by_uuid_args args; - remote_nwfilter_lookup_by_uuid_ret ret; - struct private_data *priv = conn->nwfilterPrivateData; - - remoteDriverLock(priv); - - memcpy (args.uuid, uuid, VIR_UUID_BUFLEN); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NWFILTER_LOOKUP_BY_UUID, - (xdrproc_t) xdr_remote_nwfilter_lookup_by_uuid_args, (char *) &args, - (xdrproc_t) xdr_remote_nwfilter_lookup_by_uuid_ret, (char *) &ret) == -1) - goto done; - - net = get_nonnull_nwfilter (conn, ret.nwfilter); - xdr_free ((xdrproc_t) &xdr_remote_nwfilter_lookup_by_uuid_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return net; -} - -static virNWFilterPtr -remoteNWFilterLookupByName (virConnectPtr conn, - const char *name) -{ - virNWFilterPtr net = NULL; - remote_nwfilter_lookup_by_name_args args; - remote_nwfilter_lookup_by_name_ret ret; - struct private_data *priv = conn->nwfilterPrivateData; - - remoteDriverLock(priv); - - args.name = (char *) name; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NWFILTER_LOOKUP_BY_NAME, - (xdrproc_t) xdr_remote_nwfilter_lookup_by_name_args, (char *) &args, - (xdrproc_t) xdr_remote_nwfilter_lookup_by_name_ret, (char *) &ret) == -1) - goto done; - - net = get_nonnull_nwfilter (conn, ret.nwfilter); - xdr_free ((xdrproc_t) &xdr_remote_nwfilter_lookup_by_name_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return net; -} - /*----------------------------------------------------------------------*/ static int @@ -6418,89 +5593,6 @@ done: return rv; } -static virSecretPtr -remoteSecretLookupByUUID (virConnectPtr conn, const unsigned char *uuid) -{ - virSecretPtr rv = NULL; - remote_secret_lookup_by_uuid_args args; - remote_secret_lookup_by_uuid_ret ret; - struct private_data *priv = conn->secretPrivateData; - - remoteDriverLock (priv); - - memcpy (args.uuid, uuid, VIR_UUID_BUFLEN); - - memset (&ret, 0, sizeof (ret)); - if (call (conn, priv, 0, REMOTE_PROC_SECRET_LOOKUP_BY_UUID, - (xdrproc_t) xdr_remote_secret_lookup_by_uuid_args, (char *) &args, - (xdrproc_t) xdr_remote_secret_lookup_by_uuid_ret, (char *) &ret) == -1) - goto done; - - rv = get_nonnull_secret (conn, ret.secret); - xdr_free ((xdrproc_t) xdr_remote_secret_lookup_by_uuid_ret, - (char *) &ret); - -done: - remoteDriverUnlock (priv); - return rv; -} - -static virSecretPtr -remoteSecretLookupByUsage (virConnectPtr conn, int usageType, const char *usageID) -{ - virSecretPtr rv = NULL; - remote_secret_lookup_by_usage_args args; - remote_secret_lookup_by_usage_ret ret; - struct private_data *priv = conn->secretPrivateData; - - remoteDriverLock (priv); - - args.usageType = usageType; - args.usageID = (char *)usageID; - - memset (&ret, 0, sizeof (ret)); - if (call (conn, priv, 0, REMOTE_PROC_SECRET_LOOKUP_BY_USAGE, - (xdrproc_t) xdr_remote_secret_lookup_by_usage_args, (char *) &args, - (xdrproc_t) xdr_remote_secret_lookup_by_usage_ret, (char *) &ret) == -1) - goto done; - - rv = get_nonnull_secret (conn, ret.secret); - xdr_free ((xdrproc_t) xdr_remote_secret_lookup_by_usage_ret, - (char *) &ret); - -done: - remoteDriverUnlock (priv); - return rv; -} - -static virSecretPtr -remoteSecretDefineXML (virConnectPtr conn, const char *xml, unsigned int flags) -{ - virSecretPtr rv = NULL; - remote_secret_define_xml_args args; - remote_secret_define_xml_ret ret; - struct private_data *priv = conn->secretPrivateData; - - remoteDriverLock (priv); - - args.xml = (char *) xml; - args.flags = flags; - - memset (&ret, 0, sizeof (ret)); - if (call (conn, priv, 0, REMOTE_PROC_SECRET_DEFINE_XML, - (xdrproc_t) xdr_remote_secret_define_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_secret_define_xml_ret, (char *) &ret) == -1) - goto done; - - rv = get_nonnull_secret (conn, ret.secret); - xdr_free ((xdrproc_t) xdr_remote_secret_define_xml_ret, - (char *) &ret); - -done: - remoteDriverUnlock (priv); - return rv; -} - static int remoteSecretSetValue (virSecretPtr secret, const unsigned char *value, size_t value_size, unsigned int flags) @@ -7173,36 +6265,6 @@ done: return rv; } -static virDomainSnapshotPtr -remoteDomainSnapshotCreateXML(virDomainPtr domain, - const char *xmlDesc, - unsigned int flags) -{ - virDomainSnapshotPtr snapshot = NULL; - remote_domain_snapshot_create_xml_args args; - remote_domain_snapshot_create_xml_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.xml_desc = (char *) xmlDesc; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML, - (xdrproc_t) xdr_remote_domain_snapshot_create_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_snapshot_create_xml_ret, (char *) &ret) == -1) - goto done; - - snapshot = get_nonnull_domain_snapshot(domain, ret.snap); - xdr_free ((xdrproc_t) &xdr_remote_domain_snapshot_create_xml_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return snapshot; -} - static int remoteDomainSnapshotListNames (virDomainPtr domain, char **const names, int maxnames, unsigned int flags) @@ -7266,64 +6328,6 @@ done: return rv; } - -static virDomainSnapshotPtr -remoteDomainSnapshotLookupByName (virDomainPtr domain, const char *name, - unsigned int flags) -{ - virDomainSnapshotPtr snapshot = NULL; - remote_domain_snapshot_lookup_by_name_args args; - remote_domain_snapshot_lookup_by_name_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain(&args.dom, domain); - args.name = (char *) name; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_LOOKUP_BY_NAME, - (xdrproc_t) xdr_remote_domain_snapshot_lookup_by_name_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_snapshot_lookup_by_name_ret, (char *) &ret) == -1) - goto done; - - snapshot = get_nonnull_domain_snapshot (domain, ret.snap); - xdr_free ((xdrproc_t) &xdr_remote_domain_snapshot_lookup_by_name_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return snapshot; -} - -static virDomainSnapshotPtr -remoteDomainSnapshotCurrent(virDomainPtr domain, - unsigned int flags) -{ - virDomainSnapshotPtr snapshot = NULL; - remote_domain_snapshot_current_args args; - remote_domain_snapshot_current_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain(&args.dom, domain); - args.flags = flags; - - memset(&ret, 0, sizeof ret); - if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT, - (xdrproc_t) xdr_remote_domain_snapshot_current_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_snapshot_current_ret, (char *) &ret) == -1) - goto done; - - snapshot = get_nonnull_domain_snapshot(domain, ret.snap); - xdr_free((xdrproc_t) &xdr_remote_domain_snapshot_current_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return snapshot; -} - static int remoteDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID, -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:14:06 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:14:06 +0200 Subject: [libvirt] [PATCH 19/22] remote generator, client: Handle functions with optional return values In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-20-git-send-email-matthias.bolte@googlemail.com> --- daemon/remote_generator.pl | 44 ++++++++----- src/remote/remote_client_bodies.c | 129 +++++++++++++++++++++++++++++++++++-- src/remote/remote_driver.c | 128 ------------------------------------ 3 files changed, 152 insertions(+), 149 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index b0e9a4c..774188b 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -473,9 +473,7 @@ elsif ($opt_b) { push(@ret_list, "ret->$1 = $1;"); $single_ret_var = $1; - if ($calls{$_}->{ProcName} eq "DomainGetAutostart" or - $calls{$_}->{ProcName} eq "NetworkGetAutostart" or - $calls{$_}->{ProcName} eq "StoragePoolGetAutostart") { + if ($calls{$_}->{ProcName} =~ m/GetAutostart$/) { $single_ret_by_ref = 1; } else { $single_ret_by_ref = 0; @@ -753,15 +751,12 @@ elsif ($opt_k) { "CPUBaseline", "DomainCreate", "DomainDestroy", - "DomainGetAutostart", "DomainMigrateFinish", "NWFilterDefineXML", # public API and XDR protocol mismatch "DomainMigratePerform", "DomainMigrateFinish2", "DomainSnapshotListNames", - "GetLibVersion", "FindStoragePoolSources", - "GetVersion", "IsSecure", "ListDefinedDomains", "ListDefinedInterfaces", @@ -773,8 +768,6 @@ elsif ($opt_k) { "StoragePoolListVolumes", "ListDomains", "ListStoragePools", - "NetworkGetAutostart", - "StoragePoolGetAutostart", "SecretSetValue", "GetURI", "ListInterfaces", @@ -995,18 +988,37 @@ elsif ($opt_k) { $single_ret_var = "vir${type_name}Ptr rv = NULL"; $single_ret_type = "vir${type_name}Ptr"; } elsif ($ret_member =~ m/^int (\S+);/) { - push(@ret_list, "rv = ret.$1;"); + my $arg_name = $1; + + if ($call->{ProcName} =~ m/GetAutostart$/) { + push(@args_list, "int *$arg_name"); + push(@ret_list, "if ($arg_name) *$arg_name = ret.$arg_name;"); + push(@ret_list, "rv = 0;"); + } else { + push(@ret_list, "rv = ret.$arg_name;"); + } + $single_ret_var = "int rv = -1"; $single_ret_type = "int"; } elsif ($ret_member =~ m/hyper (\S+);/) { - push(@ret_list, "rv = ret.$1;"); - - if ($call->{ProcName} eq "NodeGetFreeMemory") { - $single_ret_var = "unsigned long long rv = 0"; - $single_ret_type = "unsigned long long"; + my $arg_name = $1; + + if ($call->{ProcName} =~ m/Get(Lib)?Version/) { + push(@args_list, "unsigned long *$arg_name"); + push(@ret_list, "if ($arg_name) *$arg_name = ret.$arg_name;"); + push(@ret_list, "rv = 0;"); + $single_ret_var = "int rv = -1"; + $single_ret_type = "int"; } else { - $single_ret_var = "unsigned long rv = 0"; - $single_ret_type = "unsigned long"; + push(@ret_list, "rv = ret.$arg_name;"); + + if ($call->{ProcName} eq "NodeGetFreeMemory") { + $single_ret_var = "unsigned long long rv = 0"; + $single_ret_type = "unsigned long long"; + } else { + $single_ret_var = "unsigned long rv = 0"; + $single_ret_type = "unsigned long"; + } } } else { die "unhandled type for return value: $ret_member"; diff --git a/src/remote/remote_client_bodies.c b/src/remote/remote_client_bodies.c index 334b963..e61055b 100644 --- a/src/remote/remote_client_bodies.c +++ b/src/remote/remote_client_bodies.c @@ -319,7 +319,32 @@ done: /* remoteDispatchDomainEventsRegisterAny has to be implemented manually */ -/* remoteDispatchDomainGetAutostart has to be implemented manually */ +static int +remoteDomainGetAutostart(virDomainPtr dom, int *autostart) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_get_autostart_args args; + remote_domain_get_autostart_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_AUTOSTART, + (xdrproc_t)xdr_remote_domain_get_autostart_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_get_autostart_ret, (char *)&ret) == -1) + goto done; + + if (autostart) *autostart = ret.autostart; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchDomainGetBlkioParameters has to be implemented manually */ @@ -1538,7 +1563,29 @@ done: return rv; } -/* remoteDispatchGetLibVersion has to be implemented manually */ +static int +remoteGetLibVersion(virConnectPtr conn, unsigned long *lib_ver) +{ + int rv = -1; + struct private_data *priv = conn->privateData; + remote_get_lib_version_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_GET_LIB_VERSION, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_get_lib_version_ret, (char *)&ret) == -1) + goto done; + + if (lib_ver) *lib_ver = ret.lib_ver; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteGetMaxVcpus(virConnectPtr conn, const char *type) @@ -1596,7 +1643,29 @@ done: /* remoteDispatchGetURI has to be implemented manually */ -/* remoteDispatchGetVersion has to be implemented manually */ +static int +remoteGetVersion(virConnectPtr conn, unsigned long *hv_ver) +{ + int rv = -1; + struct private_data *priv = conn->privateData; + remote_get_version_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_GET_VERSION, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_get_version_ret, (char *)&ret) == -1) + goto done; + + if (hv_ver) *hv_ver = ret.hv_ver; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteInterfaceCreate(virInterfacePtr iface, unsigned int flags) @@ -1953,7 +2022,32 @@ done: return rv; } -/* remoteDispatchNetworkGetAutostart has to be implemented manually */ +static int +remoteNetworkGetAutostart(virNetworkPtr net, int *autostart) +{ + int rv = -1; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_get_autostart_args args; + remote_network_get_autostart_ret ret; + + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + + memset(&ret, 0, sizeof ret); + + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_GET_AUTOSTART, + (xdrproc_t)xdr_remote_network_get_autostart_args, (char *)&args, + (xdrproc_t)xdr_remote_network_get_autostart_ret, (char *)&ret) == -1) + goto done; + + if (autostart) *autostart = ret.autostart; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} static char * remoteNetworkGetBridgeName(virNetworkPtr net) @@ -3015,7 +3109,32 @@ done: return rv; } -/* remoteDispatchStoragePoolGetAutostart has to be implemented manually */ +static int +remoteStoragePoolGetAutostart(virStoragePoolPtr pool, int *autostart) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_get_autostart_args args; + remote_storage_pool_get_autostart_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + + memset(&ret, 0, sizeof ret); + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_GET_AUTOSTART, + (xdrproc_t)xdr_remote_storage_pool_get_autostart_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_pool_get_autostart_ret, (char *)&ret) == -1) + goto done; + + if (autostart) *autostart = ret.autostart; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteStoragePoolGetInfo(virStoragePoolPtr pool, virStoragePoolInfoPtr result) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 6cbcc35..8dc71d6 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1698,53 +1698,6 @@ done: return rv; } -static int -remoteGetVersion (virConnectPtr conn, unsigned long *hvVer) -{ - int rv = -1; - remote_get_version_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_GET_VERSION, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_get_version_ret, (char *) &ret) == -1) - goto done; - - if (hvVer) *hvVer = ret.hv_ver; - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteGetLibVersion (virConnectPtr conn, unsigned long *libVer) -{ - int rv = -1; - remote_get_lib_version_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_GET_LIB_VERSION, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_get_lib_version_ret, - (char *) &ret) == -1) - goto done; - - if (libVer) *libVer = ret.lib_ver; - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteIsSecure(virConnectPtr conn) { int rv = -1; @@ -2783,32 +2736,6 @@ done: return rv; } -static int -remoteDomainGetAutostart (virDomainPtr domain, int *autostart) -{ - int rv = -1; - remote_domain_get_autostart_args args; - remote_domain_get_autostart_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_AUTOSTART, - (xdrproc_t) xdr_remote_domain_get_autostart_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_get_autostart_ret, (char *) &ret) == -1) - goto done; - - if (autostart) *autostart = ret.autostart; - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - static char * remoteDomainGetSchedulerType (virDomainPtr domain, int *nparams) { @@ -3300,33 +3227,6 @@ done: return rv; } -static int -remoteNetworkGetAutostart (virNetworkPtr network, int *autostart) -{ - int rv = -1; - remote_network_get_autostart_args args; - remote_network_get_autostart_ret ret; - struct private_data *priv = network->conn->networkPrivateData; - - remoteDriverLock(priv); - - make_nonnull_network (&args.net, network); - - memset (&ret, 0, sizeof ret); - if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_GET_AUTOSTART, - (xdrproc_t) xdr_remote_network_get_autostart_args, (char *) &args, - (xdrproc_t) xdr_remote_network_get_autostart_ret, (char *) &ret) == -1) - goto done; - - if (autostart) *autostart = ret.autostart; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -3733,34 +3633,6 @@ done: } static int -remoteStoragePoolGetAutostart (virStoragePoolPtr pool, int *autostart) -{ - int rv = -1; - remote_storage_pool_get_autostart_args args; - remote_storage_pool_get_autostart_ret ret; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - - memset (&ret, 0, sizeof ret); - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_GET_AUTOSTART, - (xdrproc_t) xdr_remote_storage_pool_get_autostart_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_pool_get_autostart_ret, (char *) &ret) == -1) - goto done; - - if (autostart) *autostart = ret.autostart; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - - -static int remoteStoragePoolListVolumes (virStoragePoolPtr pool, char **const names, int maxnames) { int rv = -1; -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:14:05 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:14:05 +0200 Subject: [libvirt] [PATCH 18/22] remote generator, client: Handle functions with multiple return values In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-19-git-send-email-matthias.bolte@googlemail.com> --- daemon/remote_generator.pl | 63 +++++++--- src/remote/remote_client_bodies.c | 257 ++++++++++++++++++++++++++++++++++- src/remote/remote_driver.c | 266 ------------------------------------- 3 files changed, 296 insertions(+), 290 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 5045b7f..b0e9a4c 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -751,14 +751,9 @@ elsif ($opt_k) { "AuthPolkit", "CPUBaseline", - "DomainBlockStats", "DomainCreate", "DomainDestroy", "DomainGetAutostart", - "DomainGetBlockInfo", - "DomainGetInfo", - "DomainGetJobInfo", - "DomainInterfaceStats", "DomainMigrateFinish", "NWFilterDefineXML", # public API and XDR protocol mismatch "DomainMigratePerform", @@ -772,8 +767,6 @@ elsif ($opt_k) { "ListDefinedInterfaces", "ListNWFilters", "SupportsFeature", - "StorageVolGetInfo", - "StoragePoolGetInfo", "NodeListDevices", "NodeGetCellsFreeMemory", "ListDefinedNetworks", @@ -783,7 +776,6 @@ elsif ($opt_k) { "NetworkGetAutostart", "StoragePoolGetAutostart", "SecretSetValue", - "NodeGetInfo", "GetURI", "ListInterfaces", "ListDefinedStoragePools", @@ -831,16 +823,13 @@ elsif ($opt_k) { next; } + # handle arguments to the function my @args_list = (); my @vars_list = (); my @setters_list = (); - my @ret_list = (); my $priv_src = "conn"; my $priv_name = "privateData"; my $call_args = "&args"; - my $call_ret = "&ret"; - my $single_ret_var = "int rv = -1"; - my $single_ret_type = "int"; if ($call->{args} eq "void") { $call_args = "NULL"; @@ -937,6 +926,10 @@ elsif ($opt_k) { } } + if (! @args_list) { + push(@args_list, "virConnectPtr conn"); + } + # fix priv_name for the NumOf* functions if ($priv_name eq "privateData" and !($call->{ProcName} =~ m/Domains/) and @@ -946,13 +939,36 @@ elsif ($opt_k) { $priv_name = "${prefix}PrivateData"; } + # handle return values of the function + my @ret_list = (); + my $call_ret = "&ret"; + my $single_ret_var = "int rv = -1"; + my $single_ret_type = "int"; + my $multi_ret = 0; + + if ($call->{ret} ne "void" and + scalar(@{$call->{ret_members}}) > 1) { + $multi_ret = 1; + } + if ($call->{ret} eq "void") { $call_ret = "NULL"; } else { push(@vars_list, "$call->{ret} ret"); foreach my $ret_member (@{$call->{ret_members}}) { - if ($ret_member =~ m/remote_nonnull_string (\S+);/) { + if ($multi_ret) { + if ($ret_member =~ m/(char|short|int|hyper) (\S+)\[\S+\];/) { + push(@ret_list, "memcpy(result->$2, ret.$2, sizeof result->$2);"); + } elsif ($ret_member =~ m/char (\S+);/ or + $ret_member =~ m/short (\S+);/ or + $ret_member =~ m/int (\S+);/ or + $ret_member =~ m/hyper (\S+);/) { + push(@ret_list, "result->$1 = ret.$1;"); + } else { + die "unhandled type for multi-return-value: $ret_member"; + } + } elsif ($ret_member =~ m/remote_nonnull_string (\S+);/) { push(@ret_list, "rv = ret.$1;"); $single_ret_var = "char *rv = NULL"; $single_ret_type = "char *"; @@ -998,8 +1014,21 @@ elsif ($opt_k) { } } - if (! @args_list) { - push(@args_list, "virConnectPtr conn"); + # select struct type for multi-return-value functions + if ($multi_ret) { + my $last_arg; + my $struct_name = $call->{ProcName}; + $struct_name =~ s/Get//; + + if ($call->{ProcName} eq "DomainGetBlockInfo") { + $last_arg = pop(@args_list); + } + + push(@args_list, "vir${struct_name}Ptr result"); + + if (defined $last_arg) { + push(@args_list, $last_arg); + } } # print function @@ -1047,7 +1076,9 @@ elsif ($opt_k) { print " "; print join("\n ", @ret_list); print "\n"; - } else { + } + + if ($multi_ret or !@ret_list) { print " rv = 0;\n"; } diff --git a/src/remote/remote_client_bodies.c b/src/remote/remote_client_bodies.c index 5471c1b..334b963 100644 --- a/src/remote/remote_client_bodies.c +++ b/src/remote/remote_client_bodies.c @@ -117,7 +117,37 @@ done: /* remoteDispatchDomainBlockPeek has to be implemented manually */ -/* remoteDispatchDomainBlockStats has to be implemented manually */ +static int +remoteDomainBlockStats(virDomainPtr dom, const char *path, virDomainBlockStatsPtr result) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_block_stats_args args; + remote_domain_block_stats_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.path = (char *)path; + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_STATS, + (xdrproc_t)xdr_remote_domain_block_stats_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_block_stats_ret, (char *)&ret) == -1) + goto done; + + result->rd_req = ret.rd_req; + result->rd_bytes = ret.rd_bytes; + result->wr_req = ret.wr_req; + result->wr_bytes = ret.wr_bytes; + result->errs = ret.errs; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteDomainCoreDump(virDomainPtr dom, const char *to, int flags) @@ -293,11 +323,105 @@ done: /* remoteDispatchDomainGetBlkioParameters has to be implemented manually */ -/* remoteDispatchDomainGetBlockInfo has to be implemented manually */ +static int +remoteDomainGetBlockInfo(virDomainPtr dom, const char *path, virDomainBlockInfoPtr result, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_get_block_info_args args; + remote_domain_get_block_info_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.path = (char *)path; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_BLOCK_INFO, + (xdrproc_t)xdr_remote_domain_get_block_info_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_get_block_info_ret, (char *)&ret) == -1) + goto done; + + result->allocation = ret.allocation; + result->capacity = ret.capacity; + result->physical = ret.physical; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainGetInfo(virDomainPtr dom, virDomainInfoPtr result) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_get_info_args args; + remote_domain_get_info_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_INFO, + (xdrproc_t)xdr_remote_domain_get_info_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_get_info_ret, (char *)&ret) == -1) + goto done; -/* remoteDispatchDomainGetInfo has to be implemented manually */ + result->state = ret.state; + result->maxMem = ret.maxMem; + result->memory = ret.memory; + result->nrVirtCpu = ret.nrVirtCpu; + result->cpuTime = ret.cpuTime; + rv = 0; -/* remoteDispatchDomainGetJobInfo has to be implemented manually */ +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainGetJobInfo(virDomainPtr dom, virDomainJobInfoPtr result) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_get_job_info_args args; + remote_domain_get_job_info_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_JOB_INFO, + (xdrproc_t)xdr_remote_domain_get_job_info_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_get_job_info_ret, (char *)&ret) == -1) + goto done; + + result->type = ret.type; + result->timeElapsed = ret.timeElapsed; + result->timeRemaining = ret.timeRemaining; + result->dataTotal = ret.dataTotal; + result->dataProcessed = ret.dataProcessed; + result->dataRemaining = ret.dataRemaining; + result->memTotal = ret.memTotal; + result->memProcessed = ret.memProcessed; + result->memRemaining = ret.memRemaining; + result->fileTotal = ret.fileTotal; + result->fileProcessed = ret.fileProcessed; + result->fileRemaining = ret.fileRemaining; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} static unsigned long remoteDomainGetMaxMemory(virDomainPtr dom) @@ -468,7 +592,40 @@ done: return rv; } -/* remoteDispatchDomainInterfaceStats has to be implemented manually */ +static int +remoteDomainInterfaceStats(virDomainPtr dom, const char *path, virDomainInterfaceStatsPtr result) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_interface_stats_args args; + remote_domain_interface_stats_ret ret; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.path = (char *)path; + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_INTERFACE_STATS, + (xdrproc_t)xdr_remote_domain_interface_stats_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_interface_stats_ret, (char *)&ret) == -1) + goto done; + + result->rx_bytes = ret.rx_bytes; + result->rx_packets = ret.rx_packets; + result->rx_errs = ret.rx_errs; + result->rx_drop = ret.rx_drop; + result->tx_bytes = ret.tx_bytes; + result->tx_packets = ret.tx_packets; + result->tx_errs = ret.tx_errs; + result->tx_drop = ret.tx_drop; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteDomainIsActive(virDomainPtr dom) @@ -2143,7 +2300,36 @@ done: return rv; } -/* remoteDispatchNodeGetInfo has to be implemented manually */ +static int +remoteNodeGetInfo(virConnectPtr conn, virNodeInfoPtr result) +{ + int rv = -1; + struct private_data *priv = conn->privateData; + remote_node_get_info_ret ret; + + remoteDriverLock(priv); + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_INFO, + (xdrproc_t)xdr_void, (char *)NULL, + (xdrproc_t)xdr_remote_node_get_info_ret, (char *)&ret) == -1) + goto done; + + memcpy(result->model, ret.model, sizeof result->model); + result->memory = ret.memory; + result->cpus = ret.cpus; + result->mhz = ret.mhz; + result->nodes = ret.nodes; + result->sockets = ret.sockets; + result->cores = ret.cores; + result->threads = ret.threads; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchNodeGetSecurityModel has to be implemented manually */ @@ -2831,7 +3017,35 @@ done: /* remoteDispatchStoragePoolGetAutostart has to be implemented manually */ -/* remoteDispatchStoragePoolGetInfo has to be implemented manually */ +static int +remoteStoragePoolGetInfo(virStoragePoolPtr pool, virStoragePoolInfoPtr result) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_get_info_args args; + remote_storage_pool_get_info_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_pool(&args.pool, pool); + + memset(&ret, 0, sizeof ret); + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_GET_INFO, + (xdrproc_t)xdr_remote_storage_pool_get_info_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_pool_get_info_ret, (char *)&ret) == -1) + goto done; + + result->state = ret.state; + result->capacity = ret.capacity; + result->allocation = ret.allocation; + result->available = ret.available; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteStoragePoolIsActive(virStoragePoolPtr pool) @@ -3177,7 +3391,34 @@ done: return rv; } -/* remoteDispatchStorageVolGetInfo has to be implemented manually */ +static int +remoteStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr result) +{ + int rv = -1; + struct private_data *priv = vol->conn->storagePrivateData; + remote_storage_vol_get_info_args args; + remote_storage_vol_get_info_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_vol(&args.vol, vol); + + memset(&ret, 0, sizeof ret); + + if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_INFO, + (xdrproc_t)xdr_remote_storage_vol_get_info_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_vol_get_info_ret, (char *)&ret) == -1) + goto done; + + result->type = ret.type; + result->capacity = ret.capacity; + result->allocation = ret.allocation; + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} static char * remoteStorageVolGetPath(virStorageVolPtr vol) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 79ebfb3..6cbcc35 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1811,37 +1811,6 @@ done: } static int -remoteNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info) -{ - int rv = -1; - remote_node_get_info_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_INFO, - (xdrproc_t) xdr_void, (char *) NULL, - (xdrproc_t) xdr_remote_node_get_info_ret, (char *) &ret) == -1) - goto done; - - if (virStrcpyStatic(info->model, ret.model) == NULL) - goto done; - info->memory = ret.memory; - info->cpus = ret.cpus; - info->mhz = ret.mhz; - info->nodes = ret.nodes; - info->sockets = ret.sockets; - info->cores = ret.cores; - info->threads = ret.threads; - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems, int startCell, @@ -2291,37 +2260,6 @@ done: } static int -remoteDomainGetInfo (virDomainPtr domain, virDomainInfoPtr info) -{ - int rv = -1; - remote_domain_get_info_args args; - remote_domain_get_info_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_INFO, - (xdrproc_t) xdr_remote_domain_get_info_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_get_info_ret, (char *) &ret) == -1) - goto done; - - info->state = ret.state; - info->maxMem = ret.maxMem; - info->memory = ret.memory; - info->nrVirtCpu = ret.nrVirtCpu; - info->cpuTime = ret.cpuTime; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteDomainPinVcpu (virDomainPtr domain, unsigned int vcpu, unsigned char *cpumap, @@ -3035,78 +2973,6 @@ done: } static int -remoteDomainBlockStats (virDomainPtr domain, const char *path, - struct _virDomainBlockStats *stats) -{ - int rv = -1; - remote_domain_block_stats_args args; - remote_domain_block_stats_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.path = (char *) path; - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_STATS, - (xdrproc_t) xdr_remote_domain_block_stats_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_block_stats_ret, (char *) &ret) - == -1) - goto done; - - stats->rd_req = ret.rd_req; - stats->rd_bytes = ret.rd_bytes; - stats->wr_req = ret.wr_req; - stats->wr_bytes = ret.wr_bytes; - stats->errs = ret.errs; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteDomainInterfaceStats (virDomainPtr domain, const char *path, - struct _virDomainInterfaceStats *stats) -{ - int rv = -1; - remote_domain_interface_stats_args args; - remote_domain_interface_stats_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.path = (char *) path; - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_INTERFACE_STATS, - (xdrproc_t) xdr_remote_domain_interface_stats_args, - (char *) &args, - (xdrproc_t) xdr_remote_domain_interface_stats_ret, - (char *) &ret) == -1) - goto done; - - stats->rx_bytes = ret.rx_bytes; - stats->rx_packets = ret.rx_packets; - stats->rx_errs = ret.rx_errs; - stats->rx_drop = ret.rx_drop; - stats->tx_bytes = ret.tx_bytes; - stats->tx_packets = ret.tx_packets; - stats->tx_errs = ret.tx_errs; - stats->tx_drop = ret.tx_drop; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteDomainMemoryStats (virDomainPtr domain, struct _virDomainMemoryStat *stats, unsigned int nr_stats) @@ -3253,40 +3119,6 @@ done: return rv; } -static int -remoteDomainGetBlockInfo (virDomainPtr domain, - const char *path, - virDomainBlockInfoPtr info, - unsigned int flags) -{ - int rv = -1; - remote_domain_get_block_info_args args; - remote_domain_get_block_info_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.path = (char*)path; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_BLOCK_INFO, - (xdrproc_t) xdr_remote_domain_get_block_info_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_get_block_info_ret, (char *) &ret) == -1) - goto done; - - info->allocation = ret.allocation; - info->capacity = ret.capacity; - info->physical = ret.physical; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -3901,36 +3733,6 @@ done: } static int -remoteStoragePoolGetInfo (virStoragePoolPtr pool, virStoragePoolInfoPtr info) -{ - int rv = -1; - remote_storage_pool_get_info_args args; - remote_storage_pool_get_info_ret ret; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_pool (&args.pool, pool); - - memset (&ret, 0, sizeof ret); - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_GET_INFO, - (xdrproc_t) xdr_remote_storage_pool_get_info_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_pool_get_info_ret, (char *) &ret) == -1) - goto done; - - info->state = ret.state; - info->capacity = ret.capacity; - info->allocation = ret.allocation; - info->available = ret.available; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteStoragePoolGetAutostart (virStoragePoolPtr pool, int *autostart) { int rv = -1; @@ -4014,35 +3816,6 @@ done: return rv; } -static int -remoteStorageVolGetInfo (virStorageVolPtr vol, virStorageVolInfoPtr info) -{ - int rv = -1; - remote_storage_vol_get_info_args args; - remote_storage_vol_get_info_ret ret; - struct private_data *priv = vol->conn->storagePrivateData; - - remoteDriverLock(priv); - - make_nonnull_storage_vol (&args.vol, vol); - - memset (&ret, 0, sizeof ret); - if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_INFO, - (xdrproc_t) xdr_remote_storage_vol_get_info_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_vol_get_info_ret, (char *) &ret) == -1) - goto done; - - info->type = ret.type; - info->capacity = ret.capacity; - info->allocation = ret.allocation; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -6226,45 +5999,6 @@ done: return cpu; } - -static int -remoteDomainGetJobInfo (virDomainPtr domain, virDomainJobInfoPtr info) -{ - int rv = -1; - remote_domain_get_job_info_args args; - remote_domain_get_job_info_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_JOB_INFO, - (xdrproc_t) xdr_remote_domain_get_job_info_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_get_job_info_ret, (char *) &ret) == -1) - goto done; - - info->type = ret.type; - info->timeElapsed = ret.timeElapsed; - info->timeRemaining = ret.timeRemaining; - info->dataTotal = ret.dataTotal; - info->dataProcessed = ret.dataProcessed; - info->dataRemaining = ret.dataRemaining; - info->memTotal = ret.memTotal; - info->memProcessed = ret.memProcessed; - info->memRemaining = ret.memRemaining; - info->fileTotal = ret.fileTotal; - info->fileProcessed = ret.fileProcessed; - info->fileRemaining = ret.fileRemaining; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteDomainSnapshotListNames (virDomainPtr domain, char **const names, int maxnames, unsigned int flags) -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:14:07 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:14:07 +0200 Subject: [libvirt] [PATCH 20/22] remote: Refactor remote*Open and remote*Close functions In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-21-git-send-email-matthias.bolte@googlemail.com> Add generic versions of the open and close functions and call them. --- src/remote/remote_driver.c | 347 +++++++------------------------------------- 1 files changed, 51 insertions(+), 296 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 8dc71d6..777a7bf 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -3049,9 +3049,8 @@ done: /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) -remoteNetworkOpen (virConnectPtr conn, - virConnectAuthPtr auth, - int flags) +remoteGenericOpen(virConnectPtr conn, virConnectAuthPtr auth, + int flags, void **genericPrivateData) { if (inside_daemon) return VIR_DRV_OPEN_DECLINED; @@ -3060,45 +3059,48 @@ remoteNetworkOpen (virConnectPtr conn, STREQ (conn->driver->name, "remote")) { struct private_data *priv; - /* If we're here, the remote driver is already + /* If we're here, the remote driver is already * in use due to a) a QEMU uri, or b) a remote - * URI. So we can re-use existing connection - */ + * URI. So we can re-use existing connection */ priv = conn->privateData; remoteDriverLock(priv); priv->localUses++; - conn->networkPrivateData = priv; + *genericPrivateData = priv; + remoteDriverUnlock(priv); + return VIR_DRV_OPEN_SUCCESS; + } else if (conn->networkDriver && + STREQ (conn->networkDriver->name, "remote")) { + struct private_data *priv = conn->networkPrivateData; + remoteDriverLock(priv); + *genericPrivateData = priv; + priv->localUses++; remoteDriverUnlock(priv); return VIR_DRV_OPEN_SUCCESS; } else { /* Using a non-remote driver, so we need to open a * new connection for network APIs, forcing it to * use the UNIX transport. This handles Xen driver - * which doesn't have its own impl of the network APIs. - */ + * which doesn't have its own impl of the network APIs. */ struct private_data *priv; int ret; - ret = remoteOpenSecondaryDriver(conn, - auth, - flags, - &priv); + ret = remoteOpenSecondaryDriver(conn, auth, flags, &priv); if (ret == VIR_DRV_OPEN_SUCCESS) - conn->networkPrivateData = priv; + *genericPrivateData = priv; return ret; } } static int -remoteNetworkClose (virConnectPtr conn) +remoteGenericClose(virConnectPtr conn, void **genericPrivateData) { int rv = 0; - struct private_data *priv = conn->networkPrivateData; + struct private_data *priv = *genericPrivateData; remoteDriverLock(priv); priv->localUses--; if (!priv->localUses) { rv = doRemoteClose(conn, priv); - conn->networkPrivateData = NULL; + *genericPrivateData = NULL; remoteDriverUnlock(priv); virMutexDestroy(&priv->lock); VIR_FREE(priv); @@ -3108,6 +3110,18 @@ remoteNetworkClose (virConnectPtr conn) return rv; } +static virDrvOpenStatus ATTRIBUTE_NONNULL (1) +remoteNetworkOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags) +{ + return remoteGenericOpen(conn, auth, flags, &conn->networkPrivateData); +} + +static int +remoteNetworkClose(virConnectPtr conn) +{ + return remoteGenericClose(conn, &conn->networkPrivateData); +} + static int remoteListNetworks (virConnectPtr conn, char **const names, int maxnames) { @@ -3230,63 +3244,15 @@ done: /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) -remoteInterfaceOpen (virConnectPtr conn, - virConnectAuthPtr auth, - int flags) +remoteInterfaceOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags) { - if (inside_daemon) - return VIR_DRV_OPEN_DECLINED; - - if (conn->driver && - STREQ (conn->driver->name, "remote")) { - struct private_data *priv; - - /* If we're here, the remote driver is already - * in use due to a) a QEMU uri, or b) a remote - * URI. So we can re-use existing connection - */ - priv = conn->privateData; - remoteDriverLock(priv); - priv->localUses++; - conn->interfacePrivateData = priv; - remoteDriverUnlock(priv); - return VIR_DRV_OPEN_SUCCESS; - } else { - /* Using a non-remote driver, so we need to open a - * new connection for interface APIs, forcing it to - * use the UNIX transport. This handles Xen driver - * which doesn't have its own impl of the interface APIs. - */ - struct private_data *priv; - int ret; - ret = remoteOpenSecondaryDriver(conn, - auth, - flags, - &priv); - if (ret == VIR_DRV_OPEN_SUCCESS) - conn->interfacePrivateData = priv; - return ret; - } + return remoteGenericOpen(conn, auth, flags, &conn->interfacePrivateData); } static int -remoteInterfaceClose (virConnectPtr conn) +remoteInterfaceClose(virConnectPtr conn) { - int rv = 0; - struct private_data *priv = conn->interfacePrivateData; - - remoteDriverLock(priv); - priv->localUses--; - if (!priv->localUses) { - rv = doRemoteClose(conn, priv); - conn->interfacePrivateData = NULL; - remoteDriverUnlock(priv); - virMutexDestroy(&priv->lock); - VIR_FREE(priv); - } - if (priv) - remoteDriverUnlock(priv); - return rv; + return remoteGenericClose(conn, &conn->interfacePrivateData); } static int @@ -3410,70 +3376,15 @@ done: /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) -remoteStorageOpen (virConnectPtr conn, - virConnectAuthPtr auth, - int flags) +remoteStorageOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags) { - if (inside_daemon) - return VIR_DRV_OPEN_DECLINED; - - if (conn->driver && - STREQ (conn->driver->name, "remote")) { - struct private_data *priv = conn->privateData; - /* If we're here, the remote driver is already - * in use due to a) a QEMU uri, or b) a remote - * URI. So we can re-use existing connection - */ - remoteDriverLock(priv); - priv->localUses++; - conn->storagePrivateData = priv; - remoteDriverUnlock(priv); - return VIR_DRV_OPEN_SUCCESS; - } else if (conn->networkDriver && - STREQ (conn->networkDriver->name, "remote")) { - struct private_data *priv = conn->networkPrivateData; - remoteDriverLock(priv); - conn->storagePrivateData = priv; - priv->localUses++; - remoteDriverUnlock(priv); - return VIR_DRV_OPEN_SUCCESS; - } else { - /* Using a non-remote driver, so we need to open a - * new connection for network APIs, forcing it to - * use the UNIX transport. This handles Xen driver - * which doesn't have its own impl of the network APIs. - */ - struct private_data *priv; - int ret; - ret = remoteOpenSecondaryDriver(conn, - auth, - flags, - &priv); - if (ret == VIR_DRV_OPEN_SUCCESS) - conn->storagePrivateData = priv; - return ret; - } + return remoteGenericOpen(conn, auth, flags, &conn->storagePrivateData); } static int -remoteStorageClose (virConnectPtr conn) +remoteStorageClose(virConnectPtr conn) { - int ret = 0; - struct private_data *priv = conn->storagePrivateData; - - remoteDriverLock(priv); - priv->localUses--; - if (!priv->localUses) { - ret = doRemoteClose(conn, priv); - conn->storagePrivateData = NULL; - remoteDriverUnlock(priv); - virMutexDestroy(&priv->lock); - VIR_FREE(priv); - } - if (priv) - remoteDriverUnlock(priv); - - return ret; + return remoteGenericClose(conn, &conn->storagePrivateData); } static int @@ -3691,68 +3602,15 @@ done: /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) -remoteDevMonOpen(virConnectPtr conn, - virConnectAuthPtr auth ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED) +remoteDevMonOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags) { - if (inside_daemon) - return VIR_DRV_OPEN_DECLINED; - - if (conn->driver && - STREQ (conn->driver->name, "remote")) { - struct private_data *priv = conn->privateData; - /* If we're here, the remote driver is already - * in use due to a) a QEMU uri, or b) a remote - * URI. So we can re-use existing connection - */ - remoteDriverLock(priv); - priv->localUses++; - conn->devMonPrivateData = priv; - remoteDriverUnlock(priv); - return VIR_DRV_OPEN_SUCCESS; - } else if (conn->networkDriver && - STREQ (conn->networkDriver->name, "remote")) { - struct private_data *priv = conn->networkPrivateData; - remoteDriverLock(priv); - conn->devMonPrivateData = priv; - priv->localUses++; - remoteDriverUnlock(priv); - return VIR_DRV_OPEN_SUCCESS; - } else { - /* Using a non-remote driver, so we need to open a - * new connection for network APIs, forcing it to - * use the UNIX transport. This handles Xen driver - * which doesn't have its own impl of the network APIs. - */ - struct private_data *priv; - int ret; - ret = remoteOpenSecondaryDriver(conn, - auth, - flags, - &priv); - if (ret == VIR_DRV_OPEN_SUCCESS) - conn->devMonPrivateData = priv; - return ret; - } + return remoteGenericOpen(conn, auth, flags, &conn->devMonPrivateData); } -static int remoteDevMonClose(virConnectPtr conn) +static int +remoteDevMonClose(virConnectPtr conn) { - int ret = 0; - struct private_data *priv = conn->devMonPrivateData; - - remoteDriverLock(priv); - priv->localUses--; - if (!priv->localUses) { - ret = doRemoteClose(conn, priv); - conn->devMonPrivateData = NULL; - remoteDriverUnlock(priv); - virMutexDestroy(&priv->lock); - VIR_FREE(priv); - } - if (priv) - remoteDriverUnlock(priv); - return ret; + return remoteGenericClose(conn, &conn->devMonPrivateData); } static int remoteNodeListDevices(virConnectPtr conn, @@ -3976,63 +3834,15 @@ done: /* ------------------------------------------------------------- */ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) -remoteNWFilterOpen (virConnectPtr conn, - virConnectAuthPtr auth, - int flags) +remoteNWFilterOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags) { - if (inside_daemon) - return VIR_DRV_OPEN_DECLINED; - - if (conn->driver && - STREQ (conn->driver->name, "remote")) { - struct private_data *priv; - - /* If we're here, the remote driver is already - * in use due to a) a QEMU uri, or b) a remote - * URI. So we can re-use existing connection - */ - priv = conn->privateData; - remoteDriverLock(priv); - priv->localUses++; - conn->nwfilterPrivateData = priv; - remoteDriverUnlock(priv); - return VIR_DRV_OPEN_SUCCESS; - } else { - /* Using a non-remote driver, so we need to open a - * new connection for network filtering APIs, forcing it to - * use the UNIX transport. This handles Xen driver - * which doesn't have its own impl of the network filtering APIs. - */ - struct private_data *priv; - int ret; - ret = remoteOpenSecondaryDriver(conn, - auth, - flags, - &priv); - if (ret == VIR_DRV_OPEN_SUCCESS) - conn->nwfilterPrivateData = priv; - return ret; - } + return remoteGenericOpen(conn, auth, flags, &conn->nwfilterPrivateData); } static int -remoteNWFilterClose (virConnectPtr conn) +remoteNWFilterClose(virConnectPtr conn) { - int rv = 0; - struct private_data *priv = conn->nwfilterPrivateData; - - remoteDriverLock(priv); - priv->localUses--; - if (!priv->localUses) { - rv = doRemoteClose(conn, priv); - conn->nwfilterPrivateData = NULL; - remoteDriverUnlock(priv); - virMutexDestroy(&priv->lock); - VIR_FREE(priv); - } - if (priv) - remoteDriverUnlock(priv); - return rv; + return remoteGenericClose(conn, &conn->nwfilterPrivateData); } static virNWFilterPtr @@ -5116,70 +4926,15 @@ no_memory: static virDrvOpenStatus ATTRIBUTE_NONNULL (1) -remoteSecretOpen (virConnectPtr conn, - virConnectAuthPtr auth, - int flags) +remoteSecretOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags) { - if (inside_daemon) - return VIR_DRV_OPEN_DECLINED; - - if (conn->driver && - STREQ (conn->driver->name, "remote")) { - struct private_data *priv; - - /* If we're here, the remote driver is already - * in use due to a) a QEMU uri, or b) a remote - * URI. So we can re-use existing connection - */ - priv = conn->privateData; - remoteDriverLock(priv); - priv->localUses++; - conn->secretPrivateData = priv; - remoteDriverUnlock(priv); - return VIR_DRV_OPEN_SUCCESS; - } else if (conn->networkDriver && - STREQ (conn->networkDriver->name, "remote")) { - struct private_data *priv = conn->networkPrivateData; - remoteDriverLock(priv); - conn->secretPrivateData = priv; - priv->localUses++; - remoteDriverUnlock(priv); - return VIR_DRV_OPEN_SUCCESS; - } else { - /* Using a non-remote driver, so we need to open a - * new connection for secret APIs, forcing it to - * use the UNIX transport. - */ - struct private_data *priv; - int ret; - ret = remoteOpenSecondaryDriver(conn, - auth, - flags, - &priv); - if (ret == VIR_DRV_OPEN_SUCCESS) - conn->secretPrivateData = priv; - return ret; - } + return remoteGenericOpen(conn, auth, flags, &conn->secretPrivateData); } static int remoteSecretClose (virConnectPtr conn) { - int rv = 0; - struct private_data *priv = conn->secretPrivateData; - - conn->secretPrivateData = NULL; - remoteDriverLock(priv); - priv->localUses--; - if (!priv->localUses) { - rv = doRemoteClose(conn, priv); - remoteDriverUnlock(priv); - virMutexDestroy(&priv->lock); - VIR_FREE(priv); - } - if (priv) - remoteDriverUnlock(priv); - return rv; + return remoteGenericClose(conn, &conn->secretPrivateData); } static int -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:14:09 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:14:09 +0200 Subject: [libvirt] [PATCH 22/22] remote generator, client: Handle arguments with limited length In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-23-git-send-email-matthias.bolte@googlemail.com> This adds length checks to all affected functions. --- daemon/remote_generator.pl | 49 ++++++-- src/remote/remote_client_bodies.c | 267 ++++++++++++++++++++++++++++++++++--- src/remote/remote_driver.c | 227 ------------------------------- 3 files changed, 287 insertions(+), 256 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index f5be8d6..ac9cde8 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -734,7 +734,6 @@ elsif ($opt_k) { "DomainEventsRegisterAny", "DomainMigratePrepareTunnel", "DomainOpenConsole", - "DomainPinVcpu", "DomainSetSchedulerParameters", "DomainSetMemoryParameters", "DomainSetBlkioParameters", @@ -748,19 +747,13 @@ elsif ($opt_k) { "AuthSaslStep", "AuthPolkit", - "CPUBaseline", "DomainCreate", "DomainDestroy", - "DomainMigrateFinish", - "NWFilterDefineXML", # public API and XDR protocol mismatch - "DomainMigratePerform", - "DomainMigrateFinish2", "FindStoragePoolSources", "IsSecure", "SupportsFeature", "NodeGetCellsFreeMemory", "ListDomains", - "SecretSetValue", "GetURI", "NodeDeviceDettach", "NodeDeviceReset", @@ -806,6 +799,7 @@ elsif ($opt_k) { # handle arguments to the function my @args_list = (); my @vars_list = (); + my @args_check_list = (); my @setters_list = (); my $priv_src = "conn"; my $priv_name = "privateData"; @@ -859,11 +853,30 @@ elsif ($opt_k) { } elsif ($args_member =~ m/^remote_string (\S+);/) { push(@args_list, "const char *$1"); push(@setters_list, "args.$1 = $1 ? (char **)&$1 : NULL;"); + } elsif ($args_member =~ m/^remote_nonnull_string (\S+)<(\S+)>;/) { + push(@args_list, "const char **$1"); + push(@args_list, "unsigned int ${1}len"); + push(@setters_list, "args.$1.${1}_val = (char **)$1;"); + push(@setters_list, "args.$1.${1}_len = ${1}len;"); + push(@args_check_list, { name => "\"$1\"", arg => "${1}len", limit => $2 }); } elsif ($args_member =~ m/^remote_nonnull_string (\S+);/) { push(@args_list, "const char *$1"); push(@setters_list, "args.$1 = (char *)$1;"); - } elsif ($args_member =~ m/(\S+)<\S+>;/) { - # ignored for now + } elsif ($args_member =~ m/(\S+)<(\S+)>;/) { + if ($call->{ProcName} eq "SecretSetValue") { + push(@args_list, "const unsigned char *$1"); + push(@args_list, "size_t ${1}len"); + } elsif ($call->{ProcName} eq "DomainPinVcpu") { + push(@args_list, "unsigned char *$1"); + push(@args_list, "int ${1}len"); + } else { + push(@args_list, "const char *$1"); + push(@args_list, "int ${1}len"); + } + + push(@setters_list, "args.$1.${1}_val = (char *)$1;"); + push(@setters_list, "args.$1.${1}_len = ${1}len;"); + push(@args_check_list, { name => "\"$1\"", arg => "${1}len", limit => $2 }); } elsif ($args_member =~ m/^(.*) (\S+);/) { my $type_name = $1; my $arg_name = $2; @@ -882,6 +895,9 @@ elsif ($opt_k) { } elsif ($arg_name eq "nvcpus" and $call->{ProcName} eq "DomainSetVcpus") { $type_name = "unsigned int"; + } elsif ($arg_name eq "vcpu" and + $call->{ProcName} eq "DomainPinVcpu") { + $type_name = "unsigned int"; } } @@ -910,6 +926,11 @@ elsif ($opt_k) { push(@args_list, "virConnectPtr conn"); } + if ($call->{ProcName} eq "NWFilterDefineXML") { + # fix public API and XDR protocol mismatch + push(@args_list, "unsigned int flags ATTRIBUTE_UNUSED"); + } + # fix priv_name for the NumOf* functions if ($priv_name eq "privateData" and !($call->{ProcName} =~ m/(Domains|DomainSnapshot)/) and @@ -1082,6 +1103,16 @@ elsif ($opt_k) { print "\n"; print " remoteDriverLock(priv);\n"; + foreach my $args_check (@args_check_list) { + print "\n"; + print " if ($args_check->{arg} > $args_check->{limit}) {\n"; + print " remoteError(VIR_ERR_RPC,\n"; + print " _(\"%s length greater than maximum: %d > %d\"),\n"; + print " $args_check->{name}, (int)$args_check->{arg}, $args_check->{limit});\n"; + print " goto done;\n"; + print " }\n"; + } + if ($single_ret_as_list) { print "\n"; print " if ($single_ret_list_max_var > $single_ret_list_max_define) {\n"; diff --git a/src/remote/remote_client_bodies.c b/src/remote/remote_client_bodies.c index 4970c23..7a77d70 100644 --- a/src/remote/remote_client_bodies.c +++ b/src/remote/remote_client_bodies.c @@ -14,7 +14,40 @@ /* remoteDispatchClose has to be implemented manually */ -/* remoteDispatchCPUBaseline has to be implemented manually */ +static char * +remoteCPUBaseline(virConnectPtr conn, const char **xmlCPUs, unsigned int xmlCPUslen, unsigned int flags) +{ + char *rv = NULL; + struct private_data *priv = conn->privateData; + remote_cpu_baseline_args args; + remote_cpu_baseline_ret ret; + + remoteDriverLock(priv); + + if (xmlCPUslen > REMOTE_CPU_BASELINE_MAX) { + remoteError(VIR_ERR_RPC, + _("%s length greater than maximum: %d > %d"), + "xmlCPUs", (int)xmlCPUslen, REMOTE_CPU_BASELINE_MAX); + goto done; + } + + args.xmlCPUs.xmlCPUs_val = (char **)xmlCPUs; + args.xmlCPUs.xmlCPUs_len = xmlCPUslen; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_CPU_BASELINE, + (xdrproc_t)xdr_remote_cpu_baseline_args, (char *)&args, + (xdrproc_t)xdr_remote_cpu_baseline_ret, (char *)&ret) == -1) + goto done; + + rv = ret.cpu; + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteCPUCompare(virConnectPtr conn, const char *xml, unsigned int flags) @@ -863,11 +896,118 @@ done: /* remoteDispatchDomainMemoryStats has to be implemented manually */ -/* remoteDispatchDomainMigrateFinish has to be implemented manually */ +static virDomainPtr +remoteDomainMigrateFinish(virConnectPtr conn, const char *dname, const char *cookie, int cookielen, const char *uri, unsigned long flags) +{ + virDomainPtr rv = NULL; + struct private_data *priv = conn->privateData; + remote_domain_migrate_finish_args args; + remote_domain_migrate_finish_ret ret; + + remoteDriverLock(priv); + + if (cookielen > REMOTE_MIGRATE_COOKIE_MAX) { + remoteError(VIR_ERR_RPC, + _("%s length greater than maximum: %d > %d"), + "cookie", (int)cookielen, REMOTE_MIGRATE_COOKIE_MAX); + goto done; + } + + args.dname = (char *)dname; + args.cookie.cookie_val = (char *)cookie; + args.cookie.cookie_len = cookielen; + args.uri = (char *)uri; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH, + (xdrproc_t)xdr_remote_domain_migrate_finish_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_migrate_finish_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_domain(conn, ret.ddom); + xdr_free((xdrproc_t)xdr_remote_domain_migrate_finish_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virDomainPtr +remoteDomainMigrateFinish2(virConnectPtr conn, const char *dname, const char *cookie, int cookielen, const char *uri, unsigned long flags, int retcode) +{ + virDomainPtr rv = NULL; + struct private_data *priv = conn->privateData; + remote_domain_migrate_finish2_args args; + remote_domain_migrate_finish2_ret ret; + + remoteDriverLock(priv); + + if (cookielen > REMOTE_MIGRATE_COOKIE_MAX) { + remoteError(VIR_ERR_RPC, + _("%s length greater than maximum: %d > %d"), + "cookie", (int)cookielen, REMOTE_MIGRATE_COOKIE_MAX); + goto done; + } + + args.dname = (char *)dname; + args.cookie.cookie_val = (char *)cookie; + args.cookie.cookie_len = cookielen; + args.uri = (char *)uri; + args.flags = flags; + args.retcode = retcode; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH2, + (xdrproc_t)xdr_remote_domain_migrate_finish2_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_migrate_finish2_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_domain(conn, ret.ddom); + xdr_free((xdrproc_t)xdr_remote_domain_migrate_finish2_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteDomainMigratePerform(virDomainPtr dom, const char *cookie, int cookielen, const char *uri, unsigned long flags, const char *dname, unsigned long resource) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_migrate_perform_args args; + + remoteDriverLock(priv); + + if (cookielen > REMOTE_MIGRATE_COOKIE_MAX) { + remoteError(VIR_ERR_RPC, + _("%s length greater than maximum: %d > %d"), + "cookie", (int)cookielen, REMOTE_MIGRATE_COOKIE_MAX); + goto done; + } + + make_nonnull_domain(&args.dom, dom); + args.cookie.cookie_val = (char *)cookie; + args.cookie.cookie_len = cookielen; + args.uri = (char *)uri; + args.flags = flags; + args.dname = dname ? (char **)&dname : NULL; + args.resource = resource; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PERFORM, + (xdrproc_t)xdr_remote_domain_migrate_perform_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; -/* remoteDispatchDomainMigrateFinish2 has to be implemented manually */ + rv = 0; -/* remoteDispatchDomainMigratePerform has to be implemented manually */ +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchDomainMigratePrepare has to be implemented manually */ @@ -927,7 +1067,38 @@ done: /* remoteDispatchDomainOpenConsole has to be implemented manually */ -/* remoteDispatchDomainPinVcpu has to be implemented manually */ +static int +remoteDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap, int cpumaplen) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_pin_vcpu_args args; + + remoteDriverLock(priv); + + if (cpumaplen > REMOTE_CPUMAP_MAX) { + remoteError(VIR_ERR_RPC, + _("%s length greater than maximum: %d > %d"), + "cpumap", (int)cpumaplen, REMOTE_CPUMAP_MAX); + goto done; + } + + make_nonnull_domain(&args.dom, dom); + args.vcpu = vcpu; + args.cpumap.cpumap_val = (char *)cpumap; + args.cpumap.cpumap_len = cpumaplen; + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_PIN_VCPU, + (xdrproc_t)xdr_remote_domain_pin_vcpu_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteDomainReboot(virDomainPtr dom, unsigned int flags) @@ -1343,7 +1514,7 @@ remoteDomainSnapshotListNames(virDomainPtr dom, char **const names, int maxnames if (maxnames > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined names: %d > %d"), + _("too many remote undefineds: %d > %d"), maxnames, REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX); goto done; } @@ -1948,7 +2119,7 @@ remoteListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) if (maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined names: %d > %d"), + _("too many remote undefineds: %d > %d"), maxnames, REMOTE_DOMAIN_NAME_LIST_MAX); goto done; } @@ -2008,7 +2179,7 @@ remoteListDefinedInterfaces(virConnectPtr conn, char **const names, int maxnames if (maxnames > REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined names: %d > %d"), + _("too many remote undefineds: %d > %d"), maxnames, REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX); goto done; } @@ -2068,7 +2239,7 @@ remoteListDefinedNetworks(virConnectPtr conn, char **const names, int maxnames) if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined names: %d > %d"), + _("too many remote undefineds: %d > %d"), maxnames, REMOTE_NETWORK_NAME_LIST_MAX); goto done; } @@ -2128,7 +2299,7 @@ remoteListDefinedStoragePools(virConnectPtr conn, char **const names, int maxnam if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined names: %d > %d"), + _("too many remote undefineds: %d > %d"), maxnames, REMOTE_STORAGE_POOL_NAME_LIST_MAX); goto done; } @@ -2190,7 +2361,7 @@ remoteListInterfaces(virConnectPtr conn, char **const names, int maxnames) if (maxnames > REMOTE_INTERFACE_NAME_LIST_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined names: %d > %d"), + _("too many remote undefineds: %d > %d"), maxnames, REMOTE_INTERFACE_NAME_LIST_MAX); goto done; } @@ -2250,7 +2421,7 @@ remoteListNetworks(virConnectPtr conn, char **const names, int maxnames) if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined names: %d > %d"), + _("too many remote undefineds: %d > %d"), maxnames, REMOTE_NETWORK_NAME_LIST_MAX); goto done; } @@ -2310,7 +2481,7 @@ remoteListNWFilters(virConnectPtr conn, char **const names, int maxnames) if (maxnames > REMOTE_NWFILTER_NAME_LIST_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined names: %d > %d"), + _("too many remote undefineds: %d > %d"), maxnames, REMOTE_NWFILTER_NAME_LIST_MAX); goto done; } @@ -2370,7 +2541,7 @@ remoteListSecrets(virConnectPtr conn, char **const uuids, int maxuuids) if (maxuuids > REMOTE_SECRET_UUID_LIST_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined uuids: %d > %d"), + _("too many remote undefineds: %d > %d"), maxuuids, REMOTE_SECRET_UUID_LIST_MAX); goto done; } @@ -2430,7 +2601,7 @@ remoteListStoragePools(virConnectPtr conn, char **const names, int maxnames) if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined names: %d > %d"), + _("too many remote undefineds: %d > %d"), maxnames, REMOTE_STORAGE_POOL_NAME_LIST_MAX); goto done; } @@ -2905,7 +3076,7 @@ remoteNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames) if (maxnames > REMOTE_NODE_DEVICE_CAPS_LIST_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined names: %d > %d"), + _("too many remote undefineds: %d > %d"), maxnames, REMOTE_NODE_DEVICE_CAPS_LIST_MAX); goto done; } @@ -3081,7 +3252,7 @@ remoteNodeListDevices(virConnectPtr conn, const char *cap, char **const names, i if (maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined names: %d > %d"), + _("too many remote undefineds: %d > %d"), maxnames, REMOTE_NODE_DEVICE_NAME_LIST_MAX); goto done; } @@ -3387,7 +3558,32 @@ done: return rv; } -/* remoteDispatchNWFilterDefineXML has to be implemented manually */ +static virNWFilterPtr +remoteNWFilterDefineXML(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) +{ + virNWFilterPtr rv = NULL; + struct private_data *priv = conn->nwfilterPrivateData; + remote_nwfilter_define_xml_args args; + remote_nwfilter_define_xml_ret ret; + + remoteDriverLock(priv); + + args.xml = (char *)xml; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NWFILTER_DEFINE_XML, + (xdrproc_t)xdr_remote_nwfilter_define_xml_args, (char *)&args, + (xdrproc_t)xdr_remote_nwfilter_define_xml_ret, (char *)&ret) == -1) + goto done; + + rv = get_nonnull_nwfilter(conn, ret.nwfilter); + xdr_free((xdrproc_t)xdr_remote_nwfilter_define_xml_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static char * remoteNWFilterGetXMLDesc(virNWFilterPtr nwfilter, unsigned int flags) @@ -3607,7 +3803,38 @@ done: return rv; } -/* remoteDispatchSecretSetValue has to be implemented manually */ +static int +remoteSecretSetValue(virSecretPtr secret, const unsigned char *value, size_t valuelen, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = secret->conn->secretPrivateData; + remote_secret_set_value_args args; + + remoteDriverLock(priv); + + if (valuelen > REMOTE_SECRET_VALUE_MAX) { + remoteError(VIR_ERR_RPC, + _("%s length greater than maximum: %d > %d"), + "value", (int)valuelen, REMOTE_SECRET_VALUE_MAX); + goto done; + } + + make_nonnull_secret(&args.secret, secret); + args.value.value_val = (char *)value; + args.value.value_len = valuelen; + args.flags = flags; + + if (call(secret->conn, priv, 0, REMOTE_PROC_SECRET_SET_VALUE, + (xdrproc_t)xdr_remote_secret_set_value_args, (char *)&args, + (xdrproc_t)xdr_void, (char *)NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteSecretUndefine(virSecretPtr secret) @@ -3932,7 +4159,7 @@ remoteStoragePoolListVolumes(virStoragePoolPtr pool, char **const names, int max if (maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) { remoteError(VIR_ERR_RPC, - _("too many remote undefined names: %d > %d"), + _("too many remote undefineds: %d > %d"), maxnames, REMOTE_STORAGE_VOL_NAME_LIST_MAX); goto done; } diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 8a0fc0e..c89561c 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2213,42 +2213,6 @@ done: } static int -remoteDomainPinVcpu (virDomainPtr domain, - unsigned int vcpu, - unsigned char *cpumap, - int maplen) -{ - int rv = -1; - remote_domain_pin_vcpu_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - if (maplen > REMOTE_CPUMAP_MAX) { - remoteError(VIR_ERR_RPC, - _("map length greater than maximum: %d > %d"), - maplen, REMOTE_CPUMAP_MAX); - goto done; - } - - make_nonnull_domain (&args.dom, domain); - args.vcpu = vcpu; - args.cpumap.cpumap_len = maplen; - args.cpumap.cpumap_val = (char *) cpumap; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_PIN_VCPU, - (xdrproc_t) xdr_remote_domain_pin_vcpu_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteDomainGetVcpus (virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, @@ -2442,76 +2406,6 @@ done: } static int -remoteDomainMigratePerform (virDomainPtr domain, - const char *cookie, - int cookielen, - const char *uri, - unsigned long flags, - const char *dname, - unsigned long resource) -{ - int rv = -1; - remote_domain_migrate_perform_args args; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - make_nonnull_domain (&args.dom, domain); - args.cookie.cookie_len = cookielen; - args.cookie.cookie_val = (char *) cookie; - args.uri = (char *) uri; - args.flags = flags; - args.dname = dname == NULL ? NULL : (char **) &dname; - args.resource = resource; - - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PERFORM, - (xdrproc_t) xdr_remote_domain_migrate_perform_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock(priv); - return rv; -} - -static virDomainPtr -remoteDomainMigrateFinish (virConnectPtr dconn, - const char *dname, - const char *cookie, - int cookielen, - const char *uri, - unsigned long flags) -{ - virDomainPtr ddom = NULL; - remote_domain_migrate_finish_args args; - remote_domain_migrate_finish_ret ret; - struct private_data *priv = dconn->privateData; - - remoteDriverLock(priv); - - args.dname = (char *) dname; - args.cookie.cookie_len = cookielen; - args.cookie.cookie_val = (char *) cookie; - args.uri = (char *) uri; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH, - (xdrproc_t) xdr_remote_domain_migrate_finish_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_migrate_finish_ret, (char *) &ret) == -1) - goto done; - - ddom = get_nonnull_domain (dconn, ret.ddom); - xdr_free ((xdrproc_t) &xdr_remote_domain_migrate_finish_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return ddom; -} - -static int remoteDomainMigratePrepare2 (virConnectPtr dconn, char **cookie, int *cookielen, const char *uri_in, char **uri_out, @@ -2569,43 +2463,6 @@ error: goto done; } -static virDomainPtr -remoteDomainMigrateFinish2 (virConnectPtr dconn, - const char *dname, - const char *cookie, - int cookielen, - const char *uri, - unsigned long flags, - int retcode) -{ - virDomainPtr ddom = NULL; - remote_domain_migrate_finish2_args args; - remote_domain_migrate_finish2_ret ret; - struct private_data *priv = dconn->privateData; - - remoteDriverLock(priv); - - args.dname = (char *) dname; - args.cookie.cookie_len = cookielen; - args.cookie.cookie_val = (char *) cookie; - args.uri = (char *) uri; - args.flags = flags; - args.retcode = retcode; - - memset (&ret, 0, sizeof ret); - if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH2, - (xdrproc_t) xdr_remote_domain_migrate_finish2_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_migrate_finish2_ret, (char *) &ret) == -1) - goto done; - - ddom = get_nonnull_domain (dconn, ret.ddom); - xdr_free ((xdrproc_t) &xdr_remote_domain_migrate_finish2_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return ddom; -} - static int remoteDomainCreate (virDomainPtr domain) { @@ -3265,33 +3122,6 @@ remoteNWFilterClose(virConnectPtr conn) return remoteGenericClose(conn, &conn->nwfilterPrivateData); } -static virNWFilterPtr -remoteNWFilterDefineXML (virConnectPtr conn, const char *xmlDesc, - unsigned int flags ATTRIBUTE_UNUSED) -{ - virNWFilterPtr net = NULL; - remote_nwfilter_define_xml_args args; - remote_nwfilter_define_xml_ret ret; - struct private_data *priv = conn->nwfilterPrivateData; - - remoteDriverLock(priv); - - args.xml = (char *) xmlDesc; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NWFILTER_DEFINE_XML, - (xdrproc_t) xdr_remote_nwfilter_define_xml_args, (char *) &args, - (xdrproc_t) xdr_remote_nwfilter_define_xml_ret, (char *) &ret) == -1) - goto done; - - net = get_nonnull_nwfilter (conn, ret.nwfilter); - xdr_free ((xdrproc_t) &xdr_remote_nwfilter_define_xml_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return net; -} - /*----------------------------------------------------------------------*/ static int @@ -4298,33 +4128,6 @@ remoteSecretClose (virConnectPtr conn) return remoteGenericClose(conn, &conn->secretPrivateData); } -static int -remoteSecretSetValue (virSecretPtr secret, const unsigned char *value, - size_t value_size, unsigned int flags) -{ - int rv = -1; - remote_secret_set_value_args args; - struct private_data *priv = secret->conn->secretPrivateData; - - remoteDriverLock (priv); - - make_nonnull_secret (&args.secret, secret); - args.value.value_len = value_size; - args.value.value_val = (char *) value; - args.flags = flags; - - if (call (secret->conn, priv, 0, REMOTE_PROC_SECRET_SET_VALUE, - (xdrproc_t) xdr_remote_secret_set_value_args, (char *) &args, - (xdrproc_t) xdr_void, (char *) NULL) == -1) - goto done; - - rv = 0; - -done: - remoteDriverUnlock (priv); - return rv; -} - static unsigned char * remoteSecretGetValue (virSecretPtr secret, size_t *value_size, unsigned int flags) @@ -4901,36 +4704,6 @@ done: return rv; } -static char * -remoteCPUBaseline(virConnectPtr conn, - const char **xmlCPUs, - unsigned int ncpus, - unsigned int flags) -{ - struct private_data *priv = conn->privateData; - remote_cpu_baseline_args args; - remote_cpu_baseline_ret ret; - char *cpu = NULL; - - remoteDriverLock(priv); - - args.xmlCPUs.xmlCPUs_len = ncpus; - args.xmlCPUs.xmlCPUs_val = (char **) xmlCPUs; - args.flags = flags; - - memset(&ret, 0, sizeof (ret)); - if (call(conn, priv, 0, REMOTE_PROC_CPU_BASELINE, - (xdrproc_t) xdr_remote_cpu_baseline_args, (char *) &args, - (xdrproc_t) xdr_remote_cpu_baseline_ret, (char *) &ret) == -1) - goto done; - - cpu = ret.cpu; - -done: - remoteDriverUnlock(priv); - return cpu; -} - static int remoteDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID, -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:14:08 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:14:08 +0200 Subject: [libvirt] [PATCH 21/22] remote generator, client: Handle functions that return lists In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <1303636449-19113-22-git-send-email-matthias.bolte@googlemail.com> --- daemon/remote_generator.pl | 93 ++++- src/remote/remote_client_bodies.c | 786 ++++++++++++++++++++++++++++++++++++- src/remote/remote_driver.c | 758 ----------------------------------- 3 files changed, 851 insertions(+), 786 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 774188b..f5be8d6 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -755,29 +755,16 @@ elsif ($opt_k) { "NWFilterDefineXML", # public API and XDR protocol mismatch "DomainMigratePerform", "DomainMigrateFinish2", - "DomainSnapshotListNames", "FindStoragePoolSources", "IsSecure", - "ListDefinedDomains", - "ListDefinedInterfaces", - "ListNWFilters", "SupportsFeature", - "NodeListDevices", "NodeGetCellsFreeMemory", - "ListDefinedNetworks", - "StoragePoolListVolumes", "ListDomains", - "ListStoragePools", "SecretSetValue", "GetURI", - "ListInterfaces", - "ListDefinedStoragePools", "NodeDeviceDettach", - "ListNetworks", - "NodeDeviceListCaps", "NodeDeviceReset", "NodeDeviceReAttach", - "ListSecrets", "DomainBlockPeek", "DomainCreateWithFlags", @@ -925,8 +912,9 @@ elsif ($opt_k) { # fix priv_name for the NumOf* functions if ($priv_name eq "privateData" and - !($call->{ProcName} =~ m/Domains/) and - $call->{ProcName} =~ m/NumOf(Defined|Domain)*(\S+)s/) { + !($call->{ProcName} =~ m/(Domains|DomainSnapshot)/) and + ($call->{ProcName} =~ m/NumOf(Defined|Domain)*(\S+)s/ or + $call->{ProcName} =~ m/List(Defined|Domain)*(\S+)s/)) { my $prefix = lc $2; $prefix =~ s/(pool|vol)$//; $priv_name = "${prefix}PrivateData"; @@ -937,6 +925,11 @@ elsif ($opt_k) { my $call_ret = "&ret"; my $single_ret_var = "int rv = -1"; my $single_ret_type = "int"; + my $single_ret_as_list = 0; + my $single_ret_list_error_msg_type = "undefined"; + my $single_ret_list_name = "undefined"; + my $single_ret_list_max_var = "undefined"; + my $single_ret_list_max_define = "undefined"; my $multi_ret = 0; if ($call->{ret} ne "void" and @@ -961,6 +954,30 @@ elsif ($opt_k) { } else { die "unhandled type for multi-return-value: $ret_member"; } + } elsif ($ret_member =~ m/remote_nonnull_string (\S+)<(\S+)>;/) { + $single_ret_as_list = 1; + $single_ret_list_name = $1; + $single_ret_list_max_var = "max$1"; + $single_ret_list_max_define = $2; + + my $first_arg = shift(@args_list); + my $second_arg; + + if ($call->{ProcName} eq "NodeListDevices") { + $second_arg = shift(@args_list); + } + + unshift(@args_list, "char **const $1"); + + if (defined $second_arg) { + unshift(@args_list, $second_arg); + } + + unshift(@args_list, $first_arg); + + push(@ret_list, "rv = ret.$1.$1_len;"); + $single_ret_var = "int rv = -1"; + $single_ret_type = "int"; } elsif ($ret_member =~ m/remote_nonnull_string (\S+);/) { push(@ret_list, "rv = ret.$1;"); $single_ret_var = "char *rv = NULL"; @@ -1058,9 +1075,23 @@ elsif ($opt_k) { print " $var;\n"; } + if ($single_ret_as_list) { + print " int i;\n"; + } + print "\n"; print " remoteDriverLock(priv);\n"; + if ($single_ret_as_list) { + print "\n"; + print " if ($single_ret_list_max_var > $single_ret_list_max_define) {\n"; + print " remoteError(VIR_ERR_RPC,\n"; + print " _(\"too many remote ${single_ret_list_error_msg_type}s: %d > %d\"),\n"; + print " $single_ret_list_max_var, $single_ret_list_max_define);\n"; + print " goto done;\n"; + print " }\n"; + } + if (@setters_list) { print "\n"; print " "; @@ -1084,6 +1115,32 @@ elsif ($opt_k) { print " goto done;\n"; print "\n"; + if ($single_ret_as_list) { + print " if (ret.$single_ret_list_name.${single_ret_list_name}_len > $single_ret_list_max_var) {\n"; + print " remoteError(VIR_ERR_RPC,\n"; + print " _(\"too many remote ${single_ret_list_error_msg_type}s: %d > %d\"),\n"; + print " ret.$single_ret_list_name.${single_ret_list_name}_len, $single_ret_list_max_var);\n"; + print " goto cleanup;\n"; + print " }\n"; + print "\n"; + print " /* This call is caller-frees (although that isn't clear from\n"; + print " * the documentation). However xdr_free will free up both the\n"; + print " * names and the list of pointers, so we have to strdup the\n"; + print " * names here. */\n"; + print " for (i = 0; i < ret.$single_ret_list_name.${single_ret_list_name}_len; ++i) {\n"; + print " ${single_ret_list_name}[i] = strdup(ret.$single_ret_list_name.${single_ret_list_name}_val[i]);\n"; + print "\n"; + print " if (${single_ret_list_name}[i] == NULL) {\n"; + print " for (--i; i >= 0; --i)\n"; + print " VIR_FREE(${single_ret_list_name}[i]);\n"; + print "\n"; + print " virReportOOMError();\n"; + print " goto cleanup;\n"; + print " }\n"; + print " }\n"; + print "\n"; + } + if (@ret_list) { print " "; print join("\n ", @ret_list); @@ -1094,6 +1151,12 @@ elsif ($opt_k) { print " rv = 0;\n"; } + if ($single_ret_as_list) { + print "\n"; + print "cleanup:\n"; + print " xdr_free((xdrproc_t)xdr_remote_$call->{name}_ret, (char *)&ret);\n"; + } + print "\n"; print "done:\n"; print " remoteDriverUnlock(priv);\n"; diff --git a/src/remote/remote_client_bodies.c b/src/remote/remote_client_bodies.c index e61055b..4970c23 100644 --- a/src/remote/remote_client_bodies.c +++ b/src/remote/remote_client_bodies.c @@ -1330,7 +1330,67 @@ done: return rv; } -/* remoteDispatchDomainSnapshotListNames has to be implemented manually */ +static int +remoteDomainSnapshotListNames(virDomainPtr dom, char **const names, int maxnames, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = dom->conn->privateData; + remote_domain_snapshot_list_names_args args; + remote_domain_snapshot_list_names_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined names: %d > %d"), + maxnames, REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX); + goto done; + } + + make_nonnull_domain(&args.dom, dom); + args.maxnames = maxnames; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_NAMES, + (xdrproc_t)xdr_remote_domain_snapshot_list_names_args, (char *)&args, + (xdrproc_t)xdr_remote_domain_snapshot_list_names_ret, (char *)&ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.names.names_len; ++i) { + names[i] = strdup(ret.names.names_val[i]); + + if (names[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(names[i]); + + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.names.names_len; + +cleanup: + xdr_free((xdrproc_t)xdr_remote_domain_snapshot_list_names_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static virDomainSnapshotPtr remoteDomainSnapshotLookupByName(virDomainPtr dom, const char *name, unsigned int flags) @@ -1875,25 +1935,547 @@ done: /* remoteDispatchIsSecure has to be implemented manually */ -/* remoteDispatchListDefinedDomains has to be implemented manually */ +static int +remoteListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) +{ + int rv = -1; + struct private_data *priv = conn->privateData; + remote_list_defined_domains_args args; + remote_list_defined_domains_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined names: %d > %d"), + maxnames, REMOTE_DOMAIN_NAME_LIST_MAX); + goto done; + } + + args.maxnames = maxnames; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_LIST_DEFINED_DOMAINS, + (xdrproc_t)xdr_remote_list_defined_domains_args, (char *)&args, + (xdrproc_t)xdr_remote_list_defined_domains_ret, (char *)&ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } -/* remoteDispatchListDefinedInterfaces has to be implemented manually */ + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.names.names_len; ++i) { + names[i] = strdup(ret.names.names_val[i]); -/* remoteDispatchListDefinedNetworks has to be implemented manually */ + if (names[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(names[i]); -/* remoteDispatchListDefinedStoragePools has to be implemented manually */ + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.names.names_len; + +cleanup: + xdr_free((xdrproc_t)xdr_remote_list_defined_domains_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteListDefinedInterfaces(virConnectPtr conn, char **const names, int maxnames) +{ + int rv = -1; + struct private_data *priv = conn->interfacePrivateData; + remote_list_defined_interfaces_args args; + remote_list_defined_interfaces_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined names: %d > %d"), + maxnames, REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX); + goto done; + } + + args.maxnames = maxnames; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_LIST_DEFINED_INTERFACES, + (xdrproc_t)xdr_remote_list_defined_interfaces_args, (char *)&args, + (xdrproc_t)xdr_remote_list_defined_interfaces_ret, (char *)&ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.names.names_len; ++i) { + names[i] = strdup(ret.names.names_val[i]); + + if (names[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(names[i]); + + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.names.names_len; + +cleanup: + xdr_free((xdrproc_t)xdr_remote_list_defined_interfaces_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteListDefinedNetworks(virConnectPtr conn, char **const names, int maxnames) +{ + int rv = -1; + struct private_data *priv = conn->networkPrivateData; + remote_list_defined_networks_args args; + remote_list_defined_networks_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined names: %d > %d"), + maxnames, REMOTE_NETWORK_NAME_LIST_MAX); + goto done; + } + + args.maxnames = maxnames; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_LIST_DEFINED_NETWORKS, + (xdrproc_t)xdr_remote_list_defined_networks_args, (char *)&args, + (xdrproc_t)xdr_remote_list_defined_networks_ret, (char *)&ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.names.names_len; ++i) { + names[i] = strdup(ret.names.names_val[i]); + + if (names[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(names[i]); + + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.names.names_len; + +cleanup: + xdr_free((xdrproc_t)xdr_remote_list_defined_networks_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteListDefinedStoragePools(virConnectPtr conn, char **const names, int maxnames) +{ + int rv = -1; + struct private_data *priv = conn->storagePrivateData; + remote_list_defined_storage_pools_args args; + remote_list_defined_storage_pools_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined names: %d > %d"), + maxnames, REMOTE_STORAGE_POOL_NAME_LIST_MAX); + goto done; + } + + args.maxnames = maxnames; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_LIST_DEFINED_STORAGE_POOLS, + (xdrproc_t)xdr_remote_list_defined_storage_pools_args, (char *)&args, + (xdrproc_t)xdr_remote_list_defined_storage_pools_ret, (char *)&ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.names.names_len; ++i) { + names[i] = strdup(ret.names.names_val[i]); + + if (names[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(names[i]); + + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.names.names_len; + +cleanup: + xdr_free((xdrproc_t)xdr_remote_list_defined_storage_pools_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} /* remoteDispatchListDomains has to be implemented manually */ -/* remoteDispatchListInterfaces has to be implemented manually */ +static int +remoteListInterfaces(virConnectPtr conn, char **const names, int maxnames) +{ + int rv = -1; + struct private_data *priv = conn->interfacePrivateData; + remote_list_interfaces_args args; + remote_list_interfaces_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_INTERFACE_NAME_LIST_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined names: %d > %d"), + maxnames, REMOTE_INTERFACE_NAME_LIST_MAX); + goto done; + } + + args.maxnames = maxnames; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_LIST_INTERFACES, + (xdrproc_t)xdr_remote_list_interfaces_args, (char *)&args, + (xdrproc_t)xdr_remote_list_interfaces_ret, (char *)&ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.names.names_len; ++i) { + names[i] = strdup(ret.names.names_val[i]); + + if (names[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(names[i]); + + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.names.names_len; + +cleanup: + xdr_free((xdrproc_t)xdr_remote_list_interfaces_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteListNetworks(virConnectPtr conn, char **const names, int maxnames) +{ + int rv = -1; + struct private_data *priv = conn->networkPrivateData; + remote_list_networks_args args; + remote_list_networks_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined names: %d > %d"), + maxnames, REMOTE_NETWORK_NAME_LIST_MAX); + goto done; + } + + args.maxnames = maxnames; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_LIST_NETWORKS, + (xdrproc_t)xdr_remote_list_networks_args, (char *)&args, + (xdrproc_t)xdr_remote_list_networks_ret, (char *)&ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.names.names_len; ++i) { + names[i] = strdup(ret.names.names_val[i]); + + if (names[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(names[i]); + + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.names.names_len; + +cleanup: + xdr_free((xdrproc_t)xdr_remote_list_networks_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteListNWFilters(virConnectPtr conn, char **const names, int maxnames) +{ + int rv = -1; + struct private_data *priv = conn->nwfilterPrivateData; + remote_list_nwfilters_args args; + remote_list_nwfilters_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_NWFILTER_NAME_LIST_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined names: %d > %d"), + maxnames, REMOTE_NWFILTER_NAME_LIST_MAX); + goto done; + } + + args.maxnames = maxnames; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_LIST_NWFILTERS, + (xdrproc_t)xdr_remote_list_nwfilters_args, (char *)&args, + (xdrproc_t)xdr_remote_list_nwfilters_ret, (char *)&ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.names.names_len; ++i) { + names[i] = strdup(ret.names.names_val[i]); + + if (names[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(names[i]); + + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.names.names_len; + +cleanup: + xdr_free((xdrproc_t)xdr_remote_list_nwfilters_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteListSecrets(virConnectPtr conn, char **const uuids, int maxuuids) +{ + int rv = -1; + struct private_data *priv = conn->secretPrivateData; + remote_list_secrets_args args; + remote_list_secrets_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxuuids > REMOTE_SECRET_UUID_LIST_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined uuids: %d > %d"), + maxuuids, REMOTE_SECRET_UUID_LIST_MAX); + goto done; + } + + args.maxuuids = maxuuids; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_LIST_SECRETS, + (xdrproc_t)xdr_remote_list_secrets_args, (char *)&args, + (xdrproc_t)xdr_remote_list_secrets_ret, (char *)&ret) == -1) + goto done; + + if (ret.uuids.uuids_len > maxuuids) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.uuids.uuids_len, maxuuids); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.uuids.uuids_len; ++i) { + uuids[i] = strdup(ret.uuids.uuids_val[i]); -/* remoteDispatchListNetworks has to be implemented manually */ + if (uuids[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(uuids[i]); -/* remoteDispatchListNWFilters has to be implemented manually */ + virReportOOMError(); + goto cleanup; + } + } -/* remoteDispatchListSecrets has to be implemented manually */ + rv = ret.uuids.uuids_len; -/* remoteDispatchListStoragePools has to be implemented manually */ +cleanup: + xdr_free((xdrproc_t)xdr_remote_list_secrets_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteListStoragePools(virConnectPtr conn, char **const names, int maxnames) +{ + int rv = -1; + struct private_data *priv = conn->storagePrivateData; + remote_list_storage_pools_args args; + remote_list_storage_pools_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined names: %d > %d"), + maxnames, REMOTE_STORAGE_POOL_NAME_LIST_MAX); + goto done; + } + + args.maxnames = maxnames; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_LIST_STORAGE_POOLS, + (xdrproc_t)xdr_remote_list_storage_pools_args, (char *)&args, + (xdrproc_t)xdr_remote_list_storage_pools_ret, (char *)&ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.names.names_len; ++i) { + names[i] = strdup(ret.names.names_val[i]); + + if (names[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(names[i]); + + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.names.names_len; + +cleanup: + xdr_free((xdrproc_t)xdr_remote_list_storage_pools_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteNetworkCreate(virNetworkPtr net) @@ -2310,7 +2892,66 @@ done: /* remoteDispatchNodeDeviceGetParent has to be implemented manually */ -/* remoteDispatchNodeDeviceListCaps has to be implemented manually */ +static int +remoteNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames) +{ + int rv = -1; + struct private_data *priv = dev->conn->devMonPrivateData; + remote_node_device_list_caps_args args; + remote_node_device_list_caps_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_NODE_DEVICE_CAPS_LIST_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined names: %d > %d"), + maxnames, REMOTE_NODE_DEVICE_CAPS_LIST_MAX); + goto done; + } + + args.name = dev->name; + args.maxnames = maxnames; + + memset(&ret, 0, sizeof ret); + + if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LIST_CAPS, + (xdrproc_t)xdr_remote_node_device_list_caps_args, (char *)&args, + (xdrproc_t)xdr_remote_node_device_list_caps_ret, (char *)&ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.names.names_len; ++i) { + names[i] = strdup(ret.names.names_val[i]); + + if (names[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(names[i]); + + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.names.names_len; + +cleanup: + xdr_free((xdrproc_t)xdr_remote_node_device_list_caps_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static virNodeDevicePtr remoteNodeDeviceLookupByName(virConnectPtr conn, const char *name) @@ -2427,7 +3068,67 @@ done: /* remoteDispatchNodeGetSecurityModel has to be implemented manually */ -/* remoteDispatchNodeListDevices has to be implemented manually */ +static int +remoteNodeListDevices(virConnectPtr conn, const char *cap, char **const names, int maxnames, unsigned int flags) +{ + int rv = -1; + struct private_data *priv = conn->devMonPrivateData; + remote_node_list_devices_args args; + remote_node_list_devices_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined names: %d > %d"), + maxnames, REMOTE_NODE_DEVICE_NAME_LIST_MAX); + goto done; + } + + args.cap = cap ? (char **)&cap : NULL; + args.maxnames = maxnames; + args.flags = flags; + + memset(&ret, 0, sizeof ret); + + if (call(conn, priv, 0, REMOTE_PROC_NODE_LIST_DEVICES, + (xdrproc_t)xdr_remote_node_list_devices_args, (char *)&args, + (xdrproc_t)xdr_remote_node_list_devices_ret, (char *)&ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.names.names_len; ++i) { + names[i] = strdup(ret.names.names_val[i]); + + if (names[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(names[i]); + + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.names.names_len; + +cleanup: + xdr_free((xdrproc_t)xdr_remote_node_list_devices_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static int remoteNodeNumOfDevices(virConnectPtr conn, const char *cap, unsigned int flags) @@ -3218,7 +3919,66 @@ done: return rv; } -/* remoteDispatchStoragePoolListVolumes has to be implemented manually */ +static int +remoteStoragePoolListVolumes(virStoragePoolPtr pool, char **const names, int maxnames) +{ + int rv = -1; + struct private_data *priv = pool->conn->storagePrivateData; + remote_storage_pool_list_volumes_args args; + remote_storage_pool_list_volumes_ret ret; + int i; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) { + remoteError(VIR_ERR_RPC, + _("too many remote undefined names: %d > %d"), + maxnames, REMOTE_STORAGE_VOL_NAME_LIST_MAX); + goto done; + } + + make_nonnull_storage_pool(&args.pool, pool); + args.maxnames = maxnames; + + memset(&ret, 0, sizeof ret); + + if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES, + (xdrproc_t)xdr_remote_storage_pool_list_volumes_args, (char *)&args, + (xdrproc_t)xdr_remote_storage_pool_list_volumes_ret, (char *)&ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + remoteError(VIR_ERR_RPC, + _("too many remote undefineds: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. */ + for (i = 0; i < ret.names.names_len; ++i) { + names[i] = strdup(ret.names.names_val[i]); + + if (names[i] == NULL) { + for (--i; i >= 0; --i) + VIR_FREE(names[i]); + + virReportOOMError(); + goto cleanup; + } + } + + rv = ret.names.names_len; + +cleanup: + xdr_free((xdrproc_t)xdr_remote_storage_pool_list_volumes_ret, (char *)&ret); + +done: + remoteDriverUnlock(priv); + return rv; +} static virStoragePoolPtr remoteStoragePoolLookupByName(virConnectPtr conn, const char *name) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 777a7bf..8a0fc0e 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2607,65 +2607,6 @@ done: } static int -remoteListDefinedDomains (virConnectPtr conn, char **const names, int maxnames) -{ - int rv = -1; - int i; - remote_list_defined_domains_args args; - remote_list_defined_domains_ret ret; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - if (maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) { - remoteError(VIR_ERR_RPC, - _("too many remote domain names: %d > %d"), - maxnames, REMOTE_DOMAIN_NAME_LIST_MAX); - goto done; - } - args.maxnames = maxnames; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_LIST_DEFINED_DOMAINS, - (xdrproc_t) xdr_remote_list_defined_domains_args, (char *) &args, - (xdrproc_t) xdr_remote_list_defined_domains_ret, (char *) &ret) == -1) - goto done; - - if (ret.names.names_len > maxnames) { - remoteError(VIR_ERR_RPC, - _("too many remote domain names: %d > %d"), - ret.names.names_len, maxnames); - goto cleanup; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) { - names[i] = strdup (ret.names.names_val[i]); - - if (names[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(names[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.names.names_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_list_defined_domains_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteDomainCreate (virDomainPtr domain) { int rv = -1; @@ -3122,125 +3063,6 @@ remoteNetworkClose(virConnectPtr conn) return remoteGenericClose(conn, &conn->networkPrivateData); } -static int -remoteListNetworks (virConnectPtr conn, char **const names, int maxnames) -{ - int rv = -1; - int i; - remote_list_networks_args args; - remote_list_networks_ret ret; - struct private_data *priv = conn->networkPrivateData; - - remoteDriverLock(priv); - - if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { - remoteError(VIR_ERR_RPC, - _("too many remote networks: %d > %d"), - maxnames, REMOTE_NETWORK_NAME_LIST_MAX); - goto done; - } - args.maxnames = maxnames; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_LIST_NETWORKS, - (xdrproc_t) xdr_remote_list_networks_args, (char *) &args, - (xdrproc_t) xdr_remote_list_networks_ret, (char *) &ret) == -1) - goto done; - - if (ret.names.names_len > maxnames) { - remoteError(VIR_ERR_RPC, - _("too many remote networks: %d > %d"), - ret.names.names_len, maxnames); - goto cleanup; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) { - names[i] = strdup (ret.names.names_val[i]); - - if (names[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(names[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.names.names_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_list_networks_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteListDefinedNetworks (virConnectPtr conn, - char **const names, int maxnames) -{ - int rv = -1; - int i; - remote_list_defined_networks_args args; - remote_list_defined_networks_ret ret; - struct private_data *priv = conn->networkPrivateData; - - remoteDriverLock(priv); - - if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { - remoteError(VIR_ERR_RPC, - _("too many remote networks: %d > %d"), - maxnames, REMOTE_NETWORK_NAME_LIST_MAX); - goto done; - } - args.maxnames = maxnames; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_LIST_DEFINED_NETWORKS, - (xdrproc_t) xdr_remote_list_defined_networks_args, (char *) &args, - (xdrproc_t) xdr_remote_list_defined_networks_ret, (char *) &ret) == -1) - goto done; - - if (ret.names.names_len > maxnames) { - remoteError(VIR_ERR_RPC, - _("too many remote networks: %d > %d"), - ret.names.names_len, maxnames); - goto cleanup; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) { - names[i] = strdup (ret.names.names_val[i]); - - if (names[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(names[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.names.names_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_list_defined_networks_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -3255,124 +3077,6 @@ remoteInterfaceClose(virConnectPtr conn) return remoteGenericClose(conn, &conn->interfacePrivateData); } -static int -remoteListInterfaces (virConnectPtr conn, char **const names, int maxnames) -{ - int rv = -1; - int i; - remote_list_interfaces_args args; - remote_list_interfaces_ret ret; - struct private_data *priv = conn->interfacePrivateData; - - remoteDriverLock(priv); - - if (maxnames > REMOTE_INTERFACE_NAME_LIST_MAX) { - remoteError(VIR_ERR_RPC, - _("too many remote interfaces: %d > %d"), - maxnames, REMOTE_INTERFACE_NAME_LIST_MAX); - goto done; - } - args.maxnames = maxnames; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_LIST_INTERFACES, - (xdrproc_t) xdr_remote_list_interfaces_args, (char *) &args, - (xdrproc_t) xdr_remote_list_interfaces_ret, (char *) &ret) == -1) - goto done; - - if (ret.names.names_len > maxnames) { - remoteError(VIR_ERR_RPC, - _("too many remote interfaces: %d > %d"), - ret.names.names_len, maxnames); - goto cleanup; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) { - names[i] = strdup (ret.names.names_val[i]); - - if (names[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(names[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.names.names_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_list_interfaces_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteListDefinedInterfaces (virConnectPtr conn, char **const names, int maxnames) -{ - int rv = -1; - int i; - remote_list_defined_interfaces_args args; - remote_list_defined_interfaces_ret ret; - struct private_data *priv = conn->interfacePrivateData; - - remoteDriverLock(priv); - - if (maxnames > REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX) { - remoteError(VIR_ERR_RPC, - _("too many remote interfaces: %d > %d"), - maxnames, REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX); - goto done; - } - args.maxnames = maxnames; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_LIST_DEFINED_INTERFACES, - (xdrproc_t) xdr_remote_list_defined_interfaces_args, (char *) &args, - (xdrproc_t) xdr_remote_list_defined_interfaces_ret, (char *) &ret) == -1) - goto done; - - if (ret.names.names_len > maxnames) { - remoteError(VIR_ERR_RPC, - _("too many remote interfaces: %d > %d"), - ret.names.names_len, maxnames); - goto cleanup; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) { - names[i] = strdup (ret.names.names_val[i]); - - if (names[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(names[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.names.names_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_list_defined_interfaces_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -3387,117 +3091,6 @@ remoteStorageClose(virConnectPtr conn) return remoteGenericClose(conn, &conn->storagePrivateData); } -static int -remoteListStoragePools (virConnectPtr conn, char **const names, int maxnames) -{ - int rv = -1; - int i; - remote_list_storage_pools_args args; - remote_list_storage_pools_ret ret; - struct private_data *priv = conn->storagePrivateData; - - remoteDriverLock(priv); - - if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { - remoteError(VIR_ERR_RPC, "%s", _("too many storage pools requested")); - goto done; - } - args.maxnames = maxnames; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_LIST_STORAGE_POOLS, - (xdrproc_t) xdr_remote_list_storage_pools_args, (char *) &args, - (xdrproc_t) xdr_remote_list_storage_pools_ret, (char *) &ret) == -1) - goto done; - - if (ret.names.names_len > maxnames) { - remoteError(VIR_ERR_RPC, "%s", _("too many storage pools received")); - goto cleanup; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) { - names[i] = strdup (ret.names.names_val[i]); - - if (names[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(names[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.names.names_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_list_storage_pools_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int -remoteListDefinedStoragePools (virConnectPtr conn, - char **const names, int maxnames) -{ - int rv = -1; - int i; - remote_list_defined_storage_pools_args args; - remote_list_defined_storage_pools_ret ret; - struct private_data *priv = conn->storagePrivateData; - - remoteDriverLock(priv); - - if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { - remoteError(VIR_ERR_RPC, "%s", _("too many storage pools requested")); - goto done; - } - args.maxnames = maxnames; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_LIST_DEFINED_STORAGE_POOLS, - (xdrproc_t) xdr_remote_list_defined_storage_pools_args, (char *) &args, - (xdrproc_t) xdr_remote_list_defined_storage_pools_ret, (char *) &ret) == -1) - goto done; - - if (ret.names.names_len > maxnames) { - remoteError(VIR_ERR_RPC, "%s", _("too many storage pools received")); - goto cleanup; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) { - names[i] = strdup (ret.names.names_val[i]); - - if (names[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(names[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.names.names_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_list_defined_storage_pools_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - static char * remoteFindStoragePoolSources (virConnectPtr conn, const char *type, @@ -3543,62 +3136,6 @@ done: return rv; } -static int -remoteStoragePoolListVolumes (virStoragePoolPtr pool, char **const names, int maxnames) -{ - int rv = -1; - int i; - remote_storage_pool_list_volumes_args args; - remote_storage_pool_list_volumes_ret ret; - struct private_data *priv = pool->conn->storagePrivateData; - - remoteDriverLock(priv); - - if (maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) { - remoteError(VIR_ERR_RPC, "%s", _("too many storage volumes requested")); - goto done; - } - args.maxnames = maxnames; - make_nonnull_storage_pool(&args.pool, pool); - - memset (&ret, 0, sizeof ret); - if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES, - (xdrproc_t) xdr_remote_storage_pool_list_volumes_args, (char *) &args, - (xdrproc_t) xdr_remote_storage_pool_list_volumes_ret, (char *) &ret) == -1) - goto done; - - if (ret.names.names_len > maxnames) { - remoteError(VIR_ERR_RPC, "%s", _("too many storage volumes received")); - goto cleanup; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) { - names[i] = strdup (ret.names.names_val[i]); - - if (names[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(names[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.names.names_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_storage_pool_list_volumes_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - /*----------------------------------------------------------------------*/ static virDrvOpenStatus ATTRIBUTE_NONNULL (1) @@ -3613,66 +3150,6 @@ remoteDevMonClose(virConnectPtr conn) return remoteGenericClose(conn, &conn->devMonPrivateData); } -static int remoteNodeListDevices(virConnectPtr conn, - const char *cap, - char **const names, - int maxnames, - unsigned int flags) -{ - int rv = -1; - int i; - remote_node_list_devices_args args; - remote_node_list_devices_ret ret; - struct private_data *priv = conn->devMonPrivateData; - - remoteDriverLock(priv); - - if (maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) { - remoteError(VIR_ERR_RPC, "%s", _("too many device names requested")); - goto done; - } - args.cap = cap ? (char **)&cap : NULL; - args.maxnames = maxnames; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_NODE_LIST_DEVICES, - (xdrproc_t) xdr_remote_node_list_devices_args, (char *) &args, - (xdrproc_t) xdr_remote_node_list_devices_ret, (char *) &ret) == -1) - goto done; - - if (ret.names.names_len > maxnames) { - remoteError(VIR_ERR_RPC, "%s", _("too many device names received")); - goto cleanup; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) { - names[i] = strdup (ret.names.names_val[i]); - - if (names[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(names[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.names.names_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_node_list_devices_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - static char *remoteNodeDeviceGetParent(virNodeDevicePtr dev) { char *rv = NULL; @@ -3699,63 +3176,6 @@ done: return rv; } -static int remoteNodeDeviceListCaps(virNodeDevicePtr dev, - char **const names, - int maxnames) -{ - int rv = -1; - int i; - remote_node_device_list_caps_args args; - remote_node_device_list_caps_ret ret; - struct private_data *priv = dev->conn->devMonPrivateData; - - remoteDriverLock(priv); - - if (maxnames > REMOTE_NODE_DEVICE_CAPS_LIST_MAX) { - remoteError(VIR_ERR_RPC, "%s", _("too many capability names requested")); - goto done; - } - args.maxnames = maxnames; - args.name = dev->name; - - memset (&ret, 0, sizeof ret); - if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LIST_CAPS, - (xdrproc_t) xdr_remote_node_device_list_caps_args, (char *) &args, - (xdrproc_t) xdr_remote_node_device_list_caps_ret, (char *) &ret) == -1) - goto done; - - if (ret.names.names_len > maxnames) { - remoteError(VIR_ERR_RPC, "%s", _("too many capability names received")); - goto cleanup; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) { - names[i] = strdup (ret.names.names_val[i]); - - if (names[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(names[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.names.names_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_node_device_list_caps_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteNodeDeviceDettach (virNodeDevicePtr dev) { @@ -3872,65 +3292,6 @@ done: return net; } -static int -remoteListNWFilters (virConnectPtr conn, char **const names, int maxnames) -{ - int rv = -1; - int i; - remote_list_nwfilters_args args; - remote_list_nwfilters_ret ret; - struct private_data *priv = conn->nwfilterPrivateData; - - remoteDriverLock(priv); - - if (maxnames > REMOTE_NWFILTER_NAME_LIST_MAX) { - remoteError(VIR_ERR_RPC, - _("too many remote nwfilters: %d > %d"), - maxnames, REMOTE_NWFILTER_NAME_LIST_MAX); - goto done; - } - args.maxnames = maxnames; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_LIST_NWFILTERS, - (xdrproc_t) xdr_remote_list_nwfilters_args, (char *) &args, - (xdrproc_t) xdr_remote_list_nwfilters_ret, (char *) &ret) == -1) - goto done; - - if (ret.names.names_len > maxnames) { - remoteError(VIR_ERR_RPC, - _("too many remote nwfilters: %d > %d"), - ret.names.names_len, maxnames); - goto cleanup; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) { - names[i] = strdup (ret.names.names_val[i]); - - if (names[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(names[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.names.names_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_list_nwfilters_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - /*----------------------------------------------------------------------*/ static int @@ -4938,62 +4299,6 @@ remoteSecretClose (virConnectPtr conn) } static int -remoteListSecrets (virConnectPtr conn, char **uuids, int maxuuids) -{ - int rv = -1; - int i; - remote_list_secrets_args args; - remote_list_secrets_ret ret; - struct private_data *priv = conn->secretPrivateData; - - remoteDriverLock(priv); - - if (maxuuids > REMOTE_SECRET_UUID_LIST_MAX) { - remoteError(VIR_ERR_RPC, _("too many remote secret UUIDs: %d > %d"), - maxuuids, REMOTE_SECRET_UUID_LIST_MAX); - goto done; - } - args.maxuuids = maxuuids; - - memset (&ret, 0, sizeof ret); - if (call (conn, priv, 0, REMOTE_PROC_LIST_SECRETS, - (xdrproc_t) xdr_remote_list_secrets_args, (char *) &args, - (xdrproc_t) xdr_remote_list_secrets_ret, (char *) &ret) == -1) - goto done; - - if (ret.uuids.uuids_len > maxuuids) { - remoteError(VIR_ERR_RPC, _("too many remote secret UUIDs: %d > %d"), - ret.uuids.uuids_len, maxuuids); - goto cleanup; - } - - /* This call is caller-frees. However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.uuids.uuids_len; ++i) { - uuids[i] = strdup (ret.uuids.uuids_val[i]); - - if (uuids[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(uuids[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.uuids.uuids_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_list_secrets_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - -static int remoteSecretSetValue (virSecretPtr secret, const unsigned char *value, size_t value_size, unsigned int flags) { @@ -5626,69 +4931,6 @@ done: return cpu; } -static int -remoteDomainSnapshotListNames (virDomainPtr domain, char **const names, - int maxnames, unsigned int flags) -{ - int rv = -1; - int i; - remote_domain_snapshot_list_names_args args; - remote_domain_snapshot_list_names_ret ret; - struct private_data *priv = domain->conn->privateData; - - remoteDriverLock(priv); - - if (maxnames > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) { - remoteError(VIR_ERR_RPC, - _("too many remote domain snapshot names: %d > %d"), - maxnames, REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX); - goto done; - } - - make_nonnull_domain(&args.dom, domain); - args.maxnames = maxnames; - args.flags = flags; - - memset (&ret, 0, sizeof ret); - if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_NAMES, - (xdrproc_t) xdr_remote_domain_snapshot_list_names_args, (char *) &args, - (xdrproc_t) xdr_remote_domain_snapshot_list_names_ret, (char *) &ret) == -1) - goto done; - - if (ret.names.names_len > maxnames) { - remoteError(VIR_ERR_RPC, - _("too many remote domain snapshots: %d > %d"), - ret.names.names_len, maxnames); - goto cleanup; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) { - names[i] = strdup (ret.names.names_val[i]); - - if (names[i] == NULL) { - for (--i; i >= 0; --i) - VIR_FREE(names[i]); - - virReportOOMError(); - goto cleanup; - } - } - - rv = ret.names.names_len; - -cleanup: - xdr_free ((xdrproc_t) xdr_remote_domain_snapshot_list_names_ret, (char *) &ret); - -done: - remoteDriverUnlock(priv); - return rv; -} - static int remoteDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID, -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 09:28:52 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:28:52 +0200 Subject: [libvirt] [PATCH] esx: Move CURL handling code to it's own type In-Reply-To: <4DB1C01B.3010209@redhat.com> References: <20110410133929.GA28461@sbox> <4DB1C01B.3010209@redhat.com> Message-ID: 2011/4/22 Eric Blake : > On 04/10/2011 07:39 AM, Matthias Bolte wrote: >> --- >> ?src/esx/esx_driver.c | ? ?4 +- >> ?src/esx/esx_vi.c ? ? | ?348 ++++++++++++++++++++++++++------------------------ >> ?src/esx/esx_vi.h ? ? | ? 29 +++- >> ?3 files changed, 205 insertions(+), 176 deletions(-) >> >> +++ b/src/esx/esx_vi.h >> @@ -82,6 +82,7 @@ typedef enum _esxVI_APIVersion esxVI_APIVersion; >> ?typedef enum _esxVI_ProductVersion esxVI_ProductVersion; >> ?typedef enum _esxVI_Occurrence esxVI_Occurrence; >> ?typedef struct _esxVI_ParsedHostCpuIdInfo esxVI_ParsedHostCpuIdInfo; >> +typedef struct _esxVI_CURL esxVI_CURL; >> ?typedef struct _esxVI_Context esxVI_Context; >> ?typedef struct _esxVI_Response esxVI_Response; >> ?typedef struct _esxVI_Enumeration esxVI_Enumeration; >> @@ -142,16 +143,32 @@ struct _esxVI_ParsedHostCpuIdInfo { >> >> >> ?/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * >> + * CURL >> + */ >> + >> +struct _esxVI_CURL { >> + ? ?CURL *handle; >> + ? ?virMutex lock; >> + ? ?struct curl_slist *headers; >> + ? ?char error[CURL_ERROR_SIZE]; >> +}; >> + >> +int esxVI_CURL_Alloc(esxVI_CURL **curl); >> +void esxVI_CURL_Free(esxVI_CURL **curl); >> +int esxVI_CURL_Connect(esxVI_CURL *curl, esxUtil_ParsedUri *parsedUri); >> +int esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content); >> +int esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content); > > A new type... > >> + >> + >> + >> +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * >> ? * Context >> ? */ >> >> ?struct _esxVI_Context { >> + ? ?esxVI_CURL *curl; >> ? ? ?char *url; >> ? ? ?char *ipAddress; >> - ? ?CURL *curl_handle; >> - ? ?struct curl_slist *curl_headers; >> - ? ?char curl_error[CURL_ERROR_SIZE]; >> - ? ?virMutex curl_lock; >> ? ? ?char *username; > > extracted from several fields of a larger type, and the rest of the > patch looks like mechanical fallout to the different naming to get to > the same fields. > > Looks like a reasonable refactoring, and nothing really caught my eye as > suspicious. > > ACK. > Thanks, pushed. Matthias From matthias.bolte at googlemail.com Sun Apr 24 09:48:00 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 11:48:00 +0200 Subject: [libvirt] [PATCH] Move call to virReportOOMError into virFileBuildPath Message-ID: <20110424094800.GA6638@sbox> Suggested by Daniel P. Berrange --- src/conf/nwfilter_conf.c | 5 +---- src/conf/storage_conf.c | 7 +------ src/util/util.c | 2 ++ src/xen/xen_inotify.c | 1 - src/xen/xm_internal.c | 5 +---- 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 327fab3..09dc32b 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -2588,10 +2588,8 @@ virNWFilterLoadAllConfigs(virConnectPtr conn, if (!virFileHasSuffix(entry->d_name, ".xml")) continue; - if (!(path = virFileBuildPath(configDir, entry->d_name, NULL))) { - virReportOOMError(); + if (!(path = virFileBuildPath(configDir, entry->d_name, NULL))) continue; - } nwfilter = virNWFilterObjLoad(conn, nwfilters, entry->d_name, path); if (nwfilter) @@ -2627,7 +2625,6 @@ virNWFilterObjSaveDef(virNWFilterDriverStatePtr driver, if (!(nwfilter->configFile = virFileBuildPath(driver->configDir, def->name, ".xml"))) { - virReportOOMError(); return -1; } } diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 5a069f5..116898d 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -1483,14 +1483,11 @@ virStoragePoolLoadAllConfigs(virStoragePoolObjListPtr pools, if (!virFileHasSuffix(entry->d_name, ".xml")) continue; - if (!(path = virFileBuildPath(configDir, entry->d_name, NULL))) { - virReportOOMError(); + if (!(path = virFileBuildPath(configDir, entry->d_name, NULL))) continue; - } if (!(autostartLink = virFileBuildPath(autostartDir, entry->d_name, NULL))) { - virReportOOMError(); VIR_FREE(path); continue; } @@ -1529,13 +1526,11 @@ virStoragePoolObjSaveDef(virStorageDriverStatePtr driver, if (!(pool->configFile = virFileBuildPath(driver->configDir, def->name, ".xml"))) { - virReportOOMError(); return -1; } if (!(pool->autostartLink = virFileBuildPath(driver->autostartDir, def->name, ".xml"))) { - virReportOOMError(); VIR_FREE(pool->configFile); return -1; } diff --git a/src/util/util.c b/src/util/util.c index d4d2610..3948b01 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -1851,10 +1851,12 @@ virFileBuildPath(const char *dir, const char *name, const char *ext) if (ext == NULL) { if (virAsprintf(&path, "%s/%s", dir, name) < 0) { + virReportOOMError(); return NULL; } } else { if (virAsprintf(&path, "%s/%s%s", dir, name, ext) < 0) { + virReportOOMError(); return NULL; } } diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c index d809c45..9dde72c 100644 --- a/src/xen/xen_inotify.c +++ b/src/xen/xen_inotify.c @@ -415,7 +415,6 @@ xenInotifyOpen(virConnectPtr conn, /* Build the full file path */ if (!(path = virFileBuildPath(priv->configDir, ent->d_name, NULL))) { - virReportOOMError(); closedir(dh); return -1; } diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index db47a02..f9f52b5 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -388,7 +388,6 @@ int xenXMConfigCacheRefresh (virConnectPtr conn) { /* Build the full file path */ if (!(path = virFileBuildPath(priv->configDir, ent->d_name, NULL))) { - virReportOOMError(); closedir(dh); return -1; } @@ -1134,10 +1133,8 @@ virDomainPtr xenXMDomainDefineXML(virConnectPtr conn, const char *xml) entry = NULL; } - if (!(filename = virFileBuildPath(priv->configDir, def->name, NULL))) { - virReportOOMError(); + if (!(filename = virFileBuildPath(priv->configDir, def->name, NULL))) goto error; - } if (xenXMConfigSaveFile(conn, filename, def) < 0) goto error; -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 10:14:29 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 12:14:29 +0200 Subject: [libvirt] [PATCHv2] threads: add one-time initialization support In-Reply-To: <1303529908-32330-1-git-send-email-eblake@redhat.com> References: <1303339419-13159-1-git-send-email-eblake@redhat.com> <1303529908-32330-1-git-send-email-eblake@redhat.com> Message-ID: 2011/4/23 Eric Blake : > mingw lacks the counterpart to PTHREAD_MUTEX_INITIALIZER, so the > best we can do is portably expose once-only runtime initialization. > > * src/util/threads.h (virOnceControlPtr): New opaque type. > (virOnceFunc): New callback type. > (virOnce): New prototype. > * src/util/threads-pthread.h (virOnceControl): Declare. > (VIR_ONCE_CONTROL_INITIALIZER): Define. > * src/util/threads-win32.h (virOnceControl) > (VIR_ONCE_CONTROL_INITIALIZER): Likewise. > * src/util/threads-pthread.c (virOnce): Implement in pthreads. > * src/util/threads-win32.c (virOnce): Implement in WIN32. > * src/libvirt_private.syms: Export it. > --- > > v2: change WIN32 implementation to use lower-level primitives available > to mingw and older windows, rather than higher level but newer INIT_ONCE. > > Meanwhile, I noticed that gnulib has an LGPLv2+ 'lock' module that > provides a lot of multi-threading primitives for both pthreads, pth, > and mingw; maybe we should think about rewriting threads.c in terms > of gnulib and only have one implementation, rather than maintaining > pthread and mingw in parallel? > +int virOnce(virOnceControlPtr once, virOnceFunc func) > +{ > + ? ?if (!once->complete) { > + ? ? ? ?if (InterlockedIncrement(&once->init) == 1) { > + ? ? ? ? ? ?/* We're the first thread. */ > + ? ? ? ? ? ?func(); > + ? ? ? ? ? ?once->complete = 1; > + ? ? ? ?} else { > + ? ? ? ? ? ?/* We're a later thread. ?Decrement the init counter back > + ? ? ? ? ? ? * to avoid overflow, then yield until the first thread > + ? ? ? ? ? ? * marks that the function is complete. ?It is rare that > + ? ? ? ? ? ? * multiple threads will be waiting here, and since each > + ? ? ? ? ? ? * thread is yielding except the first, we should get out > + ? ? ? ? ? ? * soon enough. ?*/ > + ? ? ? ? ? ?InterlockedDecrement(&once->init); > + ? ? ? ? ? ?while (!once->complete) > + ? ? ? ? ? ? ? ?Sleep(0); > + ? ? ? ?} > + ? ?} > + ? ?return 0; > +} Compared to the gnulib lock module version, this one is less complex and I don't get why gnulib uses 3 states for the init and complete variables and an additional lock object. The only reason could be to minimize the time busy waiting in the while loop. > + > +struct virOnceControl { > + ? ?long init; /* 0 at startup, > 0 if init has started */ > + ? ?volatile long complete; /* 0 until first thread completes callback */ > +}; MSDN docs about InterlockedIncrement suggest that init should be volatile too. ACK, with init marked volatile. Matthias From matthias.bolte at googlemail.com Sun Apr 24 10:17:28 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sun, 24 Apr 2011 12:17:28 +0200 Subject: [libvirt] [PATCH] util: warn when passing a non-pointer to VIR_FREE In-Reply-To: <4DB210F9.5040503@redhat.com> References: <20110422170413.GC3219@teriyaki.redhat.com> <1303496484-17313-1-git-send-email-cfergeau@redhat.com> <4DB210F9.5040503@redhat.com> Message-ID: 2011/4/23 Eric Blake : > On 04/22/2011 12:21 PM, Christophe Fergeau wrote: >> There were recently some bugs where VIR_FREE was called with an >> int parameter. Try to affect the value passed to VIR_FREE to >> a const void* so that the compiler gets a chance to emit a warning >> if we didn't pass a pointer to VIR_FREE. >> --- >> ?src/util/memory.h | ? ?6 +++++- >> ?1 files changed, 5 insertions(+), 1 deletions(-) >> >> diff --git a/src/util/memory.h b/src/util/memory.h >> index 66b4c42..fab425d 100644 >> --- a/src/util/memory.h >> +++ b/src/util/memory.h >> @@ -197,7 +197,11 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); >> ? * Free the memory stored in 'ptr' and update to point >> ? * to NULL. >> ? */ >> -# define VIR_FREE(ptr) virFree(&(ptr)) >> +# define VIR_FREE(ptr) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \ >> + ? ?do { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \ >> + ? ? ? ?ATTRIBUTE_UNUSED const void *check_type = (ptr); \ >> + ? ? ? ?virFree(&(ptr)); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \ >> + ? ?} while (0) > > That evaluates ptr twice. ?We can do better, by exploiting that the > ternary operator can be used to determine the type of an expression > without evaluating it. ?Gcc allows 1?(void*)expr:pointer (the resulting > type is void*), but hates 1?(void*)expr:int (promoting to int provokes a > warning): > > cc1: warnings being treated as errors > remote.c: In function 'remoteDispatchListNetworks': > remote.c:3684:70: error: pointer/integer type mismatch in conditional > expression > > So how about: > > diff --git i/src/util/memory.h w/src/util/memory.h > index 66b4c42..d77a295 100644 > --- i/src/util/memory.h > +++ w/src/util/memory.h > @@ -1,7 +1,7 @@ > ?/* > ?* memory.c: safer memory allocation > ?* > - * Copyright (C) 2010 Red Hat, Inc. > + * Copyright (C) 2010-2011 Red Hat, Inc. > ?* Copyright (C) 2008 Daniel P. Berrange > ?* > ?* This library is free software; you can redistribute it and/or > @@ -197,7 +197,11 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); > ?* Free the memory stored in 'ptr' and update to point > ?* to NULL. > ?*/ > -# define VIR_FREE(ptr) virFree(&(ptr)) > +/* The ternary ensures that ptr is a pointer and not an integer type, > + * while evaluating ptr only once. ?For now, we intentionally cast > + * away const, since a number of callers safely pass const char *. > + */ > +# define VIR_FREE(ptr) virFree((void *) (1 ? (const void *) &(ptr) : > (ptr))) > > > ?# if TEST_OOM > ACK, to your improved version. Matthias From matthias.bolte at googlemail.com Sun Apr 24 22:26:23 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 25 Apr 2011 00:26:23 +0200 Subject: [libvirt] [PATCH] Fix small memory leaks in config parsing related functions Message-ID: <20110424222623.GA16901@sbox> Found by 'make -C tests valgrind'. xen_xm.c: Dummy allocation via virDomainChrDefNew is directly overwritten and lost. Free 'script' in success path too. vmx.c: Free virtualDev_string in success path too. domain_conf.c: Free compression in success path too. --- src/conf/domain_conf.c | 1 + src/vmx/vmx.c | 16 +++++++++------- src/xenxs/xen_xm.c | 3 +-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 381e692..0e7aeb5 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4058,6 +4058,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { VIR_FREE(compression); goto error; } + VIR_FREE(compression); def->data.spice.zlib = compressionVal; } else if (xmlStrEqual(cur->name, BAD_CAST "playback")) { diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c index daeedc3..aee2d80 100644 --- a/src/vmx/vmx.c +++ b/src/vmx/vmx.c @@ -1818,6 +1818,7 @@ int virVMXParseSCSIController(virConfPtr conf, int controller, bool *present, int *virtualDev) { + int result = -1; char present_name[32]; char virtualDev_name[32]; char *virtualDev_string = NULL; @@ -1840,16 +1841,17 @@ virVMXParseSCSIController(virConfPtr conf, int controller, bool *present, controller); if (virVMXGetConfigBoolean(conf, present_name, present, false, true) < 0) { - goto failure; + goto cleanup; } if (! *present) { - return 0; + result = 0; + goto cleanup; } if (virVMXGetConfigString(conf, virtualDev_name, &virtualDev_string, true) < 0) { - goto failure; + goto cleanup; } if (virtualDev_string != NULL) { @@ -1870,16 +1872,16 @@ virVMXParseSCSIController(virConfPtr conf, int controller, bool *present, _("Expecting VMX entry '%s' to be 'buslogic' or 'lsilogic' " "or 'lsisas1068' or 'pvscsi' but found '%s'"), virtualDev_name, virtualDev_string); - goto failure; + goto cleanup; } } - return 0; + result = 0; - failure: + cleanup: VIR_FREE(virtualDev_string); - return -1; + return result; } diff --git a/src/xenxs/xen_xm.c b/src/xenxs/xen_xm.c index dbcaf15..63ba153 100644 --- a/src/xenxs/xen_xm.c +++ b/src/xenxs/xen_xm.c @@ -983,8 +983,6 @@ xenParseXM(virConfPtr conf, int xendConfigVersion, continue; } - if (!(chr = virDomainChrDefNew())) - goto cleanup; if (!(chr = xenParseSxprChar(port, NULL))) goto cleanup; @@ -1034,6 +1032,7 @@ xenParseXM(virConfPtr conf, int xendConfigVersion, goto cleanup; } + VIR_FREE(script); return def; no_memory: -- 1.7.0.4 From matthias.bolte at googlemail.com Sun Apr 24 22:26:52 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 25 Apr 2011 00:26:52 +0200 Subject: [libvirt] [PATCH] tests: Lower stack usage below 4096 bytes Message-ID: <20110424222652.GA16936@sbox> Make virtTestLoadFile allocate the buffer to read the file into. Fix logic error in virtTestLoadFile, stop reading on the an empty line. Use virFileReadLimFD in virtTestCaptureProgramOutput. --- m4/virt-compile-warnings.m4 | 10 ++--- tests/commandhelper.c | 5 +- tests/commandtest.c | 14 ++---- tests/conftest.c | 29 +++++++++---- tests/cputest.c | 66 ++++++++++++++++++------------- tests/esxutilstest.c | 2 + tests/interfacexml2xmltest.c | 33 ++++++++++------ tests/networkxml2xmltest.c | 51 ++++++++++++++--------- tests/nodedevxml2xmltest.c | 34 ++++++++++------ tests/nodeinfotest.c | 67 ++++++++++++++++++++----------- tests/nwfilterxml2xmltest.c | 54 +++++++++++++++---------- tests/qemuargv2xmltest.c | 43 ++++++++++++-------- tests/qemuhelptest.c | 13 +++--- tests/qemuxml2argvtest.c | 56 ++++++++++++++++---------- tests/qemuxml2xmltest.c | 43 +++++++++++--------- tests/sexpr2xmltest.c | 51 ++++++++++++++--------- tests/storagepoolxml2xmltest.c | 51 ++++++++++++++--------- tests/storagevolxml2xmltest.c | 65 ++++++++++++++++++------------- tests/testutils.c | 69 ++++++++++++++------------------ tests/testutils.h | 8 +--- tests/virshtest.c | 65 +++++++++++++----------------- tests/vmx2xmltest.c | 45 ++++++++++++--------- tests/xencapstest.c | 38 ++++++++--------- tests/xmconfigtest.c | 85 +++++++++++++++++++++++---------------- tests/xml2sexprtest.c | 53 +++++++++++++++---------- tests/xml2vmxtest.c | 45 ++++++++++++--------- 26 files changed, 624 insertions(+), 471 deletions(-) diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4 index 295fd9b..305036f 100644 --- a/m4/virt-compile-warnings.m4 +++ b/m4/virt-compile-warnings.m4 @@ -88,12 +88,10 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ # that one off, so we need to manually enable this again gl_WARN_ADD([-Wjump-misses-init]) - # This should be < 256 really, but with PATH_MAX everywhere - # we have doom, even with 4096. In fact we have some functions - # with several PATH_MAX sized variables :-( We should kill off - # all PATH_MAX usage and then lower this limit - gl_WARN_ADD([-Wframe-larger-than=65700]) - dnl gl_WARN_ADD([-Wframe-larger-than=4096]) + # This should be < 256 really. Currently we're down to 4096, + # but using 1024 bytes sized buffers (mostly for virStrerror) + # stops us from going down further + gl_WARN_ADD([-Wframe-larger-than=4096]) dnl gl_WARN_ADD([-Wframe-larger-than=256]) # Extra special flags diff --git a/tests/commandhelper.c b/tests/commandhelper.c index 46c00f4..99ba22e 100644 --- a/tests/commandhelper.c +++ b/tests/commandhelper.c @@ -99,8 +99,8 @@ int main(int argc, char **argv) { } fprintf(log, "DAEMON:%s\n", getpgrp() == getsid(0) ? "yes" : "no"); - char cwd[1024]; - if (!getcwd(cwd, sizeof(cwd))) + char *cwd = NULL; + if (!(cwd = getcwd(NULL, 0))) return EXIT_FAILURE; if (strlen(cwd) > strlen("/commanddata") && STREQ(cwd + strlen(cwd) - strlen("/commanddata"), "/commanddata")) @@ -137,5 +137,6 @@ int main(int argc, char **argv) { return EXIT_SUCCESS; error: + free(cwd); return EXIT_FAILURE; } diff --git a/tests/commandtest.c b/tests/commandtest.c index c313a2c..a728d10 100644 --- a/tests/commandtest.c +++ b/tests/commandtest.c @@ -47,21 +47,18 @@ mymain(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) #else static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; static int checkoutput(const char *testname) { int ret = -1; - char cwd[1024]; char *expectname = NULL; char *expectlog = NULL; char *actualname = NULL; char *actuallog = NULL; - if (!getcwd(cwd, sizeof(cwd))) - return -1; - if (virAsprintf(&expectname, "%s/commanddata/%s.log", abs_srcdir, testname) < 0) goto cleanup; @@ -545,12 +542,12 @@ cleanup: static int test15(const void *unused ATTRIBUTE_UNUSED) { virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper"); - char *cwd = NULL; + char *wd = NULL; int ret = -1; - if (virAsprintf(&cwd, "%s/commanddata", abs_srcdir) < 0) + if (virAsprintf(&wd, "%s/commanddata", abs_srcdir) < 0) goto cleanup; - virCommandSetWorkingDirectory(cmd, cwd); + virCommandSetWorkingDirectory(cmd, wd); if (virCommandRun(cmd, NULL) < 0) { virErrorPtr err = virGetLastError(); @@ -561,7 +558,7 @@ static int test15(const void *unused ATTRIBUTE_UNUSED) ret = checkoutput("test15"); cleanup: - VIR_FREE(cwd); + VIR_FREE(wd); virCommandFree(cmd); return ret; @@ -757,7 +754,6 @@ static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; int fd; abs_srcdir = getenv("abs_srcdir"); diff --git a/tests/conftest.c b/tests/conftest.c index a7977bb..6514f4d 100644 --- a/tests/conftest.c +++ b/tests/conftest.c @@ -6,32 +6,43 @@ #include #include #include "conf.h" +#include "memory.h" -int main(int argc, char **argv) { - int ret; +int main(int argc, char **argv) +{ + int ret, exit_code = EXIT_FAILURE; virConfPtr conf; int len = 10000; - char buffer[10000]; + char *buffer = NULL; if (argc != 2) { fprintf(stderr, "Usage: %s conf_file\n", argv[0]); - exit(EXIT_FAILURE); + goto cleanup; } + if (VIR_ALLOC_N(buffer, len) < 0) { + fprintf(stderr, "out of memory\n"); + goto cleanup; + } conf = virConfReadFile(argv[1], 0); if (conf == NULL) { fprintf(stderr, "Failed to process %s\n", argv[1]); - exit(EXIT_FAILURE); + goto cleanup; } - ret = virConfWriteMem(&buffer[0], &len, conf); + ret = virConfWriteMem(buffer, &len, conf); if (ret < 0) { fprintf(stderr, "Failed to serialize %s back\n", argv[1]); - exit(EXIT_FAILURE); + goto cleanup; } virConfFree(conf); if (fwrite(buffer, 1, len, stdout) != len) { fprintf(stderr, "Write failed: %s\n", strerror (errno)); - exit(EXIT_FAILURE); + goto cleanup; } - exit(EXIT_SUCCESS); + + exit_code = EXIT_SUCCESS; + +cleanup: + VIR_FREE(buffer); + return exit_code; } diff --git a/tests/cputest.c b/tests/cputest.c index bd06958..831fa81 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -40,11 +40,11 @@ #include "cpu/cpu_map.h" static const char *progname; +static char cwd[PATH_MAX]; static const char *abs_srcdir; static const char *abs_top_srcdir; #define VIR_FROM_THIS VIR_FROM_CPU -#define MAX_FILE 4096 enum compResultShadow { ERROR = VIR_CPU_COMPARE_ERROR, @@ -91,14 +91,13 @@ struct data { static virCPUDefPtr cpuTestLoadXML(const char *arch, const char *name) { - char xml[PATH_MAX]; + char *xml = NULL; xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; virCPUDefPtr cpu = NULL; - snprintf(xml, PATH_MAX, - "%s/cputestdata/%s-%s.xml", - abs_srcdir, arch, name); + if (virAsprintf(&xml, "%s/cputestdata/%s-%s.xml", abs_srcdir, arch, name) < 0) + goto cleanup; if (!(doc = virXMLParseFile(xml)) || !(ctxt = xmlXPathNewContext(doc))) @@ -110,6 +109,7 @@ cpuTestLoadXML(const char *arch, const char *name) cleanup: xmlXPathFreeContext(ctxt); xmlFreeDoc(doc); + free(xml); return cpu; } @@ -119,7 +119,7 @@ cpuTestLoadMultiXML(const char *arch, const char *name, unsigned int *count) { - char xml[PATH_MAX]; + char *xml = NULL; xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; xmlNodePtr *nodes = NULL; @@ -127,9 +127,8 @@ cpuTestLoadMultiXML(const char *arch, int n; int i; - snprintf(xml, PATH_MAX, - "%s/cputestdata/%s-%s.xml", - abs_srcdir, arch, name); + if (virAsprintf(&xml, "%s/cputestdata/%s-%s.xml", abs_srcdir, arch, name) < 0) + goto cleanup; if (!(doc = virXMLParseFile(xml)) || !(ctxt = xmlXPathNewContext(doc))) @@ -151,6 +150,7 @@ cpuTestLoadMultiXML(const char *arch, *count = n; cleanup: + free(xml); free(nodes); xmlXPathFreeContext(ctxt); xmlFreeDoc(doc); @@ -172,17 +172,16 @@ cpuTestCompareXML(const char *arch, const virCPUDefPtr cpu, const char *name) { - char xml[PATH_MAX]; - char expected[MAX_FILE]; - char *expectedPtr = &(expected[0]); + char *xml = NULL; + char *expected = NULL; char *actual = NULL; int ret = -1; - snprintf(xml, PATH_MAX, - "%s/cputestdata/%s-%s.xml", - abs_srcdir, arch, name); + if (virAsprintf(&xml, "%s/cputestdata/%s-%s.xml", + abs_srcdir, arch, name) < 0) + goto cleanup; - if (virtTestLoadFile(xml, &expectedPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &expected) < 0) goto cleanup; if (!(actual = virCPUDefFormat(cpu, NULL, 0))) @@ -196,6 +195,8 @@ cpuTestCompareXML(const char *arch, ret = 0; cleanup: + free(xml); + free(expected); free(actual); return ret; } @@ -335,7 +336,7 @@ cpuTestBaseline(const void *arg) virCPUDefPtr *cpus = NULL; virCPUDefPtr baseline = NULL; unsigned int ncpus = 0; - char result[PATH_MAX]; + char *result = NULL; unsigned int i; if (!(cpus = cpuTestLoadMultiXML(data->arch, data->name, &ncpus))) @@ -355,7 +356,9 @@ cpuTestBaseline(const void *arg) if (!baseline) goto cleanup; - snprintf(result, PATH_MAX, "%s-result", data->name); + if (virAsprintf(&result, "%s-result", data->name) < 0) + goto cleanup; + if (cpuTestCompareXML(data->arch, baseline, result) < 0) goto cleanup; @@ -384,6 +387,7 @@ cleanup: free(cpus); } virCPUDefFree(baseline); + free(result); return ret; } @@ -395,7 +399,7 @@ cpuTestUpdate(const void *arg) int ret = -1; virCPUDefPtr host = NULL; virCPUDefPtr cpu = NULL; - char result[PATH_MAX]; + char *result = NULL; if (!(host = cpuTestLoadXML(data->arch, data->host)) || !(cpu = cpuTestLoadXML(data->arch, data->name))) @@ -404,12 +408,15 @@ cpuTestUpdate(const void *arg) if (cpuUpdate(cpu, host) < 0) goto cleanup; - snprintf(result, PATH_MAX, "%s+%s", data->host, data->name); + if (virAsprintf(&result, "%s+%s", data->host, data->name) < 0) + goto cleanup; + ret = cpuTestCompareXML(data->arch, cpu, result); cleanup: virCPUDefFree(host); virCPUDefFree(cpu); + free(result); return ret; } @@ -467,10 +474,10 @@ static int (*cpuTest[])(const void *) = { static int cpuTestRun(const char *name, const struct data *data) { - char label[PATH_MAX]; + char *label = NULL; - snprintf(label, PATH_MAX, "CPU %s(%s): %s", - apis[data->api], data->arch, name); + if (virAsprintf(&label, "CPU %s(%s): %s", apis[data->api], data->arch, name) < 0) + return -1; free(virtTestLogContentAndReset()); @@ -482,9 +489,12 @@ cpuTestRun(const char *name, const struct data *data) fprintf(stderr, "\n%s\n", log); free(log); } + + free(label); return -1; } + free(label); return 0; } @@ -497,8 +507,7 @@ static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; - char map[PATH_MAX]; + char *map = NULL; progname = argv[0]; @@ -515,9 +524,11 @@ mymain(int argc, char **argv) if (!abs_top_srcdir) abs_top_srcdir = ".."; - snprintf(map, PATH_MAX, "%s/src/cpu/cpu_map.xml", abs_top_srcdir); - if (cpuMapOverride(map) < 0) + if (virAsprintf(&map, "%s/src/cpu/cpu_map.xml", abs_top_srcdir) < 0 || + cpuMapOverride(map) < 0) { + free(map); return EXIT_FAILURE; + } #define DO_TEST(arch, api, name, host, cpu, \ models, nmodels, preferred, result) \ @@ -627,6 +638,7 @@ mymain(int argc, char **argv) DO_TEST_GUESTDATA("x86", "host", "guest", models, "qemu64", 0); DO_TEST_GUESTDATA("x86", "host", "guest", nomodel, NULL, -1); + free(map); return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE); } diff --git a/tests/esxutilstest.c b/tests/esxutilstest.c index b6bf87b..78761a1 100644 --- a/tests/esxutilstest.c +++ b/tests/esxutilstest.c @@ -276,6 +276,7 @@ testEscapeDatastoreItem(const void *data ATTRIBUTE_UNUSED) } } + VIR_FREE(escaped); return 0; } @@ -317,6 +318,7 @@ testConvertWindows1252ToUTF8(const void *data ATTRIBUTE_UNUSED) } } + VIR_FREE(utf8); return 0; } diff --git a/tests/interfacexml2xmltest.c b/tests/interfacexml2xmltest.c index 094ccf5..26a19ab 100644 --- a/tests/interfacexml2xmltest.c +++ b/tests/interfacexml2xmltest.c @@ -14,19 +14,19 @@ #include "testutilsqemu.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; -#define MAX_FILE 4096 - -static int testCompareXMLToXMLFiles(const char *xml) { - char xmlData[MAX_FILE]; - char *xmlPtr = &(xmlData[0]); +static int +testCompareXMLToXMLFiles(const char *xml) +{ + char *xmlData = NULL; char *actual = NULL; int ret = -1; virInterfaceDefPtr dev = NULL; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; if (!(dev = virInterfaceDefParseString(xmlData))) @@ -43,16 +43,26 @@ static int testCompareXMLToXMLFiles(const char *xml) { ret = 0; fail: + free(xmlData); free(actual); virInterfaceDefFree(dev); return ret; } -static int testCompareXMLToXMLHelper(const void *data) { - char xml[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/interfaceschemadata/%s.xml", - abs_srcdir, (const char*)data); - return testCompareXMLToXMLFiles(xml); +static int +testCompareXMLToXMLHelper(const void *data) +{ + int result = -1; + char *xml = NULL; + + if (virAsprintf(&xml, "%s/interfaceschemadata/%s.xml", + abs_srcdir, (const char*)data) < 0) + return -1; + + result = testCompareXMLToXMLFiles(xml); + + free (xml); + return result; } @@ -60,7 +70,6 @@ static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c index 7805548..6faeab2 100644 --- a/tests/networkxml2xmltest.c +++ b/tests/networkxml2xmltest.c @@ -14,23 +14,21 @@ #include "testutilsqemu.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; -#define MAX_FILE 4096 - - -static int testCompareXMLToXMLFiles(const char *inxml, const char *outxml) { - char inXmlData[MAX_FILE]; - char *inXmlPtr = &(inXmlData[0]); - char outXmlData[MAX_FILE]; - char *outXmlPtr = &(outXmlData[0]); +static int +testCompareXMLToXMLFiles(const char *inxml, const char *outxml) +{ + char *inXmlData = NULL; + char *outXmlData = NULL; char *actual = NULL; int ret = -1; virNetworkDefPtr dev = NULL; - if (virtTestLoadFile(inxml, &inXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(inxml, &inXmlData) < 0) goto fail; - if (virtTestLoadFile(outxml, &outXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(outxml, &outXmlData) < 0) goto fail; if (!(dev = virNetworkDefParseString(inXmlData))) @@ -47,27 +45,40 @@ static int testCompareXMLToXMLFiles(const char *inxml, const char *outxml) { ret = 0; fail: + free(inXmlData); + free(outXmlData); free(actual); virNetworkDefFree(dev); return ret; } -static int testCompareXMLToXMLHelper(const void *data) { - char inxml[PATH_MAX]; - char outxml[PATH_MAX]; - snprintf(inxml, PATH_MAX, "%s/networkxml2xmlin/%s.xml", - abs_srcdir, (const char*)data); - snprintf(outxml, PATH_MAX, "%s/networkxml2xmlout/%s.xml", - abs_srcdir, (const char*)data); - return testCompareXMLToXMLFiles(inxml, outxml); -} +static int +testCompareXMLToXMLHelper(const void *data) +{ + int result = -1; + char *inxml = NULL; + char *outxml = NULL; + + if (virAsprintf(&inxml, "%s/networkxml2xmlin/%s.xml", + abs_srcdir, (const char*)data) < 0 || + virAsprintf(&outxml, "%s/networkxml2xmlout/%s.xml", + abs_srcdir, (const char*)data) < 0) { + goto cleanup; + } + + result = testCompareXMLToXMLFiles(inxml, outxml); +cleanup: + free(inxml); + free(outxml); + + return result; +} static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c index 2bc6743..e58883b 100644 --- a/tests/nodedevxml2xmltest.c +++ b/tests/nodedevxml2xmltest.c @@ -14,19 +14,18 @@ #include "testutilsqemu.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; -#define MAX_FILE 4096 - - -static int testCompareXMLToXMLFiles(const char *xml) { - char xmlData[MAX_FILE]; - char *xmlPtr = &(xmlData[0]); +static int +testCompareXMLToXMLFiles(const char *xml) +{ + char *xmlData = NULL; char *actual = NULL; int ret = -1; virNodeDeviceDefPtr dev = NULL; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; if (!(dev = virNodeDeviceDefParseString(xmlData, EXISTING_DEVICE))) @@ -43,16 +42,26 @@ static int testCompareXMLToXMLFiles(const char *xml) { ret = 0; fail: + free(xmlData); free(actual); virNodeDeviceDefFree(dev); return ret; } -static int testCompareXMLToXMLHelper(const void *data) { - char xml[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/nodedevschemadata/%s.xml", - abs_srcdir, (const char*)data); - return testCompareXMLToXMLFiles(xml); +static int +testCompareXMLToXMLHelper(const void *data) +{ + int result = -1; + char *xml = NULL; + + if (virAsprintf(&xml, "%s/nodedevschemadata/%s.xml", + abs_srcdir, (const char*)data) < 0) + return -1; + + result = testCompareXMLToXMLFiles(xml); + + free(xml); + return result; } @@ -60,7 +69,6 @@ static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/nodeinfotest.c b/tests/nodeinfotest.c index c690403..0d8c13b 100644 --- a/tests/nodeinfotest.c +++ b/tests/nodeinfotest.c @@ -22,26 +22,27 @@ mymain(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) #else static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; -# define MAX_FILE 4096 - extern int linuxNodeInfoCPUPopulate(FILE *cpuinfo, virNodeInfoPtr nodeinfo, bool need_hyperthreads); -static int linuxTestCompareFiles(const char *cpuinfofile, const char *outputfile) { - char actualData[MAX_FILE]; - char expectData[MAX_FILE]; - char *expect = &expectData[0]; +static int +linuxTestCompareFiles(const char *cpuinfofile, const char *outputfile) +{ + int ret = -1; + char *actualData = NULL; + char *expectData = NULL; virNodeInfo nodeinfo; FILE *cpuinfo; - if (virtTestLoadFile(outputfile, &expect, MAX_FILE) < 0) - return -1; + if (virtTestLoadFile(outputfile, &expectData) < 0) + goto fail; cpuinfo = fopen(cpuinfofile, "r"); if (!cpuinfo) - return -1; + goto fail; memset(&nodeinfo, 0, sizeof(nodeinfo)); if (linuxNodeInfoCPUPopulate(cpuinfo, &nodeinfo, false) < 0) { @@ -52,7 +53,7 @@ static int linuxTestCompareFiles(const char *cpuinfofile, const char *outputfile virFreeError(error); } VIR_FORCE_FCLOSE(cpuinfo); - return -1; + goto fail; } VIR_FORCE_FCLOSE(cpuinfo); @@ -61,30 +62,49 @@ static int linuxTestCompareFiles(const char *cpuinfofile, const char *outputfile * so blank it to a predictable value */ nodeinfo.nodes = 1; - snprintf(actualData, MAX_FILE, - "CPUs: %u, MHz: %u, Nodes: %u, Cores: %u\n", - nodeinfo.cpus, nodeinfo.mhz, nodeinfo.nodes, nodeinfo.cores); + if (virAsprintf(&actualData, "CPUs: %u, MHz: %u, Nodes: %u, Cores: %u\n", + nodeinfo.cpus, nodeinfo.mhz, nodeinfo.nodes, + nodeinfo.cores) < 0) + goto fail; if (STRNEQ(actualData, expectData)) { if (getenv("DEBUG_TESTS")) { printf("Expect %d '%s'\n", (int)strlen(expectData), expectData); printf("Actual %d '%s'\n", (int)strlen(actualData), actualData); } - return -1; + goto fail; } - return 0; + ret = 0; + +fail: + free(expectData); + free(actualData); + return ret; } -static int linuxTestNodeInfo(const void *data) { - char cpuinfo[PATH_MAX]; - char output[PATH_MAX]; - snprintf(cpuinfo, PATH_MAX, "%s/nodeinfodata/linux-%s.cpuinfo", - abs_srcdir, (const char*)data); - snprintf(output, PATH_MAX, "%s/nodeinfodata/linux-%s.txt", - abs_srcdir, (const char*)data); - return linuxTestCompareFiles(cpuinfo, output); +static int +linuxTestNodeInfo(const void *data) +{ + int result = -1; + char *cpuinfo = NULL; + char *output = NULL; + + if (virAsprintf(&cpuinfo, "%s/nodeinfodata/linux-%s.cpuinfo", + abs_srcdir, (const char*)data) < 0 || + virAsprintf(&output, "%s/nodeinfodata/linux-%s.txt", + abs_srcdir, (const char*)data) < 0) { + goto cleanup; + } + + result = linuxTestCompareFiles(cpuinfo, output); + +cleanup: + free(cpuinfo); + free(output); + + return result; } @@ -101,7 +121,6 @@ mymain(int argc, char **argv) "nodeinfo-5", "nodeinfo-6", }; - char cwd[PATH_MAX]; abs_srcdir = getenv("abs_srcdir"); if (!abs_srcdir) diff --git a/tests/nwfilterxml2xmltest.c b/tests/nwfilterxml2xmltest.c index 575177a..0463a79 100644 --- a/tests/nwfilterxml2xmltest.c +++ b/tests/nwfilterxml2xmltest.c @@ -17,25 +17,22 @@ #include "testutilsqemu.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; -#define MAX_FILE 4096 - - -static int testCompareXMLToXMLFiles(const char *inxml, - const char *outxml, - bool expect_error) { - char inXmlData[MAX_FILE]; - char *inXmlPtr = &(inXmlData[0]); - char outXmlData[MAX_FILE]; - char *outXmlPtr = &(outXmlData[0]); +static int +testCompareXMLToXMLFiles(const char *inxml, const char *outxml, + bool expect_error) +{ + char *inXmlData = NULL; + char *outXmlData = NULL; char *actual = NULL; int ret = -1; virNWFilterDefPtr dev = NULL; - if (virtTestLoadFile(inxml, &inXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(inxml, &inXmlData) < 0) goto fail; - if (virtTestLoadFile(outxml, &outXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(outxml, &outXmlData) < 0) goto fail; virResetLastError(); @@ -62,6 +59,8 @@ static int testCompareXMLToXMLFiles(const char *inxml, ret = 0; fail: + free(inXmlData); + free(outXmlData); free(actual); virNWFilterDefFree(dev); return ret; @@ -72,23 +71,34 @@ typedef struct test_parms { bool expect_warning; } test_parms; -static int testCompareXMLToXMLHelper(const void *data) { +static int +testCompareXMLToXMLHelper(const void *data) +{ + int result = -1; const test_parms *tp = data; - char inxml[PATH_MAX]; - char outxml[PATH_MAX]; - snprintf(inxml, PATH_MAX, "%s/nwfilterxml2xmlin/%s.xml", - abs_srcdir, tp->name); - snprintf(outxml, PATH_MAX, "%s/nwfilterxml2xmlout/%s.xml", - abs_srcdir, tp->name); - return testCompareXMLToXMLFiles(inxml, outxml, tp->expect_warning); -} + char *inxml = NULL; + char *outxml = NULL; + + if (virAsprintf(&inxml, "%s/nwfilterxml2xmlin/%s.xml", + abs_srcdir, tp->name) < 0 || + virAsprintf(&outxml, "%s/nwfilterxml2xmlout/%s.xml", + abs_srcdir, tp->name) < 0) { + goto cleanup; + } + + result = testCompareXMLToXMLFiles(inxml, outxml, tp->expect_warning); +cleanup: + free(inxml); + free(outxml); + + return result; +} static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c index 0214db0..47e452e 100644 --- a/tests/qemuargv2xmltest.c +++ b/tests/qemuargv2xmltest.c @@ -17,11 +17,10 @@ # include "testutilsqemu.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; static struct qemud_driver driver; -# define MAX_FILE 4096 - static int blankProblemElements(char *data) { if (virtTestClearLineRegex("[[:alnum:]]+", data) < 0 || @@ -37,18 +36,16 @@ static int blankProblemElements(char *data) static int testCompareXMLToArgvFiles(const char *xml, const char *cmdfile, bool expect_warning) { - char xmlData[MAX_FILE]; - char cmdData[MAX_FILE]; - char *expectxml = &(xmlData[0]); + char *expectxml = NULL; char *actualxml = NULL; - char *cmd = &(cmdData[0]); + char *cmd = NULL; int ret = -1; virDomainDefPtr vmdef = NULL; char *log; - if (virtTestLoadFile(cmdfile, &cmd, MAX_FILE) < 0) + if (virtTestLoadFile(cmdfile, &cmd) < 0) goto fail; - if (virtTestLoadFile(xml, &expectxml, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &expectxml) < 0) goto fail; if (!(vmdef = qemuParseCommandLineString(driver.caps, cmd))) @@ -77,7 +74,9 @@ static int testCompareXMLToArgvFiles(const char *xml, ret = 0; fail: + free(expectxml); free(actualxml); + free(cmd); virDomainDefFree(vmdef); return ret; } @@ -89,15 +88,26 @@ struct testInfo { const char *migrateFrom; }; -static int testCompareXMLToArgvHelper(const void *data) { +static int +testCompareXMLToArgvHelper(const void *data) +{ + int result = -1; const struct testInfo *info = data; - char xml[PATH_MAX]; - char args[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", - abs_srcdir, info->name); - snprintf(args, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.args", - abs_srcdir, info->name); - return testCompareXMLToArgvFiles(xml, args, !!info->extraFlags); + char *xml = NULL; + char *args = NULL; + + if (virAsprintf(&xml, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&args, "%s/qemuxml2argvdata/qemuxml2argv-%s.args", + abs_srcdir, info->name) < 0) + goto cleanup; + + result = testCompareXMLToArgvFiles(xml, args, !!info->extraFlags); + +cleanup: + free(xml); + free(args); + return result; } @@ -106,7 +116,6 @@ static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index c86c578..4838e9a 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -9,8 +9,6 @@ # include "qemu/qemu_capabilities.h" # include "memory.h" -# define MAX_HELP_OUTPUT_SIZE 1024*64 - struct testInfo { const char *name; virBitmapPtr flags; @@ -20,6 +18,7 @@ struct testInfo { }; static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; static void printMismatchedFlags(virBitmapPtr got, @@ -41,8 +40,7 @@ static int testHelpStrParsing(const void *data) { const struct testInfo *info = data; char *path = NULL; - char helpStr[MAX_HELP_OUTPUT_SIZE]; - char *help = &(helpStr[0]); + char *help = NULL; unsigned int version, is_kvm, kvm_version; virBitmapPtr flags = NULL; int ret = -1; @@ -52,7 +50,7 @@ static int testHelpStrParsing(const void *data) if (virAsprintf(&path, "%s/qemuhelpdata/%s", abs_srcdir, info->name) < 0) return -1; - if (virtTestLoadFile(path, &help, MAX_HELP_OUTPUT_SIZE) < 0) + if (virtTestLoadFile(path, &help) < 0) goto cleanup; if (!(flags = qemuCapsNew())) @@ -64,11 +62,12 @@ static int testHelpStrParsing(const void *data) if (qemuCapsGet(info->flags, QEMU_CAPS_DEVICE)) { VIR_FREE(path); + VIR_FREE(help); if (virAsprintf(&path, "%s/qemuhelpdata/%s-device", abs_srcdir, info->name) < 0) goto cleanup; - if (virtTestLoadFile(path, &help, MAX_HELP_OUTPUT_SIZE) < 0) + if (virtTestLoadFile(path, &help) < 0) goto cleanup; if (qemuCapsParseDeviceStr(help, flags) < 0) @@ -114,6 +113,7 @@ static int testHelpStrParsing(const void *data) ret = 0; cleanup: VIR_FREE(path); + VIR_FREE(help); qemuCapsFree(flags); VIR_FREE(got); VIR_FREE(expected); @@ -124,7 +124,6 @@ static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index c06bdf6..023f5df 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -20,20 +20,19 @@ # include "testutilsqemu.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; static const char *abs_top_srcdir; static struct qemud_driver driver; -# define MAX_FILE 4096 - static int testCompareXMLToArgvFiles(const char *xml, const char *cmdline, virBitmapPtr extraFlags, const char *migrateFrom, int migrateFd, - bool expectError) { - char argvData[MAX_FILE]; - char *expectargv = &(argvData[0]); + bool expectError) +{ + char *expectargv = NULL; int len; char *actualargv = NULL; int ret = -1; @@ -47,7 +46,7 @@ static int testCompareXMLToArgvFiles(const char *xml, if (!(conn = virGetConnect())) goto fail; - len = virtTestLoadFile(cmdline, &expectargv, MAX_FILE); + len = virtTestLoadFile(cmdline, &expectargv); if (len < 0) goto fail; if (len && expectargv[len - 1] == '\n') @@ -158,6 +157,7 @@ static int testCompareXMLToArgvFiles(const char *xml, fail: free(log); free(emulator); + free(expectargv); free(actualargv); virCommandFree(cmd); virDomainDefFree(vmdef); @@ -174,17 +174,28 @@ struct testInfo { bool expectError; }; -static int testCompareXMLToArgvHelper(const void *data) { +static int +testCompareXMLToArgvHelper(const void *data) +{ + int result = -1; const struct testInfo *info = data; - char xml[PATH_MAX]; - char args[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", - abs_srcdir, info->name); - snprintf(args, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.args", - abs_srcdir, info->name); - return testCompareXMLToArgvFiles(xml, args, info->extraFlags, - info->migrateFrom, info->migrateFd, - info->expectError); + char *xml = NULL; + char *args = NULL; + + if (virAsprintf(&xml, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&args, "%s/qemuxml2argvdata/qemuxml2argv-%s.args", + abs_srcdir, info->name) < 0) + goto cleanup; + + result = testCompareXMLToArgvFiles(xml, args, info->extraFlags, + info->migrateFrom, info->migrateFd, + info->expectError); + +cleanup: + free(xml); + free(args); + return result; } @@ -193,14 +204,13 @@ static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; - char map[PATH_MAX]; + char *map = NULL; progname = argv[0]; if (argc > 1) { fprintf(stderr, "Usage: %s\n", progname); - return (EXIT_FAILURE); + return EXIT_FAILURE; } abs_srcdir = getenv("abs_srcdir"); @@ -224,10 +234,11 @@ mymain(int argc, char **argv) return EXIT_FAILURE; if (!(driver.spicePassword = strdup("123456"))) return EXIT_FAILURE; - - snprintf(map, PATH_MAX, "%s/src/cpu/cpu_map.xml", abs_top_srcdir); - if (cpuMapOverride(map) < 0) + if (virAsprintf(&map, "%s/src/cpu/cpu_map.xml", abs_top_srcdir) < 0 || + cpuMapOverride(map) < 0) { + free(map); return EXIT_FAILURE; + } # define DO_TEST_FULL(name, migrateFrom, migrateFd, expectError, ...) \ do { \ @@ -498,6 +509,7 @@ mymain(int argc, char **argv) free(driver.stateDir); virCapabilitiesFree(driver.caps); + free(map); return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 27330a9..9d8beeb 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -16,24 +16,22 @@ # include "testutilsqemu.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; static struct qemud_driver driver; -# define MAX_FILE 4096 - - -static int testCompareXMLToXMLFiles(const char *inxml, const char *outxml) { - char inXmlData[MAX_FILE]; - char *inXmlPtr = &(inXmlData[0]); - char outXmlData[MAX_FILE]; - char *outXmlPtr = &(outXmlData[0]); +static int +testCompareXMLToXMLFiles(const char *inxml, const char *outxml) +{ + char *inXmlData = NULL; + char *outXmlData = NULL; char *actual = NULL; int ret = -1; virDomainDefPtr def = NULL; - if (virtTestLoadFile(inxml, &inXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(inxml, &inXmlData) < 0) goto fail; - if (virtTestLoadFile(outxml, &outXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(outxml, &outXmlData) < 0) goto fail; if (!(def = virDomainDefParseString(driver.caps, inXmlData, @@ -51,6 +49,8 @@ static int testCompareXMLToXMLFiles(const char *inxml, const char *outxml) { ret = 0; fail: + free(inXmlData); + free(outXmlData); free(actual); virDomainDefFree(def); return ret; @@ -61,16 +61,19 @@ struct testInfo { int different; }; -static int testCompareXMLToXMLHelper(const void *data) { +static int +testCompareXMLToXMLHelper(const void *data) +{ const struct testInfo *info = data; - char xml_in[PATH_MAX]; - char xml_out[PATH_MAX]; - int ret; + char *xml_in = NULL; + char *xml_out = NULL; + int ret = -1; - snprintf(xml_in, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", - abs_srcdir, info->name); - snprintf(xml_out, PATH_MAX, "%s/qemuxml2xmloutdata/qemuxml2xmlout-%s.xml", - abs_srcdir, info->name); + if (virAsprintf(&xml_in, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&xml_out, "%s/qemuxml2xmloutdata/qemuxml2xmlout-%s.xml", + abs_srcdir, info->name) < 0) + goto cleanup; if (info->different) { ret = testCompareXMLToXMLFiles(xml_in, xml_out); @@ -78,6 +81,9 @@ static int testCompareXMLToXMLHelper(const void *data) { ret = testCompareXMLToXMLFiles(xml_in, xml_in); } +cleanup: + free(xml_in); + free(xml_out); return ret; } @@ -86,7 +92,6 @@ static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/sexpr2xmltest.c b/tests/sexpr2xmltest.c index 9f74ece..4df0fd5 100644 --- a/tests/sexpr2xmltest.c +++ b/tests/sexpr2xmltest.c @@ -14,18 +14,16 @@ #include "testutilsxen.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; static virCapsPtr caps; -#define MAX_FILE 4096 - -static int testCompareFiles(const char *xml, const char *sexpr, - int xendConfigVersion) { - char xmlData[MAX_FILE]; - char sexprData[MAX_FILE]; +static int +testCompareFiles(const char *xml, const char *sexpr, int xendConfigVersion) +{ + char *xmlData = NULL; + char *sexprData = NULL; char *gotxml = NULL; - char *xmlPtr = &(xmlData[0]); - char *sexprPtr = &(sexprData[0]); int id; char * tty; int vncport; @@ -38,10 +36,10 @@ static int testCompareFiles(const char *xml, const char *sexpr, conn = virGetConnect(); if (!conn) goto fail; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; - if (virtTestLoadFile(sexpr, &sexprPtr, MAX_FILE) < 0) + if (virtTestLoadFile(sexpr, &sexprData) < 0) goto fail; memset(&priv, 0, sizeof priv); @@ -72,6 +70,8 @@ static int testCompareFiles(const char *xml, const char *sexpr, ret = 0; fail: + free(xmlData); + free(sexprData); free(gotxml); virDomainDefFree(def); if (conn) @@ -86,23 +86,34 @@ struct testInfo { int version; }; -static int testCompareHelper(const void *data) { +static int +testCompareHelper(const void *data) +{ + int result = -1; const struct testInfo *info = data; - char xml[PATH_MAX]; - char args[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/sexpr2xmldata/sexpr2xml-%s.xml", - abs_srcdir, info->input); - snprintf(args, PATH_MAX, "%s/sexpr2xmldata/sexpr2xml-%s.sexpr", - abs_srcdir, info->output); - return testCompareFiles(xml, args, info->version); -} + char *xml = NULL; + char *args = NULL; + + if (virAsprintf(&xml, "%s/sexpr2xmldata/sexpr2xml-%s.xml", + abs_srcdir, info->input) < 0 || + virAsprintf(&args, "%s/sexpr2xmldata/sexpr2xml-%s.sexpr", + abs_srcdir, info->output) < 0) { + goto cleanup; + } + + result = testCompareFiles(xml, args, info->version); +cleanup: + free(xml); + free(args); + + return result; +} static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c index 2ec29e3..e947100 100644 --- a/tests/storagepoolxml2xmltest.c +++ b/tests/storagepoolxml2xmltest.c @@ -14,23 +14,21 @@ #include "testutilsqemu.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; -#define MAX_FILE 4096 - - -static int testCompareXMLToXMLFiles(const char *inxml, const char *outxml) { - char inXmlData[MAX_FILE]; - char *inXmlPtr = &(inXmlData[0]); - char outXmlData[MAX_FILE]; - char *outXmlPtr = &(outXmlData[0]); +static int +testCompareXMLToXMLFiles(const char *inxml, const char *outxml) +{ + char *inXmlData = NULL; + char *outXmlData = NULL; char *actual = NULL; int ret = -1; virStoragePoolDefPtr dev = NULL; - if (virtTestLoadFile(inxml, &inXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(inxml, &inXmlData) < 0) goto fail; - if (virtTestLoadFile(outxml, &outXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(outxml, &outXmlData) < 0) goto fail; if (!(dev = virStoragePoolDefParseString(inXmlData))) @@ -47,27 +45,40 @@ static int testCompareXMLToXMLFiles(const char *inxml, const char *outxml) { ret = 0; fail: + free(inXmlData); + free(outXmlData); free(actual); virStoragePoolDefFree(dev); return ret; } -static int testCompareXMLToXMLHelper(const void *data) { - char inxml[PATH_MAX]; - char outxml[PATH_MAX]; - snprintf(inxml, PATH_MAX, "%s/storagepoolxml2xmlin/%s.xml", - abs_srcdir, (const char*)data); - snprintf(outxml, PATH_MAX, "%s/storagepoolxml2xmlout/%s.xml", - abs_srcdir, (const char*)data); - return testCompareXMLToXMLFiles(inxml, outxml); -} +static int +testCompareXMLToXMLHelper(const void *data) +{ + int result = -1; + char *inxml = NULL; + char *outxml = NULL; + + if (virAsprintf(&inxml, "%s/storagepoolxml2xmlin/%s.xml", + abs_srcdir, (const char*)data) < 0 || + virAsprintf(&outxml, "%s/storagepoolxml2xmlout/%s.xml", + abs_srcdir, (const char*)data) < 0) { + goto cleanup; + } + + result = testCompareXMLToXMLFiles(inxml, outxml); +cleanup: + free(inxml); + free(outxml); + + return result; +} static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/storagevolxml2xmltest.c b/tests/storagevolxml2xmltest.c index ffa5dfe..c57b7a8 100644 --- a/tests/storagevolxml2xmltest.c +++ b/tests/storagevolxml2xmltest.c @@ -14,30 +14,26 @@ #include "testutilsqemu.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; -#define MAX_FILE 4096 - - -static int testCompareXMLToXMLFiles(const char *poolxml, - const char *inxml, - const char *outxml) { - char poolXmlData[MAX_FILE]; - char *poolXmlPtr = &(poolXmlData[0]); - char inXmlData[MAX_FILE]; - char *inXmlPtr = &(inXmlData[0]); - char outXmlData[MAX_FILE]; - char *outXmlPtr = &(outXmlData[0]); +static int +testCompareXMLToXMLFiles(const char *poolxml, const char *inxml, + const char *outxml) +{ + char *poolXmlData = NULL; + char *inXmlData = NULL; + char *outXmlData = NULL; char *actual = NULL; int ret = -1; virStoragePoolDefPtr pool = NULL; virStorageVolDefPtr dev = NULL; - if (virtTestLoadFile(poolxml, &poolXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(poolxml, &poolXmlData) < 0) goto fail; - if (virtTestLoadFile(inxml, &inXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(inxml, &inXmlData) < 0) goto fail; - if (virtTestLoadFile(outxml, &outXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(outxml, &outXmlData) < 0) goto fail; if (!(pool = virStoragePoolDefParseString(poolXmlData))) @@ -57,6 +53,9 @@ static int testCompareXMLToXMLFiles(const char *poolxml, ret = 0; fail: + free(poolXmlData); + free(inXmlData); + free(outXmlData); free(actual); virStoragePoolDefFree(pool); virStorageVolDefFree(dev); @@ -68,19 +67,32 @@ struct testInfo { const char *name; }; -static int testCompareXMLToXMLHelper(const void *data) { - char poolxml[PATH_MAX]; - char inxml[PATH_MAX]; - char outxml[PATH_MAX]; +static int +testCompareXMLToXMLHelper(const void *data) +{ + int result = -1; const struct testInfo *info = data; + char *poolxml = NULL; + char *inxml = NULL; + char *outxml = NULL; + + if (virAsprintf(&poolxml, "%s/storagepoolxml2xmlin/%s.xml", + abs_srcdir, info->pool) < 0 || + virAsprintf(&inxml, "%s/storagevolxml2xmlin/%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&outxml, "%s/storagevolxml2xmlout/%s.xml", + abs_srcdir, info->name) < 0) { + goto cleanup; + } + + result = testCompareXMLToXMLFiles(poolxml, inxml, outxml); + +cleanup: + free(poolxml); + free(inxml); + free(outxml); - snprintf(poolxml, PATH_MAX, "%s/storagepoolxml2xmlin/%s.xml", - abs_srcdir, (const char*)info->pool); - snprintf(inxml, PATH_MAX, "%s/storagevolxml2xmlin/%s.xml", - abs_srcdir, (const char*)info->name); - snprintf(outxml, PATH_MAX, "%s/storagevolxml2xmlout/%s.xml", - abs_srcdir, (const char*)info->name); - return testCompareXMLToXMLFiles(poolxml, inxml, outxml); + return result; } @@ -88,7 +100,6 @@ static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/testutils.c b/tests/testutils.c index 1f3b569..aaee337 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -170,17 +170,16 @@ virtTestRun(const char *title, int nloops, int (*body)(const void *data), const return ret; } -/* Read FILE into buffer BUF of length BUFLEN. - Upon any failure, or if FILE appears to contain more than BUFLEN bytes, - diagnose it and return -1, but don't bother trying to preserve errno. - Otherwise, return the number of bytes copied into BUF. */ -int virtTestLoadFile(const char *file, - char **buf, - int buflen) { +/* Allocate BUF to the size of FILE. Read FILE into buffer BUF. + Upon any failure, diagnose it and return -1, but don't bother trying + to preserve errno. Otherwise, return the number of bytes copied into BUF. */ +int +virtTestLoadFile(const char *file, char **buf) +{ FILE *fp = fopen(file, "r"); struct stat st; - char *tmp = *buf; - int len, tmplen = buflen; + char *tmp; + int len, tmplen, buflen; if (!fp) { fprintf (stderr, "%s: failed to open: %s\n", file, strerror(errno)); @@ -193,17 +192,23 @@ int virtTestLoadFile(const char *file, return -1; } - if (st.st_size > (buflen-1)) { - fprintf (stderr, "%s: larger than buffer (> %d)\n", file, buflen-1); + tmplen = buflen = st.st_size + 1; + + if (VIR_ALLOC_N(*buf, buflen) < 0) { + fprintf (stderr, "%s: larger than available memory (> %d)\n", file, buflen); VIR_FORCE_FCLOSE(fp); return -1; } + tmp = *buf; (*buf)[0] = '\0'; if (st.st_size) { /* read the file line by line */ while (fgets(tmp, tmplen, fp) != NULL) { len = strlen(tmp); + /* stop on an empty line */ + if (len == 0) + break; /* remove trailing backslash-newline pair */ if (len >= 2 && tmp[len-2] == '\\' && tmp[len-1] == '\n') { len -= 2; @@ -216,6 +221,7 @@ int virtTestLoadFile(const char *file, if (ferror(fp)) { fprintf (stderr, "%s: read failed: %s\n", file, strerror(errno)); VIR_FORCE_FCLOSE(fp); + free(*buf); return -1; } } @@ -265,10 +271,11 @@ void virtTestCaptureProgramExecChild(const char *const argv[], VIR_FORCE_CLOSE(stdinfd); } -int virtTestCaptureProgramOutput(const char *const argv[], - char **buf, - int buflen) { +int +virtTestCaptureProgramOutput(const char *const argv[], char **buf, int maxlen) +{ int pipefd[2]; + int len; if (pipe(pipefd) < 0) return -1; @@ -286,34 +293,20 @@ int virtTestCaptureProgramOutput(const char *const argv[], return -1; default: - { - int got = 0; - int ret = -1; - int want = buflen-1; - - VIR_FORCE_CLOSE(pipefd[1]); - - while (want) { - if ((ret = read(pipefd[0], (*buf)+got, want)) <= 0) - break; - got += ret; - want -= ret; - } - VIR_FORCE_CLOSE(pipefd[0]); - - if (!ret) - (*buf)[got] = '\0'; - - waitpid(pid, NULL, 0); + VIR_FORCE_CLOSE(pipefd[1]); + len = virFileReadLimFD(pipefd[0], maxlen, buf); + VIR_FORCE_CLOSE(pipefd[0]); + waitpid(pid, NULL, 0); - return ret; - } + return len; } } #else /* !WIN32 */ -int virtTestCaptureProgramOutput(const char *const argv[] ATTRIBUTE_UNUSED, - char **buf ATTRIBUTE_UNUSED, - int buflen ATTRIBUTE_UNUSED) { +int +virtTestCaptureProgramOutput(const char *const argv[] ATTRIBUTE_UNUSED, + char **buf ATTRIBUTE_UNUSED, + int maxlen ATTRIBUTE_UNUSED) +{ return -1; } #endif /* !WIN32 */ diff --git a/tests/testutils.h b/tests/testutils.h index 88603a1..6adc0a0 100644 --- a/tests/testutils.h +++ b/tests/testutils.h @@ -23,12 +23,8 @@ int virtTestRun(const char *title, int nloops, int (*body)(const void *data), const void *data); -int virtTestLoadFile(const char *name, - char **buf, - int buflen); -int virtTestCaptureProgramOutput(const char *const argv[], - char **buf, - int buflen); +int virtTestLoadFile(const char *file, char **buf); +int virtTestCaptureProgramOutput(const char *const argv[], char **buf, int maxlen); int virtTestClearLineRegex(const char *pattern, char *string); diff --git a/tests/virshtest.c b/tests/virshtest.c index 8ec97a8..e6743d7 100644 --- a/tests/virshtest.c +++ b/tests/virshtest.c @@ -6,11 +6,12 @@ #include "internal.h" #include "xml.h" +#include "util.h" #include "testutils.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; -#define MAX_FILE 4096 #define DOM_UUID "ef861801-45b9-11cb-88e3-afbfe5370493" @@ -47,41 +48,31 @@ static int testFilterLine(char *buffer, return 0; } -static int testCompareOutputLit(const char *expectData, - const char *filter, const char *const argv[]) { - char actualData[MAX_FILE]; - char *actualPtr = &(actualData[0]); - - if (virtTestCaptureProgramOutput(argv, &actualPtr, MAX_FILE) < 0) - return -1; - - if (filter) - if (testFilterLine(actualData, filter) < 0) - return -1; +static int +testCompareOutputLit(const char *expectData, + const char *filter, const char *const argv[]) +{ + int result = -1; + char *actualData = NULL; - if (STRNEQ(expectData, actualData)) { - virtTestDifference(stderr, expectData, actualData); - return -1; - } + if (virtTestCaptureProgramOutput(argv, &actualData, 4096) < 0) + goto cleanup; - return 0; -} + if (filter && testFilterLine(actualData, filter) < 0) + goto cleanup; -#if unused -static int testCompareOutput(const char *expect_rel, const char *filter, - const char *const argv[]) { - char expectData[MAX_FILE]; - char *expectPtr = &(expectData[0]); - char expect[PATH_MAX]; + if (STRNEQ(expectData, actualData)) { + virtTestDifference(stderr, expectData, actualData); + goto cleanup; + } - snprintf(expect, sizeof expect - 1, "%s/%s", abs_srcdir, expect_rel); + result = 0; - if (virtTestLoadFile(expect, &expectPtr, MAX_FILE) < 0) - return -1; +cleanup: + free(actualData); - return testCompareOutputLit(expectData, filter, argv); + return result; } -#endif #define VIRSH_DEFAULT "../tools/virsh", \ "--connect", \ @@ -235,8 +226,6 @@ static int mymain(int argc, char **argv) { int ret = 0; - char buffer[PATH_MAX]; - char cwd[PATH_MAX]; abs_srcdir = getenv("abs_srcdir"); if (!abs_srcdir) @@ -246,16 +235,17 @@ mymain(int argc, char **argv) exit (EXIT_AM_SKIP); #endif - snprintf(buffer, PATH_MAX-1, "test://%s/../examples/xml/test/testnode.xml", abs_srcdir); - buffer[PATH_MAX-1] = '\0'; - progname = argv[0]; - custom_uri = buffer; - if (argc > 1) { fprintf(stderr, "Usage: %s\n", progname); - return(EXIT_FAILURE); + return EXIT_FAILURE; } + if (virAsprintf(&custom_uri, "test://%s/../examples/xml/test/testnode.xml", + abs_srcdir) < 0) + return EXIT_FAILURE; + + progname = argv[0]; + if (virtTestRun("virsh list (default)", 1, testCompareListDefault, NULL) != 0) ret = -1; @@ -406,6 +396,7 @@ mymain(int argc, char **argv) #undef DO_TEST + free(custom_uri); return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } diff --git a/tests/vmx2xmltest.c b/tests/vmx2xmltest.c index 5fed1c4..53d66c5 100644 --- a/tests/vmx2xmltest.c +++ b/tests/vmx2xmltest.c @@ -11,13 +11,12 @@ # include "testutils.h" # include "vmx/vmx.h" -static char *progname = NULL; -static char *abs_srcdir = NULL; -static virCapsPtr caps = NULL; +static char *progname; +static char cwd[PATH_MAX]; +static char *abs_srcdir; +static virCapsPtr caps; static virVMXContext ctx; -# define MAX_FILE 4096 - static void testCapsInit(void) { @@ -71,19 +70,17 @@ static int testCompareFiles(const char *vmx, const char *xml) { int result = -1; - char vmxData[MAX_FILE]; - char xmlData[MAX_FILE]; + char *vmxData = NULL; + char *xmlData = NULL; char *formatted = NULL; - char *vmxPtr = &(vmxData[0]); - char *xmlPtr = &(xmlData[0]); virDomainDefPtr def = NULL; virErrorPtr err = NULL; - if (virtTestLoadFile(vmx, &vmxPtr, MAX_FILE) < 0) { + if (virtTestLoadFile(vmx, &vmxData) < 0) { goto failure; } - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) { + if (virtTestLoadFile(xml, &xmlData) < 0) { goto failure; } @@ -111,6 +108,8 @@ testCompareFiles(const char *vmx, const char *xml) result = 0; failure: + VIR_FREE(vmxData); + VIR_FREE(xmlData); VIR_FREE(formatted); virDomainDefFree(def); @@ -125,16 +124,25 @@ struct testInfo { static int testCompareHelper(const void *data) { + int result = -1; const struct testInfo *info = data; - char vmx[PATH_MAX]; - char xml[PATH_MAX]; + char *vmx = NULL; + char *xml = NULL; + + if (virAsprintf(&vmx, "%s/vmx2xmldata/vmx2xml-%s.vmx", abs_srcdir, + info->input) < 0 || + virAsprintf(&xml, "%s/vmx2xmldata/vmx2xml-%s.xml", abs_srcdir, + info->output) < 0) { + goto cleanup; + } - snprintf(vmx, PATH_MAX, "%s/vmx2xmldata/vmx2xml-%s.vmx", abs_srcdir, - info->input); - snprintf(xml, PATH_MAX, "%s/vmx2xmldata/vmx2xml-%s.xml", abs_srcdir, - info->output); + result = testCompareFiles(vmx, xml); - return testCompareFiles(vmx, xml); + cleanup: + VIR_FREE(vmx); + VIR_FREE(xml); + + return result; } static char * @@ -184,7 +192,6 @@ static int mymain(int argc, char **argv) { int result = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/xencapstest.c b/tests/xencapstest.c index 7b48812..a00b30b 100644 --- a/tests/xencapstest.c +++ b/tests/xencapstest.c @@ -12,34 +12,30 @@ #include "files.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; -#define MAX_FILE 4096 - -static int testCompareFiles(const char *hostmachine, - const char *xml_rel, - const char *cpuinfo_rel, - const char *capabilities_rel) { - char xmlData[MAX_FILE]; - char *expectxml = &(xmlData[0]); +static int +testCompareFiles(const char *hostmachine, const char *xml_rel, + const char *cpuinfo_rel, const char *capabilities_rel) +{ + char *expectxml = NULL; char *actualxml = NULL; FILE *fp1 = NULL, *fp2 = NULL; virCapsPtr caps = NULL; int ret = -1; - char xml[PATH_MAX]; - char cpuinfo[PATH_MAX]; - char capabilities[PATH_MAX]; + char *xml = NULL; + char *cpuinfo = NULL; + char *capabilities = NULL; - snprintf(xml, sizeof xml - 1, "%s/%s", - abs_srcdir, xml_rel); - snprintf(cpuinfo, sizeof cpuinfo - 1, "%s/%s", - abs_srcdir, cpuinfo_rel); - snprintf(capabilities, sizeof capabilities - 1, "%s/%s", - abs_srcdir, capabilities_rel); + if (virAsprintf(&xml, "%s/%s", abs_srcdir, xml_rel) < 0 || + virAsprintf(&cpuinfo, "%s/%s", abs_srcdir, cpuinfo_rel) < 0 || + virAsprintf(&capabilities, "%s/%s", abs_srcdir, capabilities_rel) < 0) + goto fail; - if (virtTestLoadFile(xml, &expectxml, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &expectxml) < 0) goto fail; if (!(fp1 = fopen(cpuinfo, "r"))) @@ -62,8 +58,11 @@ static int testCompareFiles(const char *hostmachine, ret = 0; fail: - + free(expectxml); free(actualxml); + free(xml); + free(cpuinfo); + free(capabilities); VIR_FORCE_FCLOSE(fp1); VIR_FORCE_FCLOSE(fp2); @@ -154,7 +153,6 @@ static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c index 7d418a5..41ea0c8 100644 --- a/tests/xmconfigtest.c +++ b/tests/xmconfigtest.c @@ -37,33 +37,33 @@ #include "memory.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; static virCapsPtr caps; -#define MAX_FILE 4096 - -static int testCompareParseXML(const char *xmcfg, const char *xml, - int xendConfigVersion) { - char xmlData[MAX_FILE]; - char xmcfgData[MAX_FILE]; - char gotxmcfgData[MAX_FILE]; - char *xmlPtr = &(xmlData[0]); - char *xmcfgPtr = &(xmcfgData[0]); - char *gotxmcfgPtr = &(gotxmcfgData[0]); +static int +testCompareParseXML(const char *xmcfg, const char *xml, int xendConfigVersion) +{ + char *xmlData = NULL; + char *xmcfgData = NULL; + char *gotxmcfgData = NULL; virConfPtr conf = NULL; int ret = -1; virConnectPtr conn; - int wrote = MAX_FILE; + int wrote = 4096; struct _xenUnifiedPrivate priv; virDomainDefPtr def = NULL; + if (VIR_ALLOC_N(gotxmcfgData, wrote) < 0) + goto fail; + conn = virGetConnect(); if (!conn) goto fail; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; - if (virtTestLoadFile(xmcfg, &xmcfgPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xmcfg, &xmcfgData) < 0) goto fail; /* Many puppies died to bring you this code. */ @@ -71,16 +71,16 @@ static int testCompareParseXML(const char *xmcfg, const char *xml, priv.caps = caps; conn->privateData = &priv; - if (!(def = virDomainDefParseString(caps, xmlPtr, + if (!(def = virDomainDefParseString(caps, xmlData, VIR_DOMAIN_XML_INACTIVE))) goto fail; if (!(conf = xenFormatXM(conn, def, xendConfigVersion))) goto fail; - if (virConfWriteMem(gotxmcfgPtr, &wrote, conf) < 0) + if (virConfWriteMem(gotxmcfgData, &wrote, conf) < 0) goto fail; - gotxmcfgPtr[wrote] = '\0'; + gotxmcfgData[wrote] = '\0'; if (STRNEQ(xmcfgData, gotxmcfgData)) { virtTestDifference(stderr, xmcfgData, gotxmcfgData); @@ -90,6 +90,9 @@ static int testCompareParseXML(const char *xmcfg, const char *xml, ret = 0; fail: + free(xmlData); + free(xmcfgData); + free(gotxmcfgData); if (conf) virConfFree(conf); virDomainDefFree(def); @@ -98,12 +101,11 @@ static int testCompareParseXML(const char *xmcfg, const char *xml, return ret; } -static int testCompareFormatXML(const char *xmcfg, const char *xml, - int xendConfigVersion) { - char xmlData[MAX_FILE]; - char xmcfgData[MAX_FILE]; - char *xmlPtr = &(xmlData[0]); - char *xmcfgPtr = &(xmcfgData[0]); +static int +testCompareFormatXML(const char *xmcfg, const char *xml, int xendConfigVersion) +{ + char *xmlData = NULL; + char *xmcfgData = NULL; char *gotxml = NULL; virConfPtr conf = NULL; int ret = -1; @@ -114,10 +116,10 @@ static int testCompareFormatXML(const char *xmcfg, const char *xml, conn = virGetConnect(); if (!conn) goto fail; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; - if (virtTestLoadFile(xmcfg, &xmcfgPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xmcfg, &xmcfgData) < 0) goto fail; /* Many puppies died to bring you this code. */ @@ -125,7 +127,7 @@ static int testCompareFormatXML(const char *xmcfg, const char *xml, priv.caps = caps; conn->privateData = &priv; - if (!(conf = virConfReadMem(xmcfgPtr, strlen(xmcfgPtr), 0))) + if (!(conf = virConfReadMem(xmcfgData, strlen(xmcfgData), 0))) goto fail; if (!(def = xenParseXM(conf, priv.xendConfigVersion, priv.caps))) @@ -144,6 +146,8 @@ static int testCompareFormatXML(const char *xmcfg, const char *xml, fail: if (conf) virConfFree(conf); + VIR_FREE(xmlData); + VIR_FREE(xmcfgData); VIR_FREE(gotxml); virDomainDefFree(def); virUnrefConnect(conn); @@ -158,18 +162,30 @@ struct testInfo { int mode; }; -static int testCompareHelper(const void *data) { +static int +testCompareHelper(const void *data) +{ + int result = -1; const struct testInfo *info = data; - char xml[PATH_MAX]; - char cfg[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/xmconfigdata/test-%s.xml", - abs_srcdir, info->name); - snprintf(cfg, PATH_MAX, "%s/xmconfigdata/test-%s.cfg", - abs_srcdir, info->name); + char *xml = NULL; + char *cfg = NULL; + + if (virAsprintf(&xml, "%s/xmconfigdata/test-%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&cfg, "%s/xmconfigdata/test-%s.cfg", + abs_srcdir, info->name) < 0) + goto cleanup; + if (info->mode == 0) - return testCompareParseXML(cfg, xml, info->version); + result = testCompareParseXML(cfg, xml, info->version); else - return testCompareFormatXML(cfg, xml, info->version); + result = testCompareFormatXML(cfg, xml, info->version); + +cleanup: + free(xml); + free(cfg); + + return result; } @@ -177,7 +193,6 @@ static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/xml2sexprtest.c b/tests/xml2sexprtest.c index cf530b6..b6d8c00 100644 --- a/tests/xml2sexprtest.c +++ b/tests/xml2sexprtest.c @@ -15,25 +15,23 @@ #include "testutilsxen.h" static char *progname; +static char cwd[PATH_MAX]; static char *abs_srcdir; static virCapsPtr caps; -#define MAX_FILE 4096 - -static int testCompareFiles(const char *xml, const char *sexpr, - int xendConfigVersion) { - char xmlData[MAX_FILE]; - char sexprData[MAX_FILE]; +static int +testCompareFiles(const char *xml, const char *sexpr, int xendConfigVersion) +{ + char *xmlData = NULL; + char *sexprData = NULL; char *gotsexpr = NULL; - char *xmlPtr = &(xmlData[0]); - char *sexprPtr = &(sexprData[0]); int ret = -1; virDomainDefPtr def = NULL; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; - if (virtTestLoadFile(sexpr, &sexprPtr, MAX_FILE) < 0) + if (virtTestLoadFile(sexpr, &sexprData) < 0) goto fail; if (!(def = virDomainDefParseString(caps, xmlData, @@ -51,8 +49,10 @@ static int testCompareFiles(const char *xml, const char *sexpr, ret = 0; fail: - virDomainDefFree(def); + free(xmlData); + free(sexprData); free(gotsexpr); + virDomainDefFree(def); return ret; } @@ -64,23 +64,34 @@ struct testInfo { int version; }; -static int testCompareHelper(const void *data) { +static int +testCompareHelper(const void *data) +{ + int result = -1; const struct testInfo *info = data; - char xml[PATH_MAX]; - char args[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/xml2sexprdata/xml2sexpr-%s.xml", - abs_srcdir, info->input); - snprintf(args, PATH_MAX, "%s/xml2sexprdata/xml2sexpr-%s.sexpr", - abs_srcdir, info->output); - return testCompareFiles(xml, args, info->version); -} + char *xml = NULL; + char *args = NULL; + + if (virAsprintf(&xml, "%s/xml2sexprdata/xml2sexpr-%s.xml", + abs_srcdir, info->input) < 0 || + virAsprintf(&args, "%s/xml2sexprdata/xml2sexpr-%s.sexpr", + abs_srcdir, info->output) < 0) { + goto cleanup; + } + result = testCompareFiles(xml, args, info->version); + +cleanup: + free(xml); + free(args); + + return result; +} static int mymain(int argc, char **argv) { int ret = 0; - char cwd[PATH_MAX]; progname = argv[0]; diff --git a/tests/xml2vmxtest.c b/tests/xml2vmxtest.c index a5fb4f7..1b58db8 100644 --- a/tests/xml2vmxtest.c +++ b/tests/xml2vmxtest.c @@ -11,13 +11,12 @@ # include "testutils.h" # include "vmx/vmx.h" -static char *progname = NULL; -static char *abs_srcdir = NULL; -static virCapsPtr caps = NULL; +static char *progname; +static char cwd[PATH_MAX]; +static char *abs_srcdir; +static virCapsPtr caps; static virVMXContext ctx; -# define MAX_FILE 4096 - static void testCapsInit(void) { @@ -71,18 +70,16 @@ static int testCompareFiles(const char *xml, const char *vmx, int virtualHW_version) { int result = -1; - char xmlData[MAX_FILE]; - char vmxData[MAX_FILE]; + char *xmlData = NULL; + char *vmxData = NULL; char *formatted = NULL; - char *xmlPtr = &(xmlData[0]); - char *vmxPtr = &(vmxData[0]); virDomainDefPtr def = NULL; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) { + if (virtTestLoadFile(xml, &xmlData) < 0) { goto failure; } - if (virtTestLoadFile(vmx, &vmxPtr, MAX_FILE) < 0) { + if (virtTestLoadFile(vmx, &vmxData) < 0) { goto failure; } @@ -106,6 +103,8 @@ testCompareFiles(const char *xml, const char *vmx, int virtualHW_version) result = 0; failure: + VIR_FREE(xmlData); + VIR_FREE(vmxData); VIR_FREE(formatted); virDomainDefFree(def); @@ -121,16 +120,25 @@ struct testInfo { static int testCompareHelper(const void *data) { + int result = -1; const struct testInfo *info = data; - char xml[PATH_MAX]; - char vmx[PATH_MAX]; + char *xml = NULL; + char *vmx = NULL; + + if (virAsprintf(&xml, "%s/xml2vmxdata/xml2vmx-%s.xml", abs_srcdir, + info->input) < 0 || + virAsprintf(&vmx, "%s/xml2vmxdata/xml2vmx-%s.vmx", abs_srcdir, + info->output) < 0) { + goto cleanup; + } + + result = testCompareFiles(xml, vmx, info->virtualHW_version); - snprintf(xml, PATH_MAX, "%s/xml2vmxdata/xml2vmx-%s.xml", abs_srcdir, - info->input); - snprintf(vmx, PATH_MAX, "%s/xml2vmxdata/xml2vmx-%s.vmx", abs_srcdir, - info->output); + cleanup: + VIR_FREE(xml); + VIR_FREE(vmx); - return testCompareFiles(xml, vmx, info->virtualHW_version); + return result; } static int @@ -201,7 +209,6 @@ static int mymain(int argc, char **argv) { int result = 0; - char cwd[PATH_MAX]; progname = argv[0]; -- 1.7.0.4 From laine at laine.org Mon Apr 25 07:05:51 2011 From: laine at laine.org (Laine Stump) Date: Mon, 25 Apr 2011 03:05:51 -0400 Subject: [libvirt] [PATCH] Make sure DNSMASQ_STATE_DIR exists In-Reply-To: <20110424080223.GA5669@bogon.sigxcpu.org> References: <20110424080223.GA5669@bogon.sigxcpu.org> Message-ID: <4DB51D4F.8020005@laine.org> On 04/24/2011 04:02 AM, Guido G?nther wrote: > Hi, > > otherwise the directory returned by networkDnsmasqLeaseFileName will not > be created if ipdef->nhosts == 0 in networkBuildDnsmasqArgv. > > O.k. to apply? > > Cheers, > -- Guido > > --- > src/network/bridge_driver.c | 7 +++++++ > 1 files changed, 7 insertions(+), 0 deletions(-) > > diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c > index 8b5c1b6..ed78710 100644 > --- a/src/network/bridge_driver.c > +++ b/src/network/bridge_driver.c > @@ -662,6 +662,13 @@ networkStartDhcpDaemon(virNetworkObjPtr network) > goto cleanup; > } > > + if ((err = virFileMakePath(DNSMASQ_STATE_DIR)) != 0) { > + virReportSystemError(err, > + _("cannot create directory %s"), > + DNSMASQ_STATE_DIR); > + goto cleanup; > + } > + > cmd = virCommandNew(DNSMASQ); > if (networkBuildDnsmasqArgv(network, ipdef, pidfile, cmd)< 0) { > goto cleanup; ACK. From laine at laine.org Mon Apr 25 07:17:40 2011 From: laine at laine.org (Laine Stump) Date: Mon, 25 Apr 2011 03:17:40 -0400 Subject: [libvirt] [PATCHv2] build: use gnulib passfd for simpler SCM_RIGHTS code In-Reply-To: <1303420621-25090-1-git-send-email-eblake@redhat.com> References: <1303330531-25818-1-git-send-email-eblake@redhat.com> <1303420621-25090-1-git-send-email-eblake@redhat.com> Message-ID: <4DB52014.50209@laine.org> On 04/21/2011 05:17 PM, Eric Blake wrote: > * .gnulib: Update to latest for passfd fixes. > * bootstrap.conf (gnulib_modules): Add passfd. > * src/util/util.c (virFileOpenAs): Simplify. > --- > > Now that the mingw side of passfd is fixed in gnulib, I can > resubmit this patch. > > v2: update .gnulib, no other changes > > .gnulib | 2 +- > bootstrap.conf | 1 + > src/util/util.c | 38 ++++++++------------------------------ > 3 files changed, 10 insertions(+), 31 deletions(-) > > diff --git a/.gnulib b/.gnulib > index fb79969..5a9e46a 160000 > --- a/.gnulib > +++ b/.gnulib > @@ -1 +1 @@ > -Subproject commit fb799692f5bb43310424977e0ca15599fc68d776 > +Subproject commit 5a9e46ab46042f007426c1e06b836cf5608d8d4a > diff --git a/bootstrap.conf b/bootstrap.conf > index 293f86e..3b3a90f 100644 > --- a/bootstrap.conf > +++ b/bootstrap.conf > @@ -52,6 +52,7 @@ mkstemps > mktempd > netdb > nonblocking > +passfd > perror > physmem > pipe-posix > diff --git a/src/util/util.c b/src/util/util.c > index d4d2610..de4e3b3 100644 > --- a/src/util/util.c > +++ b/src/util/util.c > @@ -78,6 +78,7 @@ > #include "files.h" > #include "command.h" > #include "nonblocking.h" > +#include "passfd.h" > > #ifndef NSIG > # define NSIG 32 > @@ -1480,11 +1481,6 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, > int waitret, status, ret = 0; > int fd = -1; > int pair[2] = { -1, -1 }; > - struct msghdr msg; > - struct cmsghdr *cmsg; > - char buf[CMSG_SPACE(sizeof(fd))]; > - char dummy = 0; > - struct iovec iov; > int forkRet; > > if ((!(flags& VIR_FILE_OPEN_AS_UID)) > @@ -1506,18 +1502,6 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, > return ret; > } > > - memset(&msg, 0, sizeof(msg)); > - iov.iov_base =&dummy; > - iov.iov_len = 1; > - msg.msg_iov =&iov; > - msg.msg_iovlen = 1; > - msg.msg_control = buf; > - msg.msg_controllen = sizeof(buf); > - cmsg = CMSG_FIRSTHDR(&msg); > - cmsg->cmsg_level = SOL_SOCKET; > - cmsg->cmsg_type = SCM_RIGHTS; > - cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); > - > forkRet = virFork(&pid); > > if (pid< 0) { > @@ -1529,26 +1513,20 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, > VIR_FORCE_CLOSE(pair[1]); > > do { > - ret = recvmsg(pair[0],&msg, 0); > + ret = recvfd(pair[0], 0); > } while (ret< 0&& errno == EINTR); > > - if (ret< 0) { > + if (ret< 0&& errno != EACCES) { > ret = -errno; > VIR_FORCE_CLOSE(pair[0]); > while ((waitret = waitpid(pid, NULL, 0) == -1) > && (errno == EINTR)); > goto parenterror; > + } else { > + fd = ret; > } What if errno == EACCES? Will we be getting all the error recovery we need in the caller? > VIR_FORCE_CLOSE(pair[0]); > > - /* See if fd was transferred. */ > - cmsg = CMSG_FIRSTHDR(&msg); > - if (cmsg&& cmsg->cmsg_len == CMSG_LEN(sizeof(fd))&& > - cmsg->cmsg_level == SOL_SOCKET&& > - cmsg->cmsg_type == SCM_RIGHTS) { > - memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); > - } > - > /* wait for child to complete, and retrieve its exit code */ > while ((waitret = waitpid(pid,&status, 0) == -1) > && (errno == EINTR)); > @@ -1557,12 +1535,14 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, > virReportSystemError(errno, > _("failed to wait for child creating '%s'"), > path); > + VIR_FORCE_CLOSE(fd); > goto parenterror; > } > if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == -EACCES || > fd == -1) { > /* fall back to the simpler method, which works better in > * some cases */ > + VIR_FORCE_CLOSE(fd); > return virFileOpenAsNoFork(path, openflags, mode, uid, gid, flags); > } > if (!ret) > @@ -1627,10 +1607,9 @@ parenterror: > path, mode); > goto childerror; > } > - memcpy(CMSG_DATA(cmsg),&fd, sizeof(fd)); > > do { > - ret = sendmsg(pair[1],&msg, 0); > + ret = sendfd(pair[1], fd); > } while (ret< 0&& errno == EINTR); > > if (ret< 0) { > @@ -1638,7 +1617,6 @@ parenterror: > goto childerror; > } > > - ret = 0; > childerror: > /* ret tracks -errno on failure, but exit value must be positive. > * If the child exits with EACCES, then the parent tries again. */ From laine at laine.org Mon Apr 25 07:18:09 2011 From: laine at laine.org (Laine Stump) Date: Mon, 25 Apr 2011 03:18:09 -0400 Subject: [libvirt] [PATCH] build: fix 32-bit test failure In-Reply-To: <1303395981-26718-1-git-send-email-eblake@redhat.com> References: <1303395981-26718-1-git-send-email-eblake@redhat.com> Message-ID: <4DB52031.30105@laine.org> On 04/21/2011 10:26 AM, Eric Blake wrote: > ARRAY_CARDINALITY is typed as size_t, not long; this matters on 32-bit > platforms: > > hashtest.c: In function 'testHashRemoveForEach': > hashtest.c:114: error: format '%lu' expects type 'long unsigned int', but argument 4 has type 'unsigned int' [-Wformat] > > * tests/hashtest.c (testHashRemoveForEach): Use correct format. > --- > > Pushing under the build-breaker rule. > > tests/hashtest.c | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/tests/hashtest.c b/tests/hashtest.c > index dff0181..722b44c 100644 > --- a/tests/hashtest.c > +++ b/tests/hashtest.c > @@ -112,7 +112,7 @@ testHashRemoveForEach(const void *data) > if (count != ARRAY_CARDINALITY(uuids)) { > if (virTestGetVerbose()) { > testError("\nvirHashForEach didn't go through all entries," > - " %d != %lu\n", > + " %d != %zu\n", > count, ARRAY_CARDINALITY(uuids)); > } > goto cleanup; ACK From rjones at redhat.com Mon Apr 25 08:27:04 2011 From: rjones at redhat.com (Richard W.M. Jones) Date: Mon, 25 Apr 2011 09:27:04 +0100 Subject: [libvirt] libvirt spice command line appears to be incorrect (was: Re: [virt-tools-list] vdagent does not start with domain defined by virt-manager 0.8.7) In-Reply-To: References: Message-ID: <20110425082704.GA29431@amd.home.annexia.org> [Copying this to libvir-list] On Mon, Apr 25, 2011 at 01:07:37AM +0400, Emre Erenoglu wrote: > Hi, > > I'm the package maintainer for virt-manager and related packages for Pardus > distribution. While testing the latest libvirt, virtinst & virt-manager > packages, I've come across a strange issue and I would like to get your > valuable opinion. > > I add all spice related devices and everything works good, except the > vdagent inside the windows xp guest. The virtio serial driver is loaded > correctly. As I track down the issue, I found out that libvirt is starting > qemu-kvm with parameters which do not match the ones adviced by the spice > people. Please see below email discussion with them on this. The offending > line seems to be the chardev parameter. qemu-kvm is started by virt-manager > with the following parameter for chardev: > > -chardev null,id=channel0 > > and the full spice related parameters are: > > -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x8 -chardev > null,id=channel0 -device > virtserialport,bus=virtio-serial0.0,nr=0,chardev=channel0,name=com.redhat.spice.0 > -usb -device usb-tablet,id=input0 -spice > port=5900,addr=127.0.0.1,disable-ticketing -vga qxl -device > qxl,id=video1,bus=pci.0,addr=0x7 > > while spice people adviced: > > -chardev spicevmc,id=channel0,name=vdagent > > and the rest of the parameters to match it. See below mail on the details. > I don't know if this is really the issue, but I also recognize the following > inside the domain XML: > > > >

    > > > the "channel type" is listed as "null", while I assume it should have been > listed as "spicevmc". (not sure of this, I saw this in some other > websites). When I edit the domain xml with virsh edit, it saves my changes > but the "null" stays the same how many times I try to change it. > > Please note that I've applied the following patches to virtinst 0.500.6: > > constrain-spicevmc-usage-correct.patch > virtinst-fix-channel-parse.patch > virtinst-spicevmc-fixes.patch > > which I obtained from the git. I also patched virt-manager 0.8.7 with the > following I obtained from the git: > > chardev-hide-unsupported-params-for-selected-type.patch > only-show-relevant-char-device-fields.patch > show-char-device-target-name.patch > chardev-propose-to-add-remove-spice-agent.patch > allow-setting-char-device-target-name.patch > fix-adding-removing-channel-device.patch > > Any idea what I might be missing to get the vdagent run inside the windows > guest? > > Many thanks, > > Emre Erenoglu > > ---------- Forwarded message ---------- > From: Marian Krcmarik > Date: Mon, Apr 18, 2011 at 5:56 PM > Subject: Re: [Spice-devel] vdagent does not start > To: Emre Erenoglu > Cc: spice-devel at lists.freedesktop.org > > > > > ----- Original Message ----- > > From: "Emre Erenoglu" > > To: spice-devel at lists.freedesktop.org > > Sent: Sunday, April 17, 2011 1:10:16 PM > > Subject: [Spice-devel] vdagent does not start > > Dear Developers, > > > > I have a virtual XP system with the spice channel enabled through the > > serial port. The command line that runs qemu has (reduced): > > > > -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x8 > > -chardev null,id=channel0 -device > > > virtserialport,bus=virtio-serial0.0,nr=0,chardev=channel0,name=com.redhat.spice.0 > > -usb -device usb-tablet,id=input0 -spice > > port=5900,addr=127.0.0.1,disable-ticketing -vga qxl -device > > qxl,id=video1,bus=pci.0,addr=0x7 > > I think you may need to specify chardev for spice so I would modify: > > -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x8 -chardev > spicevmc,id=channel0,name=vdagent -device > virtserialport,bus=virtio-serial0.0,nr=0,chardev=channel0,name=com.redhat.spice.0 > -usb -device usb-tablet,id=input0 -spice > port=5900,addr=127.0.0.1,disable-ticketing -vga qxl -device > qxl,id=video1,bus=pci.0,addr=0x7 > > with agent and virtio-serial driver installed on guest. > > > > However, the vdagent services does not start. when I give it a start > > control, it reports to start then stop immediately. Here are the logs > > I've found: > > > > -- > Emre -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming blog: http://rwmj.wordpress.com Fedora now supports 80 OCaml packages (the OPEN alternative to F#) http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora From matthias.bolte at googlemail.com Mon Apr 25 09:41:20 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 25 Apr 2011 11:41:20 +0200 Subject: [libvirt] [PATCH] esx: Fix dynamic dispatch for CastFromAnyType functions Message-ID: <20110425094120.GA15113@sbox> This was broken by the refactoring in ac1e6586ec75. It resulted in a segfault for 'virsh vol-dumpxml' and related volume functions. Before the refactoring all users of the ESX_VI__TEMPLATE__DISPATCH macro dispatched on the item type, as the item is the input to all those functions. Commit ac1e6586ec75 made the dynamically dispatched CastFromAnyType functions use this macro too, but this functions dispatched on the actual type of the AnyType object. The item is the output of the CastFromAnyType functions. This difference was missed in the refactoring, making CastFromAnyType functions dereferencing the item pointer that is NULL at the time of the dispatch. --- src/esx/esx_vi_types.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c index dd83954..6a2d5cf 100644 --- a/src/esx/esx_vi_types.c +++ b/src/esx/esx_vi_types.c @@ -533,8 +533,8 @@ * Macros to implement dynamic dispatched functions */ -#define ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, _error_return) \ - switch (item->_type) { \ +#define ESX_VI__TEMPLATE__DISPATCH(_object, __type, _dispatch, _error_return) \ + switch ((_object)->_type) { \ _dispatch \ \ case esxVI_Type_##__type: \ @@ -543,7 +543,7 @@ default: \ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ _("Call to %s for unexpected type '%s'"), __FUNCTION__, \ - esxVI_Type_ToString(item->_type)); \ + esxVI_Type_ToString((_object)->_type)); \ return _error_return; \ } @@ -585,7 +585,7 @@ #define ESX_VI__TEMPLATE__DYNAMIC_FREE(__type, _dispatch, _body) \ ESX_VI__TEMPLATE__FREE(__type, \ - ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, /* nothing */) \ + ESX_VI__TEMPLATE__DISPATCH(item, __type, _dispatch, /* nothing */) \ _body) @@ -618,14 +618,14 @@ #define ESX_VI__TEMPLATE__DYNAMIC_CAST_FROM_ANY_TYPE(__type, _dispatch) \ ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE_EXTRA(__type, esxVI_##__type, \ - ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, -1), \ + ESX_VI__TEMPLATE__DISPATCH(anyType, __type, _dispatch, -1), \ /* nothing */) #define ESX_VI__TEMPLATE__DYNAMIC_SERIALIZE(__type, _dispatch, _serialize) \ ESX_VI__TEMPLATE__SERIALIZE_EXTRA(__type, \ - ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, -1), \ + ESX_VI__TEMPLATE__DISPATCH(item, __type, _dispatch, -1), \ _serialize) -- 1.7.0.4 From jyang at redhat.com Mon Apr 25 09:41:44 2011 From: jyang at redhat.com (Osier Yang) Date: Mon, 25 Apr 2011 17:41:44 +0800 Subject: [libvirt] [PATCH v2] qemu: Unlink managed state file when a domain is undefined In-Reply-To: <4DAEDCD0.6040201@redhat.com> References: <4DAEDCD0.6040201@redhat.com> Message-ID: <1303724504-28718-1-git-send-email-jyang@redhat.com> The managed state file is not useful anymore after the domain is undefined, and perhaps cause confusion. E.g. define & start a domain which has same name but different UUID with previous undefined domain later. v1 - v2: * Try to delete the managed state file before delete domain config file, and goto fail if it failed to delete it. --- src/qemu/qemu_driver.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 771678e..4c5edd4 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3738,6 +3738,7 @@ static int qemudDomainUndefine(virDomainPtr dom) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; virDomainEventPtr event = NULL; + char *managed_save = NULL; int ret = -1; qemuDriverLock(driver); @@ -3763,6 +3764,15 @@ static int qemudDomainUndefine(virDomainPtr dom) { goto cleanup; } + if (!(managed_save = qemuDomainManagedSavePath(driver, vm))) + goto cleanup; + + if (virFileExists(managed_save) && (unlink(managed_save) < 0)) { + virReportSystemError(errno, "%s", + _("Failed to delete managed state file")); + goto cleanup; + } + if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0) goto cleanup; -- 1.7.4 From jyang at redhat.com Mon Apr 25 10:28:35 2011 From: jyang at redhat.com (Osier Yang) Date: Mon, 25 Apr 2011 18:28:35 +0800 Subject: [libvirt] [PATCH] util: Initialize hooks at daemon shutdown if no hooks defined Message-ID: <1303727315-20801-1-git-send-email-jyang@redhat.com> We support to initialize the hooks at daemon reload if there is no hooks script is defined, should we also support initialize the hooks at daemon shutdown if no hooks is defined? To address bz: https://bugzilla.redhat.com/show_bug.cgi?id=688859 --- src/util/hooks.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/src/util/hooks.c b/src/util/hooks.c index a409d77..30e20ac 100644 --- a/src/util/hooks.c +++ b/src/util/hooks.c @@ -209,7 +209,8 @@ virHookCall(int driver, const char *id, int op, int sub_op, const char *extra, */ if ((virHooksFound == -1) || ((driver == VIR_HOOK_DRIVER_DAEMON) && - (op == VIR_HOOK_DAEMON_OP_RELOAD))) + (op == VIR_HOOK_DAEMON_OP_RELOAD || + op == VIR_HOOK_DAEMON_OP_SHUTDOWN))) virHookInitialize(); if ((virHooksFound & (1 << driver)) == 0) -- 1.7.4 From matthias.bolte at googlemail.com Mon Apr 25 11:32:43 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 25 Apr 2011 13:32:43 +0200 Subject: [libvirt] [PATCH] esx: Fix dynamic dispatch for CastFromAnyType functions In-Reply-To: <20110425094120.GA15113@sbox> References: <20110425094120.GA15113@sbox> Message-ID: 2011/4/25 Matthias Bolte : > This was broken by the refactoring in ac1e6586ec75. It resulted in a > segfault for 'virsh vol-dumpxml' and related volume functions. > Actually that patch doesn't fix the problem correctly. It just turns the segfault into an error message. Here's v2 that really fixes the problem. Note the important difference between anyType->_type and anyType->type :) Matthias -------------- next part -------------- A non-text attachment was scrubbed... Name: 0002-esx-Fix-dynamic-dispatch-for-CastFromAnyType-functio.patch Type: text/x-patch Size: 3576 bytes Desc: not available URL: From matthias.bolte at googlemail.com Mon Apr 25 11:36:14 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 25 Apr 2011 13:36:14 +0200 Subject: [libvirt] [PATCH] Add virDomainEventRebootNew Message-ID: <20110425113614.GA8817@sbox> This will be used in the ESX driver event handling. --- src/conf/domain_event.c | 8 ++++++++ src/conf/domain_event.h | 1 + 2 files changed, 9 insertions(+), 0 deletions(-) diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index f0380d3..688bf6c 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -572,11 +572,19 @@ virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int de return virDomainEventNew(def->id, def->name, def->uuid, type, detail); } +virDomainEventPtr virDomainEventRebootNew(int id, const char *name, + const unsigned char *uuid) +{ + return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT, + id, name, uuid); +} + virDomainEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom) { return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT, dom->id, dom->name, dom->uuid); } + virDomainEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj) { return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT, diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h index e28293d..c03a159 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -112,6 +112,7 @@ virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detai virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail); virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail); +virDomainEventPtr virDomainEventRebootNew(int id, const char *name, const unsigned char *uuid); virDomainEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom); virDomainEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj); -- 1.7.0.4 From streidav at fel.cvut.cz Mon Apr 25 13:14:58 2011 From: streidav at fel.cvut.cz (David Streibl) Date: Mon, 25 Apr 2011 15:14:58 +0200 Subject: [libvirt] [libvirt-php] Work on ./example Message-ID: Hello, as part of my student project I am working on simple web interface which would support multiple virtualisation platforms. This of course led me to libvirt and libvirt-php more specificly. Right now I'm using modfied code of exapme Libvirt class and the plan is: - add phpdoc - refactor it to match libvirt convetion (get_domain_someting -> dmain_get_something) - split Libvirt to subclasses for domain, connection, network, storage (not completly sure if it is good idea) - add few unit tests (dont know about time and usefulness of this) Would it be welcomed if I send to whole think or even parts of it as patches to libvirt-php/example? Thanks for any reply and sorry for my english, David From eblake at redhat.com Mon Apr 25 14:21:06 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 25 Apr 2011 08:21:06 -0600 Subject: [libvirt] [PATCHv2] build: use gnulib passfd for simpler SCM_RIGHTS code In-Reply-To: <4DB52014.50209@laine.org> References: <1303330531-25818-1-git-send-email-eblake@redhat.com> <1303420621-25090-1-git-send-email-eblake@redhat.com> <4DB52014.50209@laine.org> Message-ID: <4DB58352.40608@redhat.com> On 04/25/2011 01:17 AM, Laine Stump wrote: >> @@ -1529,26 +1513,20 @@ virFileOpenAs(const char *path, int openflags, >> mode_t mode, >> VIR_FORCE_CLOSE(pair[1]); >> >> do { >> - ret = recvmsg(pair[0],&msg, 0); >> + ret = recvfd(pair[0], 0); >> } while (ret< 0&& errno == EINTR); ret == -1 and errno == EACCES on failure to transfer fd... >> >> - if (ret< 0) { >> + if (ret< 0&& errno != EACCES) { >> ret = -errno; >> VIR_FORCE_CLOSE(pair[0]); >> while ((waitret = waitpid(pid, NULL, 0) == -1) >> && (errno == EINTR)); >> goto parenterror; >> + } else { >> + fd = ret; >> } so now fd == -1... > if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == -EACCES || > fd == -1) { > /* fall back to the simpler method, which works better in > * some cases */ > return virFileOpenAsNoFork(path, openflags, mode, uid, gid, flags); > } so this uses the fallback code, regardless of child exit status, and we also ensured that the child got reaped. > > What if errno == EACCES? Will we be getting all the error recovery we > need in the caller? Yes. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From crobinso at redhat.com Mon Apr 25 14:28:22 2011 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 25 Apr 2011 10:28:22 -0400 Subject: [libvirt] [virt-tools-list] libvirt spice command line appears to be incorrect In-Reply-To: <20110425082704.GA29431@amd.home.annexia.org> References: <20110425082704.GA29431@amd.home.annexia.org> Message-ID: <4DB58506.60205@redhat.com> On 04/25/2011 04:27 AM, Richard W.M. Jones wrote: > [Copying this to libvir-list] > > On Mon, Apr 25, 2011 at 01:07:37AM +0400, Emre Erenoglu wrote: >> Hi, >> >> I'm the package maintainer for virt-manager and related packages for Pardus >> distribution. While testing the latest libvirt, virtinst & virt-manager >> packages, I've come across a strange issue and I would like to get your >> valuable opinion. >> >> I add all spice related devices and everything works good, except the >> vdagent inside the windows xp guest. The virtio serial driver is loaded >> correctly. As I track down the issue, I found out that libvirt is starting >> qemu-kvm with parameters which do not match the ones adviced by the spice >> people. Please see below email discussion with them on this. The offending >> line seems to be the chardev parameter. qemu-kvm is started by virt-manager >> with the following parameter for chardev: >> >> -chardev null,id=channel0 >> >> and the full spice related parameters are: >> >> -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x8 -chardev >> null,id=channel0 -device >> virtserialport,bus=virtio-serial0.0,nr=0,chardev=channel0,name=com.redhat.spice.0 >> -usb -device usb-tablet,id=input0 -spice >> port=5900,addr=127.0.0.1,disable-ticketing -vga qxl -device >> qxl,id=video1,bus=pci.0,addr=0x7 >> >> while spice people adviced: >> >> -chardev spicevmc,id=channel0,name=vdagent >> >> and the rest of the parameters to match it. See below mail on the details. >> I don't know if this is really the issue, but I also recognize the following >> inside the domain XML: >> >> >> >>
    >> >> >> the "channel type" is listed as "null", while I assume it should have been >> listed as "spicevmc". (not sure of this, I saw this in some other >> websites). When I edit the domain xml with virsh edit, it saves my changes >> but the "null" stays the same how many times I try to change it. >> >> Please note that I've applied the following patches to virtinst 0.500.6: >> >> constrain-spicevmc-usage-correct.patch >> virtinst-fix-channel-parse.patch >> virtinst-spicevmc-fixes.patch >> >> which I obtained from the git. I also patched virt-manager 0.8.7 with the >> following I obtained from the git: >> >> chardev-hide-unsupported-params-for-selected-type.patch >> only-show-relevant-char-device-fields.patch >> show-char-device-target-name.patch >> chardev-propose-to-add-remove-spice-agent.patch >> allow-setting-char-device-target-name.patch >> fix-adding-removing-channel-device.patch >> >> Any idea what I might be missing to get the vdagent run inside the windows >> guest? >> >> Many thanks, >> >> Emre Erenoglu What libvirt version are you using? spicevmc requires libvirt 0.8.8. However if libvirt is silently reverting to 'null' it's a bug either way. - Cole From eblake at redhat.com Mon Apr 25 14:29:13 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 25 Apr 2011 08:29:13 -0600 Subject: [libvirt] [PATCH v2] qemu: Unlink managed state file when a domain is undefined In-Reply-To: <1303724504-28718-1-git-send-email-jyang@redhat.com> References: <4DAEDCD0.6040201@redhat.com> <1303724504-28718-1-git-send-email-jyang@redhat.com> Message-ID: <4DB58539.7060600@redhat.com> On 04/25/2011 03:41 AM, Osier Yang wrote: > The managed state file is not useful anymore after the domain is > undefined, and perhaps cause confusion. E.g. define & start a domain > which has same name but different UUID with previous undefined > domain later. > > v1 - v2: > * Try to delete the managed state file before delete domain > config file, and goto fail if it failed to delete it. > --- > src/qemu/qemu_driver.c | 10 ++++++++++ > 1 files changed, 10 insertions(+), 0 deletions(-) Ouch. virDomainUndefine doesn't have a flags argument. But this is changing behavior in a user-visible manner (arguably for the better, but any change is risky) We have two options: 1. Proceed with the change: virDomainUndefine removes all associated snapshot data; but this is a silent change in behavior 2. Add a new API: virDomainUndefineFlags; flag 0 leaves snapshot data around (but warns), flag VIR_DOMAIN_UNDEFINE_ALL_ASSOCIATED_DATA (or some better name) guarantees that snapshots are also removed Being an API question, I think danpb might need to weigh in before we make a change. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 25 14:45:20 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 25 Apr 2011 08:45:20 -0600 Subject: [libvirt] [PATCH v2] qemu: Unlink managed state file when a domain is undefined In-Reply-To: <4DB58539.7060600@redhat.com> References: <4DAEDCD0.6040201@redhat.com> <1303724504-28718-1-git-send-email-jyang@redhat.com> <4DB58539.7060600@redhat.com> Message-ID: <4DB58900.7080805@redhat.com> On 04/25/2011 08:29 AM, Eric Blake wrote: > On 04/25/2011 03:41 AM, Osier Yang wrote: >> The managed state file is not useful anymore after the domain is >> undefined, and perhaps cause confusion. E.g. define & start a domain >> which has same name but different UUID with previous undefined >> domain later. >> >> v1 - v2: >> * Try to delete the managed state file before delete domain >> config file, and goto fail if it failed to delete it. >> --- >> src/qemu/qemu_driver.c | 10 ++++++++++ >> 1 files changed, 10 insertions(+), 0 deletions(-) > > Ouch. virDomainUndefine doesn't have a flags argument. But this is > changing behavior in a user-visible manner (arguably for the better, but > any change is risky) > > We have two options: > > 1. Proceed with the change: virDomainUndefine removes all associated > snapshot data; but this is a silent change in behavior > > 2. Add a new API: virDomainUndefineFlags; flag 0 leaves snapshot data > around (but warns), flag VIR_DOMAIN_UNDEFINE_ALL_ASSOCIATED_DATA (or > some better name) guarantees that snapshots are also removed Option 3: no silent deletion on undefine, and no new API, but make virDomainUndefine fail if the managed state file exists. The user is then responsible for using virDomainHasManagedSaveImage and virDomainManagedSaveRemove prior to undefining a domain. But whereas with option 1, people might complain that we removed the managed state file, now with option 3 people might complain that we prevent the undefine of a domain. Which leads to: Option 4: Add virDomainUndefineFlags(). virDomainUndefineFlags(,0) refuses to undefine a domain if state exists, while virDomainUndefineFlags(,VIR_DOMAIN_UNDEFINE_FORCE) proceeds to undefine the domain even if a managed state file exists. We'd still have to decide whether virDomainUndefine maps to Flags(,0) or Flags(,FORCE), but at least the default option is safer than in option 2 where you have to use a flag to get the safe behavior. At any rate, at the virsh level we can add a flag that maps into two API calls as necessary to use virDomainManagedSaveRemove prior to virDomainUndefine, regardless of what we do at the API level. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 25 16:08:22 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 25 Apr 2011 10:08:22 -0600 Subject: [libvirt] [PATCHv2] threads: add one-time initialization support In-Reply-To: References: <1303339419-13159-1-git-send-email-eblake@redhat.com> <1303529908-32330-1-git-send-email-eblake@redhat.com> Message-ID: <4DB59C76.5010009@redhat.com> On 04/24/2011 04:14 AM, Matthias Bolte wrote: > > Compared to the gnulib lock module version, this one is less complex > and I don't get why gnulib uses 3 states for the init and complete > variables and an additional lock object. The only reason could be to > minimize the time busy waiting in the while loop. It may also be that the gnulib module was trying to worry about cancellation points, but libvirt isn't (yet) using cancellation points. That does indeed require more complexity to handle an init callback that gets cancelled, where another thread then has to take over the one-shot initiailization. > >> + >> +struct virOnceControl { >> + long init; /* 0 at startup, > 0 if init has started */ >> + volatile long complete; /* 0 until first thread completes callback */ >> +}; > > MSDN docs about InterlockedIncrement suggest that init should be volatile too. > > ACK, with init marked volatile. Thanks, and pushed with that modification. I guess that also means that the virObject patches should also be marking its reference-counter variable as volatile. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 25 16:38:17 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 25 Apr 2011 10:38:17 -0600 Subject: [libvirt] [PATCH] util: warn when passing a non-pointer to VIR_FREE In-Reply-To: References: <20110422170413.GC3219@teriyaki.redhat.com> <1303496484-17313-1-git-send-email-cfergeau@redhat.com> <4DB210F9.5040503@redhat.com> Message-ID: <4DB5A379.50506@redhat.com> On 04/24/2011 04:17 AM, Matthias Bolte wrote: >> So how about: >> >> diff --git i/src/util/memory.h w/src/util/memory.h >> index 66b4c42..d77a295 100644 >> --- i/src/util/memory.h >> +++ w/src/util/memory.h >> @@ -1,7 +1,7 @@ >> /* >> * memory.c: safer memory allocation >> * >> - * Copyright (C) 2010 Red Hat, Inc. >> + * Copyright (C) 2010-2011 Red Hat, Inc. >> * Copyright (C) 2008 Daniel P. Berrange >> * >> * This library is free software; you can redistribute it and/or >> @@ -197,7 +197,11 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); >> * Free the memory stored in 'ptr' and update to point >> * to NULL. >> */ >> -# define VIR_FREE(ptr) virFree(&(ptr)) >> +/* The ternary ensures that ptr is a pointer and not an integer type, >> + * while evaluating ptr only once. For now, we intentionally cast >> + * away const, since a number of callers safely pass const char *. >> + */ >> +# define VIR_FREE(ptr) virFree((void *) (1 ? (const void *) &(ptr) : >> (ptr))) >> >> >> # if TEST_OOM >> > > ACK, to your improved version. Pushed with this commit message: commit 90d761eeb26c9619571b68a8863b8425a33555d6 Author: Eric Blake Date: Fri Apr 22 20:15:50 2011 -0600 build: make VIR_FREE do some type checking We can exploit the fact that gcc warns about int-to-pointer conversion in ternary cond?(void*):(int) in order to prevent future mistakes of calling VIR_FREE on a scalar lvalue. For example, between commits 158ba873 and 802e2df, we would have had this warning: cc1: warnings being treated as errors remote.c: In function 'remoteDispatchListNetworks': remote.c:3684:70: error: pointer/integer type mismatch in conditional expression There are still a number of places that malloc into a const char*; while it would probably be worth scrubbing them to use char* instead, that is a separate patch, so we have to cast away const in VIR_FREE for now. * src/util/memory.h (VIR_FREE): Make gcc warn about integers. Iteratively developed from a patch by Christophe Fergeau. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 25 16:50:54 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 25 Apr 2011 10:50:54 -0600 Subject: [libvirt] [PATCH] Add virDomainEventRebootNew In-Reply-To: <20110425113614.GA8817@sbox> References: <20110425113614.GA8817@sbox> Message-ID: <4DB5A66E.1050401@redhat.com> On 04/25/2011 05:36 AM, Matthias Bolte wrote: > This will be used in the ESX driver event handling. > --- > src/conf/domain_event.c | 8 ++++++++ > src/conf/domain_event.h | 1 + > 2 files changed, 9 insertions(+), 0 deletions(-) > > diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c > index f0380d3..688bf6c 100644 > --- a/src/conf/domain_event.c > +++ b/src/conf/domain_event.c > @@ -572,11 +572,19 @@ virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int de > return virDomainEventNew(def->id, def->name, def->uuid, type, detail); > } > > +virDomainEventPtr virDomainEventRebootNew(int id, const char *name, > + const unsigned char *uuid) > +{ > + return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT, > + id, name, uuid); ACK. Do you also need to add it to src/libvirt_private.syms? -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 25 16:54:47 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 25 Apr 2011 10:54:47 -0600 Subject: [libvirt] [PATCH] Fix small memory leaks in config parsing related functions In-Reply-To: <20110424222623.GA16901@sbox> References: <20110424222623.GA16901@sbox> Message-ID: <4DB5A757.5020100@redhat.com> On 04/24/2011 04:26 PM, Matthias Bolte wrote: > Found by 'make -C tests valgrind'. > > xen_xm.c: Dummy allocation via virDomainChrDefNew is directly > overwritten and lost. Free 'script' in success path too. > > vmx.c: Free virtualDev_string in success path too. > > domain_conf.c: Free compression in success path too. > --- > src/conf/domain_conf.c | 1 + > src/vmx/vmx.c | 16 +++++++++------- > src/xenxs/xen_xm.c | 3 +-- > 3 files changed, 11 insertions(+), 9 deletions(-) ACK to all three fixes. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Mon Apr 25 16:57:23 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 25 Apr 2011 10:57:23 -0600 Subject: [libvirt] [PATCH] tests: Lower stack usage below 4096 bytes In-Reply-To: <20110424222652.GA16936@sbox> References: <20110424222652.GA16936@sbox> Message-ID: <4DB5A7F3.2080700@redhat.com> On 04/24/2011 04:26 PM, Matthias Bolte wrote: > Make virtTestLoadFile allocate the buffer to read the file into. > > Fix logic error in virtTestLoadFile, stop reading on the an empty line. > > Use virFileReadLimFD in virtTestCaptureProgramOutput. > --- > +++ b/tests/commandhelper.c > @@ -99,8 +99,8 @@ int main(int argc, char **argv) { > } > > fprintf(log, "DAEMON:%s\n", getpgrp() == getsid(0) ? "yes" : "no"); > - char cwd[1024]; > - if (!getcwd(cwd, sizeof(cwd))) > + char *cwd = NULL; > + if (!(cwd = getcwd(NULL, 0))) Ouch. This is not portable to POSIX, and while gnulib can guarantee that it works, the current gnulib getcwd module is GPL (and relies on openat, which is a rather heavy-weight replacement!). I'm going to work on a gnulib module getcwd-lgpl which doesn't fix all the known bugs in getcwd, but at least guarantees that getcwd(NULL,0) will malloc insofar as the underlying getcwd is not buggy; we'll need to import that into libvirt before applying the rest of this patch. I haven't closely reviewed the rest of this patch yet, but like the general idea once we have getcwd sorted out. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Mon Apr 25 17:04:29 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 25 Apr 2011 19:04:29 +0200 Subject: [libvirt] [PATCH] tests: Lower stack usage below 4096 bytes In-Reply-To: <4DB5A7F3.2080700@redhat.com> References: <20110424222652.GA16936@sbox> <4DB5A7F3.2080700@redhat.com> Message-ID: 2011/4/25 Eric Blake : > On 04/24/2011 04:26 PM, Matthias Bolte wrote: >> Make virtTestLoadFile allocate the buffer to read the file into. >> >> Fix logic error in virtTestLoadFile, stop reading on the an empty line. >> >> Use virFileReadLimFD in virtTestCaptureProgramOutput. >> --- >> +++ b/tests/commandhelper.c >> @@ -99,8 +99,8 @@ int main(int argc, char **argv) { >> ? ? ?} >> >> ? ? ?fprintf(log, "DAEMON:%s\n", getpgrp() == getsid(0) ? "yes" : "no"); >> - ? ?char cwd[1024]; >> - ? ?if (!getcwd(cwd, sizeof(cwd))) >> + ? ?char *cwd = NULL; >> + ? ?if (!(cwd = getcwd(NULL, 0))) > > Ouch. ?This is not portable to POSIX, and while gnulib can guarantee > that it works, the current gnulib getcwd module is GPL (and relies on > openat, which is a rather heavy-weight replacement!). > > I'm going to work on a gnulib module getcwd-lgpl which doesn't fix all > the known bugs in getcwd, but at least guarantees that getcwd(NULL,0) > will malloc insofar as the underlying getcwd is not buggy; we'll need to > import that into libvirt before applying the rest of this patch. > > I haven't closely reviewed the rest of this patch yet, but like the > general idea once we have getcwd sorted out. > Oops. At first I used getcwd(NULL, 0) to replace the getcwd(cwd, sizeof(cwd)) calls in the main functions, but then decided to just move the cwd buffer to global scope instead. I just missed this one in the second rewrite round. Matthias From matthias.bolte at googlemail.com Mon Apr 25 17:06:33 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 25 Apr 2011 19:06:33 +0200 Subject: [libvirt] [PATCH] tests: Lower stack usage below 4096 bytes In-Reply-To: References: <20110424222652.GA16936@sbox> <4DB5A7F3.2080700@redhat.com> Message-ID: 2011/4/25 Matthias Bolte : > 2011/4/25 Eric Blake : >> On 04/24/2011 04:26 PM, Matthias Bolte wrote: >>> Make virtTestLoadFile allocate the buffer to read the file into. >>> >>> Fix logic error in virtTestLoadFile, stop reading on the an empty line. >>> >>> Use virFileReadLimFD in virtTestCaptureProgramOutput. >>> --- >>> +++ b/tests/commandhelper.c >>> @@ -99,8 +99,8 @@ int main(int argc, char **argv) { >>> ? ? ?} >>> >>> ? ? ?fprintf(log, "DAEMON:%s\n", getpgrp() == getsid(0) ? "yes" : "no"); >>> - ? ?char cwd[1024]; >>> - ? ?if (!getcwd(cwd, sizeof(cwd))) >>> + ? ?char *cwd = NULL; >>> + ? ?if (!(cwd = getcwd(NULL, 0))) >> >> Ouch. ?This is not portable to POSIX, and while gnulib can guarantee >> that it works, the current gnulib getcwd module is GPL (and relies on >> openat, which is a rather heavy-weight replacement!). >> >> I'm going to work on a gnulib module getcwd-lgpl which doesn't fix all >> the known bugs in getcwd, but at least guarantees that getcwd(NULL,0) >> will malloc insofar as the underlying getcwd is not buggy; we'll need to >> import that into libvirt before applying the rest of this patch. >> >> I haven't closely reviewed the rest of this patch yet, but like the >> general idea once we have getcwd sorted out. >> > > Oops. At first I used getcwd(NULL, 0) to replace the getcwd(cwd, > sizeof(cwd)) calls in the main functions, but then decided to just > move the cwd buffer to global scope instead. I just missed this one in > the second rewrite round. > > Matthias > Grep'ing the rest of the codebase shows a getcwd(NULL, 0) call in virFileAbsPath that probably needs care too. Matthias From matthias.bolte at googlemail.com Mon Apr 25 17:07:56 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 25 Apr 2011 19:07:56 +0200 Subject: [libvirt] [PATCH] Add virDomainEventRebootNew In-Reply-To: <4DB5A66E.1050401@redhat.com> References: <20110425113614.GA8817@sbox> <4DB5A66E.1050401@redhat.com> Message-ID: 2011/4/25 Eric Blake : > On 04/25/2011 05:36 AM, Matthias Bolte wrote: >> This will be used in the ESX driver event handling. >> --- >> ?src/conf/domain_event.c | ? ?8 ++++++++ >> ?src/conf/domain_event.h | ? ?1 + >> ?2 files changed, 9 insertions(+), 0 deletions(-) >> >> diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c >> index f0380d3..688bf6c 100644 >> --- a/src/conf/domain_event.c >> +++ b/src/conf/domain_event.c >> @@ -572,11 +572,19 @@ virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int de >> ? ? ?return virDomainEventNew(def->id, def->name, def->uuid, type, detail); >> ?} >> >> +virDomainEventPtr virDomainEventRebootNew(int id, const char *name, >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const unsigned char *uuid) >> +{ >> + ? ?return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT, >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id, name, uuid); > > ACK. > > Do you also need to add it to src/libvirt_private.syms? > Yes, I missed that. I add it and pushed the result. Matthias From matthias.bolte at googlemail.com Mon Apr 25 17:16:22 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Mon, 25 Apr 2011 19:16:22 +0200 Subject: [libvirt] [PATCH] Fix small memory leaks in config parsing related functions In-Reply-To: <4DB5A757.5020100@redhat.com> References: <20110424222623.GA16901@sbox> <4DB5A757.5020100@redhat.com> Message-ID: 2011/4/25 Eric Blake : > On 04/24/2011 04:26 PM, Matthias Bolte wrote: >> Found by 'make -C tests valgrind'. >> >> xen_xm.c: Dummy allocation via virDomainChrDefNew is directly >> overwritten and lost. Free 'script' in success path too. >> >> vmx.c: Free virtualDev_string in success path too. >> >> domain_conf.c: Free compression in success path too. >> --- >> ?src/conf/domain_conf.c | ? ?1 + >> ?src/vmx/vmx.c ? ? ? ? ?| ? 16 +++++++++------- >> ?src/xenxs/xen_xm.c ? ? | ? ?3 +-- >> ?3 files changed, 11 insertions(+), 9 deletions(-) > > ACK to all three fixes. > Thanks, pushed. Matthias From eblake at redhat.com Mon Apr 25 20:26:29 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 25 Apr 2011 14:26:29 -0600 Subject: [libvirt] [PATCH] tests: Lower stack usage below 4096 bytes In-Reply-To: <4DB5A7F3.2080700@redhat.com> References: <20110424222652.GA16936@sbox> <4DB5A7F3.2080700@redhat.com> Message-ID: <4DB5D8F5.3010407@redhat.com> On 04/25/2011 10:57 AM, Eric Blake wrote: > On 04/24/2011 04:26 PM, Matthias Bolte wrote: >> Make virtTestLoadFile allocate the buffer to read the file into. >> >> Fix logic error in virtTestLoadFile, stop reading on the an empty line. >> >> Use virFileReadLimFD in virtTestCaptureProgramOutput. >> --- >> +++ b/tests/commandhelper.c >> @@ -99,8 +99,8 @@ int main(int argc, char **argv) { >> } >> >> fprintf(log, "DAEMON:%s\n", getpgrp() == getsid(0) ? "yes" : "no"); >> - char cwd[1024]; >> - if (!getcwd(cwd, sizeof(cwd))) >> + char *cwd = NULL; >> + if (!(cwd = getcwd(NULL, 0))) > > Ouch. This is not portable to POSIX, and while gnulib can guarantee > that it works, the current gnulib getcwd module is GPL (and relies on > openat, which is a rather heavy-weight replacement!). I realize my statement may have come across as rather cryptic, so here's some more details: POSIX states that getcwd(NULL, n) has unspecified behavior. On most modern systems, it malloc's n bytes, or if n is 0, the perfect size for the answer; but older Solaris would fail with EINVAL, and it is possible that there were other old OS that failed with a core dump. POSIX also states that getcwd(buf, n) must fail with ERANGE if buf was too small, so that you can manage the malloc()s yourself and iteratively try larger buffers until you succeed (or, less likely, fail for some other reason like EACCES); at least tools/virsh.c was already using this idiom. Meanwhile, modern Linux mishandles getcwd() for large directories. The kernel refuses to return the current working directory if it is larger than a page (only possible for super-deep hierarchies, but Jim Meyering is fond of creating those as stress-tests for coreutils and gnulib). /proc/self/cwd might fare better, but is probably another instance of the kernel being likely to give up if the absolute name gets too long. glibc has fallbacks in place for when the syscall fails, which involve readdir() over progressively longer ../../ chains to learn the name of each parent directory, and by using openat() it is possible to still do this in linear instead of O(n^2) time without having to use chdir(). However, these fallbacks can fail if any directory in the middle has permissions issues, such as no search permissions. The end result: portable code must _always_ be prepared for getcwd() to fail (and not just due to ENOMEM). And while it is always possible to manage malloc() yourself, that gets to be tedious, so it would be nice to make gnulib guarantee that getcwd(NULL,0) manages malloc(). The current gnulib module for getcwd is the least likely to fail - it takes the best of all worlds (syscall, /proc/self/cwd, and openat() ../../ traversal) into some pretty complex code that has very few failure cases (it can succeed in some places where glibc does not); however, that complexity comes with some pretty heavy weight (the gnulib openat() module can cause a call to exit(), so it is not library-safe, and is therefore only GPL code and can't be used in LGPL libvirt). So I'm working on adding a new gnulib module getcwd-lgpl, which guarantees the allocation for getcwd(NULL,0), but doesn't address the possible problems with super-deep hierarchies. That is, the version is more likely to fail than the robust version used in GNU coreutils' pwd, but those failures are in corner cases unlikely to happen (no one reinstalls libvirtd into a super-deep directory) or where we can safely pass failure back to the caller (it's now up to the user to bypass their super-deep hierarchy in some other manner, since libvirt won't do it), which seems like a reasonable trade-off. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From agx at sigxcpu.org Mon Apr 25 21:42:51 2011 From: agx at sigxcpu.org (Guido =?iso-8859-1?Q?G=FCnther?=) Date: Mon, 25 Apr 2011 23:42:51 +0200 Subject: [libvirt] [PATCH] Make sure DNSMASQ_STATE_DIR exists In-Reply-To: <4DB51D4F.8020005@laine.org> References: <20110424080223.GA5669@bogon.sigxcpu.org> <4DB51D4F.8020005@laine.org> Message-ID: <20110425214251.GA16593@bogon.sigxcpu.org> On Mon, Apr 25, 2011 at 03:05:51AM -0400, Laine Stump wrote: > On 04/24/2011 04:02 AM, Guido G?nther wrote: > >Hi, > > > >otherwise the directory returned by networkDnsmasqLeaseFileName will not > >be created if ipdef->nhosts == 0 in networkBuildDnsmasqArgv. > > > >O.k. to apply? > > > >Cheers, > > -- Guido > > > >--- > > src/network/bridge_driver.c | 7 +++++++ > > 1 files changed, 7 insertions(+), 0 deletions(-) > > > >diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c > >index 8b5c1b6..ed78710 100644 > >--- a/src/network/bridge_driver.c > >+++ b/src/network/bridge_driver.c > >@@ -662,6 +662,13 @@ networkStartDhcpDaemon(virNetworkObjPtr network) > > goto cleanup; > > } > > > >+ if ((err = virFileMakePath(DNSMASQ_STATE_DIR)) != 0) { > >+ virReportSystemError(err, > >+ _("cannot create directory %s"), > >+ DNSMASQ_STATE_DIR); > >+ goto cleanup; > >+ } > >+ > > cmd = virCommandNew(DNSMASQ); > > if (networkBuildDnsmasqArgv(network, ipdef, pidfile, cmd)< 0) { > > goto cleanup; > > ACK. Pushed. Thanks, -- Guido From erenoglu at gmail.com Mon Apr 25 21:54:37 2011 From: erenoglu at gmail.com (Emre Erenoglu) Date: Tue, 26 Apr 2011 01:54:37 +0400 Subject: [libvirt] [virt-tools-list] libvirt spice command line appears to be incorrect In-Reply-To: <4DB58506.60205@redhat.com> References: <20110425082704.GA29431@amd.home.annexia.org> <4DB58506.60205@redhat.com> Message-ID: On Mon, Apr 25, 2011 at 6:28 PM, Cole Robinson wrote: > On 04/25/2011 04:27 AM, Richard W.M. Jones wrote: > > [Copying this to libvir-list] > > > > On Mon, Apr 25, 2011 at 01:07:37AM +0400, Emre Erenoglu wrote: > >> Hi, > >> > >> I'm the package maintainer for virt-manager and related packages for > Pardus > >> distribution. While testing the latest libvirt, virtinst & virt-manager > >> packages, I've come across a strange issue and I would like to get your > >> valuable opinion. > >> > >> I add all spice related devices and everything works good, except the > >> vdagent inside the windows xp guest. The virtio serial driver is loaded > >> correctly. As I track down the issue, I found out that libvirt is > starting > >> qemu-kvm with parameters which do not match the ones adviced by the > spice > >> people. Please see below email discussion with them on this. The > offending > >> line seems to be the chardev parameter. qemu-kvm is started by > virt-manager > >> with the following parameter for chardev: > >> > >> -chardev null,id=channel0 > >> > >> and the full spice related parameters are: > >> > >> -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x8 -chardev > >> null,id=channel0 -device > >> > virtserialport,bus=virtio-serial0.0,nr=0,chardev=channel0,name=com.redhat.spice.0 > >> -usb -device usb-tablet,id=input0 -spice > >> port=5900,addr=127.0.0.1,disable-ticketing -vga qxl -device > >> qxl,id=video1,bus=pci.0,addr=0x7 > >> > >> while spice people adviced: > >> > >> -chardev spicevmc,id=channel0,name=vdagent > >> > >> and the rest of the parameters to match it. See below mail on the > details. > >> I don't know if this is really the issue, but I also recognize the > following > >> inside the domain XML: > >> > >> > >> > >>
    > >> > >> > >> the "channel type" is listed as "null", while I assume it should have > been > >> listed as "spicevmc". (not sure of this, I saw this in some other > >> websites). When I edit the domain xml with virsh edit, it saves my > changes > >> but the "null" stays the same how many times I try to change it. > >> > >> Please note that I've applied the following patches to virtinst 0.500.6: > >> > >> constrain-spicevmc-usage-correct.patch > >> virtinst-fix-channel-parse.patch > >> virtinst-spicevmc-fixes.patch > >> > >> which I obtained from the git. I also patched virt-manager 0.8.7 with > the > >> following I obtained from the git: > >> > >> chardev-hide-unsupported-params-for-selected-type.patch > >> only-show-relevant-char-device-fields.patch > >> show-char-device-target-name.patch > >> chardev-propose-to-add-remove-spice-agent.patch > >> allow-setting-char-device-target-name.patch > >> fix-adding-removing-channel-device.patch > >> > >> Any idea what I might be missing to get the vdagent run inside the > windows > >> guest? > >> > >> Many thanks, > >> > >> Emre Erenoglu > > What libvirt version are you using? spicevmc requires libvirt 0.8.8. > However > if libvirt is silently reverting to 'null' it's a bug either way. > > Hi Cole, I recognized that I was using 0.8.7 since our iptables version does not support the newly added "CHECKSUM" parameter that libvirt used for iptables commands. I disabled this by patching it and now libvirt 0.9.0 runs good, with the vdagent in the guest also working OK. Many thanks for all who spent their time to fix this issue. yes, libvirt 0.8.7 was silently reverting the change I made manually in the xml file. Neither virsh edit nor editing the xml and re-defining it worked. Once libvirt saw the "spicevmc" there, it just removed it and put "null" instead. -- Emre -------------- next part -------------- An HTML attachment was scrubbed... URL: From eblake at redhat.com Mon Apr 25 22:05:49 2011 From: eblake at redhat.com (Eric Blake) Date: Mon, 25 Apr 2011 16:05:49 -0600 Subject: [libvirt] [virt-tools-list] libvirt spice command line appears to be incorrect In-Reply-To: References: <20110425082704.GA29431@amd.home.annexia.org> <4DB58506.60205@redhat.com> Message-ID: <4DB5F03D.8060809@redhat.com> On 04/25/2011 03:54 PM, Emre Erenoglu wrote: > yes, libvirt 0.8.7 was silently reverting the change I made manually in the > xml file. Neither virsh edit nor editing the xml and re-defining it worked. > Once libvirt saw the "spicevmc" there, it just removed it and put "null" > instead. There has been some upstream work to make libvirt do better at detecting bogus configurations, but I'm not sure off the top of my head if it includes the instance you tripped over. So, the question remains whether we have already fixed the bug in 0.9.0, or whether, if you put in some other random string in place of "spicevmc", then would libvirt still silently change that to "null" instead of rejecting the XML. If the former, great - we've cleaned it up! If the latter, then this is a bug still in libvirt worth fixing. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From erenoglu at gmail.com Mon Apr 25 22:19:44 2011 From: erenoglu at gmail.com (Emre Erenoglu) Date: Tue, 26 Apr 2011 02:19:44 +0400 Subject: [libvirt] [virt-tools-list] libvirt spice command line appears to be incorrect In-Reply-To: <4DB5F03D.8060809@redhat.com> References: <20110425082704.GA29431@amd.home.annexia.org> <4DB58506.60205@redhat.com> <4DB5F03D.8060809@redhat.com> Message-ID: On Tue, Apr 26, 2011 at 2:05 AM, Eric Blake wrote: > On 04/25/2011 03:54 PM, Emre Erenoglu wrote: > > yes, libvirt 0.8.7 was silently reverting the change I made manually in > the > > xml file. Neither virsh edit nor editing the xml and re-defining it > worked. > > Once libvirt saw the "spicevmc" there, it just removed it and put "null" > > instead. > > There has been some upstream work to make libvirt do better at detecting > bogus configurations, but I'm not sure off the top of my head if it > includes the instance you tripped over. So, the question remains > whether we have already fixed the bug in 0.9.0, or whether, if you put > in some other random string in place of "spicevmc", then would libvirt > still silently change that to "null" instead of rejecting the XML. If > the former, great - we've cleaned it up! If the latter, then this is a > bug still in libvirt worth fixing. > > I re-installed 0.8.7. It re-wrote the existing virtual machine channel device definition (which used to be "spicevmc" with 0.9.0) back to 'null'. I tried to edit it by hand, with any string, always reverted to 'null'. In libvirt 0.9.0, editing by hand to replace 'null' with 'spicevmc' works. Editing by hand to an arbitrary string, fails with the following error message (when I put 'emre' instead of 'null'): error: XML description for unknown type presented to host for character device: emre is not well formed or invalid So looks like it's fixed in 0.9.0 but I let you conclude the 0.8.7 behaviour. -- Emre -------------- next part -------------- An HTML attachment was scrubbed... URL: From hutao at cn.fujitsu.com Tue Apr 26 01:20:31 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Tue, 26 Apr 2011 09:20:31 +0800 Subject: [libvirt] [PATCH] free memory properly in cleanup patch Message-ID: <20110426012031.GA13689@localhost.localdomain> virsh schedinfo inactive-domain will trigger the problem. --- daemon/remote.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 1c98bba..eedbc77 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -945,8 +945,11 @@ remoteDispatchDomainGetSchedulerParameters(struct qemud_server *server ATTRIBUTE cleanup: if (rv < 0) { remoteDispatchError(rerr); - for (i = 0 ; i < nparams ; i++) - VIR_FREE(ret->params.params_val[i].field); + 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); + } } if (dom) virDomainFree(dom); -- 1.7.3.1 From kamezawa.hiroyu at jp.fujitsu.com Tue Apr 26 02:06:24 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Tue, 26 Apr 2011 11:06:24 +0900 Subject: [libvirt] [PATCHv12 1/3] libvirt/qemu - support persistent modification of devices In-Reply-To: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> References: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110426110624.5ad5a47a.kamezawa.hiroyu@jp.fujitsu.com> On Fri, 22 Apr 2011 12:07:56 +0900 KAMEZAWA Hiroyuki wrote: > > Rebased ont the latest git tree, which makes this work easier. > This series adds support for attach/detach/update disks of domain config. Ping ? Thanks, -Kame > == > This patch adds functions for modify domain's persistent definition. > To do error recovery in easy way, we use a copy of vmdef and update it. > > The whole sequence will be: > > make a copy of domain definition. > > if (flags & MODIFY_CONFIG) > update copied domain definition > if (flags & MODIF_LIVE) > do hotplug. > if (no error) > save copied one to the file and update cached definition. > else > discard copied definition. > > This patch is mixuture of Eric Blake's work and mine. > From: Eric Blake > Signed-off-by: KAMEZAWA Hiroyuki > > Changelog: v11 -> v12 > - rebased and fixed hunks. > - renamed qemudDomain....to qemuDomain... > > (virDomainObjCopyPersistentDef): make a copy of persistent vm definition > (qemuDomainAttach/Detach/UpdateDeviceConfig) : callbacks. now empty > (qemuDomainModifyDeviceFlags): add support for MODIFY_CONFIG and MODIFY_CURRENT > --- > src/conf/domain_conf.c | 18 ++++++ > src/conf/domain_conf.h | 3 + > src/libvirt_private.syms | 1 + > src/qemu/qemu_driver.c | 147 ++++++++++++++++++++++++++++++++++++---------- > 4 files changed, 137 insertions(+), 32 deletions(-) > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index 381e692..6c1098a 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -9509,3 +9509,21 @@ cleanup: > > return ret; > } > + > + > +virDomainDefPtr > +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom) > +{ > + char *xml; > + virDomainDefPtr cur, ret; > + > + cur = virDomainObjGetPersistentDef(caps, dom); > + > + xml = virDomainDefFormat(cur, VIR_DOMAIN_XML_WRITE_FLAGS); > + if (!xml) > + return NULL; > + > + ret = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS); > + > + return ret; > +} > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > index 6ea30b9..ddf111a 100644 > --- a/src/conf/domain_conf.h > +++ b/src/conf/domain_conf.h > @@ -1288,6 +1288,9 @@ int virDomainObjSetDefTransient(virCapsPtr caps, > virDomainDefPtr > virDomainObjGetPersistentDef(virCapsPtr caps, > virDomainObjPtr domain); > +virDomainDefPtr > +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom); > + > void virDomainRemoveInactive(virDomainObjListPtr doms, > virDomainObjPtr dom); > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index ba7739d..f732431 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -287,6 +287,7 @@ virDomainMemballoonModelTypeToString; > virDomainNetDefFree; > virDomainNetTypeToString; > virDomainObjAssignDef; > +virDomainObjCopyPersistentDef; > virDomainObjSetDefTransient; > virDomainObjGetPersistentDef; > virDomainObjIsDuplicate; > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 771678e..fd85c8a 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -4073,6 +4073,46 @@ qemuDomainUpdateDeviceLive(virDomainObjPtr vm, > return ret; > } > > +static int > +qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, > + virDomainDeviceDefPtr dev) > +{ > + switch (dev->type) { > + default: > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("persistent attach of device is not supported")); > + return -1; > + } > + return 0; > +} > + > + > +static int > +qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, > + virDomainDeviceDefPtr dev) > +{ > + switch (dev->type) { > + default: > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("persistent detach of device is not supported")); > + return -1; > + } > + return 0; > +} > + > +static int > +qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, > + virDomainDeviceDefPtr dev) > +{ > + switch (dev->type) { > + default: > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("persistent update of device is not supported")); > + return -1; > + } > + return 0; > +} > + > /* Actions for qemuDomainModifyDeviceFlags */ > enum { > QEMU_DEVICE_ATTACH, > @@ -4088,6 +4128,7 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > struct qemud_driver *driver = dom->conn->privateData; > virBitmapPtr qemuCaps = NULL; > virDomainObjPtr vm = NULL; > + virDomainDefPtr vmdef = NULL; > virDomainDeviceDefPtr dev = NULL; > bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; > int ret = -1; > @@ -4097,12 +4138,6 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > (action == QEMU_DEVICE_UPDATE ? > VIR_DOMAIN_DEVICE_MODIFY_FORCE : 0), -1); > > - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > - qemuReportError(VIR_ERR_OPERATION_INVALID, > - "%s", _("cannot modify the persistent configuration of a domain")); > - return -1; > - } > - > qemuDriverLock(driver); > vm = virDomainFindByUUID(&driver->domains, dom->uuid); > if (!vm) { > @@ -4116,12 +4151,27 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) > goto cleanup; > > - if (!virDomainObjIsActive(vm)) { > - qemuReportError(VIR_ERR_OPERATION_INVALID, > - "%s", _("cannot attach device on inactive domain")); > - goto endjob; > + if (virDomainObjIsActive(vm)) { > + if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT) > + flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE; > + } else { > + if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT) > + flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG; > + /* check consistency between flags and the vm state */ > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { > + qemuReportError(VIR_ERR_OPERATION_INVALID, > + "%s", > + _("cannot do live update a device on " > + "inactive domain")); > + goto endjob; > + } > } > > + if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) { > + qemuReportError(VIR_ERR_OPERATION_INVALID, > + "%s", _("cannot modify device on transient domain")); > + goto endjob; > + } > dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, > VIR_DOMAIN_XML_INACTIVE); > if (dev == NULL) > @@ -4132,35 +4182,68 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, > &qemuCaps) < 0) > goto endjob; > > - switch (action) { > - case QEMU_DEVICE_ATTACH: > - ret = qemuDomainAttachDeviceLive(vm, dev, dom, qemuCaps); > - break; > - case QEMU_DEVICE_DETACH: > - ret = qemuDomainDetachDeviceLive(vm, dev, dom, qemuCaps); > - break; > - case QEMU_DEVICE_UPDATE: > - ret = qemuDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force); > - break; > - default: > - qemuReportError(VIR_ERR_INTERNAL_ERROR, > - _("unknown domain modify action %d"), action); > - break; > - } > + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { > + /* Make a copy for updated domain. */ > + vmdef = virDomainObjCopyPersistentDef(driver->caps, vm); > + if (!vmdef) > + goto endjob; > + switch (action) { > + case QEMU_DEVICE_ATTACH: > + ret = qemuDomainAttachDeviceConfig(vmdef, dev); > + break; > + case QEMU_DEVICE_DETACH: > + ret = qemuDomainDetachDeviceConfig(vmdef, dev); > + break; > + case QEMU_DEVICE_UPDATE: > + ret = qemuDomainUpdateDeviceConfig(vmdef, dev); > + break; > + default: > + qemuReportError(VIR_ERR_INTERNAL_ERROR, > + _("unknown domain modify action %d"), action); > + break; > + } > + } else > + ret = 0; > > - /* > - * update domain status forcibly because the domain status may be changed > - * even if we attach the device failed. For example, a new controller may > - * be created. > - */ > - if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) > - ret = -1; > + if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE)) { > + switch (action) { > + case QEMU_DEVICE_ATTACH: > + ret = qemuDomainAttachDeviceLive(vm, dev, dom, qemuCaps); > + break; > + case QEMU_DEVICE_DETACH: > + ret = qemuDomainDetachDeviceLive(vm, dev, dom, qemuCaps); > + break; > + case QEMU_DEVICE_UPDATE: > + ret = qemuDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force); > + break; > + default: > + qemuReportError(VIR_ERR_INTERNAL_ERROR, > + _("unknown domain modify action %d"), action); > + break; > + } > + /* > + * update domain status forcibly because the domain status may be > + * changed even if we attach the device failed. For example, a > + * For example, a new controller may be created. > + */ > + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) > + ret = -1; > + } > + /* Finally, if no error until here, we can save config. */ > + if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) { > + ret = virDomainSaveConfig(driver->configDir, vmdef); > + if (!ret) { > + virDomainObjAssignDef(vm, vmdef, false); > + vmdef = NULL; > + } > + } > > endjob: > if (qemuDomainObjEndJob(vm) == 0) > vm = NULL; > > cleanup: > + virDomainDefFree(vmdef); > virDomainDeviceDefFree(dev); > if (vm) > virDomainObjUnlock(vm); > -- > 1.7.4.1 > > > From wency at cn.fujitsu.com Tue Apr 26 03:03:04 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Tue, 26 Apr 2011 11:03:04 +0800 Subject: [libvirt] [PATCH] fix virsh's regression Message-ID: <4DB635E8.8020705@cn.fujitsu.com> This patch does the following things: 1. The return value of cmdSchedInfoUpdate() can be -1, 0 and 1. So the type of return value should be int not bool.(This function is not a entry of a virsh command, but the name of this function likes cmdXXX) 2. The type of cmdSchedinfo()'s, cmdFreecell()'s, cmdPoolList()'s and cmdVolList()'s return value is bool not int, so change the type of variable ret_val, func_ret and functionReturn. 3. Add a variable functionReturn for cmdMigrate(), cmdAttachInterface(), cmdDetachInterface(), cmdAttachDisk() and cmdDetachDisk() to save the return value. 4. Change the type of variable ret in the function cmdAttachDevice(), cmdDetachDevice(), cmdUpdateDevice(), cmdAttachInterface(), cmdDetachInterface(), cmdAttachDisk() and cmdDetachDisk() to int, as we use it to save the return value of virXXX() and the type of virXXX()'s return value is int not bool. 5. Do some cleanup when virBuff.error is 1. The bug 1-4 were introduced by commit b56fa5bb. --- tools/virsh.c | 63 +++++++++++++++++++++++++++++--------------------------- 1 files changed, 33 insertions(+), 30 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 9ac27b3..27140f3 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -1593,7 +1593,7 @@ static const vshCmdOptDef opts_schedinfo[] = { {NULL, 0, 0, NULL} }; -static bool +static int cmdSchedInfoUpdate(vshControl *ctl, const vshCmd *cmd, virSchedParameterPtr param) { @@ -1696,7 +1696,7 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) int nparams = 0; int update = 0; int i, ret; - int ret_val = false; + bool ret_val = false; if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -2288,7 +2288,7 @@ static const vshCmdOptDef opts_freecell[] = { static bool cmdFreecell(vshControl *ctl, const vshCmd *cmd) { - int func_ret = false; + bool func_ret = false; int ret; int cell = -1, cell_given; unsigned long long memory; @@ -3847,6 +3847,7 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd) virDomainPtr dom = NULL; int p[2] = {-1, -1}; int ret = -1; + bool functionReturn = false; virThread workerThread; struct pollfd pollfd; char retchar; @@ -3921,15 +3922,15 @@ repoll: if (ret > 0) { if (saferead(p[0], &retchar, sizeof(retchar)) > 0) { if (retchar == '0') { - ret = true; + functionReturn = true; if (verbose) { /* print [100 %] */ print_job_progress(0, 1); } } else - ret = false; + functionReturn = false; } else - ret = false; + functionReturn = false; break; } @@ -3937,11 +3938,11 @@ repoll: if (errno == EINTR) { if (intCaught) { virDomainAbortJob(dom); - ret = false; intCaught = 0; } else goto repoll; } + functionReturn = false; break; } @@ -3975,7 +3976,7 @@ cleanup: virDomainFree(dom); VIR_FORCE_CLOSE(p[0]); VIR_FORCE_CLOSE(p[1]); - return ret; + return functionReturn; } /* @@ -5952,7 +5953,8 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { virStoragePoolInfo info; char **poolNames = NULL; - int i, functionReturn, ret; + int i, ret; + bool functionReturn; int numActivePools = 0, numInactivePools = 0, numAllPools = 0; size_t stringLength = 0, nameStrLength = 0; size_t autostartStrLength = 0, persistStrLength = 0; @@ -7525,7 +7527,8 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) double val; int details = vshCommandOptBool(cmd, "details"); int numVolumes = 0, i; - int ret, functionReturn; + int ret; + bool functionReturn; int stringLength = 0; size_t allocStrLength = 0, capStrLength = 0; size_t nameStrLength = 0, pathStrLength = 0; @@ -8904,7 +8907,7 @@ cmdAttachDevice(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; const char *from = NULL; char *buffer; - bool ret = true; + int ret; unsigned int flags; if (!vshConnectionUsability(ctl, ctl->conn)) @@ -8969,7 +8972,7 @@ cmdDetachDevice(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; const char *from = NULL; char *buffer; - bool ret = true; + int ret; unsigned int flags; if (!vshConnectionUsability(ctl, ctl->conn)) @@ -9035,7 +9038,7 @@ cmdUpdateDevice(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; const char *from = NULL; char *buffer; - bool ret = true; + int ret; unsigned int flags; if (!vshConnectionUsability(ctl, ctl->conn)) @@ -9110,7 +9113,8 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) const char *mac = NULL, *target = NULL, *script = NULL, *type = NULL, *source = NULL, *model = NULL; int typ; - bool ret = false; + int ret; + bool functionReturn = false; unsigned int flags; virBuffer buf = VIR_BUFFER_INITIALIZER; char *xml; @@ -9165,7 +9169,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) if (virBufferError(&buf)) { vshPrint(ctl, "%s", _("Failed to allocate XML buffer")); - return false; + goto cleanup; } xml = virBufferContentAndReset(&buf); @@ -9183,17 +9187,16 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) if (ret != 0) { vshError(ctl, "%s", _("Failed to attach interface")); - ret = false; } else { vshPrint(ctl, "%s", _("Interface attached successfully\n")); - ret = true; + functionReturn = true; } cleanup: if (dom) virDomainFree(dom); virBufferFreeAndReset(&buf); - return ret; + return functionReturn; } /* @@ -9226,7 +9229,8 @@ cmdDetachInterface(vshControl *ctl, const vshCmd *cmd) char *doc; char buf[64]; int i = 0, diff_mac; - bool ret = false; + int ret; + int functionReturn = false; unsigned int flags; if (!vshConnectionUsability(ctl, ctl->conn)) @@ -9322,10 +9326,9 @@ cmdDetachInterface(vshControl *ctl, const vshCmd *cmd) if (ret != 0) { vshError(ctl, "%s", _("Failed to detach interface")); - ret = false; } else { vshPrint(ctl, "%s", _("Interface detached successfully\n")); - ret = true; + functionReturn = true; } cleanup: @@ -9337,7 +9340,7 @@ cmdDetachInterface(vshControl *ctl, const vshCmd *cmd) xmlFreeDoc(xml); if (xml_buf) xmlBufferFree(xml_buf); - return ret; + return functionReturn; } /* @@ -9368,7 +9371,8 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom = NULL; const char *source = NULL, *target = NULL, *driver = NULL, *subdriver = NULL, *type = NULL, *mode = NULL; - bool isFile = false, ret = false; + bool isFile = false, functionReturn = false; + int ret; unsigned int flags; const char *stype = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -9460,17 +9464,16 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd) if (ret != 0) { vshError(ctl, "%s", _("Failed to attach disk")); - ret = false; } else { vshPrint(ctl, "%s", _("Disk attached successfully\n")); - ret = true; + functionReturn = true; } cleanup: if (dom) virDomainFree(dom); virBufferFreeAndReset(&buf); - return ret; + return functionReturn; } /* @@ -9501,7 +9504,8 @@ cmdDetachDisk(vshControl *ctl, const vshCmd *cmd) const char *target = NULL; char *doc; int i = 0, diff_tgt; - bool ret = false; + int ret; + bool functionReturn = false; unsigned int flags; if (!vshConnectionUsability(ctl, ctl->conn)) @@ -9582,10 +9586,9 @@ cmdDetachDisk(vshControl *ctl, const vshCmd *cmd) if (ret != 0) { vshError(ctl, "%s", _("Failed to detach disk")); - ret = false; } else { vshPrint(ctl, "%s", _("Disk detached successfully\n")); - ret = true; + functionReturn = true; } cleanup: @@ -9597,7 +9600,7 @@ cmdDetachDisk(vshControl *ctl, const vshCmd *cmd) xmlBufferFree(xml_buf); if (dom) virDomainFree(dom); - return ret; + return functionReturn; } /* -- 1.7.1 From wency at cn.fujitsu.com Tue Apr 26 03:40:01 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Tue, 26 Apr 2011 11:40:01 +0800 Subject: [libvirt] [PATCH] release PCI address only when we have ensured it successfully Message-ID: <4DB63E91.6030405@cn.fujitsu.com> Steps to reproduce this bug: 1. # cat net.xml # 00:03.0 has been used
    2. # virsh attach-device vm1 net.xml error: Failed to attach device from net.xml error: internal error unable to reserve PCI address 0:0:3 3. # virsh attach-device vm1 net.xml error: Failed to attach device from net.xml error: internal error unable to execute QEMU command 'device_add': Device 'rtl8139' could not be initialized The reason of this bug is that: we can not reserve PCI address 0:0:3 because it has been used, but we release PCI address when we reserve it failed. --- src/qemu/qemu_hotplug.c | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index b03f774..5fdb013 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -147,6 +147,7 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver, qemuDomainObjPrivatePtr priv = vm->privateData; char *devstr = NULL; char *drivestr = NULL; + bool releaseaddr = false; for (i = 0 ; i < vm->def->ndisks ; i++) { if (STREQ(vm->def->disks[i]->dst, disk->dst)) { @@ -163,6 +164,7 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver, if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info) < 0) goto error; + releaseaddr = true; if (qemuAssignDeviceDiskAlias(disk, qemuCaps) < 0) goto error; @@ -221,6 +223,7 @@ error: if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) && + releaseaddr && qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &disk->info) < 0) VIR_WARN("Unable to release PCI address on %s", disk->src); @@ -242,6 +245,7 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver, const char* type = virDomainControllerTypeToString(controller->type); char *devstr = NULL; qemuDomainObjPrivatePtr priv = vm->privateData; + bool releaseaddr = false; for (i = 0 ; i < vm->def->ncontrollers ; i++) { if ((vm->def->controllers[i]->type == controller->type) && @@ -256,6 +260,7 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver, if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &controller->info) < 0) goto cleanup; + releaseaddr = true; if (qemuAssignDeviceControllerAlias(controller) < 0) goto cleanup; @@ -288,6 +293,7 @@ cleanup: if ((ret != 0) && qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) && + releaseaddr && qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &controller->info) < 0) VIR_WARN0("Unable to release PCI address on controller"); @@ -559,6 +565,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, int ret = -1; virDomainDevicePCIAddress guestAddr; int vlan; + bool releaseaddr = false; if (!qemuCapsGet(qemuCaps, QEMU_CAPS_HOST_NET_ADD)) { qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -595,6 +602,8 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0) goto cleanup; + releaseaddr = true; + if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) && qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { vlan = -1; @@ -694,6 +703,7 @@ cleanup: if ((ret != 0) && qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) && + releaseaddr && qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &net->info) < 0) VIR_WARN0("Unable to release PCI address on NIC"); @@ -757,6 +767,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, char *devstr = NULL; int configfd = -1; char *configfd_name = NULL; + bool releaseaddr = false; if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) { virReportOOMError(); @@ -771,6 +782,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, goto error; if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &hostdev->info) < 0) goto error; + releaseaddr = true; if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_CONFIGFD)) { configfd = qemuOpenPCIConfig(hostdev); if (configfd >= 0) { @@ -823,6 +835,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, error: if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && (hostdev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) && + releaseaddr && qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &hostdev->info) < 0) VIR_WARN0("Unable to release PCI address on host device"); -- 1.7.1 From wency at cn.fujitsu.com Tue Apr 26 03:42:21 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Tue, 26 Apr 2011 11:42:21 +0800 Subject: [libvirt] [PATCH] free buf->content when vsnprintf() failed Message-ID: <4DB63F1D.6010001@cn.fujitsu.com> When buf->error is 1, we do not return buf->content in the function virBufferContentAndReset(). So we should free buf->content when vsnprintf() failed. --- src/util/buf.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/src/util/buf.c b/src/util/buf.c index 7557ad1..fdb7660 100644 --- a/src/util/buf.c +++ b/src/util/buf.c @@ -241,6 +241,9 @@ virBufferVSprintf(const virBufferPtr buf, const char *format, ...) size = buf->size - buf->use; if ((count = vsnprintf(&buf->content[buf->use], size, format, argptr)) < 0) { + VIR_FREE(buf->content); + buf->size = 0; + buf->use = 0; buf->error = 1; goto err; } @@ -259,6 +262,9 @@ virBufferVSprintf(const virBufferPtr buf, const char *format, ...) size = buf->size - buf->use; if ((count = vsnprintf(&buf->content[buf->use], size, format, argptr)) < 0) { + VIR_FREE(buf->content); + buf->size = 0; + buf->use = 0; buf->error = 1; goto err; } -- 1.7.1 From gross at univention.de Tue Apr 26 09:47:12 2011 From: gross at univention.de (=?UTF-8?q?Markus=20Gro=C3=9F?=) Date: Tue, 26 Apr 2011 11:47:12 +0200 Subject: [libvirt] =?utf-8?q?=5BPATCH_RFC=5D_Add_domainSave/Restore_to_lib?= =?utf-8?q?xl_driver?= Message-ID: <1303811232-28809-1-git-send-email-gross@univention.de> This patch adds save/restore functionality to the libxl driver. It is a v2 of this patch: https://www.redhat.com/archives/libvir-list/2011-April/msg00338.html v2: * header is now padded and has a version field * the correct restore function from libxl is used * only create the restore event once in libxlVmStart However I ran into a reproducible segfault. Assume you saved a vm with: # virsh save domU foo.img If you restore the save image, destroy the vm and restore it again, a segfault occurs: # virsh restore foo.img # virsh destroy domU # virsh restore foo.img # segfault If you restart libvirt between the restores no segfault occurs: # virsh restore foo.img # virsh destroy domU # restart libvirt # virsh restore foo.img According to a gdb backtrace a memcpy from the function xc_domain_restore is causing the segfault. Then I saved a vm with the xl tool (which also uses the libxenlight interface) and restored it twice. No segfault occured. So I figured something must went wrong in libvirt. However I was unable to identify the responsible part of code. Now I am hoping that a review will possibly solve this issue. Here is the gdb backtrace: Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x42ba1950 (LWP 23813)] 0x00007f1bc17d906b in memcpy () from /lib/libc.so.6 (gdb) bt #0 0x00007f1bc17d906b in memcpy () from /lib/libc.so.6 #1 0x00007f1bc2b49346 in xc_domain_restore () from /usr/lib/libxenguest.so.4.0 #2 0x00007f1bc31a80f3 in ?? () from /usr/lib/libxenlight.so.1.0 #3 0x00007f1bc31a105e in ?? () from /usr/lib/libxenlight.so.1.0 #4 0x000000000049389a in libxlVmStart (driver=0x7f1bb8003e80, vm=0x7f1bb8053400, start_paused=false, restore_fd=20) at libxl/libxl_driver.c:531 #5 0x00000000004945c5 in libxlDomainRestore (conn=, from=) at libxl/libxl_driver.c:1745 #6 0x00007f1bc1f85a4b in virDomainRestore (conn=0x20a4d40, from=0x7f1bb804d260 "/root/tt.img") at libvirt.c:2330 #7 0x000000000042c5b8 in remoteDispatchDomainRestore (server=, client=, conn=0xaf0, hdr=, rerr=0x42ba0e20, args=0xffffffff, ret=0x42ba0f00) at remote.c:2616 #8 0x0000000000431cb7 in remoteDispatchClientRequest (server=0x209fe90, client=0x20a4ad0, msg=0x20b1aa0) at dispatch.c:524 #9 0x000000000041dd53 in qemudWorker (data=0x20a8018) at libvirtd.c:1622 #10 0x00007f1bc1cb9fc7 in start_thread () from /lib/libpthread.so.0 #11 0x00007f1bc182b64d in clone () from /lib/libc.so.6 #12 0x0000000000000000 in ?? () Cheers, Markus --- src/libxl/libxl_conf.h | 14 +++ src/libxl/libxl_driver.c | 228 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 225 insertions(+), 17 deletions(-) diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index 8c87786..e7dd3a1 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -1,5 +1,6 @@ /*---------------------------------------------------------------------------*/ /* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. + * Copyright (C) 2011 Univention GmbH. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,6 +18,7 @@ * * Authors: * Jim Fehlig + * Markus Gro? */ /*---------------------------------------------------------------------------*/ @@ -85,6 +87,18 @@ struct _libxlDomainObjPrivate { int eventHdl; }; +#define LIBXL_SAVE_MAGIC "libvirt-xml\n \0 \r" +#define LIBXL_SAVE_VERSION 1 + +typedef struct _libxlSavefileHeader libxlSavefileHeader; +typedef libxlSavefileHeader *libxlSavefileHeaderPtr; +struct _libxlSavefileHeader { + char magic[sizeof(LIBXL_SAVE_MAGIC)-1]; + uint32_t version; + uint32_t xmlLen; + /* 24 bytes used, pad up to 64 bytes */ + uint32_t unused[10]; +}; # define libxlError(code, ...) \ virReportErrorHelper(VIR_FROM_LIBXL, code, __FILE__, \ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 247d78e..56a62c9 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "internal.h" #include "logging.h" @@ -60,11 +61,10 @@ static libxlDriverPrivatePtr libxl_driver = NULL; - /* Function declarations */ static int -libxlVmStart(libxlDriverPrivatePtr driver, - virDomainObjPtr vm, bool start_paused); +libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, + bool start_paused, int restore_fd); /* Function definitions */ @@ -188,7 +188,7 @@ libxlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, virResetLastError(); if (vm->autostart && !virDomainObjIsActive(vm) && - libxlVmStart(driver, vm, false) < 0) { + libxlVmStart(driver, vm, false, -1) < 0) { err = virGetLastError(); VIR_ERROR(_("Failed to autostart VM '%s': %s"), vm->def->name, @@ -378,7 +378,7 @@ static void libxlEventHandler(int watch, break; case SHUTDOWN_reboot: libxlVmReap(driver, vm, 0); - libxlVmStart(driver, vm, 0); + libxlVmStart(driver, vm, 0, -1); break; default: VIR_INFO("Unhandled shutdown_reason %d", info.shutdown_reason); @@ -504,8 +504,8 @@ cleanup: * virDomainObjPtr should be locked on invocation */ static int -libxlVmStart(libxlDriverPrivatePtr driver, - virDomainObjPtr vm, bool start_paused) +libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, + bool start_paused, int restore_fd) { libxl_domain_config d_config; virDomainDefPtr def = vm->def; @@ -524,12 +524,23 @@ libxlVmStart(libxlDriverPrivatePtr driver, //TODO: Balloon dom0 ?? //ret = freemem(&d_config->b_info, &d_config->dm_info); - ret = libxl_domain_create_new(&priv->ctx, &d_config, - NULL, &child_console_pid, &domid); + if (restore_fd < 0) + ret = libxl_domain_create_new(&priv->ctx, &d_config, + NULL, &child_console_pid, &domid); + else + ret = libxl_domain_create_restore(&priv->ctx, &d_config, NULL, + &child_console_pid, &domid, + restore_fd); + if (ret) { - libxlError(VIR_ERR_INTERNAL_ERROR, - _("libxenlight failed to create new domain '%s'"), - d_config.c_info.name); + if (restore_fd < 0) + libxlError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to create new domain '%s'"), + d_config.c_info.name); + else + libxlError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to restore domain '%s'"), + d_config.c_info.name); goto error; } @@ -562,7 +573,9 @@ libxlVmStart(libxlDriverPrivatePtr driver, goto error; event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_BOOTED); + restore_fd < 0 ? + VIR_DOMAIN_EVENT_STARTED_BOOTED : + VIR_DOMAIN_EVENT_STARTED_RESTORED); libxlDomainEventQueue(driver, event); libxl_domain_config_destroy(&d_config); @@ -1046,7 +1059,8 @@ libxlDomainCreateXML(virConnectPtr conn, const char *xml, goto cleanup; def = NULL; - if (libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0) < 0) { + if (libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, + -1) < 0) { virDomainRemoveInactive(&driver->domains, vm); vm = NULL; goto cleanup; @@ -1566,6 +1580,186 @@ libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) } static int +libxlDomainSave(virDomainPtr dom, const char * to) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + virDomainObjPtr vm; + libxlDomainObjPrivatePtr priv; + virDomainEventPtr event = NULL; + libxlSavefileHeader hdr; + libxl_domain_suspend_info s_info; + char *xml; + uint32_t xml_len; + int fd; + int ret = -1; + + libxlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + libxlError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + if (!virDomainObjIsActive(vm)) { + libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); + goto cleanup; + } + + priv = vm->privateData; + + if (vm->state != VIR_DOMAIN_PAUSED) { + memset(&s_info, 0, sizeof(s_info)); + + if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR, + getuid(), getgid(), 0)) < 0) { + virReportSystemError(-fd, + _("Failed to create domain save file '%s'"), + to); + goto cleanup; + } + + if ((xml = virDomainDefFormat(vm->def, 0)) == NULL) + goto cleanup; + xml_len = strlen(xml) + 1; + + memset(&hdr, 0, sizeof(hdr)); + memcpy(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic)); + hdr.version = LIBXL_SAVE_VERSION; + hdr.xmlLen = xml_len; + + if (safewrite(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("Failed to write save file header")); + goto cleanup; + } + + if (safewrite(fd, xml, xml_len) != xml_len) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("Failed to write xml description")); + goto cleanup; + } + + if (libxl_domain_suspend(&priv->ctx, &s_info, dom->id, fd) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to save domain '%d' with libxenlight"), + dom->id); + goto cleanup; + } + + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SAVED); + + if (libxlVmReap(driver, vm, 1) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to destroy domain '%d'"), dom->id); + goto cleanup; + } + + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + ret = 0; + } +cleanup: + VIR_FREE(xml); + if (VIR_CLOSE(fd) < 0) + virReportSystemError(errno, "%s", _("cannot close file")); + if (vm) + virDomainObjUnlock(vm); + if (event) + libxlDomainEventQueue(driver, event); + libxlDriverUnlock(driver); + return ret; +} + +static int +libxlDomainRestore(virConnectPtr conn, const char * from) +{ + libxlDriverPrivatePtr driver = conn->privateData; + virDomainDefPtr def = NULL; + virDomainObjPtr vm = NULL; + libxlSavefileHeader hdr; + char *xml = NULL; + int fd; + int ret = -1; + + libxlDriverLock(driver); + + if ((fd = virFileOpenAs(from, O_RDONLY, 0, getuid(), getgid(), 0)) < 0) { + libxlError(VIR_ERR_OPERATION_FAILED, + "%s", _("cannot read domain image")); + goto cleanup; + } + + if (saferead(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + libxlError(VIR_ERR_OPERATION_FAILED, + "%s", _("failed to read libxl header")); + goto cleanup; + } + + if (memcmp(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic))) { + libxlError(VIR_ERR_INVALID_ARG, "%s", _("image magic is incorrect")); + goto cleanup; + } + + if (hdr.version > LIBXL_SAVE_VERSION) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("image version is not supported (%d > %d)"), + hdr.version, LIBXL_SAVE_VERSION); + goto cleanup; + } + + if (hdr.xmlLen <= 0) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("invalid XML length: %d"), hdr.xmlLen); + goto cleanup; + } + + if (VIR_ALLOC_N(xml, hdr.xmlLen) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (saferead(fd, xml, hdr.xmlLen) != hdr.xmlLen) { + libxlError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML")); + goto cleanup; + } + + if (!(def = virDomainDefParseString(driver->caps, xml, + VIR_DOMAIN_XML_INACTIVE))) + goto cleanup; + + if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) + goto cleanup; + + if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def, true))) + goto cleanup; + + def = NULL; + + if ((ret = libxlVmStart(driver, vm, false, fd)) < 0 && + !vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + +cleanup: + VIR_FREE(xml); + virDomainDefFree(def); + if (VIR_CLOSE(fd) < 0) + virReportSystemError(errno, "%s", _("cannot close file")); + if (vm) + virDomainObjUnlock(vm); + libxlDriverUnlock(driver); + return ret; +} + +static int libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags) { @@ -2036,7 +2230,7 @@ libxlDomainCreateWithFlags(virDomainPtr dom, goto cleanup; } - ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0); + ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1); cleanup: if (vm) @@ -2672,8 +2866,8 @@ static virDriver libxlDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ libxlDomainGetInfo, /* domainGetInfo */ - NULL, /* domainSave */ - NULL, /* domainRestore */ + libxlDomainSave, /* domainSave */ + libxlDomainRestore, /* domainRestore */ NULL, /* domainCoreDump */ libxlDomainSetVcpus, /* domainSetVcpus */ libxlDomainSetVcpusFlags, /* domainSetVcpusFlags */ -- 1.7.1 From jdenemar at redhat.com Tue Apr 26 11:40:56 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 26 Apr 2011 13:40:56 +0200 Subject: [libvirt] [PATCH] Make the options "--crash" and "--live" of "virsh dump" mutually exclusive In-Reply-To: <4DB1A57A.1010202@redhat.com> References: <4DB14812.2020509@redhat.com> <20110422095709.GK1245361@orkuz.home> <4DB1A57A.1010202@redhat.com> Message-ID: <20110426114056.GM1245361@orkuz.home> On Fri, Apr 22, 2011 at 09:57:46 -0600, Eric Blake wrote: > > @@ -2379,6 +2379,12 @@ virDomainCoreDump(virDomainPtr domain, const char *to, int flags) > > goto error; > > } > > > > + if ((flags & VIR_DUMP_CRASH) && (flags & VIR_DUMP_LIVE)) { > > + virLibDomainError(VIR_ERR_INVALID_ARG, > > + _("crash and live flags are mutually exclusive")); > > > ACK, but incomplete. A few lines earlier, the documentation states: > > * @flags: extra flags, currently unused > * > * This method will dump the core of a domain on a given file for analysis. > > It would be a wise time to update the docs at the same time :) Sure. I fixed that and pushed, thanks. Jirka From jdenemar at redhat.com Tue Apr 26 11:41:18 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Tue, 26 Apr 2011 13:41:18 +0200 Subject: [libvirt] [PATCH] qemu: Add flags checking in DomainCoreDump In-Reply-To: <4DB1A49B.8030107@redhat.com> References: <4DB1A49B.8030107@redhat.com> Message-ID: <20110426114118.GN1245361@orkuz.home> On Fri, Apr 22, 2011 at 09:54:03 -0600, Eric Blake wrote: > On 04/22/2011 04:03 AM, Jiri Denemark wrote: > > --- > > src/qemu/qemu_driver.c | 5 ++++- > > 1 files changed, 4 insertions(+), 1 deletions(-) > > > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > > index f6e503a..f35616d 100644 > > --- a/src/qemu/qemu_driver.c > > +++ b/src/qemu/qemu_driver.c > > @@ -2345,7 +2345,8 @@ getCompressionType(struct qemud_driver *driver) > > > > static int qemudDomainCoreDump(virDomainPtr dom, > > const char *path, > > - int flags ATTRIBUTE_UNUSED) { > > + int flags) > > +{ > > struct qemud_driver *driver = dom->conn->privateData; > > virDomainObjPtr vm; > > int resume = 0, paused = 0; > > @@ -2353,6 +2354,8 @@ static int qemudDomainCoreDump(virDomainPtr dom, > > virDomainEventPtr event = NULL; > > qemuDomainObjPrivatePtr priv; > > > > + virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1); > > + > > ACK. Pushed, thanks. Jirka From eblake at redhat.com Tue Apr 26 14:26:50 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 26 Apr 2011 08:26:50 -0600 Subject: [libvirt] [PATCH V2] xen: check if device is assigned to guest before reattaching In-Reply-To: <1294384518-15492-1-git-send-email-yuzhang@redhat.com> References: <1294384518-15492-1-git-send-email-yuzhang@redhat.com> Message-ID: <4DB6D62A.8040003@redhat.com> On 01/07/2011 12:15 AM, Yufang Zhang wrote: > Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=664059 > > This is the version2 patch for BZ#664059. Reattaching pci device back to > host without destroying guest or detaching device from guest would cause > host to crash. This patch adds a check before doing device reattach. If > the device is being assigned to guest, libvirt refuses to reattach device > to host. The patch only works for Xen, for it just checks xenstore to get > pci device information. > > Signed-off-by: Yufang Zhang > --- > src/xen/xen_driver.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 67 insertions(+), 0 deletions(-) Wow, just noticed that this hasn't had any review - does it still apply to the latest upstream? > > diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c > index 4c11b11..318bb6a 100644 > --- a/src/xen/xen_driver.c > +++ b/src/xen/xen_driver.c > @@ -1891,11 +1891,70 @@ out: > } > > static int > +xenUnifiedNodeDeviceAssignedDomainId (virNodeDevicePtr dev) > +{ > + int numdomains; > + int ret = -1, i; > + int *ids = NULL; > + char *bdf = NULL; > + char *xref = NULL; > + unsigned int domain, bus, slot, function; > + virConnectPtr conn = dev->conn; > + xenUnifiedPrivatePtr priv = conn->privateData; > + > + /* Get active domains */ > + numdomains = xenUnifiedNumOfDomains(conn); > + if (numdomains < 0) { > + return ret; > + } > + if (numdomains > 0){ > + if (VIR_ALLOC_N(ids, numdomains) < 0){ Formatting nit - space before {, as in: if (VIR_ALLOC_N(ids, numdomains) < 0) { > + virReportOOMError(); > + goto out; > + } > + if ((numdomains = xenUnifiedListDomains(conn, &ids[0], numdomains)) < 0){ > + goto out; > + } > + } > + > + /* Get pci bdf */ > + if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) > + goto out; > + > + if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x", > + domain, bus, slot, function) < 0) { > + virReportOOMError(); > + goto out; > + } > + > + /* Check if bdf is assigned to one of active domains */ > + for (i = 0; i < numdomains; i++ ){ Again, a formatting nit: for (i = 0; i < numdomains; i++) { > + xenUnifiedLock(priv); > + xref = xenStoreDomainGetPCIID(conn, ids[i], bdf); > + xenUnifiedUnlock(priv); This locks and unlocks around every iteration of the loop. Would it be better to hold the lock for the entire loop duration, so that the action is atomic (no other thread can interrupt things), or is it better to drop the lock each iteration? I'm not as familiar with the xen architecture to give a good answer to this off the top of my head. > + if (xref == NULL) > + continue; > + else { Formatting - if one branch of an if-else has {}, then both need it: if (xref == NULL) { continue; } else { > + ret = ids[i]; > + break; > + } > + } > + > + VIR_FREE(xref); > + VIR_FREE(bdf); > +out: > + VIR_FREE(ids); > + > + return ret; > +} > + > +static int > xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev) > { > pciDevice *pci; > unsigned domain, bus, slot, function; > int ret = -1; > + int domid; > > if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) > return -1; > @@ -1904,6 +1963,14 @@ xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev) > if (!pci) > return -1; > > + /* Check if device is assigned to an active guest */ > + if ((domid = xenUnifiedNodeDeviceAssignedDomainId(dev)) >= 0){ > + xenUnifiedError(VIR_ERR_INTERNAL_ERROR, > + _("Device %s has been assigned to guest %d"), > + dev->name, domid); > + goto out; > + } > + > if (pciReAttachDevice(pci, NULL) < 0) > goto out; > -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From laine at laine.org Tue Apr 26 15:19:54 2011 From: laine at laine.org (Laine Stump) Date: Tue, 26 Apr 2011 11:19:54 -0400 Subject: [libvirt] [PATCHv2] build: use gnulib passfd for simpler SCM_RIGHTS code In-Reply-To: <4DB58352.40608@redhat.com> References: <1303330531-25818-1-git-send-email-eblake@redhat.com> <1303420621-25090-1-git-send-email-eblake@redhat.com> <4DB52014.50209@laine.org> <4DB58352.40608@redhat.com> Message-ID: <4DB6E29A.2060009@laine.org> On 04/25/2011 10:21 AM, Eric Blake wrote: > On 04/25/2011 01:17 AM, Laine Stump wrote: >>> @@ -1529,26 +1513,20 @@ virFileOpenAs(const char *path, int openflags, >>> mode_t mode, >>> VIR_FORCE_CLOSE(pair[1]); >>> >>> do { >>> - ret = recvmsg(pair[0],&msg, 0); >>> + ret = recvfd(pair[0], 0); >>> } while (ret< 0&& errno == EINTR); > ret == -1 and errno == EACCES on failure to transfer fd... > >>> - if (ret< 0) { >>> + if (ret< 0&& errno != EACCES) { >>> ret = -errno; >>> VIR_FORCE_CLOSE(pair[0]); >>> while ((waitret = waitpid(pid, NULL, 0) == -1) >>> && (errno == EINTR)); >>> goto parenterror; >>> + } else { >>> + fd = ret; >>> } > so now fd == -1... > > >> if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == -EACCES || >> fd == -1) { >> /* fall back to the simpler method, which works better in >> * some cases */ >> return virFileOpenAsNoFork(path, openflags, mode, uid, gid, flags); >> } > so this uses the fallback code, regardless of child exit status, and we > also ensured that the child got reaped. > >> What if errno == EACCES? Will we be getting all the error recovery we >> need in the caller? > Yes. Okay. In that case, ACK. From laine at laine.org Tue Apr 26 15:27:16 2011 From: laine at laine.org (Laine Stump) Date: Tue, 26 Apr 2011 11:27:16 -0400 Subject: [libvirt] [PATCH] Move call to virReportOOMError into virFileBuildPath In-Reply-To: <20110424094800.GA6638@sbox> References: <20110424094800.GA6638@sbox> Message-ID: <4DB6E454.1020802@laine.org> On 04/24/2011 05:48 AM, Matthias Bolte wrote: > Suggested by Daniel P. Berrange > --- > src/conf/nwfilter_conf.c | 5 +---- > src/conf/storage_conf.c | 7 +------ > src/util/util.c | 2 ++ > src/xen/xen_inotify.c | 1 - > src/xen/xm_internal.c | 5 +---- > 5 files changed, 5 insertions(+), 15 deletions(-) ACK. > diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c > index 327fab3..09dc32b 100644 > --- a/src/conf/nwfilter_conf.c > +++ b/src/conf/nwfilter_conf.c > @@ -2588,10 +2588,8 @@ virNWFilterLoadAllConfigs(virConnectPtr conn, > if (!virFileHasSuffix(entry->d_name, ".xml")) > continue; > > - if (!(path = virFileBuildPath(configDir, entry->d_name, NULL))) { > - virReportOOMError(); > + if (!(path = virFileBuildPath(configDir, entry->d_name, NULL))) > continue; > - } > > nwfilter = virNWFilterObjLoad(conn, nwfilters, entry->d_name, path); > if (nwfilter) > @@ -2627,7 +2625,6 @@ virNWFilterObjSaveDef(virNWFilterDriverStatePtr driver, > > if (!(nwfilter->configFile = virFileBuildPath(driver->configDir, > def->name, ".xml"))) { > - virReportOOMError(); > return -1; > } > } > diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c > index 5a069f5..116898d 100644 > --- a/src/conf/storage_conf.c > +++ b/src/conf/storage_conf.c > @@ -1483,14 +1483,11 @@ virStoragePoolLoadAllConfigs(virStoragePoolObjListPtr pools, > if (!virFileHasSuffix(entry->d_name, ".xml")) > continue; > > - if (!(path = virFileBuildPath(configDir, entry->d_name, NULL))) { > - virReportOOMError(); > + if (!(path = virFileBuildPath(configDir, entry->d_name, NULL))) > continue; > - } > > if (!(autostartLink = virFileBuildPath(autostartDir, entry->d_name, > NULL))) { > - virReportOOMError(); > VIR_FREE(path); > continue; > } > @@ -1529,13 +1526,11 @@ virStoragePoolObjSaveDef(virStorageDriverStatePtr driver, > > if (!(pool->configFile = virFileBuildPath(driver->configDir, > def->name, ".xml"))) { > - virReportOOMError(); > return -1; > } > > if (!(pool->autostartLink = virFileBuildPath(driver->autostartDir, > def->name, ".xml"))) { > - virReportOOMError(); > VIR_FREE(pool->configFile); > return -1; > } > diff --git a/src/util/util.c b/src/util/util.c > index d4d2610..3948b01 100644 > --- a/src/util/util.c > +++ b/src/util/util.c > @@ -1851,10 +1851,12 @@ virFileBuildPath(const char *dir, const char *name, const char *ext) > > if (ext == NULL) { > if (virAsprintf(&path, "%s/%s", dir, name)< 0) { > + virReportOOMError(); > return NULL; > } > } else { > if (virAsprintf(&path, "%s/%s%s", dir, name, ext)< 0) { > + virReportOOMError(); > return NULL; > } > } > diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c > index d809c45..9dde72c 100644 > --- a/src/xen/xen_inotify.c > +++ b/src/xen/xen_inotify.c > @@ -415,7 +415,6 @@ xenInotifyOpen(virConnectPtr conn, > > /* Build the full file path */ > if (!(path = virFileBuildPath(priv->configDir, ent->d_name, NULL))) { > - virReportOOMError(); > closedir(dh); > return -1; > } > diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c > index db47a02..f9f52b5 100644 > --- a/src/xen/xm_internal.c > +++ b/src/xen/xm_internal.c > @@ -388,7 +388,6 @@ int xenXMConfigCacheRefresh (virConnectPtr conn) { > > /* Build the full file path */ > if (!(path = virFileBuildPath(priv->configDir, ent->d_name, NULL))) { > - virReportOOMError(); > closedir(dh); > return -1; > } > @@ -1134,10 +1133,8 @@ virDomainPtr xenXMDomainDefineXML(virConnectPtr conn, const char *xml) > entry = NULL; > } > > - if (!(filename = virFileBuildPath(priv->configDir, def->name, NULL))) { > - virReportOOMError(); > + if (!(filename = virFileBuildPath(priv->configDir, def->name, NULL))) > goto error; > - } > > if (xenXMConfigSaveFile(conn, filename, def)< 0) > goto error; From laine at laine.org Tue Apr 26 15:43:48 2011 From: laine at laine.org (Laine Stump) Date: Tue, 26 Apr 2011 11:43:48 -0400 Subject: [libvirt] [PATCH] free buf->content when vsnprintf() failed In-Reply-To: <4DB63F1D.6010001@cn.fujitsu.com> References: <4DB63F1D.6010001@cn.fujitsu.com> Message-ID: <4DB6E834.1020305@laine.org> On 04/25/2011 11:42 PM, Wen Congyang wrote: > When buf->error is 1, we do not return buf->content in the function > virBufferContentAndReset(). So we should free buf->content when > vsnprintf() failed. > > --- > src/util/buf.c | 6 ++++++ > 1 files changed, 6 insertions(+), 0 deletions(-) > > diff --git a/src/util/buf.c b/src/util/buf.c > index 7557ad1..fdb7660 100644 > --- a/src/util/buf.c > +++ b/src/util/buf.c > @@ -241,6 +241,9 @@ virBufferVSprintf(const virBufferPtr buf, const char *format, ...) > size = buf->size - buf->use; > if ((count = vsnprintf(&buf->content[buf->use], > size, format, argptr))< 0) { > + VIR_FREE(buf->content); > + buf->size = 0; > + buf->use = 0; > buf->error = 1; These four lines are equivalent to calling virBufferNoMemory(buf). It would be more compact to do that instead. (as a matter of fact, virBufferNoMemory is the only other place that buf->error is ever set to 1, so it really is a "virBufferSetError() function). > goto err; > } > @@ -259,6 +262,9 @@ virBufferVSprintf(const virBufferPtr buf, const char *format, ...) > size = buf->size - buf->use; > if ((count = vsnprintf(&buf->content[buf->use], > size, format, argptr))< 0) { > + VIR_FREE(buf->content); > + buf->size = 0; > + buf->use = 0; > buf->error = 1; > goto err; > } From eblake at redhat.com Tue Apr 26 16:11:27 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 26 Apr 2011 10:11:27 -0600 Subject: [libvirt] [PATCH] tests: More unit tests for internal hash APIs In-Reply-To: References: <0ebc29ed7078c909b92f692d28c572f0c05ff9b9.1302629114.git.jdenemar@redhat.com> Message-ID: <4DB6EEAF.5000607@redhat.com> On 04/19/2011 07:22 AM, Jiri Denemark wrote: > This adds several tests for remaining hash APIs (custom > hasher/comparator functions are not covered yet, though). > > All tests pass both before and after the "Simplify hash implementation". > --- > src/util/hash.c | 18 +++ > src/util/hash.h | 1 + > tests/hashdata.h | 237 +++++++++++++++++++++++++++++++++++- > tests/hashtest.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 615 insertions(+), 2 deletions(-) > > diff --git a/src/util/hash.c b/src/util/hash.c > index fc7652d..5dbc7f1 100644 > --- a/src/util/hash.c > +++ b/src/util/hash.c > @@ -499,6 +499,24 @@ virHashSize(virHashTablePtr table) > } > > /** > + * virHashTableSize: > + * @table: the hash table > + * > + * Query the size of the hash @table, i.e., number of keys in the table. This is confusing. I think virHashSize is already the number of keys (or elements) in the table; whereas virHashTableSize is the number of buckets (> keys if table is not full, < keys if table is using lots of collision chains but hasn't had a reason to grow). I'd rather use the term "buckets" than "keys" for this documentation. > + * > + * Returns the number of keys in the hash table or > + * -1 in case of error > + */ > +int > +virHashTableSize(virHashTablePtr table) > +{ > + if (table == NULL) > + return -1; > + return table->size; > +} Nice, but does it also need an addition to src/libvirt_private.syms? > "d1a564b2-c7f3-4b76-8712-3b8f5aae6ded", > - "0e614f33-c1da-4cfe-b6d5-65ecd2d066f2" > + "0e614f33-c1da-4cfe-b6d5-65ecd2d066f2", > +/* [250] */ "334fdaba-f373-42ff-8546-219c1463a7c5", > + "d4ff408e-8d43-46ff-94a4-bcfa6c994776", > +/* [253] */ "d1abd887-d5de-46b0-88d6-f71f31a61305", > +/* [254] */ "1d76af65-64d6-4211-b1b5-f5b799595e4d", > +/* [255] */ "b3ad4257-29b0-4c44-b7a7-95f1d102769c" Put a trailing comma on this one (if you had done that last time, we wouldn't have the - vs. + line for 0e614f33... a few lines earlier). > +const char *uuids_new[] = { > + "a103cc42-d0e5-40fb-8f7f-3c1bee93e327", > + "01e13dc5-e65b-4988-a0cc-0d2f1f1e10fe", > + "71f3678a-a8c6-4176-a26e-c34779067135", > + "4f054508-22d5-49e1-9962-7508225c8b16", > + "e572116b-5b7b-45fd-bbe9-296029ce16b5", > + "695c8cfe-9830-4d9a-be67-50a124cefb76", > + "ea244996-645b-4a19-ad4a-48f3022b8e94", > + "0fd98758-9cc4-4779-b403-95ae3500f138", > + "b86772b4-0728-46ae-99e8-027799697838", > + "1c0cd559-81cd-4c27-8e24-6aef6f5af7f1", > + "2a37fe4a-8825-4fd6-9284-e1606967548a", > + "5920cc9d-62a3-4772-9e73-eb97f0bc483c", > + "53c215dd-bdba-4fdc-887a-86ab6f860df4" Trailing comma here, too. > +static int > +testHashRemoveSetIter(const void *payload ATTRIBUTE_UNUSED, > + const void *name, > + const void *data) > +{ > + int *count = (int *) data; > + bool rem = false; > + int i; > + > + for (i = 0; i < ARRAY_CARDINALITY(uuids_subset); i++) { > + if (STREQ(uuids_subset[i], name)) { > + rem = true; > + break; > + } > + } > + > + if (rem || rand() % 2) { Do we need to seed the random number pseudo-generator, so that the test is reproducible? I guess I'm okay if it's not seeded, though. Overall, this looks like a good patch; the fact that it passes 'make check' speaks highly, and it is some good additional coverage. ACK with nits fixed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Tue Apr 26 16:38:46 2011 From: eblake at redhat.com (Eric Blake) Date: Tue, 26 Apr 2011 10:38:46 -0600 Subject: [libvirt] [PATCHv2] build: use gnulib passfd for simpler SCM_RIGHTS code In-Reply-To: <4DB6E29A.2060009@laine.org> References: <1303330531-25818-1-git-send-email-eblake@redhat.com> <1303420621-25090-1-git-send-email-eblake@redhat.com> <4DB52014.50209@laine.org> <4DB58352.40608@redhat.com> <4DB6E29A.2060009@laine.org> Message-ID: <4DB6F516.8080608@redhat.com> On 04/26/2011 09:19 AM, Laine Stump wrote: >>>> do { >>>> - ret = recvmsg(pair[0],&msg, 0); >>>> + ret = recvfd(pair[0], 0); >>>> } while (ret< 0&& errno == EINTR); >> ret == -1 and errno == EACCES on failure to transfer fd... >> >>> if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == >>> -EACCES || >>> fd == -1) { >>> /* fall back to the simpler method, which works better in >>> * some cases */ >>> return virFileOpenAsNoFork(path, openflags, mode, uid, >>> gid, flags); >>> } >> so this uses the fallback code, regardless of child exit status, and we >> also ensured that the child got reaped. >> >>> What if errno == EACCES? Will we be getting all the error recovery we >>> need in the caller? >> Yes. Another way to look at it - for all failures except EACCES, the child is immediately reaped and the overall function failed; with EACCES, we still want to try the non-forking fallback. > > Okay. In that case, ACK. Thanks for the review; pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From bbgordonn at fastmail.fm Tue Apr 26 15:48:34 2011 From: bbgordonn at fastmail.fm (B Gordon) Date: Tue, 26 Apr 2011 08:48:34 -0700 Subject: [libvirt] libvirt and redis Message-ID: <1303832914.3491.1445290025@webmail.messagingengine.com> Is there interest in teaching libvirt to store configs in a DB? I'd like to talk out what's desirable in the scope and design with someone who knows libvirt. My eventual goal is to synchronize config between multiple libvirtds using Redis. I've been playing with a prototype that abstracts config writing and reading into handlers that can be selected at run time or from libvirtd.conf. This was to get me some familiarity--please tell me what aspects I should change to suit the rest of libvirt. The high-level, emphasizing the more questionable aspects: * "conf drivers" that cargo-cult the jargon used in "drivers" a bit even though they (currently) aren't quite a fit with the way current ones are used. * One global conf driver, because it needs to be accessed in other state drivers when a connection is not currently present in the API. * conf drivers present a file system-like key/value API to the rest of libvirt to minimize disruption. They receive an XML string to store and must be able to list the keys in a given "directory". Retrieval is done by passing an optional callback to xml.c that it will use instead of xmlCtxtReadFile(). * Keys should probably not include the full sysconfdir path, and many other ways the prototype is too FS-like. * With a relational DB, API calls to store each type of libvirt struct might make more sense than formatted XML strings. I have not tried to do this and vaguely hope that working with XML in a relational DB would be acceptable or that those calls could be added later. Using the DB's native XML handling might better for abstraction, actually. * The conf driver needs a way to receive parameters from libvirtd.conf. URI parsing? Some other key-value format? As a low-level example, here's my (current, expected to change based on feedback!) conversion of domain_conf.c: diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b6aaf33..0c7bb3c 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -47,6 +47,7 @@ #include "storage_file.h" #include "files.h" #include "bitmap.h" +#include "conf_driver.h" #define VIR_FROM_THIS VIR_FROM_DOMAIN @@ -6158,7 +6159,7 @@ virDomainDefParse(const char *xmlStr, xmlDocPtr xml; virDomainDefPtr def = NULL; - if ((xml = virXMLParse(filename, xmlStr, "domain.xml"))) { + if ((xml = virConfParse(filename, xmlStr, "domain.xml"))) { def = virDomainDefParseNode(caps, xml, xmlDocGetRootElement(xml), flags); xmlFreeDoc(xml); } @@ -6245,7 +6246,7 @@ virDomainObjPtr virDomainObjParseFile(virCapsPtr caps, xmlDocPtr xml; virDomainObjPtr obj = NULL; - if ((xml = virXMLParseFile(filename))) { + if ((xml = virConfParse(filename, NULL, filename))) { obj = virDomainObjParseNode(caps, xml, xmlDocGetRootElement(xml)); xmlFreeDoc(xml); } @@ -8324,46 +8325,26 @@ int virDomainSaveXML(const char *configDir, const char *xml) { char *configFile = NULL; - int fd = -1, ret = -1; - size_t towrite; + int ret = -1; + int err; if ((configFile = virDomainConfigFile(configDir, def->name)) == NULL) goto cleanup; - if (virFileMakePath(configDir)) { - virReportSystemError(errno, + if ((err = virConfMakePath(configDir, 0))) { + virReportSystemError(err, _("cannot create config directory '%s'"), configDir); goto cleanup; } - if ((fd = open(configFile, - O_WRONLY | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR )) < 0) { - virReportSystemError(errno, - _("cannot create config file '%s'"), - configFile); - goto cleanup; - } - - towrite = strlen(xml); - if (safewrite(fd, xml, towrite) < 0) { - virReportSystemError(errno, - _("cannot write config file '%s'"), - configFile); - goto cleanup; - } - - if (VIR_CLOSE(fd) < 0) { - virReportSystemError(errno, - _("cannot save config file '%s'"), - configFile); + if (virConfSave(configFile, xml, 0) < 0) { goto cleanup; } ret = 0; + cleanup: - VIR_FORCE_CLOSE(fd); VIR_FREE(configFile); return ret; @@ -8441,7 +8422,7 @@ static virDomainObjPtr virDomainLoadConfig(virCapsPtr caps, if ((autostartLink = virDomainConfigFile(autostartDir, name)) == NULL) goto error; - if ((autostart = virFileLinkPointsTo(autostartLink, configFile)) < 0) + if ((autostart = virConfLinkPointsTo(autostartLink, configFile, 0)) < 0) goto error; if (!(dom = virDomainAssignDef(caps, doms, def, false))) @@ -8514,12 +8495,12 @@ int virDomainLoadAllConfigs(virCapsPtr caps, virDomainLoadConfigNotify notify, void *opaque) { - DIR *dir; - struct dirent *entry; + virConfDirPtr dir; + virConfDirEntryPtr entry; VIR_INFO("Scanning for configs in %s", configDir); - if (!(dir = opendir(configDir))) { + if (!(dir = virConfOpenDir(configDir, 0))) { if (errno == ENOENT) return 0; virReportSystemError(errno, @@ -8528,23 +8509,17 @@ int virDomainLoadAllConfigs(virCapsPtr caps, return -1; } - while ((entry = readdir(dir))) { + while ((entry = virConfReadDir(dir, 0))) { virDomainObjPtr dom; - if (entry->d_name[0] == '.') - continue; - - if (!virFileStripSuffix(entry->d_name, ".xml")) - continue; - /* NB: ignoring errors, so one malformed config doesn't kill the whole process */ - VIR_INFO("Loading config file '%s.xml'", entry->d_name); + VIR_INFO("Loading config file '%s.xml'", entry->name); if (liveStatus) dom = virDomainLoadStatus(caps, doms, configDir, - entry->d_name, + entry->name, notify, opaque); else @@ -8552,7 +8527,7 @@ int virDomainLoadAllConfigs(virCapsPtr caps, doms, configDir, autostartDir, - entry->d_name, + entry->name, notify, opaque); if (dom) { @@ -8562,7 +8537,7 @@ int virDomainLoadAllConfigs(virCapsPtr caps, } } - closedir(dir); + virConfCloseDir(dir, 0); return 0; } @@ -8580,9 +8555,9 @@ int virDomainDeleteConfig(const char *configDir, goto cleanup; /* Not fatal if this doesn't work */ - unlink(autostartLink); + virConfDeletePath(autostartLink, 0); - if (unlink(configFile) < 0 && + if (virConfDeletePath(autostartLink, 0) < 0 && errno != ENOENT) { virReportSystemError(errno, _("cannot remove config %s"), @@ -8863,7 +8838,7 @@ virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, char *creation = NULL, *state = NULL; struct timeval tv; - xml = virXMLParse(NULL, xmlStr, "domainsnapshot.xml"); + xml = virXMLParseString(xmlStr, "domainsnapshot.xml"); if (!xml) { virDomainReportError(VIR_ERR_XML_ERROR, "%s",_("failed to parse snapshot xml document")); -- http://www.fastmail.fm - Choose from over 50 domains or use your own From cfergeau at redhat.com Tue Apr 26 20:03:16 2011 From: cfergeau at redhat.com (Christophe Fergeau) Date: Tue, 26 Apr 2011 22:03:16 +0200 Subject: [libvirt] [PATCH] util: warn when passing a non-pointer to VIR_FREE In-Reply-To: <4DB210F9.5040503@redhat.com> References: <20110422170413.GC3219@teriyaki.redhat.com> <1303496484-17313-1-git-send-email-cfergeau@redhat.com> <4DB210F9.5040503@redhat.com> Message-ID: <20110426200315.GA26565@teriyaki.redhat.com> Hey, On Fri, Apr 22, 2011 at 05:36:25PM -0600, Eric Blake wrote: > That evaluates ptr twice. We can do better, by exploiting that the > ternary operator can be used to determine the type of an expression > without evaluating it. Gcc allows 1?(void*)expr:pointer (the resulting > type is void*), but hates 1?(void*)expr:int (promoting to int provokes a > warning): > > cc1: warnings being treated as errors > remote.c: In function 'remoteDispatchListNetworks': > remote.c:3684:70: error: pointer/integer type mismatch in conditional > expression > > So how about: Sorry for the late answer, but this looks good to me too. Let's hope gcc doesn't get too clever and never stops warning about this. Thanks, Christophe -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 198 bytes Desc: not available URL: From jyang at redhat.com Wed Apr 27 03:46:33 2011 From: jyang at redhat.com (Osier Yang) Date: Wed, 27 Apr 2011 11:46:33 +0800 Subject: [libvirt] [PATCH] build: Fix problem of building Python bindings Message-ID: <1303875993-9780-1-git-send-email-jyang@redhat.com> If one specify "--with-python=yes" but no python-devel package is installed, we ignore it with just a notice message, which doesn't give clear guide to user. --- configure.ac | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 190bf40..758c893 100644 --- a/configure.ac +++ b/configure.ac @@ -1917,15 +1917,13 @@ if test "$with_python" != "no" ; then then PYTHON_INCLUDES=-I/usr/include/python$PYTHON_VERSION else - AC_MSG_NOTICE([Could not find python$PYTHON_VERSION/Python.h, disabling bindings]) - with_python=no + AC_MSG_ERROR([You must install python-devel to build Python bindings]) fi fi fi fi else - AC_MSG_NOTICE([Could not find python interpreter, disabling bindings]) - with_python=no + AC_MSG_ERROR([You must install python to build Python bindings]) fi else AC_MSG_NOTICE([Could not find python in $with_python, disabling bindings]) -- 1.7.4 From wency at cn.fujitsu.com Wed Apr 27 05:19:47 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 27 Apr 2011 13:19:47 +0800 Subject: [libvirt] [PATCH] free buf->content when vsnprintf() failed In-Reply-To: <4DB6E834.1020305@laine.org> References: <4DB63F1D.6010001@cn.fujitsu.com> <4DB6E834.1020305@laine.org> Message-ID: <4DB7A773.1040602@cn.fujitsu.com> At 04/26/2011 11:43 PM, Laine Stump Write: > On 04/25/2011 11:42 PM, Wen Congyang wrote: >> When buf->error is 1, we do not return buf->content in the function >> virBufferContentAndReset(). So we should free buf->content when >> vsnprintf() failed. >> >> --- >> src/util/buf.c | 6 ++++++ >> 1 files changed, 6 insertions(+), 0 deletions(-) >> >> diff --git a/src/util/buf.c b/src/util/buf.c >> index 7557ad1..fdb7660 100644 >> --- a/src/util/buf.c >> +++ b/src/util/buf.c >> @@ -241,6 +241,9 @@ virBufferVSprintf(const virBufferPtr buf, const >> char *format, ...) >> size = buf->size - buf->use; >> if ((count = vsnprintf(&buf->content[buf->use], >> size, format, argptr))< 0) { >> + VIR_FREE(buf->content); >> + buf->size = 0; >> + buf->use = 0; >> buf->error = 1; > > These four lines are equivalent to calling virBufferNoMemory(buf). It > would be more compact to do that instead. (as a matter of fact, > virBufferNoMemory is the only other place that buf->error is ever set to > 1, so it really is a "virBufferSetError() function). Yes, virBufferNoMemory() is the only place that buf->error is set to 1 now. I will rename it and update this patch. Thaks for reviewing. Wen Congyang > > >> goto err; >> } >> @@ -259,6 +262,9 @@ virBufferVSprintf(const virBufferPtr buf, const >> char *format, ...) >> size = buf->size - buf->use; >> if ((count = vsnprintf(&buf->content[buf->use], >> size, format, argptr))< 0) { >> + VIR_FREE(buf->content); >> + buf->size = 0; >> + buf->use = 0; >> buf->error = 1; >> goto err; >> } > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list > From usui at mxm.nes.nec.co.jp Wed Apr 27 05:09:04 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Wed, 27 Apr 2011 14:09:04 +0900 Subject: [libvirt] [PATCHv2 1/6] virNodeGetCPUTime: Expose new API In-Reply-To: <20110419104855.GD11901@redhat.com> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> <20110408203312.90723b75.usui@mxm.nes.nec.co.jp> <20110419104855.GD11901@redhat.com> Message-ID: <20110427140904.b07f3579.usui@mxm.nes.nec.co.jp> Hi, I'm sorry for late reply. On Tue, 19 Apr 2011 11:48:55 +0100 "Daniel P. Berrange" wrote: > On Fri, Apr 08, 2011 at 08:33:12PM +0900, Minoru Usui wrote: > > virNodeGetCPUTime: Expose new API > > > > Signed-off-by: Minoru Usui > > --- > > include/libvirt/libvirt.h.in | 64 ++++++++++++++++++++++++++++++++++++++++++ > > src/libvirt_public.syms | 5 +++ > > 2 files changed, 69 insertions(+), 0 deletions(-) > > > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > > index bd36015..154c138 100644 > > --- a/include/libvirt/libvirt.h.in > > +++ b/include/libvirt/libvirt.h.in > > @@ -228,6 +228,57 @@ struct _virNodeInfo { > > unsigned int threads;/* number of threads per core */ > > }; > > > > +/** > > + * virNodeCpuTime: > > + * > > + * a virNodeCpuTime is a structure filled by virNodeGetCpuTime() and providing > > + * the information for the cpu time of the node. > > + */ > > + > > +/** > > + * Cpu Time Statistics Tags: > > + */ > > +typedef enum { > > + /* > > + * The cumulative CPU time which spends by kernel, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_KERNEL = 0, > > + /* > > + * The cumulative CPU time which spends by user processes, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_USER = 1, > > + /* > > + * The cumulative idle CPU time, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_IDLE = 2, > > + /* > > + * The cumulative I/O wait CPU time, > > + * when the node booting up.(in nanoseconds). > > + */ > > + VIR_NODE_CPU_TIME_IOWAIT = 3, > > + /* > > + * The CPU utilization. > > + * The usage value is in percent and 100% represents all CPUs on > > + * the server. > > + */ > > + VIR_NODE_CPU_TIME_UTILIZATION = 4, > > + > > + /* > > + * The number of statistics supported by this version of the interface. > > + * To add new statistics, add them to the enum and increase this value. > > + */ > > + VIR_NODE_CPU_TIME_NR = 5, > > +} virNodeCpuTimeTags; > > + > > +typedef struct _virNodeCpuTime virNodeCpuTime; > > + > > +struct _virNodeCpuTime { > > + virNodeCpuTimeTags tag; > > + unsigned long long val; > > +}; > > I've just remembered that the virSchedParameter, virMemoryParameter and > virBlkioParameter structs all use a string to represent the data value, > rather than an enum. I wonder if we ought todo the same here. > > eg, something like > > #define VIR_NODE_CPUE_FIELD_LENGTH 80 > > struct _virNodeCpuParameter { > char field[VIR_NODE_CPU_FIELD_LENGTH] > unsigned long long value; > }; > > They also have a union for returning different data types, beyond just > 'unsigned long long' but I think that might be overkill here. I implemented this based on virDomainMemoryStats(). Is it better that the patches is based on virDomainGetMemoryParameters()/BlkioParameters()? If so, I'll rebase these patch series. -- Minoru Usui From usui at mxm.nes.nec.co.jp Wed Apr 27 05:09:13 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Wed, 27 Apr 2011 14:09:13 +0900 Subject: [libvirt] [PATCHv2 3/6] virNodeGetCPUTime: Implement public API In-Reply-To: <20110419105330.GE11901@redhat.com> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> <20110408203512.44ba817c.usui@mxm.nes.nec.co.jp> <20110419105330.GE11901@redhat.com> Message-ID: <20110427140913.06e84146.usui@mxm.nes.nec.co.jp> On Tue, 19 Apr 2011 11:53:31 +0100 "Daniel P. Berrange" wrote: > On Fri, Apr 08, 2011 at 08:35:12PM +0900, Minoru Usui wrote: > > virNodeGetCPUTime: Implement public API > > > > Signed-off-by: Minoru Usui > > --- > > src/libvirt.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > 1 files changed, 70 insertions(+), 0 deletions(-) > > > > diff --git a/src/libvirt.c b/src/libvirt.c > > index 8be18d4..a65bfc6 100644 > > --- a/src/libvirt.c > > +++ b/src/libvirt.c > > @@ -4260,6 +4260,76 @@ error: > > } > > > > /** > > + * virNodeGetCpuTime: > > + * @stats: nr_stats-sized array of stat structures (returned) > > + * @nr_stats: number of cpu time statistics requested of the node. > > + * @flags: unused, always pass 0 > > + * > > + * This function provides cpu time statistics of the node. > > + * > > + * Up to 'nr_stats' elements of 'stats' will be populated with cpu time statistics > > + * of the node. Only statistics supported by the driver, and this version of > > + * libvirt will be returned. > > + * > > + * Cpu time Statistics: > > + * > > + * VIR_NODE_CPU_TIME_KERNEL: > > + * The cumulative CPU time which spends by kernel, > > + * when the node booting up.(nanoseconds) > > + * VIR_NODE_CPU_TIME_USER: > > + * The cumulative CPU time which spends by user processes, > > + * when the node booting up.(nanoseconds) > > + * VIR_NODE_CPU_TIME_IDLE: > > + * The cumulative idle CPU time, when the node booting up.(nanoseconds) > > + * VIR_NODE_CPU_TIME_IOWAIT: > > + * The cumulative I/O wait CPU time, when the node booting up.(nanoseconds) > > + * VIR_NODE_CPU_TIME_UTILIZATION: > > + * The CPU utilization. The usage value is in percent and 100% > > + * represents all CPUs on the server. > > + * > > + * Returns: The number of stats provided or -1 in case of failure. > > + */ > > +int virNodeGetCpuTime (virConnectPtr conn, virNodeCpuTimePtr stats, > > + unsigned int nr_stats, unsigned int flags) > > +{ > > + unsigned long nr_stats_ret = 0; > > This ought to have been an 'int' to match the function return > type, and better to declare it later in the block where it was > first used. Ouch. I'll change it. > > + > > + VIR_DEBUG("conn=%p, stats=%p, nr_stats=%u", conn, stats, nr_stats); > > + > > + virResetLastError(); > > + > > + if (!VIR_IS_CONNECT (conn)) { > > + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); > > + virDispatchError(NULL); > > + return 0; > > + } > > + > > + if (flags != 0) { > > + virLibConnError(VIR_ERR_INVALID_ARG, _("flags must be zero")); > > + goto error; > > + } > > Instead of this, use the standard macro we have: > > virCheckFlags(flags, 0); OK. I'll change it. > > + if (!stats || nr_stats == 0) > > + return 0; > > + > > + if (nr_stats > VIR_NODE_CPU_TIME_NR) > > + nr_stats = VIR_NODE_CPU_TIME_NR; > > If we're following the pattern of virDomainGetMemoryParameters/BlkioParameters > then we should have passed in a pointer to nr_stats. It would be allowed to > be zero, in which case the hypervisor would initialize it with the required > size for the number of parameters. > > eg, the signature would be > > int > virNodeGetCpuParameters(virConnectPtr conn, > virNodeCpuParameterPtr params, > int *nparams, unsigned int flags) > > and then check > > if ((nparams == NULL) || (*nparams < 0)) { > virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); > goto error; > } I'll rebase these patches, if it's better to be based on virDomainGetMemoryParameters()/BlkioParameters()? > > + > > + if (conn->driver->nodeGetCpuTime) { > > + nr_stats_ret = conn->driver->nodeGetCpuTime (conn, stats, nr_stats, flags); > > + if (nr_stats_ret == -1) > > + goto error; > > + return nr_stats_ret; > > + } > > + > > + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); > > + > > +error: > > + virDispatchError(conn); > > + return -1; > > +} > > + > > +/** > > > Daniel > -- > |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| > |: http://libvirt.org -o- http://virt-manager.org :| > |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| > |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- Minoru Usui From usui at mxm.nes.nec.co.jp Wed Apr 27 05:09:24 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Wed, 27 Apr 2011 14:09:24 +0900 Subject: [libvirt] [PATCHv2 4/6] virNodeGetCPUTime: Implement remote protocol In-Reply-To: <20110419105800.GF11901@redhat.com> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> <20110408203602.7765f701.usui@mxm.nes.nec.co.jp> <20110419105800.GF11901@redhat.com> Message-ID: <20110427140924.9bf93dba.usui@mxm.nes.nec.co.jp> On Tue, 19 Apr 2011 11:58:00 +0100 "Daniel P. Berrange" wrote: > On Fri, Apr 08, 2011 at 08:36:02PM +0900, Minoru Usui wrote: > > virNodeGetCPUTime: Implement remote protocol > > > > Signed-off-by: Minoru Usui > > --- > > daemon/remote.c | 48 +++++++++++++++++++++++++++++++++++ > > daemon/remote_dispatch_args.h | 1 + > > daemon/remote_dispatch_prototypes.h | 8 ++++++ > > daemon/remote_dispatch_ret.h | 1 + > > daemon/remote_dispatch_table.h | 5 +++ > > src/remote/remote_driver.c | 37 +++++++++++++++++++++++++++ > > src/remote/remote_protocol.c | 33 ++++++++++++++++++++++++ > > src/remote/remote_protocol.h | 28 ++++++++++++++++++++ > > src/remote/remote_protocol.x | 20 ++++++++++++++- > > src/remote_protocol-structs | 14 ++++++++++ > > 10 files changed, 194 insertions(+), 1 deletions(-) > > > > diff --git a/daemon/remote.c b/daemon/remote.c > > index 1700c2d..a6c21eb 100644 > > --- a/daemon/remote.c > > +++ b/daemon/remote.c > > @@ -679,6 +679,54 @@ remoteDispatchGetCapabilities (struct qemud_server *server ATTRIBUTE_UNUSED, > > } > > > > static int > > +remoteDispatchNodeGetCpuTime (struct qemud_server *server ATTRIBUTE_UNUSED, > > + struct qemud_client *client ATTRIBUTE_UNUSED, > > + virConnectPtr conn, > > + remote_message_header *hdr ATTRIBUTE_UNUSED, > > + remote_error *rerr, > > + remote_node_get_cpu_time_args *args, > > + remote_node_get_cpu_time_ret *ret) > > +{ > > + struct _virNodeCpuTime *stats; > > + unsigned int nr_stats, i; > > + > > + if (args->maxStats > REMOTE_NODE_CPU_TIME_MAX) { > > + remoteDispatchFormatError (rerr, "%s", > > + _("maxStats > REMOTE_NODE_CPU_TIME_MAX")); > > + return -1; > > + } > > + > > + /* Allocate stats array for making dispatch call */ > > + if (VIR_ALLOC_N(stats, args->maxStats) < 0) { > > + remoteDispatchOOMError(rerr); > > + return -1; > > + } > > + > > + nr_stats = virNodeGetCpuTime (conn, stats, args->maxStats, 0); > > + if (nr_stats == -1) { > > + VIR_FREE(stats); > > + remoteDispatchConnError(rerr, conn); > > + return -1; > > + } > > + > > + /* Allocate return buffer */ > > + if (VIR_ALLOC_N(ret->stats.stats_val, args->maxStats) < 0) { > > + VIR_FREE(stats); > > + remoteDispatchOOMError(rerr); > > + return -1; > > + } > > + > > + /* Copy the stats into the xdr return structure */ > > + for (i = 0; i < nr_stats; i++) { > > + ret->stats.stats_val[i].tag = stats[i].tag; > > + ret->stats.stats_val[i].val = stats[i].val; > > + } > > + ret->stats.stats_len = nr_stats; > > + VIR_FREE(stats); > > + return 0; > > +} > > I recently re-structured all the APIs in this file, to follow a > new coding style. This method would need to be updated to match. OK. I'll change this to following style. > { > virNodeCpuTime *stats = NULL; > int nr_stats, i; > int rv = -1; > > if (args->maxStats > REMOTE_NODE_CPU_TIME_MAX) { > virNetError (VIR_ERR_INTERNAL_ERROR, "%s", > _("maxStats > REMOTE_NODE_CPU_TIME_MAX")); > goto cleanup; > } > > /* Allocate stats array for making dispatch call */ > if (VIR_ALLOC_N(stats, args->maxStats) < 0) { > virReportOOMError(); > goto cleanup; > } > > if ((nr_stats = virNodeGetCpuTime (conn, stats, args->maxStats, 0)) < 0) > goto cleanup; > > /* Allocate return buffer */ > if (VIR_ALLOC_N(ret->stats.stats_val, args->maxStats) < 0) { > virReportOOMError(); > goto cleanup; > } > > /* Copy the stats into the xdr return structure */ > for (i = 0; i < nr_stats; i++) { > ret->stats.stats_val[i].tag = stats[i].tag; > ret->stats.stats_val[i].val = stats[i].val; > } > ret->stats.stats_len = nr_stats; > rv = 0; > > cleanup: > if (rv < 0) > remoteDispatchError(rerr); > VIR_FREE(stats); > return rv; > } > > > Of course, if we change the public API as I suggest, it'll need a couple > more changes too. Yes. I'll change this to suite public API, of cource. > > Regards, > Daniel > -- > |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| > |: http://libvirt.org -o- http://virt-manager.org :| > |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| > |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- Minoru Usui From usui at mxm.nes.nec.co.jp Wed Apr 27 05:09:36 2011 From: usui at mxm.nes.nec.co.jp (Minoru Usui) Date: Wed, 27 Apr 2011 14:09:36 +0900 Subject: [libvirt] [PATCHv2 5/6] virNodeGetCPUTime: Implement virsh support In-Reply-To: <20110419110134.GG11901@redhat.com> References: <20110408201932.eb809394.usui@mxm.nes.nec.co.jp> <20110408203652.eb88d49c.usui@mxm.nes.nec.co.jp> <20110419110134.GG11901@redhat.com> Message-ID: <20110427140936.385fda46.usui@mxm.nes.nec.co.jp> On Tue, 19 Apr 2011 12:01:34 +0100 "Daniel P. Berrange" wrote: > On Fri, Apr 08, 2011 at 08:36:52PM +0900, Minoru Usui wrote: > > virNodeGetCPUTime: Implement virsh support > > > > Add nodecputime subcommand to virsh. > > This subcommand prints below output. > > > > [Linux] > > # build/tools/virsh nodecputime > > usage: 2.8% > > user : 0.8% > > system: 1.9% > > idle : 97.2% > > iowait: 0.0% > > > > [can get cpu utilization directly(ESX?)] > > # build/tools/virsh nodecputime > > usage: 2.8% > > > > Signed-off-by: Minoru Usui > > --- > > tools/virsh.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > tools/virsh.pod | 4 ++ > > 2 files changed, 100 insertions(+), 0 deletions(-) > > > > diff --git a/tools/virsh.c b/tools/virsh.c > > index 19e3449..93288ba 100644 > > --- a/tools/virsh.c > > +++ b/tools/virsh.c > > @@ -3388,6 +3388,101 @@ cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) > > } > > > > /* > > + * "nodecputime" command > > + */ > > +static const vshCmdInfo info_nodecputime[] = { > > + {"help", N_("Prints cpu utilizatoin of the node.")}, > > + {"desc", N_("Returns cpu utilizatoin of the node.(%)")}, > > + {NULL, NULL} > > +}; > > + > > +static int > > +cmdNodeCpuTime(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) > > +{ > > + int i, j; > > + int flag_utilization = FALSE; > > + virNodeCpuTime stats[VIR_NODE_CPU_TIME_NR]; > > + int nr_stats; > > + struct cpu_time { > > + unsigned long long user; > > + unsigned long long sys; > > + unsigned long long idle; > > + unsigned long long iowait; > > + unsigned long long util; > > + } cpu_time[2]; > > + double user_time, sys_time, idle_time, iowait_time, total_time; > > + double usage; > > + > > + if (!vshConnectionUsability(ctl, ctl->conn)) > > + return FALSE; > > + > > + memset(cpu_time, 0, sizeof(struct cpu_time) * 2); > > + > > + for (i = 0; i < 2; i++) { > > + memset(stats, 0, sizeof(virNodeCpuTime) * VIR_NODE_CPU_TIME_NR); > > + nr_stats = virNodeGetCpuTime(ctl->conn, &stats[0], > > + VIR_NODE_CPU_TIME_NR, 0); > > + if (nr_stats < 0) { > > + vshError(ctl, "%s", _("failed to get cpu time of the node.")); > > + return FALSE; > > + } > > + > > + for (j = 0; j < nr_stats; j++) { > > + switch (stats[j].tag) { > > + case VIR_NODE_CPU_TIME_KERNEL: > > + cpu_time[i].sys = stats[j].val; > > + break; > > + case VIR_NODE_CPU_TIME_USER: > > + cpu_time[i].user = stats[j].val; > > + break; > > + case VIR_NODE_CPU_TIME_IDLE: > > + cpu_time[i].idle = stats[j].val; > > + break; > > + case VIR_NODE_CPU_TIME_IOWAIT: > > + cpu_time[i].iowait = stats[j].val; > > + break; > > + case VIR_NODE_CPU_TIME_UTILIZATION: > > + flag_utilization = TRUE; > > + cpu_time[i].util = stats[j].val; > > + break; > > + case VIR_NODE_CPU_TIME_NR: > > + default: > > + break; > > + } > > + } > > + > > + sleep(1); > > + } > > I'm not sure about this bit. In other places in virsh, we just report > the absolute CPU time value, and don't try to calculate the deltas. > There is a virt-top program that might like to use this data to provide > a continuous display of utilization. Matthias said, ESX cannot get absolute CPU time. It just get CPU percentage. http://www.mail-archive.com/libvir-list at redhat.com/msg35769.html And I think CPU percentage is very useful for user. The user don't care about absolute CPU time value. They want to know about CPU load of each host. So I wrote this specification. > Alternatively, we could add an arg for this to request that it calculate > delta over 'n' seconds. I agree. It's very userful. But ESX cannot change interval, perhaps. > Daniel > -- > |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| > |: http://libvirt.org -o- http://virt-manager.org :| > |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| > |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- Minoru Usui From wency at cn.fujitsu.com Wed Apr 27 05:43:24 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Wed, 27 Apr 2011 13:43:24 +0800 Subject: [libvirt] [PATCH V2] free buf->content when vsnprintf() failed Message-ID: <4DB7ACFC.6060805@cn.fujitsu.com> When buf->error is 1, we do not return buf->content in the function virBufferContentAndReset(). So we should free buf->content when vsnprintf() failed. --- Changes v1->v2 - rename virBufferNoMemory() to virBufferSetError() and use it to free buf->content as Laine Stump suggested src/util/buf.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/util/buf.c b/src/util/buf.c index 7557ad1..a3cc063 100644 --- a/src/util/buf.c +++ b/src/util/buf.c @@ -39,7 +39,7 @@ struct _virBuffer { * freeing the content and setting the error flag. */ static void -virBufferNoMemory(const virBufferPtr buf) +virBufferSetError(const virBufferPtr buf) { VIR_FREE(buf->content); buf->size = 0; @@ -70,7 +70,7 @@ virBufferGrow(virBufferPtr buf, unsigned int len) size = buf->use + len + 1000; if (VIR_REALLOC_N(buf->content, size) < 0) { - virBufferNoMemory(buf); + virBufferSetError(buf); return -1; } buf->size = size; @@ -241,7 +241,7 @@ virBufferVSprintf(const virBufferPtr buf, const char *format, ...) size = buf->size - buf->use; if ((count = vsnprintf(&buf->content[buf->use], size, format, argptr)) < 0) { - buf->error = 1; + virBufferSetError(buf); goto err; } @@ -259,7 +259,7 @@ virBufferVSprintf(const virBufferPtr buf, const char *format, ...) size = buf->size - buf->use; if ((count = vsnprintf(&buf->content[buf->use], size, format, argptr)) < 0) { - buf->error = 1; + virBufferSetError(buf); goto err; } } @@ -299,7 +299,7 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st } if (VIR_ALLOC_N(escaped, 6 * len + 1) < 0) { - virBufferNoMemory(buf); + virBufferSetError(buf); return; } @@ -386,7 +386,7 @@ virBufferEscapeSexpr(const virBufferPtr buf, } if (VIR_ALLOC_N(escaped, 2 * len + 1) < 0) { - virBufferNoMemory(buf); + virBufferSetError(buf); return; } -- 1.7.1 From veillard at redhat.com Wed Apr 27 06:22:49 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 27 Apr 2011 14:22:49 +0800 Subject: [libvirt] [PATCH V2] free buf->content when vsnprintf() failed In-Reply-To: <4DB7ACFC.6060805@cn.fujitsu.com> References: <4DB7ACFC.6060805@cn.fujitsu.com> Message-ID: <20110427062249.GM10484@redhat.com> On Wed, Apr 27, 2011 at 01:43:24PM +0800, Wen Congyang wrote: > When buf->error is 1, we do not return buf->content in the function > virBufferContentAndReset(). So we should free buf->content when > vsnprintf() failed. > > --- > Changes > v1->v2 > - rename virBufferNoMemory() to virBufferSetError() and use it > to free buf->content as Laine Stump suggested > > src/util/buf.c | 12 ++++++------ > 1 files changed, 6 insertions(+), 6 deletions(-) > > diff --git a/src/util/buf.c b/src/util/buf.c > index 7557ad1..a3cc063 100644 > --- a/src/util/buf.c > +++ b/src/util/buf.c > @@ -39,7 +39,7 @@ struct _virBuffer { > * freeing the content and setting the error flag. > */ > static void > -virBufferNoMemory(const virBufferPtr buf) > +virBufferSetError(const virBufferPtr buf) > { > VIR_FREE(buf->content); > buf->size = 0; > @@ -70,7 +70,7 @@ virBufferGrow(virBufferPtr buf, unsigned int len) > size = buf->use + len + 1000; > > if (VIR_REALLOC_N(buf->content, size) < 0) { > - virBufferNoMemory(buf); > + virBufferSetError(buf); > return -1; > } > buf->size = size; > @@ -241,7 +241,7 @@ virBufferVSprintf(const virBufferPtr buf, const char *format, ...) > size = buf->size - buf->use; > if ((count = vsnprintf(&buf->content[buf->use], > size, format, argptr)) < 0) { > - buf->error = 1; > + virBufferSetError(buf); > goto err; > } > > @@ -259,7 +259,7 @@ virBufferVSprintf(const virBufferPtr buf, const char *format, ...) > size = buf->size - buf->use; > if ((count = vsnprintf(&buf->content[buf->use], > size, format, argptr)) < 0) { > - buf->error = 1; > + virBufferSetError(buf); > goto err; > } > } > @@ -299,7 +299,7 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st > } > > if (VIR_ALLOC_N(escaped, 6 * len + 1) < 0) { > - virBufferNoMemory(buf); > + virBufferSetError(buf); > return; > } > > @@ -386,7 +386,7 @@ virBufferEscapeSexpr(const virBufferPtr buf, > } > > if (VIR_ALLOC_N(escaped, 2 * len + 1) < 0) { > - virBufferNoMemory(buf); > + virBufferSetError(buf); > return; > } > ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Wed Apr 27 06:37:37 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 27 Apr 2011 14:37:37 +0800 Subject: [libvirt] [PATCH] esx: Fix dynamic dispatch for CastFromAnyType functions In-Reply-To: References: <20110425094120.GA15113@sbox> Message-ID: <20110427063737.GN10484@redhat.com> On Mon, Apr 25, 2011 at 01:32:43PM +0200, Matthias Bolte wrote: > 2011/4/25 Matthias Bolte : > > This was broken by the refactoring in ac1e6586ec75. It resulted in a > > segfault for 'virsh vol-dumpxml' and related volume functions. > > > > Actually that patch doesn't fix the problem correctly. It just turns > the segfault into an error message. > > Here's v2 that really fixes the problem. Note the important difference > between anyType->_type and anyType->type :) > > Matthias > From a17245fb92c88439ffbb84e34bebf1afb6903885 Mon Sep 17 00:00:00 2001 > From: Matthias Bolte > Date: Mon, 25 Apr 2011 12:38:17 +0200 > Subject: [PATCH] esx: Fix dynamic dispatch for CastFromAnyType functions > > This was broken by the refactoring in ac1e6586ec75. It resulted in a > segfault for 'virsh vol-dumpxml' and related volume functions. > > Before the refactoring all users of the ESX_VI__TEMPLATE__DISPATCH > macro dispatched on the item type, as the item is the input to all those > functions. > > Commit ac1e6586ec75 made the dynamically dispatched CastFromAnyType > functions use this macro too, but this functions dispatched on the > actual type of the AnyType object. The item is the output of the > CastFromAnyType functions. > > This difference was missed in the refactoring, making CastFromAnyType > functions dereferencing the item pointer that is NULL at the time of > the dispatch. > --- > src/esx/esx_vi_types.c | 14 ++++++++------ > 1 files changed, 8 insertions(+), 6 deletions(-) > > diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c > index dd83954..3c81021 100644 > --- a/src/esx/esx_vi_types.c > +++ b/src/esx/esx_vi_types.c > @@ -533,8 +533,9 @@ > * Macros to implement dynamic dispatched functions > */ > > -#define ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, _error_return) \ > - switch (item->_type) { \ > +#define ESX_VI__TEMPLATE__DISPATCH(_actual_type, __type, _dispatch, \ > + _error_return) \ > + switch (_actual_type) { \ > _dispatch \ > \ > case esxVI_Type_##__type: \ > @@ -543,7 +544,7 @@ > default: \ > ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \ > _("Call to %s for unexpected type '%s'"), __FUNCTION__, \ > - esxVI_Type_ToString(item->_type)); \ > + esxVI_Type_ToString(_actual_type)); \ > return _error_return; \ > } > > @@ -585,7 +586,8 @@ > > #define ESX_VI__TEMPLATE__DYNAMIC_FREE(__type, _dispatch, _body) \ > ESX_VI__TEMPLATE__FREE(__type, \ > - ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, /* nothing */) \ > + ESX_VI__TEMPLATE__DISPATCH(item->_type, __type, _dispatch, \ > + /* nothing */) \ > _body) > > > @@ -618,14 +620,14 @@ > > #define ESX_VI__TEMPLATE__DYNAMIC_CAST_FROM_ANY_TYPE(__type, _dispatch) \ > ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE_EXTRA(__type, esxVI_##__type, \ > - ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, -1), \ > + ESX_VI__TEMPLATE__DISPATCH(anyType->type, __type, _dispatch, -1), \ > /* nothing */) > > > > #define ESX_VI__TEMPLATE__DYNAMIC_SERIALIZE(__type, _dispatch, _serialize) \ > ESX_VI__TEMPLATE__SERIALIZE_EXTRA(__type, \ > - ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, -1), \ > + ESX_VI__TEMPLATE__DISPATCH(item->_type, __type, _dispatch, -1), \ > _serialize) > Not sure I fully understand but looks regular and okay, ACK :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Wed Apr 27 06:40:46 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 27 Apr 2011 14:40:46 +0800 Subject: [libvirt] [PATCH] free memory properly in cleanup patch In-Reply-To: <20110426012031.GA13689@localhost.localdomain> References: <20110426012031.GA13689@localhost.localdomain> Message-ID: <20110427064046.GO10484@redhat.com> On Tue, Apr 26, 2011 at 09:20:31AM +0800, Hu Tao wrote: > virsh schedinfo inactive-domain will trigger the problem. > --- > daemon/remote.c | 7 +++++-- > 1 files changed, 5 insertions(+), 2 deletions(-) > > diff --git a/daemon/remote.c b/daemon/remote.c > index 1c98bba..eedbc77 100644 > --- a/daemon/remote.c > +++ b/daemon/remote.c > @@ -945,8 +945,11 @@ remoteDispatchDomainGetSchedulerParameters(struct qemud_server *server ATTRIBUTE > cleanup: > if (rv < 0) { > remoteDispatchError(rerr); > - for (i = 0 ; i < nparams ; i++) > - VIR_FREE(ret->params.params_val[i].field); > + 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); > + } > } > if (dom) > virDomainFree(dom); ACK, a daemon leak, good fix ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Wed Apr 27 06:43:47 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 27 Apr 2011 14:43:47 +0800 Subject: [libvirt] [PATCH] release PCI address only when we have ensured it successfully In-Reply-To: <4DB63E91.6030405@cn.fujitsu.com> References: <4DB63E91.6030405@cn.fujitsu.com> Message-ID: <20110427064347.GP10484@redhat.com> On Tue, Apr 26, 2011 at 11:40:01AM +0800, Wen Congyang wrote: > Steps to reproduce this bug: > 1. # cat net.xml # 00:03.0 has been used > > > >
    > > > 2. # virsh attach-device vm1 net.xml > error: Failed to attach device from net.xml > error: internal error unable to reserve PCI address 0:0:3 > > 3. # virsh attach-device vm1 net.xml > error: Failed to attach device from net.xml > error: internal error unable to execute QEMU command 'device_add': Device 'rtl8139' could not be initialized > > The reason of this bug is that: we can not reserve PCI address 0:0:3 because it has > been used, but we release PCI address when we reserve it failed. > > --- > src/qemu/qemu_hotplug.c | 13 +++++++++++++ > 1 files changed, 13 insertions(+), 0 deletions(-) > > diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c > index b03f774..5fdb013 100644 > --- a/src/qemu/qemu_hotplug.c > +++ b/src/qemu/qemu_hotplug.c > @@ -147,6 +147,7 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver, > qemuDomainObjPrivatePtr priv = vm->privateData; > char *devstr = NULL; > char *drivestr = NULL; > + bool releaseaddr = false; > > for (i = 0 ; i < vm->def->ndisks ; i++) { > if (STREQ(vm->def->disks[i]->dst, disk->dst)) { > @@ -163,6 +164,7 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver, > if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { > if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info) < 0) > goto error; > + releaseaddr = true; > if (qemuAssignDeviceDiskAlias(disk, qemuCaps) < 0) > goto error; > > @@ -221,6 +223,7 @@ error: > > if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && > (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) && > + releaseaddr && > qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &disk->info) < 0) > VIR_WARN("Unable to release PCI address on %s", disk->src); > > @@ -242,6 +245,7 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver, > const char* type = virDomainControllerTypeToString(controller->type); > char *devstr = NULL; > qemuDomainObjPrivatePtr priv = vm->privateData; > + bool releaseaddr = false; > > for (i = 0 ; i < vm->def->ncontrollers ; i++) { > if ((vm->def->controllers[i]->type == controller->type) && > @@ -256,6 +260,7 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver, > if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { > if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &controller->info) < 0) > goto cleanup; > + releaseaddr = true; > if (qemuAssignDeviceControllerAlias(controller) < 0) > goto cleanup; > > @@ -288,6 +293,7 @@ cleanup: > if ((ret != 0) && > qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && > (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) && > + releaseaddr && > qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &controller->info) < 0) > VIR_WARN0("Unable to release PCI address on controller"); > > @@ -559,6 +565,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, > int ret = -1; > virDomainDevicePCIAddress guestAddr; > int vlan; > + bool releaseaddr = false; > > if (!qemuCapsGet(qemuCaps, QEMU_CAPS_HOST_NET_ADD)) { > qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > @@ -595,6 +602,8 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, > qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0) > goto cleanup; > > + releaseaddr = true; > + > if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) && > qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { > vlan = -1; > @@ -694,6 +703,7 @@ cleanup: > if ((ret != 0) && > qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && > (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) && > + releaseaddr && > qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &net->info) < 0) > VIR_WARN0("Unable to release PCI address on NIC"); > > @@ -757,6 +767,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, > char *devstr = NULL; > int configfd = -1; > char *configfd_name = NULL; > + bool releaseaddr = false; > > if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) { > virReportOOMError(); > @@ -771,6 +782,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, > goto error; > if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &hostdev->info) < 0) > goto error; > + releaseaddr = true; > if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_CONFIGFD)) { > configfd = qemuOpenPCIConfig(hostdev); > if (configfd >= 0) { > @@ -823,6 +835,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, > error: > if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && > (hostdev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) && > + releaseaddr && > qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &hostdev->info) < 0) > VIR_WARN0("Unable to release PCI address on host device"); The logic fo the fix sounds right, and it looks complete, ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Wed Apr 27 06:59:38 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 27 Apr 2011 14:59:38 +0800 Subject: [libvirt] [PATCH] build: Fix problem of building Python bindings In-Reply-To: <1303875993-9780-1-git-send-email-jyang@redhat.com> References: <1303875993-9780-1-git-send-email-jyang@redhat.com> Message-ID: <20110427065938.GQ10484@redhat.com> On Wed, Apr 27, 2011 at 11:46:33AM +0800, Osier Yang wrote: > If one specify "--with-python=yes" but no python-devel package > is installed, we ignore it with just a notice message, which > doesn't give clear guide to user. > --- > configure.ac | 6 ++---- > 1 files changed, 2 insertions(+), 4 deletions(-) > > diff --git a/configure.ac b/configure.ac > index 190bf40..758c893 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -1917,15 +1917,13 @@ if test "$with_python" != "no" ; then > then > PYTHON_INCLUDES=-I/usr/include/python$PYTHON_VERSION > else > - AC_MSG_NOTICE([Could not find python$PYTHON_VERSION/Python.h, disabling bindings]) > - with_python=no > + AC_MSG_ERROR([You must install python-devel to build Python bindings]) > fi > fi > fi > fi > else > - AC_MSG_NOTICE([Could not find python interpreter, disabling bindings]) > - with_python=no > + AC_MSG_ERROR([You must install python to build Python bindings]) > fi > else > AC_MSG_NOTICE([Could not find python in $with_python, disabling bindings]) Hum ... the message may be a bit less "generaic" but probably more useful, okay ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Wed Apr 27 07:02:43 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 27 Apr 2011 15:02:43 +0800 Subject: [libvirt] [PATCH 00/22] Extend remote generator to generate function bodies too In-Reply-To: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> Message-ID: <20110427070243.GR10484@redhat.com> On Sun, Apr 24, 2011 at 11:13:47AM +0200, Matthias Bolte wrote: > Richard W.M. Jones suggested [1] that the code that directly deals with the > XDR protocol should be generated. The remote_generate_stubs.pl script > already generates all the headers, just the bodies in the daemon and remote > driver are manually written. But most of the functions just follow simple > patterns. So I extended the generator to exploit this patterns and move > 11 kLOC code from manually written to generated code. > > During this I came a cross many small variations and problems in the XDR > protocol. For example, NWFilterDefineXML has a flags parameter in the public > API, but it's not transferred in the XDR protocol. Another things is the > variations in the usage of unsigned VS signed types. This comes in two forms. > public API VS XDR procotol and in between different functions. For example, > some functions use int for the flags paramater and some use unsigned int. > > This results in quite a lot of special case handling in the generator. Matthias, this sounds the right thing to do, actually cocumenting the irregularities in teh generator is an important step to make sure we keep the ABI over time. However I think it's better to postpone applying the patch since after the upcoming release and when Dan is back, I would really prefer him to have a look at it :-) okay ? Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From matthias.bolte at googlemail.com Wed Apr 27 07:18:18 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Wed, 27 Apr 2011 09:18:18 +0200 Subject: [libvirt] [PATCH 00/22] Extend remote generator to generate function bodies too In-Reply-To: <20110427070243.GR10484@redhat.com> References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> <20110427070243.GR10484@redhat.com> Message-ID: 2011/4/27 Daniel Veillard : > On Sun, Apr 24, 2011 at 11:13:47AM +0200, Matthias Bolte wrote: >> Richard W.M. Jones suggested [1] that the code that directly deals with the >> XDR protocol should be generated. The remote_generate_stubs.pl script >> already generates all the headers, just the bodies in the daemon and remote >> driver are manually written. But most of the functions just follow simple >> patterns. So I extended the generator to exploit this patterns and move >> 11 kLOC code from manually written to generated code. >> >> During this I came a cross many small variations and problems in the XDR >> protocol. For example, NWFilterDefineXML has a flags parameter in the public >> API, but it's not transferred in the XDR protocol. Another things is the >> variations in the usage of unsigned VS signed types. This comes in two forms. >> public API VS XDR procotol and in between different functions. For example, >> some functions use int for the flags paramater and some use unsigned int. >> >> This results in quite a lot of special case handling in the generator. > > ?Matthias, > > this sounds the right thing to do, actually cocumenting the > irregularities in teh generator is an important step to make sure > we keep the ABI over time. However I think it's better to postpone > applying the patch since after the upcoming release and when > Dan is back, I would really prefer him to have a look at it :-) > > ?okay ? > > Daniel Sure, this change is way to big to go into the next release, as we're supposed to be in feature freeze for 0.9.1 already, aren't we? Although everything still compiles fine and the TCK did turn up any major breakage this needs to be properly reviewed to make sure I didn't overlook anything in the conversion process. I should probably also add a 23/22 patch that adds more comments to the generator about the irregularities that are currently expressed by the special case code only. So, as you said this series has to be postponed for 0.9.2. Matthias From veillard at redhat.com Wed Apr 27 07:20:36 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 27 Apr 2011 15:20:36 +0800 Subject: [libvirt] [PATCH 00/22] Extend remote generator to generate function bodies too In-Reply-To: References: <1303636449-19113-1-git-send-email-matthias.bolte@googlemail.com> <20110427070243.GR10484@redhat.com> Message-ID: <20110427072036.GS10484@redhat.com> On Wed, Apr 27, 2011 at 09:18:18AM +0200, Matthias Bolte wrote: > 2011/4/27 Daniel Veillard : > > On Sun, Apr 24, 2011 at 11:13:47AM +0200, Matthias Bolte wrote: > >> Richard W.M. Jones suggested [1] that the code that directly deals with the > >> XDR protocol should be generated. The remote_generate_stubs.pl script > >> already generates all the headers, just the bodies in the daemon and remote > >> driver are manually written. But most of the functions just follow simple > >> patterns. So I extended the generator to exploit this patterns and move > >> 11 kLOC code from manually written to generated code. > >> > >> During this I came a cross many small variations and problems in the XDR > >> protocol. For example, NWFilterDefineXML has a flags parameter in the public > >> API, but it's not transferred in the XDR protocol. Another things is the > >> variations in the usage of unsigned VS signed types. This comes in two forms. > >> public API VS XDR procotol and in between different functions. For example, > >> some functions use int for the flags paramater and some use unsigned int. > >> > >> This results in quite a lot of special case handling in the generator. > > > > ?Matthias, > > > > this sounds the right thing to do, actually cocumenting the > > irregularities in teh generator is an important step to make sure > > we keep the ABI over time. However I think it's better to postpone > > applying the patch since after the upcoming release and when > > Dan is back, I would really prefer him to have a look at it :-) > > > > ?okay ? > > > > Daniel > > Sure, this change is way to big to go into the next release, as we're > supposed to be in feature freeze for 0.9.1 already, aren't we? Well I didn't explicitely announced t and mad no candidate release, so let's say we aren't yet, but very soon > Although everything still compiles fine and the TCK did turn up any > major breakage this needs to be properly reviewed to make sure I > didn't overlook anything in the conversion process. Agreed > I should probably also add a 23/22 patch that adds more comments to > the generator about the irregularities that are currently expressed by > the special case code only. +1 :-) > So, as you said this series has to be postponed for 0.9.2. Okay, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From veillard at redhat.com Wed Apr 27 07:25:38 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 27 Apr 2011 15:25:38 +0800 Subject: [libvirt] Entering devel freeze tomorrow Message-ID: <20110427072538.GT10484@redhat.com> Well I initially suggested to enter freeze the last week-end but I had a serious backlog and let a few day pass. What I suggest is enter freeze tomorrow morning (my time, i.e. very early) at which point I will make a first candidate release tarball for testing. Then the target for the actually release might be Wed 4 or Thu 5 depending on how things turns out. If there is patches for new features that people want in but didn't get the ACK, please raise them again quickly today so we can try to review them and push in time for 0.9.1, otherwise, that will be 0.9.2 in a month, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From matthias.bolte at googlemail.com Wed Apr 27 07:27:06 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Wed, 27 Apr 2011 09:27:06 +0200 Subject: [libvirt] [PATCH] Move call to virReportOOMError into virFileBuildPath In-Reply-To: <4DB6E454.1020802@laine.org> References: <20110424094800.GA6638@sbox> <4DB6E454.1020802@laine.org> Message-ID: 2011/4/26 Laine Stump : > On 04/24/2011 05:48 AM, Matthias Bolte wrote: >> >> Suggested by Daniel P. Berrange >> --- >> ?src/conf/nwfilter_conf.c | ? ?5 +---- >> ?src/conf/storage_conf.c ?| ? ?7 +------ >> ?src/util/util.c ? ? ? ? ?| ? ?2 ++ >> ?src/xen/xen_inotify.c ? ?| ? ?1 - >> ?src/xen/xm_internal.c ? ?| ? ?5 +---- >> ?5 files changed, 5 insertions(+), 15 deletions(-) > > ACK. > Thanks, pushed. Matthias From matthias.bolte at googlemail.com Wed Apr 27 07:35:32 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Wed, 27 Apr 2011 09:35:32 +0200 Subject: [libvirt] [PATCH] esx: Fix dynamic dispatch for CastFromAnyType functions In-Reply-To: <20110427063737.GN10484@redhat.com> References: <20110425094120.GA15113@sbox> <20110427063737.GN10484@redhat.com> Message-ID: 2011/4/27 Daniel Veillard : > On Mon, Apr 25, 2011 at 01:32:43PM +0200, Matthias Bolte wrote: >> 2011/4/25 Matthias Bolte : >> > This was broken by the refactoring in ac1e6586ec75. It resulted in a >> > segfault for 'virsh vol-dumpxml' and related volume functions. >> > >> >> Actually that patch doesn't fix the problem correctly. It just turns >> the segfault into an error message. >> >> Here's v2 that really fixes the problem. Note the important difference >> between anyType->_type and anyType->type :) >> >> Matthias > >> From a17245fb92c88439ffbb84e34bebf1afb6903885 Mon Sep 17 00:00:00 2001 >> From: Matthias Bolte >> Date: Mon, 25 Apr 2011 12:38:17 +0200 >> Subject: [PATCH] esx: Fix dynamic dispatch for CastFromAnyType functions >> >> This was broken by the refactoring in ac1e6586ec75. It resulted in a >> segfault for 'virsh vol-dumpxml' and related volume functions. >> >> Before the refactoring all users of the ESX_VI__TEMPLATE__DISPATCH >> macro dispatched on the item type, as the item is the input to all those >> functions. >> >> Commit ac1e6586ec75 made the dynamically dispatched CastFromAnyType >> functions use this macro too, but this functions dispatched on the >> actual type of the AnyType object. The item is the output of the >> CastFromAnyType functions. >> >> This difference was missed in the refactoring, making CastFromAnyType >> functions dereferencing the item pointer that is NULL at the time of >> the dispatch. >> --- >> ?src/esx/esx_vi_types.c | ? 14 ++++++++------ >> ?1 files changed, 8 insertions(+), 6 deletions(-) >> >> diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c >> index dd83954..3c81021 100644 >> --- a/src/esx/esx_vi_types.c >> +++ b/src/esx/esx_vi_types.c >> @@ -533,8 +533,9 @@ >> ? * Macros to implement dynamic dispatched functions >> ? */ >> >> -#define ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, _error_return) ? ? ? ? ?\ >> - ? ?switch (item->_type) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ >> +#define ESX_VI__TEMPLATE__DISPATCH(_actual_type, __type, _dispatch, ? ? ? ? ? \ >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? _error_return) ? ? ? ? ? ? ? ? ? ? ? ? ? ? \ >> + ? ?switch (_actual_type) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \ >> ? ? ? ?_dispatch ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \ >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ >> ? ? ? ?case esxVI_Type_##__type: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \ >> @@ -543,7 +544,7 @@ >> ? ? ? ?default: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ >> ? ? ? ? ?ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ >> ? ? ? ? ? ? ? ? ? ? ? _("Call to %s for unexpected type '%s'"), __FUNCTION__, ?\ >> - ? ? ? ? ? ? ? ? ? ? esxVI_Type_ToString(item->_type)); ? ? ? ? ? ? ? ? ? ? ? \ >> + ? ? ? ? ? ? ? ? ? ? esxVI_Type_ToString(_actual_type)); ? ? ? ? ? ? ? ? ? ? ?\ >> ? ? ? ? ?return _error_return; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \ >> ? ? ?} >> >> @@ -585,7 +586,8 @@ >> >> ?#define ESX_VI__TEMPLATE__DYNAMIC_FREE(__type, _dispatch, _body) ? ? ? ? ? ? ?\ >> ? ? ?ESX_VI__TEMPLATE__FREE(__type, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ >> - ? ? ?ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, /* nothing */) ? ? ? ? ? ?\ >> + ? ? ?ESX_VI__TEMPLATE__DISPATCH(item->_type, __type, _dispatch, ? ? ? ? ? ? ?\ >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* nothing */) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \ >> ? ? ? ?_body) >> >> >> @@ -618,14 +620,14 @@ >> >> ?#define ESX_VI__TEMPLATE__DYNAMIC_CAST_FROM_ANY_TYPE(__type, _dispatch) ? ? ? \ >> ? ? ?ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE_EXTRA(__type, esxVI_##__type, ? ? ? ?\ >> - ? ? ?ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, -1), ? ? ? ? ? ? ? ? ? ? ?\ >> + ? ? ?ESX_VI__TEMPLATE__DISPATCH(anyType->type, __type, _dispatch, -1), ? ? ? \ >> ? ? ? ?/* nothing */) >> >> >> >> ?#define ESX_VI__TEMPLATE__DYNAMIC_SERIALIZE(__type, _dispatch, _serialize) ? ?\ >> ? ? ?ESX_VI__TEMPLATE__SERIALIZE_EXTRA(__type, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \ >> - ? ? ?ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, -1), ? ? ? ? ? ? ? ? ? ? ?\ >> + ? ? ?ESX_VI__TEMPLATE__DISPATCH(item->_type, __type, _dispatch, -1), ? ? ? ? \ >> ? ? ? ?_serialize) >> > > ?Not sure I fully understand but looks regular and okay, ACK :-) > > Daniel > Actually, this shows that even I'm not always aware of all the details in the ESX driver, otherwise this regression fix wouldn't have be necessary and I wouldn't have needed two attempts to get it right. So don't feel too bad about not fully understanding it :) This is probably a sign that I should try to reduce the complexity and levels of indirection in the generated code and the code generator. Thanks, finally pushed v2. Matthias From veillard at redhat.com Wed Apr 27 08:02:05 2011 From: veillard at redhat.com (Daniel Veillard) Date: Wed, 27 Apr 2011 16:02:05 +0800 Subject: [libvirt] [PATCH] esx: Fix dynamic dispatch for CastFromAnyType functions In-Reply-To: References: <20110425094120.GA15113@sbox> <20110427063737.GN10484@redhat.com> Message-ID: <20110427080205.GU10484@redhat.com> On Wed, Apr 27, 2011 at 09:35:32AM +0200, Matthias Bolte wrote: > 2011/4/27 Daniel Veillard : > > ?Not sure I fully understand but looks regular and okay, ACK :-) > > > > Daniel > > > > Actually, this shows that even I'm not always aware of all the details > in the ESX driver, otherwise this regression fix wouldn't have be > necessary and I wouldn't have needed two attempts to get it right. So > don't feel too bad about not fully understanding it :) > > This is probably a sign that I should try to reduce the complexity and > levels of indirection in the generated code and the code generator. Reminds me of docs/apibuild.py , that's code I wrote like 10 years ago for libxml2, and I certainly don't remember all the subtelties, it's certainly not very nice code, but being a generator and automated parser the good point is that I don't have to remember it, and very seldomly hack it. I think there is no shame to having "imperfect" code which does this kind of things as long as it's done in a generic enought way that you don't have to tweak it often. If the extra indirections don't cost anything (except extra code) then maybe it's fine keeping. I would say the main driver to clean such code would be if you feel others need to hack on it and it need to be cleaner and easier to understand. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From matthias.bolte at googlemail.com Wed Apr 27 08:37:58 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Wed, 27 Apr 2011 10:37:58 +0200 Subject: [libvirt] [PATCH] esx: Fix dynamic dispatch for CastFromAnyType functions In-Reply-To: <20110427080205.GU10484@redhat.com> References: <20110425094120.GA15113@sbox> <20110427063737.GN10484@redhat.com> <20110427080205.GU10484@redhat.com> Message-ID: 2011/4/27 Daniel Veillard : > On Wed, Apr 27, 2011 at 09:35:32AM +0200, Matthias Bolte wrote: >> 2011/4/27 Daniel Veillard : >> > ?Not sure I fully understand but looks regular and okay, ACK :-) >> > >> > Daniel >> > >> >> Actually, this shows that even I'm not always aware of all the details >> in the ESX driver, otherwise this regression fix wouldn't have be >> necessary and I wouldn't have needed two attempts to get it right. So >> don't feel too bad about not fully understanding it :) >> >> This is probably a sign that I should try to reduce the complexity and >> levels of indirection in the generated code and the code generator. > > ?Reminds me of docs/apibuild.py , that's code I wrote like 10 years > ago for libxml2, and I certainly don't remember all the subtelties, > it's certainly not very nice code, but being a generator and automated > parser the good point is that I don't have to remember it, and very > seldomly hack it. I think there is no shame to having "imperfect" code > which does this kind of things as long as it's done in a generic enought > way that you don't have to tweak it often. > ?If the extra indirections don't cost anything (except extra code) then > maybe it's fine keeping. I would say the main driver to clean such code > would be if you feel others need to hack on it and it need to be cleaner > and easier to understand. > > Daniel > The generator is in a state where adding new stuff from the vSphere API boils down to just adding a definition to the input file in most cases. For some things list in the generator need to be tweaked that define what features should be generated for a specific object type. IIRC in most cases this could be automated too as the generator could detect this by analyzing the input file better. This way the generator becomes more complete and others don't need to hack on it and the code generation process to add new stuff from the vSphere API. About the complexity in the generated code: For example parts of the type handling currently nest three levels of macros, because it's "convenient" and reduces manual code duplication, but it becomes harder to understand and get right when I need to hack on it. That's the motivation behind possibly simplifying the generator related stuff :) Matthias From hutao at cn.fujitsu.com Wed Apr 27 09:07:09 2011 From: hutao at cn.fujitsu.com (Hu Tao) Date: Wed, 27 Apr 2011 17:07:09 +0800 Subject: [libvirt] [PATCH 3/4] vcpupin: implement the remote protocol to address the new API In-Reply-To: <4D9E9B87.6080606@jp.fujitsu.com> References: <4D9E999F.5070505@jp.fujitsu.com> <4D9E9B87.6080606@jp.fujitsu.com> Message-ID: <20110427090709.GA2854@localhost.localdomain> > Index: libvirt/daemon/remote_dispatch_table.h This file is generated automatically, update src/remote/remote_protocol.x instead. > =================================================================== > --- libvirt.orig/daemon/remote_dispatch_table.h > +++ libvirt/daemon/remote_dispatch_table.h > @@ -1052,3 +1052,8 @@ > .args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args, > .ret_filter = (xdrproc_t) xdr_void, > }, > +{ /* DomainPinVcpuFlags => 210 */ > + .fn = (dispatch_fn) remoteDispatchDomainPinVcpuFlags, > + .args_filter = (xdrproc_t) xdr_remote_domain_pin_vcpu_flags_args, > + .ret_filter = (xdrproc_t) xdr_void, > +}, From jdenemar at redhat.com Wed Apr 27 09:25:48 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Wed, 27 Apr 2011 11:25:48 +0200 Subject: [libvirt] [PATCH] build: Ignore old audit library Message-ID: <66ce2a4962feb3e5f2748ab0593772a90e9e9fbd.1303896348.git.jdenemar@redhat.com> Check for audit_encode_nv_string in libaudit so that ancient audit library is ignored rather than trying to compile with libaudit support and failing. --- configure.ac | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/configure.ac b/configure.ac index 190bf40..25cc15b 100644 --- a/configure.ac +++ b/configure.ac @@ -1026,7 +1026,7 @@ if test "$with_audit" != "no" ; then LIBS="$LIBS $AUDIT_LIBS" fail=0 AC_CHECK_HEADER([libaudit.h], [], [fail=1]) - AC_CHECK_LIB([audit], [audit_is_enabled], [], [fail=1]) + AC_CHECK_LIB([audit], [audit_encode_nv_string], [], [fail=1]) if test $fail = 1 ; then if test "$with_audit" = "yes" ; then -- 1.7.5.rc1 From mprivozn at redhat.com Wed Apr 27 10:17:25 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Wed, 27 Apr 2011 12:17:25 +0200 Subject: [libvirt] [PATCH] qemu: Add option to enable/disable IOEventFD feature Message-ID: <1303899445-23764-1-git-send-email-mprivozn@redhat.com> This feature allows QEMU to achieve higher throughput, but is available only in recent versions. It is accessible via ioeventfd attribute with accepting values 'on', 'off'. Only experienced users needs to set this, because QEMU defaults to 'on', meaning higher performance. Translates into virtio-{blk|net}-pci.ioeventfd option. --- docs/formatdomain.html.in | 15 ++++++++++++- docs/schemas/domain.rng | 14 +++++++++++++ src/conf/domain_conf.c | 44 +++++++++++++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 12 +++++++++++ src/libvirt_private.syms | 2 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 23 +++++++++++++++++++++ tests/qemuhelptest.c | 3 +- 9 files changed, 112 insertions(+), 4 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index a055b38..409b26a 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -751,7 +751,7 @@ </disk> ... <disk type='network'> - <driver name="qemu" type="raw" io="threads"/> + <driver name="qemu" type="raw" io="threads" ioeventfd="on"/> <source protocol="sheepdog" name="image_name"> <host name="hostname" port="7000"/> </source> @@ -835,6 +835,11 @@ policies on I/O; qemu guests support "threads" and "native". Since 0.8.8 +
  • + The optional ioeventfd attribute enables or disables + IOEventFD feature for virtqueue notify. The value can be either + 'on' or 'off'. + Since 0.9.0 (QEMU and KVM only)
    boot
    @@ -1458,7 +1463,7 @@ qemu-kvm -net nic,model=? /dev/null <source network='default'/> <target dev='vnet1'/> <model type='virtio'/> - <driver name='vhost' txmode='iothread'/> + <driver name='vhost' txmode='iothread' ioeventfd='on'/> </interface> </devices> ... @@ -1509,6 +1514,12 @@ qemu-kvm -net nic,model=? /dev/null In general you should leave this option alone, unless you are very certain you know what you are doing. +
    ioeventfd
    +
    + This optional attribute allows users to enable or disable IOeventFD + feature for virtqueue notify. The value can be either 'on' or 'off'. + Since 0.9.0 (QEMU and KVM only) +
    Overriding the target element
    diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 7163c6e..c3e8e15 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -735,6 +735,9 @@ + + + @@ -774,6 +777,14 @@ + + + + on + off + + + @@ -1074,6 +1085,9 @@ + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 0e7aeb5..2aca162 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -155,6 +155,11 @@ VIR_ENUM_IMPL(virDomainDiskIo, VIR_DOMAIN_DISK_IO_LAST, "native", "threads") +VIR_ENUM_IMPL(virDomainVirtioEventFd, VIR_DOMAIN_VIRTIO_EVENT_FD_LAST, + "default", + "on", + "off") + VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST, "ide", "fdc", @@ -1829,6 +1834,7 @@ virDomainDiskDefParseXML(virCapsPtr caps, char *cachetag = NULL; char *error_policy = NULL; char *iotag = NULL; + char *ioeventfd = NULL; char *devaddr = NULL; virStorageEncryptionPtr encryption = NULL; char *serial = NULL; @@ -1944,6 +1950,7 @@ virDomainDiskDefParseXML(virCapsPtr caps, cachetag = virXMLPropString(cur, "cache"); error_policy = virXMLPropString(cur, "error_policy"); iotag = virXMLPropString(cur, "io"); + ioeventfd = virXMLPropString(cur, "ioeventfd"); } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) { def->readonly = 1; } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) { @@ -2080,6 +2087,18 @@ virDomainDiskDefParseXML(virCapsPtr caps, } } + if (ioeventfd) { + int i; + if ((i = virDomainVirtioEventFdTypeFromString(ioeventfd)) <= 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown disk ioeventfd mode '%s'"), + ioeventfd); + goto error; + } + def->ioeventfd = i; + } + + if (devaddr) { if (virDomainParseLegacyDeviceAddress(devaddr, &def->info.addr.pci) < 0) { @@ -2142,6 +2161,7 @@ cleanup: VIR_FREE(cachetag); VIR_FREE(error_policy); VIR_FREE(iotag); + VIR_FREE(ioeventfd); VIR_FREE(devaddr); VIR_FREE(serial); virStorageEncryptionFree(encryption); @@ -2529,6 +2549,7 @@ virDomainNetDefParseXML(virCapsPtr caps, char *model = NULL; char *backend = NULL; char *txmode = NULL; + char *ioeventfd = NULL; char *filter = NULL; char *internal = NULL; char *devaddr = NULL; @@ -2618,6 +2639,7 @@ virDomainNetDefParseXML(virCapsPtr caps, } else if (xmlStrEqual (cur->name, BAD_CAST "driver")) { backend = virXMLPropString(cur, "name"); txmode = virXMLPropString(cur, "txmode"); + ioeventfd = virXMLPropString(cur, "ioeventfd"); } else if (xmlStrEqual (cur->name, BAD_CAST "filterref")) { filter = virXMLPropString(cur, "filter"); VIR_FREE(filterparams); @@ -2834,6 +2856,17 @@ virDomainNetDefParseXML(virCapsPtr caps, } def->driver.virtio.txmode = m; } + if (ioeventfd != NULL) { + int i; + if ((i = virDomainVirtioEventFdTypeFromString(ioeventfd)) <= 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown interface has been specified"), + ioeventfd); + goto error; + } + def->driver.virtio.ioeventfd = i; + } } if (filter != NULL) { @@ -2873,6 +2906,7 @@ cleanup: VIR_FREE(model); VIR_FREE(backend); VIR_FREE(txmode); + VIR_FREE(ioeventfd); VIR_FREE(filter); VIR_FREE(type); VIR_FREE(internal); @@ -6910,6 +6944,7 @@ virDomainDiskDefFormat(virBufferPtr buf, const char *cachemode = virDomainDiskCacheTypeToString(def->cachemode); const char *error_policy = virDomainDiskErrorPolicyTypeToString(def->error_policy); const char *iomode = virDomainDiskIoTypeToString(def->iomode); + const char *ioeventfd = virDomainVirtioEventFdTypeToString(def->ioeventfd); if (!type) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, @@ -6941,7 +6976,8 @@ virDomainDiskDefFormat(virBufferPtr buf, " \n", type, device); - if (def->driverName || def->driverType || def->cachemode) { + if (def->driverName || def->driverType || def->cachemode || + def->ioeventfd) { virBufferVSprintf(buf, " driverName) virBufferVSprintf(buf, " name='%s'", def->driverName); @@ -6953,6 +6989,8 @@ virDomainDiskDefFormat(virBufferPtr buf, virBufferVSprintf(buf, " error_policy='%s'", error_policy); if (def->iomode) virBufferVSprintf(buf, " io='%s'", iomode); + if (def->ioeventfd) + virBufferVSprintf(buf, " ioeventfd='%s'", ioeventfd); virBufferVSprintf(buf, "/>\n"); } @@ -7243,6 +7281,10 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferVSprintf(buf, " txmode='%s'", virDomainNetVirtioTxModeTypeToString(def->driver.virtio.txmode)); } + if (def->driver.virtio.ioeventfd) { + virBufferVSprintf(buf, " ioeventfd='%s'", + virDomainVirtioEventFdTypeToString(def->driver.virtio.ioeventfd)); + } virBufferAddLit(buf, "/>\n"); } } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6ea30b9..42ca601 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -197,6 +197,15 @@ enum virDomainDiskIo { VIR_DOMAIN_DISK_IO_LAST }; +enum virDomainVirtioEventFd { + VIR_DOMAIN_VIRTIO_EVENT_FD_DEFAULT = 0, + VIR_DOMAIN_VIRTIO_EVENT_FD_ON, + VIR_DOMAIN_VIRTIO_EVENT_FD_OFF, + + VIR_DOMAIN_VIRTIO_EVENT_FD_LAST +}; + + /* Stores the virtual disk configuration */ typedef struct _virDomainDiskDef virDomainDiskDef; typedef virDomainDiskDef *virDomainDiskDefPtr; @@ -216,6 +225,7 @@ struct _virDomainDiskDef { int error_policy; int bootIndex; int iomode; + enum virDomainVirtioEventFd ioeventfd; unsigned int readonly : 1; unsigned int shared : 1; virDomainDeviceInfo info; @@ -351,6 +361,7 @@ struct _virDomainNetDef { struct { enum virDomainNetBackendType name; /* which driver backend to use */ enum virDomainNetVirtioTxModeType txmode; + enum virDomainVirtioEventFd ioeventfd; } virtio; } driver; union { @@ -1439,6 +1450,7 @@ VIR_ENUM_DECL(virDomainDiskCache) VIR_ENUM_DECL(virDomainDiskErrorPolicy) VIR_ENUM_DECL(virDomainDiskProtocol) VIR_ENUM_DECL(virDomainDiskIo) +VIR_ENUM_DECL(virDomainVirtioEventFd) VIR_ENUM_DECL(virDomainController) VIR_ENUM_DECL(virDomainControllerModel) VIR_ENUM_DECL(virDomainFS) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 3d53287..1bd90a1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -338,6 +338,8 @@ virDomainVideoDefaultType; virDomainVideoTypeFromString; virDomainVideoTypeToString; virDomainVirtTypeToString; +virDomainVirtioEventFdTypeFromString; +virDomainVirtioEventFdTypeToString; virDomainWatchdogActionTypeFromString; virDomainWatchdogActionTypeToString; virDomainWatchdogModelTypeFromString; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 63486cc..6e8aa50 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -1124,6 +1124,8 @@ qemuCapsParseDeviceStr(const char *str, virBitmapPtr flags) qemuCapsSet(flags, QEMU_CAPS_VIRTIO_TX_ALG); if (strstr(str, "name \"qxl-vga\"")) qemuCapsSet(flags, QEMU_CAPS_DEVICE_QXL_VGA); + if (strstr(str, "virtio-blk-pci.ioeventfd")) + qemuCapsSet(flags, QEMU_CAPS_VIRTIO_IOEVENTFD); return 0; } diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 68c5958..400d73c 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -95,6 +95,7 @@ enum qemuCapsFlags { QEMU_CAPS_DEVICE_SPICEVMC = 57, /* older -device spicevmc*/ QEMU_CAPS_VIRTIO_TX_ALG = 58, /* -device virtio-net-pci,tx=string */ QEMU_CAPS_DEVICE_QXL_VGA = 59, /* Is the primary and vga campatible qxl device named qxl-vga? */ + QEMU_CAPS_VIRTIO_IOEVENTFD = 60, /* IOEventFD feature: virtio-{net|blk}-pci.ioeventfd=on/off */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2205ed1..41b4fdd 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1169,6 +1169,26 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, return 0; } +static int +qemuBuildIoEventFdStr(virBufferPtr buf, + enum virDomainVirtioEventFd use, + virBitmapPtr qemuCaps) +{ + if (qemuCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_IOEVENTFD)) { + switch (use) { + case VIR_DOMAIN_VIRTIO_EVENT_FD_ON: + case VIR_DOMAIN_VIRTIO_EVENT_FD_OFF: + virBufferVSprintf(buf, ",ioeventfd=%s", + virDomainVirtioEventFdTypeToString(use)); + break; + default: + /* In other cases (_DEFAULT, _LAST) we don't + * want to add anything */ + break; + } + } + return 0; +} #define QEMU_SERIAL_PARAM_ACCEPTED_CHARS \ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" @@ -1434,6 +1454,7 @@ qemuBuildDriveDevStr(virDomainDiskDefPtr disk, break; case VIR_DOMAIN_DISK_BUS_VIRTIO: virBufferAddLit(&opt, "virtio-blk-pci"); + qemuBuildIoEventFdStr(&opt, disk->ioeventfd, qemuCaps); qemuBuildDeviceAddressStr(&opt, &disk->info, qemuCaps); break; case VIR_DOMAIN_DISK_BUS_USB: @@ -1656,6 +1677,8 @@ qemuBuildNicDevStr(virDomainNetDefPtr net, goto error; } } + if(usingVirtio) + qemuBuildIoEventFdStr(&buf, net->driver.virtio.ioeventfd, qemuCaps); if (vlan == -1) virBufferVSprintf(&buf, ",netdev=host%s", net->info.alias); else diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index c86c578..776acf5 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -490,7 +490,8 @@ mymain(int argc, char **argv) QEMU_CAPS_CCID_PASSTHRU, QEMU_CAPS_CHARDEV_SPICEVMC, QEMU_CAPS_DEVICE_QXL_VGA, - QEMU_CAPS_VIRTIO_TX_ALG); + QEMU_CAPS_VIRTIO_TX_ALG, + QEMU_CAPS_VIRTIO_IOEVENTFD); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.7.4.4 From jdenemar at redhat.com Wed Apr 27 10:34:47 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Wed, 27 Apr 2011 12:34:47 +0200 Subject: [libvirt] [PATCH] build: Use pkg-config for libssh2 check Message-ID: Currently the build fails if /usr/local/include does not exist since its use is hardcoded in configure.ac --- configure.ac | 86 ++++++++++++++------------------------------------------- 1 files changed, 21 insertions(+), 65 deletions(-) diff --git a/configure.ac b/configure.ac index 25cc15b..39e3a05 100644 --- a/configure.ac +++ b/configure.ac @@ -68,6 +68,7 @@ DEVMAPPER_REQUIRED=1.0.0 LIBCURL_REQUIRED="7.18.0" LIBPCAP_REQUIRED="1.0.0" LIBNL_REQUIRED="1.1" +LIBSSH2_REQUIRED="1.0" dnl Checks for C compiler. AC_PROG_CC @@ -258,7 +259,7 @@ AC_ARG_WITH([openvz], AC_ARG_WITH([vmware], AC_HELP_STRING([--with-vmware], [add VMware support @<:@default=yes@:>@]),[],[with_vmware=yes]) AC_ARG_WITH([libssh2], - AC_HELP_STRING([--with-libssh2=@<:@PFX@:>@], [libssh2 location @<:@default=/usr/local/lib@:>@]),[],[with_libssh2=yes]) + AC_HELP_STRING([--with-libssh2], [libssh2 location @<:@default=check@:>@]),[],[with_libssh2=check]) AC_ARG_WITH([phyp], AC_HELP_STRING([--with-phyp], [add PHYP support @<:@default=check@:>@]),[],[with_phyp=check]) AC_ARG_WITH([xenapi], @@ -1328,78 +1329,33 @@ AM_CONDITIONAL([WITH_UML], [test "$with_uml" = "yes"]) dnl -dnl libssh checks +dnl check for libssh2 (PHYP) dnl -if test "$with_libssh2" != "yes" && test "$with_libssh2" != "no"; then - libssh2_path="$with_libssh2" -elif test "$with_libssh2" = "yes"; then - libssh2_path="/usr/local/lib/" -elif test "$with_libssh2" = "no"; then - with_phyp="no"; -fi +LIBSSH2_CFLAGS="" +LIBSSH2_LIBS="" -if test "$with_phyp" = "check"; then - AC_CHECK_LIB([ssh2],[libssh2_session_startup],[ - LIBSSH2_LIBS="$LIBSSH2_LIBS -lssh2 -L$libssh2_path" - AC_SUBST([LIBSSH2_LIBS]) - ],[ - with_phyp="no" - with_libssh2="no"; - ],[]) - - if test "$with_phyp" != "no"; then - AC_CHECK_HEADERS([libssh2.h],[ - with_phyp="yes" - LIBSSH2_CFLAGS="-I/usr/local/include" - AC_SUBST([LIBSSH2_CFLAGS]) - ],[ - with_phyp="no" - with_libssh2="no"; - ],[ - ]) - fi - - if test "$with_phyp" != "no"; then - saved_libs="$LIBS" - LIBS="$LIBS -L$libssh2_path -lssh2" - AC_TRY_LINK([#include ], [ - (void) libssh2_session_block_directions(NULL); - ], [ - AC_DEFINE_UNQUOTED([WITH_PHYP], 1, [whether IBM HMC / IVM driver is enabled]) - ], [ +if test "$with_phyp" = "yes" || test "$with_phyp" = "check"; then + PKG_CHECK_MODULES(LIBSSH2, libssh2 >= $LIBSSH2_REQUIRED, [ + with_phyp=yes + ], [ + if test "$with_phyp" = "check"; then with_phyp=no - AC_MSG_NOTICE([Function libssh2_session_block_directions() not present in your version of libssh2 but required for Phyp driver, disabling it]) - ]) - LIBS="$saved_libs" - fi -elif test "$with_phyp" = "yes"; then - AC_CHECK_LIB([ssh2],[libssh2_session_startup],[ - LIBSSH2_LIBS="$LIBSSH2_LIBS -lssh2 -L$libssh2_path" - AC_SUBST([LIBSSH2_LIBS])],[ - AC_MSG_ERROR([You must install the libssh2 to compile Phyp driver.]) - ]) - - AC_CHECK_HEADERS([libssh2.h],[ - LIBSSH2_CFLAGS="-I/usr/local/include" - AC_SUBST([LIBSSH2_CFLAGS])],[ - AC_MSG_ERROR([Cannot find libssh2 headers. Is libssh2 installed ?]) - ],[]) - - saved_libs="$LIBS" - LIBS="$LIBS -lssh2" - AC_TRY_LINK([#include ], [ - (void) libssh2_session_block_directions(NULL); - ], [], [ - AC_MSG_ERROR([Function libssh2_session_block_directions() not present in your version of libssh2. Need >= 1.0]) - ]) - LIBS="$saved_libs" + AC_MSG_NOTICE([libssh2 is required for Phyp driver, disabling it]) + else + AC_MSG_ERROR([libssh2 >= $LIBSSH2_REQUIRED is required for Phyp driver]) + fi + ]) +fi - AC_DEFINE_UNQUOTED([WITH_PHYP], 1, - [whether IBM HMC / IVM driver is enabled]) +if test "$with_phyp" = "yes"; then + AC_DEFINE_UNQUOTED([WITH_PHYP], 1, [whether IBM HMC / IVM driver is enabled]) fi AM_CONDITIONAL([WITH_PHYP],[test "$with_phyp" = "yes"]) +AC_SUBST([LIBSSH2_CFLAGS]) +AC_SUBST([LIBSSH2_LIBS]) + dnl libcap-ng AC_ARG_WITH([capng], AC_HELP_STRING([--with-capng], [use libcap-ng to reduce libvirtd privileges @<:@default=check@:>@]), -- 1.7.5.rc1 From hahn at univention.de Wed Apr 27 11:20:01 2011 From: hahn at univention.de (Philipp Hahn) Date: Wed, 27 Apr 2011 13:20:01 +0200 Subject: [libvirt] [BUG] Xen->libvirt: localtime reported as UTC Message-ID: <201104271320.11565.hahn@univention.de> Hello, just a report, no fix for that bug yet. If I create a domain and set , that information is correctly translated to Xends sxpr data, but on reading it back I get it reported as 'utc': # virsh dumpxml 85664d3f-68dd-a4c2-4d2f-be7f276b95f0 | grep clock # gfind localtime ./85664d3f-68dd-a4c2-4d2f-be7f276b95f0/config.sxp: (platform ((device_model /usr/lib64/xen/bin/qemu-dm) (localtime 1))) ./85664d3f-68dd-a4c2-4d2f-be7f276b95f0/config.sxp: (localtime 1) BYtE Philipp -- Philipp Hahn Open Source Software Engineer hahn at univention.de Univention GmbH Linux for Your Business fon: +49 421 22 232- 0 Mary-Somerville-Str.1 D-28359 Bremen fax: +49 421 22 232-99 http://www.univention.de/ -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 197 bytes Desc: This is a digitally signed message part. URL: From yuzhang at redhat.com Wed Apr 27 12:09:12 2011 From: yuzhang at redhat.com (Yufang Zhang) Date: Wed, 27 Apr 2011 20:09:12 +0800 Subject: [libvirt] [PATCH V3] xen: check if device is assigned to guest before reattaching Message-ID: <1303906152-4601-1-git-send-email-yuzhang@redhat.com> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=664059 This is the version3 patch for BZ#664059. Reattaching pci device back to host without destroying guest or detaching device from guest would cause host to crash. This patch adds a check before doing device reattach. If the device is being assigned to guest, libvirt refuses to reattach device to host. The patch only works for Xen, for it just checks xenstore to get pci device information. This version fixes some formatting problem and moves lock-unlock out of loop so that the check is atomic. Signed-off-by: Yufang Zhang --- src/xen/xen_driver.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 67 insertions(+), 0 deletions(-) diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 2a07b7b..dd94fbc 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1927,11 +1927,70 @@ out: } static int +xenUnifiedNodeDeviceAssignedDomainId (virNodeDevicePtr dev) +{ + int numdomains; + int ret = -1, i; + int *ids = NULL; + char *bdf = NULL; + char *xref = NULL; + unsigned int domain, bus, slot, function; + virConnectPtr conn = dev->conn; + xenUnifiedPrivatePtr priv = conn->privateData; + + /* Get active domains */ + numdomains = xenUnifiedNumOfDomains(conn); + if (numdomains < 0) { + return ret; + } + if (numdomains > 0){ + if (VIR_ALLOC_N(ids, numdomains) < 0) { + virReportOOMError(); + goto out; + } + if ((numdomains = xenUnifiedListDomains(conn, &ids[0], numdomains)) < 0) { + goto out; + } + } + + /* Get pci bdf */ + if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) + goto out; + + if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x", + domain, bus, slot, function) < 0) { + virReportOOMError(); + goto out; + } + + xenUnifiedLock(priv); + /* Check if bdf is assigned to one of active domains */ + for (i = 0; i < numdomains; i++ ) { + xref = xenStoreDomainGetPCIID(conn, ids[i], bdf); + if (xref == NULL) { + continue; + } else { + ret = ids[i]; + break; + } + } + xenUnifiedUnlock(priv); + + VIR_FREE(xref); + VIR_FREE(bdf); +out: + VIR_FREE(ids); + + return ret; +} + +static int xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev) { pciDevice *pci; unsigned domain, bus, slot, function; int ret = -1; + int domid; if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) return -1; @@ -1940,6 +1999,14 @@ xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev) if (!pci) return -1; + /* Check if device is assigned to an active guest */ + if ((domid = xenUnifiedNodeDeviceAssignedDomainId(dev)) >= 0) { + xenUnifiedError(VIR_ERR_INTERNAL_ERROR, + _("Device %s has been assigned to guest %d"), + dev->name, domid); + goto out; + } + if (pciReAttachDevice(pci, NULL) < 0) goto out; -- 1.7.4 From yuzhang at redhat.com Wed Apr 27 12:14:41 2011 From: yuzhang at redhat.com (Yufang Zhang) Date: Wed, 27 Apr 2011 20:14:41 +0800 Subject: [libvirt] [PATCH V2] xen: check if device is assigned to guest before reattaching In-Reply-To: <4DB6D62A.8040003@redhat.com> References: <1294384518-15492-1-git-send-email-yuzhang@redhat.com> <4DB6D62A.8040003@redhat.com> Message-ID: <4DB808B1.3010908@redhat.com> On 04/26/2011 10:26 PM, Eric Blake wrote: > On 01/07/2011 12:15 AM, Yufang Zhang wrote: >> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=664059 >> >> This is the version2 patch for BZ#664059. Reattaching pci device back to >> host without destroying guest or detaching device from guest would cause >> host to crash. This patch adds a check before doing device reattach. If >> the device is being assigned to guest, libvirt refuses to reattach device >> to host. The patch only works for Xen, for it just checks xenstore to get >> pci device information. >> >> Signed-off-by: Yufang Zhang >> --- >> src/xen/xen_driver.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ >> 1 files changed, 67 insertions(+), 0 deletions(-) > Wow, just noticed that this hasn't had any review - does it still apply > to the latest upstream? > The v3 patch has been sent which is based on latest upstream. >> diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c >> index 4c11b11..318bb6a 100644 >> --- a/src/xen/xen_driver.c >> +++ b/src/xen/xen_driver.c >> @@ -1891,11 +1891,70 @@ out: >> } >> >> static int >> +xenUnifiedNodeDeviceAssignedDomainId (virNodeDevicePtr dev) >> +{ >> + int numdomains; >> + int ret = -1, i; >> + int *ids = NULL; >> + char *bdf = NULL; >> + char *xref = NULL; >> + unsigned int domain, bus, slot, function; >> + virConnectPtr conn = dev->conn; >> + xenUnifiedPrivatePtr priv = conn->privateData; >> + >> + /* Get active domains */ >> + numdomains = xenUnifiedNumOfDomains(conn); >> + if (numdomains< 0) { >> + return ret; >> + } >> + if (numdomains> 0){ >> + if (VIR_ALLOC_N(ids, numdomains)< 0){ > Formatting nit - space before {, as in: > > if (VIR_ALLOC_N(ids, numdomains)< 0) { > >> + virReportOOMError(); >> + goto out; >> + } >> + if ((numdomains = xenUnifiedListDomains(conn,&ids[0], numdomains))< 0){ >> + goto out; >> + } >> + } >> + >> + /* Get pci bdf */ >> + if (xenUnifiedNodeDeviceGetPciInfo(dev,&domain,&bus,&slot,&function)< 0) >> + goto out; >> + >> + if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x", >> + domain, bus, slot, function)< 0) { >> + virReportOOMError(); >> + goto out; >> + } >> + >> + /* Check if bdf is assigned to one of active domains */ >> + for (i = 0; i< numdomains; i++ ){ > Again, a formatting nit: > > for (i = 0; i< numdomains; i++) { > >> + xenUnifiedLock(priv); >> + xref = xenStoreDomainGetPCIID(conn, ids[i], bdf); >> + xenUnifiedUnlock(priv); > This locks and unlocks around every iteration of the loop. Would it be > better to hold the lock for the entire loop duration, so that the action > is atomic (no other thread can interrupt things), or is it better to > drop the lock each iteration? I'm not as familiar with the xen > architecture to give a good answer to this off the top of my head. > I think moving the lock-unlock pair out of loop should work. >> + if (xref == NULL) >> + continue; >> + else { > Formatting - if one branch of an if-else has {}, then both need it: > > if (xref == NULL) { > continue; > } else { > >> + ret = ids[i]; >> + break; >> + } >> + } >> + >> + VIR_FREE(xref); >> + VIR_FREE(bdf); >> +out: >> + VIR_FREE(ids); >> + >> + return ret; >> +} >> + >> +static int >> xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev) >> { >> pciDevice *pci; >> unsigned domain, bus, slot, function; >> int ret = -1; >> + int domid; >> >> if (xenUnifiedNodeDeviceGetPciInfo(dev,&domain,&bus,&slot,&function)< 0) >> return -1; >> @@ -1904,6 +1963,14 @@ xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev) >> if (!pci) >> return -1; >> >> + /* Check if device is assigned to an active guest */ >> + if ((domid = xenUnifiedNodeDeviceAssignedDomainId(dev))>= 0){ >> + xenUnifiedError(VIR_ERR_INTERNAL_ERROR, >> + _("Device %s has been assigned to guest %d"), >> + dev->name, domid); >> + goto out; >> + } >> + >> if (pciReAttachDevice(pci, NULL)< 0) >> goto out; >> From wencongyang at gmail.com Wed Apr 27 12:15:53 2011 From: wencongyang at gmail.com (Wen Congyang) Date: Wed, 27 Apr 2011 20:15:53 +0800 Subject: [libvirt] [PATCH V2] free buf->content when vsnprintf() failed In-Reply-To: <20110427062249.GM10484@redhat.com> References: <4DB7ACFC.6060805@cn.fujitsu.com> <20110427062249.GM10484@redhat.com> Message-ID: <4DB808F9.8040003@gmail.com> At 2011-4-27 14:22, Daniel Veillard write: > On Wed, Apr 27, 2011 at 01:43:24PM +0800, Wen Congyang wrote: >> When buf->error is 1, we do not return buf->content in the function >> virBufferContentAndReset(). So we should free buf->content when >> vsnprintf() failed. >> >> --- >> Changes >> v1->v2 >> - rename virBufferNoMemory() to virBufferSetError() and use it >> to free buf->content as Laine Stump suggested >> >> src/util/buf.c | 12 ++++++------ >> 1 files changed, 6 insertions(+), 6 deletions(-) >> >> diff --git a/src/util/buf.c b/src/util/buf.c >> index 7557ad1..a3cc063 100644 >> --- a/src/util/buf.c >> +++ b/src/util/buf.c >> @@ -39,7 +39,7 @@ struct _virBuffer { >> * freeing the content and setting the error flag. >> */ >> static void >> -virBufferNoMemory(const virBufferPtr buf) >> +virBufferSetError(const virBufferPtr buf) >> { >> VIR_FREE(buf->content); >> buf->size = 0; >> @@ -70,7 +70,7 @@ virBufferGrow(virBufferPtr buf, unsigned int len) >> size = buf->use + len + 1000; >> >> if (VIR_REALLOC_N(buf->content, size)< 0) { >> - virBufferNoMemory(buf); >> + virBufferSetError(buf); >> return -1; >> } >> buf->size = size; >> @@ -241,7 +241,7 @@ virBufferVSprintf(const virBufferPtr buf, const char *format, ...) >> size = buf->size - buf->use; >> if ((count = vsnprintf(&buf->content[buf->use], >> size, format, argptr))< 0) { >> - buf->error = 1; >> + virBufferSetError(buf); >> goto err; >> } >> >> @@ -259,7 +259,7 @@ virBufferVSprintf(const virBufferPtr buf, const char *format, ...) >> size = buf->size - buf->use; >> if ((count = vsnprintf(&buf->content[buf->use], >> size, format, argptr))< 0) { >> - buf->error = 1; >> + virBufferSetError(buf); >> goto err; >> } >> } >> @@ -299,7 +299,7 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st >> } >> >> if (VIR_ALLOC_N(escaped, 6 * len + 1)< 0) { >> - virBufferNoMemory(buf); >> + virBufferSetError(buf); >> return; >> } >> >> @@ -386,7 +386,7 @@ virBufferEscapeSexpr(const virBufferPtr buf, >> } >> >> if (VIR_ALLOC_N(escaped, 2 * len + 1)< 0) { >> - virBufferNoMemory(buf); >> + virBufferSetError(buf); >> return; >> } >> > > ACK, Thanks, pushed. > > Daniel > From ghostwcy at gmail.com Wed Apr 27 12:16:20 2011 From: ghostwcy at gmail.com (ghostwcy) Date: Wed, 27 Apr 2011 20:16:20 +0800 Subject: [libvirt] [PATCH] release PCI address only when we have ensured it successfully In-Reply-To: <20110427064347.GP10484@redhat.com> References: <4DB63E91.6030405@cn.fujitsu.com> <20110427064347.GP10484@redhat.com> Message-ID: <4DB80914.1040402@gmail.com> At 2011-4-27 14:43, Daniel Veillard write: > On Tue, Apr 26, 2011 at 11:40:01AM +0800, Wen Congyang wrote: >> Steps to reproduce this bug: >> 1. # cat net.xml # 00:03.0 has been used >> >> >> >>
    >> >> >> 2. # virsh attach-device vm1 net.xml >> error: Failed to attach device from net.xml >> error: internal error unable to reserve PCI address 0:0:3 >> >> 3. # virsh attach-device vm1 net.xml >> error: Failed to attach device from net.xml >> error: internal error unable to execute QEMU command 'device_add': Device 'rtl8139' could not be initialized >> >> The reason of this bug is that: we can not reserve PCI address 0:0:3 because it has >> been used, but we release PCI address when we reserve it failed. >> >> --- >> src/qemu/qemu_hotplug.c | 13 +++++++++++++ >> 1 files changed, 13 insertions(+), 0 deletions(-) >> >> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c >> index b03f774..5fdb013 100644 >> --- a/src/qemu/qemu_hotplug.c >> +++ b/src/qemu/qemu_hotplug.c >> @@ -147,6 +147,7 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver, >> qemuDomainObjPrivatePtr priv = vm->privateData; >> char *devstr = NULL; >> char *drivestr = NULL; >> + bool releaseaddr = false; >> >> for (i = 0 ; i< vm->def->ndisks ; i++) { >> if (STREQ(vm->def->disks[i]->dst, disk->dst)) { >> @@ -163,6 +164,7 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver, >> if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { >> if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs,&disk->info)< 0) >> goto error; >> + releaseaddr = true; >> if (qemuAssignDeviceDiskAlias(disk, qemuCaps)< 0) >> goto error; >> >> @@ -221,6 +223,7 @@ error: >> >> if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)&& >> (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)&& >> + releaseaddr&& >> qemuDomainPCIAddressReleaseAddr(priv->pciaddrs,&disk->info)< 0) >> VIR_WARN("Unable to release PCI address on %s", disk->src); >> >> @@ -242,6 +245,7 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver, >> const char* type = virDomainControllerTypeToString(controller->type); >> char *devstr = NULL; >> qemuDomainObjPrivatePtr priv = vm->privateData; >> + bool releaseaddr = false; >> >> for (i = 0 ; i< vm->def->ncontrollers ; i++) { >> if ((vm->def->controllers[i]->type == controller->type)&& >> @@ -256,6 +260,7 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver, >> if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { >> if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs,&controller->info)< 0) >> goto cleanup; >> + releaseaddr = true; >> if (qemuAssignDeviceControllerAlias(controller)< 0) >> goto cleanup; >> >> @@ -288,6 +293,7 @@ cleanup: >> if ((ret != 0)&& >> qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)&& >> (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)&& >> + releaseaddr&& >> qemuDomainPCIAddressReleaseAddr(priv->pciaddrs,&controller->info)< 0) >> VIR_WARN0("Unable to release PCI address on controller"); >> >> @@ -559,6 +565,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, >> int ret = -1; >> virDomainDevicePCIAddress guestAddr; >> int vlan; >> + bool releaseaddr = false; >> >> if (!qemuCapsGet(qemuCaps, QEMU_CAPS_HOST_NET_ADD)) { >> qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", >> @@ -595,6 +602,8 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, >> qemuDomainPCIAddressEnsureAddr(priv->pciaddrs,&net->info)< 0) >> goto cleanup; >> >> + releaseaddr = true; >> + >> if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV)&& >> qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { >> vlan = -1; >> @@ -694,6 +703,7 @@ cleanup: >> if ((ret != 0)&& >> qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)&& >> (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)&& >> + releaseaddr&& >> qemuDomainPCIAddressReleaseAddr(priv->pciaddrs,&net->info)< 0) >> VIR_WARN0("Unable to release PCI address on NIC"); >> >> @@ -757,6 +767,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, >> char *devstr = NULL; >> int configfd = -1; >> char *configfd_name = NULL; >> + bool releaseaddr = false; >> >> if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1)< 0) { >> virReportOOMError(); >> @@ -771,6 +782,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, >> goto error; >> if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs,&hostdev->info)< 0) >> goto error; >> + releaseaddr = true; >> if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_CONFIGFD)) { >> configfd = qemuOpenPCIConfig(hostdev); >> if (configfd>= 0) { >> @@ -823,6 +835,7 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, >> error: >> if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)&& >> (hostdev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)&& >> + releaseaddr&& >> qemuDomainPCIAddressReleaseAddr(priv->pciaddrs,&hostdev->info)< 0) >> VIR_WARN0("Unable to release PCI address on host device"); > > The logic fo the fix sounds right, and it looks complete, > > ACK, Thanks, pushed. > > Daniel > From wencongyang at gmail.com Wed Apr 27 12:20:04 2011 From: wencongyang at gmail.com (Wen Congyang) Date: Wed, 27 Apr 2011 20:20:04 +0800 Subject: [libvirt] [PATCH] free memory properly in cleanup patch In-Reply-To: <20110427064046.GO10484@redhat.com> References: <20110426012031.GA13689@localhost.localdomain> <20110427064046.GO10484@redhat.com> Message-ID: <4DB809F4.7030707@gmail.com> At 2011-4-27 14:40, Daniel Veillard write: > On Tue, Apr 26, 2011 at 09:20:31AM +0800, Hu Tao wrote: >> virsh schedinfo inactive-domain will trigger the problem. I can reproduce this problem, and it will cause libvirtd crashed. I use gdb to analyze the core file, and see ret->params.params_val is NULL. So this patch is good fix. >> --- >> daemon/remote.c | 7 +++++-- >> 1 files changed, 5 insertions(+), 2 deletions(-) >> >> diff --git a/daemon/remote.c b/daemon/remote.c >> index 1c98bba..eedbc77 100644 >> --- a/daemon/remote.c >> +++ b/daemon/remote.c >> @@ -945,8 +945,11 @@ remoteDispatchDomainGetSchedulerParameters(struct qemud_server *server ATTRIBUTE >> cleanup: >> if (rv< 0) { >> remoteDispatchError(rerr); >> - for (i = 0 ; i< nparams ; i++) >> - VIR_FREE(ret->params.params_val[i].field); >> + 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); >> + } >> } >> if (dom) >> virDomainFree(dom); > > ACK, a daemon leak, good fix ! Thanks, applied. > > Daniel > From jyang at redhat.com Wed Apr 27 13:08:51 2011 From: jyang at redhat.com (Osier Yang) Date: Wed, 27 Apr 2011 21:08:51 +0800 Subject: [libvirt] [PATCH] build: Fix problem of building Python bindings In-Reply-To: <20110427065938.GQ10484@redhat.com> References: <1303875993-9780-1-git-send-email-jyang@redhat.com> <20110427065938.GQ10484@redhat.com> Message-ID: <4DB81563.8040209@redhat.com> ? 2011?04?27? 14:59, Daniel Veillard ??: > On Wed, Apr 27, 2011 at 11:46:33AM +0800, Osier Yang wrote: >> If one specify "--with-python=yes" but no python-devel package >> is installed, we ignore it with just a notice message, which >> doesn't give clear guide to user. >> --- >> configure.ac | 6 ++---- >> 1 files changed, 2 insertions(+), 4 deletions(-) >> >> diff --git a/configure.ac b/configure.ac >> index 190bf40..758c893 100644 >> --- a/configure.ac >> +++ b/configure.ac >> @@ -1917,15 +1917,13 @@ if test "$with_python" != "no" ; then >> then >> PYTHON_INCLUDES=-I/usr/include/python$PYTHON_VERSION >> else >> - AC_MSG_NOTICE([Could not find python$PYTHON_VERSION/Python.h, disabling bindings]) >> - with_python=no >> + AC_MSG_ERROR([You must install python-devel to build Python bindings]) >> fi >> fi >> fi >> fi >> else >> - AC_MSG_NOTICE([Could not find python interpreter, disabling bindings]) >> - with_python=no >> + AC_MSG_ERROR([You must install python to build Python bindings]) >> fi >> else >> AC_MSG_NOTICE([Could not find python in $with_python, disabling bindings]) > > Hum ... the message may be a bit less "generaic" but probably more > useful, okay > > ACK, > > Daniel > Thanks, applied Osier From hahn at univention.de Wed Apr 27 13:20:51 2011 From: hahn at univention.de (Philipp Hahn) Date: Wed, 27 Apr 2011 15:20:51 +0200 Subject: [libvirt] [PATCH] Fix domxml-from-native xen-sxpr for domain/clock/@offset='localtime' In-Reply-To: <201104271320.11565.hahn@univention.de> References: <201104271320.11565.hahn@univention.de> Message-ID: <61b714d6a96b842e37bc549350b080b320cabd3c.1303911359.git.hahn@univention.de> 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 still tries to read /domain/localtime, which now isn't found anymore. Instead domxml-from-native should read back /domain/platform/localtime. This is tracked at Signed-off-by: Philipp Hahn --- src/xenxs/xen_sxpr.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c index 0241695..5b997af 100644 --- a/src/xenxs/xen_sxpr.c +++ b/src/xenxs/xen_sxpr.c @@ -1194,12 +1194,15 @@ xenParseSxpr(const struct sexpr *root, if (sexpr_int(root, "domain/image/hvm/hap")) def->features |= (1 << VIR_DOMAIN_FEATURE_HAP); - /* Old XenD only allows localtime here for HVM */ + /* Old(?) XenD only allows localtime here for HVM */ if (sexpr_int(root, "domain/image/hvm/localtime")) def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; } - /* Current XenD allows localtime here, for PV and HVM */ + /* XenD-3.4.3 allows localtime here, for PV and HVM */ + if (sexpr_int(root, "domain/platform/localtime")) + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; + /* Current(?) XenD allows localtime here, for PV and HVM */ if (sexpr_int(root, "domain/localtime")) def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; -- 1.7.1 From jdenemar at redhat.com Wed Apr 27 13:39:13 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Wed, 27 Apr 2011 15:39:13 +0200 Subject: [libvirt] [PATCH] tests: More unit tests for internal hash APIs In-Reply-To: <4DB6EEAF.5000607@redhat.com> References: <0ebc29ed7078c909b92f692d28c572f0c05ff9b9.1302629114.git.jdenemar@redhat.com> <4DB6EEAF.5000607@redhat.com> Message-ID: <20110427133913.GA2642114@orkuz.home> On Tue, Apr 26, 2011 at 10:11:27 -0600, Eric Blake wrote: > On 04/19/2011 07:22 AM, Jiri Denemark wrote: > > This adds several tests for remaining hash APIs (custom > > hasher/comparator functions are not covered yet, though). > > > > All tests pass both before and after the "Simplify hash implementation". > > --- > > src/util/hash.c | 18 +++ > > src/util/hash.h | 1 + > > tests/hashdata.h | 237 +++++++++++++++++++++++++++++++++++- > > tests/hashtest.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > 4 files changed, 615 insertions(+), 2 deletions(-) > > Overall, this looks like a good patch; the fact that it passes 'make > check' speaks highly, and it is some good additional coverage. > > ACK with nits fixed. Thanks, I fixed the nits (inc. seeding the pseudo-random number generator) and pushed. Jirka From jdenemar at redhat.com Wed Apr 27 13:39:40 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Wed, 27 Apr 2011 15:39:40 +0200 Subject: [libvirt] [PATCH v2] util: Simplify hash implementation In-Reply-To: <4DA4A397.9080002@redhat.com> References: <0ebc29ed7078c909b92f692d28c572f0c05ff9b9.1302629114.git.jdenemar@redhat.com> <4DA4A397.9080002@redhat.com> Message-ID: <20110427133940.GA2711365@orkuz.home> On Tue, Apr 12, 2011 at 13:10:15 -0600, Eric Blake wrote: > On 04/12/2011 11:25 AM, Jiri Denemark wrote: > > So far first entries for each hash key are stored directly in the hash > > table while other entries mapped to the same key are linked through > > pointers. As a result of that, the code is cluttered with special > > handling for the first items. > > > > This patch makes all entries (even the first ones) linked through > > pointers, which significantly simplifies the code and makes it more > > maintainable. > > --- > > src/util/hash.c | 294 +++++++++++++++++-------------------------------------- > > 1 files changed, 92 insertions(+), 202 deletions(-) > > ACK - all the changes look correct, and certainly simpler. Thanks, I pushed the patch since we have the unit test now. Jirka From crobinso at redhat.com Wed Apr 27 13:47:55 2011 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 27 Apr 2011 09:47:55 -0400 Subject: [libvirt] RFC: virt-xml: command line tool for altering guest configuration Message-ID: <4DB81E8B.3010503@redhat.com> Hi all, Attached is a patch to virtinst.git that provides a new tool named virt-xml. virt-xml provides a scriptable command line interface for editing libvirt guest XML. A couple examples: Change boot order and boot menu for 'myguest': $ ./virt-xml --guest myguest --boot network,hd,cdrom,menu=on Requested changes: --- Original XML +++ New XML @@ -10,6 +10,8 @@ hvm /usr/lib/xen/boot/hvmloader + + + Change disk #7 to use cache=none for 'myguest': $ ./virt-xml --guest myguest --device 7 --disk cache=none Requested changes: --- Original XML +++ New XML @@ -74,6 +74,7 @@ + Change watchdog action for 'myguest': $ ./virt-xml --guest myguest --device 1 --watchdog action=pause Requested changes: --- Original XML +++ New XML @@ -220,7 +220,7 @@
    - + --boot, --disk, and --watchdog come straight from virt-install, see man virt-install for detailed docs of the option format. Those options shown are the only things wired up right now, but it's a straightforward task to wire up most of the relevant remaining virt-install opts. Also the tool doesn't actually apply the changes yet, but that is also a trivial addition. I think the interesting bit here is nailing down the scope of the tool and deciding on good CLI syntax. Not sure if we should do hotplug/hotunplug as a subcommand or just another option like: virt-xml ... --hotplug --disk /tmp/foo.img Also not really sure how to hotunplug using the --device syntax of the above examples: virt-xml ... --hotunplug --device 1 --disk We could make --device just an option to whatever device string the user gives virt-xml ... --hotunplug --disk id=1 We can easily allow different XML input methods like: virt-xml --guestxml file.xml ... or even batch processing virt-xml --guest * ... Maybe even have allow more intelligence about what guests we edit, say we want to set cache=none for all disk devices, not CDROM or floppy (this would take a bit of work to sort out). virt-xml --guest * --disk match,device=disk --disk cache=none Then there is also the question of extending the tool to also edit other XML like storage, network, interface, etc. Any recommendations appreciated: option syntax, future capabilities, or even a better name for the tool :) A quick word about why I think we should do this with a separate tool rather than virsh. For starters, I think the need for this functionality on the command line is clear by now, so it's just a question of where to implement it. Why not virsh? Text and command line processing in C is a serious pain compared to a higher level language like python. I don't think this is a controversial statement, in fact I think it's partly responsible for why the virsh XML building commands have typically been in a pretty sorry state. virsh could conceivably use the internal domain_conf API to make this task much easier, but it would still require a lot of command line options for every XML parameter. In contrast, virt-install already needs to do most of this command line processing, and virt-manager needs to do all the XML building, parsing, and editing. Since this code already lives in one place (virtinst), it's almost trivial for us to reuse it. Supporting a new XML property on the command line is a very simple task and will immediately benefit both virt-install and virt-xml. We also already have over 75% of the domain XML schema available via existing CLI options that are already documented :) Questions or comments appreciated! Thanks, Cole -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-virt-xml-initial-commit.patch Type: text/x-diff Size: 7964 bytes Desc: not available URL: From mprivozn at redhat.com Wed Apr 27 14:57:42 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Wed, 27 Apr 2011 16:57:42 +0200 Subject: [libvirt] [PATCH 0/4] Unify error messages Message-ID: <1303916266-31581-1-git-send-email-mprivozn@redhat.com> As libvirt error codes evolved over time, it was more unclear to know, which code should be use in what cases. This patch series tries to correct those places, so we don't say it is internal error, when in fact incorrect XML was given. Also some error messages were changed to give more hints. Michal Privoznik (4): Fix error messages codes when TypeFromString fails New error code VIR_ERR_XML_CONFIG Improve incorrect root element error messages Change XML parsing error codes when details are presented. include/libvirt/virterror.h | 1 + src/conf/cpu_conf.c | 13 ++-- src/conf/domain_conf.c | 165 +++++++++++++++++++----------------- src/conf/interface_conf.c | 56 ++++++------ src/conf/network_conf.c | 20 +++-- src/conf/node_device_conf.c | 10 ++- src/conf/nwfilter_conf.c | 16 ++-- src/conf/secret_conf.c | 14 ++-- src/conf/storage_conf.c | 66 ++++++++------- src/conf/storage_encryption_conf.c | 14 ++-- src/security/virt-aa-helper.c | 3 +- src/test/test_driver.c | 13 ++- src/util/virterror.c | 6 ++ src/util/xml.c | 2 +- 14 files changed, 218 insertions(+), 181 deletions(-) -- 1.7.4.4 From mprivozn at redhat.com Wed Apr 27 14:57:43 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Wed, 27 Apr 2011 16:57:43 +0200 Subject: [libvirt] [PATCH 1/4] Fix error messages codes when TypeFromString fails In-Reply-To: <1303916266-31581-1-git-send-email-mprivozn@redhat.com> References: <1303916266-31581-1-git-send-email-mprivozn@redhat.com> Message-ID: <1303916266-31581-2-git-send-email-mprivozn@redhat.com> --- src/conf/cpu_conf.c | 4 +- src/conf/domain_conf.c | 100 ++++++++++++++++++----------------- src/conf/interface_conf.c | 2 +- src/conf/network_conf.c | 2 +- src/conf/node_device_conf.c | 4 +- src/conf/nwfilter_conf.c | 6 +- src/conf/secret_conf.c | 2 +- src/conf/storage_conf.c | 2 +- src/conf/storage_encryption_conf.c | 4 +- 9 files changed, 64 insertions(+), 62 deletions(-) diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index ad49916..db8b4bb 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -156,7 +156,7 @@ virCPUDefParseXML(const xmlNodePtr node, VIR_FREE(match); if (def->match < 0) { - virCPUReportError(VIR_ERR_INTERNAL_ERROR, + virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Invalid match attribute for CPU specification")); goto error; } @@ -257,7 +257,7 @@ virCPUDefParseXML(const xmlNodePtr node, VIR_FREE(strpolicy); if (policy < 0) { - virCPUReportError(VIR_ERR_INTERNAL_ERROR, + virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Invalid CPU feature policy")); goto error; } diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 0e7aeb5..7fba385 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1634,7 +1634,7 @@ virDomainDeviceInfoParseXML(xmlNodePtr node, if (type) { if ((info->type = virDomainDeviceAddressTypeFromString(type)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown address type '%s'"), type); goto cleanup; } @@ -1841,7 +1841,7 @@ virDomainDiskDefParseXML(virCapsPtr caps, type = virXMLPropString(node, "type"); if (type) { if ((def->type = virDomainDiskTypeFromString(type)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown disk type '%s'"), type); goto error; } @@ -1874,7 +1874,7 @@ virDomainDiskDefParseXML(virCapsPtr caps, } def->protocol = virDomainDiskProtocolTypeFromString(protocol); if (def->protocol < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown protocol type '%s'"), protocol); goto error; @@ -1973,7 +1973,7 @@ virDomainDiskDefParseXML(virCapsPtr caps, device = virXMLPropString(node, "device"); if (device) { if ((def->device = virDomainDiskDeviceTypeFromString(device)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown disk device '%s'"), device); goto error; } @@ -2021,7 +2021,7 @@ virDomainDiskDefParseXML(virCapsPtr caps, if (bus) { if ((def->bus = virDomainDiskBusTypeFromString(bus)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown disk bus type '%s'"), bus); goto error; } @@ -2059,14 +2059,14 @@ virDomainDiskDefParseXML(virCapsPtr caps, if (cachetag && (def->cachemode = virDomainDiskCacheTypeFromString(cachetag)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown disk cache mode '%s'"), cachetag); goto error; } if (error_policy && (def->error_policy = virDomainDiskErrorPolicyTypeFromString(error_policy)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown disk error policy '%s'"), error_policy); goto error; } @@ -2074,7 +2074,7 @@ virDomainDiskDefParseXML(virCapsPtr caps, if (iotag) { if ((def->iomode = virDomainDiskIoTypeFromString(iotag)) < 0 || def->iomode == VIR_DOMAIN_DISK_IO_DEFAULT) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown disk io mode '%s'"), iotag); goto error; } @@ -2178,7 +2178,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, type = virXMLPropString(node, "type"); if (type) { if ((def->type = virDomainControllerTypeFromString(type)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unknown controller type '%s'"), type); goto error; } @@ -2196,7 +2196,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, model = virXMLPropString(node, "model"); if (model) { if ((def->model = virDomainControllerModelTypeFromString(model)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unknown model type '%s'"), model); goto error; } @@ -2286,7 +2286,7 @@ virDomainFSDefParseXML(xmlNodePtr node, type = virXMLPropString(node, "type"); if (type) { if ((def->type = virDomainFSTypeFromString(type)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown filesystem type '%s'"), type); goto error; } @@ -2297,7 +2297,7 @@ virDomainFSDefParseXML(xmlNodePtr node, accessmode = virXMLPropString(node, "accessmode"); if (accessmode) { if ((def->accessmode = virDomainFSAccessModeTypeFromString(accessmode)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown accessmode '%s'"), accessmode); goto error; } @@ -2549,7 +2549,7 @@ virDomainNetDefParseXML(virCapsPtr caps, type = virXMLPropString(node, "type"); if (type != NULL) { if ((int)(def->type = virDomainNetTypeFromString(type)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown interface type '%s'"), type); goto error; } @@ -2761,7 +2761,7 @@ virDomainNetDefParseXML(virCapsPtr caps, if (mode != NULL) { int m; if ((m = virDomainNetdevMacvtapTypeFromString(mode)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Unkown mode has been specified")); goto error; } @@ -2814,7 +2814,7 @@ virDomainNetDefParseXML(virCapsPtr caps, int name; if (((name = virDomainNetBackendTypeFromString(backend)) < 0) || (name == VIR_DOMAIN_NET_BACKEND_TYPE_DEFAULT)) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unknown interface " "has been specified"), backend); @@ -2826,7 +2826,7 @@ virDomainNetDefParseXML(virCapsPtr caps, int m; if (((m = virDomainNetVirtioTxModeTypeFromString(txmode)) < 0) || (m == VIR_DOMAIN_NET_VIRTIO_TX_MODE_DEFAULT)) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unknown interface " "has been specified"), txmode); @@ -2964,6 +2964,8 @@ virDomainChrDefParseTargetXML(virCapsPtr caps, if ((def->targetType = virDomainChrTargetTypeFromString(caps, def->deviceType, targetType)) < 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown type %s"), targetType); goto error; } @@ -3186,7 +3188,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW; else if ((def->data.tcp.protocol = virDomainChrTcpProtocolTypeFromString(protocol)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unknown protocol '%s'"), protocol); goto error; } @@ -3313,7 +3315,7 @@ virDomainChrDefParseXML(virCapsPtr caps, if (type == NULL) { def->source.type = VIR_DOMAIN_CHR_TYPE_PTY; } else if ((def->source.type = virDomainChrTypeFromString(type)) < 0) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown type presented to host for character device: %s"), type); goto error; @@ -3321,7 +3323,7 @@ virDomainChrDefParseXML(virCapsPtr caps, nodeName = (const char *) node->name; if ((def->deviceType = virDomainChrDeviceTypeFromString(nodeName)) < 0) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown character device type: %s"), nodeName); } @@ -3391,7 +3393,7 @@ virDomainSmartcardDefParseXML(xmlNodePtr node, goto error; } if ((def->type = virDomainSmartcardTypeFromString(mode)) < 0) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown smartcard device mode: %s"), mode); goto error; @@ -3453,7 +3455,7 @@ virDomainSmartcardDefParseXML(xmlNodePtr node, goto error; } if ((def->data.passthru.type = virDomainChrTypeFromString(type)) < 0) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown type presented to host for " "character device: %s"), type); goto error; @@ -3521,14 +3523,14 @@ virDomainInputDefParseXML(const char *ostype, } if ((def->type = virDomainInputTypeFromString(type)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown input device type '%s'"), type); goto error; } if (bus) { if ((def->bus = virDomainInputBusTypeFromString(bus)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown input bus type '%s'"), bus); goto error; } @@ -3618,7 +3620,7 @@ virDomainTimerDefParseXML(const xmlNodePtr node, goto error; } if ((def->name = virDomainTimerNameTypeFromString(name)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown timer name '%s'"), name); goto error; } @@ -3640,7 +3642,7 @@ virDomainTimerDefParseXML(const xmlNodePtr node, tickpolicy = virXMLPropString(node, "tickpolicy"); if (tickpolicy != NULL) { if ((def->tickpolicy = virDomainTimerTickpolicyTypeFromString(tickpolicy)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown timer tickpolicy '%s'"), tickpolicy); goto error; } @@ -3650,7 +3652,7 @@ virDomainTimerDefParseXML(const xmlNodePtr node, track = virXMLPropString(node, "track"); if (track != NULL) { if ((def->track = virDomainTimerTrackTypeFromString(track)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown timer track '%s'"), track); goto error; } @@ -3669,7 +3671,7 @@ virDomainTimerDefParseXML(const xmlNodePtr node, mode = virXMLPropString(node, "mode"); if (mode != NULL) { if ((def->mode = virDomainTimerModeTypeFromString(mode)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown timer mode '%s'"), mode); goto error; } @@ -3790,7 +3792,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { } if ((def->type = virDomainGraphicsTypeFromString(type)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown graphics device type '%s'"), type); goto error; } @@ -3979,7 +3981,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { } if ((nameval = virDomainGraphicsSpiceChannelNameTypeFromString(name)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown spice channel name %s"), name); VIR_FREE(name); @@ -3987,7 +3989,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { goto error; } if ((modeval = virDomainGraphicsSpiceChannelModeTypeFromString(mode)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown spice channel mode %s"), mode); VIR_FREE(name); @@ -4114,7 +4116,7 @@ virDomainSoundDefParseXML(const xmlNodePtr node, model = virXMLPropString(node, "model"); if ((def->model = virDomainSoundModelTypeFromString(model)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown sound model '%s'"), model); goto error; } @@ -4156,7 +4158,7 @@ virDomainWatchdogDefParseXML(const xmlNodePtr node, } def->model = virDomainWatchdogModelTypeFromString (model); if (def->model < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown watchdog model '%s'"), model); goto error; } @@ -4167,7 +4169,7 @@ virDomainWatchdogDefParseXML(const xmlNodePtr node, else { def->action = virDomainWatchdogActionTypeFromString (action); if (def->action < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown watchdog action '%s'"), action); goto error; } @@ -4208,7 +4210,7 @@ virDomainMemballoonDefParseXML(const xmlNodePtr node, goto error; } if ((def->model = virDomainMemballoonModelTypeFromString(model)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown memory balloon model '%s'"), model); goto error; } @@ -4252,7 +4254,7 @@ virSysinfoParseXML(const xmlNodePtr node, goto error; } if ((def->type = virDomainSysinfoTypeFromString(type)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown sysinfo type '%s'"), type); goto error; } @@ -4429,13 +4431,13 @@ virDomainVideoDefParseXML(const xmlNodePtr node, if (type) { if ((def->type = virDomainVideoTypeFromString(type)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown video model '%s'"), type); goto error; } } else { if ((def->type = virDomainVideoDefaultType(dom)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("missing video model and cannot determine default")); goto error; } @@ -4443,7 +4445,7 @@ virDomainVideoDefParseXML(const xmlNodePtr node, if (vram) { if (virStrToLong_ui(vram, NULL, 10, &def->vram) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("cannot parse video ram '%s'"), vram); goto error; } @@ -4453,7 +4455,7 @@ virDomainVideoDefParseXML(const xmlNodePtr node, if (heads) { if (virStrToLong_ui(heads, NULL, 10, &def->heads) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("cannot parse video heads '%s'"), heads); goto error; } @@ -4666,7 +4668,7 @@ virDomainHostdevDefParseXML(const xmlNodePtr node, mode = virXMLPropString(node, "mode"); if (mode) { if ((def->mode=virDomainHostdevModeTypeFromString(mode)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown hostdev mode '%s'"), mode); goto error; } @@ -4677,7 +4679,7 @@ virDomainHostdevDefParseXML(const xmlNodePtr node, type = virXMLPropString(node, "type"); if (type) { if ((def->source.subsys.type = virDomainHostdevSubsysTypeFromString(type)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown host device type '%s'"), type); goto error; } @@ -4796,7 +4798,7 @@ virSecurityLabelDefParseXML(const virDomainDefPtr def, def->seclabel.type = virDomainSeclabelTypeFromString(p); VIR_FREE(p); if (def->seclabel.type < 0) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("invalid security type")); goto error; } @@ -5206,7 +5208,7 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt, goto cleanup; } if ((val = virDomainBootTypeFromString(dev)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown boot device '%s'"), dev); VIR_FREE(dev); @@ -5341,7 +5343,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, } if ((def->virtType = virDomainVirtTypeFromString(tmp)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("invalid domain type %s"), tmp); goto error; } @@ -5515,7 +5517,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, for (i = 0 ; i < n ; i++) { int val = virDomainFeatureTypeFromString((const char *)nodes[i]->name); if (val < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unexpected feature %s"), nodes[i]->name); goto error; @@ -6177,7 +6179,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, int mode; if ((mode = virDomainSmbiosModeTypeFromString(tmp)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown smbios mode '%s'"), tmp); goto error; } @@ -6252,7 +6254,7 @@ static virDomainObjPtr virDomainObjParseXML(virCapsPtr caps, goto error; } if ((obj->state = virDomainStateTypeFromString(tmp)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("invalid domain state '%s'"), tmp); VIR_FREE(tmp); goto error; @@ -9070,7 +9072,7 @@ virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, } def->state = virDomainStateTypeFromString(state); if (def->state < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid state '%s' in domain snapshot XML"), state); goto cleanup; @@ -9421,7 +9423,7 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk, formatStr = "raw"; /* Xen compat */ if ((format = virStorageFileFormatTypeFromString(formatStr)) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown disk format '%s' for %s"), disk->driverType, disk->src); return -1; diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index 2fa2fa0..37b9c7c 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -682,7 +682,7 @@ virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType) { } type = virInterfaceTypeFromString(tmp); if (type == -1) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown interface type %s"), tmp); VIR_FREE(tmp); return(NULL); diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 5738757..7ab2352 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -671,7 +671,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) tmp = virXPathString("string(./forward[1]/@mode)", ctxt); if (tmp) { if ((def->forwardType = virNetworkForwardTypeFromString(tmp)) < 0) { - virNetworkReportError(VIR_ERR_INTERNAL_ERROR, + virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown forwarding type '%s'"), tmp); VIR_FREE(tmp); goto error; diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 0b080ce..cc28b2a 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -832,7 +832,7 @@ virNodeDevCapNetParseXML(xmlXPathContextPtr ctxt, int val = virNodeDevNetCapTypeFromString(tmp); VIR_FREE(tmp); if (val < 0) { - virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, + virNodeDeviceReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("invalid network type supplied for '%s'"), def->name); goto out; @@ -1082,7 +1082,7 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt, } if ((val = virNodeDevCapTypeFromString(tmp)) < 0) { - virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, + virNodeDeviceReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown capability type '%s'"), tmp); VIR_FREE(tmp); goto error; diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 09dc32b..368aca0 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -1890,7 +1890,7 @@ virNWFilterRuleParse(xmlNodePtr node) } if ((ret->action = virNWFilterRuleActionTypeFromString(action)) < 0) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, + virNWFilterReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unknown rule action attribute value")); goto err_exit; @@ -1904,7 +1904,7 @@ virNWFilterRuleParse(xmlNodePtr node) } if ((ret->tt = virNWFilterRuleDirectionTypeFromString(direction)) < 0) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, + virNWFilterReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unknown rule direction attribute value")); goto err_exit; @@ -2003,7 +2003,7 @@ virNWFilterDefParseXML(xmlXPathContextPtr ctxt) { if (chain) { if ((ret->chainsuffix = virNWFilterChainSuffixTypeFromString(chain)) < 0) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, + virNWFilterReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown chain suffix '%s'"), chain); goto cleanup; } diff --git a/src/conf/secret_conf.c b/src/conf/secret_conf.c index fc4ae82..30f1a3d 100644 --- a/src/conf/secret_conf.c +++ b/src/conf/secret_conf.c @@ -74,7 +74,7 @@ virSecretDefParseUsage(xmlXPathContextPtr ctxt, } type = virSecretUsageTypeTypeFromString(type_str); if (type < 0) { - virSecretReportError(VIR_ERR_XML_ERROR, + virSecretReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown secret usage type %s"), type_str); VIR_FREE(type_str); return -1; diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 116898d..9ccff15 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -630,7 +630,7 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) { type = virXPathString("string(./@type)", ctxt); if ((ret->type = virStoragePoolTypeFromString((const char *)type)) < 0) { - virStorageReportError(VIR_ERR_INTERNAL_ERROR, + virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown storage pool type %s"), (const char*)type); goto cleanup; } diff --git a/src/conf/storage_encryption_conf.c b/src/conf/storage_encryption_conf.c index 20e822c..4414817 100644 --- a/src/conf/storage_encryption_conf.c +++ b/src/conf/storage_encryption_conf.c @@ -94,7 +94,7 @@ virStorageEncryptionSecretParse(xmlXPathContextPtr ctxt, } type = virStorageEncryptionSecretTypeTypeFromString(type_str); if (type < 0) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown volume encryption secret type %s"), type_str); VIR_FREE(type_str); @@ -148,7 +148,7 @@ virStorageEncryptionParseXML(xmlXPathContextPtr ctxt) } format = virStorageEncryptionFormatTypeFromString(format_str); if (format < 0) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown volume encryption format type %s"), format_str); VIR_FREE(format_str); -- 1.7.4.4 From mprivozn at redhat.com Wed Apr 27 14:57:44 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Wed, 27 Apr 2011 16:57:44 +0200 Subject: [libvirt] [PATCH 2/4] New error code VIR_ERR_XML_CONFIG In-Reply-To: <1303916266-31581-1-git-send-email-mprivozn@redhat.com> References: <1303916266-31581-1-git-send-email-mprivozn@redhat.com> Message-ID: <1303916266-31581-3-git-send-email-mprivozn@redhat.com> Up to now developers didn't know which error code to use, when invalid attribute/element value was given (e.g. string when expecting integer), something was missing, etc. This patch creates a new error code for cases like that. --- include/libvirt/virterror.h | 1 + src/util/virterror.c | 6 ++++++ 2 files changed, 7 insertions(+), 0 deletions(-) diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 0708e02..2f160c9 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -231,6 +231,7 @@ typedef enum { VIR_ERR_INVALID_DOMAIN_SNAPSHOT = 71,/* invalid domain snapshot */ VIR_ERR_NO_DOMAIN_SNAPSHOT = 72, /* domain snapshot not found */ VIR_ERR_INVALID_STREAM = 73, /* stream pointer not valid */ + VIR_ERR_XML_CONFIG = 74, /* invalid or not well formed input XML*/ } virErrorNumber; /** diff --git a/src/util/virterror.c b/src/util/virterror.c index fbb4a45..f597e9b 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -1205,6 +1205,12 @@ virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("invalid stream pointer in %s"); break; + case VIR_ERR_XML_CONFIG: + if (info == NULL) + errmsg = _("XML parsing error: document not well formed or invalid"); + else + errmsg = _("XML parsing error: %s"); + break; } return (errmsg); } -- 1.7.4.4 From mprivozn at redhat.com Wed Apr 27 14:57:45 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Wed, 27 Apr 2011 16:57:45 +0200 Subject: [libvirt] [PATCH 3/4] Improve incorrect root element error messages In-Reply-To: <1303916266-31581-1-git-send-email-mprivozn@redhat.com> References: <1303916266-31581-1-git-send-email-mprivozn@redhat.com> Message-ID: <1303916266-31581-4-git-send-email-mprivozn@redhat.com> --- src/conf/cpu_conf.c | 7 ++++--- src/conf/domain_conf.c | 21 ++++++++++++++------- src/conf/interface_conf.c | 6 ++++-- src/conf/network_conf.c | 6 ++++-- src/conf/node_device_conf.c | 6 ++++-- src/conf/nwfilter_conf.c | 2 +- src/conf/secret_conf.c | 6 ++++-- src/conf/storage_conf.c | 12 ++++++++---- src/security/virt-aa-helper.c | 3 ++- src/test/test_driver.c | 13 ++++++++++--- src/util/xml.c | 2 +- 11 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index db8b4bb..9ea11cb 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -118,9 +118,10 @@ virCPUDefParseXML(const xmlNodePtr node, unsigned int i; if (!xmlStrEqual(node->name, BAD_CAST "cpu")) { - virCPUReportError(VIR_ERR_INTERNAL_ERROR, - "%s", - _("XML does not contain expected 'cpu' element")); + virCPUReportError(VIR_ERR_XML_CONFIG, + _("unexpected root element <%s> " + "expecting to see "), + node->name); return NULL; } diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 7fba385..ac3d955 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4867,7 +4867,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps, node = xmlDocGetRootElement(xml); if (node == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("missing root element")); goto error; } @@ -6322,8 +6322,10 @@ virDomainDefPtr virDomainDefParseNode(virCapsPtr caps, virDomainDefPtr def = NULL; if (!xmlStrEqual(root->name, BAD_CAST "domain")) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("incorrect root element")); + virDomainReportError(VIR_ERR_XML_CONFIG, + _("unexpected root element <%s>, " + "expecting to see "), + root->name); goto cleanup; } @@ -6351,8 +6353,10 @@ virDomainObjParseNode(virCapsPtr caps, virDomainObjPtr obj = NULL; if (!xmlStrEqual(root->name, BAD_CAST "domstatus")) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("incorrect root element")); + virDomainReportError(VIR_ERR_XML_CONFIG, + _("unexpected root element <%s>, " + "expecting to see "), + root->name); goto cleanup; } @@ -9015,13 +9019,16 @@ virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, } if ((root = xmlDocGetRootElement(xml)) == NULL) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("missing root element")); goto cleanup; } if (!xmlStrEqual(root->name, BAD_CAST "domainsnapshot")) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", _("domainsnapshot")); + virDomainReportError(VIR_ERR_XML_CONFIG, + _("unexpected root element <%s> " + "expecting to see "), + root->name); goto cleanup; } diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index 37b9c7c..c07ffc8 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -831,8 +831,10 @@ virInterfaceDefPtr virInterfaceDefParseNode(xmlDocPtr xml, virInterfaceDefPtr def = NULL; if (!xmlStrEqual(root->name, BAD_CAST "interface")) { - virInterfaceReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("incorrect root element")); + virInterfaceReportError(VIR_ERR_XML_CONFIG, + _("unexpected root element <%s>, " + "expecting to see "), + root->name); return NULL; } diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 7ab2352..88848ee 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -728,8 +728,10 @@ virNetworkDefPtr virNetworkDefParseNode(xmlDocPtr xml, virNetworkDefPtr def = NULL; if (!xmlStrEqual(root->name, BAD_CAST "network")) { - virNetworkReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("incorrect root element")); + virNetworkReportError(VIR_ERR_XML_CONFIG, + _("unexpected root element <%s>, " + "expecting to see "), + root->name); return NULL; } diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index cc28b2a..8e7c573 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -1205,8 +1205,10 @@ virNodeDeviceDefParseNode(xmlDocPtr xml, virNodeDeviceDefPtr def = NULL; if (!xmlStrEqual(root->name, BAD_CAST "device")) { - virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("incorrect root element")); + virNodeDeviceReportError(VIR_ERR_XML_CONFIG, + _("unexpected root element <%s>, " + "expecting to see "), + root->name); return NULL; } diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 368aca0..0aee8a4 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -2152,7 +2152,7 @@ virNWFilterDefParse(virConnectPtr conn, node = xmlDocGetRootElement(xml); if (node == NULL) { - virNWFilterReportError(VIR_ERR_XML_ERROR, + virNWFilterReportError(VIR_ERR_XML_CONFIG, "%s", _("missing root element")); goto cleanup; } diff --git a/src/conf/secret_conf.c b/src/conf/secret_conf.c index 30f1a3d..37a513b 100644 --- a/src/conf/secret_conf.c +++ b/src/conf/secret_conf.c @@ -112,8 +112,10 @@ secretXMLParseNode(xmlDocPtr xml, xmlNodePtr root) char *uuidstr = NULL; if (!xmlStrEqual(root->name, BAD_CAST "secret")) { - virSecretReportError(VIR_ERR_XML_ERROR, "%s", - _("incorrect root element")); + virSecretReportError(VIR_ERR_XML_CONFIG, + _("unexpected root element <%s>, " + "expecting to see "), + root->name); goto cleanup; } diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 9ccff15..76ea103 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -750,8 +750,10 @@ virStoragePoolDefParseNode(xmlDocPtr xml, virStoragePoolDefPtr def = NULL; if (STRNEQ((const char *)root->name, "pool")) { - virStorageReportError(VIR_ERR_XML_ERROR, - "%s", _("unknown root element for storage pool")); + virStorageReportError(VIR_ERR_XML_CONFIG, + _("unexpected root element <%s> " + "expecting to see "), + root->name); goto cleanup; } @@ -1130,8 +1132,10 @@ virStorageVolDefParseNode(virStoragePoolDefPtr pool, virStorageVolDefPtr def = NULL; if (STRNEQ((const char *)root->name, "volume")) { - virStorageReportError(VIR_ERR_XML_ERROR, - "%s", _("unknown root element for storage vol")); + virStorageReportError(VIR_ERR_XML_CONFIG, + _("unexpected root element <%s> " + "expecting to see "), + root->name); goto cleanup; } diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 08ff53c..0b24516 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -684,7 +684,8 @@ caps_mockup(vahControl * ctl, const char *xmlStr) } if (!xmlStrEqual(root->name, BAD_CAST "domain")) { - vah_error(NULL, 0, _("incorrect root element")); + vah_error(NULL, 0, _("unexpected root element <%s>, expecting to see " + ""), root->name)); goto cleanup; } diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 0978214..6a6f189 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -798,9 +798,16 @@ static int testOpenFromFile(virConnectPtr conn, VIR_FORCE_CLOSE(fd); root = xmlDocGetRootElement(xml); - if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "node"))) { - testError(VIR_ERR_XML_ERROR, "%s", - _("Root element is not 'node'")); + if (root == NULL) { + testError(VIR_ERR_XML_CONFIG, "%s", + _("missing root element")); + goto error; + } + if (!xmlStrEqual(root->name, BAD_CAST "node")) { + testError(VIR_ERR_XML_CONFIG, + _("unexpected root element <%s> " + "expecting to see "), + root->name); goto error; } diff --git a/src/util/xml.c b/src/util/xml.c index d2989e2..2ad21cd 100644 --- a/src/util/xml.c +++ b/src/util/xml.c @@ -696,7 +696,7 @@ virXMLParseHelper(int domcode, goto error; if (xmlDocGetRootElement(xml) == NULL) { - virGenericReportError(domcode, VIR_ERR_INTERNAL_ERROR, + virGenericReportError(domcode, VIR_ERR_XML_CONFIG, "%s", _("missing root element")); goto error; } -- 1.7.4.4 From mprivozn at redhat.com Wed Apr 27 14:57:46 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Wed, 27 Apr 2011 16:57:46 +0200 Subject: [libvirt] [PATCH 4/4] Change XML parsing error codes when details are presented. In-Reply-To: <1303916266-31581-1-git-send-email-mprivozn@redhat.com> References: <1303916266-31581-1-git-send-email-mprivozn@redhat.com> Message-ID: <1303916266-31581-5-git-send-email-mprivozn@redhat.com> Error messages which contain any additional info should be using VIR_ERR_XML_CONFIG instead of VIR_ERR_XML_ERROR. --- src/conf/cpu_conf.c | 2 +- src/conf/domain_conf.c | 44 +++++++++++++++--------------- src/conf/interface_conf.c | 48 ++++++++++++++++---------------- src/conf/network_conf.c | 12 ++++---- src/conf/nwfilter_conf.c | 8 +++--- src/conf/secret_conf.c | 6 ++-- src/conf/storage_conf.c | 52 ++++++++++++++++++------------------ src/conf/storage_encryption_conf.c | 10 +++--- 8 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index 9ea11cb..b18c2c4 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -133,7 +133,7 @@ virCPUDefParseXML(const xmlNodePtr node, if (mode == VIR_CPU_TYPE_AUTO) { if (virXPathBoolean("boolean(./arch)", ctxt)) { if (virXPathBoolean("boolean(./@match)", ctxt)) { - virCPUReportError(VIR_ERR_XML_ERROR, "%s", + virCPUReportError(VIR_ERR_XML_CONFIG, "%s", _("'arch' element element cannot be used inside 'cpu'" " element with 'match' attribute'")); goto error; diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index ac3d955..66cd07d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2855,7 +2855,7 @@ virDomainNetDefParseXML(virCapsPtr caps, if (ret >= 0) { def->tune.sndbuf_specified = true; } else if (ret == -2) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("sndbuf must be a positive integer")); goto error; } @@ -2895,7 +2895,7 @@ virDomainChrDefaultTargetType(virCapsPtr caps, int devtype) { switch (devtype) { case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL: - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, _("target type must be specified for %s device"), virDomainChrDeviceTypeToString(devtype)); break; @@ -2977,7 +2977,7 @@ virDomainChrDefParseTargetXML(virCapsPtr caps, portStr = virXMLPropString(cur, "port"); if (addrStr == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("guestfwd channel does not " "define a target address")); goto error; @@ -2999,14 +2999,14 @@ virDomainChrDefParseTargetXML(virCapsPtr caps, } if (portStr == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("guestfwd channel does " "not define a target port")); goto error; } if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, _("Invalid port number: %s"), portStr); goto error; @@ -3030,7 +3030,7 @@ virDomainChrDefParseTargetXML(virCapsPtr caps, } if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, _("Invalid port number: %s"), portStr); goto error; @@ -3388,7 +3388,7 @@ virDomainSmartcardDefParseXML(xmlNodePtr node, mode = virXMLPropString(node, "mode"); if (mode == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("missing smartcard device mode")); goto error; } @@ -3410,7 +3410,7 @@ virDomainSmartcardDefParseXML(xmlNodePtr node, if (cur->type == XML_ELEMENT_NODE && xmlStrEqual(cur->name, BAD_CAST "certificate")) { if (i == 3) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("host-certificates mode needs " "exactly three certificates")); goto error; @@ -3430,7 +3430,7 @@ virDomainSmartcardDefParseXML(xmlNodePtr node, goto error; } if (*def->data.cert.database != '/') { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, _("expecting absolute path: %s"), def->data.cert.database); goto error; @@ -3439,7 +3439,7 @@ virDomainSmartcardDefParseXML(xmlNodePtr node, cur = cur->next; } if (i < 3) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("host-certificates mode needs " "exactly three certificates")); goto error; @@ -3449,7 +3449,7 @@ virDomainSmartcardDefParseXML(xmlNodePtr node, case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH: type = virXMLPropString(node, "type"); if (type == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("passthrough mode requires a character " "device type attribute")); goto error; @@ -4237,7 +4237,7 @@ virSysinfoParseXML(const xmlNodePtr node, char *type; if (!xmlStrEqual(node->name, BAD_CAST "sysinfo")) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("XML does not contain expected 'sysinfo' element")); return(NULL); } @@ -4791,7 +4791,7 @@ virSecurityLabelDefParseXML(const virDomainDefPtr def, p = virXPathStringLimit("string(./seclabel/@type)", VIR_SECURITY_LABEL_BUFLEN-1, ctxt); if (p == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("missing security type")); goto error; } @@ -4811,7 +4811,7 @@ virSecurityLabelDefParseXML(const virDomainDefPtr def, p = virXPathStringLimit("string(./seclabel/@model)", VIR_SECURITY_MODEL_BUFLEN-1, ctxt); if (p == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("missing security model")); goto error; } @@ -4820,7 +4820,7 @@ virSecurityLabelDefParseXML(const virDomainDefPtr def, p = virXPathStringLimit("string(./seclabel/label[1])", VIR_SECURITY_LABEL_BUFLEN-1, ctxt); if (p == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("security label is missing")); goto error; } @@ -4834,7 +4834,7 @@ virSecurityLabelDefParseXML(const virDomainDefPtr def, p = virXPathStringLimit("string(./seclabel/imagelabel[1])", VIR_SECURITY_LABEL_BUFLEN-1, ctxt); if (p == NULL) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("security imagelabel is missing")); goto error; } @@ -4929,7 +4929,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps, if (!(dev->data.graphics = virDomainGraphicsDefParseXML(node, flags))) goto error; } else { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("unknown device type")); goto error; } @@ -5418,7 +5418,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, n = virXPathULong("string(./vcpu[1])", ctxt, &count); if (n == -2) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("maximum vcpus must be an integer")); goto error; } else if (n < 0) { @@ -5426,7 +5426,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, } else { def->maxvcpus = count; if (count == 0) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, _("invalid maxvcpus %lu"), count); goto error; } @@ -5434,7 +5434,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, n = virXPathULong("string(./vcpu[1]/@current)", ctxt, &count); if (n == -2) { - virDomainReportError(VIR_ERR_XML_ERROR, "%s", + virDomainReportError(VIR_ERR_XML_CONFIG, "%s", _("current vcpus must be an integer")); goto error; } else if (n < 0) { @@ -5442,7 +5442,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, } else { def->vcpus = count; if (count == 0) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, _("invalid current vcpus %lu"), count); goto error; } @@ -9013,7 +9013,7 @@ virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, xml = virXMLParse(NULL, xmlStr, "domainsnapshot.xml"); if (!xml) { - virDomainReportError(VIR_ERR_XML_ERROR, + virDomainReportError(VIR_ERR_XML_CONFIG, "%s",_("failed to parse snapshot xml document")); return NULL; } diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index c07ffc8..6f20843 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -122,7 +122,7 @@ virInterfaceDefParseName(virInterfaceDefPtr def, tmp = virXPathString("string(./@name)", ctxt); if (tmp == NULL) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("interface has no name")); return(-1); } @@ -138,7 +138,7 @@ virInterfaceDefParseMtu(virInterfaceDefPtr def, ret = virXPathULong("string(./mtu/@size)", ctxt, &mtu); if ((ret == -2) || ((ret == 0) && (mtu > 100000))) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("interface mtu value is improper")); return(-1); } else if (ret == 0) { @@ -162,7 +162,7 @@ virInterfaceDefParseStartMode(virInterfaceDefPtr def, else if (STREQ(tmp, "none")) def->startmode = VIR_INTERFACE_START_NONE; else { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, _("unknown interface startmode %s"), tmp); VIR_FREE(tmp); return(-1); @@ -194,7 +194,7 @@ virInterfaceDefParseBondMode(xmlXPathContextPtr ctxt) { else if (STREQ(tmp, "balance-alb")) ret = VIR_INTERFACE_BOND_BALALB; else { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, _("unknown bonding mode %s"), tmp); ret = -1; } @@ -215,7 +215,7 @@ virInterfaceDefParseBondMiiCarrier(xmlXPathContextPtr ctxt) { else if (STREQ(tmp, "netif")) ret = VIR_INTERFACE_BOND_MII_NETIF; else { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, _("unknown mii bonding carrier %s"), tmp); ret = -1; } @@ -238,7 +238,7 @@ virInterfaceDefParseBondArpValid(xmlXPathContextPtr ctxt) { else if (STREQ(tmp, "all")) ret = VIR_INTERFACE_BOND_ARP_ALL; else { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, _("unknown arp bonding validate %s"), tmp); ret = -1; } @@ -264,7 +264,7 @@ virInterfaceDefParseDhcp(virInterfaceProtocolDefPtr def, else if (STREQ(tmp, "no")) def->peerdns = 0; else { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, _("unknown dhcp peerdns value %s"), tmp); ret = -1; } @@ -290,7 +290,7 @@ virInterfaceDefParseIp(virInterfaceIpDefPtr def, if (ret == 0) def->prefix = (int) l; else if (ret == -2) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("Invalid ip address prefix value")); return(-1); } @@ -447,7 +447,7 @@ virInterfaceDefParseIfAdressing(virInterfaceDefPtr def, ctxt->node = protoNodes[pp]; tmp = virXPathString("string(./@family)", ctxt); if (tmp == NULL) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("protocol misses the family attribute")); virInterfaceProtocolDefFree(proto); goto error; @@ -466,7 +466,7 @@ virInterfaceDefParseIfAdressing(virInterfaceDefPtr def, goto error; } } else { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, _("unsupported protocol family '%s'"), tmp); virInterfaceProtocolDefFree(proto); goto error; @@ -537,7 +537,7 @@ virInterfaceDefParseBondItfs(virInterfaceDefPtr def, nbItf = virXPathNodeSet("./interface", ctxt, &interfaces); if (nbItf <= 0) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("bond has no interfaces")); ret = -1; goto error; @@ -585,7 +585,7 @@ virInterfaceDefParseBond(virInterfaceDefPtr def, ret = virXPathULong("string(./miimon/@freq)", ctxt, &tmp); if ((ret == -2) || (ret == -1)) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("bond interface miimon freq missing or invalid")); goto error; } @@ -593,7 +593,7 @@ virInterfaceDefParseBond(virInterfaceDefPtr def, ret = virXPathULong("string(./miimon/@downdelay)", ctxt, &tmp); if (ret == -2) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("bond interface miimon downdelay invalid")); goto error; } else if (ret == 0) { @@ -602,7 +602,7 @@ virInterfaceDefParseBond(virInterfaceDefPtr def, ret = virXPathULong("string(./miimon/@updelay)", ctxt, &tmp); if (ret == -2) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("bond interface miimon updelay invalid")); goto error; } else if (ret == 0) { @@ -621,7 +621,7 @@ virInterfaceDefParseBond(virInterfaceDefPtr def, ret = virXPathULong("string(./arpmon/@interval)", ctxt, &tmp); if ((ret == -2) || (ret == -1)) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("bond interface arpmon interval missing or invalid")); goto error; } @@ -630,7 +630,7 @@ virInterfaceDefParseBond(virInterfaceDefPtr def, def->data.bond.target = virXPathString("string(./arpmon/@target)", ctxt); if (def->data.bond.target == NULL) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("bond interface arpmon target missing")); ret = -1; goto error; @@ -651,7 +651,7 @@ virInterfaceDefParseVlan(virInterfaceDefPtr def, xmlXPathContextPtr ctxt) { def->data.vlan.tag = virXPathString("string(./@tag)", ctxt); if (def->data.vlan.tag == NULL) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("vlan interface misses the tag attribute")); return(-1); } @@ -659,7 +659,7 @@ virInterfaceDefParseVlan(virInterfaceDefPtr def, def->data.vlan.devname = virXPathString("string(./interface/@name)", ctxt); if (def->data.vlan.devname == NULL) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("vlan interface misses name attribute")); return(-1); } @@ -676,7 +676,7 @@ virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType) { /* check @type */ tmp = virXPathString("string(./@type)", ctxt); if (tmp == NULL) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("interface misses the type attribute")); return(NULL); } @@ -703,7 +703,7 @@ virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType) { || (parentIfType == VIR_INTERFACE_TYPE_ETHERNET) || (parentIfType == VIR_INTERFACE_TYPE_VLAN)) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("interface has unsupported type '%s'"), virInterfaceTypeToString(type)); goto error; @@ -740,7 +740,7 @@ virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType) { bridge = virXPathNode("./bridge[1]", ctxt); if (bridge == NULL) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("bridge interface misses the bridge element")); goto error; } @@ -752,7 +752,7 @@ virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType) { } else if (STREQ(tmp, "off")) { def->data.bridge.stp = 0; } else { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, _("bridge interface stp should be on or off got %s"), tmp); VIR_FREE(tmp); @@ -782,7 +782,7 @@ virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType) { bond = virXPathNode("./bond[1]", ctxt); if (bond == NULL) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("bond interface misses the bond element")); goto error; } @@ -803,7 +803,7 @@ virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType) { goto error; vlan = virXPathNode("./vlan[1]", ctxt); if (vlan == NULL) { - virInterfaceReportError(VIR_ERR_XML_ERROR, + virInterfaceReportError(VIR_ERR_XML_CONFIG, "%s", _("vlan interface misses the vlan element")); goto error; } diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 88848ee..41c545e 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -333,7 +333,7 @@ virNetworkDHCPRangeDefParseXML(const char *networkName, range = virSocketGetRange(&saddr, &eaddr); if (range < 0) { - virNetworkReportError(VIR_ERR_XML_ERROR, + virNetworkReportError(VIR_ERR_XML_CONFIG, _("Invalid dhcp range '%s' to '%s' in network '%s'"), start, end, networkName); VIR_FREE(start); @@ -375,7 +375,7 @@ virNetworkDHCPRangeDefParseXML(const char *networkName, * You need at least one MAC address or one host name */ if ((mac == NULL) && (name == NULL)) { - virNetworkReportError(VIR_ERR_XML_ERROR, + virNetworkReportError(VIR_ERR_XML_CONFIG, _("Static host definition in network '%s' must have mac or name attribute"), networkName); return -1; @@ -383,7 +383,7 @@ virNetworkDHCPRangeDefParseXML(const char *networkName, ip = virXMLPropString(cur, "ip"); if ((ip == NULL) || (virSocketParseAddr(ip, &inaddr, AF_UNSPEC) < 0)) { - virNetworkReportError(VIR_ERR_XML_ERROR, + virNetworkReportError(VIR_ERR_XML_CONFIG, _("Missing IP address in static host definition for network '%s'"), networkName); VIR_FREE(ip); @@ -465,7 +465,7 @@ virNetworkIPParseXML(const char *networkName, if (address) { if (virSocketParseAddr(address, &def->address, AF_UNSPEC) < 0) { - virNetworkReportError(VIR_ERR_XML_ERROR, + virNetworkReportError(VIR_ERR_XML_CONFIG, _("Bad address '%s' in definition of network '%s'"), address, networkName); goto error; @@ -497,7 +497,7 @@ virNetworkIPParseXML(const char *networkName, goto error; } } else { - virNetworkReportError(VIR_ERR_XML_ERROR, + virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unrecognized family '%s' in definition of network '%s'"), def->family, networkName); goto error; @@ -631,7 +631,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) tmp = virXPathString("string(./mac[1]/@address)", ctxt); if (tmp) { if (virParseMacAddr(tmp, def->mac) < 0) { - virNetworkReportError(VIR_ERR_XML_ERROR, + virNetworkReportError(VIR_ERR_XML_CONFIG, _("Invalid bridge mac address '%s' in network '%s'"), tmp, def->name); VIR_FREE(tmp); diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 0aee8a4..62812b3 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -2018,7 +2018,7 @@ virNWFilterDefParseXML(xmlXPathContextPtr ctxt) { } } else { if (virUUIDParse(uuid, ret->uuid) < 0) { - virNWFilterReportError(VIR_ERR_XML_ERROR, + virNWFilterReportError(VIR_ERR_XML_CONFIG, "%s", _("malformed uuid element")); goto cleanup; } @@ -2094,7 +2094,7 @@ virNWFilterDefParseNode(xmlDocPtr xml, virNWFilterDefPtr def = NULL; if (STRNEQ((const char *)root->name, "filter")) { - virNWFilterReportError(VIR_ERR_XML_ERROR, + virNWFilterReportError(VIR_ERR_XML_CONFIG, "%s", _("unknown root element for nw filter")); goto cleanup; @@ -2145,7 +2145,7 @@ virNWFilterDefParse(virConnectPtr conn, if (!xml) { if (conn && conn->err.code == VIR_ERR_NONE) - virNWFilterReportError(VIR_ERR_XML_ERROR, + virNWFilterReportError(VIR_ERR_XML_CONFIG, "%s",_("failed to parse xml document")); goto cleanup; } @@ -2537,7 +2537,7 @@ virNWFilterObjLoad(virConnectPtr conn, } if (!virFileMatchesNameSuffix(file, def->name, ".xml")) { - virNWFilterReportError(VIR_ERR_XML_ERROR, + virNWFilterReportError(VIR_ERR_XML_CONFIG, _("network filter config filename '%s' does not match name '%s'"), path, def->name); virNWFilterDefFree(def); diff --git a/src/conf/secret_conf.c b/src/conf/secret_conf.c index 37a513b..ffc5a76 100644 --- a/src/conf/secret_conf.c +++ b/src/conf/secret_conf.c @@ -68,7 +68,7 @@ virSecretDefParseUsage(xmlXPathContextPtr ctxt, type_str = virXPathString("string(./usage/@type)", ctxt); if (type_str == NULL) { - virSecretReportError(VIR_ERR_XML_ERROR, "%s", + virSecretReportError(VIR_ERR_XML_CONFIG, "%s", _("unknown secret usage type")); return -1; } @@ -138,7 +138,7 @@ secretXMLParseNode(xmlDocPtr xml, xmlNodePtr root) else if (STREQ(prop, "no")) def->ephemeral = 0; else { - virSecretReportError(VIR_ERR_XML_ERROR, "%s", + virSecretReportError(VIR_ERR_XML_CONFIG, "%s", _("invalid value of 'ephemeral'")); goto cleanup; } @@ -152,7 +152,7 @@ secretXMLParseNode(xmlDocPtr xml, xmlNodePtr root) else if (STREQ(prop, "no")) def->private = 0; else { - virSecretReportError(VIR_ERR_XML_ERROR, "%s", + virSecretReportError(VIR_ERR_XML_CONFIG, "%s", _("invalid value of 'private'")); goto cleanup; } diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 76ea103..79527ec 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -371,14 +371,14 @@ virStoragePoolDefParseAuthChap(xmlXPathContextPtr ctxt, virStoragePoolAuthChapPtr auth) { auth->login = virXPathString("string(./auth/@login)", ctxt); if (auth->login == NULL) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("missing auth host attribute")); return -1; } auth->passwd = virXPathString("string(./auth/@passwd)", ctxt); if (auth->passwd == NULL) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("missing auth passwd attribute")); return -1; } @@ -415,7 +415,7 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, source->format = options->formatFromString(format); if (source->format < 0) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown pool format type %s"), format); VIR_FREE(format); goto cleanup; @@ -427,7 +427,7 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, port = virXPathString("string(./host/@port)", ctxt); if (port) { if (virStrToLong_i(port, NULL, 10, &source->host.port) < 0) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, _("Invalid port number: %s"), port); goto cleanup; @@ -449,7 +449,7 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, char *path = virXMLPropString(nodeset[i], "path"); if (path == NULL) { VIR_FREE(nodeset); - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("missing storage pool source device path")); goto cleanup; } @@ -468,7 +468,7 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, if (STREQ(authType, "chap")) { source->authType = VIR_STORAGE_POOL_AUTH_CHAP; } else { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown auth type '%s'"), (const char *)authType); goto cleanup; @@ -507,7 +507,7 @@ virStoragePoolDefParseSourceString(const char *srcSpec, XML_PARSE_NOERROR | XML_PARSE_NOWARNING); if (doc == NULL) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("bad spec")); goto cleanup; } @@ -525,7 +525,7 @@ virStoragePoolDefParseSourceString(const char *srcSpec, node = virXPathNode("/source", xpath_ctxt); if (!node) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("root element was not source")); goto cleanup; } @@ -576,7 +576,7 @@ virStorageDefParsePerms(xmlXPathContextPtr ctxt, perms->mode = strtol(mode, &end, 8); if (*end || perms->mode < 0 || perms->mode > 0777) { VIR_FREE(mode); - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("malformed octal mode")); goto error; } @@ -587,7 +587,7 @@ virStorageDefParsePerms(xmlXPathContextPtr ctxt, perms->uid = -1; } else { if (virXPathLong("number(./owner)", ctxt, &v) < 0) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("malformed owner element")); goto error; } @@ -598,7 +598,7 @@ virStorageDefParsePerms(xmlXPathContextPtr ctxt, perms->gid = -1; } else { if (virXPathLong("number(./group)", ctxt, &v) < 0) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("malformed group element")); goto error; } @@ -654,7 +654,7 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) { options->flags & VIR_STORAGE_POOL_SOURCE_NAME) ret->name = ret->source.name; if (ret->name == NULL) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("missing pool source name element")); goto cleanup; } @@ -668,7 +668,7 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) { } } else { if (virUUIDParse(uuid, ret->uuid) < 0) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("malformed uuid element")); goto cleanup; } @@ -677,7 +677,7 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) { if (options->flags & VIR_STORAGE_POOL_SOURCE_HOST) { if (!ret->source.host.name) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("missing storage pool source host name")); goto cleanup; @@ -686,7 +686,7 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) { if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR) { if (!ret->source.dir) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("missing storage pool source path")); goto cleanup; } @@ -704,7 +704,7 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) { if (options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) { if (!ret->source.adapter) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("missing storage pool source adapter name")); goto cleanup; } @@ -713,14 +713,14 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) { /* If DEVICE is the only source type, then its required */ if (options->flags == VIR_STORAGE_POOL_SOURCE_DEVICE) { if (!ret->source.ndevice) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("missing storage pool source device name")); goto cleanup; } } if ((tmppath = virXPathString("string(./target/path)", ctxt)) == NULL) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("missing storage pool target path")); goto cleanup; } @@ -988,19 +988,19 @@ virStorageSize(const char *unit, break; default: - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, _("unknown size units '%s'"), unit); return -1; } } if (virStrToLong_ull (val, &end, 10, ret) < 0) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("malformed capacity element")); return -1; } if (*ret > (ULLONG_MAX / mult)) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("capacity element value too large")); return -1; } @@ -1031,7 +1031,7 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool, ret->name = virXPathString("string(./name)", ctxt); if (ret->name == NULL) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("missing volume name element")); goto cleanup; } @@ -1042,7 +1042,7 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool, capacity = virXPathString("string(./capacity)", ctxt); unit = virXPathString("string(./capacity/@unit)", ctxt); if (capacity == NULL) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("missing capacity element")); goto cleanup; } @@ -1071,7 +1071,7 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool, ret->target.format = (options->formatFromString)(format); if (ret->target.format < 0) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown volume format type %s"), format); VIR_FREE(format); goto cleanup; @@ -1102,7 +1102,7 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool, ret->backingStore.format = (options->formatFromString)(format); if (ret->backingStore.format < 0) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown volume format type %s"), format); VIR_FREE(format); goto cleanup; @@ -1427,7 +1427,7 @@ virStoragePoolObjLoad(virStoragePoolObjListPtr pools, } if (!virFileMatchesNameSuffix(file, def->name, ".xml")) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, _("Storage pool config filename '%s' does not match pool name '%s'"), path, def->name); virStoragePoolDefFree(def); diff --git a/src/conf/storage_encryption_conf.c b/src/conf/storage_encryption_conf.c index 4414817..dcc16dd 100644 --- a/src/conf/storage_encryption_conf.c +++ b/src/conf/storage_encryption_conf.c @@ -88,7 +88,7 @@ virStorageEncryptionSecretParse(xmlXPathContextPtr ctxt, type_str = virXPathString("string(./@type)", ctxt); if (type_str == NULL) { - virStorageReportError(VIR_ERR_XML_ERROR, "%s", + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("unknown volume encryption secret type")); goto cleanup; } @@ -106,14 +106,14 @@ virStorageEncryptionSecretParse(xmlXPathContextPtr ctxt, uuidstr = virXPathString("string(./@uuid)", ctxt); if (uuidstr) { if (virUUIDParse(uuidstr, ret->uuid) < 0) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, _("malformed volume encryption uuid '%s'"), uuidstr); goto cleanup; } VIR_FREE(uuidstr); } else { - virStorageReportError(VIR_ERR_XML_ERROR, "%s", + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("missing volume encryption uuid")); goto cleanup; } @@ -142,7 +142,7 @@ virStorageEncryptionParseXML(xmlXPathContextPtr ctxt) format_str = virXPathString("string(./@format)", ctxt); if (format_str == NULL) { - virStorageReportError(VIR_ERR_XML_ERROR, "%s", + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("unknown volume encryption format")); goto cleanup; } @@ -190,7 +190,7 @@ virStorageEncryptionParseNode(xmlDocPtr xml, xmlNodePtr root) virStorageEncryptionPtr enc = NULL; if (STRNEQ((const char *) root->name, "encryption")) { - virStorageReportError(VIR_ERR_XML_ERROR, + virStorageReportError(VIR_ERR_XML_CONFIG, "%s", _("unknown root element for volume " "encryption information")); goto cleanup; -- 1.7.4.4 From laine at laine.org Wed Apr 27 15:08:46 2011 From: laine at laine.org (Laine Stump) Date: Wed, 27 Apr 2011 11:08:46 -0400 Subject: [libvirt] [PATCH v2 1/5] Network: Add TXT record support for virtual DNS service In-Reply-To: <1301654756-3920-2-git-send-email-minovotn@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> <1301654756-3920-2-git-send-email-minovotn@redhat.com> Message-ID: <4DB8317E.4010206@laine.org> Sorry for the long delay in responding to these patches. Unfortunately, they will no longer apply with "git am", so it's difficult to look at them "in-tree", but I think they need some revision anyway :-) On 04/01/2011 06:45 AM, Michal Novotny wrote: > Make: passed > Make check: passed > Make syntax-check: passed > > Hi, > this is the patch to add support for adding TXT records to the > DNS service running on the virtual network. This has been tested > on Fedora-14 i386 box and tests are also added to RelaxNG schema > and test XML files. Since this comment will appear in the commit logs for all posterity, the information about passing make check etc shouldn't really be here (that should be implied by the fact that it's committed! :-) Also, the "this is the patch" part and telling the exact setup of the testing are things useful for annotations in the email, but not when pushing the patch, so are more appropriate for the 0/5 email. Conversely, in your 0/5 introduction, you gave an example of the new XML - that would be useful in this commit comment so that someone could easily search the git log to learn when support was added for this feature. > Since spaces are not allowed for the TXT records in DNS they > are rejected > and "TXT records in DNS doesn't support spaces" > error message is being output to the user. You don't really need to say the exact log message in the commit comment > It's been tested and checked/syntax-checked and everything was > working fine. Again, the sentence above should be in the introductory email, but is superfluous here. > Also, the formatnetwork HTML document has been altered to > include those information about new DNS tag. "Also the network XML documentation has been updated to describe the new element." > Michal Again, signature not needed in a commit comment - it's implied in the email address. > Signed-off-by: Michal Novotny > --- > docs/formatnetwork.html.in | 24 ++++++- > docs/schemas/network.rng | 12 +++ > src/conf/network_conf.c | 71 ++++++++++++++++++++ > src/conf/network_conf.h | 16 +++++ > src/network/bridge_driver.c | 15 ++++- > .../nat-network-dns-txt-record.xml | 24 +++++++ > .../nat-network-dns-txt-record.xml | 24 +++++++ > tests/networkxml2xmltest.c | 1 + > 8 files changed, 185 insertions(+), 2 deletions(-) > create mode 100644 tests/networkxml2xmlin/nat-network-dns-txt-record.xml > create mode 100644 tests/networkxml2xmlout/nat-network-dns-txt-record.xml > > diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in > index c6969eb..5211ed2 100644 > --- a/docs/formatnetwork.html.in > +++ b/docs/formatnetwork.html.in > @@ -108,7 +108,10 @@ > The final set of elements define the addresses (IPv4 and/or > IPv6, as well as MAC) to be assigned to the bridge device > associated with the virtual network, and optionally enable DHCP > - services. > + services. The network creation also supports the TXT record in > + the DNS to expose some information to the guest using this > + record. This feature could be used in the similar way like DKIM > + uses TXT records of DNS to expose public key. >

    That needs some rewording, but should also be moved into its own paragraph (see my next comment) anyway. Possibly it will end up being something like: dns The dns element of a network contains configuration information for the virtual network's DNS server. Since 0.9.1 Currently supported elements are: txt (note that I am changing the name from "txt-record" to "txt" - I think the "record" is kind of implied) A dns element can have 0 or more txt elements. Each txt element defines a DNS TXT record and has two attributes, both required: a name that can be queried via dns, and a value that will be returned when that name is queried. names cannot contain embedded spaces or commas. value is a single string that can contain multiple values which are comma-separated. (Does each value create a separate TXT record with the same name, or are they all together really a single value that happens to have commas? I ask this because if it is the former, the implementation may differ on other DNS servers - we want to avoid embedding idiosyncracies of the dnsmasq implementation into our design!) > >
    > @@ -120,6 +123,9 @@
    >               <host mac="00:16:3e:77:e2:ed" name="foo.example.com" ip="192.168.122.10" />
    >               <host mac="00:16:3e:3e:a9:1a" name="bar.example.com" ip="192.168.122.11" />
    >             </dhcp>
    > +<dns>
    > +<txt-record name="example" value="example value" />
    > +</dns>
    
    Since there is a single instance of dnsmasq listening on all IPs defined 
    for a network, and the txt records will be visible to all of them, I 
    think the DNS section should be one level up in the tree - at the same 
    level as IP rather than below it, ie:
    
    
    default
    
    
    
           ...
    
    
    
    >           </ip>
    >         </network>
    > > @@ -199,6 +205,22 @@ > element is used. The BOOTP options currently have to be the same > for all address ranges and statically assigned addresses. class="since">Since 0.7.1 (server since 0.7.3). > +
    dns
    Also within theip element > + there is an optionaldns element. The presence of this element > + enables configuration and exposal of records in the DNS service on the > + virtual network. It will further contain one or moretxt-record > + elements. Thedns element is supported for both IPv4 and IPv6 > + networks.Since 0.9.1 > +
    > +
    txt-record
    > +
    Thetxt-record element is the definition of TXT record for the > + DNS service. There are two attributes that both have to be used for the TXT > + record definition:name andvalue. Thename > +attribute doesn't support commas in it's value so the names with commas > + will be rejected. This applies only to names of the TXT record and not values > + since values (i.e.value contents) supports multiple values > + separated by commas. > +Since 0.9.1 >
    > > See my above comment. Note that some of what you say here doesn't apply if you move the record up to the top level of the hierarchy in . > diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng > index 6d01b06..e27dace 100644 > --- a/docs/schemas/network.rng > +++ b/docs/schemas/network.rng > @@ -136,6 +136,18 @@ > > > > + > + > + > + > + I prefer simply "txt" instead of "txt-record", since 1) it avoids having a - in the name, 2) that's what it's called in a DNS zone file, 3) the "-record" is really an artifact of the dnsmasq implementation (note that dnsmasq inconsistently uses "srv-host" and "cname", along with "ptr-record" and "naptr-record" - these are *all* "records" in the DNS zone file. > + > + > + > + > + > + This will move up one level. I won't bother pointing out the other places where code will change due to moving up in the hierarchy... > > > > diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c > index dcab9de..b7427d0 100644 > --- a/src/conf/network_conf.c > +++ b/src/conf/network_conf.c > @@ -435,6 +435,60 @@ virNetworkDHCPRangeDefParseXML(const char *networkName, > } > > static int > +virNetworkDNSDefParseXML(virNetworkIpDefPtr def, > + xmlNodePtr node) > +{ > + > + xmlNodePtr cur; > + int result = -1; > + > + if (VIR_ALLOC(def->dns)) > + goto oom_error; > + > + cur = node->children; > + while (cur != NULL) { > + if (cur->type == XML_ELEMENT_NODE&& > + xmlStrEqual(cur->name, BAD_CAST "txt-record")) { > + char *name, *value; > + > + if (!(name = virXMLPropString(cur, "name"))) { > + cur = cur->next; > + continue; > + } > + if (!(value = virXMLPropString(cur, "value"))) { > + VIR_FREE(name); > + cur = cur->next; > + continue; > + } > + > + if (strchr(name, ' ') != NULL) { > + virNetworkReportError(VIR_ERR_XML_DETAIL, > + _("TXT record names in DNS doesn't support spaces")); s/doesn't/don't/. Also, an error message is much more helpful if it provides context - adding the name and value to the message would be very useful. > + return -1; You leaked both name and value here. > + } > + > + if (VIR_REALLOC_N(def->dns->txtrecords, def->dns->ntxtrecords + 1)< 0) > + goto oom_error; You again leaked name and value. (def->dns->txtrecords and def->dns will be cleaned up by the caller as it destructs the def). > + def->dns->txtrecords[def->dns->ntxtrecords].name = strdup(name); > + def->dns->txtrecords[def->dns->ntxtrecords].value = strdup(value); > + def->dns->ntxtrecords++; > + > + VIR_FREE(name); > + VIR_FREE(value); Instead of doing a strdup() of each of these, immediately followed by freeing the original, you should just assign the original string into the def. > + } > + > + cur = cur->next; > + } > + > + return 0; > + > +oom_error: > + virReportOOMError(); > + return result; I actually prefer having a single exit, with virReportOOMError() called at the location of the failure, and your "return 0" turned into "ret = 0". You could even do a VIR_FREE(name); VIR_FREE(value); here (after setting them to NULL when you move the pointer into the txtrecord array). That way new error path code will never forget to free them, and as a bonus the variable "ret" is actually used for something. > +} > + > +static int > virNetworkIPParseXML(const char *networkName, > virNetworkIpDefPtr def, > xmlNodePtr node, > @@ -550,6 +604,12 @@ virNetworkIPParseXML(const char *networkName, > goto error; > > } else if (cur->type == XML_ELEMENT_NODE&& > + xmlStrEqual(cur->name, BAD_CAST "dns")) { > + result = virNetworkDNSDefParseXML(def, cur); > + if (result) > + goto error; > + Okay, I can't stop myself :-) - this should be up a level, in virNetworkParseXML(). > + } else if (cur->type == XML_ELEMENT_NODE&& > xmlStrEqual(cur->name, BAD_CAST "tftp")) { > char *root; > > @@ -828,6 +888,17 @@ virNetworkIpDefFormat(virBufferPtr buf, > > virBufferAddLit(buf, "\n"); > } > + if ((def->dns != NULL)&& (def->dns->ntxtrecords)) { > + int ii; > + > + virBufferAddLit(buf, "\n"); > + for (ii = 0 ; ii< def->dns->ntxtrecords ; ii++) { > + virBufferVSprintf(buf, "\n", > + def->dns->txtrecords[ii].name, > + def->dns->txtrecords[ii].value); > + } > + virBufferAddLit(buf, "\n"); > + } same. > > virBufferAddLit(buf, "\n"); > > diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h > index 281124b..5f47595 100644 > --- a/src/conf/network_conf.h > +++ b/src/conf/network_conf.h > @@ -57,6 +57,20 @@ struct _virNetworkDHCPHostDef { > virSocketAddr ip; > }; > > +typedef struct _virNetworkDNSTxtRecordsDef virNetworkDNSTxtRecordsDef; > +typedef virNetworkDNSTxtRecordsDef *virNetworkDNSTxtRecordsDefPtr; > +struct _virNetworkDNSTxtRecordsDef { > + char *name; > + char *value; > +}; > + > +struct virNetworkDNSDef { > + unsigned int ntxtrecords; > + virNetworkDNSTxtRecordsDefPtr txtrecords; > +} virNetworkDNSDef; > + > +typedef struct virNetworkDNSDef *virNetworkDNSDefPtr; > + > typedef struct _virNetworkIpDef virNetworkIpDef; > typedef virNetworkIpDef *virNetworkIpDefPtr; > struct _virNetworkIpDef { > @@ -75,6 +89,8 @@ struct _virNetworkIpDef { > unsigned int nranges; /* Zero or more dhcp ranges */ > virNetworkDHCPRangeDefPtr ranges; > > + virNetworkDNSDefPtr dns; /* DNS related settings for DNSMasq */ > + Move this into virNetworkDef (and no need to mention dnsmasq here, as this file could be used by other implementations in the future). > unsigned int nhosts; /* Zero or more dhcp hosts */ > virNetworkDHCPHostDefPtr hosts; > > diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c > index ea2bfd4..2e299f5 100644 > --- a/src/network/bridge_driver.c > +++ b/src/network/bridge_driver.c > @@ -442,7 +442,6 @@ networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef, > return 0; > } > > - > static int > networkBuildDnsmasqArgv(virNetworkObjPtr network, > virNetworkIpDefPtr ipdef, > @@ -497,6 +496,20 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, > if (network->def->forwardType == VIR_NETWORK_FORWARD_NONE) > virCommandAddArg(cmd, "--dhcp-option=3"); > > + if (ipdef->dns != NULL) { > + int i; > + > + for (i = 0; i< ipdef->dns->ntxtrecords; i++) { > + virBuffer buf = VIR_BUFFER_INITIALIZER; > + virBufferVSprintf(&buf, "%s,%s", > + ipdef->dns->txtrecords[i].name, > + ipdef->dns->txtrecords[i].value); > + > + virCommandAddArgPair(cmd, "--txt-record", virBufferContentAndReset(&buf)); > + VIR_FREE(buf); > + } > + } > + > /* > * --interface does not actually work with dnsmasq< 2.47, > * due to DAD for ipv6 addresses on the interface. > diff --git a/tests/networkxml2xmlin/nat-network-dns-txt-record.xml b/tests/networkxml2xmlin/nat-network-dns-txt-record.xml > new file mode 100644 > index 0000000..d3e795d > --- /dev/null > +++ b/tests/networkxml2xmlin/nat-network-dns-txt-record.xml > @@ -0,0 +1,24 @@ > + > +default > +81ff0d90-c91e-6742-64da-4a736edb9a9b > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > diff --git a/tests/networkxml2xmlout/nat-network-dns-txt-record.xml b/tests/networkxml2xmlout/nat-network-dns-txt-record.xml > new file mode 100644 > index 0000000..d3e795d > --- /dev/null > +++ b/tests/networkxml2xmlout/nat-network-dns-txt-record.xml > @@ -0,0 +1,24 @@ > + > +default > +81ff0d90-c91e-6742-64da-4a736edb9a9b > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c > index 7805548..beb00ef 100644 > --- a/tests/networkxml2xmltest.c > +++ b/tests/networkxml2xmltest.c > @@ -90,6 +90,7 @@ mymain(int argc, char **argv) > DO_TEST("nat-network"); > DO_TEST("netboot-network"); > DO_TEST("netboot-proxy-network"); > + DO_TEST("nat-network-dns-txt-record"); > > return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); > } From laine at laine.org Wed Apr 27 16:33:01 2011 From: laine at laine.org (Laine Stump) Date: Wed, 27 Apr 2011 12:33:01 -0400 Subject: [libvirt] [PATCH v2 2/5] Network: Add regression tests for the command line arguments In-Reply-To: <1301654756-3920-3-git-send-email-minovotn@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> <1301654756-3920-3-git-send-email-minovotn@redhat.com> Message-ID: <4DB8453D.1090709@laine.org> On 04/01/2011 06:45 AM, Michal Novotny wrote: > Make: passed > Make check: passed > Make syntax-check: passed > > Hi, > this is the patch that is adding regression tests for the network > bridge driver command-line arguments similar way it is done for > QEMU driver. This is checking the built dnsmasq parameters (using > networkBuildDhcpDaemonCommandLine() function) and comparing them > to excepted arguments in the *.argv files. > > This has been tested and working fine. > > Michal Same comments about the commit message as in 1/5 - don't include stuff about what tests passed, salutations, signatures; *do* include a short sample of the XML. > Signed-off-by: Michal Novotny > --- > src/network/bridge_driver.c | 27 ++++- > src/network/bridge_driver.h | 3 + > tests/Makefile.am | 11 ++ > tests/networkxml2argvdata/isolated-network.argv | 1 + > tests/networkxml2argvdata/isolated-network.xml | 11 ++ > .../nat-network-dns-txt-record.argv | 1 + > .../nat-network-dns-txt-record.xml | 24 ++++ > tests/networkxml2argvdata/nat-network.argv | 1 + > tests/networkxml2argvdata/nat-network.xml | 21 ++++ > tests/networkxml2argvdata/netboot-network.argv | 1 + > tests/networkxml2argvdata/netboot-network.xml | 14 +++ > .../networkxml2argvdata/netboot-proxy-network.argv | 1 + > .../networkxml2argvdata/netboot-proxy-network.xml | 13 ++ > tests/networkxml2argvdata/routed-network.argv | 1 + > tests/networkxml2argvdata/routed-network.xml | 9 ++ > tests/networkxml2argvtest.c | 119 ++++++++++++++++++++ > 16 files changed, 255 insertions(+), 3 deletions(-) > create mode 100644 tests/networkxml2argvdata/isolated-network.argv > create mode 100644 tests/networkxml2argvdata/isolated-network.xml > create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.argv > create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.xml > create mode 100644 tests/networkxml2argvdata/nat-network.argv > create mode 100644 tests/networkxml2argvdata/nat-network.xml > create mode 100644 tests/networkxml2argvdata/netboot-network.argv > create mode 100644 tests/networkxml2argvdata/netboot-network.xml > create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.argv > create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.xml > create mode 100644 tests/networkxml2argvdata/routed-network.argv > create mode 100644 tests/networkxml2argvdata/routed-network.xml > create mode 100644 tests/networkxml2argvtest.c > > diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c > index 2e299f5..b6ce39d 100644 > --- a/src/network/bridge_driver.c > +++ b/src/network/bridge_driver.c > @@ -613,11 +613,11 @@ cleanup: > return ret; > } > > -static int > -networkStartDhcpDaemon(virNetworkObjPtr network) > +int > +networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, virCommandPtr *cmdout, > + char *pidfile) If you make a function global, you should add it to a .syms file. In this case (as we just discussed on IRC with eblake) you should create a new src/libvirt_network.syms file and add it to that (then add that .syms file to the appropriate places in src/Makefile.am) > { > virCommandPtr cmd = NULL; > - char *pidfile = NULL; As patched, this will not compile - you removed pidfile from the new function, but left the assignment to it in. (actually, all of the directory and file creation items should be moved down into networkStartDhcpDaemon, so that networkBuildDhcpDaemonCommandLine doesn't have any side effects.) > int ret = -1, err, ii; > virNetworkIpDefPtr ipdef; > > @@ -666,6 +666,27 @@ networkStartDhcpDaemon(virNetworkObjPtr network) > goto cleanup; > } > > + if (cmdout) > + *cmdout = cmd; > + > + ret = 0; > +cleanup: > + if (ret != 0) The standard practice in libvirt is to use "ret < 0" rather than "ret != 0". > + virCommandFree(cmd); > + return ret; > +} > + > +static int > +networkStartDhcpDaemon(virNetworkObjPtr network) > +{ > + virCommandPtr cmd = NULL; > + char *pidfile = NULL; > + int ret = -1; > + > + ret = networkBuildDhcpDaemonCommandLine(network,&cmd, pidfile); > + if (ret != 0) Again, ret < 0. > + goto cleanup; > + > if (virCommandRun(cmd, NULL)< 0) > goto cleanup; > > diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h > index 32d2ae7..8d82b67 100644 > --- a/src/network/bridge_driver.h > +++ b/src/network/bridge_driver.h > @@ -28,7 +28,10 @@ > # include > > # include "internal.h" > +# include "network_conf.h" > +# include "command.h" > > int networkRegister(void); > +int networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, virCommandPtr *cmdout, char *pidfile); > > #endif /* __VIR_NETWORK__DRIVER_H */ > diff --git a/tests/Makefile.am b/tests/Makefile.am > index 5896442..a3f8d00 100644 > --- a/tests/Makefile.am > +++ b/tests/Makefile.am > @@ -50,6 +50,7 @@ EXTRA_DIST = \ > networkschematest \ > networkxml2xmlin \ > networkxml2xmlout \ > + networkxml2argvdata \ Yay for new tests! > nodedevschemadata \ > nodedevschematest \ > nodeinfodata \ > @@ -104,6 +105,8 @@ endif > > check_PROGRAMS += networkxml2xmltest > > +check_PROGRAMS += networkxml2argvtest > + > check_PROGRAMS += nwfilterxml2xmltest > > check_PROGRAMS += storagevolxml2xmltest storagepoolxml2xmltest > @@ -191,6 +194,8 @@ endif > > TESTS += networkxml2xmltest > > +TESTS += networkxml2argvtest > + > TESTS += storagevolxml2xmltest storagepoolxml2xmltest > > TESTS += nodedevxml2xmltest > @@ -308,6 +313,12 @@ networkxml2xmltest_SOURCES = \ > testutils.c testutils.h > networkxml2xmltest_LDADD = $(LDADDS) > > +networkxml2argvtest_SOURCES = \ > + networkxml2argvtest.c \ > + ../src/network/bridge_driver.c network/bridge_driver.h \ Rather than adding the source files, you should be adding the .la file libvirt_network.la. See other .la file additions for the proper pattern to follow. > + testutils.c testutils.h > +networkxml2argvtest_LDADD = $(LDADDS) > + > nwfilterxml2xmltest_SOURCES = \ > nwfilterxml2xmltest.c \ > testutils.c testutils.h > diff --git a/tests/networkxml2argvdata/isolated-network.argv b/tests/networkxml2argvdata/isolated-network.argv > new file mode 100644 > index 0000000..1c173db > --- /dev/null > +++ b/tests/networkxml2argvdata/isolated-network.argv > @@ -0,0 +1 @@ > +/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/private.pid --conf-file= --except-interface lo --dhcp-option=3 --listen-address 192.168.152.1 --dhcp-range 192.168.152.2,192.168.152.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/private.leases --dhcp-lease-max=253 --dhcp-no-override > diff --git a/tests/networkxml2argvdata/isolated-network.xml b/tests/networkxml2argvdata/isolated-network.xml > new file mode 100644 > index 0000000..cc320a9 > --- /dev/null > +++ b/tests/networkxml2argvdata/isolated-network.xml > @@ -0,0 +1,11 @@ > + > +private > +81ff0d90-c91e-6742-64da-4a736edb9a9b > + > + > + > + > + > + > + > + > diff --git a/tests/networkxml2argvdata/nat-network-dns-txt-record.argv b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv > new file mode 100644 > index 0000000..55dcf02 > --- /dev/null > +++ b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv > @@ -0,0 +1 @@ > +/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/default.pid --conf-file= --except-interface lo --txt-record=example,example value --listen-address 192.168.122.1 Does the argument to ==txt-record need to be quoted? (probably not needed, but it might help readability in the logs - will it *hurt* anything to quote it? > --listen-address 192.168.123.1 --listen-address 2001:db8:ac10:fe01::1 --listen-address 2001:db8:ac10:fd01::1 --listen-address 10.24.10.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases --dhcp-lease-max=253 --dhcp-no-override --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile > diff --git a/tests/networkxml2argvdata/nat-network-dns-txt-record.xml b/tests/networkxml2argvdata/nat-network-dns-txt-record.xml > new file mode 100644 > index 0000000..d3e795d > --- /dev/null > +++ b/tests/networkxml2argvdata/nat-network-dns-txt-record.xml > @@ -0,0 +1,24 @@ > + > +default > +81ff0d90-c91e-6742-64da-4a736edb9a9b > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > diff --git a/tests/networkxml2argvdata/nat-network.argv b/tests/networkxml2argvdata/nat-network.argv > new file mode 100644 > index 0000000..95ee6d9 > --- /dev/null > +++ b/tests/networkxml2argvdata/nat-network.argv > @@ -0,0 +1 @@ > +/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/default.pid --conf-file= --except-interface lo --listen-address 192.168.122.1 --listen-address 192.168.123.1 --listen-address 2001:db8:ac10:fe01::1 --listen-address 2001:db8:ac10:fd01::1 --listen-address 10.24.10.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases --dhcp-lease-max=253 --dhcp-no-override --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile > diff --git a/tests/networkxml2argvdata/nat-network.xml b/tests/networkxml2argvdata/nat-network.xml > new file mode 100644 > index 0000000..eb71d9e > --- /dev/null > +++ b/tests/networkxml2argvdata/nat-network.xml > @@ -0,0 +1,21 @@ > + > +default > +81ff0d90-c91e-6742-64da-4a736edb9a9b > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > + > diff --git a/tests/networkxml2argvdata/netboot-network.argv b/tests/networkxml2argvdata/netboot-network.argv > new file mode 100644 > index 0000000..36c2360 > --- /dev/null > +++ b/tests/networkxml2argvdata/netboot-network.argv > @@ -0,0 +1 @@ > +/usr/sbin/dnsmasq --strict-order --bind-interfaces --domain example.com --pid-file=/var/run/libvirt/network/netboot.pid --conf-file= --except-interface lo --listen-address 192.168.122.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/netboot.leases --dhcp-lease-max=253 --dhcp-no-override --enable-tftp --tftp-root /var/lib/tftproot --dhcp-boot pxeboot.img > diff --git a/tests/networkxml2argvdata/netboot-network.xml b/tests/networkxml2argvdata/netboot-network.xml > new file mode 100644 > index 0000000..b8a4d99 > --- /dev/null > +++ b/tests/networkxml2argvdata/netboot-network.xml > @@ -0,0 +1,14 @@ > + > +netboot > +81ff0d90-c91e-6742-64da-4a736edb9a9b > + > + > + > + > + > + > + > + > + > + > + > diff --git a/tests/networkxml2argvdata/netboot-proxy-network.argv b/tests/networkxml2argvdata/netboot-proxy-network.argv > new file mode 100644 > index 0000000..da97b72 > --- /dev/null > +++ b/tests/networkxml2argvdata/netboot-proxy-network.argv > @@ -0,0 +1 @@ > +/usr/sbin/dnsmasq --strict-order --bind-interfaces --domain example.com --pid-file=/var/run/libvirt/network/netboot.pid --conf-file= --except-interface lo --listen-address 192.168.122.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/netboot.leases --dhcp-lease-max=253 --dhcp-no-override --dhcp-boot pxeboot.img,,10.20.30.40 > diff --git a/tests/networkxml2argvdata/netboot-proxy-network.xml b/tests/networkxml2argvdata/netboot-proxy-network.xml > new file mode 100644 > index 0000000..e11c50b > --- /dev/null > +++ b/tests/networkxml2argvdata/netboot-proxy-network.xml > @@ -0,0 +1,13 @@ > + > +netboot > +81ff0d90-c91e-6742-64da-4a736edb9a9b > + > + > + > + > + > + > + > + > + > + > diff --git a/tests/networkxml2argvdata/routed-network.argv b/tests/networkxml2argvdata/routed-network.argv > new file mode 100644 > index 0000000..443087c > --- /dev/null > +++ b/tests/networkxml2argvdata/routed-network.argv > @@ -0,0 +1 @@ > +/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/local.pid --conf-file= --except-interface lo --listen-address 192.168.122.1 > diff --git a/tests/networkxml2argvdata/routed-network.xml b/tests/networkxml2argvdata/routed-network.xml > new file mode 100644 > index 0000000..3aa8109 > --- /dev/null > +++ b/tests/networkxml2argvdata/routed-network.xml > @@ -0,0 +1,9 @@ > + > +local > +81ff0d90-c91e-6742-64da-4a736edb9a9b > + > + > + > + > + > + > diff --git a/tests/networkxml2argvtest.c b/tests/networkxml2argvtest.c > new file mode 100644 > index 0000000..e3a8bb4 > --- /dev/null > +++ b/tests/networkxml2argvtest.c > @@ -0,0 +1,119 @@ > +#include > + > +#include > +#include > +#include > +#include > + > +#include > +#include > + > +#include "internal.h" > +#include "testutils.h" > +#include "network_conf.h" > +#include "command.h" > +#include "memory.h" > +#include "network/bridge_driver.h" > + > +static char *progname; > +static char *abs_srcdir; > + > +#define MAX_FILE 4096 > + > + > +static int testCompareXMLToArgvFiles(const char *inxml, const char *outargv) { > + char inXmlData[MAX_FILE]; > + char *inXmlPtr =&(inXmlData[0]); > + char outArgvData[MAX_FILE]; > + char *outArgvPtr =&(outArgvData[0]); > + char *actual = NULL; > + int ret = -1; > + virNetworkDefPtr dev = NULL; > + virNetworkObjPtr obj = NULL; > + virCommandPtr cmd = NULL; > + char *pidfile = NULL; > + > + if (virtTestLoadFile(inxml,&inXmlPtr, MAX_FILE)< 0) > + goto fail; > + > + if (virtTestLoadFile(outargv,&outArgvPtr, MAX_FILE)< 0) > + goto fail; > + > + if (!(dev = virNetworkDefParseString(inXmlData))) > + goto fail; > + > + if (VIR_ALLOC(obj)< 0) > + goto fail; > + > + obj->def = dev; > + > + if (networkBuildDhcpDaemonCommandLine(obj,&cmd, pidfile) != 0) > + goto fail; > + > + if (!(actual = virCommandToString(cmd))) > + goto fail; > + > + /* There is a new line character but syntax-check would complain > + * about this in argv files so just trim it now > + */ > + outArgvData[ strlen(outArgvData) - 1] = 0; > + > + if (STRNEQ(outArgvData, actual)) { > + virtTestDifference(stderr, outArgvData, actual); > + goto fail; > + } > + > + ret = 0; > + > + fail: > + free(actual); > + VIR_FREE(pidfile); > + virCommandFree(cmd); > + virNetworkObjFree(obj); > + return ret; > +} > + > +static int testCompareXMLToArgvHelper(const void *data) { > + char inxml[PATH_MAX]; > + char outargv[PATH_MAX]; > + snprintf(inxml, PATH_MAX, "%s/networkxml2argvdata/%s.xml", > + abs_srcdir, (const char*)data); > + snprintf(outargv, PATH_MAX, "%s/networkxml2argvdata/%s.argv", > + abs_srcdir, (const char*)data); > + return testCompareXMLToArgvFiles(inxml, outargv); > +} > + > + > +static int > +mymain(int argc, char **argv) > +{ > + int ret = 0; > + char cwd[PATH_MAX]; > + > + progname = argv[0]; > + > + if (argc> 1) { > + fprintf(stderr, "Usage: %s\n", progname); > + return (EXIT_FAILURE); > + } > + > + abs_srcdir = getenv("abs_srcdir"); > + if (!abs_srcdir) > + abs_srcdir = getcwd(cwd, sizeof(cwd)); > + > +#define DO_TEST(name) \ > + if (virtTestRun("Network XML-2-Argv " name, \ > + 1, testCompareXMLToArgvHelper, (name))< 0) \ > + ret = -1 > + > + DO_TEST("isolated-network"); > + DO_TEST("routed-network"); > + DO_TEST("nat-network"); > + DO_TEST("netboot-network"); > + DO_TEST("netboot-proxy-network"); > + DO_TEST("nat-network-dns-txt-record"); > + > + return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); > +} > + > +VIRT_TEST_MAIN(mymain) From laine at laine.org Wed Apr 27 16:39:06 2011 From: laine at laine.org (Laine Stump) Date: Wed, 27 Apr 2011 12:39:06 -0400 Subject: [libvirt] [PATCH v2 3/5] Network: Move dnsmasqContext creation to networkSaveDnsmasqHostsfile() and pass to dnsmasq only if applicable In-Reply-To: <1301654756-3920-4-git-send-email-minovotn@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> <1301654756-3920-4-git-send-email-minovotn@redhat.com> Message-ID: <4DB846AA.3060206@laine.org> On 04/01/2011 06:45 AM, Michal Novotny wrote: > Make: passed > Make check: passed > Make syntax-check: passed > > Hi, > this is the patch to move the dnsmasqContext creation to the > networkSaveDnsmasqHostsfile() function and also it passes the > hosts-file and addn-hosts to the file only if applicable, i.e. > if it's already set. > > Originally I wanted to call the DhcpHostsfile and AddnHostsfile > creation on the first call to dnsmasqAddDhcpHost/dnsmasqAddHost > however that way I would have kept track of the path name to > be generated which would require storing network name and config > directory somewhere in the structure and that's why I changed > it to simple approach used in this patch. > > Michal This all looks straightforward. The only comment I have (other than to sanitize the commit comment) would be that some day in the future I would like to be able to specify static dhcp hosts under multiple IP addresses within a network (dnsmasq can handle this, it just needs a bit of extra trickery in the commandline), so anything you do to make that easier would be good. (but as long as you don't make it any more difficult than it already is, I'll ACK this when you resubmit the series). > Signed-off-by: Michal Novotny > --- > src/network/bridge_driver.c | 38 +++++++++++++++++++++----------------- > 1 files changed, 21 insertions(+), 17 deletions(-) > > diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c > index b6ce39d..41b14f9 100644 > --- a/src/network/bridge_driver.c > +++ b/src/network/bridge_driver.c > @@ -420,13 +420,20 @@ networkShutdown(void) { > } > > > -static int > +static dnsmasqContext* > networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef, > - dnsmasqContext *dctx, > + char *name, > bool force) > { > unsigned int i; > > + dnsmasqContext *dctx = dnsmasqContextNew(name, > + DNSMASQ_STATE_DIR); > + if (dctx == NULL) { > + virReportOOMError(); > + goto cleanup; > + } > + > if (! force&& virFileExists(dctx->hostsfile->path)) > return 0; > > @@ -437,9 +444,14 @@ networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef, > } > > if (dnsmasqSave(dctx)< 0) > - return -1; > + goto cleanup; > > - return 0; > + return dctx; > + > +cleanup: > + dnsmasqContextFree(dctx); > + > + return NULL; > } > > static int > @@ -451,6 +463,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, > int nbleases = 0; > int ii; > virNetworkIpDefPtr tmpipdef; > + dnsmasqContext *dctx = NULL; > > /* > * NB, be careful about syntax for dnsmasq options in long format. > @@ -572,18 +585,11 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, > if (ipdef->nranges || ipdef->nhosts) > virCommandAddArg(cmd, "--dhcp-no-override"); > > - if (ipdef->nhosts> 0) { > - dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, > - DNSMASQ_STATE_DIR); > - if (dctx == NULL) { > - virReportOOMError(); > - goto cleanup; > - } > - > - if (networkSaveDnsmasqHostsfile(ipdef, dctx, false) == 0) { > + if ((dctx = networkSaveDnsmasqHostsfile(ipdef, network->def->name, false))) { > + if (dctx->hostsfile->nhosts) > virCommandAddArgPair(cmd, "--dhcp-hostsfile", > dctx->hostsfile->path); > - } > + > dnsmasqContextFree(dctx); > } > > @@ -2203,11 +2209,9 @@ static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) { > } > } > if (ipv4def) { > - dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR); > + dnsmasqContext* dctx = networkSaveDnsmasqHostsfile(ipv4def, network->def->name, true); > if (dctx == NULL) > goto cleanup; > - > - networkSaveDnsmasqHostsfile(ipv4def, dctx, true); > dnsmasqContextFree(dctx); > } > From eblake at redhat.com Wed Apr 27 16:45:54 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 27 Apr 2011 10:45:54 -0600 Subject: [libvirt] [PATCH] tests: More unit tests for internal hash APIs In-Reply-To: References: <0ebc29ed7078c909b92f692d28c572f0c05ff9b9.1302629114.git.jdenemar@redhat.com> Message-ID: <4DB84842.5040505@redhat.com> On 04/19/2011 07:22 AM, Jiri Denemark wrote: > This adds several tests for remaining hash APIs (custom > hasher/comparator functions are not covered yet, though). > +++ b/tests/hashtest.c Oops, sorry for not noticing sooner, but this again breaks 32-bit builds: > + if (virTestGetVerbose()) { > + testError("\nvirHashForEach didn't go through all entries," > + " %d != %lu\n", > + count, ARRAY_CARDINALITY(uuids)); I'm committing the obvious %zu fixup, just like commit 1fc288e. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From laine at laine.org Wed Apr 27 16:56:33 2011 From: laine at laine.org (Laine Stump) Date: Wed, 27 Apr 2011 12:56:33 -0400 Subject: [libvirt] [PATCH v2 4/5] Network: Add additional hosts internal infrastructure In-Reply-To: <1301654756-3920-5-git-send-email-minovotn@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> <1301654756-3920-5-git-send-email-minovotn@redhat.com> Message-ID: <4DB84AC1.7080009@laine.org> On 04/01/2011 06:45 AM, Michal Novotny wrote: > Hi, > this is the patch to introduce the internal infrastructure for > additional hosts for network bridge driver using the addnhosts* > API functions. > > This is necessary for next part of the patch to support DNS > hosts definition in the network XML description. > > Michal > > Signed-off-by: Michal Novotny > --- > src/libvirt_private.syms | 1 + > src/network/bridge_driver.c | 3 + > src/util/dnsmasq.c | 266 ++++++++++++++++++++++++++++++++++++++++++- > src/util/dnsmasq.h | 22 ++++- > 4 files changed, 287 insertions(+), 5 deletions(-) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 65a86d3..73c3f77 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -186,6 +186,7 @@ virUnrefStream; > > # dnsmasq.h > dnsmasqAddDhcpHost; > +dnsmasqAddHost; > dnsmasqContextFree; > dnsmasqContextNew; > dnsmasqDelete; > diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c > index 41b14f9..4ad3143 100644 > --- a/src/network/bridge_driver.c > +++ b/src/network/bridge_driver.c > @@ -589,6 +589,9 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, > if (dctx->hostsfile->nhosts) > virCommandAddArgPair(cmd, "--dhcp-hostsfile", > dctx->hostsfile->path); > + if (dctx->addnhostsfile->nhosts) > + virCommandAddArgPair(cmd, "--addn-hosts", > + dctx->addnhostsfile->path); > > dnsmasqContextFree(dctx); > } > diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c > index be230e1..fee3b90 100644 > --- a/src/util/dnsmasq.c > +++ b/src/util/dnsmasq.c > @@ -48,6 +48,7 @@ > > #define VIR_FROM_THIS VIR_FROM_NETWORK > #define DNSMASQ_HOSTSFILE_SUFFIX "hostsfile" > +#define DNSMASQ_ADDNHOSTSFILE_SUFFIX "addnhosts" > > static void > dhcphostFree(dnsmasqDhcpHost *host) > @@ -56,6 +57,231 @@ dhcphostFree(dnsmasqDhcpHost *host) > } > > static void > +addnhostFree(dnsmasqAddnHost *host) > +{ > + VIR_FREE(host->hostnames); > + VIR_FREE(host->ip); > +} > + > +static void > +addnhostsFree(dnsmasqAddnHostsfile *addnhostsfile) > +{ > + unsigned int i; > + > + if (addnhostsfile->hosts) { > + for (i = 0; i< addnhostsfile->nhosts; i++) > + addnhostFree(&addnhostsfile->hosts[i]); > + > + VIR_FREE(addnhostsfile->hosts); > + > + addnhostsfile->nhosts = 0; > + } > + > + VIR_FREE(addnhostsfile->path); > + > + VIR_FREE(addnhostsfile); > +} > + > +static int > +addnhostsAdd(dnsmasqAddnHostsfile *addnhostsfile, > + virSocketAddr *ip, > + const char *name) > +{ > + char *ipstr = NULL; > + int idx = -1; > + int i; > + > + if (!(ipstr = virSocketFormatAddr(ip))) > + return -1; > + > + for (i = 0; i< addnhostsfile->nhosts; i++) { > + if (STREQ((const char *)addnhostsfile->hosts[i].ip, (const char *)ipstr)) { > + idx = i; > + break; > + } > + } > + > + if (idx< 0) { > + if (VIR_REALLOC_N(addnhostsfile->hosts, addnhostsfile->nhosts + 1)< 0) > + goto alloc_error; > + > + idx = addnhostsfile->nhosts; > + if (VIR_ALLOC(addnhostsfile->hosts[idx].hostnames)< 0) > + goto alloc_error; > + > + if (virAsprintf(&addnhostsfile->hosts[idx].ip, "%s", ipstr)< 0) > + goto alloc_error; > + > + addnhostsfile->hosts[idx].nhostnames = 0; > + addnhostsfile->nhosts++; > + } > + > + if (VIR_REALLOC_N(addnhostsfile->hosts[idx].hostnames, addnhostsfile->hosts[idx].nhostnames + 1)< 0) > + goto alloc_error; > + > + if (virAsprintf(&addnhostsfile->hosts[idx].hostnames[addnhostsfile->hosts[idx].nhostnames], "%s", name)< 0) > + goto alloc_error; > + > + VIR_FREE(ipstr); > + > + addnhostsfile->hosts[idx].nhostnames++; > + > + return 0; > + > + alloc_error: > + virReportOOMError(); > + VIR_FREE(ipstr); > + return -1; > +} > + > +static dnsmasqAddnHostsfile * > +addnhostsNew(const char *name, > + const char *config_dir) > +{ > + int err; > + dnsmasqAddnHostsfile *addnhostsfile; > + > + if (VIR_ALLOC(addnhostsfile)< 0) { > + virReportOOMError(); > + return NULL; > + } > + > + addnhostsfile->hosts = NULL; > + addnhostsfile->nhosts = 0; > + > + if (virAsprintf(&addnhostsfile->path, "%s/%s.%s", config_dir, name, > + DNSMASQ_ADDNHOSTSFILE_SUFFIX)< 0) { > + virReportOOMError(); > + goto error; > + } > + > + if ((err = virFileMakePath(config_dir))) { > + virReportSystemError(err, _("cannot create config directory '%s'"), > + config_dir); > + goto error; > + } > + > + return addnhostsfile; > + > + error: > + addnhostsFree(addnhostsfile); > + return NULL; > +} > + > +static int > +addnhostsWrite(const char *path, > + dnsmasqAddnHost *hosts, > + unsigned int nhosts) > +{ > + char *tmp; > + FILE *f; > + bool istmp = true; > + unsigned int i, ii; > + int rc = 0; > + > + if (nhosts == 0) > + return rc; > + > + if (virAsprintf(&tmp, "%s.new", path)< 0) > + return ENOMEM; Oooh! Figuring that you had cut-pasted this code from the existing hostsFileWrite(), and knowing that in general we like to return -errno on failure (although there are still some exceptions), I went to look at the original code and found a bug! (hostsWriteFile() is returning errno on failure, but at least one caller is checking for ret < 0). I'm sending in a patch for that momentarily, and you should base the next revision of your code on that. > + > + if (!(f = fopen(tmp, "w"))) { > + istmp = false; > + if (!(f = fopen(path, "w"))) { > + rc = errno; > + goto cleanup; > + } > + } > + > + for (i = 0; i< nhosts; i++) { > + if (fputs(hosts[i].ip, f) == EOF || fputc('\t', f) == EOF) { > + rc = errno; > + VIR_FORCE_FCLOSE(f); > + > + if (istmp) > + unlink(tmp); > + > + goto cleanup; > + } > + > + for (ii = 0; ii< hosts[i].nhostnames; ii++) { > + if (fputs(hosts[i].hostnames[ii], f) == EOF || fputc('\t', f) == EOF) { > + rc = errno; > + VIR_FORCE_FCLOSE(f); > + > + if (istmp) > + unlink(tmp); > + > + goto cleanup; > + } > + } > + > + if (fputc('\n', f) == EOF) { > + rc = errno; > + VIR_FORCE_FCLOSE(f); > + > + if (istmp) > + unlink(tmp); > + > + goto cleanup; > + } > + } > + > + if (VIR_FCLOSE(f) == EOF) { > + rc = errno; > + goto cleanup; > + } > + > + if (istmp) { > + if (rename(tmp, path)< 0) { > + rc = errno; > + unlink(tmp); > + goto cleanup; > + } > + > + if (unlink(tmp)< 0) { > + rc = errno; > + goto cleanup; > + } > + } > + > + cleanup: > + VIR_FREE(tmp); > + > + return rc; > +} > + > +static int > +addnhostsSave(dnsmasqAddnHostsfile *addnhostsfile) > +{ > + int err = addnhostsWrite(addnhostsfile->path, addnhostsfile->hosts, > + addnhostsfile->nhosts); > + > + if (err< 0) { > + virReportSystemError(err, _("cannot write config file '%s'"), > + addnhostsfile->path); > + return -1; > + } > + > + return 0; > +} > + > +static int > +addnhostsDelete(dnsmasqAddnHostsfile *addnhostsfile) > +{ > + if (!virFileExists(addnhostsfile->path)) > + return 0; > + > + if (unlink(addnhostsfile->path)< 0) { > + virReportSystemError(errno, _("cannot remove config file '%s'"), > + addnhostsfile->path); > + return -1; > + } > + > + return 0; > +} Except for the type of the arg, this function is identical to hostsfileDelete. How about changing hostsfileDelete() to take a "const char *file", then changing its name to something more generic, and calling the same function from both places? > + > +static void > hostsfileFree(dnsmasqHostsfile *hostsfile) > { > unsigned int i; > @@ -255,6 +481,8 @@ dnsmasqContextNew(const char *network_name, > > if (!(ctx->hostsfile = hostsfileNew(network_name, config_dir))) > goto error; > + if (!(ctx->addnhostsfile = addnhostsNew(network_name, config_dir))) > + goto error; > > return ctx; > > @@ -277,6 +505,8 @@ dnsmasqContextFree(dnsmasqContext *ctx) > > if (ctx->hostsfile) > hostsfileFree(ctx->hostsfile); > + if (ctx->addnhostsfile) > + addnhostsFree(ctx->addnhostsfile); > > VIR_FREE(ctx); > } > @@ -300,6 +530,24 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx, > hostsfileAdd(ctx->hostsfile, mac, ip, name); > } > > +/* > + * dnsmasqAddHost: > + * @ctx: pointer to the dnsmasq context for each network > + * @ip: pointer to the socket address contains ip of the host > + * @name: pointer to the string contains hostname of the host > + * > + * Add additional host entry. > + */ > + > +void > +dnsmasqAddHost(dnsmasqContext *ctx, > + virSocketAddr *ip, > + const char *name) > +{ > + if (ctx->addnhostsfile) > + addnhostsAdd(ctx->addnhostsfile, ip, name); > +} > + > /** > * dnsmasqSave: > * @ctx: pointer to the dnsmasq context for each network > @@ -309,10 +557,15 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx, > int > dnsmasqSave(const dnsmasqContext *ctx) > { > + int ret1 = 0; > + int ret2 = 0; > + > if (ctx->hostsfile) > - return hostsfileSave(ctx->hostsfile); > + ret1 = hostsfileSave(ctx->hostsfile); > + if (ctx->addnhostsfile) > + ret2 = addnhostsSave(ctx->addnhostsfile); > > - return 0; > + return ((ret1 == 0)&& (ret2 == 0)) ? 0 : -1; Does it really need to be this complicated? Or can you just have a single "ret", and skip the 2nd save if the first save fails? > } > > > @@ -325,10 +578,15 @@ dnsmasqSave(const dnsmasqContext *ctx) > int > dnsmasqDelete(const dnsmasqContext *ctx) > { > + int ret1 = 0; > + int ret2 = 0; > + > if (ctx->hostsfile) > - return hostsfileDelete(ctx->hostsfile); > + ret1 = hostsfileDelete(ctx->hostsfile); > + if (ctx->addnhostsfile) > + ret2 = addnhostsDelete(ctx->addnhostsfile); > > - return 0; > + return ((ret1 == 0)&& (ret2 == 0)) ? 0 : -1; I think the "try 2nd even if 1st fails" method *is* appropriate here though. > } > > /** > diff --git a/src/util/dnsmasq.h b/src/util/dnsmasq.h > index 02a961f..3f6320a 100644 > --- a/src/util/dnsmasq.h > +++ b/src/util/dnsmasq.h > @@ -44,7 +44,24 @@ typedef struct > > typedef struct > { > - dnsmasqHostsfile *hostsfile; > + unsigned int nhostnames; > + char *ip; > + char **hostnames; > + > +} dnsmasqAddnHost; > + > +typedef struct > +{ > + unsigned int nhosts; > + dnsmasqAddnHost *hosts; > + > + char *path; /* Absolute path of dnsmasq's hostsfile. */ > +} dnsmasqAddnHostsfile; > + > +typedef struct > +{ > + dnsmasqHostsfile *hostsfile; > + dnsmasqAddnHostsfile *addnhostsfile; > } dnsmasqContext; > > dnsmasqContext * dnsmasqContextNew(const char *network_name, > @@ -54,6 +71,9 @@ void dnsmasqAddDhcpHost(dnsmasqContext *ctx, > const char *mac, > virSocketAddr *ip, > const char *name); > +void dnsmasqAddHost(dnsmasqContext *ctx, > + virSocketAddr *ip, > + const char *name); > int dnsmasqSave(const dnsmasqContext *ctx); > int dnsmasqDelete(const dnsmasqContext *ctx); > int dnsmasqReload(pid_t pid); From laine at laine.org Wed Apr 27 17:57:53 2011 From: laine at laine.org (Laine Stump) Date: Wed, 27 Apr 2011 13:57:53 -0400 Subject: [libvirt] [PATCH v2 5/5] Network: Add support for DNS hosts definition to the network XML In-Reply-To: <1301654756-3920-6-git-send-email-minovotn@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> <1301654756-3920-6-git-send-email-minovotn@redhat.com> Message-ID: <4DB85921.4030509@laine.org> On 04/01/2011 06:45 AM, Michal Novotny wrote: > Make: passed > Make check: passed > Make syntax-check: passed > > Hi, > this is the patch to add support for DNS hosts definition in the > network XML description to generate the the hosts file. This patch > uses the addnhosts* APIs implemented to the src/util/dnsmasq.c by > part 2 of this patch series. > > Also, tests for the XML to XML definition and command-line > regression tests has been added. > > Michal Same comments about the commit message - remove the testing comments, salutation, signature; add in a short example of the XML. > Signed-off-by: Michal Novotny > --- > docs/formatnetwork.html.in | 7 + > docs/schemas/network.rng | 8 ++ > src/conf/network_conf.c | 128 ++++++++++++++++++-- > src/conf/network_conf.h | 9 ++ > src/network/bridge_driver.c | 20 ++- > .../networkxml2argvdata/nat-network-dns-hosts.argv | 1 + > .../networkxml2argvdata/nat-network-dns-hosts.xml | 19 +++ > tests/networkxml2argvtest.c | 1 + > tests/networkxml2xmlin/nat-network-dns-hosts.xml | 27 ++++ > tests/networkxml2xmlout/nat-network-dns-hosts.xml | 27 ++++ > tests/networkxml2xmltest.c | 1 + > 11 files changed, 234 insertions(+), 14 deletions(-) > create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.argv > create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.xml > create mode 100644 tests/networkxml2xmlin/nat-network-dns-hosts.xml > create mode 100644 tests/networkxml2xmlout/nat-network-dns-hosts.xml > > diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in > index 5211ed2..5d18ed9 100644 > --- a/docs/formatnetwork.html.in > +++ b/docs/formatnetwork.html.in > @@ -222,6 +222,13 @@ > separated by commas. > Since 0.9.1 > > +
    host
    > +
    Thehost element is the definition of DNS hosts to be passed > + to the DNS service. The IP address is identified by theip attribute > + and the names for the IP addresses are identified in thehostname > + subelements of thehost element. > +Since 0.9.1 > +
    > > >

    Example configuration

    > diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng > index e27dace..05066a5 100644 > --- a/docs/schemas/network.rng > +++ b/docs/schemas/network.rng > @@ -146,6 +146,14 @@ > > > > + > + > + > + > + I think it would be better to simply call it "name" rather than "hostname" (since "host" is already implied by its parent being "") > + > + > + Also, this will move up a level along with the rest of . > > > > diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c > index b7427d0..1f88649 100644 > --- a/src/conf/network_conf.c > +++ b/src/conf/network_conf.c > @@ -435,6 +435,53 @@ virNetworkDHCPRangeDefParseXML(const char *networkName, > } > > static int > +virNetworkDNSHostsDefParseXML(virNetworkIpDefPtr def, (will be virNetworkDefPtr def...) > + xmlNodePtr node, > + virSocketAddr ip) > +{ > + xmlNodePtr cur; > + int result = -1; > + > + if (def->dns->hosts == NULL) { > + if (VIR_ALLOC(def->dns->hosts)< 0) > + goto oom_error; > + def->dns->nhosts = 0; > + } > + > + cur = node->children; > + while (cur != NULL) { > + if (cur->type == XML_ELEMENT_NODE&& > + xmlStrEqual(cur->name, BAD_CAST "hostname")) { Again, s/hostname/name/ > + if (cur->children != NULL) { > + char *hostname; > + > + hostname = strdup((char *)cur->children->content); > + > + if (VIR_REALLOC_N(def->dns->hosts, def->dns->nhosts + 1)< 0) { > + VIR_FREE(hostname); > + result = -1; > + goto oom_error; > + } > + > + def->dns->hosts[def->dns->nhosts].name = strdup(hostname); Rather than strduping hostname, then freeing it, just assign the original directly into the struct. > + def->dns->hosts[def->dns->nhosts].ip = ip; > + def->dns->nhosts++; > + > + VIR_FREE(hostname); > + } > + } > + > + cur = cur->next; > + } > + > + return 0; > + > +oom_error: > + virReportOOMError(); > + return result; > +} > + > +static int > virNetworkDNSDefParseXML(virNetworkIpDefPtr def, > xmlNodePtr node) > { > @@ -476,6 +523,27 @@ virNetworkDNSDefParseXML(virNetworkIpDefPtr def, > > VIR_FREE(name); > VIR_FREE(value); > + } else if (cur->type == XML_ELEMENT_NODE&& > + xmlStrEqual(cur->name, BAD_CAST "host")) { > + char *ip; > + virSocketAddr inaddr; > + memset(&inaddr, 0, sizeof(inaddr)); > + > + if (!(ip = virXMLPropString(cur, "ip"))) { > + cur = cur->next; > + continue; > + } > + if ((ip == NULL) || > + (virSocketParseAddr(ip,&inaddr, AF_UNSPEC)< 0)) { > + virNetworkReportError(VIR_ERR_XML_DETAIL, > + _("Missing IP address in DNS host definition")); "Missing/incorrect". Also, since def will end up being virNetworkDefPtr, you can add the name of the network, as well as the string that was given for ip. That will help in finding the source of the error. > + VIR_FREE(ip); > + goto error; > + } > + VIR_FREE(ip); > + result = virNetworkDNSHostsDefParseXML(def, cur, inaddr); > + if (result) > + goto error; > } > > cur = cur->next; > @@ -485,6 +553,7 @@ virNetworkDNSDefParseXML(virNetworkIpDefPtr def, > > oom_error: > virReportOOMError(); > +error: > return result; > } > > @@ -888,17 +957,60 @@ virNetworkIpDefFormat(virBufferPtr buf, > > virBufferAddLit(buf, "\n"); > } > - if ((def->dns != NULL)&& (def->dns->ntxtrecords)) { > - int ii; > - > + if (def->dns != NULL) { > virBufferAddLit(buf, "\n"); > - for (ii = 0 ; ii< def->dns->ntxtrecords ; ii++) { > - virBufferVSprintf(buf, "\n", > - def->dns->txtrecords[ii].name, > - def->dns->txtrecords[ii].value); > + > + if (def->dns->ntxtrecords) { This if() should have been in the patch for . That way this patch wouldn't be polluted with diffs unrelated to the new feature introduced in this patch. > + int ii; > + > + for (ii = 0 ; ii< def->dns->ntxtrecords; ii++) { > + virBufferVSprintf(buf, "\n", > + def->dns->txtrecords[ii].name, > + def->dns->txtrecords[ii].value); > + } > + } > + if (def->dns->nhosts) { > + int ii, j; > + char **iplist = NULL; > + int iplist_size = 0; > + bool in_list; > + > + if (VIR_ALLOC(iplist)< 0) > + goto error; > + > + for (ii = 0 ; ii< def->dns->nhosts; ii++) { > + char *ip = virSocketFormatAddr(&def->dns->hosts[ii].ip); > + in_list = false; > + for (j = 0; j< iplist_size; j++) > + if (STREQ(iplist[j], ip)) > + in_list = true; > + > + if (!in_list) { > + virBufferVSprintf(buf, "\n", ip); > + > + for (j = 0 ; j< def->dns->nhosts; j++) { > + char *thisip = virSocketFormatAddr(&def->dns->hosts[j].ip); > + if (STREQ(ip, thisip)) > + virBufferVSprintf(buf, "%s\n", > + def->dns->hosts[j].name); > + } > + virBufferVSprintf(buf, "\n"); > + > + if (VIR_REALLOC_N(iplist, iplist_size + 1)< 0) > + goto error; > + > + iplist[iplist_size] = strdup(ip); > + iplist_size++; > + } > + } > + > + for (j = 0; j< iplist_size; j++) > + VIR_FREE(iplist[j]); > + VIR_FREE(iplist); It would make more sense if virNetworkDNSHostsDef->name was char** and had an array of names, as you did in PATCH 4/5. That would make the object a more direct representation of the XML data, and eliminate all of this complicated code dealing with "iplist" and nested loops. > } > + > virBufferAddLit(buf, "\n"); > - } > + } > > virBufferAddLit(buf, "\n"); > > diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h > index 5f47595..305ef0f 100644 > --- a/src/conf/network_conf.h > +++ b/src/conf/network_conf.h > @@ -64,9 +64,18 @@ struct _virNetworkDNSTxtRecordsDef { > char *value; > }; > > +struct virNetworkDNSHostsDef { > + virSocketAddr ip; > + char *name; Again - make name char** as you did in PATCH 4/5. > +} virNetworkDNSHostsDef; > + > +typedef struct virNetworkDNSHostsDef *virNetworkDNSHostsDefPtr; > + > struct virNetworkDNSDef { > unsigned int ntxtrecords; > + unsigned int nhosts; > virNetworkDNSTxtRecordsDefPtr txtrecords; > + virNetworkDNSHostsDefPtr hosts; > } virNetworkDNSDef; > > typedef struct virNetworkDNSDef *virNetworkDNSDefPtr; > diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c > index 4ad3143..99a61b0 100644 > --- a/src/network/bridge_driver.c > +++ b/src/network/bridge_driver.c > @@ -434,13 +434,20 @@ networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef, This function is going to also need a virNetworkDefPtr arg if dns moves up a level. > goto cleanup; > } > > - if (! force&& virFileExists(dctx->hostsfile->path)) > - return 0; > + if (!(! force&& virFileExists(dctx->hostsfile->path))) { That is much easier to understand if written as: if (force || !virFileExists(dctx->hostsfile->path) > + for (i = 0; i< ipdef->nhosts; i++) { > + virNetworkDHCPHostDefPtr host =&(ipdef->hosts[i]); > + if ((host->mac)&& VIR_SOCKET_HAS_ADDR(&host->ip)) > + dnsmasqAddDhcpHost(dctx, host->mac,&host->ip, host->name); > + } > + } > > - for (i = 0; i< ipdef->nhosts; i++) { > - virNetworkDHCPHostDefPtr host =&(ipdef->hosts[i]); > - if ((host->mac)&& VIR_SOCKET_HAS_ADDR(&host->ip)) > - dnsmasqAddDhcpHost(dctx, host->mac,&host->ip, host->name); > + if (ipdef->dns) { > + for (i = 0; i< ipdef->dns->nhosts; i++) { > + virNetworkDNSHostsDefPtr host =&(ipdef->dns->hosts[i]); > + if (VIR_SOCKET_HAS_ADDR(&host->ip)) > + dnsmasqAddHost(dctx,&host->ip, host->name); If you change the virNetworkDNSHostDefPtr to contain char **name instead of char *name, and dnsmasqAddHost to accept char** rather than char*, this can remain pretty much unchanged. > + } > } > > if (dnsmasqSave(dctx)< 0) > @@ -589,6 +596,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, > if (dctx->hostsfile->nhosts) > virCommandAddArgPair(cmd, "--dhcp-hostsfile", > dctx->hostsfile->path); > + VIR_DEBUG("ADDN HOSTS: %d => %p", dctx->addnhostsfile->nhosts, ipdef->dns); Did you mean to leave this DEBUG in? > if (dctx->addnhostsfile->nhosts) > virCommandAddArgPair(cmd, "--addn-hosts", > dctx->addnhostsfile->path); > diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.argv b/tests/networkxml2argvdata/nat-network-dns-hosts.argv > new file mode 100644 > index 0000000..99dc724 > --- /dev/null > +++ b/tests/networkxml2argvdata/nat-network-dns-hosts.argv > @@ -0,0 +1 @@ > +/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/default.pid --conf-file= --except-interface lo --listen-address 192.168.122.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases --dhcp-lease-max=253 --dhcp-no-override --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile --addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts > diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.xml b/tests/networkxml2argvdata/nat-network-dns-hosts.xml > new file mode 100644 > index 0000000..35ee151 > --- /dev/null > +++ b/tests/networkxml2argvdata/nat-network-dns-hosts.xml > @@ -0,0 +1,19 @@ > + > +default > +81ff0d90-c91e-6742-64da-4a736edb9a9b > + > + > + > + > + > + > + > + > + > + > +host > +gateway > + > + > + > + > diff --git a/tests/networkxml2argvtest.c b/tests/networkxml2argvtest.c > index e3a8bb4..ce09206 100644 > --- a/tests/networkxml2argvtest.c > +++ b/tests/networkxml2argvtest.c > @@ -112,6 +112,7 @@ mymain(int argc, char **argv) > DO_TEST("netboot-network"); > DO_TEST("netboot-proxy-network"); > DO_TEST("nat-network-dns-txt-record"); > + DO_TEST("nat-network-dns-hosts"); > > return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); > } > diff --git a/tests/networkxml2xmlin/nat-network-dns-hosts.xml b/tests/networkxml2xmlin/nat-network-dns-hosts.xml > new file mode 100644 > index 0000000..fe545cf > --- /dev/null > +++ b/tests/networkxml2xmlin/nat-network-dns-hosts.xml > @@ -0,0 +1,27 @@ > + > +default > +81ff0d90-c91e-6742-64da-4a736edb9a9b > + > + > + > + > + > + > + > + > + > + > +host > +gateway > + > + > + > + > + > + > + > + > + > + > + > + > diff --git a/tests/networkxml2xmlout/nat-network-dns-hosts.xml b/tests/networkxml2xmlout/nat-network-dns-hosts.xml > new file mode 100644 > index 0000000..fe545cf > --- /dev/null > +++ b/tests/networkxml2xmlout/nat-network-dns-hosts.xml > @@ -0,0 +1,27 @@ > + > +default > +81ff0d90-c91e-6742-64da-4a736edb9a9b > + > + > + > + > + > + > + > + > + > + > +host > +gateway > + > + > + > + > + > + > + > + > + > + > + > + > diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c > index beb00ef..f5c5715 100644 > --- a/tests/networkxml2xmltest.c > +++ b/tests/networkxml2xmltest.c > @@ -91,6 +91,7 @@ mymain(int argc, char **argv) > DO_TEST("netboot-network"); > DO_TEST("netboot-proxy-network"); > DO_TEST("nat-network-dns-txt-record"); > + DO_TEST("nat-network-dns-hosts"); > > return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); > } From laine at laine.org Thu Apr 28 01:31:29 2011 From: laine at laine.org (Laine Stump) Date: Wed, 27 Apr 2011 21:31:29 -0400 Subject: [libvirt] [PATCH v2 4/5] Network: Add additional hosts internal infrastructure In-Reply-To: <1301654756-3920-5-git-send-email-minovotn@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> <1301654756-3920-5-git-send-email-minovotn@redhat.com> Message-ID: <4DB8C371.1040706@laine.org> Coming back to this now that I see how it's being used... On 04/01/2011 06:45 AM, Michal Novotny wrote: > Hi, > this is the patch to introduce the internal infrastructure for > additional hosts for network bridge driver using the addnhosts* > API functions. > > This is necessary for next part of the patch to support DNS > hosts definition in the network XML description. > > Michal > > Signed-off-by: Michal Novotny > --- > src/libvirt_private.syms | 1 + > src/network/bridge_driver.c | 3 + > src/util/dnsmasq.c | 266 ++++++++++++++++++++++++++++++++++++++++++- > src/util/dnsmasq.h | 22 ++++- > 4 files changed, 287 insertions(+), 5 deletions(-) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 65a86d3..73c3f77 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -186,6 +186,7 @@ virUnrefStream; > > # dnsmasq.h > dnsmasqAddDhcpHost; > +dnsmasqAddHost; > dnsmasqContextFree; > dnsmasqContextNew; > dnsmasqDelete; > diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c > index 41b14f9..4ad3143 100644 > --- a/src/network/bridge_driver.c > +++ b/src/network/bridge_driver.c > @@ -589,6 +589,9 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, > if (dctx->hostsfile->nhosts) > virCommandAddArgPair(cmd, "--dhcp-hostsfile", > dctx->hostsfile->path); > + if (dctx->addnhostsfile->nhosts) > + virCommandAddArgPair(cmd, "--addn-hosts", > + dctx->addnhostsfile->path); > > dnsmasqContextFree(dctx); > } > diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c > index be230e1..fee3b90 100644 > --- a/src/util/dnsmasq.c > +++ b/src/util/dnsmasq.c > @@ -48,6 +48,7 @@ > > #define VIR_FROM_THIS VIR_FROM_NETWORK > #define DNSMASQ_HOSTSFILE_SUFFIX "hostsfile" > +#define DNSMASQ_ADDNHOSTSFILE_SUFFIX "addnhosts" > > static void > dhcphostFree(dnsmasqDhcpHost *host) > @@ -56,6 +57,231 @@ dhcphostFree(dnsmasqDhcpHost *host) > } > > static void > +addnhostFree(dnsmasqAddnHost *host) > +{ > + VIR_FREE(host->hostnames); You haven't freed host->hostnames[0], hostnames[1], etc; you've only freed the array of pointers. > + VIR_FREE(host->ip); > +} > + > +static void > +addnhostsFree(dnsmasqAddnHostsfile *addnhostsfile) > +{ > + unsigned int i; > + > + if (addnhostsfile->hosts) { > + for (i = 0; i< addnhostsfile->nhosts; i++) > + addnhostFree(&addnhostsfile->hosts[i]); > + > + VIR_FREE(addnhostsfile->hosts); > + > + addnhostsfile->nhosts = 0; > + } > + > + VIR_FREE(addnhostsfile->path); > + > + VIR_FREE(addnhostsfile); > +} > + > +static int > +addnhostsAdd(dnsmasqAddnHostsfile *addnhostsfile, > + virSocketAddr *ip, You could also mark ip as a const. > + const char *name) > +{ It looks like this function could be simplified quite a lot if it was changed to take a char** instead of a char* (see my comment in 5/5 about saving it that way in the virNetworkDNSDefPtr). > + char *ipstr = NULL; > + int idx = -1; > + int i; > + > + if (!(ipstr = virSocketFormatAddr(ip))) > + return -1; > + > + for (i = 0; i< addnhostsfile->nhosts; i++) { > + if (STREQ((const char *)addnhostsfile->hosts[i].ip, (const char *)ipstr)) { > + idx = i; > + break; > + } > + } > + > + if (idx< 0) { > + if (VIR_REALLOC_N(addnhostsfile->hosts, addnhostsfile->nhosts + 1)< 0) > + goto alloc_error; > + > + idx = addnhostsfile->nhosts; > + if (VIR_ALLOC(addnhostsfile->hosts[idx].hostnames)< 0) > + goto alloc_error; > + > + if (virAsprintf(&addnhostsfile->hosts[idx].ip, "%s", ipstr)< 0) > + goto alloc_error; > + > + addnhostsfile->hosts[idx].nhostnames = 0; > + addnhostsfile->nhosts++; > + } > + > + if (VIR_REALLOC_N(addnhostsfile->hosts[idx].hostnames, addnhostsfile->hosts[idx].nhostnames + 1)< 0) > + goto alloc_error; > + > + if (virAsprintf(&addnhostsfile->hosts[idx].hostnames[addnhostsfile->hosts[idx].nhostnames], "%s", name)< 0) > + goto alloc_error; > + > + VIR_FREE(ipstr); > + > + addnhostsfile->hosts[idx].nhostnames++; > + > + return 0; > + > + alloc_error: > + virReportOOMError(); > + VIR_FREE(ipstr); > + return -1; > +} > + > +static dnsmasqAddnHostsfile * > +addnhostsNew(const char *name, > + const char *config_dir) > +{ > + int err; > + dnsmasqAddnHostsfile *addnhostsfile; > + > + if (VIR_ALLOC(addnhostsfile)< 0) { > + virReportOOMError(); > + return NULL; > + } > + > + addnhostsfile->hosts = NULL; > + addnhostsfile->nhosts = 0; > + > + if (virAsprintf(&addnhostsfile->path, "%s/%s.%s", config_dir, name, > + DNSMASQ_ADDNHOSTSFILE_SUFFIX)< 0) { > + virReportOOMError(); > + goto error; > + } > + > + if ((err = virFileMakePath(config_dir))) { > + virReportSystemError(err, _("cannot create config directory '%s'"), > + config_dir); > + goto error; > + } > + > + return addnhostsfile; > + > + error: > + addnhostsFree(addnhostsfile); > + return NULL; > +} > + > +static int > +addnhostsWrite(const char *path, > + dnsmasqAddnHost *hosts, > + unsigned int nhosts) > +{ > + char *tmp; > + FILE *f; > + bool istmp = true; > + unsigned int i, ii; > + int rc = 0; > + > + if (nhosts == 0) > + return rc; > + > + if (virAsprintf(&tmp, "%s.new", path)< 0) > + return ENOMEM; > + > + if (!(f = fopen(tmp, "w"))) { > + istmp = false; > + if (!(f = fopen(path, "w"))) { > + rc = errno; > + goto cleanup; > + } > + } > + > + for (i = 0; i< nhosts; i++) { > + if (fputs(hosts[i].ip, f) == EOF || fputc('\t', f) == EOF) { > + rc = errno; > + VIR_FORCE_FCLOSE(f); > + > + if (istmp) > + unlink(tmp); > + > + goto cleanup; > + } > + > + for (ii = 0; ii< hosts[i].nhostnames; ii++) { > + if (fputs(hosts[i].hostnames[ii], f) == EOF || fputc('\t', f) == EOF) { > + rc = errno; > + VIR_FORCE_FCLOSE(f); > + > + if (istmp) > + unlink(tmp); > + > + goto cleanup; > + } > + } > + > + if (fputc('\n', f) == EOF) { > + rc = errno; > + VIR_FORCE_FCLOSE(f); > + > + if (istmp) > + unlink(tmp); > + > + goto cleanup; > + } > + } > + > + if (VIR_FCLOSE(f) == EOF) { > + rc = errno; > + goto cleanup; > + } > + > + if (istmp) { > + if (rename(tmp, path)< 0) { > + rc = errno; > + unlink(tmp); > + goto cleanup; > + } > + > + if (unlink(tmp)< 0) { > + rc = errno; > + goto cleanup; > + } > + } > + > + cleanup: > + VIR_FREE(tmp); > + > + return rc; > +} > + > +static int > +addnhostsSave(dnsmasqAddnHostsfile *addnhostsfile) > +{ > + int err = addnhostsWrite(addnhostsfile->path, addnhostsfile->hosts, > + addnhostsfile->nhosts); > + > + if (err< 0) { > + virReportSystemError(err, _("cannot write config file '%s'"), > + addnhostsfile->path); > + return -1; > + } > + > + return 0; > +} > + > +static int > +addnhostsDelete(dnsmasqAddnHostsfile *addnhostsfile) > +{ > + if (!virFileExists(addnhostsfile->path)) > + return 0; > + > + if (unlink(addnhostsfile->path)< 0) { > + virReportSystemError(errno, _("cannot remove config file '%s'"), > + addnhostsfile->path); > + return -1; > + } > + > + return 0; > +} > + > +static void > hostsfileFree(dnsmasqHostsfile *hostsfile) > { > unsigned int i; > @@ -255,6 +481,8 @@ dnsmasqContextNew(const char *network_name, > > if (!(ctx->hostsfile = hostsfileNew(network_name, config_dir))) > goto error; > + if (!(ctx->addnhostsfile = addnhostsNew(network_name, config_dir))) > + goto error; > > return ctx; > > @@ -277,6 +505,8 @@ dnsmasqContextFree(dnsmasqContext *ctx) > > if (ctx->hostsfile) > hostsfileFree(ctx->hostsfile); > + if (ctx->addnhostsfile) > + addnhostsFree(ctx->addnhostsfile); > > VIR_FREE(ctx); > } > @@ -300,6 +530,24 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx, > hostsfileAdd(ctx->hostsfile, mac, ip, name); > } > > +/* > + * dnsmasqAddHost: > + * @ctx: pointer to the dnsmasq context for each network > + * @ip: pointer to the socket address contains ip of the host > + * @name: pointer to the string contains hostname of the host > + * > + * Add additional host entry. > + */ > + > +void > +dnsmasqAddHost(dnsmasqContext *ctx, > + virSocketAddr *ip, > + const char *name) > +{ > + if (ctx->addnhostsfile) > + addnhostsAdd(ctx->addnhostsfile, ip, name); > +} > + > /** > * dnsmasqSave: > * @ctx: pointer to the dnsmasq context for each network > @@ -309,10 +557,15 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx, > int > dnsmasqSave(const dnsmasqContext *ctx) > { > + int ret1 = 0; > + int ret2 = 0; > + > if (ctx->hostsfile) > - return hostsfileSave(ctx->hostsfile); > + ret1 = hostsfileSave(ctx->hostsfile); > + if (ctx->addnhostsfile) > + ret2 = addnhostsSave(ctx->addnhostsfile); > > - return 0; > + return ((ret1 == 0)&& (ret2 == 0)) ? 0 : -1; > } > > > @@ -325,10 +578,15 @@ dnsmasqSave(const dnsmasqContext *ctx) > int > dnsmasqDelete(const dnsmasqContext *ctx) > { > + int ret1 = 0; > + int ret2 = 0; > + > if (ctx->hostsfile) > - return hostsfileDelete(ctx->hostsfile); > + ret1 = hostsfileDelete(ctx->hostsfile); > + if (ctx->addnhostsfile) > + ret2 = addnhostsDelete(ctx->addnhostsfile); > > - return 0; > + return ((ret1 == 0)&& (ret2 == 0)) ? 0 : -1; > } > > /** > diff --git a/src/util/dnsmasq.h b/src/util/dnsmasq.h > index 02a961f..3f6320a 100644 > --- a/src/util/dnsmasq.h > +++ b/src/util/dnsmasq.h > @@ -44,7 +44,24 @@ typedef struct > > typedef struct > { > - dnsmasqHostsfile *hostsfile; > + unsigned int nhostnames; > + char *ip; > + char **hostnames; > + > +} dnsmasqAddnHost; > + > +typedef struct > +{ > + unsigned int nhosts; > + dnsmasqAddnHost *hosts; > + > + char *path; /* Absolute path of dnsmasq's hostsfile. */ > +} dnsmasqAddnHostsfile; > + > +typedef struct > +{ > + dnsmasqHostsfile *hostsfile; > + dnsmasqAddnHostsfile *addnhostsfile; > } dnsmasqContext; > > dnsmasqContext * dnsmasqContextNew(const char *network_name, > @@ -54,6 +71,9 @@ void dnsmasqAddDhcpHost(dnsmasqContext *ctx, > const char *mac, > virSocketAddr *ip, > const char *name); > +void dnsmasqAddHost(dnsmasqContext *ctx, > + virSocketAddr *ip, > + const char *name); > int dnsmasqSave(const dnsmasqContext *ctx); > int dnsmasqDelete(const dnsmasqContext *ctx); > int dnsmasqReload(pid_t pid); From kamezawa.hiroyu at jp.fujitsu.com Thu Apr 28 02:00:16 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Thu, 28 Apr 2011 11:00:16 +0900 Subject: [libvirt] [PATCHv12 1/3] libvirt/qemu - support persistent modification of devices In-Reply-To: <20110426110624.5ad5a47a.kamezawa.hiroyu@jp.fujitsu.com> References: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> <20110426110624.5ad5a47a.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <20110428110016.fee09940.kamezawa.hiroyu@jp.fujitsu.com> On Tue, 26 Apr 2011 11:06:24 +0900 KAMEZAWA Hiroyuki wrote: > On Fri, 22 Apr 2011 12:07:56 +0900 > KAMEZAWA Hiroyuki wrote: > > > > > Rebased ont the latest git tree, which makes this work easier. > > This series adds support for attach/detach/update disks of domain config. > > Ping ? > I'll take a week of holidays, so, I'll rebuild & repost again a week later. Bye, -Kame From eblake at redhat.com Thu Apr 28 02:57:52 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 27 Apr 2011 20:57:52 -0600 Subject: [libvirt] [PATCH] build: Use pkg-config for libssh2 check In-Reply-To: References: Message-ID: <4DB8D7B0.7030508@redhat.com> On 04/27/2011 04:34 AM, Jiri Denemark wrote: > Currently the build fails if /usr/local/include does not exist since > its use is hardcoded in configure.ac > --- > configure.ac | 86 ++++++++++++++------------------------------------------- > 1 files changed, 21 insertions(+), 65 deletions(-) > > +if test "$with_phyp" = "yes" || test "$with_phyp" = "check"; then > + PKG_CHECK_MODULES(LIBSSH2, libssh2 >= $LIBSSH2_REQUIRED, [ Preferred quoting style: PKG_CHECK_MODULES([LIBSSH2], [libssh2 >= $LIBSSH2_REQUIRED], [ ACK with that nit fixed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 28 02:58:40 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 27 Apr 2011 20:58:40 -0600 Subject: [libvirt] [PATCH] build: Ignore old audit library In-Reply-To: <66ce2a4962feb3e5f2748ab0593772a90e9e9fbd.1303896348.git.jdenemar@redhat.com> References: <66ce2a4962feb3e5f2748ab0593772a90e9e9fbd.1303896348.git.jdenemar@redhat.com> Message-ID: <4DB8D7E0.2040704@redhat.com> On 04/27/2011 03:25 AM, Jiri Denemark wrote: > Check for audit_encode_nv_string in libaudit so that ancient audit > library is ignored rather than trying to compile with libaudit support > and failing. > --- > configure.ac | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/configure.ac b/configure.ac > index 190bf40..25cc15b 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -1026,7 +1026,7 @@ if test "$with_audit" != "no" ; then > LIBS="$LIBS $AUDIT_LIBS" > fail=0 > AC_CHECK_HEADER([libaudit.h], [], [fail=1]) > - AC_CHECK_LIB([audit], [audit_is_enabled], [], [fail=1]) > + AC_CHECK_LIB([audit], [audit_encode_nv_string], [], [fail=1]) ACK, especially since it matches what virtaudit.c requires. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 28 03:08:07 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 27 Apr 2011 21:08:07 -0600 Subject: [libvirt] [PATCH] fix virsh's regression In-Reply-To: <4DB635E8.8020705@cn.fujitsu.com> References: <4DB635E8.8020705@cn.fujitsu.com> Message-ID: <4DB8DA17.9090406@redhat.com> On 04/25/2011 09:03 PM, Wen Congyang wrote: > This patch does the following things: > 1. The return value of cmdSchedInfoUpdate() can be -1, 0 and 1. So the > type of return value should be int not bool.(This function is not a > entry of a virsh command, but the name of this function likes cmdXXX) Phooey - mass replacement makes for a patch that's too hard to review, and indeed snuck in this regression. > > 2. The type of cmdSchedinfo()'s, cmdFreecell()'s, cmdPoolList()'s and > cmdVolList()'s return value is bool not int, so change the type of > variable ret_val, func_ret and functionReturn. Not quite as serious (int holds bool), but still worth fixing. > > 3. Add a variable functionReturn for cmdMigrate(), cmdAttachInterface(), > cmdDetachInterface(), cmdAttachDisk() and cmdDetachDisk() to save the > return value. > > 4. Change the type of variable ret in the function cmdAttachDevice(), > cmdDetachDevice(), cmdUpdateDevice(), cmdAttachInterface(), > cmdDetachInterface(), cmdAttachDisk() and cmdDetachDisk() to int, as > we use it to save the return value of virXXX() and the type of virXXX()'s > return value is int not bool. Also a regression. Thanks for catching these. > > 5. Do some cleanup when virBuff.error is 1. > > The bug 1-4 were introduced by commit b56fa5bb. > > --- > tools/virsh.c | 63 +++++++++++++++++++++++++++++--------------------------- > 1 files changed, 33 insertions(+), 30 deletions(-) ACK. And I'm glad I pushed my patch as early as I did in the release cycle, to let us catch these sort of issues pre-release. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 28 03:15:02 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 27 Apr 2011 21:15:02 -0600 Subject: [libvirt] [PATCH] util: Initialize hooks at daemon shutdown if no hooks defined In-Reply-To: <1303727315-20801-1-git-send-email-jyang@redhat.com> References: <1303727315-20801-1-git-send-email-jyang@redhat.com> Message-ID: <4DB8DBB6.7090906@redhat.com> On 04/25/2011 04:28 AM, Osier Yang wrote: > We support to initialize the hooks at daemon reload if there is no > hooks script is defined, should we also support initialize the hooks s/should we/we should/ > at daemon shutdown if no hooks is defined? s/\?/./ (that is, frame this as a statement, not a question) > > To address bz: https://bugzilla.redhat.com/show_bug.cgi?id=688859 > --- > src/util/hooks.c | 3 ++- > 1 files changed, 2 insertions(+), 1 deletions(-) > > diff --git a/src/util/hooks.c b/src/util/hooks.c > index a409d77..30e20ac 100644 > --- a/src/util/hooks.c > +++ b/src/util/hooks.c > @@ -209,7 +209,8 @@ virHookCall(int driver, const char *id, int op, int sub_op, const char *extra, > */ > if ((virHooksFound == -1) || > ((driver == VIR_HOOK_DRIVER_DAEMON) && > - (op == VIR_HOOK_DAEMON_OP_RELOAD))) > + (op == VIR_HOOK_DAEMON_OP_RELOAD || > + op == VIR_HOOK_DAEMON_OP_SHUTDOWN))) > virHookInitialize(); ACK; looks like a reasonable fix for the mentioned bugzilla. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 28 03:37:18 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 27 Apr 2011 21:37:18 -0600 Subject: [libvirt] [PATCHv12 1/3] libvirt/qemu - support persistent modification of devices In-Reply-To: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> References: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4DB8E0EE.1010209@redhat.com> On 04/21/2011 09:07 PM, KAMEZAWA Hiroyuki wrote: > > Rebased ont the latest git tree, which makes this work easier. s/ont/onto/ > This series adds support for attach/detach/update disks of domain config. > == > This patch adds functions for modify domain's persistent definition. > To do error recovery in easy way, we use a copy of vmdef and update it. > > The whole sequence will be: > > make a copy of domain definition. > > if (flags & MODIFY_CONFIG) > update copied domain definition > if (flags & MODIF_LIVE) > do hotplug. > if (no error) > save copied one to the file and update cached definition. > else > discard copied definition. > > This patch is mixuture of Eric Blake's work and mine. > From: Eric Blake > Signed-off-by: KAMEZAWA Hiroyuki > > Changelog: v11 -> v12 > - rebased and fixed hunks. > - renamed qemudDomain....to qemuDomain... > > (virDomainObjCopyPersistentDef): make a copy of persistent vm definition > (qemuDomainAttach/Detach/UpdateDeviceConfig) : callbacks. now empty > (qemuDomainModifyDeviceFlags): add support for MODIFY_CONFIG and MODIFY_CURRENT > --- > src/conf/domain_conf.c | 18 ++++++ > src/conf/domain_conf.h | 3 + > src/libvirt_private.syms | 1 + > src/qemu/qemu_driver.c | 147 ++++++++++++++++++++++++++++++++++++---------- > 4 files changed, 137 insertions(+), 32 deletions(-) > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index 381e692..6c1098a 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -9509,3 +9509,21 @@ cleanup: > > return ret; > } > + > + > +virDomainDefPtr > +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom) > +{ > + char *xml; > + virDomainDefPtr cur, ret; > + > + cur = virDomainObjGetPersistentDef(caps, dom); > + > + xml = virDomainDefFormat(cur, VIR_DOMAIN_XML_WRITE_FLAGS); > + if (!xml) > + return NULL; > + > + ret = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS); Cute. Maybe not the most efficient, but very compact addition :) > + > + return ret; But, it leaks xml. > +} > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > index 6ea30b9..ddf111a 100644 > --- a/src/conf/domain_conf.h > +++ b/src/conf/domain_conf.h > @@ -1288,6 +1288,9 @@ int virDomainObjSetDefTransient(virCapsPtr caps, > virDomainDefPtr > virDomainObjGetPersistentDef(virCapsPtr caps, > virDomainObjPtr domain); > +virDomainDefPtr > +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom); > + > void virDomainRemoveInactive(virDomainObjListPtr doms, > virDomainObjPtr dom); > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index ba7739d..f732431 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -287,6 +287,7 @@ virDomainMemballoonModelTypeToString; > virDomainNetDefFree; > virDomainNetTypeToString; > virDomainObjAssignDef; > +virDomainObjCopyPersistentDef; > virDomainObjSetDefTransient; > virDomainObjGetPersistentDef; Pre-existing unsorted line. Beyond that, it looks right to me. ACK! I squashed this in, then pushed. diff --git i/src/conf/domain_conf.c w/src/conf/domain_conf.c index 2d413e7..691e50e 100644 --- i/src/conf/domain_conf.c +++ w/src/conf/domain_conf.c @@ -9526,5 +9526,6 @@ virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom) ret = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS); + VIR_FREE(xml); return ret; } diff --git i/src/libvirt_private.syms w/src/libvirt_private.syms index 52d7b02..579c62f 100644 --- i/src/libvirt_private.syms +++ w/src/libvirt_private.syms @@ -288,7 +288,6 @@ virDomainNetDefFree; virDomainNetTypeToString; virDomainObjAssignDef; virDomainObjCopyPersistentDef; -virDomainObjSetDefTransient; virDomainObjGetPersistentDef; virDomainObjIsDuplicate; virDomainObjListDeinit; @@ -298,6 +297,7 @@ virDomainObjListInit; virDomainObjListNumOfDomains; virDomainObjLock; virDomainObjRef; +virDomainObjSetDefTransient; virDomainObjUnlock; virDomainObjUnref; virDomainRemoveInactive; -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From kamezawa.hiroyu at jp.fujitsu.com Thu Apr 28 03:33:36 2011 From: kamezawa.hiroyu at jp.fujitsu.com (KAMEZAWA Hiroyuki) Date: Thu, 28 Apr 2011 12:33:36 +0900 Subject: [libvirt] [PATCHv12 1/3] libvirt/qemu - support persistent modification of devices In-Reply-To: <4DB8E0EE.1010209@redhat.com> References: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> <4DB8E0EE.1010209@redhat.com> Message-ID: <20110428123336.0b557fc6.kamezawa.hiroyu@jp.fujitsu.com> On Wed, 27 Apr 2011 21:37:18 -0600 Eric Blake wrote: > Pre-existing unsorted line. > > Beyond that, it looks right to me. ACK! > > I squashed this in, then pushed. > Thank you!. I need to reduce careless misses... From eblake at redhat.com Thu Apr 28 03:50:05 2011 From: eblake at redhat.com (Eric Blake) Date: Wed, 27 Apr 2011 21:50:05 -0600 Subject: [libvirt] [PATCHv12 2/3] libvirt/qemu - support persistent attach/detach disks In-Reply-To: <20110422120932.0a2ed23c.kamezawa.hiroyu@jp.fujitsu.com> References: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> <20110422120932.0a2ed23c.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4DB8E3ED.8090601@redhat.com> On 04/21/2011 09:09 PM, KAMEZAWA Hiroyuki wrote: > Support changes of disks by MODIFY_CONFIG for qemu. > > This patch includes patches for qemu's disk to support > virDomainAt(De)tachDeviceFlags with VIR_DOMAIN_DEVICE_MODIFY_CONFIG. > > Other devices can be added inrecemtaly. s/inrecemtaly/incrementally/ ACK and pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From veillard at redhat.com Thu Apr 28 03:51:15 2011 From: veillard at redhat.com (Daniel Veillard) Date: Thu, 28 Apr 2011 11:51:15 +0800 Subject: [libvirt] Libvirt 0.9.1 week freeze, RC1 version to test Message-ID: <20110428035115.GA21035@redhat.com> So we are entering the week freeze for the new version. I have made an rc1 tarball available at: ftp://libvirt.org/libvirt/libvirt-0.9.1-rc1.tar.gz I have tried it locally and basic operations seems to work fine, please give it a try too, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From wency at cn.fujitsu.com Thu Apr 28 04:38:30 2011 From: wency at cn.fujitsu.com (Wen Congyang) Date: Thu, 28 Apr 2011 12:38:30 +0800 Subject: [libvirt] [PATCH] fix virsh's regression In-Reply-To: <4DB8DA17.9090406@redhat.com> References: <4DB635E8.8020705@cn.fujitsu.com> <4DB8DA17.9090406@redhat.com> Message-ID: <4DB8EF46.4000401@cn.fujitsu.com> At 04/28/2011 11:08 AM, Eric Blake Write: > On 04/25/2011 09:03 PM, Wen Congyang wrote: >> This patch does the following things: >> 1. The return value of cmdSchedInfoUpdate() can be -1, 0 and 1. So the >> type of return value should be int not bool.(This function is not a >> entry of a virsh command, but the name of this function likes cmdXXX) > > Phooey - mass replacement makes for a patch that's too hard to review, > and indeed snuck in this regression. > >> >> 2. The type of cmdSchedinfo()'s, cmdFreecell()'s, cmdPoolList()'s and >> cmdVolList()'s return value is bool not int, so change the type of >> variable ret_val, func_ret and functionReturn. > > Not quite as serious (int holds bool), but still worth fixing. > >> >> 3. Add a variable functionReturn for cmdMigrate(), cmdAttachInterface(), >> cmdDetachInterface(), cmdAttachDisk() and cmdDetachDisk() to save the >> return value. >> >> 4. Change the type of variable ret in the function cmdAttachDevice(), >> cmdDetachDevice(), cmdUpdateDevice(), cmdAttachInterface(), >> cmdDetachInterface(), cmdAttachDisk() and cmdDetachDisk() to int, as >> we use it to save the return value of virXXX() and the type of virXXX()'s >> return value is int not bool. > > Also a regression. Thanks for catching these. > >> >> 5. Do some cleanup when virBuff.error is 1. >> >> The bug 1-4 were introduced by commit b56fa5bb. >> >> --- >> tools/virsh.c | 63 +++++++++++++++++++++++++++++--------------------------- >> 1 files changed, 33 insertions(+), 30 deletions(-) > > ACK. And I'm glad I pushed my patch as early as I did in the release > cycle, to let us catch these sort of issues pre-release. Thanks, pushed. > From laine at laine.org Thu Apr 28 06:28:09 2011 From: laine at laine.org (Laine Stump) Date: Thu, 28 Apr 2011 02:28:09 -0400 Subject: [libvirt] [PATCH] network: fix return value of hostsFileWrite Message-ID: <1303972089-10631-1-git-send-email-laine@laine.org> The lone caller to hostsFileWrite (and the callers for at least 3 levels up the return stack) assume that the return value will be < 0 on failure. However, hostsFileWrite returns 0 on success, and a positive errno on failure. This patch changes hostsFileWrite to return -errno on failure. --- src/util/dnsmasq.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c index be230e1..2ba9355 100644 --- a/src/util/dnsmasq.c +++ b/src/util/dnsmasq.c @@ -159,19 +159,19 @@ hostsfileWrite(const char *path, return rc; if (virAsprintf(&tmp, "%s.new", path) < 0) - return ENOMEM; + return -ENOMEM; if (!(f = fopen(tmp, "w"))) { istmp = false; if (!(f = fopen(path, "w"))) { - rc = errno; + rc = -errno; goto cleanup; } } for (i = 0; i < nhosts; i++) { if (fputs(hosts[i].host, f) == EOF || fputc('\n', f) == EOF) { - rc = errno; + rc = -errno; VIR_FORCE_FCLOSE(f); if (istmp) @@ -182,19 +182,19 @@ hostsfileWrite(const char *path, } if (VIR_FCLOSE(f) == EOF) { - rc = errno; + rc = -errno; goto cleanup; } if (istmp) { if (rename(tmp, path) < 0) { - rc = errno; + rc = -errno; unlink(tmp); goto cleanup; } if (unlink(tmp) < 0) { - rc = errno; + rc = -errno; goto cleanup; } } -- 1.7.3.4 From jyang at redhat.com Thu Apr 28 06:50:12 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 28 Apr 2011 14:50:12 +0800 Subject: [libvirt] [PATCH] util: Initialize hooks at daemon shutdown if no hooks defined In-Reply-To: <4DB8DBB6.7090906@redhat.com> References: <1303727315-20801-1-git-send-email-jyang@redhat.com> <4DB8DBB6.7090906@redhat.com> Message-ID: <4DB90E24.2070407@redhat.com> ? 2011?04?28? 11:15, Eric Blake ??: > On 04/25/2011 04:28 AM, Osier Yang wrote: >> We support to initialize the hooks at daemon reload if there is no >> hooks script is defined, should we also support initialize the hooks > > s/should we/we should/ > >> at daemon shutdown if no hooks is defined? > > s/\?/./ > > (that is, frame this as a statement, not a question) > >> >> To address bz: https://bugzilla.redhat.com/show_bug.cgi?id=688859 >> --- >> src/util/hooks.c | 3 ++- >> 1 files changed, 2 insertions(+), 1 deletions(-) >> >> diff --git a/src/util/hooks.c b/src/util/hooks.c >> index a409d77..30e20ac 100644 >> --- a/src/util/hooks.c >> +++ b/src/util/hooks.c >> @@ -209,7 +209,8 @@ virHookCall(int driver, const char *id, int op, int sub_op, const char *extra, >> */ >> if ((virHooksFound == -1) || >> ((driver == VIR_HOOK_DRIVER_DAEMON)&& >> - (op == VIR_HOOK_DAEMON_OP_RELOAD))) >> + (op == VIR_HOOK_DAEMON_OP_RELOAD || >> + op == VIR_HOOK_DAEMON_OP_SHUTDOWN))) >> virHookInitialize(); > > ACK; looks like a reasonable fix for the mentioned bugzilla. > Thanks, applied with changing on the patch description. Regards Osier From jyang at redhat.com Thu Apr 28 07:00:28 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 28 Apr 2011 15:00:28 +0800 Subject: [libvirt] [PATCH V3] xen: check if device is assigned to guest before reattaching In-Reply-To: <1303906152-4601-1-git-send-email-yuzhang@redhat.com> References: <1303906152-4601-1-git-send-email-yuzhang@redhat.com> Message-ID: <4DB9108C.4090804@redhat.com> ? 2011?04?27? 20:09, Yufang Zhang ??: > Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=664059 > > This is the version3 patch for BZ#664059. Reattaching pci device back to > host without destroying guest or detaching device from guest would cause > host to crash. This patch adds a check before doing device reattach. If > the device is being assigned to guest, libvirt refuses to reattach device > to host. The patch only works for Xen, for it just checks xenstore to get > pci device information. This version fixes some formatting problem and moves > lock-unlock out of loop so that the check is atomic. We have same problem with qemu driver, though this patch looks fine and fix the problem for xen driver, IMHO it's not the ideal solution, ideally it will be nice if kernel could let us known if the device is still in use. I filed bug against kernel, no feedback yet though. > > Signed-off-by: Yufang Zhang > --- > src/xen/xen_driver.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 67 insertions(+), 0 deletions(-) > > diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c > index 2a07b7b..dd94fbc 100644 > --- a/src/xen/xen_driver.c > +++ b/src/xen/xen_driver.c > @@ -1927,11 +1927,70 @@ out: > } > > static int > +xenUnifiedNodeDeviceAssignedDomainId (virNodeDevicePtr dev) > +{ > + int numdomains; > + int ret = -1, i; > + int *ids = NULL; > + char *bdf = NULL; > + char *xref = NULL; > + unsigned int domain, bus, slot, function; > + virConnectPtr conn = dev->conn; > + xenUnifiedPrivatePtr priv = conn->privateData; > + > + /* Get active domains */ > + numdomains = xenUnifiedNumOfDomains(conn); > + if (numdomains< 0) { > + return ret; > + } > + if (numdomains> 0){ > + if (VIR_ALLOC_N(ids, numdomains)< 0) { > + virReportOOMError(); > + goto out; > + } > + if ((numdomains = xenUnifiedListDomains(conn,&ids[0], numdomains))< 0) { > + goto out; > + } > + } > + > + /* Get pci bdf */ > + if (xenUnifiedNodeDeviceGetPciInfo(dev,&domain,&bus,&slot,&function)< 0) > + goto out; > + > + if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x", > + domain, bus, slot, function)< 0) { > + virReportOOMError(); > + goto out; > + } > + > + xenUnifiedLock(priv); > + /* Check if bdf is assigned to one of active domains */ > + for (i = 0; i< numdomains; i++ ) { > + xref = xenStoreDomainGetPCIID(conn, ids[i], bdf); > + if (xref == NULL) { > + continue; > + } else { > + ret = ids[i]; > + break; > + } > + } > + xenUnifiedUnlock(priv); > + > + VIR_FREE(xref); > + VIR_FREE(bdf); > +out: > + VIR_FREE(ids); > + > + return ret; > +} > + > +static int > xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev) > { > pciDevice *pci; > unsigned domain, bus, slot, function; > int ret = -1; > + int domid; > > if (xenUnifiedNodeDeviceGetPciInfo(dev,&domain,&bus,&slot,&function)< 0) > return -1; > @@ -1940,6 +1999,14 @@ xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev) > if (!pci) > return -1; > > + /* Check if device is assigned to an active guest */ > + if ((domid = xenUnifiedNodeDeviceAssignedDomainId(dev))>= 0) { > + xenUnifiedError(VIR_ERR_INTERNAL_ERROR, > + _("Device %s has been assigned to guest %d"), > + dev->name, domid); > + goto out; > + } > + > if (pciReAttachDevice(pci, NULL)< 0) > goto out; > From matthias.bolte at googlemail.com Thu Apr 28 07:33:45 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Thu, 28 Apr 2011 09:33:45 +0200 Subject: [libvirt] [Libvirt-announce] Libvirt 0.9.1 week freeze, RC1 version to test In-Reply-To: <20110428035115.GA21035@redhat.com> References: <20110428035115.GA21035@redhat.com> Message-ID: 2011/4/28 Daniel Veillard : > ?So we are entering the week freeze for the new version. > I have made an rc1 tarball available at: > ?ftp://libvirt.org/libvirt/libvirt-0.9.1-rc1.tar.gz > > ?I have tried it locally and basic operations seems to work fine, > please give it a try too, > > ?thanks ! > > Daniel Testing on mingw. libvirt compiles fine but virsh has a warning about vfprintf: virsh.c: In function 'vshDebug': virsh.c:12105:5: warning: function might be possible candidate for 'ms_printf' format attribute [-Wmissing-format-attribute] I'm no sure where to fix that. make check shows two warnings in gnulib. Maybe Eric wants to take a look: getsockopt.c: In function 'rpl_getsockopt': getsockopt.c:51:7: warning: passing argument 4 of 'getsockopt' from incompatible pointer type c:\dev\msys_setup\mingw\bin\../lib/gcc/mingw32/4.5.0/../../../../include/winsock2.h:543:32: note: expected 'char *' but argument is of type 'int *' test-getaddrinfo.c:28:1: warning: initialization from incompatible pointer type Aside from that the rest seems to work fine. Matthias From laine at laine.org Thu Apr 28 07:52:17 2011 From: laine at laine.org (Laine Stump) Date: Thu, 28 Apr 2011 03:52:17 -0400 Subject: [libvirt] RFC: disconnecting guest/domain interface config from host config (aka migration with macvtap) In-Reply-To: <4DA47A44.8040307@laine.org> References: <4DA47A44.8040307@laine.org> Message-ID: <4DB91CB1.1060502@laine.org> On 04/27/2011 09:58 AM, Oved Ourfalli wrote: > Laine, hello. > > We read your proposal for abstraction of guest<--> host network > connection in libvirt. > > You has an open issue there regarding the vepa/vnlink attributes: > "3) What about the parameters in the element that are > currently used by vepa/vnlink. Do those belong with the host, or with > the guest?" > > The parameters for the virtualport element should be on the guest, and > not the host, because a specific interface can run multiple profiles, Are you talking about host interface or guest interface? If you mean that multiple different profiles can be used when connecting to a particular switch - as long as there are only a few different profiles, rather than each guest having its own unique profile, then it still seems better to have the port profile live with the network definition (and just define multiple networks, one for each port profile). > so it will be a mistake to define a profile to be interface specific > on the host. Moreover, putting it in the guest level will enable us in > the future (if supported by libvirt/qemu) to migrate a vm from a host > with vepa/vnlink interfaces, to another host with a bridge, for example. It seems to me like doing exactly the opposite would make it easier to migrate to a host that used a different kind of switching (from vepa to vnlink, or from a bridged interface to vepa, etc), since the port profile required for a particular host's network would be at the host waiting to be used. > So, in the networks at the host level you will have: > > red-network > > > > eth0 > ..... > > > eth4 > ..... > > > eth18 > ..... > > > > > > And in the guest you will have (for vepa): > > > > instanceid="09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f"/> > > > > Or (for vnlink): > > > > > > This illustrates the problem I was wondering about - in your example it would not be possible for the guest to migrate from the host using a vepa switch to the host using a vnlink switch (and it would be possible to migrate to a host using a standard bridge only if the virtualport element was ignored). If the virtualport element lived with the network definition of red-network on each host, it could be migrated without problem. The only problematic thing would be if any of the attributes within was unique for each guest (I don't know anything about the individual attributes, but "instanceid" sounds like it might be different for each guest). > Then, when migrating from a vepa/vnlink host to another vepa/vnlink > host containing red-network, the profile attributes will be available > at the guest domain xml. > In case the target host has a red-network, which isn't vepa/vnlink, we > want to be able to choose whether to make the use of the profile > attributes optional (i.e., libvirt won't fail in case of migrating to > a network of another type), or mandatory (i.e., libvirt will fail in > case of migration to a non-vepa/vnlink network). > > We have something similar in CPU flags: > > qemu64 > > > In this analogy, does "CPU flags" == "mode (vepa/vnlink/bridge)" or does "CPU flags" == "virtualport parameters" ? It seems like what you're wanting can be satisfied by simply not defining "red-network" on the hosts that don't have the proper networking setup available (maybe what you *really* want to call it is "red-vnlink-network"). From jyang at redhat.com Thu Apr 28 07:52:59 2011 From: jyang at redhat.com (Osier Yang) Date: Thu, 28 Apr 2011 15:52:59 +0800 Subject: [libvirt] Libvirt 0.9.1 week freeze, RC1 version to test In-Reply-To: <20110428035115.GA21035@redhat.com> References: <20110428035115.GA21035@redhat.com> Message-ID: <4DB91CDB.8080900@redhat.com> ? 2011?04?28? 11:51, Daniel Veillard ??: > So we are entering the week freeze for the new version. > I have made an rc1 tarball available at: > ftp://libvirt.org/libvirt/libvirt-0.9.1-rc1.tar.gz > > I have tried it locally and basic operations seems to work fine, > please give it a try too, > > thanks ! > > Daniel > Works fine on my FC14, except once one defines a lxc domain, there is errors always in libvirtd log. 15:42:29.547: 3632: error : lxcMonitorClient:1151 : Failed to connect to client socket: No such file or directory 15:42:29.547: 3632: error : lxcMonitorClient:1151 : Failed to connect to client socket: No such file or directory Caused by lxcStartup tries to reconnect to the lxc domains, regardsless of if the domain is active or not. I'm fixing it. Osier From rjones at redhat.com Thu Apr 28 10:18:36 2011 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 28 Apr 2011 11:18:36 +0100 Subject: [libvirt] [virt-tools-list] RFC: virt-xml: command line tool for altering guest configuration In-Reply-To: <4DB81E8B.3010503@redhat.com> References: <4DB81E8B.3010503@redhat.com> Message-ID: <20110428101836.GA5093@amd.home.annexia.org> Justin, how does the below affect plans to modify/fix virsh in libvirt? On Wed, Apr 27, 2011 at 09:47:55AM -0400, Cole Robinson wrote: > Hi all, > > Attached is a patch to virtinst.git that provides a new tool named > virt-xml. virt-xml provides a scriptable command line interface for > editing libvirt guest XML. > > A couple examples: > > Change boot order and boot menu for 'myguest': > $ ./virt-xml --guest myguest --boot network,hd,cdrom,menu=on > Requested changes: > --- Original XML > +++ New XML > @@ -10,6 +10,8 @@ > > hvm > /usr/lib/xen/boot/hvmloader > + > + > > + > > > > > Change disk #7 to use cache=none for 'myguest': > $ ./virt-xml --guest myguest --device 7 --disk cache=none > Requested changes: > --- Original XML > +++ New XML > @@ -74,6 +74,7 @@ > > > > + > > > > > > Change watchdog action for 'myguest': > $ ./virt-xml --guest myguest --device 1 --watchdog action=pause > Requested changes: > --- Original XML > +++ New XML > @@ -220,7 +220,7 @@ >
    > > > - > + > > > > > > --boot, --disk, and --watchdog come straight from virt-install, see man > virt-install for detailed docs of the option format. Those options shown > are the only things wired up right now, but it's a straightforward task > to wire up most of the relevant remaining virt-install opts. Also the > tool doesn't actually apply the changes yet, but that is also a trivial > addition. I think the interesting bit here is nailing down the scope of > the tool and deciding on good CLI syntax. > > Not sure if we should do hotplug/hotunplug as a subcommand or just > another option like: > > virt-xml ... --hotplug --disk /tmp/foo.img > > Also not really sure how to hotunplug using the --device syntax of the above > examples: > > virt-xml ... --hotunplug --device 1 --disk > > We could make --device just an option to whatever device string the user > gives > > virt-xml ... --hotunplug --disk id=1 > > We can easily allow different XML input methods like: > > virt-xml --guestxml file.xml ... > > or even batch processing > > virt-xml --guest * ... > > Maybe even have allow more intelligence about what guests we edit, say > we want to set cache=none for all disk devices, not CDROM or floppy > (this would take a bit of work to sort out). > > virt-xml --guest * --disk match,device=disk --disk cache=none > > Then there is also the question of extending the tool to also edit other XML > like storage, network, interface, etc. > > Any recommendations appreciated: option syntax, future capabilities, or even a > better name for the tool :) > > A quick word about why I think we should do this with a separate tool rather > than virsh. For starters, I think the need for this functionality on the > command line is clear by now, so it's just a question of where to implement it. > > Why not virsh? Text and command line processing in C is a serious pain > compared to a higher level language like python. I don't think this is a > controversial statement, in fact I think it's partly responsible for why the > virsh XML building commands have typically been in a pretty sorry state. virsh > could conceivably use the internal domain_conf API to make this task much > easier, but it would still require a lot of command line options for every XML > parameter. > > In contrast, virt-install already needs to do most of this command line > processing, and virt-manager needs to do all the XML building, parsing, and > editing. Since this code already lives in one place (virtinst), it's almost > trivial for us to reuse it. Supporting a new XML property on the command line > is a very simple task and will immediately benefit both virt-install and > virt-xml. We also already have over 75% of the domain XML schema available via > existing CLI options that are already documented :) > > Questions or comments appreciated! > > Thanks, > Cole > >From cd821fe259734767619ccb4ca3001df0667c3aed Mon Sep 17 00:00:00 2001 > From: Cole Robinson > Date: Thu, 21 Apr 2011 13:13:49 -0400 > Subject: [PATCH] virt-xml initial commit > > --- > tests/pylint-virtinst.sh | 2 +- > todo.txt | 12 +++ > virt-xml | 200 ++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 213 insertions(+), 1 deletions(-) > create mode 100644 todo.txt > create mode 100755 virt-xml > > diff --git a/tests/pylint-virtinst.sh b/tests/pylint-virtinst.sh > index 7c2a932..98c42fa 100755 > --- a/tests/pylint-virtinst.sh > +++ b/tests/pylint-virtinst.sh > @@ -1,6 +1,6 @@ > #!/bin/sh > > -FILES="setup.py tests/ virt-install virt-image virt-clone virt-convert virtinst/ virtconv virtconv/parsers/*.py" > +FILES="setup.py tests/ virt-install virt-image virt-clone virt-convert virt-xml virtinst/ virtconv virtconv/parsers/*.py" > > # Don't print pylint config warning > NO_PYL_CONFIG=".*No config file found.*" > diff --git a/todo.txt b/todo.txt > new file mode 100644 > index 0000000..9705a43 > --- /dev/null > +++ b/todo.txt > @@ -0,0 +1,12 @@ > + > +virt-xml: > + change commands: > + add device > + remove device > + edit device > + targets: > + --conn URI --guest GUESTNAME > + --conn URI --guestfile file.xml > + other opts: > + --diff (just print diff) > + --print-xml (just print new XML) > diff --git a/virt-xml b/virt-xml > new file mode 100755 > index 0000000..9369991 > --- /dev/null > +++ b/virt-xml > @@ -0,0 +1,200 @@ > +#!/usr/bin/python -tt > +# > +# Copyright 2011 Red Hat, Inc. > +# Cole Robinson > +# > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 2 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write to the Free Software > +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, > +# MA 02110-1301 USA. > + > +import sys > +import logging > +import optparse > + > +import libvirt > +import virtinst > +import virtinst.CapabilitiesParser > +import virtinst.cli as cli > +import virtinst.support as support > +from virtinst.VirtualCharDevice import VirtualCharDevice > +from virtinst.VirtualDevice import VirtualDevice > +from virtinst.cli import fail, print_stdout, print_stderr > +import difflib > + > +cli.setupGettext() > + > +def diff(orig, new): > + """ > + Return a unified diff string between the passed strings > + """ > + return "".join(difflib.unified_diff(orig.splitlines(1), > + new.splitlines(1), > + fromfile="Original XML", > + tofile="New XML")) > + > +######################### > +# XML altering # > +######################### > + > +def change_devices(guest, options): > + devmap = { > + VirtualDevice.VIRTUAL_DEV_DISK : options.diskopts, > + VirtualDevice.VIRTUAL_DEV_WATCHDOG : options.watchdog, > + } > + > + if not any(devmap.values()): > + return > + > + if sum(map(int, map(bool, devmap.values()))) > 1: > + fail(_("Only one device can be changed at a time")) > + > + if options.device is None: > + fail(_("A --device must be specified if altering an existing device")) > + if options.device < 1: > + fail(_("--device must be greater than 1")) > + > + dev = None > + try: > + for devtype, devstr in devmap.items(): > + if devstr: > + dev = guest.get_devices(devtype)[options.device - 1] > + break > + except Exception, e: > + cli.log_exception() > + fail(_("Didn't find requested device: %s" % e)) > + > + if options.diskopts: > + cli.parse_disk(guest, options.diskopts, dev) > + elif options.watchdog: > + cli.parse_watchdog(guest, options.watchdog, dev) > + > + > +################## > +# main() helpers # > +################## > + > +def get_xml_flags(vm): > + flags = 0 > + if support.check_domain_support(vm, support.SUPPORT_DOMAIN_XML_INACTIVE): > + flags |= libvirt.VIR_DOMAIN_XML_INACTIVE > + else: > + logging.debug("Domain XML inactive flag not supported.") > + > + if support.check_domain_support(vm, support.SUPPORT_DOMAIN_XML_SECURE): > + flags |= libvirt.VIR_DOMAIN_XML_SECURE > + else: > + logging.debug("Domain XML secure flag not supported.") > + > + return flags > + > +def build_guest(conn, guestname): > + try: > + vm = conn.lookupByName(guestname) > + except Exception, e: > + fail(_("Error fetching domain '%s': %s") % (guestname, e)) > + > + try: > + flags = get_xml_flags(vm) > + except Exception, e: > + cli.log_exception() > + fail(_("Error determining XML flags for '%s': %s") % (guestname, e)) > + > + try: > + xml = vm.XMLDesc(flags) > + except Exception, e: > + fail(_("Error fetching XML for '%s': %s") % (guestname, e)) > + > + logging.debug("Original XML:\n%s" % xml) > + > + try: > + return virtinst.Guest(connection=conn, parsexml=xml) > + except Exception, e: > + cli.log_exception() > + fail(_("Error parsing '%s' XML: %s") % (guestname, e)) > + > +def parse_args(): > + usage = "%prog " > + parser = cli.setupParser(usage) > + cli.add_connect_option(parser) > + > + parser.add_option("-g", "--guest", dest="guest", > + help=_("Name of guest to alter")) > + > + > + gstg = optparse.OptionGroup(parser, _("Guest Configuration")) > + gstg.add_option("", "--boot", dest="bootopts", > + help=_("Configure boot order, menu, permanent kernel " > + "boot, etc.")) > + parser.add_option_group(gstg) > + > + devg = optparse.OptionGroup(parser, _("Device Configuration")) > + devg.add_option("", "--device", type="int", dest="device", > + help=_("Device index")) > + > + devg.add_option("", "--disk", dest="diskopts", > + help=_("Specify disk device with various options. Ex.\n" > + "--disk path=/my/existing/disk\n" > + "--disk path=/my/new/disk,size=5 (in gigabytes)\n" > + "--disk vol=poolname:volname,device=cdrom,bus=scsi,...")) > + > + devg.add_option("", "--watchdog", dest="watchdog", > + help=_("Configure a watchdog device")) > + parser.add_option_group(devg) > + > + misc = optparse.OptionGroup(parser, _("Miscellaneous Options")) > + misc.add_option("-d", "--debug", action="store_true", dest="debug", > + help=_("Print debugging information")) > + parser.add_option_group(misc) > + > + (options, cliargs) = parser.parse_args() > + return options, cliargs > + > +def main(): > + cli.earlyLogging() > + options, cliargs = parse_args() > + cli.setupLogging("virt-xml", options.debug) > + > + if cliargs: > + fail(_("Unknown argument '%s'") % cliargs[0]) > + > + if not options.guest: > + fail(_("--guest must be specified")) > + > + conn = cli.getConnection(options.connect) > + guest = build_guest(conn, options.guest) > + origxml = guest.get_xml_config() > + > + change_devices(guest, options) > + cli.parse_boot(guest, options.bootopts) > + > + newxml = guest.get_xml_config() > + diffstr = diff(origxml, newxml) > + > + if diffstr: > + print_stdout(_("Requested changes:") + "\n" + diffstr) > + else: > + print_stdout(_("No configuration changes were generated")) > + > + return 0 > + > +if __name__ == "__main__": > + try: > + sys.exit(main()) > + except SystemExit, sys_e: > + sys.exit(sys_e.code) > + except KeyboardInterrupt: > + cli.log_exception() > + print_stderr(_("Installation aborted at user request")) > + except Exception, main_e: > + fail(main_e) > -- > 1.7.4 > Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From jclift at redhat.com Thu Apr 28 10:40:54 2011 From: jclift at redhat.com (Justin Clift) Date: Thu, 28 Apr 2011 20:40:54 +1000 Subject: [libvirt] [virt-tools-list] RFC: virt-xml: command line tool for altering guest configuration In-Reply-To: <20110428101836.GA5093@amd.home.annexia.org> References: <4DB81E8B.3010503@redhat.com> <20110428101836.GA5093@amd.home.annexia.org> Message-ID: <23C2892F-47C2-453D-B678-E0859FAB2D32@redhat.com> On 28/04/2011, at 8:18 PM, Richard W.M. Jones wrote: > Justin, how does the below affect plans to modify/fix virsh in > libvirt? Good question, but I'm no longer the correct person to ask. My focus is 100% Aeolus these days, so I haven't been keeping any kind of tabs on virsh. My initial impression of virt-xml is that it's a very good idea though, and well worth continuing. :) Regards and best wishes, Justin Clift -- Aeolus Community Manager http://www.aeolusproject.org From jdenemar at redhat.com Thu Apr 28 12:36:42 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Thu, 28 Apr 2011 14:36:42 +0200 Subject: [libvirt] [PATCH] build: Ignore old audit library In-Reply-To: <4DB8D7E0.2040704@redhat.com> References: <66ce2a4962feb3e5f2748ab0593772a90e9e9fbd.1303896348.git.jdenemar@redhat.com> <4DB8D7E0.2040704@redhat.com> Message-ID: <20110428123642.GQ1245361@orkuz.home> On Wed, Apr 27, 2011 at 20:58:40 -0600, Eric Blake wrote: > On 04/27/2011 03:25 AM, Jiri Denemark wrote: > > Check for audit_encode_nv_string in libaudit so that ancient audit > > library is ignored rather than trying to compile with libaudit support > > and failing. > > --- > > configure.ac | 2 +- > > 1 files changed, 1 insertions(+), 1 deletions(-) > > > > diff --git a/configure.ac b/configure.ac > > index 190bf40..25cc15b 100644 > > --- a/configure.ac > > +++ b/configure.ac > > @@ -1026,7 +1026,7 @@ if test "$with_audit" != "no" ; then > > LIBS="$LIBS $AUDIT_LIBS" > > fail=0 > > AC_CHECK_HEADER([libaudit.h], [], [fail=1]) > > - AC_CHECK_LIB([audit], [audit_is_enabled], [], [fail=1]) > > + AC_CHECK_LIB([audit], [audit_encode_nv_string], [], [fail=1]) > > ACK, especially since it matches what virtaudit.c requires. Thanks, pushed. Jirka From jdenemar at redhat.com Thu Apr 28 12:44:57 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Thu, 28 Apr 2011 14:44:57 +0200 Subject: [libvirt] [PATCH] build: Use pkg-config for libssh2 check In-Reply-To: <4DB8D7B0.7030508@redhat.com> References: <4DB8D7B0.7030508@redhat.com> Message-ID: <20110428124457.GR1245361@orkuz.home> On Wed, Apr 27, 2011 at 20:57:52 -0600, Eric Blake wrote: > On 04/27/2011 04:34 AM, Jiri Denemark wrote: > > Currently the build fails if /usr/local/include does not exist since > > its use is hardcoded in configure.ac > > --- > > configure.ac | 86 ++++++++++++++------------------------------------------- > > 1 files changed, 21 insertions(+), 65 deletions(-) > > > > +if test "$with_phyp" = "yes" || test "$with_phyp" = "check"; then > > + PKG_CHECK_MODULES(LIBSSH2, libssh2 >= $LIBSSH2_REQUIRED, [ > > Preferred quoting style: > > PKG_CHECK_MODULES([LIBSSH2], [libssh2 >= $LIBSSH2_REQUIRED], [ > > ACK with that nit fixed. Fixed and pushed, thanks. Jirka From extmaillist at linuxbox.cz Thu Apr 28 13:36:33 2011 From: extmaillist at linuxbox.cz (Nikola Ciprich) Date: Thu, 28 Apr 2011 15:36:33 +0200 Subject: [libvirt] libvirt-0.8.8 libvir: Security Labeling error : unable to set user and group to '0:0' on '...': Permission denied Message-ID: <20110428133622.GA23012@pcnci.linuxbox.cz> Hello, I just noticed strange problem. While trying to start vm with cdrom image on a samba mount, I get: libvir: Security Labeling error : unable to set user and group to '0:0' on '/home/cluster/images/interinformatics/CentOS-5.4-i386-bin-DVD.iso': Permission denied I googled this up, and found some solutions, but none seems to be suitable for me. The biggest problem is I'm not using selinux at all, its completely disabled, and I don't have a chance to change mount parameters as well... Is there any way to workaround this? thanks a lot in advance! BR nik -- ------------------------------------- Ing. Nikola CIPRICH LinuxBox.cz, s.r.o. 28. rijna 168, 709 01 Ostrava tel.: +420 596 603 142 fax: +420 596 621 273 mobil: +420 777 093 799 www.linuxbox.cz mobil servis: +420 737 238 656 email servis: servis at linuxbox.cz ------------------------------------- From ovedo at redhat.com Thu Apr 28 08:15:15 2011 From: ovedo at redhat.com (Oved Ourfalli) Date: Thu, 28 Apr 2011 04:15:15 -0400 (EDT) Subject: [libvirt] migration of vnlink VMs In-Reply-To: <4DB91543.4070200@redhat.com> Message-ID: <632295223.309151.1303978515554.JavaMail.root@zmail02.collab.prod.int.phx2.redhat.com> ----- Original Message ----- > From: "Laine Stump" > To: "Oved Ourfalli" > Cc: "Ayal Baron" , "Barak Azulay" , "Shahar Havivi" , > "Itamar Heim" , "Dan Kenigsberg" > Sent: Thursday, April 28, 2011 10:20:35 AM > Subject: Re: migration of vnlink VMs > Oved, > > Would it be okay to repost this message to the thread on libvir-list > so > that other parties can add their thoughts? > Of course. I'm sending my answer to the libvirt list. > On 04/27/2011 09:58 AM, Oved Ourfalli wrote: > > Laine, hello. > > > > We read your proposal for abstraction of guest<--> host network > > connection in libvirt. > > > > You has an open issue there regarding the vepa/vnlink attributes: > > "3) What about the parameters in the element that are > > currently used by vepa/vnlink. Do those belong with the host, or > > with the guest?" > > > > The parameters for the virtualport element should be on the guest, > > and not the host, because a specific interface can run multiple > > profiles, > > Are you talking about host interface or guest interface? If you mean > that multiple different profiles can be used when connecting to a > particular switch - as long as there are only a few different > profiles, > rather than each guest having its own unique profile, then it still > seems better to have the port profile live with the network definition > (and just define multiple networks, one for each port profile). > The profile names can be changed regularly, so it looks like it will be better to put them in the guest level, so that the network host file won't have to be changed on all hosts once something has changed in the profiles. Also, you will have a duplication of data, writing all the profile name on all the hosts that are connected to the vn-link/vepa switch. > > > so it will be a mistake to define a profile to be interface > > specific on the host. Moreover, putting it in the guest level will > > enable us in the future (if supported by libvirt/qemu) to migrate > > a vm from a host with vepa/vnlink interfaces, to another host with > > a bridge, for example. > > It seems to me like doing exactly the opposite would make it easier to > migrate to a host that used a different kind of switching (from vepa > to > vnlink, or from a bridged interface to vepa, etc), since the port > profile required for a particular host's network would be at the host > waiting to be used. You are right, but we would want to have the option to prevent that from happening in case we wouldn't want to allow it. We can make the ability to migrate between different network types configurable, and we would like an easy way to tell libvirt - "please allow/don't allow it". > > > So, in the networks at the host level you will have: > > > > red-network > > > > > > > > eth0 > > ..... > > > > > > eth4 > > ..... > > > > > > eth18 > > ..... > > > > > > > > > > > > And in the guest you will have (for vepa): > > > > > > > > > instanceid="09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f"/> > > > > > > > > Or (for vnlink): > > > > > > > > > > > > > > This illustrates the problem I was wondering about - in your example > it > would not be possible for the guest to migrate from the host using a > vepa switch to the host using a vnlink switch (and it would be > possible You are right. When trying to migrate between vepa and vnlink there will be missing attributes in each in case we leave it on the host. > to migrate to a host using a standard bridge only if the virtualport > element was ignored). If the virtualport element lived with the > network > definition of red-network on each host, it could be migrated without > problem. > > The only problematic thing would be if any of the attributes within > was unique for each guest (I don't know anything about > the > individual attributes, but "instanceid" sounds like it might be > different for each guest). > > > Then, when migrating from a vepa/vnlink host to another vepa/vnlink > > host containing red-network, the profile attributes will be > > available at the guest domain xml. > > In case the target host has a red-network, which isn't vepa/vnlink, > > we want to be able to choose whether to make the use of the profile > > attributes optional (i.e., libvirt won't fail in case of migrating > > to a network of another type), or mandatory (i.e., libvirt will fail > > in case of migration to a non-vepa/vnlink network). > > > > We have something similar in CPU flags: > > > > qemu64 > > > > > name="sse2"/> > > > > In this analogy, does "CPU flags" == "mode (vepa/vnlink/bridge)" or > does > "CPU flags" == "virtualport parameters" ? It seems like what you're > wanting can be satisfied by simply not defining "red-network" on the > hosts that don't have the proper networking setup available (maybe > what > you *really* want to call it is "red-vnlink-network"). What I meant to say in that is that we would like to have the ability to say if an attribute must me used, or not. The issues you mention are indeed interesting. I'm cc-ing libvirt-list to see what other people think. Putting it on the guest will indeed make it problematic to migrate between networks that need different parameters (vnlink/vepa for example). Oved From eblake at redhat.com Thu Apr 28 14:14:42 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 28 Apr 2011 08:14:42 -0600 Subject: [libvirt] [PATCH] maint: fix comment typos Message-ID: <1304000082-5758-1-git-send-email-eblake@redhat.com> * src/esx/esx_driver.c: Fix spelling of 'relative'. * src/util/util.c: Likewise. --- Pushing under the trivial rule. src/esx/esx_driver.c | 2 +- src/util/util.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 79c1360..81e3c8e 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -2413,7 +2413,7 @@ esxDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) VIR_DEBUG("usedCpuTimeCounterId %d END", priv->usedCpuTimeCounterId); /* - * FIXME: Cannot map between realtive used-cpu-time and absolute + * FIXME: Cannot map between relative used-cpu-time and absolute * info->cpuTime */ } diff --git a/src/util/util.c b/src/util/util.c index 16454ed..a28af0b 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -2040,7 +2040,7 @@ cleanup: /* - * Creates an absolute path for a potentialy realtive path. + * Creates an absolute path for a potentially relative path. * Return 0 if the path was not relative, or on success. * Return -1 on error. * -- 1.7.4.4 From eblake at redhat.com Thu Apr 28 14:16:48 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 28 Apr 2011 08:16:48 -0600 Subject: [libvirt] [PATCH] network: fix return value of hostsFileWrite In-Reply-To: <1303972089-10631-1-git-send-email-laine@laine.org> References: <1303972089-10631-1-git-send-email-laine@laine.org> Message-ID: <4DB976D0.5090800@redhat.com> On 04/28/2011 12:28 AM, Laine Stump wrote: > The lone caller to hostsFileWrite (and the callers for at least 3 > levels up the return stack) assume that the return value will be < 0 > on failure. However, hostsFileWrite returns 0 on success, and a > positive errno on failure. This patch changes hostsFileWrite to return > -errno on failure. > --- > src/util/dnsmasq.c | 12 ++++++------ > 1 files changed, 6 insertions(+), 6 deletions(-) > > diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c > index be230e1..2ba9355 100644 > --- a/src/util/dnsmasq.c > +++ b/src/util/dnsmasq.c > @@ -159,19 +159,19 @@ hostsfileWrite(const char *path, > return rc; I had to check context, but here rc is 0 so it is safe. All other lines in the patch are correct. ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From minovotn at redhat.com Thu Apr 28 14:31:08 2011 From: minovotn at redhat.com (Michal Novotny) Date: Thu, 28 Apr 2011 16:31:08 +0200 Subject: [libvirt] [PATCH v2 2/5] Network: Add regression tests for the command line arguments In-Reply-To: <4DB8453D.1090709@laine.org> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> <1301654756-3920-3-git-send-email-minovotn@redhat.com> <4DB8453D.1090709@laine.org> Message-ID: <4DB97A2C.8000802@redhat.com> On 04/27/2011 06:33 PM, Laine Stump wrote: > On 04/01/2011 06:45 AM, Michal Novotny wrote: >> Make: passed >> Make check: passed >> Make syntax-check: passed >> >> Hi, >> this is the patch that is adding regression tests for the network >> bridge driver command-line arguments similar way it is done for >> QEMU driver. This is checking the built dnsmasq parameters (using >> networkBuildDhcpDaemonCommandLine() function) and comparing them >> to excepted arguments in the *.argv files. >> >> This has been tested and working fine. >> >> Michal > > Same comments about the commit message as in 1/5 - don't include stuff > about what tests passed, salutations, signatures; *do* include a short > sample of the XML. > > >> Signed-off-by: Michal Novotny >> --- >> src/network/bridge_driver.c | 27 ++++- >> src/network/bridge_driver.h | 3 + >> tests/Makefile.am | 11 ++ >> tests/networkxml2argvdata/isolated-network.argv | 1 + >> tests/networkxml2argvdata/isolated-network.xml | 11 ++ >> .../nat-network-dns-txt-record.argv | 1 + >> .../nat-network-dns-txt-record.xml | 24 ++++ >> tests/networkxml2argvdata/nat-network.argv | 1 + >> tests/networkxml2argvdata/nat-network.xml | 21 ++++ >> tests/networkxml2argvdata/netboot-network.argv | 1 + >> tests/networkxml2argvdata/netboot-network.xml | 14 +++ >> .../networkxml2argvdata/netboot-proxy-network.argv | 1 + >> .../networkxml2argvdata/netboot-proxy-network.xml | 13 ++ >> tests/networkxml2argvdata/routed-network.argv | 1 + >> tests/networkxml2argvdata/routed-network.xml | 9 ++ >> tests/networkxml2argvtest.c | 119 ++++++++++++++++++++ >> 16 files changed, 255 insertions(+), 3 deletions(-) >> create mode 100644 tests/networkxml2argvdata/isolated-network.argv >> create mode 100644 tests/networkxml2argvdata/isolated-network.xml >> create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.argv >> create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.xml >> create mode 100644 tests/networkxml2argvdata/nat-network.argv >> create mode 100644 tests/networkxml2argvdata/nat-network.xml >> create mode 100644 tests/networkxml2argvdata/netboot-network.argv >> create mode 100644 tests/networkxml2argvdata/netboot-network.xml >> create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.argv >> create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.xml >> create mode 100644 tests/networkxml2argvdata/routed-network.argv >> create mode 100644 tests/networkxml2argvdata/routed-network.xml >> create mode 100644 tests/networkxml2argvtest.c >> >> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c >> index 2e299f5..b6ce39d 100644 >> --- a/src/network/bridge_driver.c >> +++ b/src/network/bridge_driver.c >> @@ -613,11 +613,11 @@ cleanup: >> return ret; >> } >> >> -static int >> -networkStartDhcpDaemon(virNetworkObjPtr network) >> +int >> +networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, virCommandPtr *cmdout, >> + char *pidfile) > If you make a function global, you should add it to a .syms file. In > this case (as we just discussed on IRC with eblake) you should create a > new src/libvirt_network.syms file and add it to that (then add that > .syms file to the appropriate places in src/Makefile.am) > >> { >> virCommandPtr cmd = NULL; >> - char *pidfile = NULL; > As patched, this will not compile - you removed pidfile from the new > function, but left the assignment to it in. (actually, all of the > directory and file creation items should be moved down into > networkStartDhcpDaemon, so that networkBuildDhcpDaemonCommandLine > doesn't have any side effects.) > >> int ret = -1, err, ii; >> virNetworkIpDefPtr ipdef; >> >> @@ -666,6 +666,27 @@ networkStartDhcpDaemon(virNetworkObjPtr network) >> goto cleanup; >> } >> >> + if (cmdout) >> + *cmdout = cmd; >> + >> + ret = 0; >> +cleanup: >> + if (ret != 0) > > The standard practice in libvirt is to use "ret < 0" rather than "ret != 0". > > >> + virCommandFree(cmd); >> + return ret; >> +} >> + >> +static int >> +networkStartDhcpDaemon(virNetworkObjPtr network) >> +{ >> + virCommandPtr cmd = NULL; >> + char *pidfile = NULL; >> + int ret = -1; >> + >> + ret = networkBuildDhcpDaemonCommandLine(network,&cmd, pidfile); >> + if (ret != 0) > Again, ret < 0. > >> + goto cleanup; >> + >> if (virCommandRun(cmd, NULL)< 0) >> goto cleanup; >> >> diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h >> index 32d2ae7..8d82b67 100644 >> --- a/src/network/bridge_driver.h >> +++ b/src/network/bridge_driver.h >> @@ -28,7 +28,10 @@ >> # include >> >> # include "internal.h" >> +# include "network_conf.h" >> +# include "command.h" >> >> int networkRegister(void); >> +int networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, virCommandPtr *cmdout, char *pidfile); >> >> #endif /* __VIR_NETWORK__DRIVER_H */ >> diff --git a/tests/Makefile.am b/tests/Makefile.am >> index 5896442..a3f8d00 100644 >> --- a/tests/Makefile.am >> +++ b/tests/Makefile.am >> @@ -50,6 +50,7 @@ EXTRA_DIST = \ >> networkschematest \ >> networkxml2xmlin \ >> networkxml2xmlout \ >> + networkxml2argvdata \ > Yay for new tests! > >> nodedevschemadata \ >> nodedevschematest \ >> nodeinfodata \ >> @@ -104,6 +105,8 @@ endif >> >> check_PROGRAMS += networkxml2xmltest >> >> +check_PROGRAMS += networkxml2argvtest >> + >> check_PROGRAMS += nwfilterxml2xmltest >> >> check_PROGRAMS += storagevolxml2xmltest storagepoolxml2xmltest >> @@ -191,6 +194,8 @@ endif >> >> TESTS += networkxml2xmltest >> >> +TESTS += networkxml2argvtest >> + >> TESTS += storagevolxml2xmltest storagepoolxml2xmltest >> >> TESTS += nodedevxml2xmltest >> @@ -308,6 +313,12 @@ networkxml2xmltest_SOURCES = \ >> testutils.c testutils.h >> networkxml2xmltest_LDADD = $(LDADDS) >> >> +networkxml2argvtest_SOURCES = \ >> + networkxml2argvtest.c \ >> + ../src/network/bridge_driver.c network/bridge_driver.h \ > Rather than adding the source files, you should be adding the .la file > libvirt_network.la. See other .la file additions for the proper pattern > to follow. > >> + testutils.c testutils.h >> +networkxml2argvtest_LDADD = $(LDADDS) >> + >> nwfilterxml2xmltest_SOURCES = \ >> nwfilterxml2xmltest.c \ >> testutils.c testutils.h >> diff --git a/tests/networkxml2argvdata/isolated-network.argv b/tests/networkxml2argvdata/isolated-network.argv >> new file mode 100644 >> index 0000000..1c173db >> --- /dev/null >> +++ b/tests/networkxml2argvdata/isolated-network.argv >> @@ -0,0 +1 @@ >> +/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/private.pid --conf-file= --except-interface lo --dhcp-option=3 --listen-address 192.168.152.1 --dhcp-range 192.168.152.2,192.168.152.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/private.leases --dhcp-lease-max=253 --dhcp-no-override >> diff --git a/tests/networkxml2argvdata/isolated-network.xml b/tests/networkxml2argvdata/isolated-network.xml >> new file mode 100644 >> index 0000000..cc320a9 >> --- /dev/null >> +++ b/tests/networkxml2argvdata/isolated-network.xml >> @@ -0,0 +1,11 @@ >> + >> +private >> +81ff0d90-c91e-6742-64da-4a736edb9a9b >> + >> + >> + >> + >> + >> + >> + >> + >> diff --git a/tests/networkxml2argvdata/nat-network-dns-txt-record.argv b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv >> new file mode 100644 >> index 0000000..55dcf02 >> --- /dev/null >> +++ b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv >> @@ -0,0 +1 @@ >> +/usr/sbin/dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/default.pid --conf-file= --except-interface lo --txt-record=example,example value --listen-address 192.168.122.1 > > Does the argument to ==txt-record need to be quoted? (probably not > needed, but it might help readability in the logs - will it *hurt* > anything to quote it? > I was having issues with the --txt-record set with the quotes. There are no quotes as you can see. And yes, unfortunately adding quoting does hurt according to my testing :( Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From laine at laine.org Thu Apr 28 14:35:45 2011 From: laine at laine.org (Laine Stump) Date: Thu, 28 Apr 2011 10:35:45 -0400 Subject: [libvirt] [libvirt-users] [Libvir] libvirt & vde_switch In-Reply-To: <4DB9721D.1060204@stereoit.com> References: <4D9B0208.1040404@stereoit.com> <20110406083406.GA2222@nicolas-desktop> <4D9C4F8A.1010200@stereoit.com> <20110406140028.GB2222@nicolas-desktop> <4D9C750B.40501@stereoit.com> <4DB9721D.1060204@stereoit.com> Message-ID: <4DB97B41.4020409@laine.org> On 04/28/2011 09:56 AM, Robert ?mol wrote: > For my needs I would like to see either vdeswitch or openvswitch > integrated in the project. Is there any preference from the > users/developers on which one of those I should start looking into? Are you volunteering to write some code? :-) There have been requests for both, and both should eventually be done, so I guess pick whichever one you like better :-) (since there's already a patch for VDE, albeit with different XML than we'd like, that may be quicker to finish.) You may want to follow development of the work I'll point out below, though, otherwise you could waste a lot of time. > > Also I would like to know how this should be integrated, from the > mails I can see devs prefers to have virtual switch present as a > network. Can someone describe how the integration should be done? > Support for additional features like vlan, QoS? Once we get into these kinds of questions, it's probably best to switch to the developers' list (libvir-list at redhat.com) to get better exposure to people writing the code. I'm Cc'ing this message there (and switching the Reply-To: as well). In particular, I recently send an RFC to libvir-list proposing an expansion of the XML to remove the hard-coded connection between guest interface and host interface for macvtap (type='direct') interfaces: https://www.redhat.com/archives/libvir-list/2011-April/msg00591.html and in a followup message showed how we could expand on this work to provide support for openvswitch (or vde): https://www.redhat.com/archives/libvir-list/2011-April/msg00640.html I'm planning to have this code finished and tested within the next two months at most (hopefully considerably earlier). If you're interested in implementing a or you should subscribe to libvir-list (if you aren't already) so that you can follow along. > > Robert > > On 04/06/2011 04:13 PM, Robert ?mol wrote: >> >> >> On 04/06/2011 04:00 PM, Nicolas Sebrecht wrote: >>> The 06/04/11, Robert ?mol wrote: >>>> On 04/06/2011 10:34 AM, Nicolas Sebrecht wrote: >>>>> The 05/04/11, Robert ?mol wrote: >>>>> >>>>>> I would like to ask about status of VDE and libvirt. I found a >>>>>> thread from >>>>>> http://www.redhat.com/archives/libvir-list/2008-February/msg00030.html. >>>>>> >>>>> AFAIK, vde_switch is still unsupported by libvirt and nobody seems to >>>>> work on it these days. >>>>> >>>>> Most people wanting vde_switch (or open vswitch) enough leave >>>>> libvirt. >>>>> >>>> On #IRC I got point to message: >>>> >>>> http://www.mail-archive.com/libvir-list at redhat.com/msg32081.html >>>> >>>> It seems there is a patch ready. I will test it against 0.9.0. What >>>> is the procedure to get the patch reviewed and eventually get into >>>> libvirt? >>> The patch wasn't merged but the why is a question to the maintainers. I >>> guess the way it was implemented did not convinced. This is what I >>> understand from the whole thread, at least. >>> >> From the thread it seems the maintainers would like to have a network >> based on VDE. To me it also looks like better idea (create vde >> network and then just attach the domain to a network. >> > From laine at laine.org Thu Apr 28 14:45:21 2011 From: laine at laine.org (Laine Stump) Date: Thu, 28 Apr 2011 10:45:21 -0400 Subject: [libvirt] [PATCH] network: fix return value of hostsFileWrite In-Reply-To: <4DB976D0.5090800@redhat.com> References: <1303972089-10631-1-git-send-email-laine@laine.org> <4DB976D0.5090800@redhat.com> Message-ID: <4DB97D81.80701@laine.org> On 04/28/2011 10:16 AM, Eric Blake wrote: > On 04/28/2011 12:28 AM, Laine Stump wrote: >> The lone caller to hostsFileWrite (and the callers for at least 3 >> levels up the return stack) assume that the return value will be< 0 >> on failure. However, hostsFileWrite returns 0 on success, and a >> positive errno on failure. This patch changes hostsFileWrite to return >> -errno on failure. >> --- >> src/util/dnsmasq.c | 12 ++++++------ >> 1 files changed, 6 insertions(+), 6 deletions(-) >> >> diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c >> index be230e1..2ba9355 100644 >> --- a/src/util/dnsmasq.c >> +++ b/src/util/dnsmasq.c >> @@ -159,19 +159,19 @@ hostsfileWrite(const char *path, >> return rc; > I had to check context, but here rc is 0 so it is safe. > > All other lines in the patch are correct. > > ACK. Pushed. Thanks! From laine at laine.org Thu Apr 28 14:50:49 2011 From: laine at laine.org (Laine Stump) Date: Thu, 28 Apr 2011 10:50:49 -0400 Subject: [libvirt] libvirt-0.8.8 libvir: Security Labeling error : unable to set user and group to '0:0' on '...': Permission denied In-Reply-To: <20110428133622.GA23012@pcnci.linuxbox.cz> References: <20110428133622.GA23012@pcnci.linuxbox.cz> Message-ID: <4DB97EC9.8030705@laine.org> On 04/28/2011 09:36 AM, Nikola Ciprich wrote: > Hello, > I just noticed strange problem. While trying to start vm with cdrom image on a samba mount, I get: > libvir: Security Labeling error : unable to set user and group to '0:0' on '/home/cluster/images/interinformatics/CentOS-5.4-i386-bin-DVD.iso': Permission denied > I googled this up, and found some solutions, but none seems to be suitable for me. The biggest problem is I'm not using selinux at all, its completely disabled, and I don't have a chance to change mount parameters as well... > Is there any way to workaround this? > thanks a lot in advance! This isn't related to selinux, but to libvirt's practice of changing the user:group of files that must be opened by qemu. You can tell libvirt to not do this - edit /etc/libvirt/qemu.conf, and uncomment the line that says "dynamic_ownership = 1" and change the 1 to a 0. Then restart libvirtd. Note that once you've done this, you'll need to make sure that all disk image files used by qemu are pre-set to the proper ownership for the "qemu user" to access them (this includes all parent directories of the image files) (the qemu user is "root" on many systems, but is "qemu" on some others (eg Fedora and RHEL). It may also be configured in /etc/libvirt/qemu.conf). From minovotn at redhat.com Thu Apr 28 15:00:07 2011 From: minovotn at redhat.com (Michal Novotny) Date: Thu, 28 Apr 2011 17:00:07 +0200 Subject: [libvirt] [PATCH v2 4/5] Network: Add additional hosts internal infrastructure In-Reply-To: <4DB8C371.1040706@laine.org> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> <1301654756-3920-5-git-send-email-minovotn@redhat.com> <4DB8C371.1040706@laine.org> Message-ID: <4DB980F7.1030701@redhat.com> On 04/28/2011 03:31 AM, Laine Stump wrote: > Coming back to this now that I see how it's being used... > > On 04/01/2011 06:45 AM, Michal Novotny wrote: >> Hi, >> this is the patch to introduce the internal infrastructure for >> additional hosts for network bridge driver using the addnhosts* >> API functions. >> >> This is necessary for next part of the patch to support DNS >> hosts definition in the network XML description. >> >> Michal >> >> Signed-off-by: Michal Novotny >> --- >> src/libvirt_private.syms | 1 + >> src/network/bridge_driver.c | 3 + >> src/util/dnsmasq.c | 266 ++++++++++++++++++++++++++++++++++++++++++- >> src/util/dnsmasq.h | 22 ++++- >> 4 files changed, 287 insertions(+), 5 deletions(-) >> >> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms >> index 65a86d3..73c3f77 100644 >> --- a/src/libvirt_private.syms >> +++ b/src/libvirt_private.syms >> @@ -186,6 +186,7 @@ virUnrefStream; >> >> # dnsmasq.h >> dnsmasqAddDhcpHost; >> +dnsmasqAddHost; >> dnsmasqContextFree; >> dnsmasqContextNew; >> dnsmasqDelete; >> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c >> index 41b14f9..4ad3143 100644 >> --- a/src/network/bridge_driver.c >> +++ b/src/network/bridge_driver.c >> @@ -589,6 +589,9 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, >> if (dctx->hostsfile->nhosts) >> virCommandAddArgPair(cmd, "--dhcp-hostsfile", >> dctx->hostsfile->path); >> + if (dctx->addnhostsfile->nhosts) >> + virCommandAddArgPair(cmd, "--addn-hosts", >> + dctx->addnhostsfile->path); >> >> dnsmasqContextFree(dctx); >> } >> diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c >> index be230e1..fee3b90 100644 >> --- a/src/util/dnsmasq.c >> +++ b/src/util/dnsmasq.c >> @@ -48,6 +48,7 @@ >> >> #define VIR_FROM_THIS VIR_FROM_NETWORK >> #define DNSMASQ_HOSTSFILE_SUFFIX "hostsfile" >> +#define DNSMASQ_ADDNHOSTSFILE_SUFFIX "addnhosts" >> >> static void >> dhcphostFree(dnsmasqDhcpHost *host) >> @@ -56,6 +57,231 @@ dhcphostFree(dnsmasqDhcpHost *host) >> } >> >> static void >> +addnhostFree(dnsmasqAddnHost *host) >> +{ >> + VIR_FREE(host->hostnames); > You haven't freed host->hostnames[0], hostnames[1], etc; you've only > freed the array of pointers. > > >> + VIR_FREE(host->ip); >> +} >> + >> +static void >> +addnhostsFree(dnsmasqAddnHostsfile *addnhostsfile) >> +{ >> + unsigned int i; >> + >> + if (addnhostsfile->hosts) { >> + for (i = 0; i< addnhostsfile->nhosts; i++) >> + addnhostFree(&addnhostsfile->hosts[i]); >> + >> + VIR_FREE(addnhostsfile->hosts); >> + >> + addnhostsfile->nhosts = 0; >> + } >> + >> + VIR_FREE(addnhostsfile->path); >> + >> + VIR_FREE(addnhostsfile); >> +} >> + >> +static int >> +addnhostsAdd(dnsmasqAddnHostsfile *addnhostsfile, >> + virSocketAddr *ip, > You could also mark ip as a const. Well, not really since I was unable to compile it anymore when prefixing it with const keyword. Michal -- Michal Novotny , RHCE Virtualization Team (xen userspace), Red Hat From laine at laine.org Thu Apr 28 16:31:57 2011 From: laine at laine.org (Laine Stump) Date: Thu, 28 Apr 2011 12:31:57 -0400 Subject: [libvirt] [PATCH v2 4/5] Network: Add additional hosts internal infrastructure In-Reply-To: <4DB980F7.1030701@redhat.com> References: <1301654756-3920-1-git-send-email-minovotn@redhat.com> <1301654756-3920-5-git-send-email-minovotn@redhat.com> <4DB8C371.1040706@laine.org> <4DB980F7.1030701@redhat.com> Message-ID: <4DB9967D.8030501@laine.org> On 04/28/2011 11:00 AM, Michal Novotny wrote: > On 04/28/2011 03:31 AM, Laine Stump wrote: >> Coming back to this now that I see how it's being used... >> >> On 04/01/2011 06:45 AM, Michal Novotny wrote: >>> + >>> +static int >>> +addnhostsAdd(dnsmasqAddnHostsfile *addnhostsfile, >>> + virSocketAddr *ip, >> You could also mark ip as a const. > Well, not really since I was unable to compile it anymore when prefixing > it with const keyword. Ah, bummer :-( So some function(s) called by addnhostsAdd() needs const for the virSocketAddr* From mprivozn at redhat.com Thu Apr 28 16:34:36 2011 From: mprivozn at redhat.com (Michal Privoznik) Date: Thu, 28 Apr 2011 18:34:36 +0200 Subject: [libvirt] [PATCH] Add warning message to XML definition files stored on disk Message-ID: <1304008476-2128-1-git-send-email-mprivozn@redhat.com> Users often edit XML domain file stored in configuration directory thinking of modifying a domain/network/pool/etc. Thus it is wise to let them know they are using the wrong way and give them hint. --- src/conf/domain_conf.c | 2 ++ src/conf/network_conf.c | 1 + src/conf/nwfilter_conf.c | 3 +++ src/conf/storage_conf.c | 2 ++ src/libvirt_private.syms | 1 + src/util/util.c | 22 ++++++++++++++++++++++ src/util/util.h | 2 ++ 7 files changed, 33 insertions(+), 0 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 2a681d9..4cd1228 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -8543,6 +8543,7 @@ int virDomainSaveConfig(const char *configDir, VIR_DOMAIN_XML_WRITE_FLAGS))) goto cleanup; + virSavePrependWarning(&xml); if (virDomainSaveXML(configDir, def, xml)) goto cleanup; @@ -8563,6 +8564,7 @@ int virDomainSaveStatus(virCapsPtr caps, if (!(xml = virDomainObjFormat(caps, obj, flags))) goto cleanup; + virSavePrependWarning(&xml); if (virDomainSaveXML(statusDir, obj->def, xml)) goto cleanup; diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 5738757..82f10e6 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -959,6 +959,7 @@ int virNetworkSaveConfig(const char *configDir, if (!(xml = virNetworkDefFormat(def))) goto cleanup; + virSavePrependWarning(&xml); if (virNetworkSaveXML(configDir, def, xml)) goto cleanup; diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 09dc32b..fcd0b24 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -2282,6 +2282,7 @@ int virNWFilterSaveConfig(const char *configDir, if (!(xml = virNWFilterDefFormat(def))) goto cleanup; + virSavePrependWarning(&xml); if (virNWFilterSaveXML(configDir, def, xml)) goto cleanup; @@ -2635,6 +2636,8 @@ virNWFilterObjSaveDef(virNWFilterDriverStatePtr driver, return -1; } + virSavePrependWarning(&xml); + if ((fd = open(nwfilter->configFile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR )) < 0) { diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 116898d..96aa567 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -1542,6 +1542,8 @@ virStoragePoolObjSaveDef(virStorageDriverStatePtr driver, return -1; } + virSavePrependWarning(&xml); + if ((fd = open(pool->configFile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR )) < 0) { diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 1b22be6..f2c005e 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -946,6 +946,7 @@ virRandom; virRandomInitialize; virRun; virRunWithHook; +virSavePrependWarning; virSetBlocking; virSetCloseExec; virSetInherit; diff --git a/src/util/util.c b/src/util/util.c index 1bb0328..c6a4634 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -3204,3 +3204,25 @@ bool virIsDevMapperDevice(const char *devname ATTRIBUTE_UNUSED) return false; } #endif + +int virSavePrependWarning(char **xml) { + char *retPtr = NULL; + int ret; + + ret = virAsprintf(&retPtr, "%s\n%s", + _("\n"), + *xml); + + if (ret < 0) + return ret; + + VIR_FREE(*xml); + *xml = retPtr; + return ret; +} diff --git a/src/util/util.h b/src/util/util.h index d320c40..a6a91de 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -299,4 +299,6 @@ int virBuildPathInternal(char **path, ...) ATTRIBUTE_SENTINEL; char *virTimestamp(void); bool virIsDevMapperDevice(const char *devname) ATTRIBUTE_NONNULL(1); + +int virSavePrependWarning(char **xml); #endif /* __VIR_UTIL_H__ */ -- 1.7.4.4 From laine at laine.org Thu Apr 28 17:42:37 2011 From: laine at laine.org (Laine Stump) Date: Thu, 28 Apr 2011 13:42:37 -0400 Subject: [libvirt] [PATCH] Add warning message to XML definition files stored on disk In-Reply-To: <1304008476-2128-1-git-send-email-mprivozn@redhat.com> References: <1304008476-2128-1-git-send-email-mprivozn@redhat.com> Message-ID: <4DB9A70D.50005@laine.org> On 04/28/2011 12:34 PM, Michal Privoznik wrote: > Users often edit XML domain file stored in configuration directory > thinking of modifying a domain/network/pool/etc. Thus it is wise > to let them know they are using the wrong way and give them hint. > --- > src/conf/domain_conf.c | 2 ++ > src/conf/network_conf.c | 1 + > src/conf/nwfilter_conf.c | 3 +++ > src/conf/storage_conf.c | 2 ++ > src/libvirt_private.syms | 1 + > src/util/util.c | 22 ++++++++++++++++++++++ > src/util/util.h | 2 ++ > 7 files changed, 33 insertions(+), 0 deletions(-) > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index 2a681d9..4cd1228 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -8543,6 +8543,7 @@ int virDomainSaveConfig(const char *configDir, > VIR_DOMAIN_XML_WRITE_FLAGS))) > goto cleanup; > > + virSavePrependWarning(&xml); > if (virDomainSaveXML(configDir, def, xml)) > goto cleanup; > > @@ -8563,6 +8564,7 @@ int virDomainSaveStatus(virCapsPtr caps, > if (!(xml = virDomainObjFormat(caps, obj, flags))) > goto cleanup; > > + virSavePrependWarning(&xml); > if (virDomainSaveXML(statusDir, obj->def, xml)) > goto cleanup; > > diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c > index 5738757..82f10e6 100644 > --- a/src/conf/network_conf.c > +++ b/src/conf/network_conf.c > @@ -959,6 +959,7 @@ int virNetworkSaveConfig(const char *configDir, > if (!(xml = virNetworkDefFormat(def))) > goto cleanup; > > + virSavePrependWarning(&xml); > if (virNetworkSaveXML(configDir, def, xml)) > goto cleanup; > > diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c > index 09dc32b..fcd0b24 100644 > --- a/src/conf/nwfilter_conf.c > +++ b/src/conf/nwfilter_conf.c > @@ -2282,6 +2282,7 @@ int virNWFilterSaveConfig(const char *configDir, > if (!(xml = virNWFilterDefFormat(def))) > goto cleanup; > > + virSavePrependWarning(&xml); > if (virNWFilterSaveXML(configDir, def, xml)) > goto cleanup; > > @@ -2635,6 +2636,8 @@ virNWFilterObjSaveDef(virNWFilterDriverStatePtr driver, > return -1; > } > > + virSavePrependWarning(&xml); > + > if ((fd = open(nwfilter->configFile, > O_WRONLY | O_CREAT | O_TRUNC, > S_IRUSR | S_IWUSR ))< 0) { > diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c > index 116898d..96aa567 100644 > --- a/src/conf/storage_conf.c > +++ b/src/conf/storage_conf.c > @@ -1542,6 +1542,8 @@ virStoragePoolObjSaveDef(virStorageDriverStatePtr driver, > return -1; > } > > + virSavePrependWarning(&xml); > + > if ((fd = open(pool->configFile, > O_WRONLY | O_CREAT | O_TRUNC, > S_IRUSR | S_IWUSR ))< 0) { > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 1b22be6..f2c005e 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -946,6 +946,7 @@ virRandom; > virRandomInitialize; > virRun; > virRunWithHook; > +virSavePrependWarning; > virSetBlocking; > virSetCloseExec; > virSetInherit; > diff --git a/src/util/util.c b/src/util/util.c > index 1bb0328..c6a4634 100644 > --- a/src/util/util.c > +++ b/src/util/util.c > @@ -3204,3 +3204,25 @@ bool virIsDevMapperDevice(const char *devname ATTRIBUTE_UNUSED) > return false; > } > #endif > + > +int virSavePrependWarning(char **xml) { > + char *retPtr = NULL; > + int ret; > + > + ret = virAsprintf(&retPtr, "%s\n%s", > + _("\n"), Can this URL change if the wiki is edited? Do we maybe want to put this info in a less modifiable place? (Dunno, just asking.) > + *xml); > + > + if (ret< 0) > + return ret; > + > + VIR_FREE(*xml); I'm not really comfortable that it requires the caller to initialize to 0. But that may be just me - anyone else have an opinion? > + *xml = retPtr; > + return ret; > +} > diff --git a/src/util/util.h b/src/util/util.h > index d320c40..a6a91de 100644 > --- a/src/util/util.h > +++ b/src/util/util.h > @@ -299,4 +299,6 @@ int virBuildPathInternal(char **path, ...) ATTRIBUTE_SENTINEL; > char *virTimestamp(void); > > bool virIsDevMapperDevice(const char *devname) ATTRIBUTE_NONNULL(1); > + > +int virSavePrependWarning(char **xml); > #endif /* __VIR_UTIL_H__ */ From jfehlig at novell.com Thu Apr 28 17:53:56 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Thu, 28 Apr 2011 11:53:56 -0600 Subject: [libvirt] [PATCH] Xen: Do not generate net ifname if domain is inactive Message-ID: <1304013236-22202-1-git-send-email-jfehlig@novell.com> The xend driver will generate a virDomainNetDef ifname if one is not specified in xend sexpr, even if domain is inactive. The result is network interface XML containing 'vif-1.Y' on dev attribute of target element, e.g. ... This patch changes the behavior to only generate the ifname if not specified in xend sexpr *and* domain is not inactive (id != -1). --- src/xenxs/xen_sxpr.c | 13 +++++++++---- 1 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c index d2ec370..66df786 100644 --- a/src/xenxs/xen_sxpr.c +++ b/src/xenxs/xen_sxpr.c @@ -547,12 +547,17 @@ xenParseSxprNets(virDomainDefPtr def, } tmp = sexpr_node(node, "device/vif/vifname"); - if (!tmp) { + /* If vifname is specified in xend config, include it in net + * definition regardless of domain state. If vifname is not + * specified, only generate one if domain is active (id != -1). */ + if (tmp) { + if (!(net->ifname = strdup(tmp))) + goto no_memory; + } else if (def->id != -1) { snprintf(buf, sizeof(buf), "vif%d.%d", def->id, vif_index); - tmp = buf; + if (!(net->ifname = strdup(buf))) + goto no_memory; } - if (!(net->ifname = strdup(tmp))) - goto no_memory; tmp = sexpr_node(node, "device/vif/mac"); if (tmp) { -- 1.7.3.1 From dallan at redhat.com Thu Apr 28 18:08:53 2011 From: dallan at redhat.com (Dave Allan) Date: Thu, 28 Apr 2011 14:08:53 -0400 Subject: [libvirt] [PATCH] Add warning message to XML definition files stored on disk In-Reply-To: <4DB9A70D.50005@laine.org> References: <1304008476-2128-1-git-send-email-mprivozn@redhat.com> <4DB9A70D.50005@laine.org> Message-ID: <20110428180848.GJ4070@redhat.com> On Thu, Apr 28, 2011 at 01:42:37PM -0400, Laine Stump wrote: > On 04/28/2011 12:34 PM, Michal Privoznik wrote: > >Users often edit XML domain file stored in configuration directory > >thinking of modifying a domain/network/pool/etc. Thus it is wise > >to let them know they are using the wrong way and give them hint. > >--- > > src/conf/domain_conf.c | 2 ++ > > src/conf/network_conf.c | 1 + > > src/conf/nwfilter_conf.c | 3 +++ > > src/conf/storage_conf.c | 2 ++ > > src/libvirt_private.syms | 1 + > > src/util/util.c | 22 ++++++++++++++++++++++ > > src/util/util.h | 2 ++ > > 7 files changed, 33 insertions(+), 0 deletions(-) > > > >diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > >index 2a681d9..4cd1228 100644 > >--- a/src/conf/domain_conf.c > >+++ b/src/conf/domain_conf.c > >@@ -8543,6 +8543,7 @@ int virDomainSaveConfig(const char *configDir, > > VIR_DOMAIN_XML_WRITE_FLAGS))) > > goto cleanup; > > > >+ virSavePrependWarning(&xml); > > if (virDomainSaveXML(configDir, def, xml)) > > goto cleanup; > > > >@@ -8563,6 +8564,7 @@ int virDomainSaveStatus(virCapsPtr caps, > > if (!(xml = virDomainObjFormat(caps, obj, flags))) > > goto cleanup; > > > >+ virSavePrependWarning(&xml); > > if (virDomainSaveXML(statusDir, obj->def, xml)) > > goto cleanup; > > > >diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c > >index 5738757..82f10e6 100644 > >--- a/src/conf/network_conf.c > >+++ b/src/conf/network_conf.c > >@@ -959,6 +959,7 @@ int virNetworkSaveConfig(const char *configDir, > > if (!(xml = virNetworkDefFormat(def))) > > goto cleanup; > > > >+ virSavePrependWarning(&xml); > > if (virNetworkSaveXML(configDir, def, xml)) > > goto cleanup; > > > >diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c > >index 09dc32b..fcd0b24 100644 > >--- a/src/conf/nwfilter_conf.c > >+++ b/src/conf/nwfilter_conf.c > >@@ -2282,6 +2282,7 @@ int virNWFilterSaveConfig(const char *configDir, > > if (!(xml = virNWFilterDefFormat(def))) > > goto cleanup; > > > >+ virSavePrependWarning(&xml); > > if (virNWFilterSaveXML(configDir, def, xml)) > > goto cleanup; > > > >@@ -2635,6 +2636,8 @@ virNWFilterObjSaveDef(virNWFilterDriverStatePtr driver, > > return -1; > > } > > > >+ virSavePrependWarning(&xml); > >+ > > if ((fd = open(nwfilter->configFile, > > O_WRONLY | O_CREAT | O_TRUNC, > > S_IRUSR | S_IWUSR ))< 0) { > >diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c > >index 116898d..96aa567 100644 > >--- a/src/conf/storage_conf.c > >+++ b/src/conf/storage_conf.c > >@@ -1542,6 +1542,8 @@ virStoragePoolObjSaveDef(virStorageDriverStatePtr driver, > > return -1; > > } > > > >+ virSavePrependWarning(&xml); > >+ > > if ((fd = open(pool->configFile, > > O_WRONLY | O_CREAT | O_TRUNC, > > S_IRUSR | S_IWUSR ))< 0) { > >diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > >index 1b22be6..f2c005e 100644 > >--- a/src/libvirt_private.syms > >+++ b/src/libvirt_private.syms > >@@ -946,6 +946,7 @@ virRandom; > > virRandomInitialize; > > virRun; > > virRunWithHook; > >+virSavePrependWarning; > > virSetBlocking; > > virSetCloseExec; > > virSetInherit; > >diff --git a/src/util/util.c b/src/util/util.c > >index 1bb0328..c6a4634 100644 > >--- a/src/util/util.c > >+++ b/src/util/util.c > >@@ -3204,3 +3204,25 @@ bool virIsDevMapperDevice(const char *devname ATTRIBUTE_UNUSED) > > return false; > > } > > #endif > >+ > >+int virSavePrependWarning(char **xml) { > >+ char *retPtr = NULL; > >+ int ret; > >+ > >+ ret = virAsprintf(&retPtr, "%s\n%s", > >+ _("\n"), > > Can this URL change if the wiki is edited? Do we maybe want to put > this info in a less modifiable place? (Dunno, just asking.) That's a good point. If we're going to point people at a URL, it should be a static page. (My bad for suggesting that URL in the first place.) > >+ *xml); > >+ > >+ if (ret< 0) > >+ return ret; > >+ > >+ VIR_FREE(*xml); > > I'm not really comfortable that it requires the caller to initialize > to 0. But that may be just me - anyone else have an opinion? > > >+ *xml = retPtr; > >+ return ret; > >+} > >diff --git a/src/util/util.h b/src/util/util.h > >index d320c40..a6a91de 100644 > >--- a/src/util/util.h > >+++ b/src/util/util.h > >@@ -299,4 +299,6 @@ int virBuildPathInternal(char **path, ...) ATTRIBUTE_SENTINEL; > > char *virTimestamp(void); > > > > bool virIsDevMapperDevice(const char *devname) ATTRIBUTE_NONNULL(1); > >+ > >+int virSavePrependWarning(char **xml); > > #endif /* __VIR_UTIL_H__ */ > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list From eblake at redhat.com Thu Apr 28 20:00:09 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 28 Apr 2011 14:00:09 -0600 Subject: [libvirt] [PATCH] Xen: Do not generate net ifname if domain is inactive In-Reply-To: <1304013236-22202-1-git-send-email-jfehlig@novell.com> References: <1304013236-22202-1-git-send-email-jfehlig@novell.com> Message-ID: <4DB9C749.3060600@redhat.com> On 04/28/2011 11:53 AM, Jim Fehlig wrote: > The xend driver will generate a virDomainNetDef ifname if one is not > specified in xend sexpr, even if domain is inactive. The result is > network interface XML containing 'vif-1.Y' on dev attribute of target > element, e.g. > > > > ... > > This patch changes the behavior to only generate the ifname if not > specified in xend sexpr *and* domain is not inactive (id != -1). Makes sense for the rationale. However... > + } else if (def->id != -1) { > snprintf(buf, sizeof(buf), "vif%d.%d", def->id, vif_index); > - tmp = buf; > + if (!(net->ifname = strdup(buf))) Rather than using snprintf and strdup, can't we just use: if (virAsprintf(&net->ifname, "vif%d.%d", def->id, vif_index) < 0) goto no_memory; -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 28 20:06:15 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 28 Apr 2011 14:06:15 -0600 Subject: [libvirt] [PATCH] Add warning message to XML definition files stored on disk In-Reply-To: <1304008476-2128-1-git-send-email-mprivozn@redhat.com> References: <1304008476-2128-1-git-send-email-mprivozn@redhat.com> Message-ID: <4DB9C8B7.603@redhat.com> On 04/28/2011 10:34 AM, Michal Privoznik wrote: > Users often edit XML domain file stored in configuration directory > thinking of modifying a domain/network/pool/etc. Thus it is wise > to let them know they are using the wrong way and give them hint. > +++ b/src/conf/domain_conf.c > @@ -8543,6 +8543,7 @@ int virDomainSaveConfig(const char *configDir, > VIR_DOMAIN_XML_WRITE_FLAGS))) > goto cleanup; > > + virSavePrependWarning(&xml); > if (virDomainSaveXML(configDir, def, xml)) Prepending can be expensive - in the middle of the operation, we have to have twice the space for xml malloc'd, and we are also spending time on a memcpy from old memory to new. Is there any way to instead change virDomainSaveXML and friends to take a flags argument, and pass 0 from most callers but VIR_XML_EMIT_WARNING from these particular callers; then if the flag is set, they call the common helper function: virEmitXMLWarning(int fd) which outputs the message directly into the target file prior to outputting xml? That would be less memory pressure and copying involved. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jfehlig at novell.com Thu Apr 28 20:45:56 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Thu, 28 Apr 2011 14:45:56 -0600 Subject: [libvirt] [PATCH] Xen: Do not generate net ifname if domain is inactive In-Reply-To: <4DB9C749.3060600@redhat.com> References: <1304013236-22202-1-git-send-email-jfehlig@novell.com> <4DB9C749.3060600@redhat.com> Message-ID: <4DB9D204.3090308@novell.com> Eric Blake wrote: > On 04/28/2011 11:53 AM, Jim Fehlig wrote: > >> The xend driver will generate a virDomainNetDef ifname if one is not >> specified in xend sexpr, even if domain is inactive. The result is >> network interface XML containing 'vif-1.Y' on dev attribute of target >> element, e.g. >> >> >> >> ... >> >> This patch changes the behavior to only generate the ifname if not >> specified in xend sexpr *and* domain is not inactive (id != -1). >> > > Makes sense for the rationale. However... > > >> + } else if (def->id != -1) { >> snprintf(buf, sizeof(buf), "vif%d.%d", def->id, vif_index); >> - tmp = buf; >> + if (!(net->ifname = strdup(buf))) >> > > Rather than using snprintf and strdup, can't we just use: > > if (virAsprintf(&net->ifname, "vif%d.%d", def->id, vif_index) < 0) > goto no_memory; > Yes, good point. Here is a V2. Regards, Jim -------------- next part -------------- A non-text attachment was scrubbed... Name: xend-ifname.patch Type: text/x-patch Size: 2274 bytes Desc: not available URL: From eblake at redhat.com Thu Apr 28 20:46:39 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 28 Apr 2011 14:46:39 -0600 Subject: [libvirt] [PATCH V3] xen: check if device is assigned to guest before reattaching In-Reply-To: <4DB9108C.4090804@redhat.com> References: <1303906152-4601-1-git-send-email-yuzhang@redhat.com> <4DB9108C.4090804@redhat.com> Message-ID: <4DB9D22F.4040606@redhat.com> On 04/28/2011 01:00 AM, Osier Yang wrote: > ? 2011?04?27? 20:09, Yufang Zhang ??: >> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=664059 >> >> This is the version3 patch for BZ#664059. This sentence is not as useful in the commit message; it's handy in reviews, but for someone using 'git am' to snarf the email message into their own git tree, the way to convey that information is by putting it after the '---' dividing line. That is, --- provides the boundary between commit details and out-of-band review helps. >> Reattaching pci device back to >> host without destroying guest or detaching device from guest would cause >> host to crash. This patch adds a check before doing device reattach. If >> the device is being assigned to guest, libvirt refuses to reattach device >> to host. The patch only works for Xen, for it just checks xenstore to get >> pci device information. This version fixes some formatting problem and moves >> lock-unlock out of loop so that the check is atomic. > > We have same problem with qemu driver, though this patch looks fine > and fix the problem for xen driver, IMHO it's not the ideal solution, > ideally it will be nice if kernel could let us known if the device is > still in use. I filed bug against kernel, no feedback yet though. Link to that bug? > >> >> Signed-off-by: Yufang Zhang >> --- >> src/xen/xen_driver.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ >> 1 files changed, 67 insertions(+), 0 deletions(-) ACK. I've added Yufang to AUTHORS (let me know off-list) if you prefer any alternate spelling to your name and pushed this patch. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 28 20:47:48 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 28 Apr 2011 14:47:48 -0600 Subject: [libvirt] [PATCH] Xen: Do not generate net ifname if domain is inactive In-Reply-To: <4DB9D204.3090308@novell.com> References: <1304013236-22202-1-git-send-email-jfehlig@novell.com> <4DB9C749.3060600@redhat.com> <4DB9D204.3090308@novell.com> Message-ID: <4DB9D274.4070607@redhat.com> On 04/28/2011 02:45 PM, Jim Fehlig wrote: >> Rather than using snprintf and strdup, can't we just use: >> >> if (virAsprintf(&net->ifname, "vif%d.%d", def->id, vif_index) < 0) >> goto no_memory; >> > > Yes, good point. Here is a V2. ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From jfehlig at novell.com Thu Apr 28 20:56:01 2011 From: jfehlig at novell.com (Jim Fehlig) Date: Thu, 28 Apr 2011 14:56:01 -0600 Subject: [libvirt] [PATCH] Xen: Do not generate net ifname if domain is inactive In-Reply-To: <4DB9D274.4070607@redhat.com> References: <1304013236-22202-1-git-send-email-jfehlig@novell.com> <4DB9C749.3060600@redhat.com> <4DB9D204.3090308@novell.com> <4DB9D274.4070607@redhat.com> Message-ID: <4DB9D461.1000506@novell.com> Eric Blake wrote: > On 04/28/2011 02:45 PM, Jim Fehlig wrote: > >>> Rather than using snprintf and strdup, can't we just use: >>> >>> if (virAsprintf(&net->ifname, "vif%d.%d", def->id, vif_index) < 0) >>> goto no_memory; >>> >>> >> Yes, good point. Here is a V2. >> > > ACK. > Thanks, pushed now. Regards, Jim From eblake at redhat.com Thu Apr 28 20:59:20 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 28 Apr 2011 14:59:20 -0600 Subject: [libvirt] [PATCHv12 3/3] libvirt/qemu - support persistent update of disks In-Reply-To: <20110422121028.8037cfa2.kamezawa.hiroyu@jp.fujitsu.com> References: <20110422120756.7f32d64f.kamezawa.hiroyu@jp.fujitsu.com> <20110422121028.8037cfa2.kamezawa.hiroyu@jp.fujitsu.com> Message-ID: <4DB9D528.1010207@redhat.com> On 04/21/2011 09:10 PM, KAMEZAWA Hiroyuki wrote: > Support update of disks by MODIFY_CONFIG > > This patch includes changes for qemu's disk to support > virDomainUpdateDeviceFlags() with VIR_DOMAIN_DEVICE_MODIFY_CONFIG. > > This patch adds support for CDROM/foppy disk types. > > Signed-off-by: KAMEZAWA Hiroyuki > > Changelog: v11->v12 > - rebased.(qemud->qemu) > > * src/qemu/qemu_driver.c > (qemuDomainUpdateDeviceConfig): support cdrom/floppy. > --- > src/qemu/qemu_driver.c | 40 +++++++++++++++++++++++++++++++++++++++- > 1 files changed, 39 insertions(+), 1 deletions(-) ACK. Technically, this is a feature addition and after the freeze created by the 0.9.1 release candidate 1, but my review of the earlier patches in this series was interleaved with DV's announcement of the rc1 creation. So I'd rather get this in now even if it is just a feature addition, to round out the series; and maybe we'll have an rc2 build with it in to make sure it didn't royally screw anything up. Thanks again for your persistence (sorry for the pun :) in getting this feature added. While all of the functionality was already present via raw XML editing, this sure makes it easier to do via virsh. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 28 21:05:26 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 28 Apr 2011 15:05:26 -0600 Subject: [libvirt] [Libvirt-announce] Libvirt 0.9.1 week freeze, RC1 version to test In-Reply-To: References: <20110428035115.GA21035@redhat.com> Message-ID: <4DB9D696.9030501@redhat.com> On 04/28/2011 01:33 AM, Matthias Bolte wrote: > libvirt compiles fine but virsh has a warning about vfprintf: > > virsh.c: In function 'vshDebug': > virsh.c:12105:5: warning: function might be possible candidate for > 'ms_printf' format attribute [-Wmissing-format-attribute] > > I'm no sure where to fix that. In mingw's . But we can't do that. vfprintf is NOT being provided by gnulib, so it does NOT understand %zu or %llu. Yet we use it with %zu. So the only real solution is to use virAsprintf (which _does_ understand %zu, thanks to gnulib) and make vshDebug go through an intermediate buffer, then use fputs on that string, rather than relying directly on the unsanitized vfprintf. Patch coming up shortly. > > make check shows two warnings in gnulib. Maybe Eric wants to take a look: > > getsockopt.c: In function 'rpl_getsockopt': > getsockopt.c:51:7: warning: passing argument 4 of 'getsockopt' from > incompatible pointer type > c:\dev\msys_setup\mingw\bin\../lib/gcc/mingw32/4.5.0/../../../../include/winsock2.h:543:32: > note: expected 'char *' but argument is of type 'int *' Yep, I can fix that one in gnulib; I'll have a counterpart patch to bump .gnulib to the latest once I've got it done. > > test-getaddrinfo.c:28:1: warning: initialization from incompatible pointer type Probably the same category of gnulib fix. > Aside from that the rest seems to work fine. So I fixed the non-blocking pipe issues that broke 0.9.0 virsh out-of-the-box? Good to hear. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Thu Apr 28 21:11:23 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 28 Apr 2011 15:11:23 -0600 Subject: [libvirt] [PATCH] virsh: avoid compiler warning on mingw Message-ID: <1304025083-19787-1-git-send-email-eblake@redhat.com> We don't use gnulib's sanitizations for vfprintf, but vshDebug was used with %zu, which means that it would fail on mingw. Thank goodness the compiler indirectly caught this for us :) virsh.c: In function 'vshDebug': virsh.c:12105:5: warning: function might be possible candidate for 'ms_printf' format attribute [-Wmissing-format-attribute] since mingw hasn't yet added gcc attributes to vfprintf. * tools/virsh.c (vshDebug): Avoid vfprintf. (vshPrintExtra): Use lighter-weight fputs. Reported by Matthias Bolte. --- tools/virsh.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 27140f3..0212b99 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -12096,6 +12096,7 @@ static void vshDebug(vshControl *ctl, int level, const char *format, ...) { va_list ap; + char *str; va_start(ap, format); vshOutputLogFile(ctl, VSH_ERR_DEBUG, format, ap); @@ -12105,8 +12106,14 @@ vshDebug(vshControl *ctl, int level, const char *format, ...) return; va_start(ap, format); - vfprintf(stdout, format, ap); + if (virVasprintf(&str, format, ap) < 0) { + /* Skip debug messages on low memory */ + va_end(ap); + return; + } va_end(ap); + fputs(str, stdout); + VIR_FREE(str); } static void @@ -12125,7 +12132,7 @@ vshPrintExtra(vshControl *ctl, const char *format, ...) return; } va_end(ap); - fprintf(stdout, "%s", str); + fputs(str, stdout); VIR_FREE(str); } -- 1.7.4.4 From eblake at redhat.com Thu Apr 28 23:42:03 2011 From: eblake at redhat.com (Eric Blake) Date: Thu, 28 Apr 2011 17:42:03 -0600 Subject: [libvirt] [PATCH] build: avoid test warnings on mingw Message-ID: <1304034123-7056-1-git-send-email-eblake@redhat.com> * .gnulib: Update to latest, for getaddrinfo fixes. Reported by Matthias Bolte. --- As promised, I've done the gnulib side of the mingw cleanups affecting the issues Matthias found with 0.9.1-rc1. Oh, and now that gnulib getcwd-lgpl exists, we could use it to fix our uses of getcwd(NULL,0), followup coming later. * .gnulib 7d06b32...74175b9 (29): > getaddrinfo: fix gai_strerror signature > getsockopt: avoid compiler warning > tests: drop unused link dependency > hash, mgetgroups: drop xalloc dependency > xalloc-oversized: new module > utimecmp: drop dependency on xmalloc > getcwd: fix mingw bugs > Typo in comment. > mkstemps: Ensure declaration on MacOS X 10.5. > mkstemp: More documentation. > mkstemp: Tweak configure message when cross-compiling. > clean-temp: Clarify what it does. > fchdir: avoid extra chdir and fix test > filenamecat-lgpl: fix licence > linkat, renameat: add missing dependency > tests: reduce dependencies > save-cwd: reduce default dependency > getcwd: enhance tests > getcwd-lgpl: new module > getcwd: tweak comments > mkstemp: replace if system version uses wrong permissions > passfd: avoid compiler warning > Change gnulib-tool to support NetBSD's join > mkstemp: mention clean-temp module > inttypes: also provide default values for 32-bit tests > strtoumax: remove dependency on strtoimax > inttypes-incomplete: new module > inttypes: omit now-redundant strtoimax and strtoumax work > strtoimax, strtoumax: simplify, port to HP-UX 11.00 64-bit .gnulib | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/.gnulib b/.gnulib index 7d06b32..74175b9 160000 --- a/.gnulib +++ b/.gnulib @@ -1 +1 @@ -Subproject commit 7d06b32684363a39fae65c616b84bc7589768106 +Subproject commit 74175b903b1716c1677658e45fa69ef1fbc99015 -- 1.7.4.4 From veillard at redhat.com Fri Apr 29 01:02:55 2011 From: veillard at redhat.com (Daniel Veillard) Date: Fri, 29 Apr 2011 09:02:55 +0800 Subject: [libvirt] [PATCH] virsh: avoid compiler warning on mingw In-Reply-To: <1304025083-19787-1-git-send-email-eblake@redhat.com> References: <1304025083-19787-1-git-send-email-eblake@redhat.com> Message-ID: <20110429010255.GC21035@redhat.com> On Thu, Apr 28, 2011 at 03:11:23PM -0600, Eric Blake wrote: > We don't use gnulib's sanitizations for vfprintf, but vshDebug > was used with %zu, which means that it would fail on mingw. > Thank goodness the compiler indirectly caught this for us :) > > virsh.c: In function 'vshDebug': > virsh.c:12105:5: warning: function might be possible candidate for > 'ms_printf' format attribute [-Wmissing-format-attribute] > > since mingw hasn't yet added gcc attributes to vfprintf. > > * tools/virsh.c (vshDebug): Avoid vfprintf. > (vshPrintExtra): Use lighter-weight fputs. > Reported by Matthias Bolte. > --- > tools/virsh.c | 11 +++++++++-- > 1 files changed, 9 insertions(+), 2 deletions(-) > > diff --git a/tools/virsh.c b/tools/virsh.c > index 27140f3..0212b99 100644 > --- a/tools/virsh.c > +++ b/tools/virsh.c > @@ -12096,6 +12096,7 @@ static void > vshDebug(vshControl *ctl, int level, const char *format, ...) > { > va_list ap; > + char *str; > > va_start(ap, format); > vshOutputLogFile(ctl, VSH_ERR_DEBUG, format, ap); > @@ -12105,8 +12106,14 @@ vshDebug(vshControl *ctl, int level, const char *format, ...) > return; > > va_start(ap, format); > - vfprintf(stdout, format, ap); > + if (virVasprintf(&str, format, ap) < 0) { > + /* Skip debug messages on low memory */ > + va_end(ap); > + return; > + } > va_end(ap); > + fputs(str, stdout); > + VIR_FREE(str); > } > > static void > @@ -12125,7 +12132,7 @@ vshPrintExtra(vshControl *ctl, const char *format, ...) > return; > } > va_end(ap); > - fprintf(stdout, "%s", str); > + fputs(str, stdout); > VIR_FREE(str); > } ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From yuzhang at redhat.com Fri Apr 29 02:53:14 2011 From: yuzhang at redhat.com (Yufang Zhang) Date: Fri, 29 Apr 2011 10:53:14 +0800 Subject: [libvirt] [PATCH V3] xen: check if device is assigned to guest before reattaching In-Reply-To: <4DB9D22F.4040606@redhat.com> References: <1303906152-4601-1-git-send-email-yuzhang@redhat.com> <4DB9108C.4090804@redhat.com> <4DB9D22F.4040606@redhat.com> Message-ID: <4DBA281A.9050100@redhat.com> On 04/29/2011 04:46 AM, Eric Blake wrote: > On 04/28/2011 01:00 AM, Osier Yang wrote: >> ? 2011?04?27? 20:09, Yufang Zhang ??: >>> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=664059 >>> >>> This is the version3 patch for BZ#664059. > This sentence is not as useful in the commit message; it's handy in > reviews, but for someone using 'git am' to snarf the email message into > their own git tree, the way to convey that information is by putting it > after the '---' dividing line. That is, --- provides the boundary > between commit details and out-of-band review helps. > >>> Reattaching pci device back to >>> host without destroying guest or detaching device from guest would cause >>> host to crash. This patch adds a check before doing device reattach. If >>> the device is being assigned to guest, libvirt refuses to reattach device >>> to host. The patch only works for Xen, for it just checks xenstore to get >>> pci device information. This version fixes some formatting problem and moves >>> lock-unlock out of loop so that the check is atomic. >> We have same problem with qemu driver, though this patch looks fine >> and fix the problem for xen driver, IMHO it's not the ideal solution, >> ideally it will be nice if kernel could let us known if the device is >> still in use. I filed bug against kernel, no feedback yet though. > Link to that bug? > https://bugzilla.redhat.com/show_bug.cgi?id=667609 >>> Signed-off-by: Yufang Zhang >>> --- >>> src/xen/xen_driver.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ >>> 1 files changed, 67 insertions(+), 0 deletions(-) > ACK. > > I've added Yufang to AUTHORS (let me know off-list) if you prefer any > alternate spelling to your name and pushed this patch. > From veillard at redhat.com Fri Apr 29 03:30:30 2011 From: veillard at redhat.com (Daniel Veillard) Date: Fri, 29 Apr 2011 11:30:30 +0800 Subject: [libvirt] [PATCH] build: avoid test warnings on mingw In-Reply-To: <1304034123-7056-1-git-send-email-eblake@redhat.com> References: <1304034123-7056-1-git-send-email-eblake@redhat.com> Message-ID: <20110429033030.GD21035@redhat.com> On Thu, Apr 28, 2011 at 05:42:03PM -0600, Eric Blake wrote: > * .gnulib: Update to latest, for getaddrinfo fixes. > Reported by Matthias Bolte. > --- > > As promised, I've done the gnulib side of the mingw cleanups > affecting the issues Matthias found with 0.9.1-rc1. > > Oh, and now that gnulib getcwd-lgpl exists, we could use it > to fix our uses of getcwd(NULL,0), followup coming later. > > * .gnulib 7d06b32...74175b9 (29): [...] > diff --git a/.gnulib b/.gnulib > index 7d06b32..74175b9 160000 > --- a/.gnulib > +++ b/.gnulib > @@ -1 +1 @@ > -Subproject commit 7d06b32684363a39fae65c616b84bc7589768106 > +Subproject commit 74175b903b1716c1677658e45fa69ef1fbc99015 ACK, and we want this fixed in time for 0.9.1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ From jdenemar at redhat.com Fri Apr 29 07:07:13 2011 From: jdenemar at redhat.com (Jiri Denemark) Date: Fri, 29 Apr 2011 09:07:13 +0200 Subject: [libvirt] [PATCH 1/4] Fix error messages codes when TypeFromString fails In-Reply-To: <1303916266-31581-2-git-send-email-mprivozn@redhat.com> References: <1303916266-31581-1-git-send-email-mprivozn@redhat.com> <1303916266-31581-2-git-send-email-mprivozn@redhat.com> Message-ID: <20110429070713.GS1245361@orkuz.home> On Wed, Apr 27, 2011 at 16:57:43 +0200, Michal Privoznik wrote: > --- > src/conf/cpu_conf.c | 4 +- > src/conf/domain_conf.c | 100 ++++++++++++++++++----------------- > src/conf/interface_conf.c | 2 +- > src/conf/network_conf.c | 2 +- > src/conf/node_device_conf.c | 4 +- > src/conf/nwfilter_conf.c | 6 +- > src/conf/secret_conf.c | 2 +- > src/conf/storage_conf.c | 2 +- > src/conf/storage_encryption_conf.c | 4 +- > 9 files changed, 64 insertions(+), 62 deletions(-) > > diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c > index ad49916..db8b4bb 100644 > --- a/src/conf/cpu_conf.c > +++ b/src/conf/cpu_conf.c > @@ -156,7 +156,7 @@ virCPUDefParseXML(const xmlNodePtr node, > VIR_FREE(match); > > if (def->match < 0) { > - virCPUReportError(VIR_ERR_INTERNAL_ERROR, > + virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, > "%s", _("Invalid match attribute for CPU specification")); > goto error; > } ... I think all of these errors should really be changed to the new VIR_ERR_XML_CONFIG. This is not the case that a driver doesn't support particular value, it's that the value is not know to libvirt at all, i.e., it is an error in XML configuration file. Jirka From jyang at redhat.com Fri Apr 29 07:21:03 2011 From: jyang at redhat.com (Osier Yang) Date: Fri, 29 Apr 2011 15:21:03 +0800 Subject: [libvirt] [PATCH] lxc: Do not try to reconnect inactive domain when do lxcStartup Message-ID: <1304061663-8886-1-git-send-email-jyang@redhat.com> Otherwise if there are inactive lxc domains, lxcStartup will try to reconnect to sockets of these domains, which results in errors in libvirtd log. --- src/lxc/lxc_driver.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e905302..ef7827b 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -1992,6 +1992,9 @@ lxcReconnectVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque) virDomainObjLock(vm); + if (!virDomainObjIsActive(vm)) + goto cleanup; + priv = vm->privateData; if ((priv->monitor = lxcMonitorClient(driver, vm)) < 0) { goto cleanup; -- 1.7.4 From mprivozn at redhat.com Fri Apr 29 07:25:15 2011 From: mprivozn at redhat.com (=?ISO-8859-1?Q?Michal_Pr=EDvozn=EDk?=) Date: Fri, 29 Apr 2011 09:25:15 +0200 Subject: [libvirt] [PATCH 1/4] Fix error messages codes when TypeFromString fails In-Reply-To: <20110429070713.GS1245361@orkuz.home> References: <1303916266-31581-1-git-send-email-mprivozn@redhat.com> <1303916266-31581-2-git-send-email-mprivozn@redhat.com> <20110429070713.GS1245361@orkuz.home> Message-ID: <4DBA67DB.8060805@redhat.com> On 04/29/2011 09:07 AM, Jiri Denemark wrote: > On Wed, Apr 27, 2011 at 16:57:43 +0200, Michal Privoznik wrote: >> --- >> src/conf/cpu_conf.c | 4 +- >> src/conf/domain_conf.c | 100 ++++++++++++++++++----------------- >> src/conf/interface_conf.c | 2 +- >> src/conf/network_conf.c | 2 +- >> src/conf/node_device_conf.c | 4 +- >> src/conf/nwfilter_conf.c | 6 +- >> src/conf/secret_conf.c | 2 +- >> src/conf/storage_conf.c | 2 +- >> src/conf/storage_encryption_conf.c | 4 +- >> 9 files changed, 64 insertions(+), 62 deletions(-) >> >> diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c >> index ad49916..db8b4bb 100644 >> --- a/src/conf/cpu_conf.c >> +++ b/src/conf/cpu_conf.c >> @@ -156,7 +156,7 @@ virCPUDefParseXML(const xmlNodePtr node, >> VIR_FREE(match); >> >> if (def->match< 0) { >> - virCPUReportError(VIR_ERR_INTERNAL_ERROR, >> + virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, >> "%s", _("Invalid match attribute for CPU specification")); >> goto error; >> } > ... > > I think all of these errors should really be changed to the new > VIR_ERR_XML_CONFIG. This is not the case that a driver doesn't support > particular value, it's that the value is not know to libvirt at all, i.e., it > is an error in XML configuration file. > > Jirka I don't agree. If we add support for new value and somebody'll give older libvirt XML with new interface type, I think libvirt should say VIR_ERR_CONFIG_UNSUPPORTED. Michal From matthias.bolte at googlemail.com Fri Apr 29 07:26:14 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 29 Apr 2011 09:26:14 +0200 Subject: [libvirt] [PATCH] virsh: avoid compiler warning on mingw In-Reply-To: <1304025083-19787-1-git-send-email-eblake@redhat.com> References: <1304025083-19787-1-git-send-email-eblake@redhat.com> Message-ID: 2011/4/28 Eric Blake : > We don't use gnulib's sanitizations for vfprintf, but vshDebug > was used with %zu, which means that it would fail on mingw. > Thank goodness the compiler indirectly caught this for us :) > > virsh.c: In function 'vshDebug': > virsh.c:12105:5: warning: function might be possible candidate for > 'ms_printf' format attribute [-Wmissing-format-attribute] > > since mingw hasn't yet added gcc attributes to vfprintf. > > * tools/virsh.c (vshDebug): Avoid vfprintf. > (vshPrintExtra): Use lighter-weight fputs. > Reported by Matthias Bolte. > --- > ?tools/virsh.c | ? 11 +++++++++-- > ?1 files changed, 9 insertions(+), 2 deletions(-) > Fixes the warning, ACK. Matthias From matthias.bolte at googlemail.com Fri Apr 29 07:27:29 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 29 Apr 2011 09:27:29 +0200 Subject: [libvirt] [PATCH] build: avoid test warnings on mingw In-Reply-To: <1304034123-7056-1-git-send-email-eblake@redhat.com> References: <1304034123-7056-1-git-send-email-eblake@redhat.com> Message-ID: 2011/4/29 Eric Blake : > * .gnulib: Update to latest, for getaddrinfo fixes. > Reported by Matthias Bolte. > --- > > As promised, I've done the gnulib side of the mingw cleanups > affecting the issues Matthias found with 0.9.1-rc1. > > Oh, and now that gnulib getcwd-lgpl exists, we could use it > to fix our uses of getcwd(NULL,0), followup coming later. > > * .gnulib 7d06b32...74175b9 (29): > ?> getaddrinfo: fix gai_strerror signature > ?> getsockopt: avoid compiler warning > ?> tests: drop unused link dependency > ?> hash, mgetgroups: drop xalloc dependency > ?> xalloc-oversized: new module > ?> utimecmp: drop dependency on xmalloc > ?> getcwd: fix mingw bugs > ?> Typo in comment. > ?> mkstemps: Ensure declaration on MacOS X 10.5. > ?> mkstemp: More documentation. > ?> mkstemp: Tweak configure message when cross-compiling. > ?> clean-temp: Clarify what it does. > ?> fchdir: avoid extra chdir and fix test > ?> filenamecat-lgpl: fix licence > ?> linkat, renameat: add missing dependency > ?> tests: reduce dependencies > ?> save-cwd: reduce default dependency > ?> getcwd: enhance tests > ?> getcwd-lgpl: new module > ?> getcwd: tweak comments > ?> mkstemp: replace if system version uses wrong permissions > ?> passfd: avoid compiler warning > ?> Change gnulib-tool to support NetBSD's join > ?> mkstemp: mention clean-temp module > ?> inttypes: also provide default values for 32-bit tests > ?> strtoumax: remove dependency on strtoimax > ?> inttypes-incomplete: new module > ?> inttypes: omit now-redundant strtoimax and strtoumax work > ?> strtoimax, strtoumax: simplify, port to HP-UX 11.00 64-bit > > ?.gnulib | ? ?2 +- > ?1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/.gnulib b/.gnulib > index 7d06b32..74175b9 160000 > --- a/.gnulib > +++ b/.gnulib > @@ -1 +1 @@ > -Subproject commit 7d06b32684363a39fae65c616b84bc7589768106 > +Subproject commit 74175b903b1716c1677658e45fa69ef1fbc99015 Compiles fine on mingw now, ACK. Matthias From matthias.bolte at googlemail.com Fri Apr 29 07:30:55 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 29 Apr 2011 09:30:55 +0200 Subject: [libvirt] [Libvirt-announce] Libvirt 0.9.1 week freeze, RC1 version to test In-Reply-To: <4DB9D696.9030501@redhat.com> References: <20110428035115.GA21035@redhat.com> <4DB9D696.9030501@redhat.com> Message-ID: 2011/4/28 Eric Blake : > On 04/28/2011 01:33 AM, Matthias Bolte wrote: >> libvirt compiles fine but virsh has a warning about vfprintf: >> >> virsh.c: In function 'vshDebug': >> virsh.c:12105:5: warning: function might be possible candidate for >> 'ms_printf' format attribute [-Wmissing-format-attribute] >> >> I'm no sure where to fix that. > > In mingw's . ?But we can't do that. > > vfprintf is NOT being provided by gnulib, so it does NOT understand %zu > or %llu. ?Yet we use it with %zu. > > So the only real solution is to use virAsprintf (which _does_ understand > %zu, thanks to gnulib) and make vshDebug go through an intermediate > buffer, then use fputs on that string, rather than relying directly on > the unsanitized vfprintf. ?Patch coming up shortly. Yep, fixed now. >> >> make check shows two warnings in gnulib. Maybe Eric wants to take a look: >> >> getsockopt.c: In function 'rpl_getsockopt': >> getsockopt.c:51:7: warning: passing argument 4 of 'getsockopt' from >> incompatible pointer type >> c:\dev\msys_setup\mingw\bin\../lib/gcc/mingw32/4.5.0/../../../../include/winsock2.h:543:32: >> note: expected 'char *' but argument is of type 'int *' > > Yep, I can fix that one in gnulib; I'll have a counterpart patch to bump > .gnulib to the latest once I've got it done. > >> >> test-getaddrinfo.c:28:1: warning: initialization from incompatible pointer type > > Probably the same category of gnulib fix. Also fixed now. >> Aside from that the rest seems to work fine. > > So I fixed the non-blocking pipe issues that broke 0.9.0 virsh > out-of-the-box? ?Good to hear. At least the call to virEventRegisterDefaultImpl in virsh doesn't fail anymore, so the pipe setup and stuff seems to work, or at least does not fail anymore. :) Current git + pending (but already ACK'ed) patches from Eric compiles and works fine on mingw, as far as I can tell. Matthias From laine at laine.org Fri Apr 29 12:45:50 2011 From: laine at laine.org (Laine Stump) Date: Fri, 29 Apr 2011 08:45:50 -0400 Subject: [libvirt] migration of vnlink VMs In-Reply-To: <632295223.309151.1303978515554.JavaMail.root@zmail02.collab.prod.int.phx2.redhat.com> References: <632295223.309151.1303978515554.JavaMail.root@zmail02.collab.prod.int.phx2.redhat.com> Message-ID: <4DBAB2FE.8090507@laine.org> On 04/28/2011 04:15 AM, Oved Ourfalli wrote: >> From: "Laine Stump"> On 04/27/2011 09:58 AM, Oved Ourfalli wrote: >>> Laine, hello. >>> >>> We read your proposal for abstraction of guest<--> host network >>> connection in libvirt. >>> >>> You has an open issue there regarding the vepa/vnlink attributes: >>> "3) What about the parameters in the element that are >>> currently used by vepa/vnlink. Do those belong with the host, or >>> with the guest?" >>> >>> The parameters for the virtualport element should be on the guest, >>> and not the host, because a specific interface can run multiple >>> profiles, >> Are you talking about host interface or guest interface? If you mean >> that multiple different profiles can be used when connecting to a >> particular switch - as long as there are only a few different >> profiles, >> rather than each guest having its own unique profile, then it still >> seems better to have the port profile live with the network definition >> (and just define multiple networks, one for each port profile). >> > The profile names can be changed regularly, so it looks like it will be better to put them in the guest level, so that the network host file won't have to be changed on all hosts once something has changed in the profiles. > > Also, you will have a duplication of data, writing all the profile name on all the hosts that are connected to the vn-link/vepa switch. But is it potentially the same for many/all guests, or is it necessarily different for every guest? If it's the former, then do you have more guests, or more hosts? >>> so it will be a mistake to define a profile to be interface >>> specific on the host. Moreover, putting it in the guest level will >>> enable us in the future (if supported by libvirt/qemu) to migrate >>> a vm from a host with vepa/vnlink interfaces, to another host with >>> a bridge, for example. >> It seems to me like doing exactly the opposite would make it easier to >> migrate to a host that used a different kind of switching (from vepa >> to >> vnlink, or from a bridged interface to vepa, etc), since the port >> profile required for a particular host's network would be at the host >> waiting to be used. > You are right, but we would want to have the option to prevent that from happening in case we wouldn't want to allow it. > We can make the ability to migrate between different network types configurable, and we would like an easy way to tell libvirt - "please allow/don't allow it". I *think* what you're getting at is this situation: HostA has a group of interfaces that are connected to a vepa-capable switch, HostB has a group of interfaces connected to a vnlink-capable switch. Guest1 is allowed to connect either via a vnlink switch or a vepa switch, but Guest2 should only use vepa. In that case, HostA would have a network that had a pool of interfaces and type "vepa", while HostB would have a pool of interfaces and a type "vnlink". Guest1 could be accommodated by giving both networks the same name, or Guest2 could be accommodated by giving each network a different name (when migrating, if the dest. host doesn't have the desired network, the migration would fail). However, using just the network naming, it wouldn't be possible to allow both. I don't think keeping the virtualport parameters only with the guest would help (or hurt) this though. What would be needed would be to have the information about network type *optionally* specified in the guest interface config (as well as in the network config); if present the migration would only succeed if the given network on the dest host matched the given type (and parameters, if any) in the guest config. >>> So, in the networks at the host level you will have: >>> >>> red-network >>> >>> >>> >>> eth0 >>> ..... >>> >>> >>> eth4 >>> ..... >>> >>> >>> eth18 >>> ..... >>> >>> >>> >>> >>> >>> And in the guest you will have (for vepa): >>> >>> >>> >>> >> instanceid="09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f"/> >>> >>> >>> >>> Or (for vnlink): >>> >>> >>> >>> >>> >>> What would the interface for a 2nd guest of each type look like? Could it be identical? Or might some parameters change for every single guest? Perhaps it would be best to have virtualport parameters on both network and guest interface XML, and merge the two to arrive at what's used (the network definition could contain all the attributes that would be common to all guests using that network on that host, and the guest interface definition would contain extra parameters specific to that host. In the case of a parameter being specified in both places, if they were not identical, the migration would fail). >> This illustrates the problem I was wondering about - in your example >> it >> would not be possible for the guest to migrate from the host using a >> vepa switch to the host using a vnlink switch (and it would be >> possible > You are right. When trying to migrate between vepa and vnlink there will be missing attributes in each in case we leave it on the host. (you mean if we leave the config on the *guest*, I guess...) >> to migrate to a host using a standard bridge only if the virtualport >> element was ignored). If the virtualport element lived with the >> network >> definition of red-network on each host, it could be migrated without >> problem. >> >> The only problematic thing would be if any of the attributes within >> was unique for each guest (I don't know anything about >> the >> individual attributes, but "instanceid" sounds like it might be >> different for each guest). >>> Then, when migrating from a vepa/vnlink host to another vepa/vnlink >>> host containing red-network, the profile attributes will be >>> available at the guest domain xml. >>> In case the target host has a red-network, which isn't vepa/vnlink, >>> we want to be able to choose whether to make the use of the profile >>> attributes optional (i.e., libvirt won't fail in case of migrating >>> to a network of another type), or mandatory (i.e., libvirt will fail >>> in case of migration to a non-vepa/vnlink network). >>> >>> We have something similar in CPU flags: >>> >>> qemu64 >>> >>> >> name="sse2"/> >>> >> In this analogy, does "CPU flags" == "mode (vepa/vnlink/bridge)" or >> does >> "CPU flags" == "virtualport parameters" ? It seems like what you're >> wanting can be satisfied by simply not defining "red-network" on the >> hosts that don't have the proper networking setup available (maybe >> what >> you *really* want to call it is "red-vnlink-network"). > What I meant to say in that is that we would like to have the ability to say if an attribute must me used, or not. Sure, it sounds useful. Would what I outlined above be sufficient? (It would allow you to say "this guest must have a vepa network connection" or "this guest can have any network connection, as long as it's named "red-network". It *won't* allow saying "this guest must have vepa or vnlink, bridge is not allowed, even if the network name is the same". You could also put most of the config with the host network definition, but allow, eg instanceid to be specified in the guest config. > The issues you mention are indeed interesting. I'm cc-ing libvirt-list to see what other people think. > Putting it on the guest will indeed make it problematic to migrate between networks that need different parameters (vnlink/vepa for example). From ovedo at redhat.com Fri Apr 29 13:29:50 2011 From: ovedo at redhat.com (Oved Ourfalli) Date: Fri, 29 Apr 2011 09:29:50 -0400 (EDT) Subject: [libvirt] migration of vnlink VMs In-Reply-To: <4DBAB2FE.8090507@laine.org> Message-ID: <333863871.338650.1304083790897.JavaMail.root@zmail02.collab.prod.int.phx2.redhat.com> See my comments below. Thank you, Oved ----- Original Message ----- > From: "Laine Stump" > To: libvir-list at redhat.com > Sent: Friday, April 29, 2011 3:45:50 PM > Subject: Re: [libvirt] migration of vnlink VMs > On 04/28/2011 04:15 AM, Oved Ourfalli wrote: > >> From: "Laine Stump" >> On 04/27/2011 09:58 AM, Oved Ourfalli wrote: > >>> Laine, hello. > >>> > >>> We read your proposal for abstraction of guest<--> host network > >>> connection in libvirt. > >>> > >>> You has an open issue there regarding the vepa/vnlink attributes: > >>> "3) What about the parameters in the element that are > >>> currently used by vepa/vnlink. Do those belong with the host, or > >>> with the guest?" > >>> > >>> The parameters for the virtualport element should be on the guest, > >>> and not the host, because a specific interface can run multiple > >>> profiles, > >> Are you talking about host interface or guest interface? If you > >> mean > >> that multiple different profiles can be used when connecting to a > >> particular switch - as long as there are only a few different > >> profiles, > >> rather than each guest having its own unique profile, then it still > >> seems better to have the port profile live with the network > >> definition > >> (and just define multiple networks, one for each port profile). > >> > > The profile names can be changed regularly, so it looks like it will > > be better to put them in the guest level, so that the network host > > file won't have to be changed on all hosts once something has > > changed in the profiles. > > > > Also, you will have a duplication of data, writing all the profile > > name on all the hosts that are connected to the vn-link/vepa switch. > > But is it potentially the same for many/all guests, or is it > necessarily > different for every guest? If it's the former, then do you have more > guests, or more hosts? > I guess it will be the same for many guests. There will be some profiles, and each group of guests will use the same profile, according to its demands. > > >>> so it will be a mistake to define a profile to be interface > >>> specific on the host. Moreover, putting it in the guest level > >>> will > >>> enable us in the future (if supported by libvirt/qemu) to > >>> migrate > >>> a vm from a host with vepa/vnlink interfaces, to another host > >>> with > >>> a bridge, for example. > >> It seems to me like doing exactly the opposite would make it easier > >> to > >> migrate to a host that used a different kind of switching (from > >> vepa > >> to > >> vnlink, or from a bridged interface to vepa, etc), since the port > >> profile required for a particular host's network would be at the > >> host > >> waiting to be used. > > You are right, but we would want to have the option to prevent that > > from happening in case we wouldn't want to allow it. > > We can make the ability to migrate between different network types > > configurable, and we would like an easy way to tell libvirt - > > "please allow/don't allow it". > > I *think* what you're getting at is this situation: > > HostA has a group of interfaces that are connected to a vepa-capable > switch, HostB has a group of interfaces connected to a vnlink-capable > switch. Guest1 is allowed to connect either via a vnlink switch or a > vepa switch, but Guest2 should only use vepa. > > In that case, HostA would have a network that had a pool of interfaces > and type "vepa", while HostB would have a pool of interfaces and a > type > "vnlink". Guest1 could be accommodated by giving both networks the > same > name, or Guest2 could be accommodated by giving each network a > different > name (when migrating, if the dest. host doesn't have the desired > network, the migration would fail). However, using just the network > naming, it wouldn't be possible to allow both. > > I don't think keeping the virtualport parameters only with the guest > would help (or hurt) this though. What would be needed would be to > have > the information about network type *optionally* specified in the guest > interface config (as well as in the network config); if present the > migration would only succeed if the given network on the dest host > matched the given type (and parameters, if any) in the guest config. > That would be great. It will enable the flexibility we need. > > >>> So, in the networks at the host level you will have: > >>> > >>> red-network > >>> > >>> > >>> > >>> eth0 > >>> ..... > >>> > >>> > >>> eth4 > >>> ..... > >>> > >>> > >>> eth18 > >>> ..... > >>> > >>> > >>> > >>> > >>> > >>> And in the guest you will have (for vepa): > >>> > >>> > >>> > >>> >>> instanceid="09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f"/> > >>> > >>> > >>> > >>> Or (for vnlink): > >>> > >>> > >>> > >>> > >>> > >>> > > What would the interface for a 2nd guest of each type look like? Could > it be identical? Or might some parameters change for every single > guest? For vn-link it will be the same, just the profile_name. As for vepa, the instanceid is vm specific so it should be on the guest (taken from http://libvirt.org/formatdomain.html): "managerid - The VSI Manager ID identifies the database containing the VSI type and instance definitions. This is an integer value and the value 0 is reserved. typeid - The VSI Type ID identifies a VSI type characterizing the network access. VSI types are typically managed by network administrator. This is an integer value. typeidversion - The VSI Type Version allows multiple versions of a VSI Type. This is an integer value. instanceid - The VSI Instance ID Identifier is generated when a VSI instance (i.e. a virtual interface of a virtual machine) is created. This is a globally unique identifier." That's what we know on vepa an vn-link now. I guess that when we'll have the possibility to test these environments we will learn more on them. > Perhaps it would be best to have virtualport parameters on both > network > and guest interface XML, and merge the two to arrive at what's used > (the > network definition could contain all the attributes that would be > common > to all guests using that network on that host, and the guest interface > definition would contain extra parameters specific to that host. In > the > case of a parameter being specified in both places, if they were not > identical, the migration would fail). > Sounds good. > >> This illustrates the problem I was wondering about - in your > >> example > >> it > >> would not be possible for the guest to migrate from the host using > >> a > >> vepa switch to the host using a vnlink switch (and it would be > >> possible > > You are right. When trying to migrate between vepa and vnlink there > > will be missing attributes in each in case we leave it on the host. > > (you mean if we leave the config on the *guest*, I guess...) > > >> to migrate to a host using a standard bridge only if the > >> virtualport > >> element was ignored). If the virtualport element lived with the > >> network > >> definition of red-network on each host, it could be migrated > >> without > >> problem. > >> > >> The only problematic thing would be if any of the attributes within > >> was unique for each guest (I don't know anything about > >> the > >> individual attributes, but "instanceid" sounds like it might be > >> different for each guest). > >>> Then, when migrating from a vepa/vnlink host to another > >>> vepa/vnlink > >>> host containing red-network, the profile attributes will be > >>> available at the guest domain xml. > >>> In case the target host has a red-network, which isn't > >>> vepa/vnlink, > >>> we want to be able to choose whether to make the use of the > >>> profile > >>> attributes optional (i.e., libvirt won't fail in case of migrating > >>> to a network of another type), or mandatory (i.e., libvirt will > >>> fail > >>> in case of migration to a non-vepa/vnlink network). > >>> > >>> We have something similar in CPU flags: > >>> > >>> qemu64 > >>> > >>> >>> name="sse2"/> > >>> > >> In this analogy, does "CPU flags" == "mode (vepa/vnlink/bridge)" or > >> does > >> "CPU flags" == "virtualport parameters" ? It seems like what you're > >> wanting can be satisfied by simply not defining "red-network" on > >> the > >> hosts that don't have the proper networking setup available (maybe > >> what > >> you *really* want to call it is "red-vnlink-network"). > > What I meant to say in that is that we would like to have the > > ability to say if an attribute must me used, or not. > > Sure, it sounds useful. Would what I outlined above be sufficient? (It > would allow you to say "this guest must have a vepa network > connection" > or "this guest can have any network connection, as long as it's named > "red-network". It *won't* allow saying "this guest must have vepa or > vnlink, bridge is not allowed, even if the network name is the same". > You could also put most of the config with the host network > definition, > but allow, eg instanceid to be specified in the guest config. > I think this would indeed be enough. > > The issues you mention are indeed interesting. I'm cc-ing > > libvirt-list to see what other people think. > > Putting it on the guest will indeed make it problematic to migrate > > between networks that need different parameters (vnlink/vepa for > > example). > > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list From eblake at redhat.com Fri Apr 29 15:02:19 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 09:02:19 -0600 Subject: [libvirt] [PATCH] virsh: avoid compiler warning on mingw In-Reply-To: <20110429010255.GC21035@redhat.com> References: <1304025083-19787-1-git-send-email-eblake@redhat.com> <20110429010255.GC21035@redhat.com> Message-ID: <4DBAD2FB.5060902@redhat.com> On 04/28/2011 07:02 PM, Daniel Veillard wrote: > On Thu, Apr 28, 2011 at 03:11:23PM -0600, Eric Blake wrote: >> We don't use gnulib's sanitizations for vfprintf, but vshDebug >> was used with %zu, which means that it would fail on mingw. >> Thank goodness the compiler indirectly caught this for us :) >> >> virsh.c: In function 'vshDebug': >> virsh.c:12105:5: warning: function might be possible candidate for >> 'ms_printf' format attribute [-Wmissing-format-attribute] >> >> since mingw hasn't yet added gcc attributes to vfprintf. >> >> * tools/virsh.c (vshDebug): Avoid vfprintf. >> (vshPrintExtra): Use lighter-weight fputs. >> Reported by Matthias Bolte. > > ACK, Thanks; pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 29 15:11:13 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 09:11:13 -0600 Subject: [libvirt] [PATCH] lxc: Do not try to reconnect inactive domain when do lxcStartup In-Reply-To: <1304061663-8886-1-git-send-email-jyang@redhat.com> References: <1304061663-8886-1-git-send-email-jyang@redhat.com> Message-ID: <4DBAD511.6020203@redhat.com> On 04/29/2011 01:21 AM, Osier Yang wrote: > Otherwise if there are inactive lxc domains, lxcStartup will > try to reconnect to sockets of these domains, which results in > errors in libvirtd log. > --- > src/lxc/lxc_driver.c | 3 +++ > 1 files changed, 3 insertions(+), 0 deletions(-) ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 29 15:12:19 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 09:12:19 -0600 Subject: [libvirt] [PATCH] build: avoid test warnings on mingw In-Reply-To: References: <1304034123-7056-1-git-send-email-eblake@redhat.com> Message-ID: <4DBAD553.9080004@redhat.com> On 04/29/2011 01:27 AM, Matthias Bolte wrote: > 2011/4/29 Eric Blake : >> * .gnulib: Update to latest, for getaddrinfo fixes. >> Reported by Matthias Bolte. >> --- >> >> As promised, I've done the gnulib side of the mingw cleanups >> affecting the issues Matthias found with 0.9.1-rc1. >> > > Compiles fine on mingw now, ACK. Thanks; pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From paolo.smiraglia at polito.it Fri Apr 29 16:13:46 2011 From: paolo.smiraglia at polito.it (Paolo Smiraglia) Date: Fri, 29 Apr 2011 18:13:46 +0200 Subject: [libvirt] Libvirt and IPSec (was: What about Trusted Virtual Domains???) In-Reply-To: <4D9C6663.3030504@polito.it> References: <4D9C6663.3030504@polito.it> Message-ID: <4DBAE3BA.7060609@polito.it> Hi to everyone! Sorry for the latency of the response but me and my team we are noticed that the TVD argument can not be treated only with a few lines in some mails. In order to avoid any possible misunderstanding, we decided to produce a little report (just four pages with images) that describes our project. Technical details are not treated in the report. You can download the report by using the link http://dl.dropbox.com/u/824617/tvd_in_libvirt.pdf Our idea is to start the discussion about Libvirt TVD implementation using as starting point the report. As already mentioned in previous mail, we think that the first step for the implementation of the TVD is to make possible the 'tunnel' modeling in Libvirt. Considering the report, what do you think about our tunnel modeling idea? It's right or some changes are needed? Thanks for the patience and (in advance) for the replies... ;-) -- PAOLO SMIRAGLIA Department of Control and Computer Engineering Polytechnic University of Turin Email: paolo.smiraglia at polito.it -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 6095 bytes Desc: S/MIME Cryptographic Signature URL: From crobinso at redhat.com Fri Apr 29 17:29:08 2011 From: crobinso at redhat.com (Cole Robinson) Date: Fri, 29 Apr 2011 13:29:08 -0400 Subject: [libvirt] [PATCH] docs: Document device Message-ID: <1304098148-11880-1-git-send-email-crobinso@redhat.com> Tried to dredge through old changelogs and commits to come up with it, so may not be completely accurate. Signed-off-by: Cole Robinson --- docs/formatdomain.html.in | 107 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 107 insertions(+), 0 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index a055b38..eafb983 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -903,6 +903,113 @@ +

    Filesystems

    + +

    + A directory on the host that can be accessed directly from the guest. + since 0.3.3 for containers, since 0.8.5 for QEMU/KVM +

    + +
    +  ...
    +  <devices>
    +    <filesystem type='template'>
    +      <source name='my-vm-template'/>
    +      <target dir='/'/>
    +    </filesystem>
    +    <filesystem type='mount' >
    +      <source dir='/export/to/guest'/>
    +      <target dir='/import/from/host'/>
    +      <readonly/>
    +    </filesystem>
    +    ...
    +  </devices>
    +  ...
    + +
    +
    filesystem
    +
    + + The filesystem attribute type specifies the type of the + source. The possible values are: + +
    +
    type='mount'
    +
    + A host directory to mount in the guest. Used by LXC, + OpenVZ (since 0.6.2) + and QEMU/KVM (since 0.8.5). + This is the default mode if one is not specified. +
    +
    type='template'
    +
    + OpenVZ filesystem template. Only used by OpenVZ driver. +
    +
    type='file'
    +
    + Currently unused. +
    +
    type='block'
    +
    + Currently unused. +
    +
    + + The filesystem block has an optional attribute mode + which specifies the security mode for accessing the source + (since 0.8.5). Currently this only works + with type='mount' for the QEMU/KVM driver. The possible + values are: + +
    +
    mode='passthrough'
    +
    + The source is accessed with the permissions of the + user inside the guest. This is the default mode if + one is not specified. + More info +
    +
    mode='mapped'
    +
    + The source is accessed with the permissions of the + hypervisor (QEMU process). + More info +
    +
    mode='squash'
    +
    + Similar to 'passthrough', the exception is that failure of + privileged operations like 'chown' are ignored. This makes a + passthrough-like mode usable for people who run the hypervisor + as non-root. + More info +
    +
    + +
    + +
    source
    +
    + The resource on the host that is being accessed in the guest. The + name attribute must be used with + type='template', and the dir attribute must + be used with type='mount' +
    + +
    target
    +
    + Where the source can be accessed in the guest. For + most drivers this is an automatic mount point, but for QEMU/KVM + this is merely an arbitrary string tag that is exported to the + guest as a hint for where to mount. +
    + +
    readonly
    +
    + An optional readonly attribute is available but currently + unused. +
    +
    +

    Controllers

    -- 1.7.4 From eblake at redhat.com Fri Apr 29 17:29:30 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 11:29:30 -0600 Subject: [libvirt] [PATCH 1/2] tests: simplify common setup In-Reply-To: <1304034123-7056-1-git-send-email-eblake@redhat.com> References: <1304034123-7056-1-git-send-email-eblake@redhat.com> Message-ID: <1304098171-15981-1-git-send-email-eblake@redhat.com> A few of the tests were missing basic sanity checks, while most of them were doing copy-and-paste initialization (in fact, some of them pasted the argc > 1 check more than once!). It's much nicer to do things in one common place, and minimizes the size of the next patch that fixes getcwd usage. * tests/testutils.h (EXIT_AM_HARDFAIL): New define. (progname, abs_srcdir): Define for all tests. (VIRT_TEST_MAIN): Change callback signature. * tests/testutils.c (virtTestMain): Do more common init. * tests/commandtest.c (mymain): Simplify. * tests/cputest.c (mymain): Likewise. * tests/esxutilstest.c (mymain): Likewise. * tests/eventtest.c (mymain): Likewise. * tests/hashtest.c (mymain): Likewise. * tests/networkxml2xmltest.c (mymain): Likewise. * tests/nodedevxml2xmltest.c (myname): Likewise. * tests/nodeinfotest.c (mymain): Likewise. * tests/nwfilterxml2xmltest.c (mymain): Likewise. * tests/qemuargv2xmltest.c (mymain): Likewise. * tests/qemuhelptest.c (mymain): Likewise. * tests/qemuxml2argvtest.c (mymain): Likewise. * tests/qemuxml2xmltest.c (mymain): Likewise. * tests/qparamtest.c (mymain): Likewise. * tests/sexpr2xmltest.c (mymain): Likewise. * tests/sockettest.c (mymain): Likewise. * tests/statstest.c (mymain): Likewise. * tests/storagepoolxml2xmltest.c (mymain): Likewise. * tests/storagevolxml2xmltest.c (mymain): Likewise. * tests/virbuftest.c (mymain): Likewise. * tests/virshtest.c (mymain): Likewise. * tests/vmx2xmltest.c (mymain): Likewise. * tests/xencapstest.c (mymain): Likewise. * tests/xmconfigtest.c (mymain): Likewise. * tests/xml2sexprtest.c (mymain): Likewise. * tests/xml2vmxtest.c (mymain): Likewise. --- tests/commandtest.c | 18 +----------------- tests/cputest.c | 18 ++---------------- tests/esxutilstest.c | 17 +---------------- tests/eventtest.c | 11 +---------- tests/hashtest.c | 3 +-- tests/interfacexml2xmltest.c | 17 +---------------- tests/networkxml2xmltest.c | 17 +---------------- tests/nodedevxml2xmltest.c | 17 +---------------- tests/nodeinfotest.c | 17 +---------------- tests/nwfilterxml2xmltest.c | 17 +---------------- tests/qemuargv2xmltest.c | 16 +--------------- tests/qemuhelptest.c | 17 +---------------- tests/qemuxml2argvtest.c | 16 +--------------- tests/qemuxml2xmltest.c | 16 +--------------- tests/qparamtest.c | 3 +-- tests/sexpr2xmltest.c | 21 +-------------------- tests/sockettest.c | 5 ++--- tests/statstest.c | 3 +-- tests/storagepoolxml2xmltest.c | 17 +---------------- tests/storagevolxml2xmltest.c | 17 +---------------- tests/testutils.c | 29 +++++++++++++++++++++++------ tests/testutils.h | 15 ++++++++++----- tests/virbuftest.c | 3 +-- tests/virshtest.c | 18 +++--------------- tests/vmx2xmltest.c | 23 +---------------------- tests/xencapstest.c | 17 +---------------- tests/xmconfigtest.c | 18 ++---------------- tests/xml2sexprtest.c | 16 +--------------- tests/xml2vmxtest.c | 23 +---------------------- 29 files changed, 65 insertions(+), 380 deletions(-) diff --git a/tests/commandtest.c b/tests/commandtest.c index c313a2c..509c888 100644 --- a/tests/commandtest.c +++ b/tests/commandtest.c @@ -46,10 +46,6 @@ mymain(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) #else -static char *progname; -static char *abs_srcdir; - - static int checkoutput(const char *testname) { int ret = -1; @@ -754,23 +750,11 @@ cleanup: } static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; int fd; - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return(EXIT_FAILURE); - } - if (chdir("/tmp") < 0) return(EXIT_FAILURE); diff --git a/tests/cputest.c b/tests/cputest.c index bd06958..a8d28dc 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -1,7 +1,7 @@ /* * cputest.c: Test the libvirtd internal CPU APIs * - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -39,8 +39,6 @@ #include "cpu/cpu.h" #include "cpu/cpu_map.h" -static const char *progname; -static const char *abs_srcdir; static const char *abs_top_srcdir; #define VIR_FROM_THIS VIR_FROM_CPU @@ -494,23 +492,11 @@ static const char *nomodel[] = { "nomodel" }; static const char *models[] = { "qemu64", "core2duo", "Nehalem" }; static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; char map[PATH_MAX]; - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return EXIT_FAILURE; - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); - abs_top_srcdir = getenv("abs_top_srcdir"); if (!abs_top_srcdir) abs_top_srcdir = ".."; diff --git a/tests/esxutilstest.c b/tests/esxutilstest.c index b6bf87b..830f79c 100644 --- a/tests/esxutilstest.c +++ b/tests/esxutilstest.c @@ -14,9 +14,6 @@ # include "esx/esx_util.h" # include "esx/esx_vi_types.h" -static char *progname; - - static void testQuietError(void *userData ATTRIBUTE_UNUSED, @@ -323,22 +320,10 @@ testConvertWindows1252ToUTF8(const void *data ATTRIBUTE_UNUSED) static int -mymain(int argc, char **argv) +mymain(void) { int result = 0; - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return EXIT_FAILURE; - } - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return EXIT_FAILURE; - } - virSetErrorFunc(NULL, testQuietError); # define DO_TEST(_name) \ diff --git a/tests/eventtest.c b/tests/eventtest.c index eb4b755..4c45860 100644 --- a/tests/eventtest.c +++ b/tests/eventtest.c @@ -259,20 +259,12 @@ resetAll(void) } static int -mymain(int argc, char **argv) +mymain(void) { - char *progname; int i; pthread_t eventThread; char one = '1'; - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return EXIT_FAILURE; - } - for (i = 0 ; i < NUM_FDS ; i++) { if (pipe(handles[i].pipeFD) < 0) { fprintf(stderr, "Cannot create pipe: %d", errno); @@ -483,5 +475,4 @@ mymain(int argc, char **argv) return EXIT_SUCCESS; } - VIRT_TEST_MAIN(mymain) diff --git a/tests/hashtest.c b/tests/hashtest.c index bb3a812..525ae06 100644 --- a/tests/hashtest.c +++ b/tests/hashtest.c @@ -476,8 +476,7 @@ cleanup: static int -mymain(int argc ATTRIBUTE_UNUSED, - char **argv ATTRIBUTE_UNUSED) +mymain(void) { int ret = 0; diff --git a/tests/interfacexml2xmltest.c b/tests/interfacexml2xmltest.c index 094ccf5..fb454c1 100644 --- a/tests/interfacexml2xmltest.c +++ b/tests/interfacexml2xmltest.c @@ -13,9 +13,6 @@ #include "interface_conf.h" #include "testutilsqemu.h" -static char *progname; -static char *abs_srcdir; - #define MAX_FILE 4096 @@ -57,21 +54,9 @@ static int testCompareXMLToXMLHelper(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return (EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); #define DO_TEST(name) \ if (virtTestRun("Interface XML-2-XML " name, \ diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c index 7805548..f7489f5 100644 --- a/tests/networkxml2xmltest.c +++ b/tests/networkxml2xmltest.c @@ -13,9 +13,6 @@ #include "network_conf.h" #include "testutilsqemu.h" -static char *progname; -static char *abs_srcdir; - #define MAX_FILE 4096 @@ -64,21 +61,9 @@ static int testCompareXMLToXMLHelper(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return (EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); #define DO_TEST(name) \ if (virtTestRun("Network XML-2-XML " name, \ diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c index 2bc6743..f6a1335 100644 --- a/tests/nodedevxml2xmltest.c +++ b/tests/nodedevxml2xmltest.c @@ -13,9 +13,6 @@ #include "node_device_conf.h" #include "testutilsqemu.h" -static char *progname; -static char *abs_srcdir; - #define MAX_FILE 4096 @@ -57,21 +54,9 @@ static int testCompareXMLToXMLHelper(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return (EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); #define DO_TEST(name) \ if (virtTestRun("Node device XML-2-XML " name, \ diff --git a/tests/nodeinfotest.c b/tests/nodeinfotest.c index c690403..9a87dc0 100644 --- a/tests/nodeinfotest.c +++ b/tests/nodeinfotest.c @@ -21,9 +21,6 @@ mymain(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) #else -static char *progname; -static char *abs_srcdir; - # define MAX_FILE 4096 extern int linuxNodeInfoCPUPopulate(FILE *cpuinfo, virNodeInfoPtr nodeinfo, @@ -89,7 +86,7 @@ static int linuxTestNodeInfo(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; int i; @@ -101,18 +98,6 @@ mymain(int argc, char **argv) "nodeinfo-5", "nodeinfo-6", }; - char cwd[PATH_MAX]; - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return(EXIT_FAILURE); - } if (virInitialize() < 0) return EXIT_FAILURE; diff --git a/tests/nwfilterxml2xmltest.c b/tests/nwfilterxml2xmltest.c index 575177a..a1f57fa 100644 --- a/tests/nwfilterxml2xmltest.c +++ b/tests/nwfilterxml2xmltest.c @@ -16,9 +16,6 @@ #include "nwfilter_conf.h" #include "testutilsqemu.h" -static char *progname; -static char *abs_srcdir; - #define MAX_FILE 4096 @@ -85,21 +82,9 @@ static int testCompareXMLToXMLHelper(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return (EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); #define DO_TEST(NAME, EXPECT_WARN) \ do { \ diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c index 0214db0..60dce46 100644 --- a/tests/qemuargv2xmltest.c +++ b/tests/qemuargv2xmltest.c @@ -16,8 +16,6 @@ # include "testutilsqemu.h" -static char *progname; -static char *abs_srcdir; static struct qemud_driver driver; # define MAX_FILE 4096 @@ -103,21 +101,9 @@ static int testCompareXMLToArgvHelper(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return (EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); if ((driver.caps = testQemuCapsInit()) == NULL) return EXIT_FAILURE; diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index c86c578..792b5ab 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -19,9 +19,6 @@ struct testInfo { unsigned int kvm_version; }; -static char *progname; -static char *abs_srcdir; - static void printMismatchedFlags(virBitmapPtr got, virBitmapPtr expect) { @@ -121,21 +118,9 @@ cleanup: } static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return (EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); # define DO_TEST(name, version, is_kvm, kvm_version, ...) \ do { \ diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index c06bdf6..ebde3a1 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -19,8 +19,6 @@ # include "testutilsqemu.h" -static char *progname; -static char *abs_srcdir; static const char *abs_top_srcdir; static struct qemud_driver driver; @@ -190,23 +188,11 @@ static int testCompareXMLToArgvHelper(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; char map[PATH_MAX]; - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return (EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); - abs_top_srcdir = getenv("abs_top_srcdir"); if (!abs_top_srcdir) abs_top_srcdir = ".."; diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 27330a9..6f51d1e 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -15,8 +15,6 @@ # include "qemu/qemu_conf.h" # include "testutilsqemu.h" -static char *progname; -static char *abs_srcdir; static struct qemud_driver driver; # define MAX_FILE 4096 @@ -83,21 +81,9 @@ static int testCompareXMLToXMLHelper(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return (EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); if ((driver.caps = testQemuCapsInit()) == NULL) return (EXIT_FAILURE); diff --git a/tests/qparamtest.c b/tests/qparamtest.c index a4ed1fb..6dfac43 100644 --- a/tests/qparamtest.c +++ b/tests/qparamtest.c @@ -183,8 +183,7 @@ static const struct qparamParseDataEntry params5[] = { { "foo", "one two" } }; static const struct qparamParseDataEntry params6[] = { { "foo", "one" } }; static int -mymain(int argc ATTRIBUTE_UNUSED, - char **argv ATTRIBUTE_UNUSED) +mymain(void) { int ret = 0; diff --git a/tests/sexpr2xmltest.c b/tests/sexpr2xmltest.c index 9f74ece..0919435 100644 --- a/tests/sexpr2xmltest.c +++ b/tests/sexpr2xmltest.c @@ -13,8 +13,6 @@ #include "testutils.h" #include "testutilsxen.h" -static char *progname; -static char *abs_srcdir; static virCapsPtr caps; #define MAX_FILE 4096 @@ -99,26 +97,9 @@ static int testCompareHelper(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return(EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return(EXIT_FAILURE); - } if (!(caps = testXenCapsInit())) return(EXIT_FAILURE); diff --git a/tests/sockettest.c b/tests/sockettest.c index 2c9ff03..b9e37ab 100644 --- a/tests/sockettest.c +++ b/tests/sockettest.c @@ -1,7 +1,7 @@ /* * sockettest.c: Testing for src/util/network.c APIs * - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -159,8 +159,7 @@ static int testNetmaskHelper(const void *opaque) static int -mymain(int argc ATTRIBUTE_UNUSED, - char **argv ATTRIBUTE_UNUSED) +mymain(void) { int ret = 0; /* Some of our tests deliberately test failure cases, so diff --git a/tests/statstest.c b/tests/statstest.c index 36cbea4..d18bb0c 100644 --- a/tests/statstest.c +++ b/tests/statstest.c @@ -41,8 +41,7 @@ static int testDeviceHelper(const void *data) } static int -mymain(int argc ATTRIBUTE_UNUSED, - char **argv ATTRIBUTE_UNUSED) +mymain(void) { int ret = 0; /* Some of our tests delibrately test failure cases, so diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c index 2ec29e3..6641153 100644 --- a/tests/storagepoolxml2xmltest.c +++ b/tests/storagepoolxml2xmltest.c @@ -13,9 +13,6 @@ #include "storage_conf.h" #include "testutilsqemu.h" -static char *progname; -static char *abs_srcdir; - #define MAX_FILE 4096 @@ -64,21 +61,9 @@ static int testCompareXMLToXMLHelper(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return (EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); #define DO_TEST(name) \ if (virtTestRun("Storage Pool XML-2-XML " name, \ diff --git a/tests/storagevolxml2xmltest.c b/tests/storagevolxml2xmltest.c index ffa5dfe..0cd57af 100644 --- a/tests/storagevolxml2xmltest.c +++ b/tests/storagevolxml2xmltest.c @@ -13,9 +13,6 @@ #include "storage_conf.h" #include "testutilsqemu.h" -static char *progname; -static char *abs_srcdir; - #define MAX_FILE 4096 @@ -85,21 +82,9 @@ static int testCompareXMLToXMLHelper(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return (EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); #define DO_TEST(pool, name) \ do { \ diff --git a/tests/testutils.c b/tests/testutils.c index 1f3b569..456a735 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -55,6 +55,9 @@ static unsigned int testVerbose = -1; static unsigned int testOOM = 0; static unsigned int testCounter = 0; +char *progname; +char *abs_srcdir; + double virtTestCountAverage(double *items, int nitems) { @@ -472,9 +475,10 @@ virTestGetVerbose(void) { int virtTestMain(int argc, char **argv, - int (*func)(int, char **)) + int (*func)(void)) { int ret; + char cwd[PATH_MAX]; #if TEST_OOM int approxAlloc = 0; int n; @@ -485,7 +489,20 @@ int virtTestMain(int argc, int worker = 0; #endif - fprintf(stderr, "TEST: %s\n", STRPREFIX(argv[0], "./") ? argv[0] + 2 : argv[0]); + abs_srcdir = getenv("abs_srcdir"); + if (!abs_srcdir) + abs_srcdir = getcwd(cwd, sizeof(cwd)); + if (!abs_srcdir) + exit(EXIT_AM_HARDFAIL); + + progname = argv[0]; + if (STRPREFIX(progname, "./")) + progname += 2; + if (argc > 1) { + fprintf(stderr, "Usage: %s\n", argv[0]); + return EXIT_FAILURE; + } + fprintf(stderr, "TEST: %s\n", progname); if (!virTestGetVerbose()) fprintf(stderr, " "); @@ -520,7 +537,7 @@ int virtTestMain(int argc, } /* Run once to prime any static allocations & ensure it passes */ - ret = (func)(argc, argv); + ret = (func)(); if (ret != EXIT_SUCCESS) goto cleanup; @@ -537,7 +554,7 @@ int virtTestMain(int argc, virAllocTestInit(); /* Run again to count allocs, and ensure it passes :-) */ - ret = (func)(argc, argv); + ret = (func)(); if (ret != EXIT_SUCCESS) goto cleanup; @@ -574,7 +591,7 @@ int virtTestMain(int argc, } virAllocTestOOM(n+1, oomCount); - if (((func)(argc, argv)) != EXIT_FAILURE) { + if (((func)()) != EXIT_FAILURE) { ret = EXIT_FAILURE; break; } @@ -604,7 +621,7 @@ int virtTestMain(int argc, } cleanup: #else - ret = (func)(argc, argv); + ret = (func)(); #endif virResetLastError(); diff --git a/tests/testutils.h b/tests/testutils.h index 88603a1..0ea70ee 100644 --- a/tests/testutils.h +++ b/tests/testutils.h @@ -1,7 +1,7 @@ /* * utils.c: test utils * - * Copyright (C) 2005, 2008-2010 Red Hat, Inc. + * Copyright (C) 2005, 2008-2011 Red Hat, Inc. * * See COPYING.LIB for the License of this software * @@ -14,6 +14,10 @@ # include # define EXIT_AM_SKIP 77 /* tell Automake we're skipping a test */ +# define EXIT_AM_HARDFAIL 99 /* tell Automake that the framework is broken */ + +extern char *progname; +extern char *abs_srcdir; double virtTestCountAverage(double *items, int nitems); @@ -44,11 +48,12 @@ char *virtTestLogContentAndReset(void); int virtTestMain(int argc, char **argv, - int (*func)(int, char **)); + int (*func)(void)); -# define VIRT_TEST_MAIN(func) \ - int main(int argc, char **argv) { \ - return virtTestMain(argc,argv, func); \ +/* Setup, then call func() */ +# define VIRT_TEST_MAIN(func) \ + int main(int argc, char **argv) { \ + return virtTestMain(argc, argv, func); \ } #endif /* __VIT_TEST_UTILS_H__ */ diff --git a/tests/virbuftest.c b/tests/virbuftest.c index db08fc4..0094a16 100644 --- a/tests/virbuftest.c +++ b/tests/virbuftest.c @@ -64,8 +64,7 @@ out: } static int -mymain(int argc ATTRIBUTE_UNUSED, - char **argv ATTRIBUTE_UNUSED) +mymain(void) { int ret = 0; diff --git a/tests/virshtest.c b/tests/virshtest.c index 8ec97a8..465d5ea 100644 --- a/tests/virshtest.c +++ b/tests/virshtest.c @@ -8,8 +8,6 @@ #include "xml.h" #include "testutils.h" -static char *progname; -static char *abs_srcdir; #define MAX_FILE 4096 #define DOM_UUID "ef861801-45b9-11cb-88e3-afbfe5370493" @@ -232,30 +230,20 @@ static int testCompareEcho(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; char buffer[PATH_MAX]; - char cwd[PATH_MAX]; - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); #ifdef WIN32 exit (EXIT_AM_SKIP); #endif - snprintf(buffer, PATH_MAX-1, "test://%s/../examples/xml/test/testnode.xml", abs_srcdir); + snprintf(buffer, PATH_MAX-1, + "test://%s/../examples/xml/test/testnode.xml", abs_srcdir); buffer[PATH_MAX-1] = '\0'; - progname = argv[0]; custom_uri = buffer; - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return(EXIT_FAILURE); - } - if (virtTestRun("virsh list (default)", 1, testCompareListDefault, NULL) != 0) ret = -1; diff --git a/tests/vmx2xmltest.c b/tests/vmx2xmltest.c index 5fed1c4..3b7e9be 100644 --- a/tests/vmx2xmltest.c +++ b/tests/vmx2xmltest.c @@ -11,8 +11,6 @@ # include "testutils.h" # include "vmx/vmx.h" -static char *progname = NULL; -static char *abs_srcdir = NULL; static virCapsPtr caps = NULL; static virVMXContext ctx; @@ -181,28 +179,9 @@ testParseVMXFileName(const char *fileName, void *opaque ATTRIBUTE_UNUSED) } static int -mymain(int argc, char **argv) +mymain(void) { int result = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return EXIT_FAILURE; - } - - abs_srcdir = getenv("abs_srcdir"); - - if (abs_srcdir == NULL) { - abs_srcdir = getcwd(cwd, sizeof(cwd)); - } - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return EXIT_FAILURE; - } # define DO_TEST(_in, _out) \ do { \ diff --git a/tests/xencapstest.c b/tests/xencapstest.c index 7b48812..36946cf 100644 --- a/tests/xencapstest.c +++ b/tests/xencapstest.c @@ -11,9 +11,6 @@ #include "xen/xen_hypervisor.h" #include "files.h" -static char *progname; -static char *abs_srcdir; - #define MAX_FILE 4096 static int testCompareFiles(const char *hostmachine, @@ -151,21 +148,9 @@ static int testXenppc64(const void *data ATTRIBUTE_UNUSED) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return(EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); virInitialize(); diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c index 7d418a5..62d3488 100644 --- a/tests/xmconfigtest.c +++ b/tests/xmconfigtest.c @@ -1,7 +1,7 @@ /* * xmconfigtest.c: Test backend for xm_internal config file handling * - * Copyright (C) 2007, 2010 Red Hat, Inc. + * Copyright (C) 2007, 2010-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -36,8 +36,6 @@ #include "testutilsxen.h" #include "memory.h" -static char *progname; -static char *abs_srcdir; static virCapsPtr caps; #define MAX_FILE 4096 @@ -174,21 +172,9 @@ static int testCompareHelper(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return(EXIT_FAILURE); - } - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); if (!(caps = testXenCapsInit())) return(EXIT_FAILURE); diff --git a/tests/xml2sexprtest.c b/tests/xml2sexprtest.c index cf530b6..b258c3d 100644 --- a/tests/xml2sexprtest.c +++ b/tests/xml2sexprtest.c @@ -14,8 +14,6 @@ #include "testutils.h" #include "testutilsxen.h" -static char *progname; -static char *abs_srcdir; static virCapsPtr caps; #define MAX_FILE 4096 @@ -77,21 +75,9 @@ static int testCompareHelper(const void *data) { static int -mymain(int argc, char **argv) +mymain(void) { int ret = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return(EXIT_FAILURE); - } #define DO_TEST(in, out, name, version) \ do { \ diff --git a/tests/xml2vmxtest.c b/tests/xml2vmxtest.c index a5fb4f7..6a4b795 100644 --- a/tests/xml2vmxtest.c +++ b/tests/xml2vmxtest.c @@ -11,8 +11,6 @@ # include "testutils.h" # include "vmx/vmx.h" -static char *progname = NULL; -static char *abs_srcdir = NULL; static virCapsPtr caps = NULL; static virVMXContext ctx; @@ -198,28 +196,9 @@ testFormatVMXFileName(const char *src, void *opaque ATTRIBUTE_UNUSED) } static int -mymain(int argc, char **argv) +mymain(void) { int result = 0; - char cwd[PATH_MAX]; - - progname = argv[0]; - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return EXIT_FAILURE; - } - - abs_srcdir = getenv("abs_srcdir"); - - if (abs_srcdir == NULL) { - abs_srcdir = getcwd(cwd, sizeof(cwd)); - } - - if (argc > 1) { - fprintf(stderr, "Usage: %s\n", progname); - return EXIT_FAILURE; - } # define DO_TEST(_in, _out, _version) \ do { \ -- 1.7.4.4 From eblake at redhat.com Fri Apr 29 17:29:31 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 11:29:31 -0600 Subject: [libvirt] [PATCH 2/2] build: fix getcwd portability problems In-Reply-To: <1304098171-15981-1-git-send-email-eblake@redhat.com> References: <1304034123-7056-1-git-send-email-eblake@redhat.com> <1304098171-15981-1-git-send-email-eblake@redhat.com> Message-ID: <1304098171-15981-2-git-send-email-eblake@redhat.com> * bootstrap.conf (gnulib_modules): Add getcwd-lgpl. * tests/commandtest.c (checkoutput): Drop unused cwd. * tests/commandhelper.c (main): Let getcwd malloc. * tests/testutils.c (virTestMain): Likewise. * tools/virsh.c (cmdPwd): Likewise. (virshCmds): Expose cmdPwd and cmdCd on mingw. --- > Oh, and now that gnulib getcwd-lgpl exists, we could use it > to fix our uses of getcwd(NULL,0), followup coming later. bootstrap.conf | 1 + tests/commandhelper.c | 7 ++++--- tests/commandtest.c | 4 ---- tests/testutils.c | 3 +-- tools/virsh.c | 34 ++++++++-------------------------- 5 files changed, 14 insertions(+), 35 deletions(-) diff --git a/bootstrap.conf b/bootstrap.conf index 3b3a90f..fde00da 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -36,6 +36,7 @@ dirname-lgpl fcntl-h func getaddrinfo +getcwd-lgpl gethostname getpass gettext-h diff --git a/tests/commandhelper.c b/tests/commandhelper.c index 46c00f4..d60d505 100644 --- a/tests/commandhelper.c +++ b/tests/commandhelper.c @@ -51,6 +51,7 @@ int main(int argc, char **argv) { int i, n; char **origenv; char **newenv; + char *cwd; FILE *log = fopen(abs_builddir "/commandhelper.log", "w"); if (!log) @@ -99,13 +100,13 @@ int main(int argc, char **argv) { } fprintf(log, "DAEMON:%s\n", getpgrp() == getsid(0) ? "yes" : "no"); - char cwd[1024]; - if (!getcwd(cwd, sizeof(cwd))) + if (!(cwd = getcwd(NULL, 0))) return EXIT_FAILURE; - if (strlen(cwd) > strlen("/commanddata") && + if (strlen(cwd) > strlen(".../commanddata") && STREQ(cwd + strlen(cwd) - strlen("/commanddata"), "/commanddata")) strcpy(cwd, ".../commanddata"); fprintf(log, "CWD:%s\n", cwd); + VIR_FREE(cwd); VIR_FORCE_FCLOSE(log); diff --git a/tests/commandtest.c b/tests/commandtest.c index 509c888..fa0061c 100644 --- a/tests/commandtest.c +++ b/tests/commandtest.c @@ -49,15 +49,11 @@ mymain(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) static int checkoutput(const char *testname) { int ret = -1; - char cwd[1024]; char *expectname = NULL; char *expectlog = NULL; char *actualname = NULL; char *actuallog = NULL; - if (!getcwd(cwd, sizeof(cwd))) - return -1; - if (virAsprintf(&expectname, "%s/commanddata/%s.log", abs_srcdir, testname) < 0) goto cleanup; diff --git a/tests/testutils.c b/tests/testutils.c index 456a735..91035a2 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -478,7 +478,6 @@ int virtTestMain(int argc, int (*func)(void)) { int ret; - char cwd[PATH_MAX]; #if TEST_OOM int approxAlloc = 0; int n; @@ -491,7 +490,7 @@ int virtTestMain(int argc, abs_srcdir = getenv("abs_srcdir"); if (!abs_srcdir) - abs_srcdir = getcwd(cwd, sizeof(cwd)); + abs_srcdir = getcwd(NULL, 0); if (!abs_srcdir) exit(EXIT_AM_HARDFAIL); diff --git a/tools/virsh.c b/tools/virsh.c index 0212b99..506572b 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -9893,7 +9893,6 @@ editReadBackFile (vshControl *ctl, const char *filename) } -#ifndef WIN32 /* * "cd" command */ @@ -9936,9 +9935,6 @@ cmdCd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) return ret; } -#endif - -#ifndef WIN32 /* * "pwd" command */ @@ -9952,30 +9948,20 @@ static bool cmdPwd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { char *cwd; - size_t path_max; - bool err = true; - - path_max = (size_t) PATH_MAX + 2; - cwd = vshMalloc (ctl, path_max); - while (cwd) { - err = getcwd (cwd, path_max) == NULL; - if (!err || errno != ERANGE) - break; - - path_max *= 2; - cwd = vshRealloc (ctl, cwd, path_max); - } + bool ret = true; - if (err) + cwd = getcwd(NULL, 0); + if (!cwd) { vshError(ctl, _("pwd: cannot get current directory: %s"), strerror(errno)); - else + ret = false; + } else { vshPrint (ctl, _("%s\n"), cwd); + VIR_FREE(cwd); + } - VIR_FREE(cwd); - return !err; + return ret; } -#endif /* * "echo" command @@ -10862,15 +10848,11 @@ static const vshCmdDef secretCmds[] = { }; static const vshCmdDef virshCmds[] = { -#ifndef WIN32 {"cd", cmdCd, opts_cd, info_cd}, -#endif {"echo", cmdEcho, opts_echo, info_echo}, {"exit", cmdQuit, NULL, info_quit}, {"help", cmdHelp, opts_help, info_help}, -#ifndef WIN32 {"pwd", cmdPwd, NULL, info_pwd}, -#endif {"quit", cmdQuit, NULL, info_quit}, {NULL, NULL, NULL, NULL} }; -- 1.7.4.4 From laine at laine.org Fri Apr 29 17:32:07 2011 From: laine at laine.org (Laine Stump) Date: Fri, 29 Apr 2011 13:32:07 -0400 Subject: [libvirt] Libvirt and IPSec (was: What about Trusted Virtual Domains???) In-Reply-To: <4DBAE3BA.7060609@polito.it> References: <4D9C6663.3030504@polito.it> <4DBAE3BA.7060609@polito.it> Message-ID: <4DBAF617.703@laine.org> On 04/29/2011 12:13 PM, Paolo Smiraglia wrote: > Hi to everyone! > > Sorry for the latency of the response but me and my team we are noticed > that the TVD argument can not be treated only with a few lines in some > mails. In order to avoid any possible misunderstanding, we decided to > produce a little report (just four pages with images) that describes our > project. Technical details are not treated in the report. You can > download the report by using the link > > http://dl.dropbox.com/u/824617/tvd_in_libvirt.pdf > > Our idea is to start the discussion about Libvirt TVD implementation > using as starting point the report. > > > As already mentioned in previous mail, we think that the first step for > the implementation of the TVD is to make possible the 'tunnel' modeling > in Libvirt. > > Considering the report, what do you think about our tunnel modeling > idea? It's right or some changes are needed? Paolo, Did you see my recent email titled "RFC: disconnecting guest/domain interface config from host config": https://www.redhat.com/archives/libvir-list/2011-April/msg00591.html We both want to expand the usage of , so we'd do well to avoid stepping on each others' toes! :-) I'm wondering how the element would fit in with network types that were not "bridge". I'm also curious about your work with openvswitch, because one of the potentials I can see as a result of expanding the usage of is that openvswitch could be supported directly by libvirt by defining a new (I mention that in one of the followup messages. Also I'm still curious about my questions in my earlier response to you: https://www.redhat.com/archives/libvir-list/2011-April/msg00589.html in particular: 1) does the network on each host always have a element for forwarding local traffic directly out to the public network? or alternately, is it possible to force a network on one host to send all traffic over the L2-over-L3 tunnel to a network on another machine, and from there out to the public network? It seems that, in this case, there would be no default route for the systems on the former network (in the case of no forwarding on a libvirt network, no default route is sent in the dhcp response - maybe that needs to be configurable...) 2) Is there an exact 1:1 correspondence between network and tunnel (or perhaps there may be multiple tunnels for a network, but those tunnels are not used by any other network on the same host)? If so, perhaps your project could be simplified by just putting the tunnel config as a subelement of , rather than referencing it - this way you would avoid the need for the extra APIs to define/undefine/etc sectunnel. 3) Are your tunnels always L2, or do you have provision for setting up L3 tunnels? (Perhaps that could be done by allowing multiple elements, and having a that specified a tunnel rather than a physical interface, as well as a list of routes as subelements? This, along with a sectunnel subelement should be enough info to setup a secure L3 tunnel which would be used for the specified routes, right? (BTW, after thinking about it some more, I think I agree that is the right place to implement this, rather than a virInterface (host) based (although that would also be useful, totally separate from libvirt)). It seems we can gain a lot from each other! I'm hoping to have my expansion of the network config completed by the end of June at latest, but your work may enable/force me to hurry it a bit more than that :-) From eblake at redhat.com Fri Apr 29 17:40:20 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 11:40:20 -0600 Subject: [libvirt] [PATCH] docs: Document device In-Reply-To: <1304098148-11880-1-git-send-email-crobinso@redhat.com> References: <1304098148-11880-1-git-send-email-crobinso@redhat.com> Message-ID: <4DBAF804.5030109@redhat.com> On 04/29/2011 11:29 AM, Cole Robinson wrote: > Tried to dredge through old changelogs and commits to come up with it, so > may not be completely accurate. Maybe true, but still better than nothing. Thanks for tackling this. > > Signed-off-by: Cole Robinson > --- > docs/formatdomain.html.in | 107 +++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 107 insertions(+), 0 deletions(-) > > diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in > index a055b38..eafb983 100644 > --- a/docs/formatdomain.html.in > +++ b/docs/formatdomain.html.in > @@ -903,6 +903,113 @@ > > > > +

    Filesystems

    > + > +

    > + A directory on the host that can be accessed directly from the guest. > + since 0.3.3 for containers, since 0.8.5 for QEMU/KVM Should this read 'LXC containers'? > + More info > + > +

    mode='mapped'
    > +
    > + The source is accessed with the permissions of the > + hypervisor (QEMU process). > + More info > +
    > +
    mode='squash'
    > +
    > + Similar to 'passthrough', the exception is that failure of > + privileged operations like 'chown' are ignored. This makes a > + passthrough-like mode usable for people who run the hypervisor > + as non-root. > + More info For consistency, we should use http://lists.gnu.org/archive/html/qemu-devel/2010-09/msg00121.html for the third URL, so that all three are pointing to the same archive site. ACK with nits addressed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Fri Apr 29 17:41:48 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 29 Apr 2011 19:41:48 +0200 Subject: [libvirt] [PATCH 1/2] tests: simplify common setup In-Reply-To: <1304098171-15981-1-git-send-email-eblake@redhat.com> References: <1304034123-7056-1-git-send-email-eblake@redhat.com> <1304098171-15981-1-git-send-email-eblake@redhat.com> Message-ID: 2011/4/29 Eric Blake : > A few of the tests were missing basic sanity checks, while most > of them were doing copy-and-paste initialization (in fact, some > of them pasted the argc > 1 check more than once!). ?It's much > nicer to do things in one common place, and minimizes the size of > the next patch that fixes getcwd usage. > > * tests/testutils.h (EXIT_AM_HARDFAIL): New define. > (progname, abs_srcdir): Define for all tests. > (VIRT_TEST_MAIN): Change callback signature. > * tests/testutils.c (virtTestMain): Do more common init. > * tests/commandtest.c (mymain): Simplify. > * tests/cputest.c (mymain): Likewise. > * tests/esxutilstest.c (mymain): Likewise. > * tests/eventtest.c (mymain): Likewise. > * tests/hashtest.c (mymain): Likewise. > * tests/networkxml2xmltest.c (mymain): Likewise. > * tests/nodedevxml2xmltest.c (myname): Likewise. > * tests/nodeinfotest.c (mymain): Likewise. > * tests/nwfilterxml2xmltest.c (mymain): Likewise. > * tests/qemuargv2xmltest.c (mymain): Likewise. > * tests/qemuhelptest.c (mymain): Likewise. > * tests/qemuxml2argvtest.c (mymain): Likewise. > * tests/qemuxml2xmltest.c (mymain): Likewise. > * tests/qparamtest.c (mymain): Likewise. > * tests/sexpr2xmltest.c (mymain): Likewise. > * tests/sockettest.c (mymain): Likewise. > * tests/statstest.c (mymain): Likewise. > * tests/storagepoolxml2xmltest.c (mymain): Likewise. > * tests/storagevolxml2xmltest.c (mymain): Likewise. > * tests/virbuftest.c (mymain): Likewise. > * tests/virshtest.c (mymain): Likewise. > * tests/vmx2xmltest.c (mymain): Likewise. > * tests/xencapstest.c (mymain): Likewise. > * tests/xmconfigtest.c (mymain): Likewise. > * tests/xml2sexprtest.c (mymain): Likewise. > * tests/xml2vmxtest.c (mymain): Likewise. > --- > ?tests/commandtest.c ? ? ? ? ? ?| ? 18 +----------------- > ?tests/cputest.c ? ? ? ? ? ? ? ?| ? 18 ++---------------- > ?tests/esxutilstest.c ? ? ? ? ? | ? 17 +---------------- > ?tests/eventtest.c ? ? ? ? ? ? ?| ? 11 +---------- > ?tests/hashtest.c ? ? ? ? ? ? ? | ? ?3 +-- > ?tests/interfacexml2xmltest.c ? | ? 17 +---------------- > ?tests/networkxml2xmltest.c ? ? | ? 17 +---------------- > ?tests/nodedevxml2xmltest.c ? ? | ? 17 +---------------- > ?tests/nodeinfotest.c ? ? ? ? ? | ? 17 +---------------- > ?tests/nwfilterxml2xmltest.c ? ?| ? 17 +---------------- > ?tests/qemuargv2xmltest.c ? ? ? | ? 16 +--------------- > ?tests/qemuhelptest.c ? ? ? ? ? | ? 17 +---------------- > ?tests/qemuxml2argvtest.c ? ? ? | ? 16 +--------------- > ?tests/qemuxml2xmltest.c ? ? ? ?| ? 16 +--------------- > ?tests/qparamtest.c ? ? ? ? ? ? | ? ?3 +-- > ?tests/sexpr2xmltest.c ? ? ? ? ?| ? 21 +-------------------- > ?tests/sockettest.c ? ? ? ? ? ? | ? ?5 ++--- > ?tests/statstest.c ? ? ? ? ? ? ?| ? ?3 +-- > ?tests/storagepoolxml2xmltest.c | ? 17 +---------------- > ?tests/storagevolxml2xmltest.c ?| ? 17 +---------------- > ?tests/testutils.c ? ? ? ? ? ? ?| ? 29 +++++++++++++++++++++++------ > ?tests/testutils.h ? ? ? ? ? ? ?| ? 15 ++++++++++----- > ?tests/virbuftest.c ? ? ? ? ? ? | ? ?3 +-- > ?tests/virshtest.c ? ? ? ? ? ? ?| ? 18 +++--------------- > ?tests/vmx2xmltest.c ? ? ? ? ? ?| ? 23 +---------------------- > ?tests/xencapstest.c ? ? ? ? ? ?| ? 17 +---------------- > ?tests/xmconfigtest.c ? ? ? ? ? | ? 18 ++---------------- > ?tests/xml2sexprtest.c ? ? ? ? ?| ? 16 +--------------- > ?tests/xml2vmxtest.c ? ? ? ? ? ?| ? 23 +---------------------- > ?29 files changed, 65 insertions(+), 380 deletions(-) > Nice cleanup, ACK. Matthias From eblake at redhat.com Fri Apr 29 17:44:26 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 11:44:26 -0600 Subject: [libvirt] [PATCH] tests: Lower stack usage below 4096 bytes In-Reply-To: <4DB5A7F3.2080700@redhat.com> References: <20110424222652.GA16936@sbox> <4DB5A7F3.2080700@redhat.com> Message-ID: <4DBAF8FA.5000909@redhat.com> On 04/25/2011 10:57 AM, Eric Blake wrote: > On 04/24/2011 04:26 PM, Matthias Bolte wrote: >> Make virtTestLoadFile allocate the buffer to read the file into. >> >> Fix logic error in virtTestLoadFile, stop reading on the an empty line. >> >> Use virFileReadLimFD in virtTestCaptureProgramOutput. >> --- >> +++ b/tests/commandhelper.c >> @@ -99,8 +99,8 @@ int main(int argc, char **argv) { >> } >> >> fprintf(log, "DAEMON:%s\n", getpgrp() == getsid(0) ? "yes" : "no"); >> - char cwd[1024]; >> - if (!getcwd(cwd, sizeof(cwd))) >> + char *cwd = NULL; >> + if (!(cwd = getcwd(NULL, 0))) > > Ouch. This is not portable to POSIX, and while gnulib can guarantee > that it works, the current gnulib getcwd module is GPL (and relies on > openat, which is a rather heavy-weight replacement!). > > I'm going to work on a gnulib module getcwd-lgpl which doesn't fix all > the known bugs in getcwd, but at least guarantees that getcwd(NULL,0) > will malloc insofar as the underlying getcwd is not buggy; we'll need to > import that into libvirt before applying the rest of this patch. I've now done that. Should we review my patches first, then rebase this on top of my cleanups? If nothing else, it makes the cleanup in the tests/ directory much smaller. https://www.redhat.com/archives/libvir-list/2011-April/msg01255.html -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Fri Apr 29 17:48:27 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 29 Apr 2011 19:48:27 +0200 Subject: [libvirt] [PATCH 2/2] build: fix getcwd portability problems In-Reply-To: <1304098171-15981-2-git-send-email-eblake@redhat.com> References: <1304034123-7056-1-git-send-email-eblake@redhat.com> <1304098171-15981-1-git-send-email-eblake@redhat.com> <1304098171-15981-2-git-send-email-eblake@redhat.com> Message-ID: 2011/4/29 Eric Blake : > * bootstrap.conf (gnulib_modules): Add getcwd-lgpl. > * tests/commandtest.c (checkoutput): Drop unused cwd. > * tests/commandhelper.c (main): Let getcwd malloc. > * tests/testutils.c (virTestMain): Likewise. > * tools/virsh.c (cmdPwd): Likewise. > (virshCmds): Expose cmdPwd and cmdCd on mingw. > --- > >> Oh, and now that gnulib getcwd-lgpl exists, we could use it >> to fix our uses of getcwd(NULL,0), followup coming later. > > ?bootstrap.conf ? ? ? ?| ? ?1 + > ?tests/commandhelper.c | ? ?7 ++++--- > ?tests/commandtest.c ? | ? ?4 ---- > ?tests/testutils.c ? ? | ? ?3 +-- > ?tools/virsh.c ? ? ? ? | ? 34 ++++++++-------------------------- > ?5 files changed, 14 insertions(+), 35 deletions(-) > diff --git a/tests/testutils.c b/tests/testutils.c > index 456a735..91035a2 100644 > --- a/tests/testutils.c > +++ b/tests/testutils.c > @@ -478,7 +478,6 @@ int virtTestMain(int argc, > ? ? ? ? ? ? ? ? ?int (*func)(void)) > ?{ > ? ? int ret; > - ? ?char cwd[PATH_MAX]; > ?#if TEST_OOM > ? ? int approxAlloc = 0; > ? ? int n; > @@ -491,7 +490,7 @@ int virtTestMain(int argc, > > ? ? abs_srcdir = getenv("abs_srcdir"); > ? ? if (!abs_srcdir) > - ? ? ? ?abs_srcdir = getcwd(cwd, sizeof(cwd)); > + ? ? ? ?abs_srcdir = getcwd(NULL, 0); > ? ? if (!abs_srcdir) > ? ? ? ? exit(EXIT_AM_HARDFAIL); Now you have created a memory leak (not a critical one, that's true), because abs_srcdir can be malloc'ed and you missed to free it. ACK, with that memory leak fixed. Matthias From eblake at redhat.com Fri Apr 29 17:53:59 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 11:53:59 -0600 Subject: [libvirt] [PATCH 1/2] tests: simplify common setup In-Reply-To: References: <1304034123-7056-1-git-send-email-eblake@redhat.com> <1304098171-15981-1-git-send-email-eblake@redhat.com> Message-ID: <4DBAFB37.1060305@redhat.com> On 04/29/2011 11:41 AM, Matthias Bolte wrote: > 2011/4/29 Eric Blake : >> A few of the tests were missing basic sanity checks, while most >> of them were doing copy-and-paste initialization (in fact, some >> of them pasted the argc > 1 check more than once!). It's much >> nicer to do things in one common place, and minimizes the size of >> the next patch that fixes getcwd usage. >> >> 29 files changed, 65 insertions(+), 380 deletions(-) >> > > Nice cleanup, ACK. Thanks; pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 29 18:13:44 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 12:13:44 -0600 Subject: [libvirt] [PATCH 2/2] build: fix getcwd portability problems In-Reply-To: References: <1304034123-7056-1-git-send-email-eblake@redhat.com> <1304098171-15981-1-git-send-email-eblake@redhat.com> <1304098171-15981-2-git-send-email-eblake@redhat.com> Message-ID: <4DBAFFD8.60605@redhat.com> On 04/29/2011 11:48 AM, Matthias Bolte wrote: >> +++ b/tests/testutils.c >> @@ -478,7 +478,6 @@ int virtTestMain(int argc, >> int (*func)(void)) >> { >> int ret; >> - char cwd[PATH_MAX]; >> #if TEST_OOM >> int approxAlloc = 0; >> int n; >> @@ -491,7 +490,7 @@ int virtTestMain(int argc, >> >> abs_srcdir = getenv("abs_srcdir"); >> if (!abs_srcdir) >> - abs_srcdir = getcwd(cwd, sizeof(cwd)); >> + abs_srcdir = getcwd(NULL, 0); >> if (!abs_srcdir) >> exit(EXIT_AM_HARDFAIL); > > Now you have created a memory leak (not a critical one, that's true), > because abs_srcdir can be malloc'ed and you missed to free it. It's technically only a leak if someone overwrites abs_srcdir with different contents without freeing it first, since there is a global variable that still tracks the pointer through the point of program exit(). Valgrind reports this type of open-ended allocation as "still reachable", rather than "definitely lost". But, to make valgrind even quieter, yes, I can fix things up to free the memory if it was not read from getenv and before returning from virtTestMain. > > ACK, with that memory leak fixed. Pushed with this addition: diff --git i/tests/testutils.c w/tests/testutils.c index 91035a2..ae73530 100644 --- i/tests/testutils.c +++ w/tests/testutils.c @@ -478,6 +478,7 @@ int virtTestMain(int argc, int (*func)(void)) { int ret; + bool abs_srcdir_cleanup = falseb; #if TEST_OOM int approxAlloc = 0; int n; @@ -489,8 +490,10 @@ int virtTestMain(int argc, #endif abs_srcdir = getenv("abs_srcdir"); - if (!abs_srcdir) + if (!abs_srcdir) { abs_srcdir = getcwd(NULL, 0); + abs_srcdir_cleanup = true; + } if (!abs_srcdir) exit(EXIT_AM_HARDFAIL); @@ -623,6 +626,8 @@ cleanup: ret = (func)(); #endif + if (abs_srcdir_cleanup) + VIR_FREE(abs_srcdir); virResetLastError(); if (!virTestGetVerbose()) { int i; -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Fri Apr 29 18:19:38 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Fri, 29 Apr 2011 20:19:38 +0200 Subject: [libvirt] [PATCH 2/2] build: fix getcwd portability problems In-Reply-To: <4DBAFFD8.60605@redhat.com> References: <1304034123-7056-1-git-send-email-eblake@redhat.com> <1304098171-15981-1-git-send-email-eblake@redhat.com> <1304098171-15981-2-git-send-email-eblake@redhat.com> <4DBAFFD8.60605@redhat.com> Message-ID: 2011/4/29 Eric Blake : > On 04/29/2011 11:48 AM, Matthias Bolte wrote: >>> +++ b/tests/testutils.c >>> @@ -478,7 +478,6 @@ int virtTestMain(int argc, >>> ? ? ? ? ? ? ? ? ?int (*func)(void)) >>> ?{ >>> ? ? int ret; >>> - ? ?char cwd[PATH_MAX]; >>> ?#if TEST_OOM >>> ? ? int approxAlloc = 0; >>> ? ? int n; >>> @@ -491,7 +490,7 @@ int virtTestMain(int argc, >>> >>> ? ? abs_srcdir = getenv("abs_srcdir"); >>> ? ? if (!abs_srcdir) >>> - ? ? ? ?abs_srcdir = getcwd(cwd, sizeof(cwd)); >>> + ? ? ? ?abs_srcdir = getcwd(NULL, 0); >>> ? ? if (!abs_srcdir) >>> ? ? ? ? exit(EXIT_AM_HARDFAIL); >> >> Now you have created a memory leak (not a critical one, that's true), >> because abs_srcdir can be malloc'ed and you missed to free it. > > It's technically only a leak if someone overwrites abs_srcdir with > different contents without freeing it first, since there is a global > variable that still tracks the pointer through the point of program > exit(). ?Valgrind reports this type of open-ended allocation as "still > reachable", rather than "definitely lost". I know, but I like valgrind clean software :) > But, to make valgrind even quieter, yes, I can fix things up to free the > memory if it was not read from getenv and before returning from > virtTestMain. Thanks. >> >> ACK, with that memory leak fixed. > > Pushed with this addition: > > diff --git i/tests/testutils.c w/tests/testutils.c > index 91035a2..ae73530 100644 > --- i/tests/testutils.c > +++ w/tests/testutils.c > @@ -478,6 +478,7 @@ int virtTestMain(int argc, > ? ? ? ? ? ? ? ? ?int (*func)(void)) > ?{ > ? ? int ret; > + ? ?bool abs_srcdir_cleanup = falseb; As I saw this line, I hoped you didn't push it with that typo... and you didn't :) Now I'll go and rebase my stack usage cleanup patch. Matthias From crobinso at redhat.com Fri Apr 29 18:34:35 2011 From: crobinso at redhat.com (Cole Robinson) Date: Fri, 29 Apr 2011 14:34:35 -0400 Subject: [libvirt] [PATCH] docs: Document device In-Reply-To: <4DBAF804.5030109@redhat.com> References: <1304098148-11880-1-git-send-email-crobinso@redhat.com> <4DBAF804.5030109@redhat.com> Message-ID: <4DBB04BB.2030101@redhat.com> On 04/29/2011 01:40 PM, Eric Blake wrote: > On 04/29/2011 11:29 AM, Cole Robinson wrote: >> Tried to dredge through old changelogs and commits to come up with it, so >> may not be completely accurate. > > Maybe true, but still better than nothing. Thanks for tackling this. > >> >> Signed-off-by: Cole Robinson >> --- >> docs/formatdomain.html.in | 107 +++++++++++++++++++++++++++++++++++++++++++++ >> 1 files changed, 107 insertions(+), 0 deletions(-) >> >> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in >> index a055b38..eafb983 100644 >> --- a/docs/formatdomain.html.in >> +++ b/docs/formatdomain.html.in >> @@ -903,6 +903,113 @@ >>
    >> >> >> +

    Filesystems

    >> + >> +

    >> + A directory on the host that can be accessed directly from the guest. >> + since 0.3.3 for containers, since 0.8.5 for QEMU/KVM > > Should this read 'LXC containers'? > Actually I think OpenVZ is basically a 'container' so I meant it for both. Basically has been supported for OpenVZ and LXC since their first commits more or less, so I just dropped the 'for containers' bit here. >> + More info >> + >> +

    mode='mapped'
    >> +
    >> + The source is accessed with the permissions of the >> + hypervisor (QEMU process). >> + More info >> +
    >> +
    mode='squash'
    >> +
    >> + Similar to 'passthrough', the exception is that failure of >> + privileged operations like 'chown' are ignored. This makes a >> + passthrough-like mode usable for people who run the hypervisor >> + as non-root. >> + More info > > For consistency, we should use > http://lists.gnu.org/archive/html/qemu-devel/2010-09/msg00121.html > for the third URL, so that all three are pointing to the same archive site. > Ah, tried to find that but somehow missed it in the google results. Pushed now. Thanks, Cole From eblake at redhat.com Fri Apr 29 18:35:07 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 12:35:07 -0600 Subject: [libvirt] [PATCH] docs: Document device In-Reply-To: <4DBB04BB.2030101@redhat.com> References: <1304098148-11880-1-git-send-email-crobinso@redhat.com> <4DBAF804.5030109@redhat.com> <4DBB04BB.2030101@redhat.com> Message-ID: <4DBB04DB.6010504@redhat.com> On 04/29/2011 12:34 PM, Cole Robinson wrote: >>> + More info >> >> For consistency, we should use >> http://lists.gnu.org/archive/html/qemu-devel/2010-09/msg00121.html >> for the third URL, so that all three are pointing to the same archive site. >> > > Ah, tried to find that but somehow missed it in the google results. I found it by brute force. On the mail-archive.com site, I took note of the date and subject title; then I searched http://lists.gnu.org/archive/html/qemu-devel/2010-09/ (based on the date) for the right title. For once, something I can do without google :) -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 29 18:43:50 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 12:43:50 -0600 Subject: [libvirt] [PATCH v2] util: Simplify hash implementation In-Reply-To: <0ebc29ed7078c909b92f692d28c572f0c05ff9b9.1302629114.git.jdenemar@redhat.com> References: <0ebc29ed7078c909b92f692d28c572f0c05ff9b9.1302629114.git.jdenemar@redhat.com> Message-ID: <4DBB06E6.3040601@redhat.com> On 04/12/2011 11:25 AM, Jiri Denemark wrote: > So far first entries for each hash key are stored directly in the hash > table while other entries mapped to the same key are linked through > pointers. As a result of that, the code is cluttered with special > handling for the first items. > > This patch makes all entries (even the first ones) linked through > pointers, which significantly simplifies the code and makes it more > maintainable. > @@ -632,44 +539,27 @@ int virHashRemoveSet(virHashTablePtr table, virHashSearcher iter, const void *da > table->iterating = true; > table->current = NULL; > for (i = 0 ; i < table->size ; i++) { > - virHashEntryPtr prev = NULL; > - virHashEntryPtr entry = &(table->table[i]); > + virHashEntryPtr *nextptr = table->table + i; > > - while (entry && entry->valid) { > - if (iter(entry->payload, entry->name, data)) { > + while (*nextptr) { > + virHashEntryPtr entry = *nextptr; > + if (!iter(entry->payload, entry->name, data)) { > + *nextptr = entry->next; > + } else { > count++; > if (table->dataFree) > table->dataFree(entry->payload, entry->name); > if (table->keyFree) > table->keyFree(entry->name); > + *nextptr = entry->next; Oops. We should first be updating *nextptr->next before advancing nextptr. Without that, we're corrupting the table. I caught this by running valgrind on hashtest.c; I'm working on a patch now. Also, virHashFree is leaking table->table. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 29 19:53:57 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 13:53:57 -0600 Subject: [libvirt] [PATCH] hash: fix memory leak and regression Message-ID: <1304106837-18876-1-git-send-email-eblake@redhat.com> Commit 1671d1d introduced a memory leak in virHashFree, and wholesale table corruption in virHashRemoveSet (elements not requested to be freed are lost). * src/util/hash.c (virHashFree): Free bucket array. (virHashRemoveSet): Don't lose elements. * tests/hashtest.c (testHashCheckForEachCount): New method. (testHashCheckCount): Expose the bug. --- src/util/hash.c | 6 +++--- tests/hashtest.c | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/util/hash.c b/src/util/hash.c index a9b09b0..5366dd6 100644 --- a/src/util/hash.c +++ b/src/util/hash.c @@ -269,6 +269,7 @@ virHashFree(virHashTablePtr table) } } + VIR_FREE(table->table); VIR_FREE(table); } @@ -532,13 +533,12 @@ int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data) * virHashRemoveSet * @table: the hash table to process * @iter: callback to identify elements for removal - * @f: callback to free memory from element payload * @data: opaque data to pass to the iterator * * Iterates over all elements in the hash table, invoking the 'iter' * callback. If the callback returns a non-zero value, the element * will be removed from the hash table & its payload passed to the - * callback 'f' for de-allocation. + * data freer callback registered at creation. * * Returns number of items removed on success, -1 on failure */ @@ -562,7 +562,7 @@ int virHashRemoveSet(virHashTablePtr table, while (*nextptr) { virHashEntryPtr entry = *nextptr; if (!iter(entry->payload, entry->name, data)) { - *nextptr = entry->next; + nextptr = &entry->next; } else { count++; if (table->dataFree) diff --git a/tests/hashtest.c b/tests/hashtest.c index 525ae06..f02b3a9 100644 --- a/tests/hashtest.c +++ b/tests/hashtest.c @@ -61,16 +61,31 @@ testHashInit(int size) return hash; } +static void +testHashCheckForEachCount(void *payload ATTRIBUTE_UNUSED, + const void *name ATTRIBUTE_UNUSED, + void *data ATTRIBUTE_UNUSED) +{ +} static int testHashCheckCount(virHashTablePtr hash, int count) { + int iter_count = 0; + if (virHashSize(hash) != count) { testError("\nhash contains %d instead of %d elements\n", virHashSize(hash), count); return -1; } + iter_count = virHashForEach(hash, testHashCheckForEachCount, NULL); + if (count != iter_count) { + testError("\nhash claims to have %d elements but iteration finds %d\n", + count, iter_count); + return -1; + } + return 0; } -- 1.7.4.4 From laine at laine.org Fri Apr 29 20:12:55 2011 From: laine at laine.org (Laine Stump) Date: Fri, 29 Apr 2011 16:12:55 -0400 Subject: [libvirt] migration of vnlink VMs In-Reply-To: <333863871.338650.1304083790897.JavaMail.root@zmail02.collab.prod.int.phx2.redhat.com> References: <333863871.338650.1304083790897.JavaMail.root@zmail02.collab.prod.int.phx2.redhat.com> Message-ID: <4DBB1BC7.4030504@laine.org> To "cut to the chase", go down to the end of the message, where I outline the proposed XML changes to support this. If everyone approves of it, I'll make the RNG based on that description and update the parser, then worry about filling in the functionality. On 04/29/2011 09:29 AM, Oved Ourfalli wrote: > See my comments below. > > Thank you, > Oved This is very useful, Oved! Thanks for the replies. > ----- Original Message ----- >> From: "Laine Stump" >> To: libvir-list at redhat.com >> Sent: Friday, April 29, 2011 3:45:50 PM >> Subject: Re: [libvirt] migration of vnlink VMs >> On 04/28/2011 04:15 AM, Oved Ourfalli wrote: >>>> From: "Laine Stump">>> On 04/27/2011 09:58 AM, Oved Ourfalli wrote: >>>>> Laine, hello. >>>>> >>>>> We read your proposal for abstraction of guest<--> host network >>>>> connection in libvirt. >>>>> >>>>> You has an open issue there regarding the vepa/vnlink attributes: >>>>> "3) What about the parameters in the element that are >>>>> currently used by vepa/vnlink. Do those belong with the host, or >>>>> with the guest?" >>>>> >>>>> The parameters for the virtualport element should be on the guest, >>>>> and not the host, because a specific interface can run multiple >>>>> profiles, >>>> Are you talking about host interface or guest interface? If you >>>> mean >>>> that multiple different profiles can be used when connecting to a >>>> particular switch - as long as there are only a few different >>>> profiles, >>>> rather than each guest having its own unique profile, then it still >>>> seems better to have the port profile live with the network >>>> definition >>>> (and just define multiple networks, one for each port profile). >>>> >>> The profile names can be changed regularly, so it looks like it will >>> be better to put them in the guest level, so that the network host >>> file won't have to be changed on all hosts once something has >>> changed in the profiles. >>> >>> Also, you will have a duplication of data, writing all the profile >>> name on all the hosts that are connected to the vn-link/vepa switch. >> But is it potentially the same for many/all guests, or is it >> necessarily >> different for every guest? If it's the former, then do you have more >> guests, or more hosts? >> > I guess it will be the same for many guests. There will be some profiles, and each group of guests will use the same profile, according to its demands. Except instanceid, as you point out below. Since there is at least one exception to the "same for all guests", we do need to keep with the guest, but since many are changed, we should also supply it with the network. Things are starting to take shape now :-) >>>>> so it will be a mistake to define a profile to be interface >>>>> specific on the host. Moreover, putting it in the guest level >>>>> will >>>>> enable us in the future (if supported by libvirt/qemu) to >>>>> migrate >>>>> a vm from a host with vepa/vnlink interfaces, to another host >>>>> with >>>>> a bridge, for example. >>>> It seems to me like doing exactly the opposite would make it easier >>>> to >>>> migrate to a host that used a different kind of switching (from >>>> vepa >>>> to >>>> vnlink, or from a bridged interface to vepa, etc), since the port >>>> profile required for a particular host's network would be at the >>>> host >>>> waiting to be used. >>> You are right, but we would want to have the option to prevent that >>> from happening in case we wouldn't want to allow it. >>> We can make the ability to migrate between different network types >>> configurable, and we would like an easy way to tell libvirt - >>> "please allow/don't allow it". >> I *think* what you're getting at is this situation: >> >> HostA has a group of interfaces that are connected to a vepa-capable >> switch, HostB has a group of interfaces connected to a vnlink-capable >> switch. Guest1 is allowed to connect either via a vnlink switch or a >> vepa switch, but Guest2 should only use vepa. >> >> In that case, HostA would have a network that had a pool of interfaces >> and type "vepa", while HostB would have a pool of interfaces and a >> type >> "vnlink". Guest1 could be accommodated by giving both networks the >> same >> name, or Guest2 could be accommodated by giving each network a >> different >> name (when migrating, if the dest. host doesn't have the desired >> network, the migration would fail). However, using just the network >> naming, it wouldn't be possible to allow both. >> >> I don't think keeping the virtualport parameters only with the guest >> would help (or hurt) this though. What would be needed would be to >> have >> the information about network type *optionally* specified in the guest >> interface config (as well as in the network config); if present the >> migration would only succeed if the given network on the dest host >> matched the given type (and parameters, if any) in the guest config. >> > That would be great. It will enable the flexibility we need >>>>> So, in the networks at the host level you will have: >>>>> >>>>> red-network >>>>> >>>>> >>>>> >>>>> eth0 >>>>> ..... >>>>> >>>>> >>>>> eth4 >>>>> ..... >>>>> >>>>> >>>>> eth18 >>>>> ..... >>>>> >>>>> I'm assuming there will never be a case when an interface pool might need to be used by *both* a vepa network and a vnlink network (doesn't really make sense - it will be physically connected to a switch that supports vnlink, or one that supports vepa; by definition it can't be connected to both (I don't foresee any switch that supports both!). So defining the pool inside network should work okay. Since each interface will always have a name (and just one name), I think it makes sense to make that an attribute rather than subelement. >>>>> >>>>> >>>>> >>>>> And in the guest you will have (for vepa): >>>>> >>>>> and if you want to force connecting only to vepa or vnlink, you can do: for example. >>>>> >>>>> >>>> instanceid="09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f"/> >>>>> Likewise, anything that's specified here MUST either match what is in the definition on the host, or be unspecified on the host. The final virtualport definition used will be the OR of the two. >>>>> >>>>> >>>>> Or (for vnlink): >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >> What would the interface for a 2nd guest of each type look like? Could >> it be identical? Or might some parameters change for every single >> guest? > For vn-link it will be the same, just the profile_name. > As for vepa, the instanceid is vm specific so it should be on the guest (taken from http://libvirt.org/formatdomain.html): > > "managerid - The VSI Manager ID identifies the database containing the VSI type and instance definitions. This is an integer value and the value 0 is reserved. > typeid - The VSI Type ID identifies a VSI type characterizing the network access. VSI types are typically managed by network administrator. This is an integer value. > typeidversion - The VSI Type Version allows multiple versions of a VSI Type. This is an integer value. > instanceid - The VSI Instance ID Identifier is generated when a VSI instance (i.e. a virtual interface of a virtual machine) is created. This is a globally unique identifier." > > That's what we know on vepa an vn-link now. I guess that when we'll have the possibility to test these environments we will learn more on them. > >> Perhaps it would be best to have virtualport parameters on both >> network >> and guest interface XML, and merge the two to arrive at what's used >> (the >> network definition could contain all the attributes that would be >> common >> to all guests using that network on that host, and the guest interface >> definition would contain extra parameters specific to that host. In >> the >> case of a parameter being specified in both places, if they were not >> identical, the migration would fail). >> > Sounds good. Okay, here's a brief description of what I *think* will work. I'll build up the RNG based on this pseudo-xml: For the definition in the guest XML, the main change will be that will be valid (but optional) when interface type='network' - in this case, it will just be used to match against the source mode of the network on the host. will also become valid for type='network', and will serve two purposes: 1) if there is a mismatch with the virtualport on the host network, the migrate/start will fail. 2) It will be ORed with on the host network to arrive at the virtualport settings actually used. For example: (NB: if "mode" isn't specified, and the host network is actually a bridge or virtual network, the contents of virtualport will be ignored.) will be expanded by giving it an optional "type" attribute (which will default to 'virtual'), subelement, and subelement. When type='bridge', you can specify source exactly as you would in a domain definition: red-network When type='direct', again you can specify source and virtualport pretty much as you would in an interface definition: red-network However, dev would be optional - if not specified, we would expect a pool of interfaces to be defined within source, eg: red-network at connect time, source dev would be allocated from the pool of interfaces, round robin, with each interface having at most maxConnect connections to guests at any given time. Again, is optional, and if specified would have the same purpose as in the interface definition. Does this look like it covers everything? BTW, for all the people asking about sectunnel, openvswitch, and vde - can you see how those would fit in with this? In particular, do you see any conflicts? (It's easy to add more stuff on later if something is just missing, but much more problematic if I put something in that is just plain wrong). From laine at laine.org Fri Apr 29 20:18:33 2011 From: laine at laine.org (Laine Stump) Date: Fri, 29 Apr 2011 16:18:33 -0400 Subject: [libvirt] Libvirt and IPSec (was: What about Trusted Virtual Domains???) In-Reply-To: <4DBAF617.703@laine.org> References: <4D9C6663.3030504@polito.it> <4DBAE3BA.7060609@polito.it> <4DBAF617.703@laine.org> Message-ID: <4DBB1D19.7040902@laine.org> On 04/29/2011 01:32 PM, Laine Stump wrote: > On 04/29/2011 12:13 PM, Paolo Smiraglia wrote: >> Hi to everyone! >> >> Sorry for the latency of the response but me and my team we are noticed >> that the TVD argument can not be treated only with a few lines in some >> mails. In order to avoid any possible misunderstanding, we decided to >> produce a little report (just four pages with images) that describes our >> project. Technical details are not treated in the report. You can >> download the report by using the link >> >> http://dl.dropbox.com/u/824617/tvd_in_libvirt.pdf >> >> Our idea is to start the discussion about Libvirt TVD implementation >> using as starting point the report. >> >> >> As already mentioned in previous mail, we think that the first step for >> the implementation of the TVD is to make possible the 'tunnel' modeling >> in Libvirt. >> >> Considering the report, what do you think about our tunnel modeling >> idea? It's right or some changes are needed? > > Paolo, > > Did you see my recent email titled "RFC: disconnecting guest/domain > interface config from host config": > > https://www.redhat.com/archives/libvir-list/2011-April/msg00591.html And more discussion on the same topic that unfortunately got put into a different thread: https://www.redhat.com/archives/libvir-list/2011-April/msg01269.html Please let me know how sectunnel stuff would fit in with that. > > We both want to expand the usage of , so we'd do well to > avoid stepping on each others' toes! :-) > > I'm wondering how the element would fit in with network > types that were not "bridge". I'm also curious about your work with > openvswitch, because one of the potentials I can see as a result of > expanding the usage of is that openvswitch could be > supported directly by libvirt by defining a new type='openvswitch'> (I mention that in one of the followup messages. > > Also I'm still curious about my questions in my earlier response to you: > > https://www.redhat.com/archives/libvir-list/2011-April/msg00589.html > > in particular: > > 1) does the network on each host always have a element > for forwarding local traffic directly out to the public network? or > alternately, is it possible to force a network on one host to send all > traffic over the L2-over-L3 tunnel to a network on another machine, > and from there out to the public network? It seems that, in this case, > there would be no default route for the systems on the former network > (in the case of no forwarding on a libvirt network, no default route > is sent in the dhcp response - maybe that needs to be configurable...) > > 2) Is there an exact 1:1 correspondence between network and tunnel (or > perhaps there may be multiple tunnels for a network, but those tunnels > are not used by any other network on the same host)? If so, perhaps > your project could be simplified by just putting the tunnel config as > a subelement of , rather than referencing it - this way you > would avoid the need for the extra APIs to define/undefine/etc sectunnel. > > 3) Are your tunnels always L2, or do you have provision for setting up > L3 tunnels? (Perhaps that could be done by allowing multiple > elements, and having a that specified a tunnel rather than a > physical interface, as well as a list of routes as subelements? This, > along with a sectunnel subelement should be enough info to setup a > secure L3 tunnel which would be used for the specified routes, right? > > (BTW, after thinking about it some more, I think I agree that > is the right place to implement this, rather than a > virInterface (host) based (although that would also be > useful, totally separate from libvirt)). > > It seems we can gain a lot from each other! I'm hoping to have my > expansion of the network config completed by the end of June at > latest, but your work may enable/force me to hurry it a bit more than > that :-) > -- > libvir-list mailing list > libvir-list at redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list > From laine at laine.org Fri Apr 29 20:21:03 2011 From: laine at laine.org (Laine Stump) Date: Fri, 29 Apr 2011 16:21:03 -0400 Subject: [libvirt] [PATCH] hash: fix memory leak and regression In-Reply-To: <1304106837-18876-1-git-send-email-eblake@redhat.com> References: <1304106837-18876-1-git-send-email-eblake@redhat.com> Message-ID: <4DBB1DAF.2080800@laine.org> On 04/29/2011 03:53 PM, Eric Blake wrote: > Commit 1671d1d introduced a memory leak in virHashFree, and > wholesale table corruption in virHashRemoveSet (elements not > requested to be freed are lost). > > * src/util/hash.c (virHashFree): Free bucket array. > (virHashRemoveSet): Don't lose elements. > * tests/hashtest.c (testHashCheckForEachCount): New method. > (testHashCheckCount): Expose the bug. > --- > src/util/hash.c | 6 +++--- > tests/hashtest.c | 15 +++++++++++++++ > 2 files changed, 18 insertions(+), 3 deletions(-) > > diff --git a/src/util/hash.c b/src/util/hash.c > index a9b09b0..5366dd6 100644 > --- a/src/util/hash.c > +++ b/src/util/hash.c > @@ -269,6 +269,7 @@ virHashFree(virHashTablePtr table) > } > } > > + VIR_FREE(table->table); > VIR_FREE(table); > } > > @@ -532,13 +533,12 @@ int virHashForEach(virHashTablePtr table, virHashIterator iter, void *data) > * virHashRemoveSet > * @table: the hash table to process > * @iter: callback to identify elements for removal > - * @f: callback to free memory from element payload > * @data: opaque data to pass to the iterator > * > * Iterates over all elements in the hash table, invoking the 'iter' > * callback. If the callback returns a non-zero value, the element > * will be removed from the hash table& its payload passed to the > - * callback 'f' for de-allocation. > + * data freer callback registered at creation. > * > * Returns number of items removed on success, -1 on failure > */ > @@ -562,7 +562,7 @@ int virHashRemoveSet(virHashTablePtr table, > while (*nextptr) { > virHashEntryPtr entry = *nextptr; > if (!iter(entry->payload, entry->name, data)) { > - *nextptr = entry->next; > + nextptr =&entry->next; > } else { > count++; > if (table->dataFree) > diff --git a/tests/hashtest.c b/tests/hashtest.c > index 525ae06..f02b3a9 100644 > --- a/tests/hashtest.c > +++ b/tests/hashtest.c > @@ -61,16 +61,31 @@ testHashInit(int size) > return hash; > } > > +static void > +testHashCheckForEachCount(void *payload ATTRIBUTE_UNUSED, > + const void *name ATTRIBUTE_UNUSED, > + void *data ATTRIBUTE_UNUSED) > +{ > +} > > static int > testHashCheckCount(virHashTablePtr hash, int count) > { > + int iter_count = 0; > + > if (virHashSize(hash) != count) { > testError("\nhash contains %d instead of %d elements\n", > virHashSize(hash), count); > return -1; > } > > + iter_count = virHashForEach(hash, testHashCheckForEachCount, NULL); > + if (count != iter_count) { > + testError("\nhash claims to have %d elements but iteration finds %d\n", > + count, iter_count); > + return -1; > + } > + > return 0; > } ACK. From eblake at redhat.com Fri Apr 29 20:40:50 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 14:40:50 -0600 Subject: [libvirt] [PATCH] hash: fix memory leak and regression In-Reply-To: <4DBB1DAF.2080800@laine.org> References: <1304106837-18876-1-git-send-email-eblake@redhat.com> <4DBB1DAF.2080800@laine.org> Message-ID: <4DBB2252.8090908@redhat.com> On 04/29/2011 02:21 PM, Laine Stump wrote: > On 04/29/2011 03:53 PM, Eric Blake wrote: >> Commit 1671d1d introduced a memory leak in virHashFree, and >> wholesale table corruption in virHashRemoveSet (elements not >> requested to be freed are lost). >> >> * src/util/hash.c (virHashFree): Free bucket array. >> (virHashRemoveSet): Don't lose elements. >> * tests/hashtest.c (testHashCheckForEachCount): New method. >> (testHashCheckCount): Expose the bug. >> --- >> src/util/hash.c | 6 +++--- >> tests/hashtest.c | 15 +++++++++++++++ >> 2 files changed, 18 insertions(+), 3 deletions(-) > ACK. Thanks; pushed. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Fri Apr 29 23:54:44 2011 From: eblake at redhat.com (Eric Blake) Date: Fri, 29 Apr 2011 17:54:44 -0600 Subject: [libvirt] [PATCH] build: Fix problem of building Python bindings In-Reply-To: <1303875993-9780-1-git-send-email-jyang@redhat.com> References: <1303875993-9780-1-git-send-email-jyang@redhat.com> Message-ID: <4DBB4FC4.2010500@redhat.com> On 04/26/2011 09:46 PM, Osier Yang wrote: > If one specify "--with-python=yes" but no python-devel package > is installed, we ignore it with just a notice message, which > doesn't give clear guide to user. > --- > configure.ac | 6 ++---- > 1 files changed, 2 insertions(+), 4 deletions(-) > > diff --git a/configure.ac b/configure.ac > index 190bf40..758c893 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -1917,15 +1917,13 @@ if test "$with_python" != "no" ; then > then > PYTHON_INCLUDES=-I/usr/include/python$PYTHON_VERSION > else > - AC_MSG_NOTICE([Could not find python$PYTHON_VERSION/Python.h, disabling bindings]) > - with_python=no > + AC_MSG_ERROR([You must install python-devel to build Python bindings]) Hmm, this patch isn't quite right. I tested on an Ubuntu system where I don't have the devel package installed for python, and to my surprise, ./configure now fails, where it used to succeed without building any python bindings: configure: error: You must install python-devel to build Python bindings In reality, we want the default to be --with-python=check, which gracefully switches to --with-python=no if python is not present, and only issue the AC_MSG_ERROR on an explicit --with-python=yes without python bindings. I ran out of time to look at this today, but think it needs to be fixed before 0.9.1. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From supriyak at in.ibm.com Sat Apr 30 10:56:14 2011 From: supriyak at in.ibm.com (Supriya Kannery) Date: Sat, 30 Apr 2011 16:26:14 +0530 Subject: [libvirt] [PATCH] virsh: fix regression in log to file Message-ID: <4DBBEACE.1020503@in.ibm.com> Commit 36deff04 introduced a regression due to which virsh is not able to log to a file - msg_buf was changed from an array to a pointer without corresponding change to usage of "sizeof()". Fix regression in virsh logging Signed-off-by: Supriya Kannery --- tools/virsh.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) Index: libvirt/tools/virsh.c =================================================================== --- libvirt.orig/tools/virsh.c +++ libvirt/tools/virsh.c @@ -12257,7 +12257,7 @@ vshOutputLogFile(vshControl *ctl, int lo */ gettimeofday(&stTimeval, NULL); stTm = localtime(&stTimeval.tv_sec); - snprintf(msg_buf, sizeof(msg_buf), + snprintf(msg_buf, MSG_BUFFER, "[%d.%02d.%02d %02d:%02d:%02d ", (1900 + stTm->tm_year), (1 + stTm->tm_mon), @@ -12265,7 +12265,7 @@ vshOutputLogFile(vshControl *ctl, int lo (stTm->tm_hour), (stTm->tm_min), (stTm->tm_sec)); - snprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf), + snprintf(msg_buf + strlen(msg_buf), MSG_BUFFER - strlen(msg_buf), "%s] ", SIGN_NAME); switch (log_level) { case VSH_ERR_DEBUG: @@ -12287,13 +12287,13 @@ vshOutputLogFile(vshControl *ctl, int lo lvl = LVL_DEBUG; break; } - snprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf), + snprintf(msg_buf + strlen(msg_buf), MSG_BUFFER - strlen(msg_buf), "%s ", lvl); - vsnprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf), + vsnprintf(msg_buf + strlen(msg_buf), MSG_BUFFER - strlen(msg_buf), msg_format, ap); if (msg_buf[strlen(msg_buf) - 1] != '\n') - snprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf), "\n"); + snprintf(msg_buf + strlen(msg_buf), MSG_BUFFER - strlen(msg_buf), "\n"); /* write log */ if (safewrite(ctl->log_fd, msg_buf, strlen(msg_buf)) < 0) { From matthias.bolte at googlemail.com Sat Apr 30 11:10:55 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 30 Apr 2011 13:10:55 +0200 Subject: [libvirt] [PATCH v2] tests: Lower stack usage below 4096 bytes Message-ID: <20110430111055.GA2607@sbox> Make virtTestLoadFile allocate the buffer to read the file into. Fix logic error in virtTestLoadFile, stop reading on the first empty line. Use virFileReadLimFD in virtTestCaptureProgramOutput to avoid manual buffer handling. --- v2: rebased to current git head. m4/virt-compile-warnings.m4 | 10 ++--- tests/conftest.c | 29 ++++++++++---- tests/cputest.c | 64 ++++++++++++++++++------------ tests/esxutilstest.c | 2 + tests/interfacexml2xmltest.c | 31 ++++++++++----- tests/networkxml2xmltest.c | 49 ++++++++++++++--------- tests/nodedevxml2xmltest.c | 32 ++++++++++------ tests/nodeinfotest.c | 65 ++++++++++++++++++++----------- tests/nwfilterxml2xmltest.c | 52 +++++++++++++++---------- tests/qemuargv2xmltest.c | 41 ++++++++++++-------- tests/qemuhelptest.c | 11 ++--- tests/qemuxml2argvtest.c | 52 +++++++++++++++---------- tests/qemuxml2xmltest.c | 41 +++++++++++--------- tests/sexpr2xmltest.c | 49 ++++++++++++++--------- tests/storagepoolxml2xmltest.c | 49 ++++++++++++++--------- tests/storagevolxml2xmltest.c | 63 ++++++++++++++++++------------ tests/testutils.c | 69 +++++++++++++++------------------ tests/testutils.h | 8 +--- tests/virshtest.c | 58 +++++++++++----------------- tests/vmx2xmltest.c | 39 +++++++++++-------- tests/xencapstest.c | 36 ++++++++--------- tests/xmconfigtest.c | 83 +++++++++++++++++++++++---------------- tests/xml2sexprtest.c | 51 +++++++++++++++---------- tests/xml2vmxtest.c | 39 +++++++++++-------- 24 files changed, 588 insertions(+), 435 deletions(-) diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4 index 295fd9b..305036f 100644 --- a/m4/virt-compile-warnings.m4 +++ b/m4/virt-compile-warnings.m4 @@ -88,12 +88,10 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ # that one off, so we need to manually enable this again gl_WARN_ADD([-Wjump-misses-init]) - # This should be < 256 really, but with PATH_MAX everywhere - # we have doom, even with 4096. In fact we have some functions - # with several PATH_MAX sized variables :-( We should kill off - # all PATH_MAX usage and then lower this limit - gl_WARN_ADD([-Wframe-larger-than=65700]) - dnl gl_WARN_ADD([-Wframe-larger-than=4096]) + # This should be < 256 really. Currently we're down to 4096, + # but using 1024 bytes sized buffers (mostly for virStrerror) + # stops us from going down further + gl_WARN_ADD([-Wframe-larger-than=4096]) dnl gl_WARN_ADD([-Wframe-larger-than=256]) # Extra special flags diff --git a/tests/conftest.c b/tests/conftest.c index a7977bb..6514f4d 100644 --- a/tests/conftest.c +++ b/tests/conftest.c @@ -6,32 +6,43 @@ #include #include #include "conf.h" +#include "memory.h" -int main(int argc, char **argv) { - int ret; +int main(int argc, char **argv) +{ + int ret, exit_code = EXIT_FAILURE; virConfPtr conf; int len = 10000; - char buffer[10000]; + char *buffer = NULL; if (argc != 2) { fprintf(stderr, "Usage: %s conf_file\n", argv[0]); - exit(EXIT_FAILURE); + goto cleanup; } + if (VIR_ALLOC_N(buffer, len) < 0) { + fprintf(stderr, "out of memory\n"); + goto cleanup; + } conf = virConfReadFile(argv[1], 0); if (conf == NULL) { fprintf(stderr, "Failed to process %s\n", argv[1]); - exit(EXIT_FAILURE); + goto cleanup; } - ret = virConfWriteMem(&buffer[0], &len, conf); + ret = virConfWriteMem(buffer, &len, conf); if (ret < 0) { fprintf(stderr, "Failed to serialize %s back\n", argv[1]); - exit(EXIT_FAILURE); + goto cleanup; } virConfFree(conf); if (fwrite(buffer, 1, len, stdout) != len) { fprintf(stderr, "Write failed: %s\n", strerror (errno)); - exit(EXIT_FAILURE); + goto cleanup; } - exit(EXIT_SUCCESS); + + exit_code = EXIT_SUCCESS; + +cleanup: + VIR_FREE(buffer); + return exit_code; } diff --git a/tests/cputest.c b/tests/cputest.c index a8d28dc..b132ceb 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -42,7 +42,6 @@ static const char *abs_top_srcdir; #define VIR_FROM_THIS VIR_FROM_CPU -#define MAX_FILE 4096 enum compResultShadow { ERROR = VIR_CPU_COMPARE_ERROR, @@ -89,14 +88,13 @@ struct data { static virCPUDefPtr cpuTestLoadXML(const char *arch, const char *name) { - char xml[PATH_MAX]; + char *xml = NULL; xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; virCPUDefPtr cpu = NULL; - snprintf(xml, PATH_MAX, - "%s/cputestdata/%s-%s.xml", - abs_srcdir, arch, name); + if (virAsprintf(&xml, "%s/cputestdata/%s-%s.xml", abs_srcdir, arch, name) < 0) + goto cleanup; if (!(doc = virXMLParseFile(xml)) || !(ctxt = xmlXPathNewContext(doc))) @@ -108,6 +106,7 @@ cpuTestLoadXML(const char *arch, const char *name) cleanup: xmlXPathFreeContext(ctxt); xmlFreeDoc(doc); + free(xml); return cpu; } @@ -117,7 +116,7 @@ cpuTestLoadMultiXML(const char *arch, const char *name, unsigned int *count) { - char xml[PATH_MAX]; + char *xml = NULL; xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; xmlNodePtr *nodes = NULL; @@ -125,9 +124,8 @@ cpuTestLoadMultiXML(const char *arch, int n; int i; - snprintf(xml, PATH_MAX, - "%s/cputestdata/%s-%s.xml", - abs_srcdir, arch, name); + if (virAsprintf(&xml, "%s/cputestdata/%s-%s.xml", abs_srcdir, arch, name) < 0) + goto cleanup; if (!(doc = virXMLParseFile(xml)) || !(ctxt = xmlXPathNewContext(doc))) @@ -149,6 +147,7 @@ cpuTestLoadMultiXML(const char *arch, *count = n; cleanup: + free(xml); free(nodes); xmlXPathFreeContext(ctxt); xmlFreeDoc(doc); @@ -170,17 +169,16 @@ cpuTestCompareXML(const char *arch, const virCPUDefPtr cpu, const char *name) { - char xml[PATH_MAX]; - char expected[MAX_FILE]; - char *expectedPtr = &(expected[0]); + char *xml = NULL; + char *expected = NULL; char *actual = NULL; int ret = -1; - snprintf(xml, PATH_MAX, - "%s/cputestdata/%s-%s.xml", - abs_srcdir, arch, name); + if (virAsprintf(&xml, "%s/cputestdata/%s-%s.xml", + abs_srcdir, arch, name) < 0) + goto cleanup; - if (virtTestLoadFile(xml, &expectedPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &expected) < 0) goto cleanup; if (!(actual = virCPUDefFormat(cpu, NULL, 0))) @@ -194,6 +192,8 @@ cpuTestCompareXML(const char *arch, ret = 0; cleanup: + free(xml); + free(expected); free(actual); return ret; } @@ -333,7 +333,7 @@ cpuTestBaseline(const void *arg) virCPUDefPtr *cpus = NULL; virCPUDefPtr baseline = NULL; unsigned int ncpus = 0; - char result[PATH_MAX]; + char *result = NULL; unsigned int i; if (!(cpus = cpuTestLoadMultiXML(data->arch, data->name, &ncpus))) @@ -353,7 +353,9 @@ cpuTestBaseline(const void *arg) if (!baseline) goto cleanup; - snprintf(result, PATH_MAX, "%s-result", data->name); + if (virAsprintf(&result, "%s-result", data->name) < 0) + goto cleanup; + if (cpuTestCompareXML(data->arch, baseline, result) < 0) goto cleanup; @@ -382,6 +384,7 @@ cleanup: free(cpus); } virCPUDefFree(baseline); + free(result); return ret; } @@ -393,7 +396,7 @@ cpuTestUpdate(const void *arg) int ret = -1; virCPUDefPtr host = NULL; virCPUDefPtr cpu = NULL; - char result[PATH_MAX]; + char *result = NULL; if (!(host = cpuTestLoadXML(data->arch, data->host)) || !(cpu = cpuTestLoadXML(data->arch, data->name))) @@ -402,12 +405,15 @@ cpuTestUpdate(const void *arg) if (cpuUpdate(cpu, host) < 0) goto cleanup; - snprintf(result, PATH_MAX, "%s+%s", data->host, data->name); + if (virAsprintf(&result, "%s+%s", data->host, data->name) < 0) + goto cleanup; + ret = cpuTestCompareXML(data->arch, cpu, result); cleanup: virCPUDefFree(host); virCPUDefFree(cpu); + free(result); return ret; } @@ -465,10 +471,10 @@ static int (*cpuTest[])(const void *) = { static int cpuTestRun(const char *name, const struct data *data) { - char label[PATH_MAX]; + char *label = NULL; - snprintf(label, PATH_MAX, "CPU %s(%s): %s", - apis[data->api], data->arch, name); + if (virAsprintf(&label, "CPU %s(%s): %s", apis[data->api], data->arch, name) < 0) + return -1; free(virtTestLogContentAndReset()); @@ -480,9 +486,12 @@ cpuTestRun(const char *name, const struct data *data) fprintf(stderr, "\n%s\n", log); free(log); } + + free(label); return -1; } + free(label); return 0; } @@ -495,15 +504,17 @@ static int mymain(void) { int ret = 0; - char map[PATH_MAX]; + char *map = NULL; abs_top_srcdir = getenv("abs_top_srcdir"); if (!abs_top_srcdir) abs_top_srcdir = ".."; - snprintf(map, PATH_MAX, "%s/src/cpu/cpu_map.xml", abs_top_srcdir); - if (cpuMapOverride(map) < 0) + if (virAsprintf(&map, "%s/src/cpu/cpu_map.xml", abs_top_srcdir) < 0 || + cpuMapOverride(map) < 0) { + free(map); return EXIT_FAILURE; + } #define DO_TEST(arch, api, name, host, cpu, \ models, nmodels, preferred, result) \ @@ -613,6 +624,7 @@ mymain(void) DO_TEST_GUESTDATA("x86", "host", "guest", models, "qemu64", 0); DO_TEST_GUESTDATA("x86", "host", "guest", nomodel, NULL, -1); + free(map); return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE); } diff --git a/tests/esxutilstest.c b/tests/esxutilstest.c index 830f79c..2b36535 100644 --- a/tests/esxutilstest.c +++ b/tests/esxutilstest.c @@ -273,6 +273,7 @@ testEscapeDatastoreItem(const void *data ATTRIBUTE_UNUSED) } } + VIR_FREE(escaped); return 0; } @@ -314,6 +315,7 @@ testConvertWindows1252ToUTF8(const void *data ATTRIBUTE_UNUSED) } } + VIR_FREE(utf8); return 0; } diff --git a/tests/interfacexml2xmltest.c b/tests/interfacexml2xmltest.c index fb454c1..dc08ea7 100644 --- a/tests/interfacexml2xmltest.c +++ b/tests/interfacexml2xmltest.c @@ -13,17 +13,16 @@ #include "interface_conf.h" #include "testutilsqemu.h" -#define MAX_FILE 4096 - -static int testCompareXMLToXMLFiles(const char *xml) { - char xmlData[MAX_FILE]; - char *xmlPtr = &(xmlData[0]); +static int +testCompareXMLToXMLFiles(const char *xml) +{ + char *xmlData = NULL; char *actual = NULL; int ret = -1; virInterfaceDefPtr dev = NULL; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; if (!(dev = virInterfaceDefParseString(xmlData))) @@ -40,16 +39,26 @@ static int testCompareXMLToXMLFiles(const char *xml) { ret = 0; fail: + free(xmlData); free(actual); virInterfaceDefFree(dev); return ret; } -static int testCompareXMLToXMLHelper(const void *data) { - char xml[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/interfaceschemadata/%s.xml", - abs_srcdir, (const char*)data); - return testCompareXMLToXMLFiles(xml); +static int +testCompareXMLToXMLHelper(const void *data) +{ + int result = -1; + char *xml = NULL; + + if (virAsprintf(&xml, "%s/interfaceschemadata/%s.xml", + abs_srcdir, (const char*)data) < 0) + return -1; + + result = testCompareXMLToXMLFiles(xml); + + free (xml); + return result; } diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c index f7489f5..468785b 100644 --- a/tests/networkxml2xmltest.c +++ b/tests/networkxml2xmltest.c @@ -13,21 +13,18 @@ #include "network_conf.h" #include "testutilsqemu.h" -#define MAX_FILE 4096 - - -static int testCompareXMLToXMLFiles(const char *inxml, const char *outxml) { - char inXmlData[MAX_FILE]; - char *inXmlPtr = &(inXmlData[0]); - char outXmlData[MAX_FILE]; - char *outXmlPtr = &(outXmlData[0]); +static int +testCompareXMLToXMLFiles(const char *inxml, const char *outxml) +{ + char *inXmlData = NULL; + char *outXmlData = NULL; char *actual = NULL; int ret = -1; virNetworkDefPtr dev = NULL; - if (virtTestLoadFile(inxml, &inXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(inxml, &inXmlData) < 0) goto fail; - if (virtTestLoadFile(outxml, &outXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(outxml, &outXmlData) < 0) goto fail; if (!(dev = virNetworkDefParseString(inXmlData))) @@ -44,21 +41,35 @@ static int testCompareXMLToXMLFiles(const char *inxml, const char *outxml) { ret = 0; fail: + free(inXmlData); + free(outXmlData); free(actual); virNetworkDefFree(dev); return ret; } -static int testCompareXMLToXMLHelper(const void *data) { - char inxml[PATH_MAX]; - char outxml[PATH_MAX]; - snprintf(inxml, PATH_MAX, "%s/networkxml2xmlin/%s.xml", - abs_srcdir, (const char*)data); - snprintf(outxml, PATH_MAX, "%s/networkxml2xmlout/%s.xml", - abs_srcdir, (const char*)data); - return testCompareXMLToXMLFiles(inxml, outxml); -} +static int +testCompareXMLToXMLHelper(const void *data) +{ + int result = -1; + char *inxml = NULL; + char *outxml = NULL; + + if (virAsprintf(&inxml, "%s/networkxml2xmlin/%s.xml", + abs_srcdir, (const char*)data) < 0 || + virAsprintf(&outxml, "%s/networkxml2xmlout/%s.xml", + abs_srcdir, (const char*)data) < 0) { + goto cleanup; + } + + result = testCompareXMLToXMLFiles(inxml, outxml); +cleanup: + free(inxml); + free(outxml); + + return result; +} static int mymain(void) diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c index f6a1335..d0deaeb 100644 --- a/tests/nodedevxml2xmltest.c +++ b/tests/nodedevxml2xmltest.c @@ -13,17 +13,15 @@ #include "node_device_conf.h" #include "testutilsqemu.h" -#define MAX_FILE 4096 - - -static int testCompareXMLToXMLFiles(const char *xml) { - char xmlData[MAX_FILE]; - char *xmlPtr = &(xmlData[0]); +static int +testCompareXMLToXMLFiles(const char *xml) +{ + char *xmlData = NULL; char *actual = NULL; int ret = -1; virNodeDeviceDefPtr dev = NULL; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; if (!(dev = virNodeDeviceDefParseString(xmlData, EXISTING_DEVICE))) @@ -40,16 +38,26 @@ static int testCompareXMLToXMLFiles(const char *xml) { ret = 0; fail: + free(xmlData); free(actual); virNodeDeviceDefFree(dev); return ret; } -static int testCompareXMLToXMLHelper(const void *data) { - char xml[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/nodedevschemadata/%s.xml", - abs_srcdir, (const char*)data); - return testCompareXMLToXMLFiles(xml); +static int +testCompareXMLToXMLHelper(const void *data) +{ + int result = -1; + char *xml = NULL; + + if (virAsprintf(&xml, "%s/nodedevschemadata/%s.xml", + abs_srcdir, (const char*)data) < 0) + return -1; + + result = testCompareXMLToXMLFiles(xml); + + free(xml); + return result; } diff --git a/tests/nodeinfotest.c b/tests/nodeinfotest.c index 9a87dc0..b4e81b3 100644 --- a/tests/nodeinfotest.c +++ b/tests/nodeinfotest.c @@ -21,24 +21,24 @@ mymain(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) #else -# define MAX_FILE 4096 - extern int linuxNodeInfoCPUPopulate(FILE *cpuinfo, virNodeInfoPtr nodeinfo, bool need_hyperthreads); -static int linuxTestCompareFiles(const char *cpuinfofile, const char *outputfile) { - char actualData[MAX_FILE]; - char expectData[MAX_FILE]; - char *expect = &expectData[0]; +static int +linuxTestCompareFiles(const char *cpuinfofile, const char *outputfile) +{ + int ret = -1; + char *actualData = NULL; + char *expectData = NULL; virNodeInfo nodeinfo; FILE *cpuinfo; - if (virtTestLoadFile(outputfile, &expect, MAX_FILE) < 0) - return -1; + if (virtTestLoadFile(outputfile, &expectData) < 0) + goto fail; cpuinfo = fopen(cpuinfofile, "r"); if (!cpuinfo) - return -1; + goto fail; memset(&nodeinfo, 0, sizeof(nodeinfo)); if (linuxNodeInfoCPUPopulate(cpuinfo, &nodeinfo, false) < 0) { @@ -49,7 +49,7 @@ static int linuxTestCompareFiles(const char *cpuinfofile, const char *outputfile virFreeError(error); } VIR_FORCE_FCLOSE(cpuinfo); - return -1; + goto fail; } VIR_FORCE_FCLOSE(cpuinfo); @@ -58,30 +58,49 @@ static int linuxTestCompareFiles(const char *cpuinfofile, const char *outputfile * so blank it to a predictable value */ nodeinfo.nodes = 1; - snprintf(actualData, MAX_FILE, - "CPUs: %u, MHz: %u, Nodes: %u, Cores: %u\n", - nodeinfo.cpus, nodeinfo.mhz, nodeinfo.nodes, nodeinfo.cores); + if (virAsprintf(&actualData, "CPUs: %u, MHz: %u, Nodes: %u, Cores: %u\n", + nodeinfo.cpus, nodeinfo.mhz, nodeinfo.nodes, + nodeinfo.cores) < 0) + goto fail; if (STRNEQ(actualData, expectData)) { if (getenv("DEBUG_TESTS")) { printf("Expect %d '%s'\n", (int)strlen(expectData), expectData); printf("Actual %d '%s'\n", (int)strlen(actualData), actualData); } - return -1; + goto fail; } - return 0; + ret = 0; + +fail: + free(expectData); + free(actualData); + return ret; } -static int linuxTestNodeInfo(const void *data) { - char cpuinfo[PATH_MAX]; - char output[PATH_MAX]; - snprintf(cpuinfo, PATH_MAX, "%s/nodeinfodata/linux-%s.cpuinfo", - abs_srcdir, (const char*)data); - snprintf(output, PATH_MAX, "%s/nodeinfodata/linux-%s.txt", - abs_srcdir, (const char*)data); - return linuxTestCompareFiles(cpuinfo, output); +static int +linuxTestNodeInfo(const void *data) +{ + int result = -1; + char *cpuinfo = NULL; + char *output = NULL; + + if (virAsprintf(&cpuinfo, "%s/nodeinfodata/linux-%s.cpuinfo", + abs_srcdir, (const char*)data) < 0 || + virAsprintf(&output, "%s/nodeinfodata/linux-%s.txt", + abs_srcdir, (const char*)data) < 0) { + goto cleanup; + } + + result = linuxTestCompareFiles(cpuinfo, output); + +cleanup: + free(cpuinfo); + free(output); + + return result; } diff --git a/tests/nwfilterxml2xmltest.c b/tests/nwfilterxml2xmltest.c index a1f57fa..49c6b99 100644 --- a/tests/nwfilterxml2xmltest.c +++ b/tests/nwfilterxml2xmltest.c @@ -16,23 +16,19 @@ #include "nwfilter_conf.h" #include "testutilsqemu.h" -#define MAX_FILE 4096 - - -static int testCompareXMLToXMLFiles(const char *inxml, - const char *outxml, - bool expect_error) { - char inXmlData[MAX_FILE]; - char *inXmlPtr = &(inXmlData[0]); - char outXmlData[MAX_FILE]; - char *outXmlPtr = &(outXmlData[0]); +static int +testCompareXMLToXMLFiles(const char *inxml, const char *outxml, + bool expect_error) +{ + char *inXmlData = NULL; + char *outXmlData = NULL; char *actual = NULL; int ret = -1; virNWFilterDefPtr dev = NULL; - if (virtTestLoadFile(inxml, &inXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(inxml, &inXmlData) < 0) goto fail; - if (virtTestLoadFile(outxml, &outXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(outxml, &outXmlData) < 0) goto fail; virResetLastError(); @@ -59,6 +55,8 @@ static int testCompareXMLToXMLFiles(const char *inxml, ret = 0; fail: + free(inXmlData); + free(outXmlData); free(actual); virNWFilterDefFree(dev); return ret; @@ -69,17 +67,29 @@ typedef struct test_parms { bool expect_warning; } test_parms; -static int testCompareXMLToXMLHelper(const void *data) { +static int +testCompareXMLToXMLHelper(const void *data) +{ + int result = -1; const test_parms *tp = data; - char inxml[PATH_MAX]; - char outxml[PATH_MAX]; - snprintf(inxml, PATH_MAX, "%s/nwfilterxml2xmlin/%s.xml", - abs_srcdir, tp->name); - snprintf(outxml, PATH_MAX, "%s/nwfilterxml2xmlout/%s.xml", - abs_srcdir, tp->name); - return testCompareXMLToXMLFiles(inxml, outxml, tp->expect_warning); -} + char *inxml = NULL; + char *outxml = NULL; + + if (virAsprintf(&inxml, "%s/nwfilterxml2xmlin/%s.xml", + abs_srcdir, tp->name) < 0 || + virAsprintf(&outxml, "%s/nwfilterxml2xmlout/%s.xml", + abs_srcdir, tp->name) < 0) { + goto cleanup; + } + + result = testCompareXMLToXMLFiles(inxml, outxml, tp->expect_warning); +cleanup: + free(inxml); + free(outxml); + + return result; +} static int mymain(void) diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c index 60dce46..db68b60 100644 --- a/tests/qemuargv2xmltest.c +++ b/tests/qemuargv2xmltest.c @@ -18,8 +18,6 @@ static struct qemud_driver driver; -# define MAX_FILE 4096 - static int blankProblemElements(char *data) { if (virtTestClearLineRegex("[[:alnum:]]+", data) < 0 || @@ -35,18 +33,16 @@ static int blankProblemElements(char *data) static int testCompareXMLToArgvFiles(const char *xml, const char *cmdfile, bool expect_warning) { - char xmlData[MAX_FILE]; - char cmdData[MAX_FILE]; - char *expectxml = &(xmlData[0]); + char *expectxml = NULL; char *actualxml = NULL; - char *cmd = &(cmdData[0]); + char *cmd = NULL; int ret = -1; virDomainDefPtr vmdef = NULL; char *log; - if (virtTestLoadFile(cmdfile, &cmd, MAX_FILE) < 0) + if (virtTestLoadFile(cmdfile, &cmd) < 0) goto fail; - if (virtTestLoadFile(xml, &expectxml, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &expectxml) < 0) goto fail; if (!(vmdef = qemuParseCommandLineString(driver.caps, cmd))) @@ -75,7 +71,9 @@ static int testCompareXMLToArgvFiles(const char *xml, ret = 0; fail: + free(expectxml); free(actualxml); + free(cmd); virDomainDefFree(vmdef); return ret; } @@ -87,15 +85,26 @@ struct testInfo { const char *migrateFrom; }; -static int testCompareXMLToArgvHelper(const void *data) { +static int +testCompareXMLToArgvHelper(const void *data) +{ + int result = -1; const struct testInfo *info = data; - char xml[PATH_MAX]; - char args[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", - abs_srcdir, info->name); - snprintf(args, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.args", - abs_srcdir, info->name); - return testCompareXMLToArgvFiles(xml, args, !!info->extraFlags); + char *xml = NULL; + char *args = NULL; + + if (virAsprintf(&xml, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&args, "%s/qemuxml2argvdata/qemuxml2argv-%s.args", + abs_srcdir, info->name) < 0) + goto cleanup; + + result = testCompareXMLToArgvFiles(xml, args, !!info->extraFlags); + +cleanup: + free(xml); + free(args); + return result; } diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index 792b5ab..2522396 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -9,8 +9,6 @@ # include "qemu/qemu_capabilities.h" # include "memory.h" -# define MAX_HELP_OUTPUT_SIZE 1024*64 - struct testInfo { const char *name; virBitmapPtr flags; @@ -38,8 +36,7 @@ static int testHelpStrParsing(const void *data) { const struct testInfo *info = data; char *path = NULL; - char helpStr[MAX_HELP_OUTPUT_SIZE]; - char *help = &(helpStr[0]); + char *help = NULL; unsigned int version, is_kvm, kvm_version; virBitmapPtr flags = NULL; int ret = -1; @@ -49,7 +46,7 @@ static int testHelpStrParsing(const void *data) if (virAsprintf(&path, "%s/qemuhelpdata/%s", abs_srcdir, info->name) < 0) return -1; - if (virtTestLoadFile(path, &help, MAX_HELP_OUTPUT_SIZE) < 0) + if (virtTestLoadFile(path, &help) < 0) goto cleanup; if (!(flags = qemuCapsNew())) @@ -61,11 +58,12 @@ static int testHelpStrParsing(const void *data) if (qemuCapsGet(info->flags, QEMU_CAPS_DEVICE)) { VIR_FREE(path); + VIR_FREE(help); if (virAsprintf(&path, "%s/qemuhelpdata/%s-device", abs_srcdir, info->name) < 0) goto cleanup; - if (virtTestLoadFile(path, &help, MAX_HELP_OUTPUT_SIZE) < 0) + if (virtTestLoadFile(path, &help) < 0) goto cleanup; if (qemuCapsParseDeviceStr(help, flags) < 0) @@ -111,6 +109,7 @@ static int testHelpStrParsing(const void *data) ret = 0; cleanup: VIR_FREE(path); + VIR_FREE(help); qemuCapsFree(flags); VIR_FREE(got); VIR_FREE(expected); diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index ebde3a1..a7e4cc0 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -22,16 +22,14 @@ static const char *abs_top_srcdir; static struct qemud_driver driver; -# define MAX_FILE 4096 - static int testCompareXMLToArgvFiles(const char *xml, const char *cmdline, virBitmapPtr extraFlags, const char *migrateFrom, int migrateFd, - bool expectError) { - char argvData[MAX_FILE]; - char *expectargv = &(argvData[0]); + bool expectError) +{ + char *expectargv = NULL; int len; char *actualargv = NULL; int ret = -1; @@ -45,7 +43,7 @@ static int testCompareXMLToArgvFiles(const char *xml, if (!(conn = virGetConnect())) goto fail; - len = virtTestLoadFile(cmdline, &expectargv, MAX_FILE); + len = virtTestLoadFile(cmdline, &expectargv); if (len < 0) goto fail; if (len && expectargv[len - 1] == '\n') @@ -156,6 +154,7 @@ static int testCompareXMLToArgvFiles(const char *xml, fail: free(log); free(emulator); + free(expectargv); free(actualargv); virCommandFree(cmd); virDomainDefFree(vmdef); @@ -172,17 +171,28 @@ struct testInfo { bool expectError; }; -static int testCompareXMLToArgvHelper(const void *data) { +static int +testCompareXMLToArgvHelper(const void *data) +{ + int result = -1; const struct testInfo *info = data; - char xml[PATH_MAX]; - char args[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", - abs_srcdir, info->name); - snprintf(args, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.args", - abs_srcdir, info->name); - return testCompareXMLToArgvFiles(xml, args, info->extraFlags, - info->migrateFrom, info->migrateFd, - info->expectError); + char *xml = NULL; + char *args = NULL; + + if (virAsprintf(&xml, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&args, "%s/qemuxml2argvdata/qemuxml2argv-%s.args", + abs_srcdir, info->name) < 0) + goto cleanup; + + result = testCompareXMLToArgvFiles(xml, args, info->extraFlags, + info->migrateFrom, info->migrateFd, + info->expectError); + +cleanup: + free(xml); + free(args); + return result; } @@ -191,7 +201,7 @@ static int mymain(void) { int ret = 0; - char map[PATH_MAX]; + char *map = NULL; abs_top_srcdir = getenv("abs_top_srcdir"); if (!abs_top_srcdir) @@ -210,10 +220,11 @@ mymain(void) return EXIT_FAILURE; if (!(driver.spicePassword = strdup("123456"))) return EXIT_FAILURE; - - snprintf(map, PATH_MAX, "%s/src/cpu/cpu_map.xml", abs_top_srcdir); - if (cpuMapOverride(map) < 0) + if (virAsprintf(&map, "%s/src/cpu/cpu_map.xml", abs_top_srcdir) < 0 || + cpuMapOverride(map) < 0) { + free(map); return EXIT_FAILURE; + } # define DO_TEST_FULL(name, migrateFrom, migrateFd, expectError, ...) \ do { \ @@ -484,6 +495,7 @@ mymain(void) free(driver.stateDir); virCapabilitiesFree(driver.caps); + free(map); return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 6f51d1e..5bfbcab 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -17,21 +17,18 @@ static struct qemud_driver driver; -# define MAX_FILE 4096 - - -static int testCompareXMLToXMLFiles(const char *inxml, const char *outxml) { - char inXmlData[MAX_FILE]; - char *inXmlPtr = &(inXmlData[0]); - char outXmlData[MAX_FILE]; - char *outXmlPtr = &(outXmlData[0]); +static int +testCompareXMLToXMLFiles(const char *inxml, const char *outxml) +{ + char *inXmlData = NULL; + char *outXmlData = NULL; char *actual = NULL; int ret = -1; virDomainDefPtr def = NULL; - if (virtTestLoadFile(inxml, &inXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(inxml, &inXmlData) < 0) goto fail; - if (virtTestLoadFile(outxml, &outXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(outxml, &outXmlData) < 0) goto fail; if (!(def = virDomainDefParseString(driver.caps, inXmlData, @@ -49,6 +46,8 @@ static int testCompareXMLToXMLFiles(const char *inxml, const char *outxml) { ret = 0; fail: + free(inXmlData); + free(outXmlData); free(actual); virDomainDefFree(def); return ret; @@ -59,16 +58,19 @@ struct testInfo { int different; }; -static int testCompareXMLToXMLHelper(const void *data) { +static int +testCompareXMLToXMLHelper(const void *data) +{ const struct testInfo *info = data; - char xml_in[PATH_MAX]; - char xml_out[PATH_MAX]; - int ret; + char *xml_in = NULL; + char *xml_out = NULL; + int ret = -1; - snprintf(xml_in, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", - abs_srcdir, info->name); - snprintf(xml_out, PATH_MAX, "%s/qemuxml2xmloutdata/qemuxml2xmlout-%s.xml", - abs_srcdir, info->name); + if (virAsprintf(&xml_in, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&xml_out, "%s/qemuxml2xmloutdata/qemuxml2xmlout-%s.xml", + abs_srcdir, info->name) < 0) + goto cleanup; if (info->different) { ret = testCompareXMLToXMLFiles(xml_in, xml_out); @@ -76,6 +78,9 @@ static int testCompareXMLToXMLHelper(const void *data) { ret = testCompareXMLToXMLFiles(xml_in, xml_in); } +cleanup: + free(xml_in); + free(xml_out); return ret; } diff --git a/tests/sexpr2xmltest.c b/tests/sexpr2xmltest.c index 0919435..f465105 100644 --- a/tests/sexpr2xmltest.c +++ b/tests/sexpr2xmltest.c @@ -15,15 +15,12 @@ static virCapsPtr caps; -#define MAX_FILE 4096 - -static int testCompareFiles(const char *xml, const char *sexpr, - int xendConfigVersion) { - char xmlData[MAX_FILE]; - char sexprData[MAX_FILE]; +static int +testCompareFiles(const char *xml, const char *sexpr, int xendConfigVersion) +{ + char *xmlData = NULL; + char *sexprData = NULL; char *gotxml = NULL; - char *xmlPtr = &(xmlData[0]); - char *sexprPtr = &(sexprData[0]); int id; char * tty; int vncport; @@ -36,10 +33,10 @@ static int testCompareFiles(const char *xml, const char *sexpr, conn = virGetConnect(); if (!conn) goto fail; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; - if (virtTestLoadFile(sexpr, &sexprPtr, MAX_FILE) < 0) + if (virtTestLoadFile(sexpr, &sexprData) < 0) goto fail; memset(&priv, 0, sizeof priv); @@ -70,6 +67,8 @@ static int testCompareFiles(const char *xml, const char *sexpr, ret = 0; fail: + free(xmlData); + free(sexprData); free(gotxml); virDomainDefFree(def); if (conn) @@ -84,17 +83,29 @@ struct testInfo { int version; }; -static int testCompareHelper(const void *data) { +static int +testCompareHelper(const void *data) +{ + int result = -1; const struct testInfo *info = data; - char xml[PATH_MAX]; - char args[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/sexpr2xmldata/sexpr2xml-%s.xml", - abs_srcdir, info->input); - snprintf(args, PATH_MAX, "%s/sexpr2xmldata/sexpr2xml-%s.sexpr", - abs_srcdir, info->output); - return testCompareFiles(xml, args, info->version); -} + char *xml = NULL; + char *args = NULL; + + if (virAsprintf(&xml, "%s/sexpr2xmldata/sexpr2xml-%s.xml", + abs_srcdir, info->input) < 0 || + virAsprintf(&args, "%s/sexpr2xmldata/sexpr2xml-%s.sexpr", + abs_srcdir, info->output) < 0) { + goto cleanup; + } + + result = testCompareFiles(xml, args, info->version); +cleanup: + free(xml); + free(args); + + return result; +} static int mymain(void) diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c index 6641153..f2c1780 100644 --- a/tests/storagepoolxml2xmltest.c +++ b/tests/storagepoolxml2xmltest.c @@ -13,21 +13,18 @@ #include "storage_conf.h" #include "testutilsqemu.h" -#define MAX_FILE 4096 - - -static int testCompareXMLToXMLFiles(const char *inxml, const char *outxml) { - char inXmlData[MAX_FILE]; - char *inXmlPtr = &(inXmlData[0]); - char outXmlData[MAX_FILE]; - char *outXmlPtr = &(outXmlData[0]); +static int +testCompareXMLToXMLFiles(const char *inxml, const char *outxml) +{ + char *inXmlData = NULL; + char *outXmlData = NULL; char *actual = NULL; int ret = -1; virStoragePoolDefPtr dev = NULL; - if (virtTestLoadFile(inxml, &inXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(inxml, &inXmlData) < 0) goto fail; - if (virtTestLoadFile(outxml, &outXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(outxml, &outXmlData) < 0) goto fail; if (!(dev = virStoragePoolDefParseString(inXmlData))) @@ -44,21 +41,35 @@ static int testCompareXMLToXMLFiles(const char *inxml, const char *outxml) { ret = 0; fail: + free(inXmlData); + free(outXmlData); free(actual); virStoragePoolDefFree(dev); return ret; } -static int testCompareXMLToXMLHelper(const void *data) { - char inxml[PATH_MAX]; - char outxml[PATH_MAX]; - snprintf(inxml, PATH_MAX, "%s/storagepoolxml2xmlin/%s.xml", - abs_srcdir, (const char*)data); - snprintf(outxml, PATH_MAX, "%s/storagepoolxml2xmlout/%s.xml", - abs_srcdir, (const char*)data); - return testCompareXMLToXMLFiles(inxml, outxml); -} +static int +testCompareXMLToXMLHelper(const void *data) +{ + int result = -1; + char *inxml = NULL; + char *outxml = NULL; + + if (virAsprintf(&inxml, "%s/storagepoolxml2xmlin/%s.xml", + abs_srcdir, (const char*)data) < 0 || + virAsprintf(&outxml, "%s/storagepoolxml2xmlout/%s.xml", + abs_srcdir, (const char*)data) < 0) { + goto cleanup; + } + + result = testCompareXMLToXMLFiles(inxml, outxml); +cleanup: + free(inxml); + free(outxml); + + return result; +} static int mymain(void) diff --git a/tests/storagevolxml2xmltest.c b/tests/storagevolxml2xmltest.c index 0cd57af..c8dddbb 100644 --- a/tests/storagevolxml2xmltest.c +++ b/tests/storagevolxml2xmltest.c @@ -13,28 +13,23 @@ #include "storage_conf.h" #include "testutilsqemu.h" -#define MAX_FILE 4096 - - -static int testCompareXMLToXMLFiles(const char *poolxml, - const char *inxml, - const char *outxml) { - char poolXmlData[MAX_FILE]; - char *poolXmlPtr = &(poolXmlData[0]); - char inXmlData[MAX_FILE]; - char *inXmlPtr = &(inXmlData[0]); - char outXmlData[MAX_FILE]; - char *outXmlPtr = &(outXmlData[0]); +static int +testCompareXMLToXMLFiles(const char *poolxml, const char *inxml, + const char *outxml) +{ + char *poolXmlData = NULL; + char *inXmlData = NULL; + char *outXmlData = NULL; char *actual = NULL; int ret = -1; virStoragePoolDefPtr pool = NULL; virStorageVolDefPtr dev = NULL; - if (virtTestLoadFile(poolxml, &poolXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(poolxml, &poolXmlData) < 0) goto fail; - if (virtTestLoadFile(inxml, &inXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(inxml, &inXmlData) < 0) goto fail; - if (virtTestLoadFile(outxml, &outXmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(outxml, &outXmlData) < 0) goto fail; if (!(pool = virStoragePoolDefParseString(poolXmlData))) @@ -54,6 +49,9 @@ static int testCompareXMLToXMLFiles(const char *poolxml, ret = 0; fail: + free(poolXmlData); + free(inXmlData); + free(outXmlData); free(actual); virStoragePoolDefFree(pool); virStorageVolDefFree(dev); @@ -65,19 +63,32 @@ struct testInfo { const char *name; }; -static int testCompareXMLToXMLHelper(const void *data) { - char poolxml[PATH_MAX]; - char inxml[PATH_MAX]; - char outxml[PATH_MAX]; +static int +testCompareXMLToXMLHelper(const void *data) +{ + int result = -1; const struct testInfo *info = data; + char *poolxml = NULL; + char *inxml = NULL; + char *outxml = NULL; + + if (virAsprintf(&poolxml, "%s/storagepoolxml2xmlin/%s.xml", + abs_srcdir, info->pool) < 0 || + virAsprintf(&inxml, "%s/storagevolxml2xmlin/%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&outxml, "%s/storagevolxml2xmlout/%s.xml", + abs_srcdir, info->name) < 0) { + goto cleanup; + } + + result = testCompareXMLToXMLFiles(poolxml, inxml, outxml); + +cleanup: + free(poolxml); + free(inxml); + free(outxml); - snprintf(poolxml, PATH_MAX, "%s/storagepoolxml2xmlin/%s.xml", - abs_srcdir, (const char*)info->pool); - snprintf(inxml, PATH_MAX, "%s/storagevolxml2xmlin/%s.xml", - abs_srcdir, (const char*)info->name); - snprintf(outxml, PATH_MAX, "%s/storagevolxml2xmlout/%s.xml", - abs_srcdir, (const char*)info->name); - return testCompareXMLToXMLFiles(poolxml, inxml, outxml); + return result; } diff --git a/tests/testutils.c b/tests/testutils.c index 58b0275..bc89690 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -173,17 +173,16 @@ virtTestRun(const char *title, int nloops, int (*body)(const void *data), const return ret; } -/* Read FILE into buffer BUF of length BUFLEN. - Upon any failure, or if FILE appears to contain more than BUFLEN bytes, - diagnose it and return -1, but don't bother trying to preserve errno. - Otherwise, return the number of bytes copied into BUF. */ -int virtTestLoadFile(const char *file, - char **buf, - int buflen) { +/* Allocate BUF to the size of FILE. Read FILE into buffer BUF. + Upon any failure, diagnose it and return -1, but don't bother trying + to preserve errno. Otherwise, return the number of bytes copied into BUF. */ +int +virtTestLoadFile(const char *file, char **buf) +{ FILE *fp = fopen(file, "r"); struct stat st; - char *tmp = *buf; - int len, tmplen = buflen; + char *tmp; + int len, tmplen, buflen; if (!fp) { fprintf (stderr, "%s: failed to open: %s\n", file, strerror(errno)); @@ -196,17 +195,23 @@ int virtTestLoadFile(const char *file, return -1; } - if (st.st_size > (buflen-1)) { - fprintf (stderr, "%s: larger than buffer (> %d)\n", file, buflen-1); + tmplen = buflen = st.st_size + 1; + + if (VIR_ALLOC_N(*buf, buflen) < 0) { + fprintf (stderr, "%s: larger than available memory (> %d)\n", file, buflen); VIR_FORCE_FCLOSE(fp); return -1; } + tmp = *buf; (*buf)[0] = '\0'; if (st.st_size) { /* read the file line by line */ while (fgets(tmp, tmplen, fp) != NULL) { len = strlen(tmp); + /* stop on an empty line */ + if (len == 0) + break; /* remove trailing backslash-newline pair */ if (len >= 2 && tmp[len-2] == '\\' && tmp[len-1] == '\n') { len -= 2; @@ -219,6 +224,7 @@ int virtTestLoadFile(const char *file, if (ferror(fp)) { fprintf (stderr, "%s: read failed: %s\n", file, strerror(errno)); VIR_FORCE_FCLOSE(fp); + free(*buf); return -1; } } @@ -268,10 +274,11 @@ void virtTestCaptureProgramExecChild(const char *const argv[], VIR_FORCE_CLOSE(stdinfd); } -int virtTestCaptureProgramOutput(const char *const argv[], - char **buf, - int buflen) { +int +virtTestCaptureProgramOutput(const char *const argv[], char **buf, int maxlen) +{ int pipefd[2]; + int len; if (pipe(pipefd) < 0) return -1; @@ -289,34 +296,20 @@ int virtTestCaptureProgramOutput(const char *const argv[], return -1; default: - { - int got = 0; - int ret = -1; - int want = buflen-1; - - VIR_FORCE_CLOSE(pipefd[1]); - - while (want) { - if ((ret = read(pipefd[0], (*buf)+got, want)) <= 0) - break; - got += ret; - want -= ret; - } - VIR_FORCE_CLOSE(pipefd[0]); - - if (!ret) - (*buf)[got] = '\0'; - - waitpid(pid, NULL, 0); + VIR_FORCE_CLOSE(pipefd[1]); + len = virFileReadLimFD(pipefd[0], maxlen, buf); + VIR_FORCE_CLOSE(pipefd[0]); + waitpid(pid, NULL, 0); - return ret; - } + return len; } } #else /* !WIN32 */ -int virtTestCaptureProgramOutput(const char *const argv[] ATTRIBUTE_UNUSED, - char **buf ATTRIBUTE_UNUSED, - int buflen ATTRIBUTE_UNUSED) { +int +virtTestCaptureProgramOutput(const char *const argv[] ATTRIBUTE_UNUSED, + char **buf ATTRIBUTE_UNUSED, + int maxlen ATTRIBUTE_UNUSED) +{ return -1; } #endif /* !WIN32 */ diff --git a/tests/testutils.h b/tests/testutils.h index 0ea70ee..e8f4153 100644 --- a/tests/testutils.h +++ b/tests/testutils.h @@ -27,12 +27,8 @@ int virtTestRun(const char *title, int nloops, int (*body)(const void *data), const void *data); -int virtTestLoadFile(const char *name, - char **buf, - int buflen); -int virtTestCaptureProgramOutput(const char *const argv[], - char **buf, - int buflen); +int virtTestLoadFile(const char *file, char **buf); +int virtTestCaptureProgramOutput(const char *const argv[], char **buf, int maxlen); int virtTestClearLineRegex(const char *pattern, char *string); diff --git a/tests/virshtest.c b/tests/virshtest.c index 465d5ea..0932efd 100644 --- a/tests/virshtest.c +++ b/tests/virshtest.c @@ -6,10 +6,9 @@ #include "internal.h" #include "xml.h" +#include "util.h" #include "testutils.h" -#define MAX_FILE 4096 - #define DOM_UUID "ef861801-45b9-11cb-88e3-afbfe5370493" static const char *dominfo_fc4 = "\ @@ -45,41 +44,31 @@ static int testFilterLine(char *buffer, return 0; } -static int testCompareOutputLit(const char *expectData, - const char *filter, const char *const argv[]) { - char actualData[MAX_FILE]; - char *actualPtr = &(actualData[0]); +static int +testCompareOutputLit(const char *expectData, + const char *filter, const char *const argv[]) +{ + int result = -1; + char *actualData = NULL; - if (virtTestCaptureProgramOutput(argv, &actualPtr, MAX_FILE) < 0) - return -1; + if (virtTestCaptureProgramOutput(argv, &actualData, 4096) < 0) + goto cleanup; - if (filter) - if (testFilterLine(actualData, filter) < 0) - return -1; + if (filter && testFilterLine(actualData, filter) < 0) + goto cleanup; - if (STRNEQ(expectData, actualData)) { - virtTestDifference(stderr, expectData, actualData); - return -1; - } + if (STRNEQ(expectData, actualData)) { + virtTestDifference(stderr, expectData, actualData); + goto cleanup; + } - return 0; -} - -#if unused -static int testCompareOutput(const char *expect_rel, const char *filter, - const char *const argv[]) { - char expectData[MAX_FILE]; - char *expectPtr = &(expectData[0]); - char expect[PATH_MAX]; + result = 0; - snprintf(expect, sizeof expect - 1, "%s/%s", abs_srcdir, expect_rel); +cleanup: + free(actualData); - if (virtTestLoadFile(expect, &expectPtr, MAX_FILE) < 0) - return -1; - - return testCompareOutputLit(expectData, filter, argv); + return result; } -#endif #define VIRSH_DEFAULT "../tools/virsh", \ "--connect", \ @@ -233,16 +222,14 @@ static int mymain(void) { int ret = 0; - char buffer[PATH_MAX]; #ifdef WIN32 exit (EXIT_AM_SKIP); #endif - snprintf(buffer, PATH_MAX-1, - "test://%s/../examples/xml/test/testnode.xml", abs_srcdir); - buffer[PATH_MAX-1] = '\0'; - custom_uri = buffer; + if (virAsprintf(&custom_uri, "test://%s/../examples/xml/test/testnode.xml", + abs_srcdir) < 0) + return EXIT_FAILURE; if (virtTestRun("virsh list (default)", 1, testCompareListDefault, NULL) != 0) @@ -394,6 +381,7 @@ mymain(void) #undef DO_TEST + free(custom_uri); return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } diff --git a/tests/vmx2xmltest.c b/tests/vmx2xmltest.c index 3b7e9be..e01e8ad 100644 --- a/tests/vmx2xmltest.c +++ b/tests/vmx2xmltest.c @@ -11,11 +11,9 @@ # include "testutils.h" # include "vmx/vmx.h" -static virCapsPtr caps = NULL; +static virCapsPtr caps; static virVMXContext ctx; -# define MAX_FILE 4096 - static void testCapsInit(void) { @@ -69,19 +67,17 @@ static int testCompareFiles(const char *vmx, const char *xml) { int result = -1; - char vmxData[MAX_FILE]; - char xmlData[MAX_FILE]; + char *vmxData = NULL; + char *xmlData = NULL; char *formatted = NULL; - char *vmxPtr = &(vmxData[0]); - char *xmlPtr = &(xmlData[0]); virDomainDefPtr def = NULL; virErrorPtr err = NULL; - if (virtTestLoadFile(vmx, &vmxPtr, MAX_FILE) < 0) { + if (virtTestLoadFile(vmx, &vmxData) < 0) { goto failure; } - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) { + if (virtTestLoadFile(xml, &xmlData) < 0) { goto failure; } @@ -109,6 +105,8 @@ testCompareFiles(const char *vmx, const char *xml) result = 0; failure: + VIR_FREE(vmxData); + VIR_FREE(xmlData); VIR_FREE(formatted); virDomainDefFree(def); @@ -123,16 +121,25 @@ struct testInfo { static int testCompareHelper(const void *data) { + int result = -1; const struct testInfo *info = data; - char vmx[PATH_MAX]; - char xml[PATH_MAX]; + char *vmx = NULL; + char *xml = NULL; + + if (virAsprintf(&vmx, "%s/vmx2xmldata/vmx2xml-%s.vmx", abs_srcdir, + info->input) < 0 || + virAsprintf(&xml, "%s/vmx2xmldata/vmx2xml-%s.xml", abs_srcdir, + info->output) < 0) { + goto cleanup; + } - snprintf(vmx, PATH_MAX, "%s/vmx2xmldata/vmx2xml-%s.vmx", abs_srcdir, - info->input); - snprintf(xml, PATH_MAX, "%s/vmx2xmldata/vmx2xml-%s.xml", abs_srcdir, - info->output); + result = testCompareFiles(vmx, xml); - return testCompareFiles(vmx, xml); + cleanup: + VIR_FREE(vmx); + VIR_FREE(xml); + + return result; } static char * diff --git a/tests/xencapstest.c b/tests/xencapstest.c index 36946cf..3f96cf2 100644 --- a/tests/xencapstest.c +++ b/tests/xencapstest.c @@ -11,32 +11,27 @@ #include "xen/xen_hypervisor.h" #include "files.h" -#define MAX_FILE 4096 - -static int testCompareFiles(const char *hostmachine, - const char *xml_rel, - const char *cpuinfo_rel, - const char *capabilities_rel) { - char xmlData[MAX_FILE]; - char *expectxml = &(xmlData[0]); +static int +testCompareFiles(const char *hostmachine, const char *xml_rel, + const char *cpuinfo_rel, const char *capabilities_rel) +{ + char *expectxml = NULL; char *actualxml = NULL; FILE *fp1 = NULL, *fp2 = NULL; virCapsPtr caps = NULL; int ret = -1; - char xml[PATH_MAX]; - char cpuinfo[PATH_MAX]; - char capabilities[PATH_MAX]; + char *xml = NULL; + char *cpuinfo = NULL; + char *capabilities = NULL; - snprintf(xml, sizeof xml - 1, "%s/%s", - abs_srcdir, xml_rel); - snprintf(cpuinfo, sizeof cpuinfo - 1, "%s/%s", - abs_srcdir, cpuinfo_rel); - snprintf(capabilities, sizeof capabilities - 1, "%s/%s", - abs_srcdir, capabilities_rel); + if (virAsprintf(&xml, "%s/%s", abs_srcdir, xml_rel) < 0 || + virAsprintf(&cpuinfo, "%s/%s", abs_srcdir, cpuinfo_rel) < 0 || + virAsprintf(&capabilities, "%s/%s", abs_srcdir, capabilities_rel) < 0) + goto fail; - if (virtTestLoadFile(xml, &expectxml, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &expectxml) < 0) goto fail; if (!(fp1 = fopen(cpuinfo, "r"))) @@ -59,8 +54,11 @@ static int testCompareFiles(const char *hostmachine, ret = 0; fail: - + free(expectxml); free(actualxml); + free(xml); + free(cpuinfo); + free(capabilities); VIR_FORCE_FCLOSE(fp1); VIR_FORCE_FCLOSE(fp2); diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c index 62d3488..02a8900 100644 --- a/tests/xmconfigtest.c +++ b/tests/xmconfigtest.c @@ -38,30 +38,29 @@ static virCapsPtr caps; -#define MAX_FILE 4096 - -static int testCompareParseXML(const char *xmcfg, const char *xml, - int xendConfigVersion) { - char xmlData[MAX_FILE]; - char xmcfgData[MAX_FILE]; - char gotxmcfgData[MAX_FILE]; - char *xmlPtr = &(xmlData[0]); - char *xmcfgPtr = &(xmcfgData[0]); - char *gotxmcfgPtr = &(gotxmcfgData[0]); +static int +testCompareParseXML(const char *xmcfg, const char *xml, int xendConfigVersion) +{ + char *xmlData = NULL; + char *xmcfgData = NULL; + char *gotxmcfgData = NULL; virConfPtr conf = NULL; int ret = -1; virConnectPtr conn; - int wrote = MAX_FILE; + int wrote = 4096; struct _xenUnifiedPrivate priv; virDomainDefPtr def = NULL; + if (VIR_ALLOC_N(gotxmcfgData, wrote) < 0) + goto fail; + conn = virGetConnect(); if (!conn) goto fail; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; - if (virtTestLoadFile(xmcfg, &xmcfgPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xmcfg, &xmcfgData) < 0) goto fail; /* Many puppies died to bring you this code. */ @@ -69,16 +68,16 @@ static int testCompareParseXML(const char *xmcfg, const char *xml, priv.caps = caps; conn->privateData = &priv; - if (!(def = virDomainDefParseString(caps, xmlPtr, + if (!(def = virDomainDefParseString(caps, xmlData, VIR_DOMAIN_XML_INACTIVE))) goto fail; if (!(conf = xenFormatXM(conn, def, xendConfigVersion))) goto fail; - if (virConfWriteMem(gotxmcfgPtr, &wrote, conf) < 0) + if (virConfWriteMem(gotxmcfgData, &wrote, conf) < 0) goto fail; - gotxmcfgPtr[wrote] = '\0'; + gotxmcfgData[wrote] = '\0'; if (STRNEQ(xmcfgData, gotxmcfgData)) { virtTestDifference(stderr, xmcfgData, gotxmcfgData); @@ -88,6 +87,9 @@ static int testCompareParseXML(const char *xmcfg, const char *xml, ret = 0; fail: + free(xmlData); + free(xmcfgData); + free(gotxmcfgData); if (conf) virConfFree(conf); virDomainDefFree(def); @@ -96,12 +98,11 @@ static int testCompareParseXML(const char *xmcfg, const char *xml, return ret; } -static int testCompareFormatXML(const char *xmcfg, const char *xml, - int xendConfigVersion) { - char xmlData[MAX_FILE]; - char xmcfgData[MAX_FILE]; - char *xmlPtr = &(xmlData[0]); - char *xmcfgPtr = &(xmcfgData[0]); +static int +testCompareFormatXML(const char *xmcfg, const char *xml, int xendConfigVersion) +{ + char *xmlData = NULL; + char *xmcfgData = NULL; char *gotxml = NULL; virConfPtr conf = NULL; int ret = -1; @@ -112,10 +113,10 @@ static int testCompareFormatXML(const char *xmcfg, const char *xml, conn = virGetConnect(); if (!conn) goto fail; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; - if (virtTestLoadFile(xmcfg, &xmcfgPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xmcfg, &xmcfgData) < 0) goto fail; /* Many puppies died to bring you this code. */ @@ -123,7 +124,7 @@ static int testCompareFormatXML(const char *xmcfg, const char *xml, priv.caps = caps; conn->privateData = &priv; - if (!(conf = virConfReadMem(xmcfgPtr, strlen(xmcfgPtr), 0))) + if (!(conf = virConfReadMem(xmcfgData, strlen(xmcfgData), 0))) goto fail; if (!(def = xenParseXM(conf, priv.xendConfigVersion, priv.caps))) @@ -142,6 +143,8 @@ static int testCompareFormatXML(const char *xmcfg, const char *xml, fail: if (conf) virConfFree(conf); + VIR_FREE(xmlData); + VIR_FREE(xmcfgData); VIR_FREE(gotxml); virDomainDefFree(def); virUnrefConnect(conn); @@ -156,18 +159,30 @@ struct testInfo { int mode; }; -static int testCompareHelper(const void *data) { +static int +testCompareHelper(const void *data) +{ + int result = -1; const struct testInfo *info = data; - char xml[PATH_MAX]; - char cfg[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/xmconfigdata/test-%s.xml", - abs_srcdir, info->name); - snprintf(cfg, PATH_MAX, "%s/xmconfigdata/test-%s.cfg", - abs_srcdir, info->name); + char *xml = NULL; + char *cfg = NULL; + + if (virAsprintf(&xml, "%s/xmconfigdata/test-%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&cfg, "%s/xmconfigdata/test-%s.cfg", + abs_srcdir, info->name) < 0) + goto cleanup; + if (info->mode == 0) - return testCompareParseXML(cfg, xml, info->version); + result = testCompareParseXML(cfg, xml, info->version); else - return testCompareFormatXML(cfg, xml, info->version); + result = testCompareFormatXML(cfg, xml, info->version); + +cleanup: + free(xml); + free(cfg); + + return result; } diff --git a/tests/xml2sexprtest.c b/tests/xml2sexprtest.c index b258c3d..dab8c84 100644 --- a/tests/xml2sexprtest.c +++ b/tests/xml2sexprtest.c @@ -16,22 +16,19 @@ static virCapsPtr caps; -#define MAX_FILE 4096 - -static int testCompareFiles(const char *xml, const char *sexpr, - int xendConfigVersion) { - char xmlData[MAX_FILE]; - char sexprData[MAX_FILE]; +static int +testCompareFiles(const char *xml, const char *sexpr, int xendConfigVersion) +{ + char *xmlData = NULL; + char *sexprData = NULL; char *gotsexpr = NULL; - char *xmlPtr = &(xmlData[0]); - char *sexprPtr = &(sexprData[0]); int ret = -1; virDomainDefPtr def = NULL; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) + if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; - if (virtTestLoadFile(sexpr, &sexprPtr, MAX_FILE) < 0) + if (virtTestLoadFile(sexpr, &sexprData) < 0) goto fail; if (!(def = virDomainDefParseString(caps, xmlData, @@ -49,8 +46,10 @@ static int testCompareFiles(const char *xml, const char *sexpr, ret = 0; fail: - virDomainDefFree(def); + free(xmlData); + free(sexprData); free(gotsexpr); + virDomainDefFree(def); return ret; } @@ -62,17 +61,29 @@ struct testInfo { int version; }; -static int testCompareHelper(const void *data) { +static int +testCompareHelper(const void *data) +{ + int result = -1; const struct testInfo *info = data; - char xml[PATH_MAX]; - char args[PATH_MAX]; - snprintf(xml, PATH_MAX, "%s/xml2sexprdata/xml2sexpr-%s.xml", - abs_srcdir, info->input); - snprintf(args, PATH_MAX, "%s/xml2sexprdata/xml2sexpr-%s.sexpr", - abs_srcdir, info->output); - return testCompareFiles(xml, args, info->version); -} + char *xml = NULL; + char *args = NULL; + + if (virAsprintf(&xml, "%s/xml2sexprdata/xml2sexpr-%s.xml", + abs_srcdir, info->input) < 0 || + virAsprintf(&args, "%s/xml2sexprdata/xml2sexpr-%s.sexpr", + abs_srcdir, info->output) < 0) { + goto cleanup; + } + result = testCompareFiles(xml, args, info->version); + +cleanup: + free(xml); + free(args); + + return result; +} static int mymain(void) diff --git a/tests/xml2vmxtest.c b/tests/xml2vmxtest.c index 6a4b795..efd4d74 100644 --- a/tests/xml2vmxtest.c +++ b/tests/xml2vmxtest.c @@ -11,11 +11,9 @@ # include "testutils.h" # include "vmx/vmx.h" -static virCapsPtr caps = NULL; +static virCapsPtr caps; static virVMXContext ctx; -# define MAX_FILE 4096 - static void testCapsInit(void) { @@ -69,18 +67,16 @@ static int testCompareFiles(const char *xml, const char *vmx, int virtualHW_version) { int result = -1; - char xmlData[MAX_FILE]; - char vmxData[MAX_FILE]; + char *xmlData = NULL; + char *vmxData = NULL; char *formatted = NULL; - char *xmlPtr = &(xmlData[0]); - char *vmxPtr = &(vmxData[0]); virDomainDefPtr def = NULL; - if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0) { + if (virtTestLoadFile(xml, &xmlData) < 0) { goto failure; } - if (virtTestLoadFile(vmx, &vmxPtr, MAX_FILE) < 0) { + if (virtTestLoadFile(vmx, &vmxData) < 0) { goto failure; } @@ -104,6 +100,8 @@ testCompareFiles(const char *xml, const char *vmx, int virtualHW_version) result = 0; failure: + VIR_FREE(xmlData); + VIR_FREE(vmxData); VIR_FREE(formatted); virDomainDefFree(def); @@ -119,16 +117,25 @@ struct testInfo { static int testCompareHelper(const void *data) { + int result = -1; const struct testInfo *info = data; - char xml[PATH_MAX]; - char vmx[PATH_MAX]; + char *xml = NULL; + char *vmx = NULL; + + if (virAsprintf(&xml, "%s/xml2vmxdata/xml2vmx-%s.xml", abs_srcdir, + info->input) < 0 || + virAsprintf(&vmx, "%s/xml2vmxdata/xml2vmx-%s.vmx", abs_srcdir, + info->output) < 0) { + goto cleanup; + } + + result = testCompareFiles(xml, vmx, info->virtualHW_version); - snprintf(xml, PATH_MAX, "%s/xml2vmxdata/xml2vmx-%s.xml", abs_srcdir, - info->input); - snprintf(vmx, PATH_MAX, "%s/xml2vmxdata/xml2vmx-%s.vmx", abs_srcdir, - info->output); + cleanup: + VIR_FREE(xml); + VIR_FREE(vmx); - return testCompareFiles(xml, vmx, info->virtualHW_version); + return result; } static int -- 1.7.0.4 From matthias.bolte at googlemail.com Sat Apr 30 11:11:52 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 30 Apr 2011 13:11:52 +0200 Subject: [libvirt] [PATCH] Fix memory leak in __virExec Message-ID: <20110430111152.GA2644@sbox> Commit e0d014f2379dd made binary potentially allocated on the heap. It was freed in the parent in the error path, but not in the success path that doesn't goto the cleanup label. Found by 'make -C tests valgrind'. --- src/util/util.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/src/util/util.c b/src/util/util.c index c337aa9..37472bb 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -568,6 +568,10 @@ __virExec(const char *const*argv, } *retpid = pid; + + if (binary != argv[0]) + VIR_FREE(binary); + return 0; } -- 1.7.0.4 From matthias.bolte at googlemail.com Sat Apr 30 11:12:13 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 30 Apr 2011 13:12:13 +0200 Subject: [libvirt] [PATCH] qemu: Fix qemuDomainModifyDeviceFlags leaking the caps bitmap Message-ID: <20110430111213.GA2708@sbox> --- src/qemu/qemu_driver.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b277cc5..a19c4a7 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4316,6 +4316,7 @@ endjob: vm = NULL; cleanup: + qemuCapsFree(qemuCaps); virDomainDefFree(vmdef); virDomainDeviceDefFree(dev); if (vm) -- 1.7.0.4 From matthias.bolte at googlemail.com Sat Apr 30 11:12:58 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 30 Apr 2011 13:12:58 +0200 Subject: [libvirt] [PATCH] nwfilter: Fix memory leak in the ebtables subdriver Message-ID: <20110430111258.GA2770@sbox> Call shutdown functions for all subcompontents in nwfilterDriverShutdown. Make sure that this shutdown functions can safely be called multiple times and independent from the actual subcompontents state. --- src/conf/nwfilter_conf.c | 8 ++++++++ src/nwfilter/nwfilter_driver.c | 2 ++ src/nwfilter/nwfilter_learnipaddr.c | 5 ++++- 3 files changed, 14 insertions(+), 1 deletions(-) diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 09dc32b..615c0f1 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -125,6 +125,7 @@ struct int_map { * only one filter update allowed */ static virMutex updateMutex; +static bool initialized = false; void virNWFilterLockFilterUpdates(void) { @@ -2971,6 +2972,8 @@ int virNWFilterConfLayerInit(virHashIterator domUpdateCB) { virNWFilterDomainFWUpdateCB = domUpdateCB; + initialized = true; + if (virMutexInitRecursive(&updateMutex)) return 1; @@ -2980,7 +2983,12 @@ int virNWFilterConfLayerInit(virHashIterator domUpdateCB) void virNWFilterConfLayerShutdown(void) { + if (!initialized) + return; + virMutexDestroy(&updateMutex); + + initialized = false; } diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index a579306..8af3f8a 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -199,6 +199,8 @@ nwfilterDriverShutdown(void) { if (!driverState) return -1; + virNWFilterConfLayerShutdown(); + virNWFilterTechDriversShutdown(); virNWFilterLearnShutdown(); nwfilterDriverLock(driverState); diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 9ee439a..96d2a55 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -873,7 +873,10 @@ virNWFilterLearnThreadsTerminate(bool allowNewThreads) { * Shutdown of this layer */ void -virNWFilterLearnShutdown(void) { +virNWFilterLearnShutdown(void) +{ + if (!pendingLearnReq) + return; virNWFilterLearnThreadsTerminate(false); -- 1.7.0.4 From matthias.bolte at googlemail.com Sat Apr 30 11:13:24 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 30 Apr 2011 13:13:24 +0200 Subject: [libvirt] [PATCH] tests: Update valgrind suppressions file Message-ID: <20110430111324.GA2805@sbox> --- tests/.valgrind.supp | 58 +++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 51 insertions(+), 7 deletions(-) diff --git a/tests/.valgrind.supp b/tests/.valgrind.supp index 4af10b1..68cfa0c 100644 --- a/tests/.valgrind.supp +++ b/tests/.valgrind.supp @@ -258,14 +258,58 @@ Memcheck:Param capget(data) fun:capget + fun:* fun:capng_clear + fun:virClearCapabilities fun:__virExec fun:virExecWithHook - fun:virExec - fun:qemudProbeMachineTypes - fun:qemudCapsInitGuest - fun:qemudCapsInit - fun:qemudStartup - fun:virStateInitialize - fun:main +} +{ + libnlMemoryLeak1 + Memcheck:Leak + fun:malloc + fun:strdup + obj:/usr/lib/libnl.so.1.1 +} +{ + libnlMemoryLeak2 + Memcheck:Leak + fun:calloc + obj:/usr/lib/libnl.so.1.1 +} +{ + libselinuxMemoryLeak1 + Memcheck:Leak + fun:malloc + fun:getdelim + obj:/lib/libselinux.so.1 +} +{ + dashMemoryLeak1 + Memcheck:Leak + fun:malloc + obj:/bin/dash +} +{ + dashMemoryLeak2 + Memcheck:Leak + fun:malloc + fun:strdup + obj:/bin/dash +} +{ + vboxMemoryLeak1 + Memcheck:Leak + ... + fun:VBoxNsxpNS_InitXPCOM2 +} +{ + libnetcfMemoryLeak1 + fun:malloc + fun:xmlStrndup + fun:xmlHashUpdateEntry3 + fun:* + fun:xsltRegisterAllExtras + fun:drv_init + fun:interfaceOpenInterface } -- 1.7.0.4 From eblake at redhat.com Sat Apr 30 13:39:01 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 30 Apr 2011 07:39:01 -0600 Subject: [libvirt] [PATCH] Fix memory leak in __virExec In-Reply-To: <20110430111152.GA2644@sbox> References: <20110430111152.GA2644@sbox> Message-ID: <4DBC10F5.4070203@redhat.com> On 04/30/2011 05:11 AM, Matthias Bolte wrote: > Commit e0d014f2379dd made binary potentially allocated on the heap. > It was freed in the parent in the error path, but not in the success path > that doesn't goto the cleanup label. > > Found by 'make -C tests valgrind'. > --- > src/util/util.c | 4 ++++ > 1 files changed, 4 insertions(+), 0 deletions(-) > > diff --git a/src/util/util.c b/src/util/util.c > index c337aa9..37472bb 100644 > --- a/src/util/util.c > +++ b/src/util/util.c > @@ -568,6 +568,10 @@ __virExec(const char *const*argv, > } > > *retpid = pid; > + > + if (binary != argv[0]) > + VIR_FREE(binary); ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Sat Apr 30 13:40:00 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 30 Apr 2011 07:40:00 -0600 Subject: [libvirt] [PATCH] qemu: Fix qemuDomainModifyDeviceFlags leaking the caps bitmap In-Reply-To: <20110430111213.GA2708@sbox> References: <20110430111213.GA2708@sbox> Message-ID: <4DBC1130.6090607@redhat.com> On 04/30/2011 05:12 AM, Matthias Bolte wrote: > --- > src/qemu/qemu_driver.c | 1 + > 1 files changed, 1 insertions(+), 0 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index b277cc5..a19c4a7 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -4316,6 +4316,7 @@ endjob: > vm = NULL; > > cleanup: > + qemuCapsFree(qemuCaps); > virDomainDefFree(vmdef); > virDomainDeviceDefFree(dev); ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Sat Apr 30 13:42:03 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 30 Apr 2011 07:42:03 -0600 Subject: [libvirt] [PATCH] nwfilter: Fix memory leak in the ebtables subdriver In-Reply-To: <20110430111258.GA2770@sbox> References: <20110430111258.GA2770@sbox> Message-ID: <4DBC11AB.8040604@redhat.com> On 04/30/2011 05:12 AM, Matthias Bolte wrote: > Call shutdown functions for all subcompontents in nwfilterDriverShutdown. s/subcompontents/subcomponents/ (twice) > +++ b/src/conf/nwfilter_conf.c > @@ -125,6 +125,7 @@ struct int_map { > * only one filter update allowed > */ > static virMutex updateMutex; > +static bool initialized = false; You could omit '= false' and still get the same results, since static storage is guaranteed to be zero-initialized, but that's just style and does not have to be changed. ACK. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Sat Apr 30 13:44:51 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 30 Apr 2011 07:44:51 -0600 Subject: [libvirt] [PATCH] virsh: fix regression in log to file In-Reply-To: <4DBBEACE.1020503@in.ibm.com> References: <4DBBEACE.1020503@in.ibm.com> Message-ID: <4DBC1253.4050801@redhat.com> On 04/30/2011 04:56 AM, Supriya Kannery wrote: > Commit 36deff04 introduced a regression due to which virsh is not able > to log to a file - msg_buf was changed from an array to a pointer > without corresponding change to usage of "sizeof()". > > Fix regression in virsh logging Good catch. However, I'd prefer if we instead rewrote this function to use virBuffer instead of snprintf. Much less error-prone to maintain. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From matthias.bolte at googlemail.com Sat Apr 30 15:49:03 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 30 Apr 2011 17:49:03 +0200 Subject: [libvirt] [PATCH] Fix memory leak in __virExec In-Reply-To: <4DBC10F5.4070203@redhat.com> References: <20110430111152.GA2644@sbox> <4DBC10F5.4070203@redhat.com> Message-ID: 2011/4/30 Eric Blake : > On 04/30/2011 05:11 AM, Matthias Bolte wrote: >> Commit e0d014f2379dd made binary potentially allocated on the heap. >> It was freed in the parent in the error path, but not in the success path >> that doesn't goto the cleanup label. >> >> Found by 'make -C tests valgrind'. >> --- >> ?src/util/util.c | ? ?4 ++++ >> ?1 files changed, 4 insertions(+), 0 deletions(-) >> >> diff --git a/src/util/util.c b/src/util/util.c >> index c337aa9..37472bb 100644 >> --- a/src/util/util.c >> +++ b/src/util/util.c >> @@ -568,6 +568,10 @@ __virExec(const char *const*argv, >> ? ? ? ? ?} >> >> ? ? ? ? ?*retpid = pid; >> + >> + ? ? ? ?if (binary != argv[0]) >> + ? ? ? ? ? ?VIR_FREE(binary); > > ACK. > Thanks, pushed. Matthias From matthias.bolte at googlemail.com Sat Apr 30 15:49:24 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 30 Apr 2011 17:49:24 +0200 Subject: [libvirt] [PATCH] qemu: Fix qemuDomainModifyDeviceFlags leaking the caps bitmap In-Reply-To: <4DBC1130.6090607@redhat.com> References: <20110430111213.GA2708@sbox> <4DBC1130.6090607@redhat.com> Message-ID: 2011/4/30 Eric Blake : > On 04/30/2011 05:12 AM, Matthias Bolte wrote: >> --- >> ?src/qemu/qemu_driver.c | ? ?1 + >> ?1 files changed, 1 insertions(+), 0 deletions(-) >> >> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c >> index b277cc5..a19c4a7 100644 >> --- a/src/qemu/qemu_driver.c >> +++ b/src/qemu/qemu_driver.c >> @@ -4316,6 +4316,7 @@ endjob: >> ? ? ? ? ?vm = NULL; >> >> ?cleanup: >> + ? ?qemuCapsFree(qemuCaps); >> ? ? ?virDomainDefFree(vmdef); >> ? ? ?virDomainDeviceDefFree(dev); > > ACK. > Thanks, pushed. Matthias From matthias.bolte at googlemail.com Sat Apr 30 15:50:10 2011 From: matthias.bolte at googlemail.com (Matthias Bolte) Date: Sat, 30 Apr 2011 17:50:10 +0200 Subject: [libvirt] [PATCH] nwfilter: Fix memory leak in the ebtables subdriver In-Reply-To: <4DBC11AB.8040604@redhat.com> References: <20110430111258.GA2770@sbox> <4DBC11AB.8040604@redhat.com> Message-ID: 2011/4/30 Eric Blake : > On 04/30/2011 05:12 AM, Matthias Bolte wrote: >> Call shutdown functions for all subcompontents in nwfilterDriverShutdown. > > s/subcompontents/subcomponents/ (twice) Fixed. >> +++ b/src/conf/nwfilter_conf.c >> @@ -125,6 +125,7 @@ struct int_map { >> ? * only one filter update allowed >> ? */ >> ?static virMutex updateMutex; >> +static bool initialized = false; > > You could omit '= false' and still get the same results, since static > storage is guaranteed to be zero-initialized, but that's just style and > does not have to be changed. > > ACK. > I pushed it unchanged, thanks. Matthias From eblake at redhat.com Sat Apr 30 16:18:33 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 30 Apr 2011 10:18:33 -0600 Subject: [libvirt] [PATCH] virsh: fix regression in log to file In-Reply-To: <4DBC1253.4050801@redhat.com> References: <4DBBEACE.1020503@in.ibm.com> <4DBC1253.4050801@redhat.com> Message-ID: <4DBC3659.6000703@redhat.com> On 04/30/2011 07:44 AM, Eric Blake wrote: > On 04/30/2011 04:56 AM, Supriya Kannery wrote: >> Commit 36deff04 introduced a regression due to which virsh is not able >> to log to a file - msg_buf was changed from an array to a pointer >> without corresponding change to usage of "sizeof()". >> >> Fix regression in virsh logging > > Good catch. However, I'd prefer if we instead rewrote this function to > use virBuffer instead of snprintf. Much less error-prone to maintain. On second thought, after some IRC discussions with others, I'm planning on: 1. push your patch as-is for 0.9.1 (it's minimal, which is good since we're post-freeze) 2. after 0.9.1, revert your patch, and replace it with: 3. global rename of virBufferVSprintf -> virBufferAsprintf (to match the existing virAsprintf name) 4. add virBufferVasprintf (to match the existing virVasprintf name) 5. fix virsh to use virBuffer, including the new virBufferVasprintf -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Sat Apr 30 16:32:51 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 30 Apr 2011 10:32:51 -0600 Subject: [libvirt] [PATCH] virsh: fix regression in log to file In-Reply-To: <4DBC3659.6000703@redhat.com> References: <4DBBEACE.1020503@in.ibm.com> <4DBC1253.4050801@redhat.com> <4DBC3659.6000703@redhat.com> Message-ID: <4DBC39B3.2060306@redhat.com> On 04/30/2011 10:18 AM, Eric Blake wrote: > On second thought, after some IRC discussions with others, I'm planning on: > > 1. push your patch as-is for 0.9.1 (it's minimal, which is good since > we're post-freeze) Now complete. I've pushed your patch; thanks again for catching this. > 2. after 0.9.1, revert your patch, and replace it with: Or maybe squash step 2 into step 5. > 3. global rename of virBufferVSprintf -> virBufferAsprintf (to match the > existing virAsprintf name) > 4. add virBufferVasprintf (to match the existing virVasprintf name) > 5. fix virsh to use virBuffer, including the new virBufferVasprintf Series coming up later, but it will be on hold until after the release. -- Eric Blake eblake at redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 619 bytes Desc: OpenPGP digital signature URL: From eblake at redhat.com Sat Apr 30 17:09:26 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 30 Apr 2011 11:09:26 -0600 Subject: [libvirt] [PATCH 2/3] buf: add virBufferVasprintf In-Reply-To: <1304183367-3491-1-git-send-email-eblake@redhat.com> References: <4DBC1253.4050801@redhat.com> <1304183367-3491-1-git-send-email-eblake@redhat.com> Message-ID: <1304183367-3491-3-git-send-email-eblake@redhat.com> Match the fact that we have virAsprintf and virVasprintf. * src/util/buf.h (virBufferVasprintf): New prototype. * src/util/buf.c (virBufferAsprintf): Move guts... (virBufferVasprintf): ...to new function. * src/libvirt_private.syms (buf.h): Export it. * bootstrap.conf (gnulib_modules): Add stdarg, for va_copy. --- bootstrap.conf | 1 + src/libvirt_private.syms | 3 ++- src/util/buf.c | 39 ++++++++++++++++++++++++++------------- src/util/buf.h | 6 +++++- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/bootstrap.conf b/bootstrap.conf index fde00da..09e8218 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -70,6 +70,7 @@ sigaction sigpipe snprintf socket +stdarg stpcpy strchrnul strndup diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fc8edb4..00f7e08 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -22,6 +22,7 @@ virBitmapString; # buf.h virBufferAdd; virBufferAddChar; +virBufferAsprintf; virBufferContentAndReset; virBufferError; virBufferEscapeSexpr; @@ -30,7 +31,7 @@ virBufferFreeAndReset; virBufferStrcat; virBufferURIEncodeString; virBufferUse; -virBufferAsprintf; +virBufferVasprintf; # caps.h diff --git a/src/util/buf.c b/src/util/buf.c index 7814e8e..750e277 100644 --- a/src/util/buf.c +++ b/src/util/buf.c @@ -1,7 +1,7 @@ /* * buf.c: buffers for libvirt * - * Copyright (C) 2005-2008, 2010 Red Hat, Inc. + * Copyright (C) 2005-2008, 2010-2011 Red Hat, Inc. * * See COPYING.LIB for the License of this software * @@ -223,8 +223,25 @@ virBufferUse(const virBufferPtr buf) void virBufferAsprintf(const virBufferPtr buf, const char *format, ...) { - int size, count, grow_size; va_list argptr; + va_start(argptr, format); + virBufferVasprintf(buf, format, argptr); + va_end(argptr); +} + +/** + * virBufferVasprintf: + * @buf: the buffer to dump + * @format: the format + * @argptr: the variable list of arguments + * + * Do a formatted print to an XML buffer. + */ +void +virBufferVasprintf(const virBufferPtr buf, const char *format, va_list argptr) +{ + int size, count, grow_size; + va_list copy; if ((format == NULL) || (buf == NULL)) return; @@ -236,38 +253,34 @@ virBufferAsprintf(const virBufferPtr buf, const char *format, ...) virBufferGrow(buf, 100) < 0) return; - va_start(argptr, format); + va_copy(copy, argptr); size = buf->size - buf->use; if ((count = vsnprintf(&buf->content[buf->use], - size, format, argptr)) < 0) { + size, format, copy)) < 0) { virBufferSetError(buf); - goto err; + va_end(copy); + return; } + va_end(copy); /* Grow buffer if necessary and retry */ if (count >= size) { buf->content[buf->use] = 0; - va_end(argptr); - va_start(argptr, format); grow_size = (count + 1 > 1000) ? count + 1 : 1000; if (virBufferGrow(buf, grow_size) < 0) { - goto err; + return; } size = buf->size - buf->use; if ((count = vsnprintf(&buf->content[buf->use], size, format, argptr)) < 0) { virBufferSetError(buf); - goto err; + return; } } buf->use += count; - -err: - va_end(argptr); - return; } /** diff --git a/src/util/buf.h b/src/util/buf.h index 00f2043..06d01ba 100644 --- a/src/util/buf.h +++ b/src/util/buf.h @@ -1,7 +1,7 @@ /* * buf.h: buffers for libvirt * - * Copyright (C) 2005-2008 Red Hat, Inc. + * Copyright (C) 2005-2008, 2011 Red Hat, Inc. * * See COPYING.LIB for the License of this software * @@ -13,6 +13,8 @@ # include "internal.h" +# include + /** * virBuffer: * @@ -42,6 +44,8 @@ void virBufferAdd(const virBufferPtr buf, const char *str, int len); void virBufferAddChar(const virBufferPtr buf, char c); void virBufferAsprintf(const virBufferPtr buf, const char *format, ...) ATTRIBUTE_FMT_PRINTF(2, 3); +void virBufferVasprintf(const virBufferPtr buf, const char *format, va_list ap) + ATTRIBUTE_FMT_PRINTF(2, 0); void virBufferStrcat(const virBufferPtr buf, ...) ATTRIBUTE_SENTINEL; void virBufferEscapeString(const virBufferPtr buf, const char *format, const char *str); -- 1.7.4.4 From eblake at redhat.com Sat Apr 30 17:09:24 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 30 Apr 2011 11:09:24 -0600 Subject: [libvirt] [PATCH 0/3] virsh: replace snprintf with virBuffer In-Reply-To: <4DBC1253.4050801@redhat.com> References: <4DBC1253.4050801@redhat.com> Message-ID: <1304183367-3491-1-git-send-email-eblake@redhat.com> This is probably too invasive for inclusion in 0.9.1. Eric Blake (3): maint: rename virBufferVSprintf to virBufferAsprintf buf: add virBufferVasprintf virsh: use new method for easier log to file ChangeLog-old | 2 +- HACKING | 2 +- bootstrap.conf | 1 + docs/api_extension/0008-support-new-xml.patch | 46 ++-- ...improve-vcpu-support-in-qemu-command-line.patch | 8 +- ...-improve-vcpu-support-in-xen-command-line.patch | 12 +- docs/hacking.html.in | 2 +- docs/news.html.in | 4 +- src/conf/capabilities.c | 48 ++-- src/conf/cpu_conf.c | 24 +- src/conf/domain_conf.c | 294 ++++++++++---------- src/conf/interface_conf.c | 60 ++-- src/conf/network_conf.c | 26 +- src/conf/node_device_conf.c | 62 ++-- src/conf/nwfilter_conf.c | 34 ++-- src/conf/nwfilter_params.c | 2 +- src/conf/secret_conf.c | 4 +- src/conf/storage_conf.c | 70 +++--- src/conf/storage_encryption_conf.c | 6 +- src/cpu/cpu_map.c | 2 +- src/esx/esx_driver.c | 4 +- src/esx/esx_vi.c | 2 +- src/esx/esx_vi_types.c | 6 +- src/libvirt_private.syms | 3 +- src/network/bridge_driver.c | 4 +- src/node_device/node_device_udev.c | 4 +- src/nwfilter/nwfilter_ebiptables_driver.c | 206 +++++++------- src/nwfilter/nwfilter_learnipaddr.c | 4 +- src/openvz/openvz_driver.c | 18 +- src/phyp/phyp_driver.c | 248 ++++++++-------- src/qemu/qemu_command.c | 256 +++++++++--------- src/qemu/qemu_domain.c | 6 +- src/qemu/qemu_monitor.c | 4 +- src/security/virt-aa-helper.c | 12 +- src/uml/uml_conf.c | 10 +- src/util/bitmap.c | 2 +- src/util/buf.c | 51 +++-- src/util/buf.h | 8 +- src/util/conf.c | 10 +- src/util/logging.c | 8 +- src/util/sexpr.c | 2 +- src/util/sysinfo.c | 12 +- src/vmx/vmx.c | 138 +++++----- src/xen/xend_internal.c | 2 +- src/xen/xm_internal.c | 2 +- src/xenapi/xenapi_utils.c | 2 +- src/xenxs/xen_sxpr.c | 60 ++-- src/xenxs/xen_xm.c | 40 ++-- tests/cputest.c | 6 +- tests/virbuftest.c | 2 +- tools/virsh.c | 120 +++++---- 51 files changed, 994 insertions(+), 967 deletions(-) -- 1.7.4.4 From eblake at redhat.com Sat Apr 30 17:09:27 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 30 Apr 2011 11:09:27 -0600 Subject: [libvirt] [PATCH 3/3] virsh: use new method for easier log to file In-Reply-To: <1304183367-3491-1-git-send-email-eblake@redhat.com> References: <4DBC1253.4050801@redhat.com> <1304183367-3491-1-git-send-email-eblake@redhat.com> Message-ID: <1304183367-3491-4-git-send-email-eblake@redhat.com> Easier to maintain, and no longer an arbitrary line length limit. * tools/virsh.c (vshOutputLogFile): Replace snprintf with virBuffer. --- > However, I'd prefer if we instead rewrote this function to > use virBuffer instead of snprintf. Much less error-prone to maintain. Like this. tools/virsh.c | 56 ++++++++++++++++++++++++++++++++------------------------ 1 files changed, 32 insertions(+), 24 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index b249829..256baec 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -12230,7 +12230,9 @@ static void vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, va_list ap) { - char *msg_buf; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *str; + size_t len; const char *lvl = ""; struct timeval stTimeval; struct tm *stTm; @@ -12238,8 +12240,6 @@ vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, if (ctl->log_fd == -1) return; - msg_buf = vshMalloc(ctl, MSG_BUFFER); - /** * create log format * @@ -12247,16 +12247,14 @@ vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, */ gettimeofday(&stTimeval, NULL); stTm = localtime(&stTimeval.tv_sec); - snprintf(msg_buf, MSG_BUFFER, - "[%d.%02d.%02d %02d:%02d:%02d ", - (1900 + stTm->tm_year), - (1 + stTm->tm_mon), - (stTm->tm_mday), - (stTm->tm_hour), - (stTm->tm_min), - (stTm->tm_sec)); - snprintf(msg_buf + strlen(msg_buf), MSG_BUFFER - strlen(msg_buf), - "%s] ", SIGN_NAME); + virBufferAsprintf(&buf, "[%d.%02d.%02d %02d:%02d:%02d %s] ", + (1900 + stTm->tm_year), + (1 + stTm->tm_mon), + stTm->tm_mday, + stTm->tm_hour, + stTm->tm_min, + stTm->tm_sec, + SIGN_NAME); switch (log_level) { case VSH_ERR_DEBUG: lvl = LVL_DEBUG; @@ -12277,21 +12275,31 @@ vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, lvl = LVL_DEBUG; break; } - snprintf(msg_buf + strlen(msg_buf), MSG_BUFFER - strlen(msg_buf), - "%s ", lvl); - vsnprintf(msg_buf + strlen(msg_buf), MSG_BUFFER - strlen(msg_buf), - msg_format, ap); + virBufferAsprintf(&buf, "%s ", lvl); + virBufferVasprintf(&buf, msg_format, ap); + virBufferAddChar(&buf, '\n'); - if (msg_buf[strlen(msg_buf) - 1] != '\n') - snprintf(msg_buf + strlen(msg_buf), MSG_BUFFER - strlen(msg_buf), "\n"); + if (virBufferError(&buf)) + goto error; - /* write log */ - if (safewrite(ctl->log_fd, msg_buf, strlen(msg_buf)) < 0) { - vshCloseLogFile(ctl); - vshError(ctl, "%s", _("failed to write the log file")); + str = virBufferContentAndReset(&buf); + len = strlen(str); + if (len > 1 && str[len - 2] == '\n') { + str[len - 1] = '\0'; + len--; } - VIR_FREE(msg_buf); + /* write log */ + if (safewrite(ctl->log_fd, str, len) < 0) + goto error; + + return; + +error: + vshCloseLogFile(ctl); + vshError(ctl, "%s", _("failed to write the log file")); + virBufferFreeAndReset(&buf); + VIR_FREE(str); } /** -- 1.7.4.4 From eblake at redhat.com Sat Apr 30 17:09:25 2011 From: eblake at redhat.com (Eric Blake) Date: Sat, 30 Apr 2011 11:09:25 -0600 Subject: [libvirt] [PATCH 1/3] maint: rename virBufferVSprintf to virBufferAsprintf In-Reply-To: <1304183367-3491-1-git-send-email-eblake@redhat.com> References: <4DBC1253.4050801@redhat.com> <1304183367-3491-1-git-send-email-eblake@redhat.com> Message-ID: <1304183367-3491-2-git-send-email-eblake@redhat.com> We already have virAsprintf, so picking a similar name helps for seeing a similar purpose. Furthermore, the prefix V before printf generally implies va_arg, even though this variant was ..., and therefore the old name got in the way of adding a new va_arg version. global rename performed with: $ git grep -l virBufferVSprintf \ | xargs -L1 sed -i 's/virBufferVSprintf/virBufferAsprintf/g' --- Completely mechanical. ChangeLog-old | 2 +- HACKING | 2 +- docs/api_extension/0008-support-new-xml.patch | 46 ++-- ...improve-vcpu-support-in-qemu-command-line.patch | 8 +- ...-improve-vcpu-support-in-xen-command-line.patch | 12 +- docs/hacking.html.in | 2 +- docs/news.html.in | 4 +- src/conf/capabilities.c | 48 ++-- src/conf/cpu_conf.c | 24 +- src/conf/domain_conf.c | 294 ++++++++++---------- src/conf/interface_conf.c | 60 ++-- src/conf/network_conf.c | 26 +- src/conf/node_device_conf.c | 62 ++-- src/conf/nwfilter_conf.c | 34 ++-- src/conf/nwfilter_params.c | 2 +- src/conf/secret_conf.c | 4 +- src/conf/storage_conf.c | 70 +++--- src/conf/storage_encryption_conf.c | 6 +- src/cpu/cpu_map.c | 2 +- src/esx/esx_driver.c | 4 +- src/esx/esx_vi.c | 2 +- src/esx/esx_vi_types.c | 6 +- src/libvirt_private.syms | 2 +- src/network/bridge_driver.c | 4 +- src/node_device/node_device_udev.c | 4 +- src/nwfilter/nwfilter_ebiptables_driver.c | 206 +++++++------- src/nwfilter/nwfilter_learnipaddr.c | 4 +- src/openvz/openvz_driver.c | 18 +- src/phyp/phyp_driver.c | 248 ++++++++-------- src/qemu/qemu_command.c | 256 +++++++++--------- src/qemu/qemu_domain.c | 6 +- src/qemu/qemu_monitor.c | 4 +- src/security/virt-aa-helper.c | 12 +- src/uml/uml_conf.c | 10 +- src/util/bitmap.c | 2 +- src/util/buf.c | 12 +- src/util/buf.h | 2 +- src/util/conf.c | 10 +- src/util/logging.c | 8 +- src/util/sexpr.c | 2 +- src/util/sysinfo.c | 12 +- src/vmx/vmx.c | 138 +++++----- src/xen/xend_internal.c | 2 +- src/xen/xm_internal.c | 2 +- src/xenapi/xenapi_utils.c | 2 +- src/xenxs/xen_sxpr.c | 60 ++-- src/xenxs/xen_xm.c | 40 ++-- tests/cputest.c | 6 +- tests/virbuftest.c | 2 +- tools/virsh.c | 64 +++--- 50 files changed, 929 insertions(+), 929 deletions(-) diff --git a/ChangeLog-old b/ChangeLog-old index c3b41e2..af9b914 100644 --- a/ChangeLog-old +++ b/ChangeLog-old @@ -15782,7 +15782,7 @@ Wed May 10 13:17:00 CEST 2006 Karel Zak * src/xml.c src/xml.h: added virBufferNew() and virBufferStrcat() * tests/xmlrpctest.c: added performace tests for virBufferStrcat() and - virBufferVSprintf() + virBufferAsprintf() * src/xmlrpc.c: used virBufferStrcat() Tue May 9 16:37:22 CEST 2006 Karel Zak diff --git a/HACKING b/HACKING index 686328c..8ebbec7 100644 --- a/HACKING +++ b/HACKING @@ -545,7 +545,7 @@ Typical usage is as follows: ... virBufferAddLit(&buf, "\n"); - virBufferVSprintf(&buf, " %d\n", memory); + virBufferAsprintf(&buf, " %d\n", memory); ... virBufferAddLit(&buf, "\n"); diff --git a/docs/api_extension/0008-support-new-xml.patch b/docs/api_extension/0008-support-new-xml.patch index 821cfa5..276b339 100644 --- a/docs/api_extension/0008-support-new-xml.patch +++ b/docs/api_extension/0008-support-new-xml.patch @@ -107,7 +107,7 @@ index 78d7a6a..a997e06 100644 allones = 0; - if (allones) { -- virBufferVSprintf(&buf, " %lu\n", def->vcpus); +- virBufferAsprintf(&buf, " %lu\n", def->vcpus); - } else { + virBufferAddLit(&buf, " cpumask, def->cpumasklen)) == NULL) goto cleanup; -- virBufferVSprintf(&buf, " %lu\n", +- virBufferAsprintf(&buf, " %lu\n", - cpumask, def->vcpus); -+ virBufferVSprintf(&buf, " cpuset='%s'", cpumask); ++ virBufferAsprintf(&buf, " cpuset='%s'", cpumask); VIR_FREE(cpumask); } + if (def->vcpus != def->maxvcpus) -+ virBufferVSprintf(&buf, " current='%u'", def->vcpus); -+ virBufferVSprintf(&buf, ">%u\n", def->maxvcpus); ++ virBufferAsprintf(&buf, " current='%u'", def->vcpus); ++ virBufferAsprintf(&buf, ">%u\n", def->maxvcpus); if (def->os.bootloader) { virBufferEscapeString(&buf, " %s\n", @@ -184,8 +184,8 @@ index 7ec8c0e..0a26614 100644 goto cleanup; } -- virBufferVSprintf(&buffer, "numvcpus = \"%d\"\n", (int)def->vcpus); -+ virBufferVSprintf(&buffer, "numvcpus = \"%d\"\n", def->maxvcpus); +- virBufferAsprintf(&buffer, "numvcpus = \"%d\"\n", (int)def->vcpus); ++ virBufferAsprintf(&buffer, "numvcpus = \"%d\"\n", def->maxvcpus); /* def:cpumask -> vmx:sched.cpu.affinity */ if (def->cpumasklen > 0) { @@ -221,8 +221,8 @@ index 44e28dc..2079c51 100644 { int i; virBuffer buf= VIR_BUFFER_INITIALIZER; -- virBufferVSprintf(&buf,"#OpenNebula Template automatically generated by libvirt\nNAME = %s\nCPU = %ld\nMEMORY = %ld\n", -+ virBufferVSprintf(&buf,"#OpenNebula Template automatically generated " +- virBufferAsprintf(&buf,"#OpenNebula Template automatically generated by libvirt\nNAME = %s\nCPU = %ld\nMEMORY = %ld\n", ++ virBufferAsprintf(&buf,"#OpenNebula Template automatically generated " + "by libvirt\nNAME = %s\nCPU = %d\nMEMORY = %ld\n", def->name, - def->vcpus, @@ -311,19 +311,19 @@ index 83c0f83..38c8351 100644 { virBuffer buf = VIR_BUFFER_INITIALIZER; -- virBufferVSprintf(&buf, "%lu", def->vcpus); -+ virBufferVSprintf(&buf, "%u", def->vcpus); +- virBufferAsprintf(&buf, "%lu", def->vcpus); ++ virBufferAsprintf(&buf, "%u", def->vcpus); if ((qemuCmdFlags & QEMUD_CMD_FLAG_SMP_TOPOLOGY)) { /* sockets, cores, and threads are either all zero @@ -3722,11 +3722,18 @@ qemuBuildSmpArgStr(const virDomainDefPtr def, - virBufferVSprintf(&buf, ",threads=%u", def->cpu->threads); + virBufferAsprintf(&buf, ",threads=%u", def->cpu->threads); } else { -- virBufferVSprintf(&buf, ",sockets=%lu", def->vcpus); -+ virBufferVSprintf(&buf, ",sockets=%u", def->maxvcpus); - virBufferVSprintf(&buf, ",cores=%u", 1); - virBufferVSprintf(&buf, ",threads=%u", 1); +- virBufferAsprintf(&buf, ",sockets=%lu", def->vcpus); ++ virBufferAsprintf(&buf, ",sockets=%u", def->maxvcpus); + virBufferAsprintf(&buf, ",cores=%u", 1); + virBufferAsprintf(&buf, ",threads=%u", 1); } } + if (def->vcpus != def->maxvcpus) { @@ -425,20 +425,20 @@ index 5ffc3c8..456b477 100644 */ char * @@ -5666,7 +5667,7 @@ xenDaemonFormatSxpr(virConnectPtr conn, - virBufferVSprintf(&buf, "(name '%s')", def->name); - virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", + virBufferAsprintf(&buf, "(name '%s')", def->name); + virBufferAsprintf(&buf, "(memory %lu)(maxmem %lu)", def->mem.cur_balloon/1024, def->mem.max_balloon/1024); -- virBufferVSprintf(&buf, "(vcpus %lu)", def->vcpus); -+ virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus); +- virBufferAsprintf(&buf, "(vcpus %lu)", def->vcpus); ++ virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus); if (def->cpumask) { char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen); @@ -5761,7 +5762,7 @@ xenDaemonFormatSxpr(virConnectPtr conn, else - virBufferVSprintf(&buf, "(kernel '%s')", def->os.loader); + virBufferAsprintf(&buf, "(kernel '%s')", def->os.loader); -- virBufferVSprintf(&buf, "(vcpus %lu)", def->vcpus); -+ virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus); +- virBufferAsprintf(&buf, "(vcpus %lu)", def->vcpus); ++ virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus); for (i = 0 ; i < def->os.nBootDevs ; i++) { switch (def->os.bootDevs[i]) { diff --git a/docs/api_extension/0010-improve-vcpu-support-in-qemu-command-line.patch b/docs/api_extension/0010-improve-vcpu-support-in-qemu-command-line.patch index e082991..02320bb 100644 --- a/docs/api_extension/0010-improve-vcpu-support-in-qemu-command-line.patch +++ b/docs/api_extension/0010-improve-vcpu-support-in-qemu-command-line.patch @@ -23,17 +23,17 @@ index 38c8351..ffe184b 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -3714,6 +3714,8 @@ qemuBuildSmpArgStr(const virDomainDefPtr def, - virBufferVSprintf(&buf, "%u", def->vcpus); + virBufferAsprintf(&buf, "%u", def->vcpus); if ((qemuCmdFlags & QEMUD_CMD_FLAG_SMP_TOPOLOGY)) { + if (def->vcpus != def->maxvcpus) -+ virBufferVSprintf(&buf, ",maxcpus=%u", def->maxvcpus); ++ virBufferAsprintf(&buf, ",maxcpus=%u", def->maxvcpus); /* sockets, cores, and threads are either all zero * or all non-zero, thus checking one of them is enough */ if (def->cpu && def->cpu->sockets) { @@ -3726,12 +3728,12 @@ qemuBuildSmpArgStr(const virDomainDefPtr def, - virBufferVSprintf(&buf, ",cores=%u", 1); - virBufferVSprintf(&buf, ",threads=%u", 1); + virBufferAsprintf(&buf, ",cores=%u", 1); + virBufferAsprintf(&buf, ",threads=%u", 1); } - } - if (def->vcpus != def->maxvcpus) { diff --git a/docs/api_extension/0012-improve-vcpu-support-in-xen-command-line.patch b/docs/api_extension/0012-improve-vcpu-support-in-xen-command-line.patch index f8764b3..0a7b2fc 100644 --- a/docs/api_extension/0012-improve-vcpu-support-in-xen-command-line.patch +++ b/docs/api_extension/0012-improve-vcpu-support-in-xen-command-line.patch @@ -88,21 +88,21 @@ index 456b477..dfc6415 100644 } @@ -5668,6 +5675,9 @@ xenDaemonFormatSxpr(virConnectPtr conn, - virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", + virBufferAsprintf(&buf, "(memory %lu)(maxmem %lu)", def->mem.cur_balloon/1024, def->mem.max_balloon/1024); - virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus); + virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus); + /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is 32. */ + if (def->vcpus < def->maxvcpus) -+ virBufferVSprintf(&buf, "(vcpu_avail %u)", (1U << def->vcpus) - 1); ++ virBufferAsprintf(&buf, "(vcpu_avail %u)", (1U << def->vcpus) - 1); if (def->cpumask) { char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen); @@ -5763,6 +5773,9 @@ xenDaemonFormatSxpr(virConnectPtr conn, - virBufferVSprintf(&buf, "(kernel '%s')", def->os.loader); + virBufferAsprintf(&buf, "(kernel '%s')", def->os.loader); - virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus); + virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus); + if (def->vcpus < def->maxvcpus) -+ virBufferVSprintf(&buf, "(vcpu_avail %u)", ++ virBufferAsprintf(&buf, "(vcpu_avail %u)", + (1U << def->vcpus) - 1); for (i = 0 ; i < def->os.nBootDevs ; i++) { diff --git a/docs/hacking.html.in b/docs/hacking.html.in index dd8eeb8..6888687 100644 --- a/docs/hacking.html.in +++ b/docs/hacking.html.in @@ -654,7 +654,7 @@ ... virBufferAddLit(&buf, "<domain>\n"); - virBufferVSprintf(&buf, " <memory>%d</memory>\n", memory); + virBufferAsprintf(&buf, " <memory>%d</memory>\n", memory); ... virBufferAddLit(&buf, "</domain>\n"); diff --git a/docs/news.html.in b/docs/news.html.in index 25dd467..60fa896 100644 --- a/docs/news.html.in +++ b/docs/news.html.in @@ -870,7 +870,7 @@ and check the GIT log
  • Documentation:
    updated c# bindings with arnauds latest changes (Justin Clift),
    - Fix spelling of virBufferVSprintf (Jiri Denemark),
    + Fix spelling of virBufferAsprintf (Jiri Denemark),
    Fix broken XML entity for '>' (Philipp Hahn),
    removed outdated reference to virt-mem (Justin Clift),
    Add doc for missed options of migrate (Osier Yang),
    @@ -2578,7 +2578,7 @@ and check the GIT log virsh.c: avoid all leaks in OOM path in cmdCPUBaseline (Jiri Denemark),
    Fixed reference count in virsh pool-build command (David Allan),
    Fix daemon-conf invalid failures (David Allan),
    - virBufferVSprintf: do not omit va_end(argptr) call (Jim Meyering),
    + virBufferAsprintf: do not omit va_end(argptr) call (Jim Meyering),
    xend_internal.c: don't dereference NULL for unexpected input (Jim Meyering),
    virsh: be careful to return "FALSE" upon OOM (Jim Meyering),
    virBufferStrcat: do not skip va_end (Jim Meyering),
    diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index cb9113c..2f243ae 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -666,16 +666,16 @@ virCapabilitiesFormatXML(virCapsPtr caps) virBufferAddLit(&xml, " \n"); if (virUUIDIsValid(caps->host.host_uuid)) { virUUIDFormat(caps->host.host_uuid, host_uuid); - virBufferVSprintf(&xml," %s\n", host_uuid); + virBufferAsprintf(&xml," %s\n", host_uuid); } virBufferAddLit(&xml, " \n"); - virBufferVSprintf(&xml, " %s\n", + virBufferAsprintf(&xml, " %s\n", caps->host.arch); if (caps->host.nfeatures) { virBufferAddLit(&xml, " \n"); for (i = 0 ; i < caps->host.nfeatures ; i++) { - virBufferVSprintf(&xml, " <%s/>\n", + virBufferAsprintf(&xml, " <%s/>\n", caps->host.features[i]); } virBufferAddLit(&xml, " \n"); @@ -693,7 +693,7 @@ virCapabilitiesFormatXML(virCapsPtr caps) if (caps->host.nmigrateTrans) { virBufferAddLit(&xml, " \n"); for (i = 0 ; i < caps->host.nmigrateTrans ; i++) { - virBufferVSprintf(&xml, " %s\n", + virBufferAsprintf(&xml, " %s\n", caps->host.migrateTrans[i]); } virBufferAddLit(&xml, " \n"); @@ -703,15 +703,15 @@ virCapabilitiesFormatXML(virCapsPtr caps) if (caps->host.nnumaCell) { virBufferAddLit(&xml, " \n"); - virBufferVSprintf(&xml, " \n", + virBufferAsprintf(&xml, " \n", caps->host.nnumaCell); for (i = 0 ; i < caps->host.nnumaCell ; i++) { - virBufferVSprintf(&xml, " \n", + virBufferAsprintf(&xml, " \n", caps->host.numaCell[i]->num); - virBufferVSprintf(&xml, " \n", + virBufferAsprintf(&xml, " \n", caps->host.numaCell[i]->ncpus); for (j = 0 ; j < caps->host.numaCell[i]->ncpus ; j++) - virBufferVSprintf(&xml, " \n", + virBufferAsprintf(&xml, " \n", caps->host.numaCell[i]->cpus[j]); virBufferAddLit(&xml, " \n"); virBufferAddLit(&xml, " \n"); @@ -722,8 +722,8 @@ virCapabilitiesFormatXML(virCapsPtr caps) if (caps->host.secModel.model) { virBufferAddLit(&xml, " \n"); - virBufferVSprintf(&xml, " %s\n", caps->host.secModel.model); - virBufferVSprintf(&xml, " %s\n", caps->host.secModel.doi); + virBufferAsprintf(&xml, " %s\n", caps->host.secModel.model); + virBufferAsprintf(&xml, " %s\n", caps->host.secModel.doi); virBufferAddLit(&xml, " \n"); } @@ -732,43 +732,43 @@ virCapabilitiesFormatXML(virCapsPtr caps) for (i = 0 ; i < caps->nguests ; i++) { virBufferAddLit(&xml, " \n"); - virBufferVSprintf(&xml, " %s\n", + virBufferAsprintf(&xml, " %s\n", caps->guests[i]->ostype); - virBufferVSprintf(&xml, " \n", + virBufferAsprintf(&xml, " \n", caps->guests[i]->arch.name); - virBufferVSprintf(&xml, " %d\n", + virBufferAsprintf(&xml, " %d\n", caps->guests[i]->arch.wordsize); if (caps->guests[i]->arch.defaultInfo.emulator) - virBufferVSprintf(&xml, " %s\n", + virBufferAsprintf(&xml, " %s\n", caps->guests[i]->arch.defaultInfo.emulator); if (caps->guests[i]->arch.defaultInfo.loader) - virBufferVSprintf(&xml, " %s\n", + virBufferAsprintf(&xml, " %s\n", caps->guests[i]->arch.defaultInfo.loader); for (j = 0 ; j < caps->guests[i]->arch.defaultInfo.nmachines ; j++) { virCapsGuestMachinePtr machine = caps->guests[i]->arch.defaultInfo.machines[j]; virBufferAddLit(&xml, " canonical) - virBufferVSprintf(&xml, " canonical='%s'", machine->canonical); - virBufferVSprintf(&xml, ">%s\n", machine->name); + virBufferAsprintf(&xml, " canonical='%s'", machine->canonical); + virBufferAsprintf(&xml, ">%s\n", machine->name); } for (j = 0 ; j < caps->guests[i]->arch.ndomains ; j++) { - virBufferVSprintf(&xml, " \n", + virBufferAsprintf(&xml, " \n", caps->guests[i]->arch.domains[j]->type); if (caps->guests[i]->arch.domains[j]->info.emulator) - virBufferVSprintf(&xml, " %s\n", + virBufferAsprintf(&xml, " %s\n", caps->guests[i]->arch.domains[j]->info.emulator); if (caps->guests[i]->arch.domains[j]->info.loader) - virBufferVSprintf(&xml, " %s\n", + virBufferAsprintf(&xml, " %s\n", caps->guests[i]->arch.domains[j]->info.loader); for (k = 0 ; k < caps->guests[i]->arch.domains[j]->info.nmachines ; k++) { virCapsGuestMachinePtr machine = caps->guests[i]->arch.domains[j]->info.machines[k]; virBufferAddLit(&xml, " canonical) - virBufferVSprintf(&xml, " canonical='%s'", machine->canonical); - virBufferVSprintf(&xml, ">%s\n", machine->name); + virBufferAsprintf(&xml, " canonical='%s'", machine->canonical); + virBufferAsprintf(&xml, ">%s\n", machine->name); } virBufferAddLit(&xml, " \n"); } @@ -784,10 +784,10 @@ virCapabilitiesFormatXML(virCapsPtr caps) STREQ(caps->guests[i]->features[j]->name, "ia64_be") || STREQ(caps->guests[i]->features[j]->name, "cpuselection") || STREQ(caps->guests[i]->features[j]->name, "deviceboot")) { - virBufferVSprintf(&xml, " <%s/>\n", + virBufferAsprintf(&xml, " <%s/>\n", caps->guests[i]->features[j]->name); } else { - virBufferVSprintf(&xml, " <%s default='%s' toggle='%s'/>\n", + virBufferAsprintf(&xml, " <%s default='%s' toggle='%s'/>\n", caps->guests[i]->features[j]->name, caps->guests[i]->features[j]->defaultOn ? "on" : "off", caps->guests[i]->features[j]->toggle ? "yes" : "no"); diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index ad49916..98d598a 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -353,28 +353,28 @@ virCPUDefFormatBuf(virBufferPtr buf, return -1; } - virBufferVSprintf(buf, "%s\n", indent, match); + virBufferAsprintf(buf, "%s\n", indent, match); } else - virBufferVSprintf(buf, "%s\n", indent); + virBufferAsprintf(buf, "%s\n", indent); if (def->arch) - virBufferVSprintf(buf, "%s %s\n", indent, def->arch); + virBufferAsprintf(buf, "%s %s\n", indent, def->arch); } if (def->model) - virBufferVSprintf(buf, "%s %s\n", indent, def->model); + virBufferAsprintf(buf, "%s %s\n", indent, def->model); if (def->vendor) { - virBufferVSprintf(buf, "%s %s\n", + virBufferAsprintf(buf, "%s %s\n", indent, def->vendor); } if (def->sockets && def->cores && def->threads) { - virBufferVSprintf(buf, "%s sockets); - virBufferVSprintf(buf, " cores='%u'", def->cores); - virBufferVSprintf(buf, " threads='%u'", def->threads); + virBufferAsprintf(buf, "%s sockets); + virBufferAsprintf(buf, " cores='%u'", def->cores); + virBufferAsprintf(buf, " threads='%u'", def->threads); virBufferAddLit(buf, "/>\n"); } @@ -396,17 +396,17 @@ virCPUDefFormatBuf(virBufferPtr buf, _("Unexpected CPU feature policy %d"), feature->policy); return -1; } - virBufferVSprintf(buf, "%s \n", + virBufferAsprintf(buf, "%s \n", indent, policy, feature->name); } else { - virBufferVSprintf(buf, "%s \n", + virBufferAsprintf(buf, "%s \n", indent, feature->name); } } if (!(flags & VIR_CPU_FORMAT_EMBEDED)) - virBufferVSprintf(buf, "%s\n", indent); + virBufferAsprintf(buf, "%s\n", indent); return 0; } diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 2a681d9..70ea350 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1347,19 +1347,19 @@ virDomainDeviceInfoFormat(virBufferPtr buf, { if (info->alias && !(flags & VIR_DOMAIN_XML_INACTIVE)) { - virBufferVSprintf(buf, " \n", info->alias); + virBufferAsprintf(buf, " \n", info->alias); } if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) return 0; /* We'll be in domain/devices/[device type]/ so 3 level indent */ - virBufferVSprintf(buf, "
    type)); switch (info->type) { case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: - virBufferVSprintf(buf, " domain='0x%.4x' bus='0x%.2x' slot='0x%.2x' function='0x%.1x'", + virBufferAsprintf(buf, " domain='0x%.4x' bus='0x%.2x' slot='0x%.2x' function='0x%.1x'", info->addr.pci.domain, info->addr.pci.bus, info->addr.pci.slot, @@ -1367,21 +1367,21 @@ virDomainDeviceInfoFormat(virBufferPtr buf, break; case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE: - virBufferVSprintf(buf, " controller='%d' bus='%d' unit='%d'", + virBufferAsprintf(buf, " controller='%d' bus='%d' unit='%d'", info->addr.drive.controller, info->addr.drive.bus, info->addr.drive.unit); break; case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL: - virBufferVSprintf(buf, " controller='%d' bus='%d' port='%d'", + virBufferAsprintf(buf, " controller='%d' bus='%d' port='%d'", info->addr.vioserial.controller, info->addr.vioserial.bus, info->addr.vioserial.port); break; case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID: - virBufferVSprintf(buf, " controller='%d' slot='%d'", + virBufferAsprintf(buf, " controller='%d' slot='%d'", info->addr.ccid.controller, info->addr.ccid.slot); break; @@ -4974,7 +4974,7 @@ virVirtualPortProfileFormat(virBufferPtr buf, if (virtPort->virtPortType == VIR_VIRTUALPORT_NONE) return; - virBufferVSprintf(buf, "%s\n", + virBufferAsprintf(buf, "%s\n", indent, virVirtualPortTypeToString(virtPort->virtPortType)); @@ -4986,7 +4986,7 @@ virVirtualPortProfileFormat(virBufferPtr buf, case VIR_VIRTUALPORT_8021QBG: virUUIDFormat(virtPort->u.virtPort8021Qbg.instanceID, uuidstr); - virBufferVSprintf(buf, + virBufferAsprintf(buf, "%s \n", indent, @@ -4997,14 +4997,14 @@ virVirtualPortProfileFormat(virBufferPtr buf, break; case VIR_VIRTUALPORT_8021QBH: - virBufferVSprintf(buf, + virBufferAsprintf(buf, "%s \n", indent, virtPort->u.virtPort8021Qbh.profileID); break; } - virBufferVSprintf(buf, "%s\n", indent); + virBufferAsprintf(buf, "%s\n", indent); } int virDomainDiskIndexByName(virDomainDefPtr def, const char *name) @@ -6653,9 +6653,9 @@ virDomainCpuSetFormat(char *cpuset, int maxcpu) else first = 0; if (cur == start + 1) - virBufferVSprintf(&buf, "%d", start); + virBufferAsprintf(&buf, "%d", start); else - virBufferVSprintf(&buf, "%d-%d", start, cur - 1); + virBufferAsprintf(&buf, "%d-%d", start, cur - 1); start = -1; } cur++; @@ -6664,9 +6664,9 @@ virDomainCpuSetFormat(char *cpuset, int maxcpu) if (!first) virBufferAddLit(&buf, ","); if (maxcpu == start + 1) - virBufferVSprintf(&buf, "%d", start); + virBufferAsprintf(&buf, "%d", start); else - virBufferVSprintf(&buf, "%d-%d", start, maxcpu - 1); + virBufferAsprintf(&buf, "%d-%d", start, maxcpu - 1); } if (virBufferError(&buf)) { @@ -6915,7 +6915,7 @@ virDomainLifecycleDefFormat(virBufferPtr buf, return -1; } - virBufferVSprintf(buf, " <%s>%s\n", name, typeStr, name); + virBufferAsprintf(buf, " <%s>%s\n", name, typeStr, name); return 0; } @@ -6959,23 +6959,23 @@ virDomainDiskDefFormat(virBufferPtr buf, return -1; } - virBufferVSprintf(buf, + virBufferAsprintf(buf, " \n", type, device); if (def->driverName || def->driverType || def->cachemode) { - virBufferVSprintf(buf, " driverName) - virBufferVSprintf(buf, " name='%s'", def->driverName); + virBufferAsprintf(buf, " name='%s'", def->driverName); if (def->driverType) - virBufferVSprintf(buf, " type='%s'", def->driverType); + virBufferAsprintf(buf, " type='%s'", def->driverType); if (def->cachemode) - virBufferVSprintf(buf, " cache='%s'", cachemode); + virBufferAsprintf(buf, " cache='%s'", cachemode); if (def->error_policy) - virBufferVSprintf(buf, " error_policy='%s'", error_policy); + virBufferAsprintf(buf, " error_policy='%s'", error_policy); if (def->iomode) - virBufferVSprintf(buf, " io='%s'", iomode); - virBufferVSprintf(buf, "/>\n"); + virBufferAsprintf(buf, " io='%s'", iomode); + virBufferAsprintf(buf, "/>\n"); } if (def->src || def->nhosts > 0) { @@ -6993,24 +6993,24 @@ virDomainDiskDefFormat(virBufferPtr buf, def->src); break; case VIR_DOMAIN_DISK_TYPE_NETWORK: - virBufferVSprintf(buf, " protocol)); if (def->src) { virBufferEscapeString(buf, " name='%s'", def->src); } if (def->nhosts == 0) { - virBufferVSprintf(buf, "/>\n"); + virBufferAsprintf(buf, "/>\n"); } else { int i; - virBufferVSprintf(buf, ">\n"); + virBufferAsprintf(buf, ">\n"); for (i = 0; i < def->nhosts; i++) { virBufferEscapeString(buf, " hosts[i].name); virBufferEscapeString(buf, " port='%s'/>\n", def->hosts[i].port); } - virBufferVSprintf(buf, " \n"); + virBufferAsprintf(buf, " \n"); } break; default: @@ -7021,11 +7021,11 @@ virDomainDiskDefFormat(virBufferPtr buf, } } - virBufferVSprintf(buf, " \n", + virBufferAsprintf(buf, " \n", def->dst, bus); if (def->bootIndex) - virBufferVSprintf(buf, " \n", def->bootIndex); + virBufferAsprintf(buf, " \n", def->bootIndex); if (def->readonly) virBufferAddLit(buf, " \n"); if (def->shared) @@ -7069,7 +7069,7 @@ virDomainControllerDefFormat(virBufferPtr buf, } } - virBufferVSprintf(buf, + virBufferAsprintf(buf, " idx); @@ -7080,11 +7080,11 @@ virDomainControllerDefFormat(virBufferPtr buf, switch (def->type) { case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: if (def->opts.vioserial.ports != -1) { - virBufferVSprintf(buf, " ports='%d'", + virBufferAsprintf(buf, " ports='%d'", def->opts.vioserial.ports); } if (def->opts.vioserial.vectors != -1) { - virBufferVSprintf(buf, " vectors='%d'", + virBufferAsprintf(buf, " vectors='%d'", def->opts.vioserial.vectors); } break; @@ -7126,7 +7126,7 @@ virDomainFSDefFormat(virBufferPtr buf, } - virBufferVSprintf(buf, + virBufferAsprintf(buf, " \n", type, accessmode); @@ -7153,7 +7153,7 @@ virDomainFSDefFormat(virBufferPtr buf, } } - virBufferVSprintf(buf, " \n", + virBufferAsprintf(buf, " \n", def->dst); if (def->readonly) @@ -7181,9 +7181,9 @@ virDomainNetDefFormat(virBufferPtr buf, return -1; } - virBufferVSprintf(buf, " \n", type); + virBufferAsprintf(buf, " \n", type); - virBufferVSprintf(buf, + virBufferAsprintf(buf, " \n", def->mac[0], def->mac[1], def->mac[2], def->mac[3], def->mac[4], def->mac[5]); @@ -7199,7 +7199,7 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " \n", def->data.ethernet.dev); if (def->data.ethernet.ipaddr) - virBufferVSprintf(buf, " \n", + virBufferAsprintf(buf, " \n", def->data.ethernet.ipaddr); if (def->data.ethernet.script) virBufferEscapeString(buf, "