[libvirt] [PATCH] error: avoid API breakage with vmware

Eric Blake eblake at redhat.com
Tue Dec 21 22:12:43 UTC 2010


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.
---
 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;

 /**
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 &&
-- 
1.7.3.3




More information about the libvir-list mailing list