[libvirt] PATCH: Fix multiple bugs in RPC handling
by Daniel P. Berrange
A number of bugs conspired together to cause some nasty problems when
a QEMU vm failed to start
- vm->monitor was not initialized to -1, so when a VM failed to start
the vm->monitor was just '0', and thus we closed FD 0 (libvirtd's stdin)
- The next client to connect got FD 0 as its socket
- The first bug struck again, causing the client to be closed even
though libvirt thought it was still open
- libvirtd now polle on FD=0, which gave back POLLNVAL because it was
closed
- event.c was not looking for POLLNVAL so it span 100% cpu when this
happened, instead of invoking the callback with an error code
- virsh was not cleaning up the priv->watiDispatch call upon I/O errors,
so virsh then hung when doing virConenctClose
This patch does 3 things
- Treats POLLNVAL as VIR_EVENT_HANDLE_ERROR, so the callback gets
to see the error & de-registers the client from the event loop
- Add the missing initialization of vm->monitor
- Fix remote_internal.c handling of I/O errors
Daniel
Index: qemud/event.c
===================================================================
RCS file: /data/cvs/libvirt/qemud/event.c,v
retrieving revision 1.17
diff -u -p -u -p -r1.17 event.c
--- qemud/event.c 22 Dec 2008 12:55:47 -0000 1.17
+++ qemud/event.c 5 Feb 2009 17:12:51 -0000
@@ -653,6 +653,8 @@ virPollEventToEventHandleType(int events
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;
Index: src/domain_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/domain_conf.c,v
retrieving revision 1.64
diff -u -p -u -p -r1.64 domain_conf.c
--- src/domain_conf.c 30 Jan 2009 21:52:22 -0000 1.64
+++ src/domain_conf.c 5 Feb 2009 17:12:51 -0000
@@ -504,6 +504,7 @@ virDomainObjPtr virDomainAssignDef(virCo
domain->state = VIR_DOMAIN_SHUTOFF;
domain->def = def;
domain->monitor_watch = -1;
+ domain->monitor = -1;
if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) {
virReportOOMError(conn);
Index: src/remote_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/remote_internal.c,v
retrieving revision 1.136
diff -u -p -u -p -r1.136 remote_internal.c
--- src/remote_internal.c 3 Feb 2009 13:08:07 -0000 1.136
+++ src/remote_internal.c 5 Feb 2009 17:12:52 -0000
@@ -6192,17 +6192,17 @@ processCalls(virConnectPtr conn,
continue;
virReportSystemError(in_open ? NULL : conn, errno,
"%s", _("poll on socket failed"));
- return -1;
+ goto error;
}
if (fds[0].revents & POLLOUT) {
if (processCallSend(conn, priv, in_open) < 0)
- return -1;
+ goto error;
}
if (fds[0].revents & POLLIN) {
if (processCallRecv(conn, priv, in_open) < 0)
- return -1;
+ goto error;
}
/* Iterate through waiting threads and if
@@ -6253,9 +6253,21 @@ processCalls(virConnectPtr conn,
if (fds[0].revents & (POLLHUP | POLLERR)) {
errorf(in_open ? NULL : conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("received hangup / error event on socket"));
- return -1;
+ goto error;
}
}
+
+
+error:
+ priv->waitDispatch = thiscall->next;
+ DEBUG("Giving up the buck due to I/O error %d %p %p", thiscall->proc_nr, thiscall, priv->waitDispatch);
+ /* See if someone else is still waiting
+ * and if so, then pass the buck ! */
+ if (priv->waitDispatch) {
+ DEBUG("Passing the buck to %d %p", priv->waitDispatch->proc_nr, priv->waitDispatch);
+ virCondSignal(&priv->waitDispatch->cond);
+ }
+ return -1;
}
/*
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
15 years, 9 months
[libvirt] storage error
by Farkas Levente
hi,
first of all i don't know which is the right list for this. since it's
created by virt-manager, but the error says libvirtError.
anyway another error during a new guest install.
-------------------------------------------
[Fri, 06 Feb 2009 10:54:14 virt-manager 32039] DEBUG (error:76) Uncaught
Error: Uncaught error validating input: cannot open volume
'/var/lib/libvirt/images/fedora-i386.img': No such file or directory : Trac
eback (most recent call last):
File "/usr/share/virt-manager/virtManager/create.py", line 301, in forward
if(self.validate(notebook.get_current_page()) != True):
File "/usr/share/virt-manager/virtManager/create.py", line 1004, in
validate
conn=self._guest.conn)
File "/usr/lib/python2.4/site-packages/virtinst/VirtualDisk.py", line
166, in __init__
self.__validate_params()
File "/usr/lib/python2.4/site-packages/virtinst/VirtualDisk.py", line
492, in __validate_params
self.__set_dev_type()
File "/usr/lib/python2.4/site-packages/virtinst/VirtualDisk.py", line
290, in __set_dev_type
t = self.vol_object.info()[0]
File "/usr/lib64/python2.4/site-packages/libvirt.py", line 947, in info
if ret is None: raise libvirtError ('virStorageVolGetInfo() failed',
vol=self)
libvirtError: cannot open volume
'/var/lib/libvirt/images/fedora-i386.img': No such file or directory
-------------------------------------------
the current situation i'm not able to install any new guests:-(
--
Levente "Si vis pacem para bellum!"
15 years, 9 months
[libvirt] RFC: configuring host interfaces with libvirt
by David Lutterkort
For certain applications, we want libvirt to be able to configure host
network interfaces in a variety of ways; currently, we are most
interested in teaching libvirt how to set up ordinary ethernet
interfaces, bridges, bonding and vlan's.
Below is a high-level proposal of how that could be done. Please comment
copiously ;)
1. XML Format
=============
The first question is how the user would describe the host interfaces they
want. Below are some sketches of what an XML representation of the various
kinds of interfaces would look like. This covers the minimal amount of
settings for these to be useful, though I am sure we'll need to add more
over time.
<interface device="eth0" onboot="yes">
<hwaddr>00:19:d2:9f:88:96</hwaddr>
<dhcp peerdns="yes"/>
</interface>
<interface device="eth1" onboot="yes">
<hwaddr>00:19:d2:9f:88:97</hwaddr>
<static ipaddr="192.168.0.5" gateway="192.168.0.1" netmask="255.255.255.0"/>
</interface>
<interface device="eth2" onboot="yes">
<hwaddr>00:19:d2:9f:88:98</hwaddr>
</interface>
<bond name="bond00" onboot="yes" mode="active-backup">
<slave device="eth0" primary="yes"/>
<slave device="eth1"/>
</bond>
<bridge name="br0" stp="off" onboot="yes">
<member device="eth2"/>
<dhcp peerdns="yes"/>
</bridge>
<vlan device="eth0" tag="42" reorder_hdr="yes"/>
All of these should also allow a <uuid> element for specifying a uuid; I
omitted that for brevity.
2. API Changes
==============
There are two options for dealing with network interfaces: (1) use the
existing virNetwork* calls or (2) add completely new API calls.
Repurposing existing virNetwork* calls
--------------------------------------
The existing calls map well to the operations we need for managing
interfaces, with a few exceptions:
- virNetworkGetAutostart/SetAutostart: depending on how we implement all
this (see below), 'autostart' might actually mean 'on boot', not 'when
libvirtd starts'
- virNetworkGetBridgeName doesn't make sense for interfaces, and should
return NULL for interfaces
We'll probably also end up adding some functions to query details about an
interface, in particular, a call to see what kind of network/interface a
virNetworkPtr represents
Add completely new virInterface* calls
--------------------------------------
This would add roughly the same API calls as the virNetwork* calls,
i.e. we'd have something like
typedef struct virInterface *virInterfacePtr;
int virInterfaceCreate(virInterfacePtr);
virInterfacePtr virInterfaceCreateXML(..);
...
plus some calls to extract information from a virInterfacePtr
The second option seems cleaner to me and easier to implement, and avoids
any subtle changes in the behavior of existing API, though I don't like
that we'll be adding another 20 or so calls to libvirt's public API, with
attendant churn both in the drivers and in virsh.
3. Implementation
=================
Configuring network interfaces is highly OS and OS-variant/distro
dependant. There are at least two different ways how libvirt can go about
modifying the host to create interfaces:
1. Modify the system's network setup scripts (ifcfg-XXX on RH)
2. Directly use the system's network utilities like ifconfig
3. Rely on NetworkManager (not an option right now, as NM doesn't know
about bridges and the like)
Option (1) saves us from replicating every bit of network setup
functionality that those scripts already have - besides configuring the
interface, we also might have to setup routes, run dhclient etc.
Option (2) would require far fewer backend implementations than (1) - we
should be able to get away with one implementation for Linux, rather than
one for Fedora/RHEL, one for Debian, one for SuSe, three for gentoo
etc.
If we want 'autostart' for an interface to mean 'bring up the interface
as soon as the system boots', we are pretty much forced to go with
option (1).
All in all, option (1) seems more attractive, since it should save us from
dealing with a lot of low-level details of network setup, and the distro
scripts should be much better integrated with the rest of the system than
what we come up with for libvirt.
4. Misc issues
==============
* Should interfaces have labels/roles ('data-interface') to help admins
make sense of the current config ?
* Do we expect interfaces to be in a specific state before we create them
or do we just tear them down and reconfigure them no matter what ?
* Are there crucial config options that are not covered by the sketches
above (e.g., setting an explicit MTU) ? Are there things in the XML
sketches above that will be impossible to implement on some OS ?
* Should this even be done as part of libvirt ? It seems like a very
generic network config tool, and libvirt merely the conduit to exposing
this through an API, most importantly, a remotable API.
David
15 years, 9 months
[libvirt] [PATCH] Improve error reporting in virsh
by john.levon@sun.com
# HG changeset patch
# User john.levon(a)sun.com
# Date 1233791330 28800
# Node ID 6588879d8cc9a3af1147a5edd624aee5155493ae
# Parent da162569b5f7e132c4ccbfc56fc3670fb5ecee10
Improve error reporting in virsh
Rather than verbosely printing every error, save the last error and
report that only if the entire command fails. Additionally, avoid
over-writing an existing error in various places in the library.
Signed-off-by: John Levon <john.levon(a)sun.com>
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -187,6 +187,8 @@ void virConnSetErrorFunc (virConnectPt
virErrorFunc handler);
int virConnCopyLastError (virConnectPtr conn,
virErrorPtr to);
+
+virErrorPtr virCloneError (virErrorPtr from);
#ifdef __cplusplus
}
#endif
diff --git a/src/domain_conf.c b/src/domain_conf.c
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -2432,8 +2432,7 @@ catchXMLError (void *ctx, const char *ms
if (ctxt) {
virConnectPtr conn = ctxt->_private;
- if (conn &&
- conn->err.code == VIR_ERR_NONE &&
+ if (virGetLastError() == NULL &&
ctxt->lastError.level == XML_ERR_FATAL &&
ctxt->lastError.message != NULL) {
virDomainReportError (conn, VIR_ERR_XML_DETAIL,
@@ -2466,7 +2465,7 @@ virDomainDefPtr virDomainDefParseString(
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOWARNING);
if (!xml) {
- if (conn && conn->err.code == VIR_ERR_NONE)
+ if (virGetLastError() == NULL)
virDomainReportError(conn, VIR_ERR_XML_ERROR,
"%s", _("failed to parse xml document"));
goto cleanup;
@@ -2507,7 +2506,7 @@ virDomainDefPtr virDomainDefParseFile(vi
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOWARNING);
if (!xml) {
- if (conn && conn->err.code == VIR_ERR_NONE)
+ if (virGetLastError() == NULL)
virDomainReportError(conn, VIR_ERR_XML_ERROR,
"%s", _("failed to parse xml document"));
goto cleanup;
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -244,6 +244,7 @@ LIBVIRT_0.6.0 {
virStoragePoolRef;
virStorageVolRef;
virNodeDeviceRef;
+ virCloneError;
} LIBVIRT_0.5.0;
diff --git a/src/virsh.c b/src/virsh.c
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -93,22 +93,6 @@ typedef enum {
} vshErrorLevel;
/*
- * The error handler for virsh
- */
-static void
-virshErrorHandler(void *unused, virErrorPtr error)
-{
- if ((unused != NULL) || (error == NULL))
- return;
-
- /* Suppress the VIR_ERR_NO_XEN error which fails as non-root */
- if ((error->code == VIR_ERR_NO_XEN) || (error->code == VIR_ERR_OK))
- return;
-
- virDefaultErrorFunc(error);
-}
-
-/*
* virsh command line grammar:
*
* command_line = <command>\n | <command>; <command>; ...
@@ -319,6 +303,41 @@ static int namesorter(const void *a, con
const char **sb = (const char**)b;
return strcasecmp(*sa, *sb);
+}
+
+static virErrorPtr last_error;
+
+/*
+ * Quieten libvirt until we're done with the command.
+ */
+static void
+virshErrorHandler(void *unused, virErrorPtr error)
+{
+ last_error = virCloneError(error);
+ if (getenv("VIRSH_DEBUG") != NULL)
+ virDefaultErrorFunc(error);
+}
+
+/*
+ * Report an error when a command finishes. This is better than before
+ * (when correct operation would report errors), but it has some
+ * problems: we lose the smarter formatting of virDefaultErrorFunc(),
+ * and it can become harder to debug problems, if errors get reported
+ * twice during one command. This case shouldn't really happen anyway,
+ * and it's IMHO a bug that libvirt does that sometimes.
+ */
+static void
+virshReportError(vshControl *ctl)
+{
+ if (last_error == NULL)
+ return;
+
+ if (last_error->code == VIR_ERR_OK) {
+ vshError(ctl, TRUE, "%s", _("unknown error"));
+ return;
+ }
+
+ vshError(ctl, TRUE, "%s", last_error->message);
}
@@ -6102,6 +6121,9 @@ vshCommandRun(vshControl *ctl, const vsh
if (ctl->timing)
GETTIMEOFDAY(&after);
+
+ if (ret == FALSE)
+ virshReportError(ctl);
if (STREQ(cmd->def->name, "quit")) /* hack ... */
return ret;
diff --git a/src/virterror.c b/src/virterror.c
--- a/src/virterror.c
+++ b/src/virterror.c
@@ -259,6 +259,32 @@ virGetLastError(void)
}
/**
+ * virCloneError:
+ * @from: source error to copy from
+ *
+ * Allocate a new error object and deep-copy it from the given error
+ * object. The destination error is reset before the copy. If NULL is
+ * passed, a new error object is allocated.
+ *
+ * Returns a pointer to the copied error or NULL if allocation failed.
+ */
+virErrorPtr
+virCloneError(virErrorPtr from)
+{
+ virErrorPtr to;
+
+ if (VIR_ALLOC(to) < 0)
+ return NULL;
+
+ if (from)
+ virCopyError(from, to);
+ else
+ virResetError(to);
+
+ return to;
+}
+
+/**
* virCopyLastError:
* @to: target to receive the copy
*
diff --git a/src/xend_internal.c b/src/xend_internal.c
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -105,12 +105,16 @@ virDomainDevID(virDomainPtr domain,
int devid_len);
#endif
-#define virXendError(conn, code, fmt...) \
- virReportErrorHelper(conn, VIR_FROM_XEND, code, __FILE__, \
- __FUNCTION__, __LINE__, fmt)
-
+#define virXendError(conn, codeval, fmt...) \
+ do { \
+ if (virGetLastError() == NULL) { \
+ virReportErrorHelper(conn, VIR_FROM_XEND, codeval, __FILE__, \
+ __FUNCTION__, __LINE__, fmt); \
+ } \
+ } while (0)
+
#define virXendErrorInt(conn, code, ival) \
- virXendError(conn, code, "%d", ival)
+ virXendError(conn, code, "%d", ival)
/**
* do_connect:
15 years, 9 months
[libvirt] [PATCH] Improve error reporting in virsh
by john.levon@sun.com
# HG changeset patch
# User john.levon(a)sun.com
# Date 1233859425 28800
# Node ID c594c1c54b88947082a01b6aaa81ad7756bbd951
# Parent a23da778e0ddf954d8bf0a185b508fc236feb4be
Improve error reporting in virsh
Rather than verbosely printing every error, save the last error and
report that only if the entire command fails.
Signed-off-by: John Levon <john.levon(a)sun.com>
diff --git a/src/virsh.c b/src/virsh.c
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -93,22 +93,6 @@ typedef enum {
} vshErrorLevel;
/*
- * The error handler for virsh
- */
-static void
-virshErrorHandler(void *unused, virErrorPtr error)
-{
- if ((unused != NULL) || (error == NULL))
- return;
-
- /* Suppress the VIR_ERR_NO_XEN error which fails as non-root */
- if ((error->code == VIR_ERR_NO_XEN) || (error->code == VIR_ERR_OK))
- return;
-
- virDefaultErrorFunc(error);
-}
-
-/*
* virsh command line grammar:
*
* command_line = <command>\n | <command>; <command>; ...
@@ -319,6 +303,45 @@ static int namesorter(const void *a, con
const char **sb = (const char**)b;
return strcasecmp(*sa, *sb);
+}
+
+static virErrorPtr last_error;
+
+/*
+ * Quieten libvirt until we're done with the command.
+ */
+static void
+virshErrorHandler(void *unused, virErrorPtr error)
+{
+ last_error = virSaveLastError();
+ if (getenv("VIRSH_DEBUG") != NULL)
+ virDefaultErrorFunc(error);
+}
+
+/*
+ * Report an error when a command finishes. This is better than before
+ * (when correct operation would report errors), but it has some
+ * problems: we lose the smarter formatting of virDefaultErrorFunc(),
+ * and it can become harder to debug problems, if errors get reported
+ * twice during one command. This case shouldn't really happen anyway,
+ * and it's IMHO a bug that libvirt does that sometimes.
+ */
+static void
+virshReportError(vshControl *ctl)
+{
+ if (last_error == NULL)
+ return;
+
+ if (last_error->code == VIR_ERR_OK) {
+ vshError(ctl, FALSE, "%s", _("unknown error"));
+ goto out;
+ }
+
+ vshError(ctl, FALSE, "%s", last_error->message);
+
+out:
+ free(last_error);
+ last_error = NULL;
}
@@ -6102,6 +6125,9 @@ vshCommandRun(vshControl *ctl, const vsh
if (ctl->timing)
GETTIMEOFDAY(&after);
+
+ if (ret == FALSE)
+ virshReportError(ctl);
if (STREQ(cmd->def->name, "quit")) /* hack ... */
return ret;
15 years, 9 months
[libvirt] [PATCH] Introduce virCopyLastError()
by john.levon@sun.com
# HG changeset patch
# User john.levon(a)sun.com
# Date 1233859424 28800
# Node ID dd8a1923aae38d9e36cb98a934af64450ecd85a2
# Parent 8086732c0e4250d26a4cfed2411e86b209712eb5
Introduce virCopyLastError()
Allow applications to store a copy of the last error reported.
Signed-off-by: John Levon <john.levon(a)sun.com>
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -172,6 +172,7 @@ typedef void (*virErrorFunc) (void *user
*/
virErrorPtr virGetLastError (void);
+virErrorPtr virSaveLastError (void);
void virResetLastError (void);
void virResetError (virErrorPtr err);
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -247,4 +247,9 @@ LIBVIRT_0.6.0 {
} LIBVIRT_0.5.0;
+LIBVIRT_0.6.1 {
+ global:
+ virSaveLastError;
+} LIBVIRT_0.6.0;
+
# .... define new API here using predicted next version number ....
diff --git a/src/virterror.c b/src/virterror.c
--- a/src/virterror.c
+++ b/src/virterror.c
@@ -286,6 +286,25 @@ virCopyLastError(virErrorPtr to)
}
/**
+ * virSaveLastError:
+ *
+ * Save the last error into a new error object.
+ *
+ * Returns a pointer to the copied error or NULL if allocation failed.
+ */
+virErrorPtr
+virSaveLastError(void)
+{
+ virErrorPtr to;
+
+ if (VIR_ALLOC(to) < 0)
+ return NULL;
+
+ virCopyLastError(to);
+ return to;
+}
+
+/**
* virResetError:
* @err: pointer to the virError to clean up
*
15 years, 9 months
[libvirt] autostart with xend
by John Levon
It doesn't work quite right with a running domain. The 'new' will
correctly set the config, but the temporary config doesn't include the
new setting. So tests of the form "set autostart; is it set?" will fail.
Suggestions?
Also, why isn't this represented in the XML?
thanks,
john
15 years, 9 months
[libvirt] [PATCH] Add <distro> to domain XML
by john.levon@sun.com
# HG changeset patch
# User john.levon(a)sun.com
# Date 1233340700 28800
# Node ID c1cc701bfb5b7417c2c8cd3571022dcd161c518f
# Parent cb53cd19242ca7c4a8d20a54495108d7f6639e57
Add <distro> to domain XML
Support recording the distro type and variant of a domain.
Signed-off-by: John Levon <john.levon(a)sun.com>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -19,6 +19,7 @@
<ref name='resources'/>
<ref name='features'/>
<ref name='termination'/>
+ <ref name='distro'/>
<optional>
<ref name='devices'/>
</optional>
@@ -326,6 +327,20 @@
</attribute>
<empty/>
</element>
+ </define>
+
+
+ <define name='distro'>
+ <optional>
+ <element name='distro'>
+ <element name='type'>
+ <text/>
+ </element>
+ <element name='variant'>
+ <text/>
+ </element>
+ </element>
+ </optional>
</define>
diff --git a/src/domain_conf.c b/src/domain_conf.c
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -436,6 +436,8 @@ void virDomainDefFree(virDomainDefPtr de
VIR_FREE(def->name);
VIR_FREE(def->cpumask);
VIR_FREE(def->emulator);
+ VIR_FREE(def->distro_type);
+ VIR_FREE(def->distro_variant);
VIR_FREE(def);
}
@@ -2010,6 +2012,9 @@ static virDomainDefPtr virDomainDefParse
&def->onCrash, VIR_DOMAIN_LIFECYCLE_DESTROY) < 0)
goto error;
+ def->distro_type = virXPathString(conn, "string(./distro/type[1])", ctxt);
+ def->distro_variant = virXPathString(conn,
+ "string(./distro/variant[1])", ctxt);
tmp = virXPathString(conn, "string(./clock/@offset)", ctxt);
if (tmp && STREQ(tmp, "localtime"))
@@ -3352,6 +3357,17 @@ char *virDomainDefFormat(virConnectPtr c
"on_crash") < 0)
goto cleanup;
+ if (def->distro_type != NULL) {
+ virBufferAddLit(&buf, " <distro>\n");
+ virBufferEscapeString(&buf, " <type>%s</type>\n",
+ def->distro_type);
+ if (def->distro_variant != NULL) {
+ virBufferEscapeString(&buf, " <variant>%s</variant>\n",
+ def->distro_variant);
+ }
+ virBufferAddLit(&buf, " </distro>\n");
+ }
+
virBufferAddLit(&buf, " <devices>\n");
if (def->emulator)
diff --git a/src/domain_conf.h b/src/domain_conf.h
--- a/src/domain_conf.h
+++ b/src/domain_conf.h
@@ -428,6 +428,9 @@ struct _virDomainDef {
int onReboot;
int onPoweroff;
int onCrash;
+
+ char *distro_type;
+ char *distro_variant;
virDomainOSDef os;
char *emulator;
diff --git a/src/xend_internal.c b/src/xend_internal.c
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -2274,6 +2274,14 @@ xenDaemonParseSxpr(virConnectPtr conn,
}
} else
def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
+
+ tmp = sexpr_node(root, "domain/distro_type");
+ if (tmp != NULL && (def->distro_type = strdup(tmp)) == NULL)
+ goto no_memory;
+
+ tmp = sexpr_node(root, "domain/distro_variant");
+ if (tmp != NULL && (def->distro_variant = strdup(tmp)) == NULL)
+ goto no_memory;
if (hvm) {
@@ -5337,6 +5345,11 @@ xenDaemonFormatSxpr(virConnectPtr conn,
}
virBufferVSprintf(&buf, "(on_crash '%s')", tmp);
+ if (def->distro_type != NULL)
+ virBufferVSprintf(&buf, "(distro_type '%s')", def->distro_type);
+ if (def->distro_variant != NULL)
+ virBufferVSprintf(&buf, "(distro_variant '%s')", def->distro_variant);
+
/*
* xend puts localtime in image/{hvm,linux}/, but is clearly
* bootloader independent. As a simple workaround, we define it
diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-distro.sexpr b/tests/sexpr2xmldata/sexpr2xml-fv-distro.sexpr
new file mode 100644
--- /dev/null
+++ b/tests/sexpr2xmldata/sexpr2xml-fv-distro.sexpr
@@ -0,0 +1,86 @@
+(domain
+ (domid 1)
+ (on_crash destroy)
+ (uuid 7dbd82d8-bd75-72ea-0f23-f988c4ef95bd)
+ (bootloader_args )
+ (vcpus 1)
+ (name domu-220)
+ (on_poweroff destroy)
+ (on_reboot destroy)
+ (bootloader )
+ (maxmem 1024)
+ (memory 1024)
+ (shadow_memory 9)
+ (cpu_weight 256)
+ (cpu_cap 0)
+ (features )
+ (on_xend_start ignore)
+ (on_xend_stop shutdown)
+ (start_time 1233338703.67)
+ (cpu_time 31.675171334)
+ (online_vcpus 1)
+ (distro_type windows)
+ (distro_variant winxp)
+ (image
+ (hvm
+ (kernel /usr/lib/xen/boot/hvmloader)
+ (boot d)
+ (device_model /usr/lib/xen/bin/qemu-dm)
+ (keymap en-us)
+ (localtime 1)
+ (pae 1)
+ (serial pty)
+ (usb 1)
+ (usbdevice tablet)
+ (notes (SUSPEND_CANCEL 1))
+ )
+ )
+ (status 2)
+ (state r-----)
+ (store_mfn 262142)
+ (device
+ (vif
+ (mac 00:16:36:1a:73:6d)
+ (script vif-vnic)
+ (uuid e81f0e1a-69d9-fd9a-6bee-540693c66eeb)
+ (backend 0)
+ )
+ )
+ (device
+ (vbd
+ (uname phy:/dev/zvol/dsk/export/dom/domu-220-root)
+ (uuid 4e71c222-f7cf-7fac-bae3-dc57f1e3f2bc)
+ (mode w)
+ (dev hda:disk)
+ (backend 0)
+ (bootable 1)
+ )
+ )
+ (device
+ (vbd
+ (uname file:/net/heaped/export/netimage/windows/xp-sp2-vol.iso)
+ (uuid 2f321f31-80c9-c71e-cb80-0e6a932b071b)
+ (mode r)
+ (dev hdc:cdrom)
+ (backend 0)
+ (bootable 0)
+ )
+ )
+ (device (vkbd (backend 0)))
+ (device
+ (vfb
+ (vncunused 1)
+ (keymap en-us)
+ (type vnc)
+ (uuid a296597b-b5ac-a5b6-05c5-1d98200c528f)
+ (location localhost:5900)
+ )
+ )
+ (device
+ (console
+ (protocol vt100)
+ (location 3)
+ (uuid 8665fe81-678a-4ddc-5f8d-24e3d5fa46d9)
+ )
+ )
+)
diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-distro.xml b/tests/sexpr2xmldata/sexpr2xml-fv-distro.xml
new file mode 100644
--- /dev/null
+++ b/tests/sexpr2xmldata/sexpr2xml-fv-distro.xml
@@ -0,0 +1,51 @@
+<domain type='xen' id='1'>
+ <name>domu-220</name>
+ <uuid>7dbd82d8-bd75-72ea-0f23-f988c4ef95bd</uuid>
+ <memory>1048576</memory>
+ <currentMemory>1048576</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type>hvm</type>
+ <loader>/usr/lib/xen/boot/hvmloader</loader>
+ <boot dev='cdrom'/>
+ </os>
+ <features>
+ <pae/>
+ </features>
+ <clock offset='localtime'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>destroy</on_reboot>
+ <on_crash>destroy</on_crash>
+ <distro>
+ <type>windows</type>
+ <variant>winxp</variant>
+ </distro>
+ <devices>
+ <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+ <disk type='block' device='disk'>
+ <driver name='phy'/>
+ <source dev='/dev/zvol/dsk/export/dom/domu-220-root'/>
+ <target dev='hda' bus='ide'/>
+ </disk>
+ <disk type='file' device='cdrom'>
+ <driver name='file'/>
+ <source file='/net/heaped/export/netimage/windows/xp-sp2-vol.iso'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ </disk>
+ <interface type='ethernet'>
+ <mac address='00:16:36:1a:73:6d'/>
+ <script path='vif-vnic'/>
+ <target dev='vif1.0'/>
+ </interface>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target port='0'/>
+ </console>
+ <input type='tablet' bus='usb'/>
+ <input type='mouse' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes' keymap='en-us'/>
+ </devices>
+</domain>
diff --git a/tests/sexpr2xmltest.c b/tests/sexpr2xmltest.c
--- a/tests/sexpr2xmltest.c
+++ b/tests/sexpr2xmltest.c
@@ -150,6 +150,7 @@ mymain(int argc, char **argv)
DO_TEST("fv-usbmouse", "fv-usbmouse", 1);
DO_TEST("fv-usbtablet", "fv-usbtablet", 1);
DO_TEST("fv-kernel", "fv-kernel", 1);
+ DO_TEST("fv-distro", "fv-distro", 3);
DO_TEST("fv-serial-null", "fv-serial-null", 1);
DO_TEST("fv-serial-file", "fv-serial-file", 1);
diff --git a/tests/xml2sexprdata/xml2sexpr-fv-distro.sexpr b/tests/xml2sexprdata/xml2sexpr-fv-distro.sexpr
new file mode 100644
--- /dev/null
+++ b/tests/xml2sexprdata/xml2sexpr-fv-distro.sexpr
@@ -0,0 +1,1 @@
+(vm (name 'domu-220')(memory 1024)(maxmem 1024)(vcpus 1)(uuid '7dbd82d8-bd75-72ea-0f23-f988c4ef95bd')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(distro_type 'windows')(distro_variant 'winxp')(localtime 1)(image (hvm (kernel '/usr/lib/xen/boot/hvmloader')(vcpus 1)(boot d)(pae 1)(usb 1)(usbdevice tablet)(parallel none)(serial pty)(device_model '/usr/lib/xen/bin/qemu-dm')(vnc 1)(vncunused 1)(keymap 'en-us')))(device (vbd (dev 'hda:disk')(uname 'phy:/dev/zvol/dsk/export/dom/domu-220-root')(mode 'w')))(device (vbd (dev 'hdc:cdrom')(uname 'file:/net/heaped/export/netimage/windows/xp-sp2-vol.iso')(mode 'r')))(device (vif (mac '00:16:36:1a:73:6d')(script 'vif-vnic')(type ioemu))))
\ No newline at end of file
diff --git a/tests/xml2sexprdata/xml2sexpr-fv-distro.xml b/tests/xml2sexprdata/xml2sexpr-fv-distro.xml
new file mode 100644
--- /dev/null
+++ b/tests/xml2sexprdata/xml2sexpr-fv-distro.xml
@@ -0,0 +1,51 @@
+<domain type='xen' id='1'>
+ <name>domu-220</name>
+ <uuid>7dbd82d8-bd75-72ea-0f23-f988c4ef95bd</uuid>
+ <memory>1048576</memory>
+ <currentMemory>1048576</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type>hvm</type>
+ <loader>/usr/lib/xen/boot/hvmloader</loader>
+ <boot dev='cdrom'/>
+ </os>
+ <features>
+ <pae/>
+ </features>
+ <clock offset='localtime'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>destroy</on_reboot>
+ <on_crash>destroy</on_crash>
+ <distro>
+ <type>windows</type>
+ <variant>winxp</variant>
+ </distro>
+ <devices>
+ <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+ <disk type='block' device='disk'>
+ <driver name='phy'/>
+ <source dev='/dev/zvol/dsk/export/dom/domu-220-root'/>
+ <target dev='hda' bus='ide'/>
+ </disk>
+ <disk type='file' device='cdrom'>
+ <driver name='file'/>
+ <source file='/net/heaped/export/netimage/windows/xp-sp2-vol.iso'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ </disk>
+ <interface type='ethernet'>
+ <mac address='00:16:36:1a:73:6d'/>
+ <script path='vif-vnic'/>
+ <target dev='vif1.0'/>
+ </interface>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target port='0'/>
+ </console>
+ <input type='tablet' bus='usb'/>
+ <input type='mouse' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes' keymap='en-us'/>
+ </devices>
+</domain>
diff --git a/tests/xml2sexprtest.c b/tests/xml2sexprtest.c
--- a/tests/xml2sexprtest.c
+++ b/tests/xml2sexprtest.c
@@ -136,6 +136,7 @@ mymain(int argc, char **argv)
DO_TEST("fv-usbmouse", "fv-usbmouse", "fvtest", 1);
DO_TEST("fv-usbmouse", "fv-usbmouse", "fvtest", 1);
DO_TEST("fv-kernel", "fv-kernel", "fvtest", 1);
+ DO_TEST("fv-distro", "fv-distro", "fvtest", 3);
DO_TEST("fv-serial-null", "fv-serial-null", "fvtest", 1);
DO_TEST("fv-serial-file", "fv-serial-file", "fvtest", 1);
15 years, 9 months
[libvirt] [PATCH] Use virMacAddrCompare() in xs_internal.c
by john.levon@sun.com
# HG changeset patch
# User john.levon(a)sun.com
# Date 1233800565 28800
# Node ID 379763c63798c9f0c426facb9b9b61e34e6477e2
# Parent e6b17082b9b9440ce14ad76bd2f4c003ae2404db
Use virMacAddrCompare() in xs_internal.c
This solves a failure to look up a net device.
Signed-off-by: John Levon <john.levon(a)sun.com>
diff --git a/src/xs_internal.c b/src/xs_internal.c
--- a/src/xs_internal.c
+++ b/src/xs_internal.c
@@ -915,7 +915,7 @@ char *
char *
xenStoreDomainGetNetworkID(virConnectPtr conn, int id, const char *mac) {
char dir[80], path[128], **list = NULL, *val = NULL;
- unsigned int maclen, len, i, num;
+ unsigned int len, i, num;
char *ret = NULL;
xenUnifiedPrivatePtr priv;
@@ -926,9 +926,6 @@ xenStoreDomainGetNetworkID(virConnectPtr
if (priv->xshandle == NULL)
return (NULL);
if (mac == NULL)
- return (NULL);
- maclen = strlen(mac);
- if (maclen <= 0)
return (NULL);
snprintf(dir, sizeof(dir), "/local/domain/0/backend/vif/%d", id);
@@ -937,18 +934,20 @@ xenStoreDomainGetNetworkID(virConnectPtr
return(NULL);
for (i = 0; i < num; i++) {
snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "mac");
- val = xs_read(priv->xshandle, 0, path, &len);
- if (val == NULL)
+ if ((val = xs_read(priv->xshandle, 0, path, &len)) == NULL)
break;
- if ((maclen != len) || memcmp(val, mac, len)) {
- free(val);
- } else {
+
+ if (virMacAddrCompare(val, mac) == 0) {
ret = strdup(list[i]);
- free(val);
- break;
+ goto out;
}
- }
- free(list);
+
+ VIR_FREE(val);
+ }
+
+out:
+ VIR_FREE(val);
+ VIR_FREE(list);
return(ret);
}
15 years, 9 months
[libvirt] [PATCH] Robustify sexpr parser for NICs
by john.levon@sun.com
# HG changeset patch
# User john.levon(a)sun.com
# Date 1233806614 28800
# Node ID 0b9d8336e5e089b19ac8381fdc77eadc72ef9eb7
# Parent 379763c63798c9f0c426facb9b9b61e34e6477e2
Robustify sexpr parser for NICs
xend can occassionally get itself confused. Avoid crashing libvirt in
this case.
Signed-off-by: John Levon <john.levon(a)sun.com>
diff --git a/src/xend_internal.c b/src/xend_internal.c
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -1759,7 +1759,8 @@ xenDaemonParseSxprNets(virConnectPtr con
if (VIR_ALLOC(net) < 0)
goto no_memory;
- if (tmp != NULL || (STREQ(tmp2, DEFAULT_VIF_SCRIPT))) {
+ if (tmp != NULL ||
+ (tmp2 != NULL && STREQ(tmp2, DEFAULT_VIF_SCRIPT))) {
net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
/* XXX virtual network reverse resolve */
15 years, 9 months