Re: [libvirt] [RFC 0/5]: QMP: add balloon-get-memory-stats command
by Eric Blake
On 01/19/2012 08:56 AM, Luiz Capitulino wrote:
> Long ago, commit 625a5be added the guest provided memory statistics to
> the query-balloon command. Unfortunately, it also introduced a severe
> bug: query-balloon would hang if the guest didn't respond. This, in turn,
> would also cause a hang in libvirt.
>
> Because of that, we decided to disable the guest memory stats feature
> (commit 11724ff).
>
> As we decided to let commands implement ad-hoc async mechanisms until we
> get a proper way to do it, I decided to try to re-enable that feature.
>
> My idea is to have a command and an event. The command gets the process
> started by sending a request to guest and returns. Later, when the guest
> makes the memory stats info available, it's sent to the client by means
> of an QMP event (please, take a look at patch 05/05 for full details).
>
> I'm not sure if that approach is good for libvirt though, so it would be
> very helpful to get their input (Eric, I'm CC'ing you here, but feel free
> to route this to someone else).
[I went ahead and cc'd the libvirt list]
Yes, libvirt can live with this approach. And having this in parallel
to a qemu-ga verb is nice, since, as it was pointed out, this would
allow interaction with guests that have a balloon device but not a guest
agent.
You may want to read this thread [1], for thoughts on the impact of
making another existing blocking command be extended into one that
starts an async event and ends when an event is raised; libvirt can
expose both a blocking and an asynchronous implementation to the user on
top of the qemu model being just asynchronous.
[1] https://www.redhat.com/archives/libvir-list/2012-January/msg00562.html
Thinking aloud - do we need a means to poll the state of the
balloon-stat query? On the one hand, if libvirtd issues the start
command, then gets stopped, then the event occurs, then libvirtd is
restarted, then libvirt won't know that the event was missed. On the
other hand, since this involves guest interaction, libvirt already has
to assume that the guest may be malicious and refuse to report stats
and/or report invalid stats, so libvirt would already have to be
prepared to give up if no event has arrived in a fixed amount of time,
and that also means that restarting libvirtd can just ignore any balloon
query that was in flight before the restart.
So I guess I'm okay with just a start and an event, with no poll of the
last-known guest response. But it does mean that qemu has to gracefully
handle if libvirt makes two start requests in a row without any
intervening events, and conversely that libvirt has to be prepared for
an event that happens even when libvirt doesn't remember triggering the
start command.
> Another interesting point is that, there's another way of doing this and
> it's using qemu-ga instead. That's, qemu-ga could read that information
> from proc and return it. This is easier & simpler, as it doesn't involve
> guest communication. We also could return a lot more information if needed.
> The only disadvantage I can see is the dependency on qemu-ga...
Most likely, we would want to teach libvirt to use both methods, and
give the choice to the user on which approach to use when the guest
supports both.
--
Eric Blake eblake(a)redhat.com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
13 years, 5 months
[libvirt] [test-API][PATCH 1/2] Fix compatibility problem on python 2.4
by Wayne Sun
* switch rpartition with rsplit
* adjust the style
---
generator.py | 15 +++++++++++----
1 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/generator.py b/generator.py
index 9a2ed06..6108963 100644
--- a/generator.py
+++ b/generator.py
@@ -124,10 +124,14 @@ class FuncGen(object):
for i in range(loop_number):
case_ref_name = self.cases_ref_names[i]
- pkg_casename = case_ref_name.rpartition(":")[0]
- funcname = case_ref_name.rpartition(":")[-1]
+ pkg_casename = case_ref_name.rsplit(":", 1)[0]
+ funcname = case_ref_name.rsplit(":", 1)[-1]
+
+ if "_clean" not in funcname:
+ cleanoper = 0
+ else:
+ cleanoper = 1
- cleanoper = 0 if "_clean" not in funcname else 1
if not cleanoper:
self.fmt.print_start(pkg_casename, env_logger)
@@ -182,7 +186,10 @@ class FuncGen(object):
if not cleanoper:
self.fmt.print_end(pkg_casename, ret, env_logger)
else:
- self.fmt.print_string(21*" " + "Done" if clean_ret < 1 else 21*" " + "Fail", env_logger)
+ if clean_ret < 1:
+ self.fmt.print_string(21*" " + "Done", env_logger)
+ else:
+ self.fmt.print_string(21*" " + "Fail", env_logger)
end_time = time.strftime("%Y-%m-%d %H:%M:%S")
--
1.7.1
13 years, 5 months
[libvirt] [PATCHv2 0/6] various cleanups
by Eric Blake
I think I've posted all of these before, but with no reviews yet.
Eric Blake (6):
threads: check for failure to set thread-local value
build: silence some compiler warnings from gnulib
lxc: use live/config helper
util: add new file for virTypedParameter utils
util: use new virTypedParameter helpers
error: drop old-style error reporting
daemon/remote.c | 1 +
m4/virt-compile-warnings.m4 | 7 +-
po/POTFILES.in | 1 +
src/Makefile.am | 1 +
src/esx/esx_driver.c | 81 +++---
src/libvirt_private.syms | 21 +-
src/libxl/libxl_driver.c | 44 +--
src/lxc/lxc_driver.c | 370 ++++++-----------------
src/qemu/qemu_driver.c | 656 +++++++++++++----------------------------
src/test/test_driver.c | 27 +-
src/util/conf.c | 22 +-
src/util/threads-pthread.c | 14 +-
src/util/threads-win32.c | 9 +-
src/util/threads.h | 2 +-
src/util/util.c | 16 +-
src/util/util.h | 4 +-
src/util/virterror.c | 7 +-
src/util/virterror_internal.h | 8 -
src/util/virtypedparam.c | 187 ++++++++++++
src/util/virtypedparam.h | 37 +++
src/xen/xen_hypervisor.c | 215 ++++++--------
tools/virsh.c | 1 +
22 files changed, 721 insertions(+), 1010 deletions(-)
create mode 100644 src/util/virtypedparam.c
create mode 100644 src/util/virtypedparam.h
--
1.7.7.5
13 years, 5 months
[libvirt] Hidden symbols
by Shradha Shah
Hello All,
When using a systemtap to get a call chain of functions that are executed during the migration of a vm from one host to another I realised that many of the symbols in libvirt are hidden and not visible to systemtap.
Is there a way I can make all the symbols visible just for debugging purposes?
Many Thanks,
Regards,
Shradha Shah
13 years, 5 months
[libvirt] [libvirt-glib 1/4] Refactor gvir_config_object_delete_child
by Christophe Fergeau
By changing gvir_config_xml_foreach_child to make it robust against
current node deletion in the "foreach" callback, we can use
gvir_config_object_foreach_child to implement
gvir_config_object_delete_child
---
libvirt-gconfig/libvirt-gconfig-helpers.c | 5 +++-
libvirt-gconfig/libvirt-gconfig-object.c | 32 ++++++++++++++++++----------
2 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/libvirt-gconfig/libvirt-gconfig-helpers.c b/libvirt-gconfig/libvirt-gconfig-helpers.c
index cc2e5cc..c406a49 100644
--- a/libvirt-gconfig/libvirt-gconfig-helpers.c
+++ b/libvirt-gconfig/libvirt-gconfig-helpers.c
@@ -169,14 +169,17 @@ void gvir_config_xml_foreach_child(xmlNodePtr node,
g_return_if_fail(iter_func != NULL);
- for (it = node->children; it != NULL; it = it->next) {
+ it = node->children;
+ while (it != NULL) {
gboolean cont;
+ xmlNodePtr next = it->next;
if (xmlIsBlankNode(it))
continue;
cont = iter_func(it, opaque);
if (!cont)
break;
+ it = next;
}
}
diff --git a/libvirt-gconfig/libvirt-gconfig-object.c b/libvirt-gconfig/libvirt-gconfig-object.c
index 5645490..7fb8b69 100644
--- a/libvirt-gconfig/libvirt-gconfig-object.c
+++ b/libvirt-gconfig/libvirt-gconfig-object.c
@@ -465,27 +465,35 @@ gvir_config_object_replace_child_with_attribute(GVirConfigObject *object,
g_object_unref(G_OBJECT(child));
}
+static gboolean maybe_unlink_node(xmlNodePtr node, const char *name)
+{
+ if (g_strcmp0((char *)node->name, name) == 0) {
+ xmlUnlinkNode(node);
+ xmlFreeNode(node);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean remove_oneshot(xmlNodePtr node, gpointer opaque)
+{
+ return !maybe_unlink_node(node, opaque);
+}
+
G_GNUC_INTERNAL void
gvir_config_object_delete_child(GVirConfigObject *object,
const char *child_name)
{
- xmlNodePtr parent_node;
- xmlNodePtr old_node;
-
g_return_if_fail(GVIR_CONFIG_IS_OBJECT(object));
g_return_if_fail(child_name != NULL);
- parent_node = gvir_config_object_get_xml_node(GVIR_CONFIG_OBJECT(object));
- g_return_if_fail(parent_node != NULL);
+ gvir_config_object_foreach_child(object, NULL, remove_oneshot,
+ (gpointer)child_name);
+}
- if (!(old_node = gvir_config_xml_get_element(parent_node, child_name, NULL)))
- return;
- /* FIXME: should we make sure there are no multiple occurrences
- * of this node?
- */
- xmlUnlinkNode(old_node);
- xmlFreeNode(old_node);
}
--
1.7.7.5
13 years, 5 months
[libvirt] pibvirt php help
by punit gupta
sir
i am trying to create ssh connention and i am able to connect with out
password from terminal using
virsh -c qemu+ssh://punit@192.168.102.133/system
but this is not working with libvirt-php binding
error :for libvirt-php ssh connection
"Libvirt last error: cannot recv data: Resource temporarily unavailable"
my php code is
<?php
$res1=libvirt_connect("qemu+ssh://punit@192.168.102.133/system",false);
print_r($res1); printf ("\n");
if ($res1==false)
{
echo ("Libvirt last error: ".libvirt_get_last_error());
}
?>
--
Punit Gupta
M-Tect (jiit noida)
13 years, 5 months
[libvirt] can not get screen shot using libvirt-php
by punit gupta
sir
i am able to connect to local system an gett all the parameters but i am
not able to get screen shots
it gives error
"Cannot find gvnccapture binary"
--
Punit Gupta
M-Tect (jiit noida)
13 years, 5 months
[libvirt] [PATCH] Fix rpc generator to anchor matches for method names
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
The RPC generator transforms methods matching certain
patterns like 'id' or 'uuid', etc but does not anchor
its matches to the end of the word. So if a method
contains 'id' in the middle (eg virIdentity) then the
RPC generator munges that.
* src/rpc/gendispatch.pl: Anchor matches
---
src/rpc/gendispatch.pl | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index b36ca69..0460fca 100755
--- a/src/rpc/gendispatch.pl
+++ b/src/rpc/gendispatch.pl
@@ -34,10 +34,10 @@ sub name_to_ProcName {
my $name = shift;
my @elems = split /_/, $name;
@elems = map ucfirst, @elems;
- @elems = map { $_ =~ s/Nwfilter/NWFilter/; $_ =~ s/Xml/XML/;
- $_ =~ s/Uri/URI/; $_ =~ s/Uuid/UUID/; $_ =~ s/Id/ID/;
- $_ =~ s/Mac/MAC/; $_ =~ s/Cpu/CPU/; $_ =~ s/Os/OS/;
- $_ =~ s/Nmi/NMI/; $_ } @elems;
+ @elems = map { $_ =~ s/Nwfilter/NWFilter/; $_ =~ s/Xml$/XML/;
+ $_ =~ s/Uri$/URI/; $_ =~ s/Uuid$/UUID/; $_ =~ s/Id$/ID/;
+ $_ =~ s/Mac$/MAC/; $_ =~ s/Cpu$/CPU/; $_ =~ s/Os$/OS/;
+ $_ =~ s/Nmi$/NMI/; $_ } @elems;
join "", @elems
}
--
1.7.7.5
13 years, 5 months
[libvirt] [PATCH 0/4] Misc patches to support RBAC work
by Daniel P. Berrange
The following patches aren't really needed on their own, rather
they are part of the role based access control work I'm doing.
In order to keep my patch queue small, I'm sending these out
now, since there is no harm in merging them
13 years, 5 months
[libvirt] [PATCH] errors: Improve error reporting to log multiple errors instead of just the last one
by Michal Novotny
This patch introduces a new structure called virErrorsPtr which can get all
the errors that occurred since the connection open. The error callback function
is being used as many times as necessary. The new public function called
virGetAllErrors() has been introduced to get all the errors that occurred.
Also, a new test called errorreport has been written to test the functionality
of error logging for multiple error occurrences.
Signed-off-by: Michal Novotny <minovotn(a)redhat.com>
---
include/libvirt/virterror.h | 14 ++++++
python/generator.py | 1 +
src/util/virterror.c | 99 ++++++++++++++++++++++++++++++++++++----
src/util/virterror_internal.h | 1 +
tests/Makefile.am | 9 +++-
tests/errorreport.c | 74 ++++++++++++++++++++++++++++++
6 files changed, 186 insertions(+), 12 deletions(-)
create mode 100644 tests/errorreport.c
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index e896d67..c7a8018 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -118,6 +118,19 @@ struct _virError {
see note above */
};
+/*
+ * virErrors:
+ *
+ * A libvirt Errors array instance
+ */
+typedef struct _virErrors virErrors;
+typedef virErrors *virErrorsPtr;
+struct _virErrors {
+ virErrorPtr lastError;
+ unsigned int nerrors;
+ virErrorPtr errors;
+};
+
/**
* virErrorNumber:
*
@@ -261,6 +274,7 @@ typedef void (*virErrorFunc) (void *userData, virErrorPtr error);
*/
virErrorPtr virGetLastError (void);
+virErrorsPtr virGetAllErrors (void);
virErrorPtr virSaveLastError (void);
void virResetLastError (void);
void virResetError (virErrorPtr err);
diff --git a/python/generator.py b/python/generator.py
index 6fee3a4..315eb51 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -356,6 +356,7 @@ skip_impl = (
'virDomainSnapshotListChildrenNames',
'virConnGetLastError',
'virGetLastError',
+ 'virGetAllErrors',
'virDomainGetInfo',
'virDomainGetState',
'virDomainGetControlInfo',
diff --git a/src/util/virterror.c b/src/util/virterror.c
index 380dc56..b03ae7c 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -190,11 +190,17 @@ static const char *virErrorDomainName(virErrorDomain domain) {
static void
virLastErrFreeData(void *data)
{
- virErrorPtr err = data;
- if (!err)
+ virErrorsPtr errs = data;
+ if (!errs)
return;
- virResetError(err);
- VIR_FREE(err);
+
+ if (errs->lastError) {
+ virResetError(errs->lastError);
+ VIR_FREE(errs->lastError);
+ }
+ if (errs->errors)
+ VIR_FREE(errs->errors);
+ VIR_FREE(errs);
}
@@ -262,14 +268,18 @@ virCopyError(virErrorPtr from,
static virErrorPtr
virLastErrorObject(void)
{
- virErrorPtr err;
- err = virThreadLocalGet(&virLastErr);
- if (!err) {
- if (VIR_ALLOC(err) < 0)
+ virErrorsPtr errs = NULL;
+
+ errs = virThreadLocalGet(&virLastErr);
+ if (!errs) {
+ if (VIR_ALLOC(errs) < 0)
+ return NULL;
+ if (VIR_ALLOC(errs->lastError) < 0)
return NULL;
- virThreadLocalSet(&virLastErr, err);
+ virThreadLocalSet(&virLastErr, errs);
}
- return err;
+
+ return errs->lastError;
}
@@ -292,6 +302,27 @@ virGetLastError(void)
return err;
}
+/*
+ * virGetAllErrors:
+ *
+ * Provide a pointer to all errors caught at the library level
+ *
+ * The error object is kept in thread local storage, so separate
+ * threads can safely access this concurrently.
+ *
+ * Returns a pointer to all errors caught or NULL if none occurred.
+ */
+virErrorsPtr
+virGetAllErrors(void)
+{
+ virErrorsPtr errs;
+
+ errs = virThreadLocalGet(&virLastErr);
+ if (!errs || errs->nerrors == 0)
+ return NULL;
+ return errs;
+}
+
/**
* virSetError:
* @newerr: previously saved error object
@@ -316,11 +347,56 @@ virSetError(virErrorPtr newerr)
virResetError(err);
ret = virCopyError(newerr, err);
+
+ /* Add error into the error array */
+ virAddError(newerr);
cleanup:
errno = saved_errno;
return ret;
}
+/*
+ * virAddError:
+ * @err: error pointer
+ *
+ * Add the error to the array of error pointer
+ */
+void
+virAddError(virErrorPtr err)
+{
+ virErrorsPtr errs;
+
+ /* Discard all error codes that mean 'no error' */
+ if (!err || err->code == VIR_ERR_OK)
+ return;
+
+ errs = virThreadLocalGet(&virLastErr);
+
+ /* Shouldn't happen but doesn't hurt to check */
+ if (!errs)
+ return;
+
+ if (errs->errors == NULL) {
+ if (VIR_ALLOC(errs->errors) < 0)
+ return;
+ errs->nerrors = 0;
+ }
+ else {
+ if (VIR_REALLOC_N(errs->errors, errs->nerrors + 1) < 0)
+ return;
+ }
+
+ /* Insert data into errors array element */
+ errs->errors[errs->nerrors].domain = err->domain;
+ errs->errors[errs->nerrors].code = err->code;
+ errs->errors[errs->nerrors].message = strdup(err->message);
+ errs->errors[errs->nerrors].level = err->level;
+ errs->errors[errs->nerrors].int1 = err->int1;
+ errs->errors[errs->nerrors].int2 = err->int2;
+
+ errs->nerrors++;
+}
+
/**
* virCopyLastError:
* @to: target to receive the copy
@@ -730,6 +806,9 @@ virRaiseErrorFull(const char *filename ATTRIBUTE_UNUSED,
to->int1 = int1;
to->int2 = int2;
+ /* Add error into the error array */
+ virAddError(to);
+
/*
* Hook up the error or warning to the logging facility
* XXXX should we include filename as 'category' instead of domain name ?
diff --git a/src/util/virterror_internal.h b/src/util/virterror_internal.h
index d61ea0d..b26aec2 100644
--- a/src/util/virterror_internal.h
+++ b/src/util/virterror_internal.h
@@ -86,6 +86,7 @@ void virReportOOMErrorFull(int domcode,
int virSetError(virErrorPtr newerr);
+void virAddError(virErrorPtr err);
void virDispatchError(virConnectPtr conn);
const char *virStrerror(int theerrno, char *errBuf, size_t errBufLen);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f3b0c09..f15c915 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -97,7 +97,7 @@ check_PROGRAMS = virshtest conftest sockettest \
commandtest commandhelper seclabeltest \
hashtest virnetmessagetest virnetsockettest ssh \
utiltest virnettlscontexttest shunloadtest \
- virtimetest
+ virtimetest errorreport
check_LTLIBRARIES = libshunload.la
@@ -221,6 +221,7 @@ TESTS = virshtest \
virtimetest \
shunloadtest \
utiltest \
+ errorreport \
$(test_scripts)
if HAVE_YAJL
@@ -321,6 +322,10 @@ xencapstest_SOURCES = \
xencapstest.c testutils.h testutils.c
xencapstest_LDADD = ../src/libvirt_driver_xen.la $(LDADDS)
+errorreport_SOURCES = \
+ errorreport.c testutils.h testutils.c
+errorreport_LDADD = $(LDADDS)
+
reconnect_SOURCES = \
reconnect.c testutils.h testutils.c
reconnect_LDADD = $(LDADDS)
@@ -331,7 +336,7 @@ statstest_LDADD = ../src/libvirt_driver_xen.la $(LDADDS)
else
EXTRA_DIST += xml2sexprtest.c sexpr2xmltest.c xmconfigtest.c \
- xencapstest.c reconnect.c \
+ xencapstest.c reconnect.c errorreport.c \
testutilsxen.c testutilsxen.h
endif
diff --git a/tests/errorreport.c b/tests/errorreport.c
new file mode 100644
index 0000000..cbe84dd
--- /dev/null
+++ b/tests/errorreport.c
@@ -0,0 +1,74 @@
+#define BOGUS_NAME "SomeBogusDomainName"
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "internal.h"
+#include "testutils.h"
+#include "command.h"
+
+/*
+ * malloc/realloc function used in this code since I was unable to use
+ * VIR_[RE]ALLOC[_N] functions as the compilation failed
+ */
+
+int numErrors = 0;
+int *myErrorCodes = NULL;
+
+static void errorHandler(void *userData ATTRIBUTE_UNUSED,
+ virErrorPtr error) {
+ myErrorCodes = (int *)realloc( myErrorCodes, (numErrors + 1) * sizeof(int));
+
+ myErrorCodes[numErrors] = error->code;
+ numErrors++;
+}
+
+static int
+mymain(void)
+{
+ int i, ret = EXIT_SUCCESS;
+ virConnectPtr conn;
+ virDomainPtr dom;
+ virErrorsPtr errs;
+
+ myErrorCodes = (int *)malloc( sizeof(int) );
+
+ virSetErrorFunc(NULL, errorHandler);
+
+ conn = virConnectOpen(NULL);
+ if (conn == NULL)
+ conn = virConnectOpenReadOnly(NULL);
+
+ /* Attempt to fail for the first time */
+ dom = virDomainLookupByID(conn, -1);
+ /* Attempt for the second time */
+ virDomainFree(dom);
+ /* ... third time ... */
+ dom = virDomainLookupByName(conn, BOGUS_NAME);
+ /* Now close the connection */
+ virConnectClose(conn);
+
+ /* ...and try to lookup - generate error for the fourth time :-) */
+ dom = virDomainLookupByName(conn, BOGUS_NAME);
+
+ errs = virGetAllErrors();
+ if (errs) {
+ if (errs->nerrors != numErrors) {
+ ret = EXIT_FAILURE;
+ goto cleanup;
+ }
+
+ for (i = 0; i < errs->nerrors; i++) {
+ if (errs->errors[i].code != myErrorCodes[i])
+ fprintf(stderr, "Error code for error #%d mismatch: expect %d, actual %d\n", i, myErrorCodes[i], errs->errors[i].code);
+ }
+ }
+
+cleanup:
+ free(myErrorCodes);
+
+ return ret;
+}
+
+VIRT_TEST_MAIN(mymain)
--
1.7.7.4
13 years, 5 months