[libvirt] PATCH: 9/25: Make global error object thread local

Daniel P. Berrange berrange at redhat.com
Tue Jan 13 17:42:15 UTC 2009


The virGetLastError() and virConnGetLastError() methods are not
even remotely thread safe, and the virCopyLastError/virConnCopyLastError
methods don't help in this goal, being open to a race condition.

This patch changes the internal impl of the global error object to
store its virError instance in a thread local variable. All errors
are now reported against the global error object. In the public
API entry points, we explicitly reset the global error object to
ensure no stale errors are hanging around. In all error paths we
also set a generic error, if the internal driver forget to set an
explicit error. Finally we also copy the global error to the per
connection error object for back-compatability, though the global
object remains non-threadsafe for application access.


 src/datatypes.c          |   31 
 src/datatypes.h          |   15 
 src/libvirt.c            | 3276 ++++++++++++++++++++++++++++++++---------------
 src/virterror.c          |  258 +++
 src/virterror_internal.h |    5 
 tests/cpuset             |    2 
 tests/read-bufsiz        |    2 
 tests/start              |    4 
 tests/undefine           |    8 
 tests/vcpupin            |    4 
 10 files changed, 2507 insertions(+), 1098 deletions(-)

Daniel

diff --git a/src/datatypes.c b/src/datatypes.c
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -195,8 +195,6 @@ virReleaseConnect(virConnectPtr conn) {
         virHashFree(conn->nodeDevices, (virHashDeallocator) virNodeDeviceFree);
 
     virResetError(&conn->err);
-    if (virLastErr.conn == conn)
-        virLastErr.conn = NULL;
 
     xmlFreeURI(conn->uri);
 
@@ -219,7 +217,7 @@ virUnrefConnect(virConnectPtr conn) {
     int refs;
 
     if ((!VIR_IS_CONNECT(conn))) {
-        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(-1);
     }
     virMutexLock(&conn->lock);
@@ -253,7 +251,7 @@ virGetDomain(virConnectPtr conn, const c
     virDomainPtr ret = NULL;
 
     if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) {
-        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(NULL);
     }
     virMutexLock(&conn->lock);
@@ -323,10 +321,6 @@ virReleaseDomain(virDomainPtr domain) {
         virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
                         _("domain missing from connection hash table"));
 
-    if (conn->err.dom == domain)
-        conn->err.dom = NULL;
-    if (virLastErr.dom == domain)
-        virLastErr.dom = NULL;
     domain->magic = -1;
     domain->id = -1;
     VIR_FREE(domain->name);
@@ -358,7 +352,7 @@ virUnrefDomain(virDomainPtr domain) {
     int refs;
 
     if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibConnError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(-1);
     }
     virMutexLock(&domain->conn->lock);
@@ -393,7 +387,7 @@ virGetNetwork(virConnectPtr conn, const 
     virNetworkPtr ret = NULL;
 
     if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) {
-        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(NULL);
     }
     virMutexLock(&conn->lock);
@@ -459,11 +453,6 @@ virReleaseNetwork(virNetworkPtr network)
         virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
                         _("network missing from connection hash table"));
 
-    if (conn->err.net == network)
-        conn->err.net = NULL;
-    if (virLastErr.net == network)
-        virLastErr.net = NULL;
-
     network->magic = -1;
     VIR_FREE(network->name);
     VIR_FREE(network);
@@ -494,7 +483,7 @@ virUnrefNetwork(virNetworkPtr network) {
     int refs;
 
     if (!VIR_IS_CONNECTED_NETWORK(network)) {
-        virLibConnError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(-1);
     }
     virMutexLock(&network->conn->lock);
@@ -530,7 +519,7 @@ virGetStoragePool(virConnectPtr conn, co
     virStoragePoolPtr ret = NULL;
 
     if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) {
-        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(NULL);
     }
     virMutexLock(&conn->lock);
@@ -627,7 +616,7 @@ virUnrefStoragePool(virStoragePoolPtr po
     int refs;
 
     if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
-        virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(-1);
     }
     virMutexLock(&pool->conn->lock);
@@ -664,7 +653,7 @@ virGetStorageVol(virConnectPtr conn, con
     virStorageVolPtr ret = NULL;
 
     if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (key == NULL)) {
-        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(NULL);
     }
     virMutexLock(&conn->lock);
@@ -765,7 +754,7 @@ virUnrefStorageVol(virStorageVolPtr vol)
     int refs;
 
     if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) {
-        virLibConnError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(-1);
     }
     virMutexLock(&vol->conn->lock);
@@ -801,7 +790,7 @@ virGetNodeDevice(virConnectPtr conn, con
     virNodeDevicePtr ret = NULL;
 
     if ((!VIR_IS_CONNECT(conn)) || (name == NULL)) {
-        virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(NULL);
     }
     virMutexLock(&conn->lock);
diff --git a/src/datatypes.h b/src/datatypes.h
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -95,6 +95,10 @@
  * Internal structure associated to a connection
  */
 struct _virConnect {
+    /* All the variables from here, until the 'lock' declaration
+     * are setup at time of connection open, and never changed
+     * since. Thus no need to lock when accessing them
+     */
     unsigned int magic;     /* specific value to check */
     int flags;              /* a set of connection flags */
     xmlURIPtr uri;          /* connection URI */
@@ -114,11 +118,6 @@ struct _virConnect {
     void *            storagePrivateData;
     void *            devMonPrivateData;
 
-    /* Per-connection error. */
-    virError err;           /* the last error */
-    virErrorFunc handler;   /* associated handlet */
-    void *userData;         /* the user data */
-
     /*
      * The lock mutex must be acquired before accessing/changing
      * any of members following this point, or changing the ref
@@ -126,6 +125,12 @@ struct _virConnect {
      * this connection
      */
     virMutex lock;
+
+    /* Per-connection error. */
+    virError err;           /* the last error */
+    virErrorFunc handler;   /* associated handlet */
+    void *userData;         /* the user data */
+
     virHashTablePtr domains;  /* hash table for known domains */
     virHashTablePtr networks; /* hash table for known domains */
     virHashTablePtr storagePools;/* hash table for known storage pools */
diff --git a/src/libvirt.c b/src/libvirt.c
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -256,7 +256,8 @@ virInitialize(void)
 
     initialized = 1;
 
-    if (virThreadInitialize() < 0)
+    if (virThreadInitialize() < 0 ||
+        virErrorInitialize() < 0)
         return -1;
 
 #ifdef ENABLE_DEBUG
@@ -847,6 +848,8 @@ do_open (const char *name,
     int i, res;
     virConnectPtr ret;
 
+    virResetLastError();
+
     ret = virGetConnect();
     if (ret == NULL)
         return NULL;
@@ -1000,17 +1003,8 @@ do_open (const char *name,
 failed:
     if (ret->driver) ret->driver->close (ret);
 
-    /* If no global error was set, copy any error set
-       in the connection object we're about to dispose of */
-    if (virLastErr.code == VIR_ERR_OK) {
-        memcpy(&virLastErr, &ret->err, sizeof(ret->err));
-        memset(&ret->err, 0, sizeof(ret->err));
-    }
-
-    /* Still no error set, then raise a generic error */
-    if (virLastErr.code == VIR_ERR_OK)
-        virLibConnError (NULL, VIR_ERR_INTERNAL_ERROR,
-                         _("unable to open connection"));
+    /* Ensure a global error is set in case driver forgot */
+    virSetGlobalError();
 
     virUnrefConnect(ret);
 
@@ -1105,8 +1099,12 @@ virConnectClose(virConnectPtr conn)
 {
     DEBUG("conn=%p", conn);
 
-    if (!VIR_IS_CONNECT(conn))
-        return (-1);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
 
     if (conn->networkDriver)
         conn->networkDriver->close (conn);
@@ -1128,12 +1126,20 @@ virConnectClose(virConnectPtr conn)
 int
 virDrvSupportsFeature (virConnectPtr conn, int feature)
 {
+    int ret;
     DEBUG("conn=%p, feature=%d", conn, feature);
 
-    if (!VIR_IS_CONNECT(conn))
-        return (-1);
-
-    return VIR_DRV_SUPPORTS_FEATURE (conn->driver, conn, feature);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    ret = VIR_DRV_SUPPORTS_FEATURE (conn->driver, conn, feature);
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
+    return ret;
 }
 
 /**
@@ -1153,6 +1159,8 @@ virConnectGetType(virConnectPtr conn)
     const char *ret;
     DEBUG("conn=%p", conn);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
@@ -1183,20 +1191,30 @@ virConnectGetVersion(virConnectPtr conn,
 {
     DEBUG("conn=%p, hvVer=%p", conn, hvVer);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return -1;
     }
 
     if (hvVer == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->driver->version)
-        return conn->driver->version (conn, hvVer);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->version) {
+        int ret = conn->driver->version (conn, hvVer);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -1217,15 +1235,25 @@ virConnectGetHostname (virConnectPtr con
 {
     DEBUG("conn=%p", conn);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return NULL;
-    }
-
-    if (conn->driver->getHostname)
-        return conn->driver->getHostname (conn);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return NULL;
+    }
+
+    if (conn->driver->getHostname) {
+        char *ret = conn->driver->getHostname (conn);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -1248,8 +1276,9 @@ char *
 virConnectGetURI (virConnectPtr conn)
 {
     char *name;
-
-    DEBUG("conn=%p", conn);
+    DEBUG("conn=%p", conn);
+
+    virResetLastError();
 
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
@@ -1259,15 +1288,23 @@ virConnectGetURI (virConnectPtr conn)
     /* Drivers may override getURI, but if they don't then
      * we provide a default implementation.
      */
-    if (conn->driver->getURI)
-        return conn->driver->getURI (conn);
+    if (conn->driver->getURI) {
+        name = conn->driver->getURI (conn);
+        if (!name)
+            goto error;
+    }
 
     name = (char *)xmlSaveUri(conn->uri);
     if (!name) {
         virLibConnError (conn, VIR_ERR_NO_MEMORY, __FUNCTION__);
-        return NULL;
+        goto error;
     }
     return name;
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
+    return NULL;
 }
 
 /**
@@ -1287,15 +1324,24 @@ virConnectGetMaxVcpus(virConnectPtr conn
 {
     DEBUG("conn=%p, type=%s", conn, type);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->driver->getMaxVcpus)
-        return conn->driver->getMaxVcpus (conn, type);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return -1;
+    }
+
+    if (conn->driver->getMaxVcpus) {
+        int ret = conn->driver->getMaxVcpus (conn, type);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -1314,20 +1360,29 @@ virConnectListDomains(virConnectPtr conn
 {
     DEBUG("conn=%p, ids=%p, maxids=%d", conn, ids, maxids);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return -1;
     }
 
     if ((ids == NULL) || (maxids < 0)) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->driver->listDomains)
-        return conn->driver->listDomains (conn, ids, maxids);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->listDomains) {
+        int ret = conn->driver->listDomains (conn, ids, maxids);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -1344,15 +1399,24 @@ virConnectNumOfDomains(virConnectPtr con
 {
     DEBUG("conn=%p", conn);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->driver->numOfDomains)
-        return conn->driver->numOfDomains (conn);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->numOfDomains) {
+        int ret = conn->driver->numOfDomains (conn);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -1375,7 +1439,9 @@ virDomainGetConnect (virDomainPtr dom)
 {
     DEBUG("dom=%p", dom);
 
-    if (!VIR_IS_DOMAIN (dom)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
         virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return NULL;
     }
@@ -1403,23 +1469,33 @@ virDomainCreateXML(virConnectPtr conn, c
 {
     DEBUG("conn=%p, xmlDesc=%s, flags=%d", conn, xmlDesc, flags);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (xmlDesc == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-    if (conn->flags & VIR_CONNECT_RO) {
-        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->driver->domainCreateXML)
-        return conn->driver->domainCreateXML (conn, xmlDesc, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainCreateXML) {
+        virDomainPtr ret;
+        ret = conn->driver->domainCreateXML (conn, xmlDesc, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -1459,19 +1535,30 @@ virDomainLookupByID(virConnectPtr conn, 
 {
     DEBUG("conn=%p, id=%d", conn, id);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (id < 0) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->driver->domainLookupByID)
-        return conn->driver->domainLookupByID (conn, id);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainLookupByID) {
+        virDomainPtr ret;
+        ret = conn->driver->domainLookupByID (conn, id);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -1490,19 +1577,30 @@ virDomainLookupByUUID(virConnectPtr conn
 {
     DEBUG("conn=%p, uuid=%s", conn, uuid);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (uuid == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->driver->domainLookupByUUID)
-        return conn->driver->domainLookupByUUID (conn, uuid);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainLookupByUUID) {
+        virDomainPtr ret;
+        ret = conn->driver->domainLookupByUUID (conn, uuid);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -1525,14 +1623,15 @@ virDomainLookupByUUIDString(virConnectPt
 
     DEBUG("conn=%p, uuidstr=%s", conn, uuidstr);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (uuidstr == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-
+        goto error;
     }
     /* XXX: sexpr_uuid() also supports 'xxxx-xxxx-xxxx-xxxx' format.
      *      We needn't it here. Right?
@@ -1550,12 +1649,17 @@ virDomainLookupByUUIDString(virConnectPt
 
     if (ret!=VIR_UUID_BUFLEN) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
+        goto error;
     }
     for (i = 0; i < VIR_UUID_BUFLEN; i++)
         uuid[i] = raw[i] & 0xFF;
 
     return virDomainLookupByUUID(conn, &uuid[0]);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
+    return NULL;
 }
 
 /**
@@ -1573,19 +1677,30 @@ virDomainLookupByName(virConnectPtr conn
 {
     DEBUG("conn=%p, name=%s", conn, name);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (name == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->driver->domainLookupByName)
-        return conn->driver->domainLookupByName (conn, name);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainLookupByName) {
+        virDomainPtr dom;
+        dom = conn->driver->domainLookupByName (conn, name);
+        if (!dom)
+            goto error;
+        return dom;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -1607,21 +1722,32 @@ virDomainDestroy(virDomainPtr domain)
 
     DEBUG("domain=%p", domain);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = domain->conn;
-    if (conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->driver->domainDestroy)
-        return conn->driver->domainDestroy (domain);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+
+    conn = domain->conn;
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainDestroy) {
+        int ret;
+        ret = conn->driver->domainDestroy (domain);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -1639,12 +1765,14 @@ virDomainFree(virDomainPtr domain)
 {
     DEBUG("domain=%p", domain);
 
-    if (!VIR_IS_DOMAIN(domain)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
         virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return (-1);
     }
     if (virUnrefDomain(domain) < 0)
-        return (-1);
+        return -1;
     return(0);
 }
 
@@ -1666,21 +1794,32 @@ virDomainSuspend(virDomainPtr domain)
     virConnectPtr conn;
     DEBUG("domain=%p", domain);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = domain->conn;
-
-    if (conn->driver->domainSuspend)
-        return conn->driver->domainSuspend (domain);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainSuspend) {
+        int ret;
+        ret = conn->driver->domainSuspend (domain);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -1700,21 +1839,32 @@ virDomainResume(virDomainPtr domain)
     virConnectPtr conn;
     DEBUG("domain=%p", domain);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = domain->conn;
-
-    if (conn->driver->domainResume)
-        return conn->driver->domainResume (domain);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainResume) {
+        int ret;
+        ret = conn->driver->domainResume (domain);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -1737,18 +1887,20 @@ virDomainSave(virDomainPtr domain, const
     virConnectPtr conn;
     DEBUG("domain=%p, to=%s", domain, to);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
     }
     conn = domain->conn;
     if (to == NULL) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     /*
@@ -1771,10 +1923,19 @@ virDomainSave(virDomainPtr domain, const
 
     }
 
-    if (conn->driver->domainSave)
-        return conn->driver->domainSave (domain, to);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->driver->domainSave) {
+        int ret;
+        ret = conn->driver->domainSave (domain, to);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -1793,17 +1954,19 @@ virDomainRestore(virConnectPtr conn, con
     char filepath[4096];
     DEBUG("conn=%p, from=%s", conn, from);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-    if (conn->flags & VIR_CONNECT_RO) {
-        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
     }
     if (from == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     /*
@@ -1814,21 +1977,36 @@ virDomainRestore(virConnectPtr conn, con
         unsigned int len, t;
 
         t = strlen(from);
-        if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL)
-            return (-1);
+        if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) {
+            virLibConnError(conn, VIR_ERR_SYSTEM_ERROR,
+                            _("cannot get working directory"));
+            goto error;
+        }
         len = strlen(filepath);
         /* that should be covered by getcwd() semantic, but be 100% sure */
-        if (len > sizeof(filepath) - (t + 3))
-            return (-1);
+        if (len > sizeof(filepath) - (t + 3)) {
+            virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
+                            _("path too long"));
+            goto error;
+        }
         filepath[len] = '/';
         strcpy(&filepath[len + 1], from);
         from = &filepath[0];
     }
 
-    if (conn->driver->domainRestore)
-        return conn->driver->domainRestore (conn, from);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->driver->domainRestore) {
+        int ret;
+        ret = conn->driver->domainRestore (conn, from);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -1851,18 +2029,20 @@ virDomainCoreDump(virDomainPtr domain, c
     virConnectPtr conn;
     DEBUG("domain=%p, to=%s, flags=%d", domain, to, flags);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
     }
     conn = domain->conn;
     if (to == NULL) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     /*
@@ -1873,22 +2053,37 @@ virDomainCoreDump(virDomainPtr domain, c
         unsigned int len, t;
 
         t = strlen(to);
-        if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL)
-            return (-1);
+        if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) {
+            virLibDomainError(domain, VIR_ERR_SYSTEM_ERROR,
+                              _("cannot get current directory"));
+            goto error;
+        }
         len = strlen(filepath);
         /* that should be covered by getcwd() semantic, but be 100% sure */
-        if (len > sizeof(filepath) - (t + 3))
-            return (-1);
+        if (len > sizeof(filepath) - (t + 3)) {
+            virLibDomainError(domain, VIR_ERR_INTERNAL_ERROR,
+                              _("path too long"));
+            goto error;
+        }
         filepath[len] = '/';
         strcpy(&filepath[len + 1], to);
         to = &filepath[0];
 
     }
 
-    if (conn->driver->domainCoreDump)
-        return conn->driver->domainCoreDump (domain, to, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->driver->domainCoreDump) {
+        int ret;
+        ret = conn->driver->domainCoreDump (domain, to, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -1911,21 +2106,32 @@ virDomainShutdown(virDomainPtr domain)
     virConnectPtr conn;
     DEBUG("domain=%p", domain);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = domain->conn;
-
-    if (conn->driver->domainShutdown)
-        return conn->driver->domainShutdown (domain);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainShutdown) {
+        int ret;
+        ret = conn->driver->domainShutdown (domain);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -1946,21 +2152,32 @@ virDomainReboot(virDomainPtr domain, uns
     virConnectPtr conn;
     DEBUG("domain=%p, flags=%u", domain, flags);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = domain->conn;
-
-    if (conn->driver->domainReboot)
-        return conn->driver->domainReboot (domain, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainReboot) {
+        int ret;
+        ret = conn->driver->domainReboot (domain, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -1978,6 +2195,8 @@ virDomainGetName(virDomainPtr domain)
 {
     DEBUG("domain=%p", domain);
 
+    virResetLastError();
+
     if (!VIR_IS_DOMAIN(domain)) {
         virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return (NULL);
@@ -1999,12 +2218,16 @@ virDomainGetUUID(virDomainPtr domain, un
 {
     DEBUG("domain=%p, uuid=%p", domain, uuid);
 
+    virResetLastError();
+
     if (!VIR_IS_DOMAIN(domain)) {
         virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return (-1);
     }
     if (uuid == NULL) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        /* Copy to connection error object for back compatability */
+        virSetConnError(domain->conn);
         return (-1);
     }
 
@@ -2029,20 +2252,27 @@ virDomainGetUUIDString(virDomainPtr doma
     unsigned char uuid[VIR_UUID_BUFLEN];
     DEBUG("domain=%p, buf=%p", domain, buf);
 
+    virResetLastError();
+
     if (!VIR_IS_DOMAIN(domain)) {
         virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return (-1);
     }
     if (buf == NULL) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     if (virDomainGetUUID(domain, &uuid[0]))
-        return (-1);
+        goto error;
 
     virUUIDFormat(uuid, buf);
     return (0);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
+    return -1;
 }
 
 /**
@@ -2058,6 +2288,8 @@ virDomainGetID(virDomainPtr domain)
 {
     DEBUG("domain=%p", domain);
 
+    virResetLastError();
+
     if (!VIR_IS_DOMAIN(domain)) {
         virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return ((unsigned int) -1);
@@ -2080,17 +2312,28 @@ virDomainGetOSType(virDomainPtr domain)
     virConnectPtr conn;
     DEBUG("domain=%p", domain);
 
-    if (!VIR_IS_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (NULL);
-    }
-
-    conn = domain->conn;
-
-    if (conn->driver->domainGetOSType)
-        return conn->driver->domainGetOSType (domain);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (NULL);
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainGetOSType) {
+        char *ret;
+        ret = conn->driver->domainGetOSType (domain);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return NULL;
 }
 
@@ -2110,6 +2353,8 @@ virDomainGetMaxMemory(virDomainPtr domai
     virConnectPtr conn;
     DEBUG("domain=%p", domain);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
         virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return (0);
@@ -2117,10 +2362,19 @@ virDomainGetMaxMemory(virDomainPtr domai
 
     conn = domain->conn;
 
-    if (conn->driver->domainGetMaxMemory)
-        return conn->driver->domainGetMaxMemory (domain);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->driver->domainGetMaxMemory) {
+        unsigned long ret;
+        ret = conn->driver->domainGetMaxMemory (domain);
+        if (ret == 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return 0;
 }
 
@@ -2142,28 +2396,35 @@ virDomainSetMaxMemory(virDomainPtr domai
     virConnectPtr conn;
     DEBUG("domain=%p, memory=%lu", domain, memory);
 
-    if (domain == NULL) {
-        TODO
-        return (-1);
-    }
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
     }
     if (memory < 4096) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-    conn = domain->conn;
-
-    if (conn->driver->domainSetMaxMemory)
-        return conn->driver->domainSetMaxMemory (domain, memory);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+    conn = domain->conn;
+
+    if (conn->driver->domainSetMaxMemory) {
+        int ret;
+        ret = conn->driver->domainSetMaxMemory (domain, memory);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -2185,29 +2446,36 @@ virDomainSetMemory(virDomainPtr domain, 
     virConnectPtr conn;
     DEBUG("domain=%p, memory=%lu", domain, memory);
 
-    if (domain == NULL) {
-        TODO
-        return (-1);
-    }
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
     }
     if (memory < 4096) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = domain->conn;
-
-    if (conn->driver->domainSetMemory)
-        return conn->driver->domainSetMemory (domain, memory);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainSetMemory) {
+        int ret;
+        ret = conn->driver->domainSetMemory (domain, memory);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -2228,23 +2496,34 @@ virDomainGetInfo(virDomainPtr domain, vi
     virConnectPtr conn;
     DEBUG("domain=%p, info=%p", domain, info);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
         virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return (-1);
     }
     if (info == NULL) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     memset(info, 0, sizeof(virDomainInfo));
 
     conn = domain->conn;
 
-    if (conn->driver->domainGetInfo)
-        return conn->driver->domainGetInfo (domain, info);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->driver->domainGetInfo) {
+        int ret;
+        ret = conn->driver->domainGetInfo (domain, info);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -2265,17 +2544,28 @@ virDomainGetXMLDesc(virDomainPtr domain,
     virConnectPtr conn;
     DEBUG("domain=%p, flags=%d", domain, flags);
 
-    if (!VIR_IS_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (NULL);
-    }
-
-    conn = domain->conn;
-
-    if (conn->driver->domainDumpXML)
-        return conn->driver->domainDumpXML (domain, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (NULL);
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainDumpXML) {
+        char *ret;
+        ret = conn->driver->domainDumpXML (domain, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return NULL;
 }
 
@@ -2344,24 +2634,26 @@ virDomainMigrate (virDomainPtr domain,
     DEBUG("domain=%p, dconn=%p, flags=%lu, dname=%s, uri=%s, bandwidth=%lu",
           domain, dconn, flags, dname, uri, bandwidth);
 
-    if (!VIR_IS_DOMAIN (domain)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN (domain)) {
         virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return NULL;
     }
     conn = domain->conn;        /* Source connection. */
     if (!VIR_IS_CONNECT (dconn)) {
         virLibConnError (conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return NULL;
-    }
-
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return NULL;
+        goto error;
+    }
+
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
     }
     if (dconn->flags & VIR_CONNECT_RO) {
         /* NB, delibrately report error against source object, not dest here */
         virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return NULL;
+        goto error;
     }
 
     /* Check that migration is supported by both drivers. */
@@ -2377,7 +2669,7 @@ virDomainMigrate (virDomainPtr domain,
         version = 2;
     else {
         virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-        return NULL;
+        goto error;
     }
 
     /* Prepare the migration.
@@ -2412,13 +2704,13 @@ virDomainMigrate (virDomainPtr domain,
          */
         if (!conn->driver->domainDumpXML) {
             virLibConnError (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__);
-            return NULL;
+            goto error;
         }
         dom_xml = conn->driver->domainDumpXML (domain,
                                                VIR_DOMAIN_XML_SECURE);
 
         if (!dom_xml)
-            return NULL;
+            goto error;
 
         ret = dconn->driver->domainMigratePrepare2
             (dconn, &cookie, &cookielen, uri, &uri_out, flags, dname,
@@ -2468,6 +2760,11 @@ virDomainMigrate (virDomainPtr domain,
     free (uri_out);
     free (cookie);
     return ddomain;
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
+    return NULL;
 }
 
 /*
@@ -2486,6 +2783,8 @@ virDomainMigratePrepare (virConnectPtr d
 {
     DEBUG("dconn=%p, cookie=%p, cookielen=%p, uri_in=%s, uri_out=%p, flags=%lu, dname=%s, bandwidth=%lu", dconn, cookie, cookielen, uri_in, uri_out, flags, dname, bandwidth);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT (dconn)) {
         virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return -1;
@@ -2493,15 +2792,24 @@ virDomainMigratePrepare (virConnectPtr d
 
     if (dconn->flags & VIR_CONNECT_RO) {
         virLibConnError(dconn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return -1;
-    }
-
-    if (dconn->driver->domainMigratePrepare)
-        return dconn->driver->domainMigratePrepare (dconn, cookie, cookielen,
-                                                    uri_in, uri_out,
-                                                    flags, dname, bandwidth);
+        goto error;
+    }
+
+    if (dconn->driver->domainMigratePrepare) {
+        int ret;
+        ret = dconn->driver->domainMigratePrepare (dconn, cookie, cookielen,
+                                                   uri_in, uri_out,
+                                                   flags, dname, bandwidth);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
 
     virLibConnError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(dconn);
     return -1;
 }
 
@@ -2521,7 +2829,9 @@ virDomainMigratePerform (virDomainPtr do
     virConnectPtr conn;
     DEBUG("domain=%p, cookie=%p, cookielen=%d, uri=%s, flags=%lu, dname=%s, bandwidth=%lu", domain, cookie, cookielen, uri, flags, dname, bandwidth);
 
-    if (!VIR_IS_DOMAIN (domain)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN (domain)) {
         virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return -1;
     }
@@ -2529,15 +2839,24 @@ virDomainMigratePerform (virDomainPtr do
 
     if (domain->conn->flags & VIR_CONNECT_RO) {
         virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return -1;
-    }
-
-    if (conn->driver->domainMigratePerform)
-        return conn->driver->domainMigratePerform (domain, cookie, cookielen,
-                                                   uri,
-                                                   flags, dname, bandwidth);
+        goto error;
+    }
+
+    if (conn->driver->domainMigratePerform) {
+        int ret;
+        ret = conn->driver->domainMigratePerform (domain, cookie, cookielen,
+                                                  uri,
+                                                  flags, dname, bandwidth);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
 
     virLibDomainError (domain, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -2555,6 +2874,8 @@ virDomainMigrateFinish (virConnectPtr dc
 {
     DEBUG("dconn=%p, dname=%s, cookie=%p, cookielen=%d, uri=%s, flags=%lu", dconn, dname, cookie, cookielen, uri, flags);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT (dconn)) {
         virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return NULL;
@@ -2562,15 +2883,24 @@ virDomainMigrateFinish (virConnectPtr dc
 
     if (dconn->flags & VIR_CONNECT_RO) {
         virLibConnError(dconn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return NULL;
-    }
-
-    if (dconn->driver->domainMigrateFinish)
-        return dconn->driver->domainMigrateFinish (dconn, dname,
-                                                   cookie, cookielen,
-                                                   uri, flags);
+        goto error;
+    }
+
+    if (dconn->driver->domainMigrateFinish) {
+        virDomainPtr ret;
+        ret = dconn->driver->domainMigrateFinish (dconn, dname,
+                                                  cookie, cookielen,
+                                                  uri, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
 
     virLibConnError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(dconn);
     return NULL;
 }
 
@@ -2592,6 +2922,8 @@ virDomainMigratePrepare2 (virConnectPtr 
 {
     DEBUG("dconn=%p, cookie=%p, cookielen=%p, uri_in=%s, uri_out=%p, flags=%lu, dname=%s, bandwidth=%lu, dom_xml=%s", dconn, cookie, cookielen, uri_in, uri_out, flags, dname, bandwidth, dom_xml);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT (dconn)) {
         virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return -1;
@@ -2599,16 +2931,25 @@ virDomainMigratePrepare2 (virConnectPtr 
 
     if (dconn->flags & VIR_CONNECT_RO) {
         virLibConnError(dconn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return -1;
-    }
-
-    if (dconn->driver->domainMigratePrepare2)
-        return dconn->driver->domainMigratePrepare2 (dconn, cookie, cookielen,
-                                                     uri_in, uri_out,
-                                                     flags, dname, bandwidth,
-                                                     dom_xml);
+        goto error;
+    }
+
+    if (dconn->driver->domainMigratePrepare2) {
+        int ret;
+        ret = dconn->driver->domainMigratePrepare2 (dconn, cookie, cookielen,
+                                                    uri_in, uri_out,
+                                                    flags, dname, bandwidth,
+                                                    dom_xml);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
 
     virLibConnError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(dconn);
     return -1;
 }
 
@@ -2627,6 +2968,8 @@ virDomainMigrateFinish2 (virConnectPtr d
 {
     DEBUG("dconn=%p, dname=%s, cookie=%p, cookielen=%d, uri=%s, flags=%lu, retcode=%d", dconn, dname, cookie, cookielen, uri, flags, retcode);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT (dconn)) {
         virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return NULL;
@@ -2634,16 +2977,25 @@ virDomainMigrateFinish2 (virConnectPtr d
 
     if (dconn->flags & VIR_CONNECT_RO) {
         virLibConnError(dconn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return NULL;
-    }
-
-    if (dconn->driver->domainMigrateFinish2)
-        return dconn->driver->domainMigrateFinish2 (dconn, dname,
-                                                    cookie, cookielen,
-                                                    uri, flags,
-                                                    retcode);
+        goto error;
+    }
+
+    if (dconn->driver->domainMigrateFinish2) {
+        virDomainPtr ret;
+        ret = dconn->driver->domainMigrateFinish2 (dconn, dname,
+                                                   cookie, cookielen,
+                                                   uri, flags,
+                                                   retcode);
+        if (!ret)
+            goto error;
+        return ret;
+    }
 
     virLibConnError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(dconn);
     return NULL;
 }
 
@@ -2662,19 +3014,30 @@ virNodeGetInfo(virConnectPtr conn, virNo
 {
     DEBUG("conn=%p, info=%p", conn, info);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (-1);
     }
     if (info == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->driver->nodeGetInfo)
-        return conn->driver->nodeGetInfo (conn, info);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->nodeGetInfo) {
+        int ret;
+        ret = conn->driver->nodeGetInfo (conn, info);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -2693,15 +3056,26 @@ virConnectGetCapabilities (virConnectPtr
 {
     DEBUG("conn=%p", conn);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT (conn)) {
         virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return NULL;
     }
 
-    if (conn->driver->getCapabilities)
-        return conn->driver->getCapabilities (conn);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->driver->getCapabilities) {
+        char *ret;
+        ret = conn->driver->getCapabilities (conn);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -2718,15 +3092,26 @@ virNodeGetFreeMemory(virConnectPtr conn)
 {
     DEBUG("conn=%p", conn);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT (conn)) {
         virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return 0;
     }
 
-    if (conn->driver->getFreeMemory)
-        return conn->driver->getFreeMemory (conn);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->driver->getFreeMemory) {
+        unsigned long long ret;
+        ret = conn->driver->getFreeMemory (conn);
+        if (ret == 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return 0;
 }
 
@@ -2746,6 +3131,8 @@ virDomainGetSchedulerType(virDomainPtr d
     char *schedtype;
     DEBUG("domain=%p, nparams=%p", domain, nparams);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
         virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return NULL;
@@ -2754,10 +3141,16 @@ virDomainGetSchedulerType(virDomainPtr d
 
     if (conn->driver->domainGetSchedulerType){
         schedtype = conn->driver->domainGetSchedulerType (domain, nparams);
+        if (!schedtype)
+            goto error;
         return schedtype;
     }
 
     virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return NULL;
 }
 
@@ -2783,16 +3176,27 @@ virDomainGetSchedulerParameters(virDomai
     virConnectPtr conn;
     DEBUG("domain=%p, params=%p, nparams=%p", domain, params, nparams);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return -1;
-    }
-    conn = domain->conn;
-
-    if (conn->driver->domainGetSchedulerParameters)
-        return conn->driver->domainGetSchedulerParameters (domain, params, nparams);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return -1;
+    }
+    conn = domain->conn;
+
+    if (conn->driver->domainGetSchedulerParameters) {
+        int ret;
+        ret = conn->driver->domainGetSchedulerParameters (domain, params, nparams);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -2815,20 +3219,31 @@ virDomainSetSchedulerParameters(virDomai
     virConnectPtr conn;
     DEBUG("domain=%p, params=%p, nparams=%d", domain, params, nparams);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return -1;
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return -1;
-    }
-    conn = domain->conn;
-
-    if (conn->driver->domainSetSchedulerParameters)
-        return conn->driver->domainSetSchedulerParameters (domain, params, nparams);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return -1;
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+    conn = domain->conn;
+
+    if (conn->driver->domainSetSchedulerParameters) {
+        int ret;
+        ret = conn->driver->domainSetSchedulerParameters (domain, params, nparams);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -2864,25 +3279,31 @@ virDomainBlockStats (virDomainPtr dom, c
     struct _virDomainBlockStats stats2 = { -1, -1, -1, -1, -1 };
     DEBUG("domain=%p, path=%s, stats=%p, size=%zi", dom, path, stats, size);
 
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
+        virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return -1;
+    }
     if (!stats || size > sizeof stats2) {
         virLibDomainError (dom, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return -1;
-    }
-    if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
-        virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return -1;
+        goto error;
     }
     conn = dom->conn;
 
     if (conn->driver->domainBlockStats) {
         if (conn->driver->domainBlockStats (dom, path, &stats2) == -1)
-            return -1;
+            goto error;
 
         memcpy (stats, &stats2, size);
         return 0;
     }
 
     virLibDomainError (dom, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(dom->conn);
     return -1;
 }
 
@@ -2916,25 +3337,31 @@ virDomainInterfaceStats (virDomainPtr do
                                                -1, -1, -1, -1 };
     DEBUG("domain=%p, path=%s, stats=%p, size=%zi", dom, path, stats, size);
 
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
+        virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return -1;
+    }
     if (!stats || size > sizeof stats2) {
         virLibDomainError (dom, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return -1;
-    }
-    if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
-        virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return -1;
+        goto error;
     }
     conn = dom->conn;
 
     if (conn->driver->domainInterfaceStats) {
         if (conn->driver->domainInterfaceStats (dom, path, &stats2) == -1)
-            return -1;
+            goto error;
 
         memcpy (stats, &stats2, size);
         return 0;
     }
 
     virLibDomainError (dom, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(dom->conn);
     return -1;
 }
 
@@ -2989,6 +3416,8 @@ virDomainBlockPeek (virDomainPtr dom,
     DEBUG("domain=%p, path=%s, offset=%lld, size=%zi, buffer=%p",
           dom, path, offset, size, buffer);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
         virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return -1;
@@ -2997,33 +3426,42 @@ virDomainBlockPeek (virDomainPtr dom,
 
     if (dom->conn->flags & VIR_CONNECT_RO) {
         virLibDomainError(dom, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     if (!path) {
         virLibDomainError (dom, VIR_ERR_INVALID_ARG,
                            _("path is NULL"));
-        return -1;
+        goto error;
     }
 
     if (flags != 0) {
         virLibDomainError (dom, VIR_ERR_INVALID_ARG,
                            _("flags must be zero"));
-        return -1;
+        goto error;
     }
 
     /* Allow size == 0 as an access test. */
     if (size > 0 && !buffer) {
         virLibDomainError (dom, VIR_ERR_INVALID_ARG,
                            _("buffer is NULL"));
-        return -1;
-    }
-
-    if (conn->driver->domainBlockPeek)
-        return conn->driver->domainBlockPeek (dom, path, offset, size,
-                                              buffer, flags);
+        goto error;
+    }
+
+    if (conn->driver->domainBlockPeek) {
+        int ret;
+        ret =conn->driver->domainBlockPeek (dom, path, offset, size,
+                                            buffer, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
 
     virLibDomainError (dom, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(dom->conn);
     return -1;
 }
 
@@ -3069,6 +3507,8 @@ virDomainMemoryPeek (virDomainPtr dom,
     DEBUG ("domain=%p, start=%lld, size=%zi, buffer=%p, flags=%d",
            dom, start, size, buffer, flags);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
         virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return -1;
@@ -3077,7 +3517,7 @@ virDomainMemoryPeek (virDomainPtr dom,
 
     if (dom->conn->flags & VIR_CONNECT_RO) {
         virLibDomainError(dom, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     /* Flags must be VIR_MEMORY_VIRTUAL at the moment.
@@ -3104,21 +3544,30 @@ virDomainMemoryPeek (virDomainPtr dom,
     if (flags != VIR_MEMORY_VIRTUAL) {
         virLibDomainError (dom, VIR_ERR_INVALID_ARG,
                            _("flags parameter must be VIR_MEMORY_VIRTUAL"));
-        return -1;
+        goto error;
     }
 
     /* Allow size == 0 as an access test. */
     if (size > 0 && !buffer) {
         virLibDomainError (dom, VIR_ERR_INVALID_ARG,
                            _("buffer is NULL but size is non-zero"));
-        return -1;
-    }
-
-    if (conn->driver->domainMemoryPeek)
-        return conn->driver->domainMemoryPeek (dom, start, size,
-                                               buffer, flags);
+        goto error;
+    }
+
+    if (conn->driver->domainMemoryPeek) {
+        int ret;
+        ret = conn->driver->domainMemoryPeek (dom, start, size,
+                                              buffer, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
 
     virLibDomainError (dom, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(dom->conn);
     return -1;
 }
 
@@ -3144,23 +3593,34 @@ virDomainPtr
 virDomainDefineXML(virConnectPtr conn, const char *xml) {
     DEBUG("conn=%p, xml=%s", conn, xml);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (NULL);
-    }
-    if (conn->flags & VIR_CONNECT_RO) {
-        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (NULL);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
     }
     if (xml == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->driver->domainDefineXML)
-        return conn->driver->domainDefineXML (conn, xml);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainDefineXML) {
+        virDomainPtr ret;
+        ret = conn->driver->domainDefineXML (conn, xml);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -3177,20 +3637,31 @@ virDomainUndefine(virDomainPtr domain) {
     virConnectPtr conn;
     DEBUG("domain=%p", domain);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    conn = domain->conn;
-    if (conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->driver->domainUndefine)
-        return conn->driver->domainUndefine (domain);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    conn = domain->conn;
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainUndefine) {
+        int ret;
+        ret = conn->driver->domainUndefine (domain);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -3207,15 +3678,26 @@ virConnectNumOfDefinedDomains(virConnect
 {
     DEBUG("conn=%p", conn);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->driver->numOfDefinedDomains)
-        return conn->driver->numOfDefinedDomains (conn);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->driver->numOfDefinedDomains) {
+        int ret;
+        ret = conn->driver->numOfDefinedDomains (conn);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -3235,6 +3717,8 @@ virConnectListDefinedDomains(virConnectP
                              int maxnames) {
     DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (-1);
@@ -3242,13 +3726,22 @@ virConnectListDefinedDomains(virConnectP
 
     if ((names == NULL) || (maxnames < 0)) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->driver->listDefinedDomains)
-        return conn->driver->listDefinedDomains (conn, names, maxnames);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->listDefinedDomains) {
+        int ret;
+        ret = conn->driver->listDefinedDomains (conn, names, maxnames);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -3266,24 +3759,31 @@ virDomainCreate(virDomainPtr domain) {
     virConnectPtr conn;
     DEBUG("domain=%p", domain);
 
-    if (domain == NULL) {
-        TODO
-        return (-1);
-    }
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    conn = domain->conn;
-    if (conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->driver->domainCreate)
-        return conn->driver->domainCreate (domain);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    conn = domain->conn;
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainCreate) {
+        int ret;
+        ret = conn->driver->domainCreate (domain);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -3305,21 +3805,32 @@ virDomainGetAutostart(virDomainPtr domai
     virConnectPtr conn;
     DEBUG("domain=%p, autostart=%p", domain, autostart);
 
-    if (!VIR_IS_DOMAIN(domain)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
         virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return (-1);
     }
     if (!autostart) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = domain->conn;
-
-    if (conn->driver->domainGetAutostart)
-        return conn->driver->domainGetAutostart (domain, autostart);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainGetAutostart) {
+        int ret;
+        ret = conn->driver->domainGetAutostart (domain, autostart);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -3340,22 +3851,33 @@ virDomainSetAutostart(virDomainPtr domai
     virConnectPtr conn;
     DEBUG("domain=%p, autostart=%d", domain, autostart);
 
-    if (!VIR_IS_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = domain->conn;
-
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->driver->domainSetAutostart)
-        return conn->driver->domainSetAutostart (domain, autostart);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+
+    conn = domain->conn;
+
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainSetAutostart) {
+        int ret;
+        ret = conn->driver->domainSetAutostart (domain, autostart);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -3378,29 +3900,36 @@ virDomainSetVcpus(virDomainPtr domain, u
     virConnectPtr conn;
     DEBUG("domain=%p, nvcpus=%u", domain, nvcpus);
 
-    if (domain == NULL) {
-        TODO
-        return (-1);
-    }
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
     }
 
     if (nvcpus < 1) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-    conn = domain->conn;
-
-    if (conn->driver->domainSetVcpus)
-        return conn->driver->domainSetVcpus (domain, nvcpus);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+    conn = domain->conn;
+
+    if (conn->driver->domainSetVcpus) {
+        int ret;
+        ret = conn->driver->domainSetVcpus (domain, nvcpus);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -3429,30 +3958,37 @@ virDomainPinVcpu(virDomainPtr domain, un
     virConnectPtr conn;
     DEBUG("domain=%p, vcpu=%u, cpumap=%p, maplen=%d", domain, vcpu, cpumap, maplen);
 
-    if (domain == NULL) {
-        TODO
-        return (-1);
-    }
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
     }
 
     if ((vcpu > 32000) || (cpumap == NULL) || (maplen < 1)) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = domain->conn;
-
-    if (conn->driver->domainPinVcpu)
-        return conn->driver->domainPinVcpu (domain, vcpu, cpumap, maplen);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+       goto error;
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainPinVcpu) {
+        int ret;
+        ret = conn->driver->domainPinVcpu (domain, vcpu, cpumap, maplen);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -3484,30 +4020,37 @@ virDomainGetVcpus(virDomainPtr domain, v
     virConnectPtr conn;
     DEBUG("domain=%p, info=%p, maxinfo=%d, cpumaps=%p, maplen=%d", domain, info, maxinfo, cpumaps, maplen);
 
-    if (domain == NULL) {
-        TODO
-        return (-1);
-    }
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
         virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
         return (-1);
     }
     if ((info == NULL) || (maxinfo < 1)) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
     if (cpumaps != NULL && maplen < 1) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = domain->conn;
-
-    if (conn->driver->domainGetVcpus)
-        return conn->driver->domainGetVcpus (domain, info, maxinfo,
-                                             cpumaps, maplen);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainGetVcpus) {
+        int ret;
+        ret = conn->driver->domainGetVcpus (domain, info, maxinfo,
+                                            cpumaps, maplen);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -3529,17 +4072,28 @@ virDomainGetMaxVcpus(virDomainPtr domain
     virConnectPtr conn;
     DEBUG("domain=%p", domain);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = domain->conn;
-
-    if (conn->driver->domainGetMaxVcpus)
-        return conn->driver->domainGetMaxVcpus (domain);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainGetMaxVcpus) {
+        int ret;
+        ret = conn->driver->domainGetMaxVcpus (domain);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -3559,20 +4113,31 @@ virDomainAttachDevice(virDomainPtr domai
     virConnectPtr conn;
     DEBUG("domain=%p, xml=%s", domain, xml);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-    conn = domain->conn;
-
-    if (conn->driver->domainAttachDevice)
-        return conn->driver->domainAttachDevice (domain, xml);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+    conn = domain->conn;
+
+    if (conn->driver->domainAttachDevice) {
+        int ret;
+        ret = conn->driver->domainAttachDevice (domain, xml);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -3591,20 +4156,31 @@ virDomainDetachDevice(virDomainPtr domai
     virConnectPtr conn;
     DEBUG("domain=%p, xml=%s", domain, xml);
 
-    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
-        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
-        return (-1);
-    }
-    if (domain->conn->flags & VIR_CONNECT_RO) {
-        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-    conn = domain->conn;
-
-    if (conn->driver->domainDetachDevice)
-        return conn->driver->domainDetachDevice (domain, xml);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+    conn = domain->conn;
+
+    if (conn->driver->domainDetachDevice) {
+        int ret;
+        ret = conn->driver->domainDetachDevice (domain, xml);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(domain->conn);
     return -1;
 }
 
@@ -3633,6 +4209,8 @@ virNodeGetCellsFreeMemory(virConnectPtr 
     DEBUG("conn=%p, freeMems=%p, startCell=%d, maxCells=%d",
           conn, freeMems, startCell, maxCells);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (-1);
@@ -3640,13 +4218,22 @@ virNodeGetCellsFreeMemory(virConnectPtr 
 
     if ((freeMems == NULL) || (maxCells <= 0) || (startCell < 0)) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->driver->nodeGetCellsFreeMemory)
-        return conn->driver->nodeGetCellsFreeMemory (conn, freeMems, startCell, maxCells);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->nodeGetCellsFreeMemory) {
+        int ret;
+        ret = conn->driver->nodeGetCellsFreeMemory (conn, freeMems, startCell, maxCells);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -3669,7 +4256,9 @@ virNetworkGetConnect (virNetworkPtr net)
 {
     DEBUG("net=%p", net);
 
-    if (!VIR_IS_NETWORK (net)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_NETWORK (net)) {
         virLibNetworkError (NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return NULL;
     }
@@ -3689,15 +4278,26 @@ virConnectNumOfNetworks(virConnectPtr co
 {
     DEBUG("conn=%p", conn);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->networkDriver && conn->networkDriver->numOfNetworks)
-        return conn->networkDriver->numOfNetworks (conn);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->networkDriver && conn->networkDriver->numOfNetworks) {
+        int ret;
+        ret = conn->networkDriver->numOfNetworks (conn);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -3716,6 +4316,8 @@ virConnectListNetworks(virConnectPtr con
 {
     DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (-1);
@@ -3723,13 +4325,22 @@ virConnectListNetworks(virConnectPtr con
 
     if ((names == NULL) || (maxnames < 0)) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->networkDriver && conn->networkDriver->listNetworks)
-        return conn->networkDriver->listNetworks (conn, names, maxnames);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->networkDriver && conn->networkDriver->listNetworks) {
+        int ret;
+        ret = conn->networkDriver->listNetworks (conn, names, maxnames);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -3746,15 +4357,26 @@ virConnectNumOfDefinedNetworks(virConnec
 {
     DEBUG("conn=%p", conn);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->networkDriver && conn->networkDriver->numOfDefinedNetworks)
-        return conn->networkDriver->numOfDefinedNetworks (conn);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->networkDriver && conn->networkDriver->numOfDefinedNetworks) {
+        int ret;
+        ret = conn->networkDriver->numOfDefinedNetworks (conn);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -3774,6 +4396,8 @@ virConnectListDefinedNetworks(virConnect
 {
     DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (-1);
@@ -3781,14 +4405,23 @@ virConnectListDefinedNetworks(virConnect
 
     if ((names == NULL) || (maxnames < 0)) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->networkDriver && conn->networkDriver->listDefinedNetworks)
-        return conn->networkDriver->listDefinedNetworks (conn,
-                                                         names, maxnames);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->networkDriver && conn->networkDriver->listDefinedNetworks) {
+        int ret;
+        ret = conn->networkDriver->listDefinedNetworks (conn,
+                                                        names, maxnames);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -3807,19 +4440,30 @@ virNetworkLookupByName(virConnectPtr con
 {
     DEBUG("conn=%p, name=%s", conn, name);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (name == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->networkDriver && conn->networkDriver->networkLookupByName)
-        return conn->networkDriver->networkLookupByName (conn, name);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto  error;
+    }
+
+    if (conn->networkDriver && conn->networkDriver->networkLookupByName) {
+        virNetworkPtr ret;
+        ret = conn->networkDriver->networkLookupByName (conn, name);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -3838,19 +4482,30 @@ virNetworkLookupByUUID(virConnectPtr con
 {
     DEBUG("conn=%p, uuid=%s", conn, uuid);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (uuid == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->networkDriver && conn->networkDriver->networkLookupByUUID)
-        return conn->networkDriver->networkLookupByUUID (conn, uuid);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->networkDriver && conn->networkDriver->networkLookupByUUID){
+        virNetworkPtr ret;
+        ret = conn->networkDriver->networkLookupByUUID (conn, uuid);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -3872,13 +4527,15 @@ virNetworkLookupByUUIDString(virConnectP
     int ret;
     DEBUG("conn=%p, uuidstr=%s", conn, uuidstr);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (uuidstr == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
+        goto error;
     }
 
     /* XXX: sexpr_uuid() also supports 'xxxx-xxxx-xxxx-xxxx' format.
@@ -3897,12 +4554,17 @@ virNetworkLookupByUUIDString(virConnectP
 
     if (ret!=VIR_UUID_BUFLEN) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
+        goto error;
     }
     for (i = 0; i < VIR_UUID_BUFLEN; i++)
         uuid[i] = raw[i] & 0xFF;
 
     return virNetworkLookupByUUID(conn, &uuid[0]);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
+    return NULL;
 }
 
 /**
@@ -3920,23 +4582,34 @@ virNetworkCreateXML(virConnectPtr conn, 
 {
     DEBUG("conn=%p, xmlDesc=%s", conn, xmlDesc);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (xmlDesc == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-    if (conn->flags & VIR_CONNECT_RO) {
-        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->networkDriver && conn->networkDriver->networkCreateXML)
-        return conn->networkDriver->networkCreateXML (conn, xmlDesc);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->networkDriver && conn->networkDriver->networkCreateXML) {
+        virNetworkPtr ret;
+        ret = conn->networkDriver->networkCreateXML (conn, xmlDesc);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -3954,23 +4627,34 @@ virNetworkDefineXML(virConnectPtr conn, 
 {
     DEBUG("conn=%p, xml=%s", conn, xml);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (NULL);
-    }
-    if (conn->flags & VIR_CONNECT_RO) {
-        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (NULL);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
     }
     if (xml == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->networkDriver && conn->networkDriver->networkDefineXML)
-        return conn->networkDriver->networkDefineXML (conn, xml);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->networkDriver && conn->networkDriver->networkDefineXML) {
+        virNetworkPtr ret;
+        ret = conn->networkDriver->networkDefineXML (conn, xml);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -3987,6 +4671,8 @@ virNetworkUndefine(virNetworkPtr network
     virConnectPtr conn;
     DEBUG("network=%p", network);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_NETWORK(network)) {
         virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (-1);
@@ -3994,13 +4680,22 @@ virNetworkUndefine(virNetworkPtr network
     conn = network->conn;
     if (conn->flags & VIR_CONNECT_RO) {
         virLibNetworkError(network, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->networkDriver && conn->networkDriver->networkUndefine)
-        return conn->networkDriver->networkUndefine (network);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->networkDriver && conn->networkDriver->networkUndefine) {
+        int ret;
+        ret = conn->networkDriver->networkUndefine (network);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(network->conn);
     return -1;
 }
 
@@ -4019,10 +4714,8 @@ virNetworkCreate(virNetworkPtr network)
     virConnectPtr conn;
     DEBUG("network=%p", network);
 
-    if (network == NULL) {
-        TODO
-        return (-1);
-    }
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_NETWORK(network)) {
         virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (-1);
@@ -4030,13 +4723,22 @@ virNetworkCreate(virNetworkPtr network)
     conn = network->conn;
     if (conn->flags & VIR_CONNECT_RO) {
         virLibNetworkError(network, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->networkDriver && conn->networkDriver->networkCreate)
-        return conn->networkDriver->networkCreate (network);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->networkDriver && conn->networkDriver->networkCreate) {
+        int ret;
+        ret = conn->networkDriver->networkCreate (network);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(network->conn);
     return -1;
 }
 
@@ -4057,6 +4759,8 @@ virNetworkDestroy(virNetworkPtr network)
     virConnectPtr conn;
     DEBUG("network=%p", network);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_NETWORK(network)) {
         virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (-1);
@@ -4065,13 +4769,22 @@ virNetworkDestroy(virNetworkPtr network)
     conn = network->conn;
     if (conn->flags & VIR_CONNECT_RO) {
         virLibNetworkError(network, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->networkDriver && conn->networkDriver->networkDestroy)
-        return conn->networkDriver->networkDestroy (network);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->networkDriver && conn->networkDriver->networkDestroy) {
+        int ret;
+        ret = conn->networkDriver->networkDestroy (network);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(network->conn);
     return -1;
 }
 
@@ -4089,7 +4802,9 @@ virNetworkFree(virNetworkPtr network)
 {
     DEBUG("network=%p", network);
 
-    if (!VIR_IS_NETWORK(network)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_NETWORK(network)) {
         virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (-1);
     }
@@ -4112,6 +4827,8 @@ virNetworkGetName(virNetworkPtr network)
 {
     DEBUG("network=%p", network);
 
+    virResetLastError();
+
     if (!VIR_IS_NETWORK(network)) {
         virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (NULL);
@@ -4133,18 +4850,25 @@ virNetworkGetUUID(virNetworkPtr network,
 {
     DEBUG("network=%p, uuid=%p", network, uuid);
 
+    virResetLastError();
+
     if (!VIR_IS_NETWORK(network)) {
         virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (-1);
     }
     if (uuid == NULL) {
         virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     memcpy(uuid, &network->uuid[0], VIR_UUID_BUFLEN);
 
     return (0);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(network->conn);
+    return -1;
 }
 
 /**
@@ -4163,13 +4887,15 @@ virNetworkGetUUIDString(virNetworkPtr ne
     unsigned char uuid[VIR_UUID_BUFLEN];
     DEBUG("network=%p, buf=%p", network, buf);
 
+    virResetLastError();
+
     if (!VIR_IS_NETWORK(network)) {
         virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (-1);
     }
     if (buf == NULL) {
         virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     if (virNetworkGetUUID(network, &uuid[0]))
@@ -4177,6 +4903,11 @@ virNetworkGetUUIDString(virNetworkPtr ne
 
     virUUIDFormat(uuid, buf);
     return (0);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(network->conn);
+    return -1;
 }
 
 /**
@@ -4196,21 +4927,32 @@ virNetworkGetXMLDesc(virNetworkPtr netwo
     virConnectPtr conn;
     DEBUG("network=%p, flags=%d", network, flags);
 
-    if (!VIR_IS_NETWORK(network)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_NETWORK(network)) {
         virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (NULL);
     }
     if (flags != 0) {
         virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
+        goto error;
     }
 
     conn = network->conn;
 
-    if (conn->networkDriver && conn->networkDriver->networkDumpXML)
-        return conn->networkDriver->networkDumpXML (network, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->networkDriver && conn->networkDriver->networkDumpXML) {
+        char *ret;
+        ret = conn->networkDriver->networkDumpXML (network, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(network->conn);
     return NULL;
 }
 
@@ -4230,17 +4972,28 @@ virNetworkGetBridgeName(virNetworkPtr ne
     virConnectPtr conn;
     DEBUG("network=%p", network);
 
-    if (!VIR_IS_NETWORK(network)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_NETWORK(network)) {
         virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (NULL);
     }
 
     conn = network->conn;
 
-    if (conn->networkDriver && conn->networkDriver->networkGetBridgeName)
-        return conn->networkDriver->networkGetBridgeName (network);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->networkDriver && conn->networkDriver->networkGetBridgeName) {
+        char *ret;
+        ret = conn->networkDriver->networkGetBridgeName (network);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(network->conn);
     return NULL;
 }
 
@@ -4262,21 +5015,32 @@ virNetworkGetAutostart(virNetworkPtr net
     virConnectPtr conn;
     DEBUG("network=%p, autostart=%p", network, autostart);
 
-    if (!VIR_IS_NETWORK(network)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_NETWORK(network)) {
         virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (-1);
     }
     if (!autostart) {
         virLibNetworkError(network, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     conn = network->conn;
 
-    if (conn->networkDriver && conn->networkDriver->networkGetAutostart)
-        return conn->networkDriver->networkGetAutostart (network, autostart);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->networkDriver && conn->networkDriver->networkGetAutostart) {
+        int ret;
+        ret = conn->networkDriver->networkGetAutostart (network, autostart);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(network->conn);
     return -1;
 }
 
@@ -4297,22 +5061,33 @@ virNetworkSetAutostart(virNetworkPtr net
     virConnectPtr conn;
     DEBUG("network=%p, autostart=%d", network, autostart);
 
-    if (!VIR_IS_NETWORK(network)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_NETWORK(network)) {
         virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (-1);
     }
 
     if (network->conn->flags & VIR_CONNECT_RO) {
         virLibNetworkError(network, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     conn = network->conn;
 
-    if (conn->networkDriver && conn->networkDriver->networkSetAutostart)
-        return conn->networkDriver->networkSetAutostart (network, autostart);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->networkDriver && conn->networkDriver->networkSetAutostart) {
+        int ret;
+        ret = conn->networkDriver->networkSetAutostart (network, autostart);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(network->conn);
     return -1;
 }
 
@@ -4336,7 +5111,9 @@ virStoragePoolGetConnect (virStoragePool
 {
     DEBUG("pool=%p", pool);
 
-    if (!VIR_IS_STORAGE_POOL (pool)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_STORAGE_POOL (pool)) {
         virLibStoragePoolError (NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return NULL;
     }
@@ -4356,15 +5133,26 @@ virConnectNumOfStoragePools	(virConnectP
 {
     DEBUG("conn=%p", conn);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->numOfPools)
-        return conn->storageDriver->numOfPools (conn);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->numOfPools) {
+        int ret;
+        ret = conn->storageDriver->numOfPools (conn);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -4387,6 +5175,8 @@ virConnectListStoragePools	(virConnectPt
 {
     DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (-1);
@@ -4394,15 +5184,23 @@ virConnectListStoragePools	(virConnectPt
 
     if ((names == NULL) || (maxnames < 0)) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->listPools)
-        return conn->storageDriver->listPools (conn, names, maxnames);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->listPools) {
+        int ret;
+        ret = conn->storageDriver->listPools (conn, names, maxnames);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
+    return -1;
 }
 
 
@@ -4419,15 +5217,26 @@ virConnectNumOfDefinedStoragePools(virCo
 {
     DEBUG("conn=%p", conn);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->numOfDefinedPools)
-        return conn->storageDriver->numOfDefinedPools (conn);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+
+    if (conn->storageDriver && conn->storageDriver->numOfDefinedPools) {
+        int ret;
+        ret = conn->storageDriver->numOfDefinedPools (conn);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -4451,6 +5260,8 @@ virConnectListDefinedStoragePools(virCon
 {
     DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (-1);
@@ -4458,13 +5269,22 @@ virConnectListDefinedStoragePools(virCon
 
     if ((names == NULL) || (maxnames < 0)) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->listDefinedPools)
-        return conn->storageDriver->listDefinedPools (conn, names, maxnames);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->listDefinedPools) {
+        int ret;
+        ret = conn->storageDriver->listDefinedPools (conn, names, maxnames);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -4496,24 +5316,37 @@ virConnectFindStoragePoolSources(virConn
                                  const char *srcSpec,
                                  unsigned int flags)
 {
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return NULL;
+    DEBUG("conn=%p, type=%s, src=%s, flags=%u", conn, type ? type : "", srcSpec ? srcSpec : "", flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        goto error;
     }
     if (type == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return NULL;
-    }
-
-    if (conn->flags & VIR_CONNECT_RO) {
-        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return NULL;
-    }
-
-    if (conn->storageDriver && conn->storageDriver->findPoolSources)
-        return conn->storageDriver->findPoolSources(conn, type, srcSpec, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->findPoolSources) {
+        char *ret;
+        ret = conn->storageDriver->findPoolSources(conn, type, srcSpec, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -4533,19 +5366,30 @@ virStoragePoolLookupByName(virConnectPtr
 {
     DEBUG("conn=%p, name=%s", conn, name);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (name == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->poolLookupByName)
-        return conn->storageDriver->poolLookupByName (conn, name);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolLookupByName) {
+        virStoragePoolPtr ret;
+        ret = conn->storageDriver->poolLookupByName (conn, name);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -4565,21 +5409,31 @@ virStoragePoolLookupByUUID(virConnectPtr
 {
     DEBUG("conn=%p, uuid=%s", conn, uuid);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (uuid == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->poolLookupByUUID)
-        return conn->storageDriver->poolLookupByUUID (conn, uuid);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return NULL;
-
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolLookupByUUID) {
+        virStoragePoolPtr ret;
+        ret = conn->storageDriver->poolLookupByUUID (conn, uuid);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
+    return NULL;
 }
 
 
@@ -4594,26 +5448,33 @@ virStoragePoolLookupByUUID(virConnectPtr
  */
 virStoragePoolPtr
 virStoragePoolLookupByUUIDString(virConnectPtr conn,
-                                                                 const char *uuidstr)
+                                 const char *uuidstr)
 {
     unsigned char uuid[VIR_UUID_BUFLEN];
     DEBUG("conn=%p, uuidstr=%s", conn, uuidstr);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (uuidstr == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
+        goto error;
     }
 
     if (virUUIDParse(uuidstr, uuid) < 0) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
+        goto error;
     }
 
     return virStoragePoolLookupByUUID(conn, uuid);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
+    return NULL;
 }
 
 
@@ -4630,17 +5491,27 @@ virStoragePoolLookupByVolume(virStorageV
 {
     DEBUG("vol=%p", vol);
 
-    if (!VIR_IS_STORAGE_VOL(vol)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (vol->conn->storageDriver && vol->conn->storageDriver->poolLookupByVolume)
-        return vol->conn->storageDriver->poolLookupByVolume (vol);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+
+    if (vol->conn->storageDriver && vol->conn->storageDriver->poolLookupByVolume) {
+        virStoragePoolPtr ret;
+        ret = vol->conn->storageDriver->poolLookupByVolume (vol);
+        if (!ret)
+            goto error;
+        return ret;
+    }
 
     virLibConnError (vol->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return NULL;
-
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(vol->conn);
+    return NULL;
 }
 
 /**
@@ -4662,23 +5533,34 @@ virStoragePoolCreateXML(virConnectPtr co
 {
     DEBUG("conn=%p, xmlDesc=%s", conn, xmlDesc);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (xmlDesc == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-    if (conn->flags & VIR_CONNECT_RO) {
-        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->poolCreateXML)
-        return conn->storageDriver->poolCreateXML (conn, xmlDesc, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolCreateXML) {
+        virStoragePoolPtr ret;
+        ret = conn->storageDriver->poolCreateXML (conn, xmlDesc, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -4700,25 +5582,35 @@ virStoragePoolDefineXML(virConnectPtr co
 {
     DEBUG("conn=%p, xml=%s", conn, xml);
 
-    if (!VIR_IS_CONNECT(conn)) {
-        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (NULL);
-    }
-    if (conn->flags & VIR_CONNECT_RO) {
-        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (NULL);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (NULL);
+    }
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
     }
     if (xml == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->poolDefineXML)
-        return conn->storageDriver->poolDefineXML (conn, xml, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return NULL;
-
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolDefineXML) {
+        virStoragePoolPtr ret;
+        ret = conn->storageDriver->poolDefineXML (conn, xml, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
+    return NULL;
 }
 
 /**
@@ -4737,6 +5629,8 @@ virStoragePoolBuild(virStoragePoolPtr po
     virConnectPtr conn;
     DEBUG("pool=%p, flags=%u", pool, flags);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (-1);
@@ -4744,15 +5638,23 @@ virStoragePoolBuild(virStoragePoolPtr po
     conn = pool->conn;
     if (conn->flags & VIR_CONNECT_RO) {
         virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->poolBuild)
-        return conn->storageDriver->poolBuild (pool, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolBuild) {
+        int ret;
+        ret = conn->storageDriver->poolBuild (pool, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
+    return -1;
 }
 
 
@@ -4770,6 +5672,8 @@ virStoragePoolUndefine(virStoragePoolPtr
     virConnectPtr conn;
     DEBUG("pool=%p", pool);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__);
         return (-1);
@@ -4777,15 +5681,23 @@ virStoragePoolUndefine(virStoragePoolPtr
     conn = pool->conn;
     if (conn->flags & VIR_CONNECT_RO) {
         virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->poolUndefine)
-        return conn->storageDriver->poolUndefine (pool);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolUndefine) {
+        int ret;
+        ret = conn->storageDriver->poolUndefine (pool);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
+    return -1;
 }
 
 
@@ -4805,10 +5717,8 @@ virStoragePoolCreate(virStoragePoolPtr p
     virConnectPtr conn;
     DEBUG("pool=%p", pool);
 
-    if (pool == NULL) {
-        TODO;
-        return (-1);
-    }
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (-1);
@@ -4816,15 +5726,23 @@ virStoragePoolCreate(virStoragePoolPtr p
     conn = pool->conn;
     if (conn->flags & VIR_CONNECT_RO) {
         virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->poolCreate)
-        return conn->storageDriver->poolCreate (pool, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolCreate) {
+        int ret;
+        ret = conn->storageDriver->poolCreate (pool, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
+    return -1;
 }
 
 
@@ -4846,6 +5764,8 @@ virStoragePoolDestroy(virStoragePoolPtr 
     virConnectPtr conn;
     DEBUG("pool=%p", pool);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (-1);
@@ -4854,13 +5774,22 @@ virStoragePoolDestroy(virStoragePoolPtr 
     conn = pool->conn;
     if (conn->flags & VIR_CONNECT_RO) {
         virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->poolDestroy)
-        return conn->storageDriver->poolDestroy (pool);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolDestroy) {
+        int ret;
+        ret = conn->storageDriver->poolDestroy (pool);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
     return -1;
 }
 
@@ -4882,6 +5811,8 @@ virStoragePoolDelete(virStoragePoolPtr p
     virConnectPtr conn;
     DEBUG("pool=%p, flags=%u", pool, flags);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (-1);
@@ -4890,13 +5821,22 @@ virStoragePoolDelete(virStoragePoolPtr p
     conn = pool->conn;
     if (conn->flags & VIR_CONNECT_RO) {
         virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->poolDelete)
-        return conn->storageDriver->poolDelete (pool, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolDelete) {
+        int ret;
+        ret = conn->storageDriver->poolDelete (pool, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
     return -1;
 }
 
@@ -4915,7 +5855,9 @@ virStoragePoolFree(virStoragePoolPtr poo
 {
     DEBUG("pool=%p", pool);
 
-    if (!VIR_IS_STORAGE_POOL(pool)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (-1);
     }
@@ -4944,6 +5886,8 @@ virStoragePoolRefresh(virStoragePoolPtr 
     virConnectPtr conn;
     DEBUG("pool=%p flags=%u", pool, flags);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (-1);
@@ -4952,13 +5896,22 @@ virStoragePoolRefresh(virStoragePoolPtr 
     conn = pool->conn;
     if (conn->flags & VIR_CONNECT_RO) {
         virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->poolRefresh)
-        return conn->storageDriver->poolRefresh (pool, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->poolRefresh) {
+        int ret;
+        ret = conn->storageDriver->poolRefresh (pool, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
     return -1;
 }
 
@@ -4976,12 +5929,13 @@ virStoragePoolGetName(virStoragePoolPtr 
 {
     DEBUG("pool=%p", pool);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (NULL);
     }
     return (pool->name);
-
 }
 
 
@@ -5000,19 +5954,25 @@ virStoragePoolGetUUID(virStoragePoolPtr 
 {
     DEBUG("pool=%p, uuid=%p", pool, uuid);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (-1);
     }
     if (uuid == NULL) {
         virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     memcpy(uuid, &pool->uuid[0], VIR_UUID_BUFLEN);
 
     return (0);
 
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
+    return -1;
 }
 
 /**
@@ -5031,21 +5991,27 @@ virStoragePoolGetUUIDString(virStoragePo
     unsigned char uuid[VIR_UUID_BUFLEN];
     DEBUG("pool=%p, buf=%p", pool, buf);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (-1);
     }
     if (buf == NULL) {
         virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     if (virStoragePoolGetUUID(pool, &uuid[0]))
-        return (-1);
+        goto error;
 
     virUUIDFormat(uuid, buf);
     return (0);
 
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
+    return -1;
 }
 
 
@@ -5066,25 +6032,35 @@ virStoragePoolGetInfo(virStoragePoolPtr 
     virConnectPtr conn;
     DEBUG("pool=%p, info=%p", pool, info);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (-1);
     }
     if (info == NULL) {
         virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     memset(info, 0, sizeof(virStoragePoolInfo));
 
     conn = pool->conn;
 
-    if (conn->storageDriver->poolGetInfo)
-        return conn->storageDriver->poolGetInfo (pool, info);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return -1;
-
+    if (conn->storageDriver->poolGetInfo) {
+        int ret;
+        ret = conn->storageDriver->poolGetInfo (pool, info);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
+    return -1;
 }
 
 
@@ -5106,23 +6082,33 @@ virStoragePoolGetXMLDesc(virStoragePoolP
     virConnectPtr conn;
     DEBUG("pool=%p, flags=%u", pool, flags);
 
-    if (!VIR_IS_STORAGE_POOL(pool)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (NULL);
     }
     if (flags != 0) {
         virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    conn = pool->conn;
-
-    if (conn->storageDriver && conn->storageDriver->poolGetXMLDesc)
-        return conn->storageDriver->poolGetXMLDesc (pool, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return NULL;
-
+        goto error;
+    }
+
+    conn = pool->conn;
+
+    if (conn->storageDriver && conn->storageDriver->poolGetXMLDesc) {
+        char *ret;
+        ret = conn->storageDriver->poolGetXMLDesc (pool, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
+    return NULL;
 }
 
 
@@ -5143,21 +6129,32 @@ virStoragePoolGetAutostart(virStoragePoo
     virConnectPtr conn;
     DEBUG("pool=%p, autostart=%p", pool, autostart);
 
-    if (!VIR_IS_STORAGE_POOL(pool)) {
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
         virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (-1);
     }
     if (!autostart) {
         virLibStoragePoolError(pool, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = pool->conn;
-
-    if (conn->storageDriver && conn->storageDriver->poolGetAutostart)
-        return conn->storageDriver->poolGetAutostart (pool, autostart);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    conn = pool->conn;
+
+    if (conn->storageDriver && conn->storageDriver->poolGetAutostart) {
+        int ret;
+        ret = conn->storageDriver->poolGetAutostart (pool, autostart);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
     return -1;
 }
 
@@ -5178,22 +6175,33 @@ virStoragePoolSetAutostart(virStoragePoo
     virConnectPtr conn;
     DEBUG("pool=%p, autostart=%d", pool, autostart);
 
-    if (!VIR_IS_STORAGE_POOL(pool)) {
-        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
-        return (-1);
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
+        virLibStoragePoolError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
+        goto error;
     }
 
     if (pool->conn->flags & VIR_CONNECT_RO) {
         virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    conn = pool->conn;
-
-    if (conn->storageDriver && conn->storageDriver->poolSetAutostart)
-        return conn->storageDriver->poolSetAutostart (pool, autostart);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    conn = pool->conn;
+
+    if (conn->storageDriver && conn->storageDriver->poolSetAutostart) {
+        int ret;
+        ret = conn->storageDriver->poolSetAutostart (pool, autostart);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
     return -1;
 }
 
@@ -5211,15 +6219,26 @@ virStoragePoolNumOfVolumes(virStoragePoo
 {
     DEBUG("pool=%p", pool);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_POOL(pool)) {
         virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (-1);
     }
 
-    if (pool->conn->storageDriver && pool->conn->storageDriver->poolNumOfVolumes)
-        return pool->conn->storageDriver->poolNumOfVolumes (pool);
+    if (pool->conn->storageDriver && pool->conn->storageDriver->poolNumOfVolumes) {
+        int ret;
+        ret = pool->conn->storageDriver->poolNumOfVolumes (pool);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
 
     virLibConnError (pool->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
     return -1;
 }
 
@@ -5242,6 +6261,8 @@ virStoragePoolListVolumes(virStoragePool
 {
     DEBUG("pool=%p, names=%p, maxnames=%d", pool, names, maxnames);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_POOL(pool)) {
         virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_POOL, __FUNCTION__);
         return (-1);
@@ -5249,13 +6270,22 @@ virStoragePoolListVolumes(virStoragePool
 
     if ((names == NULL) || (maxnames < 0)) {
         virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if (pool->conn->storageDriver && pool->conn->storageDriver->poolListVolumes)
-        return pool->conn->storageDriver->poolListVolumes (pool, names, maxnames);
+        goto error;
+    }
+
+    if (pool->conn->storageDriver && pool->conn->storageDriver->poolListVolumes) {
+        int ret;
+        ret = pool->conn->storageDriver->poolListVolumes (pool, names, maxnames);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
 
     virLibConnError (pool->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
     return -1;
 }
 
@@ -5279,6 +6309,8 @@ virStorageVolGetConnect (virStorageVolPt
 {
     DEBUG("vol=%p", vol);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_VOL (vol)) {
         virLibStoragePoolError (NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
         return NULL;
@@ -5303,19 +6335,30 @@ virStorageVolLookupByName(virStoragePool
 {
     DEBUG("pool=%p, name=%s", pool, name);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_POOL(pool)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (name == NULL) {
         virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (pool->conn->storageDriver && pool->conn->storageDriver->volLookupByName)
-        return pool->conn->storageDriver->volLookupByName (pool, name);
+        goto error;
+    }
+
+    if (pool->conn->storageDriver && pool->conn->storageDriver->volLookupByName) {
+        virStorageVolPtr ret;
+        ret = pool->conn->storageDriver->volLookupByName (pool, name);
+        if (!ret)
+            goto error;
+        return ret;
+    }
 
     virLibConnError (pool->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
     return NULL;
 }
 
@@ -5337,19 +6380,30 @@ virStorageVolLookupByKey(virConnectPtr c
 {
     DEBUG("conn=%p, key=%s", conn, key);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (key == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->volLookupByKey)
-        return conn->storageDriver->volLookupByKey (conn, key);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->volLookupByKey) {
+        virStorageVolPtr ret;
+        ret = conn->storageDriver->volLookupByKey (conn, key);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -5369,19 +6423,30 @@ virStorageVolLookupByPath(virConnectPtr 
 {
     DEBUG("conn=%p, path=%s", conn, path);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (NULL);
     }
     if (path == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->volLookupByPath)
-        return conn->storageDriver->volLookupByPath (conn, path);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->volLookupByPath) {
+        virStorageVolPtr ret;
+        ret = conn->storageDriver->volLookupByPath (conn, path);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -5400,6 +6465,8 @@ virStorageVolGetName(virStorageVolPtr vo
 {
     DEBUG("vol=%p", vol);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_VOL(vol)) {
         virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
         return (NULL);
@@ -5423,6 +6490,8 @@ virStorageVolGetKey(virStorageVolPtr vol
 {
     DEBUG("vol=%p", vol);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_VOL(vol)) {
         virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
         return (NULL);
@@ -5450,6 +6519,8 @@ virStorageVolCreateXML(virStoragePoolPtr
 {
     DEBUG("pool=%p, flags=%u", pool, flags);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_POOL(pool)) {
         virLibConnError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
         return (NULL);
@@ -5457,13 +6528,22 @@ virStorageVolCreateXML(virStoragePoolPtr
 
     if (pool->conn->flags & VIR_CONNECT_RO) {
         virLibConnError(pool->conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (NULL);
-    }
-
-    if (pool->conn->storageDriver && pool->conn->storageDriver->volCreateXML)
-        return pool->conn->storageDriver->volCreateXML (pool, xmldesc, flags);
+        goto error;
+    }
+
+    if (pool->conn->storageDriver && pool->conn->storageDriver->volCreateXML) {
+        virStorageVolPtr ret;
+        ret = pool->conn->storageDriver->volCreateXML (pool, xmldesc, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
 
     virLibConnError (pool->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(pool->conn);
     return NULL;
 }
 
@@ -5484,6 +6564,8 @@ virStorageVolDelete(virStorageVolPtr vol
     virConnectPtr conn;
     DEBUG("vol=%p, flags=%u", vol, flags);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) {
         virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
         return (-1);
@@ -5492,13 +6574,22 @@ virStorageVolDelete(virStorageVolPtr vol
     conn = vol->conn;
     if (conn->flags & VIR_CONNECT_RO) {
         virLibStorageVolError(vol, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->storageDriver && conn->storageDriver->volDelete)
-        return conn->storageDriver->volDelete (vol, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->storageDriver && conn->storageDriver->volDelete) {
+        int ret;
+        ret = conn->storageDriver->volDelete (vol, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(vol->conn);
     return -1;
 }
 
@@ -5517,6 +6608,8 @@ virStorageVolFree(virStorageVolPtr vol)
 {
     DEBUG("vol=%p", vol);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_VOL(vol)) {
         virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
         return (-1);
@@ -5544,23 +6637,34 @@ virStorageVolGetInfo(virStorageVolPtr vo
     virConnectPtr conn;
     DEBUG("vol=%p, info=%p", vol, info);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) {
         virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
         return (-1);
     }
     if (info == NULL) {
         virLibStorageVolError(vol, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
+        goto error;
     }
 
     memset(info, 0, sizeof(virStorageVolInfo));
 
     conn = vol->conn;
 
-    if (conn->storageDriver->volGetInfo)
-        return conn->storageDriver->volGetInfo (vol, info);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->storageDriver->volGetInfo){
+        int ret;
+        ret = conn->storageDriver->volGetInfo (vol, info);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(vol->conn);
     return -1;
 }
 
@@ -5582,23 +6686,33 @@ virStorageVolGetXMLDesc(virStorageVolPtr
     virConnectPtr conn;
     DEBUG("vol=%p, flags=%u", vol, flags);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_VOL(vol)) {
         virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
         return (NULL);
     }
     if (flags != 0) {
         virLibStorageVolError(vol, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (NULL);
+        goto error;
     }
 
     conn = vol->conn;
 
-    if (conn->storageDriver && conn->storageDriver->volGetXMLDesc)
-        return conn->storageDriver->volGetXMLDesc (vol, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-    return NULL;
-
+    if (conn->storageDriver && conn->storageDriver->volGetXMLDesc) {
+        char *ret;
+        ret = conn->storageDriver->volGetXMLDesc (vol, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(vol->conn);
+    return NULL;
 }
 
 
@@ -5620,6 +6734,8 @@ virStorageVolGetPath(virStorageVolPtr vo
     virConnectPtr conn;
     DEBUG("vol=%p", vol);
 
+    virResetLastError();
+
     if (!VIR_IS_STORAGE_VOL(vol)) {
         virLibStorageVolError(NULL, VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
         return (NULL);
@@ -5627,10 +6743,19 @@ virStorageVolGetPath(virStorageVolPtr vo
 
     conn = vol->conn;
 
-    if (conn->storageDriver && conn->storageDriver->volGetPath)
-        return conn->storageDriver->volGetPath (vol);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    if (conn->storageDriver && conn->storageDriver->volGetPath) {
+        char *ret;
+        ret = conn->storageDriver->volGetPath (vol);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(vol->conn);
     return NULL;
 }
 
@@ -5655,19 +6780,30 @@ virNodeNumOfDevices(virConnectPtr conn, 
 {
     DEBUG("conn=%p, cap=%s, flags=%d", conn, cap, flags);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (-1);
     }
     if (flags != 0) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->deviceMonitor && conn->deviceMonitor->numOfDevices)
-        return conn->deviceMonitor->numOfDevices (conn, cap, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->deviceMonitor && conn->deviceMonitor->numOfDevices) {
+        int ret;
+        ret = conn->deviceMonitor->numOfDevices (conn, cap, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -5696,19 +6832,30 @@ virNodeListDevices(virConnectPtr conn,
     DEBUG("conn=%p, cap=%s, names=%p, maxnames=%d, flags=%d",
           conn, cap, names, maxnames, flags);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return (-1);
     }
     if ((flags != 0) || (names == NULL) || (maxnames < 0)) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if (conn->deviceMonitor && conn->deviceMonitor->listDevices)
-        return conn->deviceMonitor->listDevices (conn, cap, names, maxnames, flags);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->deviceMonitor && conn->deviceMonitor->listDevices) {
+        int ret;
+        ret = conn->deviceMonitor->listDevices (conn, cap, names, maxnames, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -5726,6 +6873,8 @@ virNodeDevicePtr virNodeDeviceLookupByNa
 {
     DEBUG("conn=%p, name=%p", conn, name);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
         return NULL;
@@ -5733,13 +6882,22 @@ virNodeDevicePtr virNodeDeviceLookupByNa
 
     if (name == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return NULL;
-    }
-
-    if (conn->deviceMonitor && conn->deviceMonitor->deviceLookupByName)
-        return conn->deviceMonitor->deviceLookupByName (conn, name);
-
-    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->deviceMonitor && conn->deviceMonitor->deviceLookupByName) {
+        virNodeDevicePtr ret;
+        ret = conn->deviceMonitor->deviceLookupByName (conn, name);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return NULL;
 }
 
@@ -5758,15 +6916,26 @@ char *virNodeDeviceGetXMLDesc(virNodeDev
 {
     DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) {
         virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__);
         return NULL;
     }
 
-    if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceDumpXML)
-        return dev->conn->deviceMonitor->deviceDumpXML (dev, flags);
+    if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceDumpXML) {
+        char *ret;
+        ret = dev->conn->deviceMonitor->deviceDumpXML (dev, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
 
     virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(dev->conn);
     return NULL;
 }
 
@@ -5804,6 +6973,8 @@ const char *virNodeDeviceGetParent(virNo
 {
     DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) {
         virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__);
         return NULL;
@@ -5814,6 +6985,7 @@ const char *virNodeDeviceGetParent(virNo
             dev->parent = dev->conn->deviceMonitor->deviceGetParent (dev);
         } else {
             virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+            virSetConnError(dev->conn);
             return NULL;
         }
     }
@@ -5832,15 +7004,26 @@ int virNodeDeviceNumOfCaps(virNodeDevice
 {
     DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) {
         virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__);
         return -1;
     }
 
-    if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceNumOfCaps)
-        return dev->conn->deviceMonitor->deviceNumOfCaps (dev);
+    if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceNumOfCaps) {
+        int ret;
+        ret = dev->conn->deviceMonitor->deviceNumOfCaps (dev);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
 
     virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(dev->conn);
     return -1;
 }
 
@@ -5861,15 +7044,26 @@ int virNodeDeviceListCaps(virNodeDeviceP
     DEBUG("dev=%p, conn=%p, names=%p, maxnames=%d",
           dev, dev ? dev->conn : NULL, names, maxnames);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) {
         virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__);
         return -1;
     }
 
-    if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceListCaps)
-        return dev->conn->deviceMonitor->deviceListCaps (dev, names, maxnames);
+    if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceListCaps) {
+        int ret;
+        ret = dev->conn->deviceMonitor->deviceListCaps (dev, names, maxnames);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
 
     virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(dev->conn);
     return -1;
 }
 
@@ -5887,6 +7081,8 @@ int virNodeDeviceFree(virNodeDevicePtr d
 {
     DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL);
 
+    virResetLastError();
+
     if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) {
         virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__);
         return (-1);
@@ -5919,6 +7115,8 @@ virConnectDomainEventRegister(virConnect
                               void *opaque,
                               virFreeCallback freecb)
 {
+    DEBUG("conn=%p, cb=%p, opaque=%p, freecb=%p", conn, cb, opaque, freecb);
+    virResetLastError();
 
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
@@ -5926,11 +7124,21 @@ virConnectDomainEventRegister(virConnect
     }
     if (cb == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-
-    if ((conn->driver) && (conn->driver->domainEventRegister))
-        return conn->driver->domainEventRegister (conn, cb, opaque, freecb);
+        goto error;
+    }
+
+    if ((conn->driver) && (conn->driver->domainEventRegister)) {
+        int ret;
+        ret = conn->driver->domainEventRegister (conn, cb, opaque, freecb);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
     return -1;
 }
 
@@ -5949,6 +7157,9 @@ int
 virConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback cb)
 {
+    DEBUG("conn=%p, cb=%p", conn, cb);
+
+    virResetLastError();
 
     if (!VIR_IS_CONNECT(conn)) {
         virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
@@ -5956,12 +7167,21 @@ virConnectDomainEventDeregister(virConne
     }
     if (cb == NULL) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-        return (-1);
-    }
-    if ((conn->driver) && (conn->driver->domainEventDeregister))
-        return conn->driver->domainEventDeregister (conn, cb);
-
-    return -1;
-}
-
-
+        goto error;
+    }
+    if ((conn->driver) && (conn->driver->domainEventDeregister)) {
+        int ret;
+        ret = conn->driver->domainEventDeregister (conn, cb);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+    /* Copy to connection error object for back compatability */
+    virSetConnError(conn);
+    return -1;
+}
+
+
diff --git a/src/virterror.c b/src/virterror.c
--- a/src/virterror.c
+++ b/src/virterror.c
@@ -18,11 +18,11 @@
 #include "virterror_internal.h"
 #include "datatypes.h"
 #include "logging.h"
+#include "memory.h"
+#include "threads.h"
 
-virError virLastErr =       /* the last error */
-  { .code = 0, .domain = 0, .message = NULL, .level = VIR_ERR_NONE,
-    .conn = NULL, .dom = NULL, .str1 = NULL, .str2 = NULL, .str3 = NULL,
-    .int1 = 0, .int2 = 0, .net = NULL };
+virThreadLocal virLastErr;
+
 virErrorFunc virErrorHandler = NULL;     /* global error handler */
 void *virUserData = NULL;        /* associated data */
 
@@ -154,28 +154,118 @@ static const char *virErrorDomainName(vi
     return(dom);
 }
 
+
 /*
+ * Internal helper that is called when a thread exits, to
+ * release the error object stored in the thread local
+ */
+static void
+virLastErrFreeData(void *data)
+{
+    virErrorPtr err = data;
+    if (!err)
+        return;
+    virResetError(err);
+    VIR_FREE(err);
+}
+
+
+int
+virErrorInitialize(void)
+{
+    return virThreadLocalInit(&virLastErr, virLastErrFreeData);
+}
+
+
+/*
+ * Internal helper to ensure a generic error code is stored
+ * in case where API returns failure, but forgot to set an
+ * error
+ */
+static void
+virErrorGenericFailure(virErrorPtr err)
+{
+    err->code = VIR_ERR_INTERNAL_ERROR;
+    err->domain = VIR_FROM_NONE;
+    err->level = VIR_ERR_ERROR;
+    err->message = strdup(_("Unknown failure"));
+}
+
+
+/*
+ * Internal helper to perform a deep copy of the an error
+ */
+static int
+virCopyError(virErrorPtr from,
+             virErrorPtr to)
+{
+    int ret = 0;
+    if (!to)
+        return 0;
+    virResetError(to);
+    if (!from)
+        return 0;
+    to->code = from->code;
+    to->domain = from->domain;
+    to->level = from->level;
+    if (from->message && !(to->message = strdup(from->message)))
+        ret = -1;
+    if (from->str1 && !(to->str1 = strdup(from->str1)))
+        ret = -1;
+    if (from->str2 && !(to->str2 = strdup(from->str2)))
+        ret = -1;
+    if (from->str3 && !(to->str3 = strdup(from->str3)))
+        ret = -1;
+    to->int1 = from->int1;
+    to->int2 = from->int2;
+    /*
+     * Delibrately not setting 'conn', 'dom', 'net' references
+     */
+    return ret;
+}
+
+static virErrorPtr
+virLastErrorObject(void)
+{
+    virErrorPtr err;
+    err = virThreadLocalGet(&virLastErr);
+    if (!err) {
+        if (VIR_ALLOC(err) < 0)
+            return NULL;
+        virThreadLocalSet(&virLastErr, err);
+    }
+    return err;
+}
+
+
+/**
  * virGetLastError:
  *
  * Provide a pointer to the last error caught at the library level
- * Simpler but may not be suitable for multithreaded accesses, in which
- * case use virCopyLastError()
+ *
+ * The error object is kept in thread local storage, so separate
+ * threads can safely access this concurrently.
  *
  * Returns a pointer to the last error or NULL if none occurred.
  */
 virErrorPtr
 virGetLastError(void)
 {
-    if (virLastErr.code == VIR_ERR_OK)
-        return (NULL);
-    return (&virLastErr);
+    virErrorPtr err = virLastErrorObject();
+    if (!err || err->code == VIR_ERR_OK)
+        return NULL;
+    return err;
 }
 
-/*
+/**
  * virCopyLastError:
  * @to: target to receive the copy
  *
  * Copy the content of the last error caught at the library level
+ *
+ * The error object is kept in thread local storage, so separate
+ * threads can safely access this concurrently.
+ *
  * One will need to free the result with virResetError()
  *
  * Returns 0 if no error was found and the error code otherwise and -1 in case
@@ -184,12 +274,14 @@ virGetLastError(void)
 int
 virCopyLastError(virErrorPtr to)
 {
-    if (to == NULL)
-        return (-1);
-    if (virLastErr.code == VIR_ERR_OK)
-        return (0);
-    memcpy(to, &virLastErr, sizeof(virError));
-    return (virLastErr.code);
+    virErrorPtr err = virLastErrorObject();
+    /* We can't guarentee caller has initialized it to zero */
+    memset(to, 0, sizeof(*to));
+    if (err)
+        virCopyError(err, to);
+    else
+        virResetError(to);
+    return to->code;
 }
 
 /**
@@ -210,15 +302,22 @@ virResetError(virErrorPtr err)
     memset(err, 0, sizeof(virError));
 }
 
+
 /**
  * virResetLastError:
  *
  * Reset the last error caught at the library level.
+ *
+ * The error object is kept in thread local storage, so separate
+ * threads can safely access this concurrently, only resetting
+ * their own error object.
  */
 void
 virResetLastError(void)
 {
-    virResetError(&virLastErr);
+    virErrorPtr err = virLastErrorObject();
+    if (err)
+        virResetError(err);
 }
 
 /**
@@ -226,8 +325,20 @@ virResetLastError(void)
  * @conn: pointer to the hypervisor connection
  *
  * Provide a pointer to the last error caught on that connection
- * Simpler but may not be suitable for multithreaded accesses, in which
- * case use virConnCopyLastError()
+ *
+ * This method is not protected against access from multiple
+ * threads. In a multi-threaded application, always use the
+ * global virGetLastError() API which is backed by thread
+ * local storage.
+ *
+ * If the connection object was discovered to be invalid by
+ * an API call, then the error will be reported against the
+ * global error object.
+ * 
+ * Since 0.6.0, all errors reported in the per-connection object
+ * are also duplicated in the global error object. As such an
+ * application can always use virGetLastError(). This method
+ * remains for backwards compatability.
  *
  * Returns a pointer to the last error or NULL if none occurred.
  */
@@ -235,8 +346,8 @@ virErrorPtr
 virConnGetLastError(virConnectPtr conn)
 {
     if (conn == NULL)
-        return (NULL);
-    return (&conn->err);
+        return NULL;
+    return &conn->err;
 }
 
 /**
@@ -245,6 +356,21 @@ virConnGetLastError(virConnectPtr conn)
  * @to: target to receive the copy
  *
  * Copy the content of the last error caught on that connection
+ *
+ * This method is not protected against access from multiple
+ * threads. In a multi-threaded application, always use the
+ * global virGetLastError() API which is backed by thread
+ * local storage.
+ *
+ * If the connection object was discovered to be invalid by
+ * an API call, then the error will be reported against the
+ * global error object.
+ * 
+ * Since 0.6.0, all errors reported in the per-connection object
+ * are also duplicated in the global error object. As such an
+ * application can always use virGetLastError(). This method
+ * remains for backwards compatability.
+ *
  * One will need to free the result with virResetError()
  *
  * Returns 0 if no error was found and the error code otherwise and -1 in case
@@ -253,20 +379,27 @@ virConnGetLastError(virConnectPtr conn)
 int
 virConnCopyLastError(virConnectPtr conn, virErrorPtr to)
 {
+    /* We can't guarentee caller has initialized it to zero */
+    memset(to, 0, sizeof(*to));
+
     if (conn == NULL)
-        return (-1);
-    if (to == NULL)
-        return (-1);
+        return -1;
+    virMutexLock(&conn->lock);
     if (conn->err.code == VIR_ERR_OK)
-        return (0);
-    memcpy(to, &conn->err, sizeof(virError));
-    return (conn->err.code);
+        virResetError(to);
+    else
+        virCopyError(&conn->err, to);
+    virMutexUnlock(&conn->lock);
+    return to->code;
 }
 
 /**
  * virConnResetLastError:
  * @conn: pointer to the hypervisor connection
  *
+ * The error object is kept in thread local storage, so separate
+ * threads can safely access this concurrently.
+ *
  * Reset the last error caught on that connection
  */
 void
@@ -274,7 +407,9 @@ virConnResetLastError(virConnectPtr conn
 {
     if (conn == NULL)
         return;
+    virMutexLock(&conn->lock);
     virResetError(&conn->err);
+    virMutexUnlock(&conn->lock);
 }
 
 /**
@@ -309,8 +444,10 @@ virConnSetErrorFunc(virConnectPtr conn, 
 {
     if (conn == NULL)
         return;
+    virMutexLock(&conn->lock);
     conn->handler = handler;
     conn->userData = userData;
+    virMutexUnlock(&conn->lock);
 }
 
 /**
@@ -357,6 +494,44 @@ virDefaultErrorFunc(virErrorPtr err)
                 dom, lvl, domain, network, err->message);
 }
 
+/*
+ * Internal helper to ensure the global error object
+ * is initialized with a generic message if not already
+ * set.
+ */
+void
+virSetGlobalError(void)
+{
+    virErrorPtr err = virLastErrorObject();
+
+    if (err && err->code == VIR_ERR_OK)
+        virErrorGenericFailure(err);
+}
+
+/*
+ * Internal helper to ensure the connection error object
+ * is initialized from the global object.
+ */
+void
+virSetConnError(virConnectPtr conn)
+{
+    virErrorPtr err = virLastErrorObject();
+
+    if (err && err->code == VIR_ERR_OK)
+        virErrorGenericFailure(err);
+
+    if (conn) {
+        virMutexLock(&conn->lock);
+        if (err)
+            virCopyError(err, &conn->err);
+        else
+            virErrorGenericFailure(&conn->err);
+        virMutexUnlock(&conn->lock);
+    }
+}
+
+
+
 /**
  * virRaiseError:
  * @conn: the connection to the hypervisor if available
@@ -377,16 +552,29 @@ virDefaultErrorFunc(virErrorPtr err)
  * immediately if a callback is found and store it for later handling.
  */
 void
-virRaiseError(virConnectPtr conn, virDomainPtr dom, virNetworkPtr net,
+virRaiseError(virConnectPtr conn,
+              virDomainPtr dom ATTRIBUTE_UNUSED,
+              virNetworkPtr net ATTRIBUTE_UNUSED,
               int domain, int code, virErrorLevel level,
               const char *str1, const char *str2, const char *str3,
               int int1, int int2, const char *msg, ...)
 {
-    virErrorPtr to = &virLastErr;
+    virErrorPtr to;
     void *userData = virUserData;
     virErrorFunc handler = virErrorHandler;
     char *str;
 
+    /*
+     * All errors are recorded in thread local storage
+     * For compatability, public API calls will copy them
+     * to the per-connection error object when neccessary
+     */
+    to = virLastErrorObject();
+    if (!to)
+        return; /* Hit OOM allocating thread error object, sod all we can do now */
+
+    virResetError(to);
+
     if (code == VIR_ERR_OK)
         return;
 
@@ -394,11 +582,12 @@ virRaiseError(virConnectPtr conn, virDom
      * try to find the best place to save and report the error
      */
     if (conn != NULL) {
-        to = &conn->err;
+        virMutexLock(&conn->lock);
         if (conn->handler != NULL) {
             handler = conn->handler;
             userData = conn->userData;
         }
+        virMutexUnlock(&conn->lock);
     }
 
     /*
@@ -421,9 +610,10 @@ virRaiseError(virConnectPtr conn, virDom
      * Save the information about the error
      */
     virResetError(to);
-    to->conn = conn;
-    to->dom = dom;
-    to->net = net;
+    /*
+     * Delibrately not setting conn, dom & net fields since
+     * they're utterly unsafe
+     */
     to->domain = domain;
     to->code = code;
     to->message = str;
@@ -813,3 +1003,5 @@ void virReportErrorHelper(virConnectPtr 
                   virerr, errorMessage, NULL, -1, -1, virerr, errorMessage);
 
 }
+
+
diff --git a/src/virterror_internal.h b/src/virterror_internal.h
--- a/src/virterror_internal.h
+++ b/src/virterror_internal.h
@@ -24,7 +24,6 @@
 
 #include "internal.h"
 
-extern virError virLastErr;
 extern virErrorFunc virErrorHandler;
 extern void *virUserData;
 
@@ -33,6 +32,7 @@ extern void *virUserData;
  *		API for error handling					*
  *									*
  ************************************************************************/
+int virErrorInitialize(void);
 void virRaiseError(virConnectPtr conn,
                    virDomainPtr dom,
                    virNetworkPtr net,
@@ -53,4 +53,7 @@ void virReportErrorHelper(virConnectPtr 
   ATTRIBUTE_FORMAT(printf, 7, 8);
 
 
+void virSetGlobalError(void);
+void virSetConnError(virConnectPtr conn);
+
 #endif
diff --git a/tests/cpuset b/tests/cpuset
--- a/tests/cpuset
+++ b/tests/cpuset
@@ -40,6 +40,6 @@ libvir: Domain Config error : failed Xen
 error: Failed to define domain from xml-invalid
 
 EOF
-compare out exp || fail=1
+compare exp out || fail=1
 
 (exit $fail); exit $fail
diff --git a/tests/read-bufsiz b/tests/read-bufsiz
--- a/tests/read-bufsiz
+++ b/tests/read-bufsiz
@@ -37,7 +37,7 @@ for i in before after; do
 
   virsh --connect test:///default define $in > out || fail=1
   printf "Domain test defined from $in\n\n" > exp || fail=1
-  compare out exp || fail=1
+  compare exp out || fail=1
 done
 
 (exit $fail); exit $fail
diff --git a/tests/start b/tests/start
--- a/tests/start
+++ b/tests/start
@@ -34,9 +34,9 @@ virsh -c $test_url start test > out 2> e
 
 # stdout gets a newline
 echo > exp || fail=1
-compare out exp || fail=1
+compare exp out || fail=1
 
 echo 'error: Domain is already active' > exp || fail=1
-compare err exp || fail=1
+compare exp err || fail=1
 
 (exit $fail); exit $fail
diff --git a/tests/undefine b/tests/undefine
--- a/tests/undefine
+++ b/tests/undefine
@@ -9,7 +9,7 @@
 # (at your option) any later version.
 
 # This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# but WITHEXP ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 
@@ -32,7 +32,7 @@ cat <<\EOF > exp || fail=1
 libvir: Test error : internal error Domain 'test' is still running
 error: Failed to undefine domain test
 EOF
-compare out exp || fail=1
+compare exp out || fail=1
 
 # A different diagnostic when specifying a domain ID
 virsh -q -c test:///default undefine 1 > out 2>&1
@@ -41,7 +41,7 @@ cat <<\EOF > exp || fail=1
 error: a running domain like 1 cannot be undefined;
 to undefine, first shutdown then undefine using its name or UUID
 EOF
-compare out exp || fail=1
+compare exp out || fail=1
 
 # Succeed, now: first shut down, then undefine, both via name.
 virsh -q -c test:///default 'shutdown test; undefine test' > out 2>&1
@@ -50,6 +50,6 @@ cat <<\EOF > exp || fail=1
 Domain test is being shutdown
 Domain test has been undefined
 EOF
-compare out exp || fail=1
+compare exp out || fail=1
 
 (exit $fail); exit $fail
diff --git a/tests/vcpupin b/tests/vcpupin
--- a/tests/vcpupin
+++ b/tests/vcpupin
@@ -32,7 +32,7 @@ cat <<\EOF > exp || fail=1
 error: vcpupin: Invalid or missing vCPU number.
 
 EOF
-compare out exp || fail=1
+compare exp out || fail=1
 
 # An out-of-range vCPU number deserves a diagnostic, too.
 virsh --connect test:///default vcpupin test 100 0,1 > out 2>&1
@@ -41,6 +41,6 @@ cat <<\EOF > exp || fail=1
 error: vcpupin: Invalid vCPU number.
 
 EOF
-compare out exp || fail=1
+compare exp out || fail=1
 
 (exit $fail); exit $fail

-- 
|: 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 :|




More information about the libvir-list mailing list