[libvirt] [PATCH] error: avoid API breakage with vmware
Chris Lalancette
clalance at redhat.com
Wed Dec 22 14:01:51 UTC 2010
On 12/21/10 - 03:12:43PM, Eric Blake wrote:
> Fix glitch in commit cddd2a06 (thankfully post-0.8.6, so no
> released version has the glitch).
>
> Document and try to workaround glitch in commit 46e9b0f (in 0.8.0,
> which invalidated 6 virErrorNumber dating back to 0.7.1).
>
> Thankfully, my audit did not find any other glitches until pre-0.1.0
> days. I'm not sure how to add a syntax-check off the top of my
> head, but hopefully the explicit numbering will make people think
> twice about renumbering in the future.
>
> * include/libvirt/virterror.h (virErrorDomain): Avoid inserting
> new values in the middle, and add explicit numbering to help avoid
> this in the future.
> (virErrorNumber): Add explicit numbering, and document the snafu.
> * src/remote/remote_driver.c (remoteIO): Compensate for the snafu.
Thanks for looking at this, Eric.
> ---
> include/libvirt/virterror.h | 266 ++++++++++++++++++++++++------------------
> src/remote/remote_driver.c | 30 +++++-
> 2 files changed, 181 insertions(+), 115 deletions(-)
>
> diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
> index a1f88f4..0e59c0e 100644
> --- a/include/libvirt/virterror.h
> +++ b/include/libvirt/virterror.h
> @@ -4,7 +4,7 @@
> * Description: Provides the interfaces of the libvirt library to handle
> * errors raised while using the library.
> *
> - * Copy: Copyright (C) 2006 Red Hat, Inc.
> + * Copy: Copyright (C) 2006, 2010 Red Hat, Inc.
> *
> * See COPYING.LIB for the License of this software
> *
> @@ -34,49 +34,51 @@ typedef enum {
> /**
> * virErrorDomain:
> *
> - * Indicates where an error may have come from
> + * Indicates where an error may have come from. This should remain
> + * stable, with all additions placed at the end since libvirt 0.1.0.
> */
> typedef enum {
> VIR_FROM_NONE = 0,
> - VIR_FROM_XEN, /* Error at Xen hypervisor layer */
> - VIR_FROM_XEND, /* Error at connection with xend daemon */
> - VIR_FROM_XENSTORE, /* Error at connection with xen store */
> - VIR_FROM_SEXPR, /* Error in the S-Expression code */
> - VIR_FROM_XML, /* Error in the XML code */
> - VIR_FROM_DOM, /* Error when operating on a domain */
> - VIR_FROM_RPC, /* Error in the XML-RPC code */
> - VIR_FROM_PROXY, /* Error in the proxy code */ /* unused since 0.8.6 */
> - VIR_FROM_CONF, /* Error in the configuration file handling */
> - VIR_FROM_QEMU, /* Error at the QEMU daemon */
> - VIR_FROM_NET, /* Error when operating on a network */
> - VIR_FROM_TEST, /* Error from test driver */
> - VIR_FROM_REMOTE, /* Error from remote driver */
> - VIR_FROM_OPENVZ, /* Error from OpenVZ driver */
> - VIR_FROM_VMWARE, /* Error from VMware driver */
> - VIR_FROM_XENXM, /* Error at Xen XM layer */
> - VIR_FROM_STATS_LINUX,/* Error in the Linux Stats code */
> - VIR_FROM_LXC, /* Error from Linux Container driver */
> - VIR_FROM_STORAGE, /* Error from storage driver */
> - VIR_FROM_NETWORK, /* Error from network config */
> - VIR_FROM_DOMAIN, /* Error from domain config */
> - VIR_FROM_UML, /* Error at the UML driver */
> - VIR_FROM_NODEDEV, /* Error from node device monitor */
> - VIR_FROM_XEN_INOTIFY,/* Error from xen inotify layer */
> - VIR_FROM_SECURITY, /* Error from security framework */
> - VIR_FROM_VBOX, /* Error from VirtualBox driver */
> - VIR_FROM_INTERFACE, /* Error when operating on an interface */
> - VIR_FROM_ONE, /* Error from OpenNebula driver */
> - VIR_FROM_ESX, /* Error from ESX driver */
> - VIR_FROM_PHYP, /* Error from IBM power hypervisor */
> - VIR_FROM_SECRET, /* Error from secret storage */
> - VIR_FROM_CPU, /* Error from CPU driver */
> - VIR_FROM_XENAPI, /* Error from XenAPI */
> - VIR_FROM_NWFILTER, /* Error from network filter driver */
> - VIR_FROM_HOOK, /* Error from Synchronous hooks */
> - VIR_FROM_DOMAIN_SNAPSHOT, /* Error from domain snapshot */
> - VIR_FROM_AUDIT, /* Error from auditing subsystem */
> - VIR_FROM_SYSINFO, /* Error from sysinfo/SMBIOS */
> - VIR_FROM_STREAMS, /* Error from I/O streams */
> + VIR_FROM_XEN = 1, /* Error at Xen hypervisor layer */
> + VIR_FROM_XEND = 2, /* Error at connection with xend daemon */
> + VIR_FROM_XENSTORE = 3, /* Error at connection with xen store */
> + VIR_FROM_SEXPR = 4, /* Error in the S-Expression code */
> + VIR_FROM_XML = 5, /* Error in the XML code */
> + VIR_FROM_DOM = 6, /* Error when operating on a domain */
> + VIR_FROM_RPC = 7, /* Error in the XML-RPC code */
> + VIR_FROM_PROXY = 8, /* Error in the proxy code; unused since
> + 0.8.6 */
> + VIR_FROM_CONF = 9, /* Error in the configuration file handling */
> + VIR_FROM_QEMU = 10, /* Error at the QEMU daemon */
> + VIR_FROM_NET = 11, /* Error when operating on a network */
> + VIR_FROM_TEST = 12, /* Error from test driver */
> + VIR_FROM_REMOTE = 13, /* Error from remote driver */
> + VIR_FROM_OPENVZ = 14, /* Error from OpenVZ driver */
> + VIR_FROM_XENXM = 15, /* Error at Xen XM layer */
> + VIR_FROM_STATS_LINUX = 16, /* Error in the Linux Stats code */
> + VIR_FROM_LXC = 17, /* Error from Linux Container driver */
> + VIR_FROM_STORAGE = 18, /* Error from storage driver */
> + VIR_FROM_NETWORK = 19, /* Error from network config */
> + VIR_FROM_DOMAIN = 20, /* Error from domain config */
> + VIR_FROM_UML = 21, /* Error at the UML driver */
> + VIR_FROM_NODEDEV = 22, /* Error from node device monitor */
> + VIR_FROM_XEN_INOTIFY = 23, /* Error from xen inotify layer */
> + VIR_FROM_SECURITY = 24, /* Error from security framework */
> + VIR_FROM_VBOX = 25, /* Error from VirtualBox driver */
> + VIR_FROM_INTERFACE = 26, /* Error when operating on an interface */
> + VIR_FROM_ONE = 27, /* Error from OpenNebula driver */
> + VIR_FROM_ESX = 28, /* Error from ESX driver */
> + VIR_FROM_PHYP = 29, /* Error from IBM power hypervisor */
> + VIR_FROM_SECRET = 30, /* Error from secret storage */
> + VIR_FROM_CPU = 31, /* Error from CPU driver */
> + VIR_FROM_XENAPI = 32, /* Error from XenAPI */
> + VIR_FROM_NWFILTER = 33, /* Error from network filter driver */
> + VIR_FROM_HOOK = 34, /* Error from Synchronous hooks */
> + VIR_FROM_DOMAIN_SNAPSHOT = 35,/* Error from domain snapshot */
> + VIR_FROM_AUDIT = 36, /* Error from auditing subsystem */
> + VIR_FROM_SYSINFO = 37, /* Error from sysinfo/SMBIOS */
> + VIR_FROM_STREAMS = 38, /* Error from I/O streams */
> + VIR_FROM_VMWARE = 39, /* Error from VMware driver */
> } virErrorDomain;
>
>
> @@ -114,82 +116,118 @@ struct _virError {
> * virErrorNumber:
> *
> * The full list of errors the library can generate
> + *
> + * This list should remain stable, with all additions placed at the
> + * end since libvirt 0.1.0. There is one exception: values added
> + * between libvirt 0.7.1 and libvirt 0.7.7 (VIR_WAR_NO_SECRET through
> + * VIR_ERROR_MIGRATE_PERSIST_FAILED) were inadvertently relocated by
> + * four positions in 0.8.0. If you suspect version mismatch between a
> + * server and client, then you can decipher values as follows:
> + *
> + * switch (err.code) {
> + * case 60:
> + * // no way to tell VIR_WAR_NO_SECRET apart from VIR_WAR_NO_NWFILTER,
> + * // but both are very similar warnings
> + * break;
> + * case 61: case 62: case 63:
> + * if (err.domain != VIR_FROM_NWFILTER)
> + * err.code += 4;
> + * break;
> + * case 64:
> + * if (err.domain == VIR_FROM_QEMU)
> + * err.code += 4;
> + * break;
> + * case 65:
> + * if (err.domain == VIR_FROM_XEN)
> + * err.code += 4;
> + * break;
> + * default:
> + * }
> */
> typedef enum {
> VIR_ERR_OK = 0,
> - VIR_ERR_INTERNAL_ERROR, /* internal error */
> - VIR_ERR_NO_MEMORY, /* memory allocation failure */
> - VIR_ERR_NO_SUPPORT, /* no support for this function */
> - VIR_ERR_UNKNOWN_HOST,/* could not resolve hostname */
> - VIR_ERR_NO_CONNECT, /* can't connect to hypervisor */
> - VIR_ERR_INVALID_CONN,/* invalid connection object */
> - VIR_ERR_INVALID_DOMAIN,/* invalid domain object */
> - VIR_ERR_INVALID_ARG,/* invalid function argument */
> - VIR_ERR_OPERATION_FAILED,/* a command to hypervisor failed */
> - VIR_ERR_GET_FAILED,/* a HTTP GET command to failed */
> - VIR_ERR_POST_FAILED,/* a HTTP POST command to failed */
> - VIR_ERR_HTTP_ERROR,/* unexpected HTTP error code */
> - VIR_ERR_SEXPR_SERIAL,/* failure to serialize an S-Expr */
> - VIR_ERR_NO_XEN,/* could not open Xen hypervisor control */
> - VIR_ERR_XEN_CALL,/* failure doing an hypervisor call */
> - VIR_ERR_OS_TYPE, /* unknown OS type */
> - VIR_ERR_NO_KERNEL, /* missing kernel information */
> - VIR_ERR_NO_ROOT, /* missing root device information */
> - VIR_ERR_NO_SOURCE, /* missing source device information */
> - VIR_ERR_NO_TARGET, /* missing target device information */
> - VIR_ERR_NO_NAME, /* missing domain name information */
> - VIR_ERR_NO_OS, /* missing domain OS information */
> - VIR_ERR_NO_DEVICE, /* missing domain devices information */
> - VIR_ERR_NO_XENSTORE,/* could not open Xen Store control */
> - VIR_ERR_DRIVER_FULL, /* too many drivers registered */
> - VIR_ERR_CALL_FAILED, /* not supported by the drivers (DEPRECATED) */
> - VIR_ERR_XML_ERROR, /* an XML description is not well formed or broken */
> - VIR_ERR_DOM_EXIST,/* the domain already exist */
> - VIR_ERR_OPERATION_DENIED, /* operation forbidden on read-only connections */
> - VIR_ERR_OPEN_FAILED, /* failed to open a conf file */
> - VIR_ERR_READ_FAILED, /* failed to read a conf file */
> - VIR_ERR_PARSE_FAILED, /* failed to parse a conf file */
> - VIR_ERR_CONF_SYNTAX, /* failed to parse the syntax of a conf file */
> - VIR_ERR_WRITE_FAILED, /* failed to write a conf file */
> - VIR_ERR_XML_DETAIL, /* detail of an XML error */
> - VIR_ERR_INVALID_NETWORK, /* invalid network object */
> - VIR_ERR_NETWORK_EXIST, /* the network already exist */
> - VIR_ERR_SYSTEM_ERROR, /* general system call failure */
> - VIR_ERR_RPC, /* some sort of RPC error */
> - VIR_ERR_GNUTLS_ERROR, /* error from a GNUTLS call */
> - VIR_WAR_NO_NETWORK, /* failed to start network */
> - VIR_ERR_NO_DOMAIN, /* domain not found or unexpectedly disappeared */
> - VIR_ERR_NO_NETWORK, /* network not found */
> - VIR_ERR_INVALID_MAC, /* invalid MAC address */
> - VIR_ERR_AUTH_FAILED, /* authentication failed */
> - VIR_ERR_INVALID_STORAGE_POOL, /* invalid storage pool object */
> - VIR_ERR_INVALID_STORAGE_VOL, /* invalid storage vol object */
> - VIR_WAR_NO_STORAGE, /* failed to start storage */
> - VIR_ERR_NO_STORAGE_POOL, /* storage pool not found */
> - VIR_ERR_NO_STORAGE_VOL, /* storage pool not found */
> - VIR_WAR_NO_NODE, /* failed to start node driver */
> - VIR_ERR_INVALID_NODE_DEVICE,/* invalid node device object */
> - VIR_ERR_NO_NODE_DEVICE,/* node device not found */
> - VIR_ERR_NO_SECURITY_MODEL, /* security model not found */
> - VIR_ERR_OPERATION_INVALID, /* operation is not applicable at this time */
> - VIR_WAR_NO_INTERFACE, /* failed to start interface driver */
> - VIR_ERR_NO_INTERFACE, /* interface driver not running */
> - VIR_ERR_INVALID_INTERFACE, /* invalid interface object */
> - VIR_ERR_MULTIPLE_INTERFACES, /* more than one matching interface found */
> - VIR_WAR_NO_NWFILTER, /* failed to start nwfilter driver */
> - VIR_ERR_INVALID_NWFILTER, /* invalid nwfilter object */
> - VIR_ERR_NO_NWFILTER, /* nw filter pool not found */
> - VIR_ERR_BUILD_FIREWALL, /* nw filter pool not found */
> - VIR_WAR_NO_SECRET, /* failed to start secret storage */
> - VIR_ERR_INVALID_SECRET, /* invalid secret */
> - VIR_ERR_NO_SECRET, /* secret not found */
> - VIR_ERR_CONFIG_UNSUPPORTED, /* unsupported configuration construct */
> - VIR_ERR_OPERATION_TIMEOUT, /* timeout occurred during operation */
> - VIR_ERR_MIGRATE_PERSIST_FAILED, /* a migration worked, but making the
> - VM persist on the dest host failed */
> - VIR_ERR_HOOK_SCRIPT_FAILED, /* a synchronous hook script failed */
> - VIR_ERR_INVALID_DOMAIN_SNAPSHOT, /* invalid domain snapshot */
> - VIR_ERR_NO_DOMAIN_SNAPSHOT, /* domain snapshot not found */
> + VIR_ERR_INTERNAL_ERROR = 1, /* internal error */
> + VIR_ERR_NO_MEMORY = 2, /* memory allocation failure */
> + VIR_ERR_NO_SUPPORT = 3, /* no support for this function */
> + VIR_ERR_UNKNOWN_HOST = 4, /* could not resolve hostname */
> + VIR_ERR_NO_CONNECT = 5, /* can't connect to hypervisor */
> + VIR_ERR_INVALID_CONN = 6, /* invalid connection object */
> + VIR_ERR_INVALID_DOMAIN = 7, /* invalid domain object */
> + VIR_ERR_INVALID_ARG = 8, /* invalid function argument */
> + VIR_ERR_OPERATION_FAILED = 9, /* a command to hypervisor failed */
> + VIR_ERR_GET_FAILED = 10, /* a HTTP GET command to failed */
> + VIR_ERR_POST_FAILED = 11, /* a HTTP POST command to failed */
> + VIR_ERR_HTTP_ERROR = 12, /* unexpected HTTP error code */
> + VIR_ERR_SEXPR_SERIAL = 13, /* failure to serialize an S-Expr */
> + VIR_ERR_NO_XEN = 14, /* could not open Xen hypervisor
> + control */
> + VIR_ERR_XEN_CALL = 15, /* failure doing an hypervisor call */
> + VIR_ERR_OS_TYPE = 16, /* unknown OS type */
> + VIR_ERR_NO_KERNEL = 17, /* missing kernel information */
> + VIR_ERR_NO_ROOT = 18, /* missing root device information */
> + VIR_ERR_NO_SOURCE = 19, /* missing source device information */
> + VIR_ERR_NO_TARGET = 20, /* missing target device information */
> + VIR_ERR_NO_NAME = 21, /* missing domain name information */
> + VIR_ERR_NO_OS = 22, /* missing domain OS information */
> + VIR_ERR_NO_DEVICE = 23, /* missing domain devices information */
> + VIR_ERR_NO_XENSTORE = 24, /* could not open Xen Store control */
> + VIR_ERR_DRIVER_FULL = 25, /* too many drivers registered */
> + VIR_ERR_CALL_FAILED = 26, /* not supported by the drivers
> + (DEPRECATED) */
> + VIR_ERR_XML_ERROR = 27, /* an XML description is not well
> + formed or broken */
> + VIR_ERR_DOM_EXIST = 28, /* the domain already exist */
> + VIR_ERR_OPERATION_DENIED = 29, /* operation forbidden on read-only
> + connections */
> + VIR_ERR_OPEN_FAILED = 30, /* failed to open a conf file */
> + VIR_ERR_READ_FAILED = 31, /* failed to read a conf file */
> + VIR_ERR_PARSE_FAILED = 32, /* failed to parse a conf file */
> + VIR_ERR_CONF_SYNTAX = 33, /* failed to parse the syntax of a
> + conf file */
> + VIR_ERR_WRITE_FAILED = 34, /* failed to write a conf file */
> + VIR_ERR_XML_DETAIL = 35, /* detail of an XML error */
> + VIR_ERR_INVALID_NETWORK = 36, /* invalid network object */
> + VIR_ERR_NETWORK_EXIST = 37, /* the network already exist */
> + VIR_ERR_SYSTEM_ERROR = 38, /* general system call failure */
> + VIR_ERR_RPC = 39, /* some sort of RPC error */
> + VIR_ERR_GNUTLS_ERROR = 40, /* error from a GNUTLS call */
> + VIR_WAR_NO_NETWORK = 41, /* failed to start network */
> + VIR_ERR_NO_DOMAIN = 42, /* domain not found or unexpectedly
> + disappeared */
> + VIR_ERR_NO_NETWORK = 43, /* network not found */
> + VIR_ERR_INVALID_MAC = 44, /* invalid MAC address */
> + VIR_ERR_AUTH_FAILED = 45, /* authentication failed */
> + VIR_ERR_INVALID_STORAGE_POOL = 46, /* invalid storage pool object */
> + VIR_ERR_INVALID_STORAGE_VOL = 47, /* invalid storage vol object */
> + VIR_WAR_NO_STORAGE = 48, /* failed to start storage */
> + VIR_ERR_NO_STORAGE_POOL = 49, /* storage pool not found */
> + VIR_ERR_NO_STORAGE_VOL = 50, /* storage pool not found */
> + VIR_WAR_NO_NODE = 51, /* failed to start node driver */
> + VIR_ERR_INVALID_NODE_DEVICE = 52, /* invalid node device object */
> + VIR_ERR_NO_NODE_DEVICE = 53, /* node device not found */
> + VIR_ERR_NO_SECURITY_MODEL = 54, /* security model not found */
> + VIR_ERR_OPERATION_INVALID = 55, /* operation is not applicable at this
> + time */
> + VIR_WAR_NO_INTERFACE = 56, /* failed to start interface driver */
> + VIR_ERR_NO_INTERFACE = 57, /* interface driver not running */
> + VIR_ERR_INVALID_INTERFACE = 58, /* invalid interface object */
> + VIR_ERR_MULTIPLE_INTERFACES = 59, /* more than one matching interface
> + found */
> + VIR_WAR_NO_NWFILTER = 60, /* failed to start nwfilter driver */
> + VIR_ERR_INVALID_NWFILTER = 61, /* invalid nwfilter object */
> + VIR_ERR_NO_NWFILTER = 62, /* nw filter pool not found */
> + VIR_ERR_BUILD_FIREWALL = 63, /* nw filter pool not found */
> + VIR_WAR_NO_SECRET = 64, /* failed to start secret storage */
> + VIR_ERR_INVALID_SECRET = 65, /* invalid secret */
> + VIR_ERR_NO_SECRET = 66, /* secret not found */
> + VIR_ERR_CONFIG_UNSUPPORTED = 67, /* unsupported configuration
> + construct */
> + VIR_ERR_OPERATION_TIMEOUT = 68, /* timeout occurred during operation */
> + VIR_ERR_MIGRATE_PERSIST_FAILED = 69,/* a migration worked, but making the
> + VM persist on the dest host failed */
> + VIR_ERR_HOOK_SCRIPT_FAILED = 70, /* a synchronous hook script failed */
> + VIR_ERR_INVALID_DOMAIN_SNAPSHOT = 71,/* invalid domain snapshot */
> + VIR_ERR_NO_DOMAIN_SNAPSHOT = 72, /* domain snapshot not found */
> } virErrorNumber;
Definitely ACK to these two parts; moving VIR_FROM_VMWARE to the end and
explicitly numbering everything. See below.
>
> /**
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index fae191c..66d3852 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -10371,8 +10371,36 @@ remoteIO(virConnectPtr conn,
> return -1;
>
> cleanup:
> - DEBUG("All done with our call %d %p %p", thiscall->proc_nr, priv->waitDispatch, thiscall);
> + DEBUG("All done with our call %d %p %p", thiscall->proc_nr,
> + priv->waitDispatch, thiscall);
> if (thiscall->mode == REMOTE_MODE_ERROR) {
> + /* Interop for virErrorNumber glitch in 0.8.0, if server is
> + * 0.7.1 through 0.7.7 */
> + switch (thiscall->err.code) {
> + case VIR_WAR_NO_NWFILTER:
> + /* no way to tell old VIR_WAR_NO_SECRET apart from
> + * VIR_WAR_NO_NWFILTER, but both are very similar
> + * warnings, so ignore the difference */
> + break;
> + case VIR_ERR_INVALID_NWFILTER:
> + case VIR_ERR_NO_NWFILTER:
> + case VIR_ERR_BUILD_FIREWALL:
> + if (thiscall->err.domain != VIR_FROM_NWFILTER)
> + thiscall->err.code += 4;
> + break;
> + case VIR_WAR_NO_SECRET:
> + if (thiscall->err.domain == VIR_FROM_QEMU)
> + thiscall->err.code = VIR_ERR_OPERATION_TIMEOUT;
> + break;
> + case VIR_ERR_INVALID_SECRET:
> + if (thiscall->err.domain == VIR_FROM_XEN)
> + thiscall->err.code = VIR_ERR_MIGRATE_PERSIST_FAILED;
> + break;
> + default:
> + /* Nothing to alter. */
> + break;
> + }
> +
> /* See if caller asked us to keep quiet about missing RPCs
> * eg for interop with older servers */
> if (flags & REMOTE_CALL_QUIET_MISSING_RPC &&
Clever. Make sure it is of the right "domain", and if not, you know you are
talking to an older server. At first I thought it was confusing, but this
will do the right thing in *almost* all situations, so I like it.
ACK to this; as DV says, maybe we can make a "make check" or
"make syntax-check" to automatically catch it in the future, but this at least
fixes the current breakage.
--
Chris Lalancette
More information about the libvir-list
mailing list