* TODO: updated

* include/virterror.h src/internal.h src/libvirt.c src/virterror.c
  src/xend_internal.c: commiting a first pass at adding error handling
  in the code, not finished, but it starts to work, need more coverage
  and testing.
Daniel
This commit is contained in:
Daniel Veillard 2006-02-27 16:27:18 +00:00
parent 4d9187a696
commit 596b601021
8 changed files with 486 additions and 49 deletions

View File

@ -1,3 +1,11 @@
Mon Feb 27 17:25:48 CET 2006 Daniel Veillard <veillard@redhat.com>
* TODO: updated
* include/virterror.h src/internal.h src/libvirt.c src/virterror.c
src/xend_internal.c: commiting a first pass at adding error handling
in the code, not finished, but it starts to work, need more coverage
and testing.
Fri Feb 24 23:33:55 CET 2006 Daniel Veillard <veillard@redhat.com>
* src/Makefile.am src/internal.h src/libvirt.c src/libvirt_sym.version

1
TODO
View File

@ -12,6 +12,7 @@ TODO:
- DTD/RNG/XSD schemas for the XML Domain descriptions
- in python bindings raise an exception if a lookup or connection fails
to return a non-None object
- Add uuid to XML format
virsh TODO:
- decide where will be default directory for domains configurations (/etc/xen/domains/* ?)

View File

@ -53,7 +53,7 @@ typedef enum {
typedef struct _virError virError;
typedef virError *virErrorPtr;
struct _virError {
int code; /* The error code, e.g. an virParserError */
int code; /* The error code, a virErrorNumber */
int domain; /* What part of the library raised this error */
char *message;/* human-readable informative error message */
virErrorLevel level;/* how consequent is the error */
@ -73,8 +73,14 @@ struct _virError {
*/
typedef enum {
VIR_ERR_OK = 0,
VIR_ERR_INTERNAL_ERROR, /* 1 */
VIR_ERR_NO_MEMORY /* 2 */
VIR_ERR_INTERNAL_ERROR, /* internal error */
VIR_ERR_NO_MEMORY, /* memory allocation failure */
VIR_ERR_NO_SUPPORT, /* no support for this connection */
VIR_ERR_NO_CONNECT, /* can't connect to hypervisor */
VIR_ERR_INVALID_CONN,/* invalid connection object */
VIR_ERR_INVALID_DOMAIN,/* invalid domain object */
VIR_ERR_INVALID_ARG,/* invalid function argument */
VIR_ERR_OPERATION_FAILED,/* a command to hypervisor failed */
} virErrorNumber;
/**

View File

@ -53,7 +53,7 @@ typedef enum {
typedef struct _virError virError;
typedef virError *virErrorPtr;
struct _virError {
int code; /* The error code, e.g. an virParserError */
int code; /* The error code, a virErrorNumber */
int domain; /* What part of the library raised this error */
char *message;/* human-readable informative error message */
virErrorLevel level;/* how consequent is the error */
@ -73,8 +73,14 @@ struct _virError {
*/
typedef enum {
VIR_ERR_OK = 0,
VIR_ERR_INTERNAL_ERROR, /* 1 */
VIR_ERR_NO_MEMORY /* 2 */
VIR_ERR_INTERNAL_ERROR, /* internal error */
VIR_ERR_NO_MEMORY, /* memory allocation failure */
VIR_ERR_NO_SUPPORT, /* no support for this connection */
VIR_ERR_NO_CONNECT, /* can't connect to hypervisor */
VIR_ERR_INVALID_CONN,/* invalid connection object */
VIR_ERR_INVALID_DOMAIN,/* invalid domain object */
VIR_ERR_INVALID_ARG,/* invalid function argument */
VIR_ERR_OPERATION_FAILED,/* a command to hypervisor failed */
} virErrorNumber;
/**

View File

@ -129,6 +129,21 @@ char * virDomainGetVMInfo (virDomainPtr domain,
const char *vm,
const char *name);
void __virRaiseError (virConnectPtr conn,
virDomainPtr dom,
int domain,
int code,
virErrorLevel level,
const char *str1,
const char *str2,
const char *str3,
int int1,
int int2,
const char *msg,
...);
const char * __virErrorMsg (virErrorNumber error,
const char *info);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -33,6 +33,50 @@
* - memory wrappers for malloc/free ?
*/
/**
* virLibConnError:
* @conn: the connection if available
* @error: the error noumber
* @info: extra information string
*
* Handle an error at the connection level
*/
static void
virLibConnError(virConnectPtr conn, virErrorNumber error, const char *info) {
const char *errmsg;
if (error == VIR_ERR_OK)
return;
errmsg = __virErrorMsg(error, info);
__virRaiseError(conn, NULL, VIR_FROM_NONE, error, VIR_ERR_ERROR,
errmsg, info, NULL, 0, 0, errmsg, info);
}
/**
* virLibConnError:
* @conn: the connection if available
* @error: the error noumber
* @info: extra information string
*
* Handle an error at the connection level
*/
static void
virLibDomainError(virDomainPtr domain, virErrorNumber error, const char *info) {
virConnectPtr conn = NULL;
const char *errmsg;
if (error == VIR_ERR_OK)
return;
errmsg = __virErrorMsg(error, info);
if (error != VIR_ERR_INVALID_DOMAIN) {
conn = domain->conn;
}
__virRaiseError(conn, domain, VIR_FROM_DOM, error, VIR_ERR_ERROR,
errmsg, info, NULL, 0, 0, errmsg, info);
}
/**
* virGetVersion:
* @libVer: return value for the library version (OUT)
@ -68,6 +112,7 @@ virGetVersion(unsigned long *libVer, const char *type, unsigned long *typeVer) {
}
} else {
*typeVer = 0;
virLibConnError(NULL, VIR_ERR_NO_SUPPORT, "type");
return(-1);
}
}
@ -90,19 +135,26 @@ virConnectOpen(const char *name) {
struct xs_handle *xshandle = NULL;
/* we can only talk to the local Xen supervisor ATM */
if (name != NULL)
if (name != NULL) {
virLibConnError(NULL, VIR_ERR_NO_SUPPORT, name);
return(NULL);
}
handle = xenHypervisorOpen();
if (handle == -1)
if (handle == -1) {
goto failed;
}
xshandle = xs_daemon_open();
if (xshandle == NULL)
if (xshandle == NULL) {
virLibConnError(NULL, VIR_ERR_NO_CONNECT, "XenStore");
goto failed;
}
ret = (virConnectPtr) malloc(sizeof(virConnect));
if (ret == NULL)
if (ret == NULL) {
virLibConnError(NULL, VIR_ERR_NO_MEMORY, "Allocating connection");
goto failed;
}
memset(ret, 0, sizeof(virConnect));
ret->magic = VIR_CONNECT_MAGIC;
ret->handle = handle;
@ -143,8 +195,10 @@ virConnectOpenReadOnly(const char *name) {
struct xs_handle *xshandle = NULL;
/* we can only talk to the local Xen supervisor ATM */
if (name != NULL)
if (name != NULL) {
virLibConnError(NULL, VIR_ERR_NO_SUPPORT, name);
return(NULL);
}
handle = xenHypervisorOpen();
if (handle >= 0)
@ -157,8 +211,10 @@ virConnectOpenReadOnly(const char *name) {
method++;
ret = (virConnectPtr) malloc(sizeof(virConnect));
if (ret == NULL)
if (ret == NULL) {
virLibConnError(NULL, VIR_ERR_NO_MEMORY, "Allocating connection");
goto failed;
}
memset(ret, 0, sizeof(virConnect));
ret->magic = VIR_CONNECT_MAGIC;
ret->handle = handle;
@ -166,9 +222,14 @@ virConnectOpenReadOnly(const char *name) {
if (xend_setup(ret) == 0)
method++;
ret->domains = virHashCreate(20);
ret->flags = VIR_CONNECT_RO;
if ((ret->domains == NULL) || (method == 0))
if (ret->domains == NULL)
goto failed;
ret->flags = VIR_CONNECT_RO;
if (method == 0) {
virLibConnError(NULL, VIR_ERR_NO_CONNECT,
"could not connect to Xen Daemon nor Xen Store");
goto failed;
}
return(ret);
failed:
@ -259,8 +320,10 @@ virConnectClose(virConnectPtr conn) {
*/
const char *
virConnectGetType(virConnectPtr conn) {
if (!VIR_IS_CONNECT(conn))
if (!VIR_IS_CONNECT(conn)) {
virLibConnError(conn, VIR_ERR_INVALID_CONN, "in virConnectGetType");
return(NULL);
}
return("Xen");
}
@ -281,11 +344,15 @@ int
virConnectGetVersion(virConnectPtr conn, unsigned long *hvVer) {
unsigned long ver;
if (!VIR_IS_CONNECT(conn))
if (!VIR_IS_CONNECT(conn)) {
virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
return(-1);
}
if (hvVer == NULL)
if (hvVer == NULL) {
virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
/* this can't be extracted from the Xenstore */
if (conn->handle < 0) {
@ -315,11 +382,15 @@ virConnectListDomains(virConnectPtr conn, int *ids, int maxids) {
long id;
char **idlist = NULL, *endptr;
if (!VIR_IS_CONNECT(conn))
if (!VIR_IS_CONNECT(conn)) {
virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
return(-1);
}
if ((ids == NULL) || (maxids <= 0))
if ((ids == NULL) || (maxids <= 0)) {
virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
idlist = xend_get_domains(conn);
if (idlist != NULL) {
@ -368,8 +439,10 @@ virConnectNumOfDomains(virConnectPtr conn) {
unsigned int num;
char **idlist = NULL;
if (!VIR_IS_CONNECT(conn))
if (!VIR_IS_CONNECT(conn)) {
virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
return(-1);
}
/*
* try first with Xend interface
@ -415,10 +488,15 @@ virDomainCreateLinux(virConnectPtr conn,
char *name = NULL;
virDomainPtr dom;
if (!VIR_IS_CONNECT(conn))
if (!VIR_IS_CONNECT(conn)) {
virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
return(NULL);
if (xmlDesc == NULL)
}
if (xmlDesc == NULL) {
virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
sexpr = virDomainParseXMLDesc(xmlDesc, &name);
if ((sexpr == NULL) || (name == NULL)) {
if (sexpr != NULL)
@ -614,10 +692,14 @@ virDomainLookupByID(virConnectPtr conn, int id) {
char *name = NULL;
unsigned char uuid[16];
if (!VIR_IS_CONNECT(conn))
if (!VIR_IS_CONNECT(conn)) {
virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
return(NULL);
if (id < 0)
}
if (id < 0) {
virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
/* lookup is easier with the Xen store so try it first */
if (conn->xshandle != NULL) {
@ -690,10 +772,14 @@ virDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) {
unsigned char ident[16];
int id = -1;
if (!VIR_IS_CONNECT(conn))
if (!VIR_IS_CONNECT(conn)) {
virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
return(NULL);
if (uuid == NULL)
}
if (uuid == NULL) {
virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
names = xend_get_domains(conn);
tmp = names;
@ -753,10 +839,14 @@ virDomainLookupByName(virConnectPtr conn, const char *name) {
int found = 0;
struct xend_domain *xenddomain = NULL;
if (!VIR_IS_CONNECT(conn))
if (!VIR_IS_CONNECT(conn)) {
virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
return(NULL);
if (name == NULL)
}
if (name == NULL) {
virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
/* try first though Xend */
xenddomain = xend_get_domain(conn, name);
@ -834,8 +924,10 @@ int
virDomainDestroy(virDomainPtr domain) {
int ret;
if (!VIR_IS_CONNECTED_DOMAIN(domain))
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(-1);
}
/*
* try first with the xend method
@ -865,8 +957,10 @@ virDomainDestroy(virDomainPtr domain) {
*/
int
virDomainFree(virDomainPtr domain) {
if (!VIR_IS_DOMAIN(domain))
if (!VIR_IS_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(-1);
}
domain->magic = -1;
domain->handle = -1;
if (domain->path != NULL)
@ -893,8 +987,11 @@ int
virDomainSuspend(virDomainPtr domain) {
int ret;
if (!VIR_IS_CONNECTED_DOMAIN(domain))
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(-1);
}
/* first try though the Xen daemon */
ret = xend_pause(domain->conn, domain->name);
if (ret == 0)
@ -918,8 +1015,11 @@ int
virDomainResume(virDomainPtr domain) {
int ret;
if (!VIR_IS_CONNECTED_DOMAIN(domain))
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(-1);
}
/* first try though the Xen daemon */
ret = xend_unpause(domain->conn, domain->name);
if (ret == 0)
@ -946,8 +1046,14 @@ virDomainSave(virDomainPtr domain, const char *to) {
int ret;
char filepath[4096];
if ((!VIR_IS_CONNECTED_DOMAIN(domain)) || (to == NULL))
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(-1);
}
if (to == NULL) {
virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
/*
* We must absolutize the file path as the save is done out of process
@ -987,8 +1093,15 @@ virDomainRestore(virConnectPtr conn, const char *from) {
int ret;
char filepath[4096];
if ((!VIR_IS_CONNECT(conn)) || (from == NULL))
if (!VIR_IS_CONNECT(conn)) {
virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
return(-1);
}
if (from == NULL) {
virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
/*
* We must absolutize the file path as the restore is done out of process
* TODO: check for URI when libxml2 is linked in.
@ -1029,8 +1142,10 @@ int
virDomainShutdown(virDomainPtr domain) {
int ret;
if (!VIR_IS_CONNECTED_DOMAIN(domain))
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(-1);
}
/*
* try first with the xend daemon
@ -1061,8 +1176,10 @@ virDomainShutdown(virDomainPtr domain) {
*/
const char *
virDomainGetName(virDomainPtr domain) {
if (!VIR_IS_DOMAIN(domain))
if (!VIR_IS_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(NULL);
}
return(domain->name);
}
@ -1077,11 +1194,18 @@ virDomainGetName(virDomainPtr domain) {
*/
int
virDomainGetUUID(virDomainPtr domain, unsigned char *uuid) {
if ((!VIR_IS_DOMAIN(domain)) || (uuid == NULL))
if (!VIR_IS_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(-1);
if (domain->handle == 0)
}
if (uuid == NULL) {
virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
if (domain->handle == 0) {
memset(uuid, 0, 16);
else {
} else {
if ((domain->uuid[0] == 0) && (domain->uuid[1] == 0) &&
(domain->uuid[2] == 0) && (domain->uuid[3] == 0) &&
(domain->uuid[4] == 0) && (domain->uuid[5] == 0) &&
@ -1106,8 +1230,10 @@ virDomainGetUUID(virDomainPtr domain, unsigned char *uuid) {
*/
unsigned int
virDomainGetID(virDomainPtr domain) {
if (!VIR_IS_DOMAIN(domain))
if (!VIR_IS_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return((unsigned int) -1);
}
return(domain->handle);
}
@ -1123,8 +1249,10 @@ char *
virDomainGetOSType(virDomainPtr domain) {
char *vm, *str = NULL;
if (!VIR_IS_DOMAIN(domain))
if (!VIR_IS_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(NULL);
}
vm = virDomainGetVM(domain);
if (vm) {
@ -1151,8 +1279,10 @@ unsigned long
virDomainGetMaxMemory(virDomainPtr domain) {
unsigned long ret = 0;
if (!VIR_IS_CONNECTED_DOMAIN(domain))
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(0);
}
if (domain->conn->flags & VIR_CONNECT_RO) {
char *tmp;
@ -1192,10 +1322,14 @@ virDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) {
int ret;
char s[256], v[30];
if (!VIR_IS_CONNECTED_DOMAIN(domain))
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(-1);
if (memory < 4096)
}
if (memory < 4096) {
virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
if (domain->conn->flags & VIR_CONNECT_RO)
return(-1);
if (domain->conn->xshandle==NULL)
@ -1240,10 +1374,14 @@ virDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) {
char request[200];
if (!VIR_IS_CONNECTED_DOMAIN(domain))
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(-1);
if (info == NULL)
}
if (info == NULL) {
virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
memset(info, 0, sizeof(virDomainInfo));
@ -1352,10 +1490,14 @@ xend_info:
*/
char *
virDomainGetXMLDesc(virDomainPtr domain, int flags) {
if (!VIR_IS_DOMAIN(domain))
if (!VIR_IS_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return(NULL);
if (flags != 0)
}
if (flags != 0) {
virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
}
return(xend_get_domain_xml(domain));
}

View File

@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "libvirt.h"
#include "virterror.h"
#include "internal.h"
@ -20,6 +21,43 @@ static virError lastErr = /* the last error */
static virErrorFunc virErrorHandler = NULL;/* global error handlet */
static void *virUserData = NULL; /* associated data */
/*
* Macro used to format the message as a string in __virRaiseError
* and borrowed from libxml2.
*/
#define VIR_GET_VAR_STR(msg, str) { \
int size, prev_size = -1; \
int chars; \
char *larger; \
va_list ap; \
\
str = (char *) malloc(150); \
if (str != NULL) { \
\
size = 150; \
\
while (1) { \
va_start(ap, msg); \
chars = vsnprintf(str, size, msg, ap); \
va_end(ap); \
if ((chars > -1) && (chars < size)) { \
if (prev_size == chars) { \
break; \
} else { \
prev_size = chars; \
} \
} \
if (chars > -1) \
size += chars + 1; \
else \
size += 100; \
if ((larger = (char *) realloc(str, size)) == NULL) { \
break; \
} \
str = larger; \
}} \
}
/*
* virGetLastError:
*
@ -173,3 +211,181 @@ virConnSetErrorFunc(virConnectPtr conn, void *userData, virErrorFunc handler) {
conn->userData = userData;
}
/**
* virReportError:
* @err: pointer to the error.
*
* Internal routine reporting an error to stderr.
*/
static void
virReportError(virErrorPtr err) {
const char *lvl = "", *dom = "", *domain = "";
int len;
if ((err == NULL) || (err->code == VIR_ERR_OK))
return;
switch (err->level) {
case VIR_ERR_NONE:
lvl = "";
break;
case VIR_ERR_WARNING:
lvl = "warning";
break;
case VIR_ERR_ERROR:
lvl = "error";
break;
}
switch (err->domain) {
case VIR_FROM_NONE:
dom = "";
break;
case VIR_FROM_XEN:
dom = "Xen ";
break;
case VIR_FROM_XEND:
dom = "Xen Daemon ";
break;
case VIR_FROM_DOM:
dom = "Domain ";
break;
}
if ((err->dom != NULL) && (err->code != VIR_ERR_INVALID_DOMAIN)) {
domain = err->dom->name;
}
len = strlen(err->message);
if ((len == 0) || (err->message[len - 1] != '\n'))
fprintf(stderr, "libvir: %s%s %s: %s\n",
dom, lvl, domain, err->message);
else
fprintf(stderr, "libvir: %s%s %s: %s",
dom, lvl, domain, err->message);
}
/**
* __virRaiseError:
* @conn: the connection to the hypervisor if available
* @dom: the domain if available
* @domain: the virErrorDomain indicating where it's coming from
* @code: the virErrorNumber code for the error
* @level: the virErrorLevel for the error
* @str1: extra string info
* @str2: extra string info
* @str3: extra string info
* @int1: extra int info
* @int2: extra int info
* @msg: the message to display/transmit
* @...: extra parameters for the message display
*
* Internal routine called when an error is detected. It will raise it
* immediately if a callback is found and store it for later handling.
*/
void
__virRaiseError(virConnectPtr conn, virDomainPtr dom,
int domain, int code, virErrorLevel level,
const char *str1, const char *str2, const char *str3,
int int1, int int2, const char *msg, ...) {
virErrorPtr to = &lastErr;
void *userData = virUserData;
virErrorFunc handler = virErrorHandler;
char *str;
if (code == VIR_ERR_OK)
return;
/*
* try to find the best place to save and report the error
*/
if (conn != NULL) {
to = &conn->err;
if (conn->handler != NULL) {
handler = conn->handler;
userData = conn->userData;
}
}
/*
* formats the message
*/
if (msg == NULL) {
str = strdup("No error message provided");
} else {
VIR_GET_VAR_STR(msg, str);
}
/*
* Save the information about the error
*/
virResetError(to);
to->conn = conn;
to->dom = dom;
to->domain = domain;
to->code = code;
to->message = str;
to->level = level;
if (str1 != NULL)
to->str1 = strdup(str1);
if (str2 != NULL)
to->str2 = strdup(str2);
if (str3 != NULL)
to->str3 = strdup(str3);
to->int1 = int1;
to->int2 = int2;
/*
* now, report it
*/
if (handler != NULL) {
handler(userData, to);
} else {
virReportError(to);
}
}
/**
* __virErrorMsg:
* @error: the virErrorNumber
* @info: usually the first paprameter string
*
* Internal routine to get the message associated to an error raised
* from the library
*
* Returns the constant string associated to @error
*/
const char *
__virErrorMsg(virErrorNumber error, const char *info) {
const char *errmsg = NULL;
switch (error) {
case VIR_ERR_OK:
return(NULL);
case VIR_ERR_INTERNAL_ERROR:
if (info != NULL)
errmsg = "internal error %s";
else
errmsg = "internal error";
break;
case VIR_ERR_NO_MEMORY:
errmsg = "out of memory";
break;
case VIR_ERR_NO_SUPPORT:
errmsg = "no support for hypervisor %s";
break;
case VIR_ERR_NO_CONNECT:
if (info == NULL)
errmsg = "could not connect to hypervisor";
else
errmsg = "could not connect to %s";
break;
case VIR_ERR_INVALID_CONN:
errmsg = "invalid connection pointer in";
break;
case VIR_ERR_INVALID_DOMAIN:
errmsg = "invalid domain pointer in";
break;
case VIR_ERR_INVALID_ARG:
errmsg = "invalid domain pointer in";
break;
}
return(errmsg);
}

View File

@ -57,6 +57,28 @@ struct xend {
struct sockaddr_in addr_in;
};
/**
* virXendError:
* @conn: the connection if available
* @error: the error noumber
* @info: extra information string
*
* Handle an error at the xend daemon interface
*/
static void
virXendError(virConnectPtr conn, virErrorNumber error, const char *info) {
const char *errmsg;
if (error == VIR_ERR_OK)
return;
errmsg = __virErrorMsg(error, info);
__virRaiseError(conn, NULL, VIR_FROM_XEND, error, VIR_ERR_ERROR,
errmsg, info, NULL, 0, 0, errmsg, info);
}
#define foreach(iterator, start) \
for (_for_i = (start), *iterator = (start)->car; \
_for_i->kind == SEXPR_CONS; \
@ -81,10 +103,14 @@ do_connect(virConnectPtr xend)
int serrno;
s = socket(xend->type, SOCK_STREAM, 0);
if (s == -1)
if (s == -1) {
virXendError(xend, VIR_ERR_INTERNAL_ERROR,
"failed to create a socket");
return -1;
}
if (connect(s, xend->addr, xend->len) == -1) {
virXendError(xend, VIR_ERR_NO_CONNECT, "Xen Daemon");
serrno = errno;
close(s);
errno = serrno;
@ -131,6 +157,13 @@ wr_sync(int fd, void *buffer, size_t size, int do_read)
/* unrecoverable error */
if (len == -1) {
if (do_read)
virXendError(NULL, VIR_ERR_INTERNAL_ERROR,
"faid to read from Xen Daemon");
else
virXendError(NULL, VIR_ERR_INTERNAL_ERROR,
"faid to read from Xen Daemon");
return(-1);
}
@ -309,6 +342,11 @@ xend_get(virConnectPtr xend, const char *path,
ret = xend_req(s, content, n_content);
close(s);
if ((ret < 0) || (ret >= 300)) {
virXendError(NULL, VIR_ERR_OPERATION_FAILED,
content);
}
return ret;
}
@ -353,6 +391,11 @@ xend_post(virConnectPtr xend, const char *path, const char *ops,
ret = xend_req(s, content, n_content);
close(s);
if ((ret < 0) || (ret >= 300)) {
virXendError(NULL, VIR_ERR_OPERATION_FAILED,
content);
}
return ret;
}