Re: [libvirt] [virt-tools-list] [PATCH virt-manager v4] Add inspection to virt-manager
by Richard W.M. Jones
On Tue, Jul 19, 2011 at 03:40:53PM +0100, Daniel P. Berrange wrote:
> On Tue, Jul 19, 2011 at 10:17:02AM -0400, Cole Robinson wrote:
> > On 07/19/2011 03:49 AM, Richard W.M. Jones wrote:
> > > On Mon, Jul 18, 2011 at 05:41:00PM -0400, Cole Robinson wrote:
> > >> On 07/18/2011 02:53 PM, Richard W.M. Jones wrote:
> > >>> This updates 1/4 with the fixes you suggested. Also, all check-pylint
> > >>> warnings and errors have been fixed.
> > >>>
> > >>> Rich.
> > >>>
> > >>
> > >> Thanks! Pushed the series.
> > >
> > > In reply to your comment on IRC:
> > >
> > > crobinso> rjones: so in the default usage of virt-manager in fedora,
> > > the guest inspection probably won't work since we
> > > save disk images in /var/lib/libvirt/images/, which
> > > regular user doesn't have access to.
> > > crobinso> rjones: that's not entirely clear from feature page.
> > > crobinso> rjones: I'm thinking of adding a disk path access check in
> > > the inspection thread, to avoid flooding the logs
> > > with errors if we can't even read the disk
> > > image. that should be safe to do?
> > >
> > > I always run virt-manager as root (or from sudo) so this hasn't been
> > > an issue. What user does virt-manager run as normally?
> > >
> >
> > I think most common usage is just running virt-manager as the logged in
> > user, using policykit to authenticate the libvirt connection so the rest
> > of the app doesn't have root privs.
> >
> > > AFAICT if there's no access to the disks, then the call to either
> > > g.add_drive_opts or g.launch will throw an exception. But the
> > > inspection._vmseen hash will mean this will only happen once per
> > > domain per run of virt-manager.
> > >
> > > On an unrelated note: I think we need to cache inspection between runs
> > > of virt-manager. Does virt-manager currently store permanent state (I
> > > assume it must do - ie. list of connections), and where?
> > >
> >
> > We store config like that in gconf, though I don't think sticking
> > largish data like list of applications or a png in there is a good idea.
> > hostname + os info could be cached, though ideally the latter would be
> > stored in libvirt XML at some point.
>
> Agreed, it would be desirable to cache the PNGs in $HOME/.virt-manager
> though, perhaps as
>
> $HOME/.virt-manager/icons/$CONN_URI/$DOMAIN_UUID
>
> To avoid growing without bound, probably want to have virt-manager
> purge files in that directory on startup, if the PNG is older than
> 3 months and the associated connection or domain no longer exists.
> ie don't immediately purge them, since a user might later re-add a
> connection or re-create a VM.
>
> Another thought though is that we've also got some work going on a
> little plugin for gnome-shell to capture & display screenshots of
> VMs. It might be nice for virt-manager to take advantage of this
> too, while also the shell plugin might like the icon image. So
> perhaps we should declare a standard location for storing assets
> related to a VM, which are expensive to extract/fetch.
>
> $HOME/.local/libvirt/$CONN_URI/$DOMAIN_UUID/screenshot.png
> $HOME/.local/libvirt/$CONN_URI/$DOMAIN_UUID/icon.png
> $HOME/.local/libvirt/$CONN_URI/$DOMAIN_UUID/osinfo.json
>
> or something like that
+1
CC-ing to libvir-list.
Rich.
--
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
13 years, 4 months
[libvirt] RFC (V2) New virDomainBlockPull API family to libvirt
by Adam Litke
In light of discussion on V1 of this API, here is V2 of the next generation BlockPull API. In this series we make the abort and info operations more generic so that they may apply to future block jobs (such as compression, live block copy, etc). We also add in a mechanism to set the maximum bandwidth of an operation.
Changes since V1:
- Make virDomainBlockPullAbort() and virDomainGetBlockPullInfo() into a
generic BlockJob interface.
- Added virDomainBlockJobSetSpeed()
- Rename VIR_DOMAIN_EVENT_ID_BLOCK_PULL event to fit into block job API
- Add bandwidth argument to virDomainBlockPull()
Summary of changes since first generation patch series:
- Qemu dropped incremental streaming so remove libvirt incremental
BlockPull() API
- Rename virDomainBlockPullAll() to virDomainBlockPull()
- Changes required to qemu monitor handlers for changed command names
--
To help speed the provisioning process for large domains, new QED disks are
created with backing to a template image. These disks are configured with
copy on read such that blocks that are read from the backing file are copied
to the new disk. This reduces I/O over a potentially costly path to the
backing image.
In such a configuration, there is a desire to remove the dependency on the
backing image as the domain runs. To accomplish this, qemu will provide an
interface to perform sequential copy on read operations during normal VM
operation. Once all data has been copied, the disk image's link to the
backing file is removed.
The virDomainBlockPull API family brings this functionality to libvirt.
virDomainBlockPull() instructs the hypervisor to stream the entire device in
the background. Progress of this operation can be checked with the function
virDomainBlockJobInfo(). An ongoing stream can be cancelled with
virDomainBlockJobAbort(). virDomainBlockJobSetSpeed() allows you to limit the
bandwidth that the operation may consume.
An event (VIR_DOMAIN_EVENT_ID_BLOCK_JOB) will be emitted when a disk has been
fully populated or if a BlockPull() operation was terminated due to an error.
This event is useful to avoid polling on virDomainBlockJobInfo() for
completion and could also be used by the security driver to revoke access to
the backing file when it is no longer needed.
/*
* BlockJob API
*/
/**
* virDomainBlockJobType:
*
* VIR_DOMAIN_BLOCK_JOB_TYPE_PULL: Block Pull (virDomainBlockPull)
*/
typedef enum {
VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN = -1,
VIR_DOMAIN_BLOCK_JOB_TYPE_PULL = 0,
} virDomainBlockJobType;
/* An iterator for monitoring block job operations */
typedef unsigned long long virDomainBlockJobCursor;
typedef struct _virDomainBlockJobInfo virDomainBlockJobInfo;
struct _virDomainBlockJobInfo {
virDomainBlockJobType type;
/*
* The following fields provide an indication of block job progress. @cur
* indicates the current position and will be between 0 and @end. @end is
* the final cursor position for this operation and represents completion.
* To approximate progress, divide @cur by @end.
*/
virDomainBlockJobCursor cur;
virDomainBlockJobCursor end;
};
typedef virDomainBlockJobInfo *virDomainBlockJobInfoPtr;
/**
* virDomainBlockJobAbort:
* @dom: pointer to domain object
* @path: fully-qualified filename of disk
* @flags: currently unused, for future extension
*
* Cancel the active block job on the given disk.
*
* Returns -1 in case of failure, 0 when successful.
*/
int virDomainBlockJobAbort(virDomainPtr dom,
const char *path,
unsigned int flags);
/**
* virDomainGetBlockJobInfo:
* @dom: pointer to domain object
* @path: fully-qualified filename of disk
* @info: pointer to a virDomainBlockJobInfo structure
* @flags: currently unused, for future extension
*
* Request block job information for the given disk. If an operation is active
* @info will be updated with the current progress.
*
* Returns -1 in case of failure, 0 when successful.
*/
int virDomainGetBlockJobInfo(virDomainPtr dom,
const char *path,
virDomainBlockJobInfoPtr info,
unsigned int flags);
/**
* virDomainBlockJobSetSpeed:
* @dom: pointer to domain object
* @path: fully-qualified filename of disk
* @bandwidth: specify bandwidth limit in Mbps
* @flags: currently unused, for future extension
*
* Set the maximimum allowable bandwidth that a block job may consume. If
* bandwidth is 0, the limit will revert to the hypervisor default.
*
* Returns -1 in case of failure, 0 when successful.
*/
int virDomainBlockJobSetSpeed(virDomainPtr dom,
const char *path,
unsigned long bandwidth,
unsigned int flags);
/**
* virConnectDomainEventBlockJobStatus:
*
* The final status of a block job
*/
typedef enum {
VIR_DOMAIN_BLOCK_JOB_COMPLETED = 0,
VIR_DOMAIN_BLOCK_JOB_FAILED = 1,
} virConnectDomainEventBlockJobStatus;
/**
* virConnectDomainEventBlockPullCallback:
* @conn: connection object
* @dom: domain on which the event occurred
* @path: fully-qualified filename of the affected disk
* @type: type of block job (virDomainBlockJobType)
* @status: final status of the operation (virConnectDomainEventBlockPullStatus)
* @opaque: callback context
*
* The callback signature to use when registering for an event of type
* VIR_DOMAIN_EVENT_ID_BLOCK_PULL with virConnectDomainEventRegisterAny()
*/
typedef void (*virConnectDomainEventBlockPullCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *path,
int type,
int status,
void *opaque);
/**
* virDomainBlockPull:
* @dom: pointer to domain object
* @path: Fully-qualified filename of disk
* @bandwidth: (optional) specify copy bandwidth limit in Mbps
* @flags: currently unused, for future extension
*
* Populate a disk image with data from its backing image. Once all data from
* its backing image has been pulled, the disk no longer depends on a backing
* image. This function pulls data for the entire device in the background.
* Progress of the operation can be checked with virDomainGetBlockJobInfo() and
* the operation can be aborted with virDomainBlockJobAbort(). When finished,
* an asynchronous event is raised to indicate the final status.
*
* The maximum bandwidth (in Mbps) that will be used to do the copy can be
* specified with the bandwidth parameter. If set to 0, libvirt will choose a
* suitable default. Some hypervisors do not support this feature and will
* return an error if bandwidth is not 0.
*
* Returns 0 if the operation has started, -1 on failure.
*/
int virDomainBlockPull(virDomainPtr dom,
const char *path,
unsigned long bandwidth,
unsigned int flags);
--
Adam Litke
IBM Linux Technology Center
13 years, 4 months
[libvirt] [PATCH] Quieten build & ensure API build scripts exit with non-zero status
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
The current API build scripts will continue and exit with a zero
status even if they find problems. This has been the cause of many
build problems, or hidden build errors, in the past. Change the
scripts so they always exit with a non-zero status for any problems
they do not understand. Also turn off all debug output by default
so they respect $(AM_V_GEN)
* docs/Makefile.am: Use $(AM_V_GEN) for API/HTML scripts
* docs/apibuild.py, python/generator.py: Exit with non-zero status
if problems are found. Also be silent, not outputting any debug
messages.
* src/Makefile.am: Use $(AM_V_GEN) for ESX generator
* python/Makefile.am: Tweak rule
---
docs/Makefile.am | 11 ++----
docs/apibuild.py | 95 ++++++++++++++++++++++++++++++--------------------
python/Makefile.am | 6 ++--
python/generator.py | 16 +++++---
src/Makefile.am | 2 +-
5 files changed, 75 insertions(+), 55 deletions(-)
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 7ff94a0..4ba6b9d 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -153,21 +153,18 @@ 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
- -@if [ -x $(XSLTPROC) ] ; then \
- echo "Rebuilding the HTML pages from the XML API" ; \
+ $(AM_V_GEN)if [ -x $(XSLTPROC) ] ; then \
$(XSLTPROC) --nonet -o $(srcdir)/ \
- $(srcdir)/newapi.xsl $(srcdir)/libvirt-api.xml ; fi
- -@if test -x $(XMLLINT) && test -x $(XMLCATALOG) ; then \
+ $(srcdir)/newapi.xsl $(srcdir)/libvirt-api.xml ; fi ; \
+ 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 ; \
else echo "missing XHTML1 DTD" ; fi ; fi
$(addprefix $(srcdir)/,$(devhelphtml)): $(srcdir)/libvirt-api.xml $(devhelpxsl)
- -@echo Rebuilding devhelp files
- -@if [ -x $(XSLTPROC) ] ; then \
+ $(AM_V_GEN)if [ -x $(XSLTPROC) ] ; then \
$(XSLTPROC) --nonet -o $(srcdir)/devhelp/ \
$(top_srcdir)/docs/devhelp/devhelp.xsl $(srcdir)/libvirt-api.xml ; fi
diff --git a/docs/apibuild.py b/docs/apibuild.py
index f31a853..cb273dc 100755
--- a/docs/apibuild.py
+++ b/docs/apibuild.py
@@ -11,6 +11,8 @@ import os, sys
import string
import glob
+quiet=1
+warnings=0
debug=0
debugsym=None
@@ -95,7 +97,7 @@ class identifier:
self.conditionals = None
else:
self.conditionals = conditionals[:]
- if self.name == debugsym:
+ if self.name == debugsym and not quiet:
print "=> define %s : %s" % (debugsym, (module, type, info,
extra, conditionals))
@@ -155,7 +157,7 @@ class identifier:
def update(self, header, module, type = None, info = None, extra=None,
conditionals=None):
- if self.name == debugsym:
+ if self.name == debugsym and not quiet:
print "=> update %s : %s" % (debugsym, (module, type, info,
extra, conditionals))
if header != None and self.header == None:
@@ -203,7 +205,7 @@ class index:
if d != None and name != None and type != None:
self.references[name] = d
- if name == debugsym:
+ if name == debugsym and not quiet:
print "New ref: %s" % (d)
return d
@@ -244,9 +246,9 @@ class index:
elif type == "macro":
self.macros[name] = d
else:
- print "Unable to register type ", type
+ self.warning("Unable to register type ", type)
- if name == debugsym:
+ if name == debugsym and not quiet:
print "New symbol: %s" % (d)
return d
@@ -260,8 +262,8 @@ class index:
if self.macros.has_key(id):
del self.macros[id]
if self.functions.has_key(id):
- print "function %s from %s redeclared in %s" % (
- id, self.functions[id].header, idx.functions[id].header)
+ self.warning("function %s from %s redeclared in %s" % (
+ id, self.functions[id].header, idx.functions[id].header))
else:
self.functions[id] = idx.functions[id]
self.identifiers[id] = idx.functions[id]
@@ -273,15 +275,15 @@ class index:
if self.macros.has_key(id):
del self.macros[id]
if self.variables.has_key(id):
- print "variable %s from %s redeclared in %s" % (
- id, self.variables[id].header, idx.variables[id].header)
+ self.warning("variable %s from %s redeclared in %s" % (
+ id, self.variables[id].header, idx.variables[id].header))
else:
self.variables[id] = idx.variables[id]
self.identifiers[id] = idx.variables[id]
for id in idx.structs.keys():
if self.structs.has_key(id):
- print "struct %s from %s redeclared in %s" % (
- id, self.structs[id].header, idx.structs[id].header)
+ self.warning("struct %s from %s redeclared in %s" % (
+ id, self.structs[id].header, idx.structs[id].header))
else:
self.structs[id] = idx.structs[id]
self.identifiers[id] = idx.structs[id]
@@ -294,8 +296,8 @@ class index:
self.identifiers[id] = idx.unions[id]
for id in idx.typedefs.keys():
if self.typedefs.has_key(id):
- print "typedef %s from %s redeclared in %s" % (
- id, self.typedefs[id].header, idx.typedefs[id].header)
+ self.warning("typedef %s from %s redeclared in %s" % (
+ id, self.typedefs[id].header, idx.typedefs[id].header))
else:
self.typedefs[id] = idx.typedefs[id]
self.identifiers[id] = idx.typedefs[id]
@@ -311,15 +313,15 @@ class index:
if self.enums.has_key(id):
continue
if self.macros.has_key(id):
- print "macro %s from %s redeclared in %s" % (
- id, self.macros[id].header, idx.macros[id].header)
+ self.warning("macro %s from %s redeclared in %s" % (
+ id, self.macros[id].header, idx.macros[id].header))
else:
self.macros[id] = idx.macros[id]
self.identifiers[id] = idx.macros[id]
for id in idx.enums.keys():
if self.enums.has_key(id):
- print "enum %s from %s redeclared in %s" % (
- id, self.enums[id].header, idx.enums[id].header)
+ self.warning("enum %s from %s redeclared in %s" % (
+ id, self.enums[id].header, idx.enums[id].header))
else:
self.enums[id] = idx.enums[id]
self.identifiers[id] = idx.enums[id]
@@ -330,10 +332,10 @@ class index:
# check that function condition agrees with header
if idx.functions[id].conditionals != \
self.functions[id].conditionals:
- print "Header condition differs from Function for %s:" \
- % id
- print " H: %s" % self.functions[id].conditionals
- print " C: %s" % idx.functions[id].conditionals
+ self.warning("Header condition differs from Function for %s:" \
+ % id)
+ self.warning(" H: %s" % self.functions[id].conditionals)
+ self.warning(" C: %s" % idx.functions[id].conditionals)
up = idx.functions[id]
self.functions[id].update(None, up.module, up.type, up.info, up.extra)
# else:
@@ -356,12 +358,13 @@ class index:
def analyze(self):
- self.analyze_dict("functions", self.functions)
- self.analyze_dict("variables", self.variables)
- self.analyze_dict("structs", self.structs)
- self.analyze_dict("unions", self.unions)
- self.analyze_dict("typedefs", self.typedefs)
- self.analyze_dict("macros", self.macros)
+ if not quiet:
+ self.analyze_dict("functions", self.functions)
+ self.analyze_dict("variables", self.variables)
+ self.analyze_dict("structs", self.structs)
+ self.analyze_dict("unions", self.unions)
+ self.analyze_dict("typedefs", self.typedefs)
+ self.analyze_dict("macros", self.macros)
class CLexer:
"""A lexer for the C language, tokenize the input by reading and
@@ -621,6 +624,8 @@ class CParser:
info, extra, self.conditionals)
def warning(self, msg):
+ global warnings
+ warnings = warnings + 1
if self.no_error:
return
print msg
@@ -1802,7 +1807,8 @@ class CParser:
return token
def parse(self):
- self.warning("Parsing %s" % (self.filename))
+ if not quiet:
+ print "Parsing %s" % (self.filename)
token = self.token()
while token != None:
if token[0] == 'name':
@@ -1869,7 +1875,8 @@ class docBuilder:
pass
def analyze(self):
- print "Project %s : %d headers, %d modules" % (self.name, len(self.headers.keys()), len(self.modules.keys()))
+ if not quiet:
+ print "Project %s : %d headers, %d modules" % (self.name, len(self.headers.keys()), len(self.modules.keys()))
self.idx.analyze()
def scanHeaders(self):
@@ -1995,7 +2002,7 @@ class docBuilder:
else:
output.write(" <field name='%s' type='%s' info='%s'/>\n" % (field[1] , field[0], desc))
except:
- print "Failed to serialize struct %s" % (name)
+ self.warning("Failed to serialize struct %s" % (name))
output.write(" </struct>\n")
else:
output.write("/>\n");
@@ -2023,7 +2030,7 @@ class docBuilder:
def serialize_function(self, output, name):
id = self.idx.functions[name]
- if name == debugsym:
+ if name == debugsym and not quiet:
print "=>", id
output.write(" <%s name='%s' file='%s' module='%s'>\n" % (id.type,
@@ -2059,7 +2066,7 @@ class docBuilder:
output.write(" <arg name='%s' type='%s' info='%s'/>\n" % (param[1], param[0], escape(param[2])))
self.indexString(name, param[2])
except:
- print "Failed to save function %s info: " % name, `id.info`
+ self.warning("Failed to save function %s info: " % name, `id.info`)
output.write(" </%s>\n" % (id.type))
def serialize_exports(self, output, file):
@@ -2074,7 +2081,7 @@ class docBuilder:
escape(dict.info[data]),
string.lower(data)))
except:
- print "Header %s lacks a %s description" % (module, data)
+ self.warning("Header %s lacks a %s description" % (module, data))
if dict.info.has_key('Description'):
desc = dict.info['Description']
if string.find(desc, "DEPRECATED") != -1:
@@ -2287,7 +2294,8 @@ class docBuilder:
def serialize(self):
filename = "%s/%s-api.xml" % (self.path, self.name)
- print "Saving XML description %s" % (filename)
+ if not quiet:
+ print "Saving XML description %s" % (filename)
output = open(filename, "w")
output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
output.write("<api name='%s'>\n" % self.name)
@@ -2323,7 +2331,8 @@ class docBuilder:
output.close()
filename = "%s/%s-refs.xml" % (self.path, self.name)
- print "Saving XML Cross References %s" % (filename)
+ if not quiet:
+ print "Saving XML Cross References %s" % (filename)
output = open(filename, "w")
output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
output.write("<apirefs name='%s'>\n" % self.name)
@@ -2336,7 +2345,8 @@ def rebuild():
builder = None
srcdir = os.environ["srcdir"]
if glob.glob(srcdir + "/../src/libvirt.c") != [] :
- print "Rebuilding API description for libvirt"
+ if not quiet:
+ print "Rebuilding API description for libvirt"
dirs = [srcdir + "/../src",
srcdir + "/../src/util",
srcdir + "/../include/libvirt"]
@@ -2344,12 +2354,13 @@ def rebuild():
dirs.append("../include/libvirt")
builder = docBuilder("libvirt", srcdir, dirs, [])
elif glob.glob("src/libvirt.c") != [] :
- print "Rebuilding API description for libvirt"
+ if not quiet:
+ print "Rebuilding API description for libvirt"
builder = docBuilder("libvirt", srcdir,
["src", "src/util", "include/libvirt"],
[])
else:
- print "rebuild() failed, unable to guess the module"
+ self.warning("rebuild() failed, unable to guess the module")
return None
builder.scan()
builder.analyze()
@@ -2368,5 +2379,13 @@ if __name__ == "__main__":
if len(sys.argv) > 1:
debug = 1
parse(sys.argv[1])
+ if warnings > 0:
+ sys.exit(2)
+ else:
+ sys.exit(0)
else:
rebuild()
+ if warnings > 0:
+ sys.exit(2)
+ else:
+ sys.exit(0)
diff --git a/python/Makefile.am b/python/Makefile.am
index 0edb3e4..a4c9a6b 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -53,11 +53,11 @@ GENERATED= libvirt-export.c \
libvirt.h \
libvirt.py
-generated.stamp: $(srcdir)/$(GENERATE) $(API_DESC)
- $(PYTHON) $(srcdir)/$(GENERATE) $(PYTHON)
+$(GENERATE).stamp: $(srcdir)/$(GENERATE) $(API_DESC)
+ $(AM_V_GEN)$(PYTHON) $(srcdir)/$(GENERATE) $(PYTHON) && \
touch $@
-$(GENERATED): generated.stamp
+$(GENERATED): $(GENERATE).stamp
$(libvirtmod_la_OBJECTS): $(GENERATED)
diff --git a/python/generator.py b/python/generator.py
index c27ff73..d3a3616 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -11,6 +11,8 @@ import sys
import string
import re
+quiet=1
+
if __name__ == "__main__":
# launched as a script
srcPref = os.path.dirname(sys.argv[0])
@@ -617,7 +619,8 @@ def buildStubs():
sys.exit(1)
n = len(functions.keys())
- print "Found %d functions in libvirt-api.xml" % (n)
+ if not quiet:
+ print "Found %d functions in libvirt-api.xml" % (n)
py_types['pythonObject'] = ('O', "pythonObject", "pythonObject", "pythonObject")
try:
@@ -629,8 +632,8 @@ def buildStubs():
except IOError, msg:
print file, ":", msg
-
- print "Found %d functions in libvirt-override-api.xml" % (
+ if not quiet:
+ print "Found %d functions in libvirt-override-api.xml" % (
len(functions.keys()) - n)
nb_wrap = 0
failed = 0
@@ -662,20 +665,21 @@ def buildStubs():
export.close()
wrapper.close()
- print "Generated %d wrapper functions" % nb_wrap
+ if not quiet:
+ print "Generated %d wrapper functions" % nb_wrap
if unknown_types:
print "Missing type converters: "
for type in unknown_types.keys():
print "%s:%d " % (type, len(unknown_types[type])),
- print
-
for f in functions_failed:
print "ERROR: failed %s" % f
if failed > 0:
return -1
+ if len(unknown_types) > 0:
+ return -1
return 0
#######################################################################
diff --git a/src/Makefile.am b/src/Makefile.am
index 54b1ca0..875a43d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -796,7 +796,7 @@ endif
BUILT_SOURCES += $(ESX_DRIVER_GENERATED)
$(ESX_DRIVER_GENERATED): $(srcdir)/esx/esx_vi_generator.input $(srcdir)/esx/esx_vi_generator.py
- -srcdir=$(srcdir) $(srcdir)/esx/esx_vi_generator.py
+ $(AM_V_GEN)srcdir=$(srcdir) $(srcdir)/esx/esx_vi_generator.py
if WITH_ESX
if WITH_DRIVER_MODULES
--
1.7.6
13 years, 4 months
[libvirt] [PATCH] tests: Fix virshtest failure after dominfo changed
by Osier Yang
Caused by the new changed "dominfo" command. Pushed under trival
rule.
---
tests/virshtest.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/tests/virshtest.c b/tests/virshtest.c
index 0932efd..e22e582 100644
--- a/tests/virshtest.c
+++ b/tests/virshtest.c
@@ -22,6 +22,7 @@ Max memory: 261072 kB\n\
Used memory: 131072 kB\n\
Persistent: yes\n\
Autostart: disable\n\
+Managed save: unknown\n\
\n";
static const char *domuuid_fc4 = DOM_UUID "\n\n";
static const char *domid_fc4 = "2\n\n";
--
1.7.6
13 years, 4 months
[libvirt] [PATCH v2] util: avoid fds leak when virEventPollAddHandle fail
by ajia@redhat.com
* src/util/event_poll.c: only fix file descriptors leak on when
virEventPollAddHandle fail on virEventPollInit function.
Detected in valgrind run:
==1254==
==1254== FILE DESCRIPTORS: 6 open at exit.
==1254== Open file descriptor 5:
==1254== at 0x30736D9D47: pipe2 (syscall-template.S:82)
==1254== by 0x4DD6267: rpl_pipe2 (pipe2.c:61)
==1254== by 0x4C4C1C5: virEventPollInit (event_poll.c:648)
==1254== by 0x4C4AA94: virEventRegisterDefaultImpl (event.c:208)
==1254== by 0x42150C: main (virsh.c:13790)
==1254==
==1254== Open file descriptor 4:
==1254== at 0x30736D9D47: pipe2 (syscall-template.S:82)
==1254== by 0x4DD6267: rpl_pipe2 (pipe2.c:61)
==1254== by 0x4C4C1C5: virEventPollInit (event_poll.c:648)
==1254== by 0x4C4AA94: virEventRegisterDefaultImpl (event.c:208)
==1254== by 0x42150C: main (virsh.c:13790)
==1254==
* how to reproduce?
% valgrind -v --track-fds=yes virsh list
---
src/util/event_poll.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/src/util/event_poll.c b/src/util/event_poll.c
index 285ba50..e2ae3a6 100644
--- a/src/util/event_poll.c
+++ b/src/util/event_poll.c
@@ -36,6 +36,7 @@
#include "event_poll.h"
#include "memory.h"
#include "util.h"
+#include "files.h"
#include "ignore-value.h"
#include "virterror_internal.h"
@@ -657,6 +658,8 @@ int virEventPollInit(void)
virEventError(VIR_ERR_INTERNAL_ERROR,
_("Unable to add handle %d to event loop"),
eventLoop.wakeupfd[0]);
+ VIR_FORCE_CLOSE(eventLoop.wakeupfd[0]);
+ VIR_FORCE_CLOSE(eventLoop.wakeupfd[1]);
return -1;
}
--
1.7.1
13 years, 4 months
Re: [libvirt] [libvirt-users] cannot perform tunnelled migration without using peer2peer flag
by Eric Blake
On 07/18/2011 04:11 AM, Osier Yang wrote:
> 于 2011年07月18日 10:07, zhang xintao 写道:
>> Dear All
>> I try to migration a kvm guest os to another host failed
>> server: ubuntu 11.04 server
>> virsh:migrate --live --tunnelled vm1 qemu+ssh://192.168.10.3/system
>> error:Requested operation is not valid:cannot perform
>> tunnelled migration without using peer2peer flag
>
> The error tells you all, you need to use "--p2p".
That said, why can't virsh be smarter, and automatically request the
right underlying flags without making the user also type --p2p? Any
problems with this patch?
From db318d41c2a70189c21303c824aa4a862815874a Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake(a)redhat.com>
Date: Mon, 18 Jul 2011 13:10:29 -0600
Subject: [PATCH] virsh: make migrate --tunnelled imply --p2p
We can make the virsh migrate UI friendlier by supplying the
missing bit automatically instead of erroring out when requesting
--tunnelled without --p2p.
* tools/virsh.c (doMigrate): Make --p2p optional when using
--tunnelled.
* tools/virsh.pod (migrate): Tweak wording accordingly.
---
tools/virsh.c | 2 +-
tools/virsh.pod | 5 +++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 6c8032f..05aeb6c 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -4475,7 +4475,7 @@ doMigrate (void *opaque)
if (vshCommandOptBool (cmd, "p2p"))
flags |= VIR_MIGRATE_PEER2PEER;
if (vshCommandOptBool (cmd, "tunnelled"))
- flags |= VIR_MIGRATE_TUNNELLED;
+ flags |= VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER;
if (vshCommandOptBool (cmd, "persistent"))
flags |= VIR_MIGRATE_PERSIST_DEST;
diff --git a/tools/virsh.pod b/tools/virsh.pod
index e156232..e0adc31 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -534,14 +534,15 @@ Provide the maximum number of virtual CPUs
supported for a guest VM on
this connection. If provided, the I<type> parameter must be a valid
type attribute for the <domain> element of XML.
-=item B<migrate> [I<--live>] [I<--direct>] [I<--p2p> [I<--tunnelled>]]
+=item B<migrate> [I<--live>] [I<--direct>] [I<--p2p>] [I<--tunnelled>]
[I<--persistent>] [I<--undefinesource>] [I<--suspend>]
[I<--copy-storage-all>]
[I<--copy-storage-inc>] [I<--verbose>] I<domain-id> I<desturi>
[I<migrateuri>]
[I<dname>] [I<--timeout> B<seconds>]
Migrate domain to another host. Add I<--live> for live migration;
I<--p2p>
for peer-2-peer migration; I<--direct> for direct migration; or
I<--tunnelled>
-for tunnelled migration. I<--persistent> leaves the domain persistent on
+for tunnelled migration (I<--tunnelled> implies I<--p2p>). I<--persistent>
+leaves the domain persistent on
destination host, I<--undefinesource> undefines the domain on the
source host,
and I<--suspend> leaves the domain paused on the destination host.
I<--copy-storage-all> indicates migration with non-shared storage with
full
--
1.7.4.4
--
Eric Blake eblake(a)redhat.com +1-801-349-2682
Libvirt virtualization library http://libvirt.org
13 years, 4 months
[libvirt] [PATCH] rpc: Make the dispatch generator handle 'void name(void)' style procedures
by Matthias Bolte
Currently there are no such procedures in the protocol, but programming
errors like a missing _args or _ret suffix on the structs in the .x files
can create such a situation by accident. Making the generator aware of
this avoids bogus errors from the generator such as:
Use of uninitialized value in exists at ./rpc/gendispatch.pl line 967.
Reported by Michal Privoznik
---
src/rpc/gendispatch.pl | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index e068b53..e6a4a1c 100755
--- a/src/rpc/gendispatch.pl
+++ b/src/rpc/gendispatch.pl
@@ -143,6 +143,20 @@ while (<PROTOCOL>) {
$flags = $3;
$ProcName = name_to_ProcName ($name);
+ if (!exists $calls{$name}) {
+ # that the argument and return value cases have not yet added
+ # this procedure to the calls hash means that it has no arguments
+ # and no return value. add it to the calls hash now because all
+ # procedures have to be listed in the calls hash
+ $calls{$name} = {
+ name => $name,
+ ProcName => $ProcName,
+ UC_NAME => uc $name,
+ args => "void",
+ ret => "void"
+ }
+ }
+
if ($opt_b or $opt_k) {
if (!($flags =~ m/^\s*\/\*\s*(\S+)\s+(\S+)\s*(.*)\*\/\s*$/)) {
die "invalid generator flags for ${procprefix}_PROC_${name}"
--
1.7.4.1
13 years, 4 months
[libvirt] [PATCH] util: avoid fds leak on virEventPollInit
by ajia@redhat.com
* src/util/event_poll.c: fix file descriptors leak on virEventPollInit.
Detected in valgrind run:
==1254==
==1254== FILE DESCRIPTORS: 6 open at exit.
==1254== Open file descriptor 5:
==1254== at 0x30736D9D47: pipe2 (syscall-template.S:82)
==1254== by 0x4DD6267: rpl_pipe2 (pipe2.c:61)
==1254== by 0x4C4C1C5: virEventPollInit (event_poll.c:648)
==1254== by 0x4C4AA94: virEventRegisterDefaultImpl (event.c:208)
==1254== by 0x42150C: main (virsh.c:13790)
==1254==
==1254== Open file descriptor 4:
==1254== at 0x30736D9D47: pipe2 (syscall-template.S:82)
==1254== by 0x4DD6267: rpl_pipe2 (pipe2.c:61)
==1254== by 0x4C4C1C5: virEventPollInit (event_poll.c:648)
==1254== by 0x4C4AA94: virEventRegisterDefaultImpl (event.c:208)
==1254== by 0x42150C: main (virsh.c:13790)
==1254==
* how to reproduce?
% valgrind -v --track-fds=yes virsh list
---
src/util/event_poll.c | 13 ++++++++++---
1 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/util/event_poll.c b/src/util/event_poll.c
index 285ba50..1e4ef96 100644
--- a/src/util/event_poll.c
+++ b/src/util/event_poll.c
@@ -639,6 +639,8 @@ static void virEventPollHandleWakeup(int watch ATTRIBUTE_UNUSED,
int virEventPollInit(void)
{
+ int ret = -1;
+
if (virMutexInit(&eventLoop.lock) < 0) {
virReportSystemError(errno, "%s",
_("Unable to initialize mutex"));
@@ -648,7 +650,7 @@ int virEventPollInit(void)
if (pipe2(eventLoop.wakeupfd, O_CLOEXEC | O_NONBLOCK) < 0) {
virReportSystemError(errno, "%s",
_("Unable to setup wakeup pipe"));
- return -1;
+ goto cleanup;
}
if (virEventPollAddHandle(eventLoop.wakeupfd[0],
@@ -657,10 +659,15 @@ int virEventPollInit(void)
virEventError(VIR_ERR_INTERNAL_ERROR,
_("Unable to add handle %d to event loop"),
eventLoop.wakeupfd[0]);
- return -1;
+ goto cleanup;
}
- return 0;
+ ret = 0;
+
+cleanup:
+ close(eventLoop.wakeupfd[0]);
+ close(eventLoop.wakeupfd[1]);
+ return ret;
}
static int virEventPollInterruptLocked(void)
--
1.7.1
13 years, 4 months
[libvirt] [PATCH v3] util: avoid fds leak when virEventPollAddHandle fail
by ajia@redhat.com
* src/util/event_poll.c: avoid file descriptors leak when
virEventPollAddHandle fail on virEventPollInit function.
---
src/util/event_poll.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/src/util/event_poll.c b/src/util/event_poll.c
index 285ba50..e2ae3a6 100644
--- a/src/util/event_poll.c
+++ b/src/util/event_poll.c
@@ -36,6 +36,7 @@
#include "event_poll.h"
#include "memory.h"
#include "util.h"
+#include "files.h"
#include "ignore-value.h"
#include "virterror_internal.h"
@@ -657,6 +658,8 @@ int virEventPollInit(void)
virEventError(VIR_ERR_INTERNAL_ERROR,
_("Unable to add handle %d to event loop"),
eventLoop.wakeupfd[0]);
+ VIR_FORCE_CLOSE(eventLoop.wakeupfd[0]);
+ VIR_FORCE_CLOSE(eventLoop.wakeupfd[1]);
return -1;
}
--
1.7.1
13 years, 4 months
[libvirt] [PATCH] interface: Check for interface (in-)activity on some operations
by Michal Privoznik
Right now it is possible to undefine an active interface, or
destroy inactive. This patch add some checking to these operations
to prevent this. Also fix test driver.
---
src/interface/netcf_driver.c | 83 ++++++++++++++++++++++++++++++++++++------
src/test/test_driver.c | 5 +++
2 files changed, 76 insertions(+), 12 deletions(-)
diff --git a/src/interface/netcf_driver.c b/src/interface/netcf_driver.c
index 855b5a3..bf590f3 100644
--- a/src/interface/netcf_driver.c
+++ b/src/interface/netcf_driver.c
@@ -119,6 +119,40 @@ static struct netcf_if *interfaceDriverGetNetcfIF(struct netcf *ncf, virInterfac
return iface;
}
+/*
+ * interfaceObjIsActive:
+ * @iface - interface
+ *
+ * Caller MUST have driver locked to prevent race condition.
+ * Returns:
+ * -1 on error
+ * 0 on inactive interface
+ * 1 on active interface
+ */
+static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+interfaceObjIsActive(struct interface_driver *driver,
+ struct netcf_if *iface,
+ virInterfacePtr ifinfo)
+{
+ int ret = -1;
+ unsigned int flags = 0;
+
+ if (ncf_if_status(iface, &flags) < 0) {
+ 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: %s%s%s"),
+ ifinfo->name, errmsg, details ? " - " : "",
+ details ? details : "");
+ goto cleanup;
+ }
+
+ ret = flags & NETCF_IFACE_ACTIVE ? 1 : 0;
+
+cleanup:
+ return ret;
+}
+
static virDrvOpenStatus interfaceOpenInterface(virConnectPtr conn,
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
unsigned int flags)
@@ -438,6 +472,7 @@ static int interfaceUndefine(virInterfacePtr ifinfo) {
struct interface_driver *driver = ifinfo->conn->interfacePrivateData;
struct netcf_if *iface = NULL;
int ret = -1;
+ int active;
interfaceDriverLock(driver);
@@ -447,6 +482,17 @@ static int interfaceUndefine(virInterfacePtr ifinfo) {
goto cleanup;
}
+ active = interfaceObjIsActive(driver, iface, ifinfo);
+ if (active < 0) {
+ /* helper already reported error */
+ goto cleanup;
+ } else if (active) {
+ interfaceReportError(VIR_ERR_OPERATION_INVALID,
+ _("interface %s is active"),
+ ifinfo->name);
+ goto cleanup;
+ }
+
ret = ncf_if_undefine(iface);
if (ret < 0) {
const char *errmsg, *details;
@@ -470,6 +516,7 @@ static int interfaceCreate(virInterfacePtr ifinfo,
struct interface_driver *driver = ifinfo->conn->interfacePrivateData;
struct netcf_if *iface = NULL;
int ret = -1;
+ int active;
virCheckFlags(0, -1);
@@ -481,6 +528,17 @@ static int interfaceCreate(virInterfacePtr ifinfo,
goto cleanup;
}
+ active = interfaceObjIsActive(driver, iface, ifinfo);
+ if (active < 0) {
+ /* helper already reported error */
+ goto cleanup;
+ } else if (active) {
+ interfaceReportError(VIR_ERR_OPERATION_INVALID,
+ _("interface %s is already active"),
+ ifinfo->name);
+ goto cleanup;
+ }
+
ret = ncf_if_up(iface);
if (ret < 0) {
const char *errmsg, *details;
@@ -504,6 +562,7 @@ static int interfaceDestroy(virInterfacePtr ifinfo,
struct interface_driver *driver = ifinfo->conn->interfacePrivateData;
struct netcf_if *iface = NULL;
int ret = -1;
+ int active;
virCheckFlags(0, -1);
@@ -515,6 +574,17 @@ static int interfaceDestroy(virInterfacePtr ifinfo,
goto cleanup;
}
+ active = interfaceObjIsActive(driver, iface, ifinfo);
+ if (active < 0) {
+ /* helper already reported error */
+ goto cleanup;
+ } else if (!active) {
+ interfaceReportError(VIR_ERR_OPERATION_INVALID,
+ _("interface %s is not active"),
+ ifinfo->name);
+ goto cleanup;
+ }
+
ret = ncf_if_down(iface);
if (ret < 0) {
const char *errmsg, *details;
@@ -536,7 +606,6 @@ static int interfaceIsActive(virInterfacePtr ifinfo)
{
struct interface_driver *driver = ifinfo->conn->interfacePrivateData;
struct netcf_if *iface = NULL;
- unsigned int flags = 0;
int ret = -1;
interfaceDriverLock(driver);
@@ -547,17 +616,7 @@ static int interfaceIsActive(virInterfacePtr ifinfo)
goto cleanup;
}
- if (ncf_if_status(iface, &flags) < 0) {
- 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: %s%s%s"),
- ifinfo->name, errmsg, details ? " - " : "",
- details ? details : "");
- goto cleanup;
- }
-
- ret = flags & NETCF_IFACE_ACTIVE ? 1 : 0;
+ ret = interfaceObjIsActive(driver, iface, ifinfo);
cleanup:
ncf_if_free(iface);
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index f3fb320..d165586 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -3648,6 +3648,11 @@ static int testInterfaceUndefine(virInterfacePtr iface)
goto cleanup;
}
+ if (privinterface->active != 0) {
+ testError(VIR_ERR_OPERATION_INVALID, NULL);
+ goto cleanup;
+ }
+
virInterfaceRemove(&privconn->ifaces,
privinterface);
ret = 0;
--
1.7.5.rc3
13 years, 4 months