diff --git a/ChangeLog b/ChangeLog index 19d36a21303fef9ce16760dbf12b29d12882ab9c..e900a14a3f5db3ee8f185d44f480295dc1d84c07 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Mon Feb 27 14:56:57 EST 2006 Daniel Veillard + + * include/virterror.h src/virterror.c src/xend_internal.c: more work + plugging in the error system in the code. + Mon Feb 27 17:25:48 CET 2006 Daniel Veillard * TODO: updated diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index d9d3972f593cfdb89c1ca1fb04a20979d2f1a7fb..a81bb83a7f42fb84818992862e530dcd07596411 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -40,7 +40,8 @@ typedef enum { VIR_FROM_NONE = 0, VIR_FROM_XEN, /* Error at Xen hypervisor layer */ VIR_FROM_XEND, /* Error at connection with xend daemon */ - VIR_FROM_DOM /* Error when operating on a domain */ + VIR_FROM_SEXPR, /* Error in the S-Epression code */ + VIR_FROM_DOM, /* Error when operating on a domain */ } virErrorDomain; @@ -76,11 +77,15 @@ typedef enum { VIR_ERR_INTERNAL_ERROR, /* internal error */ VIR_ERR_NO_MEMORY, /* memory allocation failure */ VIR_ERR_NO_SUPPORT, /* no support for this connection */ + VIR_ERR_UNKNOWN_HOST,/* could not resolve hostname */ VIR_ERR_NO_CONNECT, /* can't connect to hypervisor */ VIR_ERR_INVALID_CONN,/* invalid connection object */ VIR_ERR_INVALID_DOMAIN,/* invalid domain object */ VIR_ERR_INVALID_ARG,/* invalid function argument */ VIR_ERR_OPERATION_FAILED,/* a command to hypervisor failed */ + VIR_ERR_GET_FAILED,/* a HTTP GET command to failed */ + VIR_ERR_POST_FAILED,/* a HTTP POST command to failed */ + VIR_ERR_HTTP_ERROR,/* unexpected HTTP error code */ } virErrorNumber; /** diff --git a/include/virterror.h b/include/virterror.h index d9d3972f593cfdb89c1ca1fb04a20979d2f1a7fb..a81bb83a7f42fb84818992862e530dcd07596411 100644 --- a/include/virterror.h +++ b/include/virterror.h @@ -40,7 +40,8 @@ typedef enum { VIR_FROM_NONE = 0, VIR_FROM_XEN, /* Error at Xen hypervisor layer */ VIR_FROM_XEND, /* Error at connection with xend daemon */ - VIR_FROM_DOM /* Error when operating on a domain */ + VIR_FROM_SEXPR, /* Error in the S-Epression code */ + VIR_FROM_DOM, /* Error when operating on a domain */ } virErrorDomain; @@ -76,11 +77,15 @@ typedef enum { VIR_ERR_INTERNAL_ERROR, /* internal error */ VIR_ERR_NO_MEMORY, /* memory allocation failure */ VIR_ERR_NO_SUPPORT, /* no support for this connection */ + VIR_ERR_UNKNOWN_HOST,/* could not resolve hostname */ VIR_ERR_NO_CONNECT, /* can't connect to hypervisor */ VIR_ERR_INVALID_CONN,/* invalid connection object */ VIR_ERR_INVALID_DOMAIN,/* invalid domain object */ VIR_ERR_INVALID_ARG,/* invalid function argument */ VIR_ERR_OPERATION_FAILED,/* a command to hypervisor failed */ + VIR_ERR_GET_FAILED,/* a HTTP GET command to failed */ + VIR_ERR_POST_FAILED,/* a HTTP POST command to failed */ + VIR_ERR_HTTP_ERROR,/* unexpected HTTP error code */ } virErrorNumber; /** diff --git a/src/virterror.c b/src/virterror.c index 8e6fc51b17f2432b3b89b6d5a4e257ea0155f927..f385cc3368a3286479f802e13424d9f4a520d30f 100644 --- a/src/virterror.c +++ b/src/virterror.c @@ -385,6 +385,30 @@ __virErrorMsg(virErrorNumber error, const char *info) { case VIR_ERR_INVALID_ARG: errmsg = "invalid domain pointer in"; break; + case VIR_ERR_OPERATION_FAILED: + if (info != NULL) + errmsg = "operation failed: %s"; + else + errmsg = "operation failed"; + break; + case VIR_ERR_GET_FAILED: + if (info != NULL) + errmsg = "GET operation failed: %s"; + else + errmsg = "GET operation failed"; + break; + case VIR_ERR_POST_FAILED: + if (info != NULL) + errmsg = "POST operation failed: %s"; + else + errmsg = "POST operation failed"; + break; + case VIR_ERR_HTTP_ERROR: + errmsg = "got unknown HTTP error code %d"; + break; + case VIR_ERR_UNKNOWN_HOST: + errmsg = "Unknown host %s"; + break; } return(errmsg); } diff --git a/src/xend_internal.c b/src/xend_internal.c index 06bf4d6dc32e14c7272fddbe9d1856c7299ddca9..1d94e772b0e7c166213c832e94fca01cd0924e43 100644 --- a/src/xend_internal.c +++ b/src/xend_internal.c @@ -78,6 +78,27 @@ virXendError(virConnectPtr conn, virErrorNumber error, const char *info) { errmsg, info, NULL, 0, 0, errmsg, info); } +/** + * virXendErrorInt: + * @conn: the connection if available + * @error: the error noumber + * @val: extra integer information + * + * Handle an error at the xend daemon interface + */ +static void +virXendErrorInt(virConnectPtr conn, virErrorNumber error, + int val) { + const char *errmsg; + + if (error == VIR_ERR_OK) + return; + + errmsg = __virErrorMsg(error, NULL); + __virRaiseError(conn, NULL, VIR_FROM_XEND, error, VIR_ERR_ERROR, + errmsg, NULL, NULL, val, 0, errmsg, val); +} + #define foreach(iterator, start) \ for (_for_i = (start), *iterator = (start)->car; \ @@ -343,8 +364,7 @@ xend_get(virConnectPtr xend, const char *path, close(s); if ((ret < 0) || (ret >= 300)) { - virXendError(NULL, VIR_ERR_OPERATION_FAILED, - content); + virXendError(NULL, VIR_ERR_GET_FAILED, content); } return ret; @@ -392,8 +412,7 @@ xend_post(virConnectPtr xend, const char *path, const char *ops, close(s); if ((ret < 0) || (ret >= 300)) { - virXendError(NULL, VIR_ERR_OPERATION_FAILED, - content); + virXendError(NULL, VIR_ERR_POST_FAILED, content); } return ret; @@ -421,7 +440,7 @@ http2unix(int ret) errno = ESRCH; break; default: - printf("unknown error code %d\n", ret); + virXendErrorInt(NULL, VIR_ERR_HTTP_ERROR, ret); errno = EINVAL; break; } @@ -1048,6 +1067,7 @@ xend_setup_tcp(virConnectPtr xend, const char *host, int port) pent = gethostbyname(host); if (pent == NULL) { if (inet_aton(host, &ip) == 0) { + virXendError(xend, VIR_ERR_UNKNOWN_HOST, host); errno = ESRCH; return(-1); } @@ -1152,8 +1172,11 @@ xend_unpause(virConnectPtr xend, const char *name) int xend_rename(virConnectPtr xend, const char *old, const char *new) { - if ((xend == NULL) || (old == NULL) || (new == NULL)) + if ((xend == NULL) || (old == NULL) || (new == NULL)) { + /* this should be caught at the interface but ... */ + virXendError(xend, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); + } return xend_op(xend, old, "op", "rename", "name", new, NULL); } @@ -1169,8 +1192,11 @@ xend_rename(virConnectPtr xend, const char *old, const char *new) int xend_reboot(virConnectPtr xend, const char *name) { - if ((xend == NULL) || (name == NULL)) + if ((xend == NULL) || (name == NULL)) { + /* this should be caught at the interface but ... */ + virXendError(xend, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); + } return xend_op(xend, name, "op", "shutdown", "reason", "reboot", NULL); } @@ -1187,8 +1213,11 @@ xend_reboot(virConnectPtr xend, const char *name) int xend_shutdown(virConnectPtr xend, const char *name) { - if ((xend == NULL) || (name == NULL)) + if ((xend == NULL) || (name == NULL)) { + /* this should be caught at the interface but ... */ + virXendError(xend, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); + } return xend_op(xend, name, "op", "shutdown", "reason", "halt", NULL); } @@ -1206,8 +1235,11 @@ xend_shutdown(virConnectPtr xend, const char *name) int xend_sysrq(virConnectPtr xend, const char *name, const char *key) { - if ((xend == NULL) || (name == NULL) || (key == NULL)) + if ((xend == NULL) || (name == NULL) || (key == NULL)) { + /* this should be caught at the interface but ... */ + virXendError(xend, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); + } return xend_op(xend, name, "op", "sysrq", "key", key, NULL); } @@ -1225,8 +1257,11 @@ xend_sysrq(virConnectPtr xend, const char *name, const char *key) int xend_destroy(virConnectPtr xend, const char *name) { - if ((xend == NULL) || (name == NULL)) + if ((xend == NULL) || (name == NULL)) { + /* this should be caught at the interface but ... */ + virXendError(xend, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); + } return xend_op(xend, name, "op", "destroy", NULL); } @@ -1247,8 +1282,11 @@ xend_destroy(virConnectPtr xend, const char *name) int xend_save(virConnectPtr xend, const char *name, const char *filename) { - if ((xend == NULL) || (filename == NULL)) + if ((xend == NULL) || (filename == NULL)) { + /* this should be caught at the interface but ... */ + virXendError(xend, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); + } return xend_op(xend, name, "op", "save", "file", filename, NULL); } @@ -1266,8 +1304,11 @@ xend_save(virConnectPtr xend, const char *name, const char *filename) int xend_restore(virConnectPtr xend, const char *filename) { - if ((xend == NULL) || (filename == NULL)) + if ((xend == NULL) || (filename == NULL)) { + /* this should be caught at the interface but ... */ + virXendError(xend, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); + } return xend_op(xend, "", "op", "restore", "file", filename, NULL); } @@ -1463,6 +1504,12 @@ xend_create_sexpr(virConnectPtr xend, const char *sexpr) char *ptr; ptr = urlencode(sexpr); + if (ptr == NULL) { + /* this should be caught at the interface but ... */ + virXendError(xend, VIR_ERR_INTERNAL_ERROR, + "Failed to urlencode the create S-Expr"); + return(-1); + } ret = xend_op(xend, "", "op", "create", "config", ptr, NULL); @@ -1977,14 +2024,22 @@ xend_get_domain_ids(virConnectPtr xend, const char *domname, goto error; value = sexpr_node(root, "domain/domid"); - if (value == NULL) + if (value == NULL) { + virXendError(xend, VIR_ERR_INTERNAL_ERROR, + "domain informations incomplete, missing domid"); goto error; + } ret = strtol(value, NULL, 0); if ((ret == 0) && (value[0] != '0')) { + virXendError(xend, VIR_ERR_INTERNAL_ERROR, + "domain informations incorrect domid not numberic"); ret = -1; } else if (uuid != NULL) { char **ptr = (char **) &uuid; - sexpr_uuid(ptr, root, "domain/uuid"); + if (sexpr_uuid(ptr, root, "domain/uuid") == NULL) { + virXendError(xend, VIR_ERR_INTERNAL_ERROR, + "domain informations incomplete, missing uuid"); + } } error: @@ -2188,7 +2243,8 @@ xend_parse_sexp_desc(struct sexpr *root) { sexpr_int(root, "domain/domid")); tmp = sexpr_node(root, "domain/name"); if (tmp == NULL) { - /* VIR_ERR_NO_NAME */ + virXendError(NULL, VIR_ERR_INTERNAL_ERROR, + "domain informations incomplete, missing name"); goto error; } virBufferVSprintf(&buf, " %s\n", tmp); @@ -2197,7 +2253,8 @@ xend_parse_sexp_desc(struct sexpr *root) { /* * TODO: we will need some fallback here for other guest OSes */ - /* VIR_ERR_NO_KERNEL */ + virXendError(NULL, VIR_ERR_INTERNAL_ERROR, + "domain informations incomplete, missing kernel"); goto error; } virBufferAdd(&buf, " \n", 7); @@ -2230,7 +2287,8 @@ xend_parse_sexp_desc(struct sexpr *root) { virBufferVSprintf(&buf, " \n", tmp); tmp = sexpr_node(node, "device/vbd/dev"); if (tmp == NULL) { - /* VIR_ERR_NO_DEV */ + virXendError(NULL, VIR_ERR_INTERNAL_ERROR, + "domain informations incomplete, vbd has no dev"); goto error; } virBufferVSprintf(&buf, " \n", tmp); @@ -2244,7 +2302,8 @@ xend_parse_sexp_desc(struct sexpr *root) { virBufferVSprintf(&buf, " \n", tmp); tmp = sexpr_node(node, "device/vbd/dev"); if (tmp == NULL) { - /* VIR_ERR_NO_DEV */ + virXendError(NULL, VIR_ERR_INTERNAL_ERROR, + "domain informations incomplete, vbd has no dev"); goto error; } virBufferVSprintf(&buf, " \n", tmp); @@ -2316,8 +2375,11 @@ xend_get_domain_xml(virDomainPtr domain) { char *ret = NULL; struct sexpr *root; - if (!VIR_IS_DOMAIN(domain)) + if (!VIR_IS_DOMAIN(domain)) { + /* this should be caught at the interface but ... */ + virXendError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return(NULL); + } root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name); if (root == NULL)