2006-02-24 22:36:10 +00:00
|
|
|
/*
|
|
|
|
* virterror.c: implements error handling and reporting code for libvirt
|
|
|
|
*
|
|
|
|
* Copy: Copyright (C) 2006 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* See COPYING.LIB for the License of this software
|
|
|
|
*
|
|
|
|
* Author: Daniel Veillard <veillard@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2006-02-27 16:27:18 +00:00
|
|
|
#include <stdarg.h>
|
2006-02-24 22:36:10 +00:00
|
|
|
#include "libvirt.h"
|
|
|
|
#include "virterror.h"
|
|
|
|
#include "internal.h"
|
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
static virError lastErr = /* the last error */
|
|
|
|
{ 0, 0, NULL, VIR_ERR_NONE, NULL, NULL, NULL, NULL, NULL, 0, 0 };
|
|
|
|
static virErrorFunc virErrorHandler = NULL; /* global error handlet */
|
|
|
|
static void *virUserData = NULL; /* associated data */
|
2006-02-24 22:36:10 +00:00
|
|
|
|
2006-02-27 16:27:18 +00:00
|
|
|
/*
|
|
|
|
* 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; \
|
|
|
|
}} \
|
|
|
|
}
|
|
|
|
|
2006-02-24 22:36:10 +00:00
|
|
|
/*
|
|
|
|
* 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()
|
|
|
|
*
|
|
|
|
* Returns a pointer to the last error or NULL if none occured.
|
|
|
|
*/
|
|
|
|
virErrorPtr
|
2006-03-15 12:13:25 +00:00
|
|
|
virGetLastError(void)
|
|
|
|
{
|
2006-02-24 22:36:10 +00:00
|
|
|
if (lastErr.code == VIR_ERR_OK)
|
2006-03-15 12:13:25 +00:00
|
|
|
return (NULL);
|
|
|
|
return (&lastErr);
|
2006-02-24 22:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virCopyLastError:
|
|
|
|
* @to: target to receive the copy
|
|
|
|
*
|
|
|
|
* Copy the content of the last error caught at the library level
|
|
|
|
* 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
|
|
|
|
* of parameter error.
|
|
|
|
*/
|
|
|
|
int
|
2006-03-15 12:13:25 +00:00
|
|
|
virCopyLastError(virErrorPtr to)
|
|
|
|
{
|
2006-02-24 22:36:10 +00:00
|
|
|
if (to == NULL)
|
2006-03-15 12:13:25 +00:00
|
|
|
return (-1);
|
2006-02-24 22:36:10 +00:00
|
|
|
if (lastErr.code == VIR_ERR_OK)
|
2006-03-15 12:13:25 +00:00
|
|
|
return (0);
|
2006-02-24 22:36:10 +00:00
|
|
|
memcpy(to, &lastErr, sizeof(virError));
|
2006-03-15 12:13:25 +00:00
|
|
|
return (lastErr.code);
|
2006-02-24 22:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virResetError:
|
|
|
|
* @err: pointer to the virError to clean up
|
|
|
|
*
|
|
|
|
* Reset the error being pointed to
|
|
|
|
*/
|
|
|
|
void
|
2006-03-15 12:13:25 +00:00
|
|
|
virResetError(virErrorPtr err)
|
|
|
|
{
|
2006-02-24 22:36:10 +00:00
|
|
|
if (err == NULL)
|
|
|
|
return;
|
|
|
|
if (err->message != NULL)
|
|
|
|
free(err->message);
|
|
|
|
if (err->str1 != NULL)
|
|
|
|
free(err->str1);
|
|
|
|
if (err->str2 != NULL)
|
|
|
|
free(err->str2);
|
|
|
|
if (err->str3 != NULL)
|
|
|
|
free(err->str3);
|
|
|
|
memset(err, 0, sizeof(virError));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virResetLastError:
|
|
|
|
*
|
|
|
|
* Reset the last error caught at the library level.
|
|
|
|
*/
|
|
|
|
void
|
2006-03-15 12:13:25 +00:00
|
|
|
virResetLastError(void)
|
|
|
|
{
|
2006-02-24 22:36:10 +00:00
|
|
|
virResetError(&lastErr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virConnGetLastError:
|
|
|
|
* @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()
|
|
|
|
*
|
|
|
|
* Returns a pointer to the last error or NULL if none occured.
|
|
|
|
*/
|
|
|
|
virErrorPtr
|
2006-03-15 12:13:25 +00:00
|
|
|
virConnGetLastError(virConnectPtr conn)
|
|
|
|
{
|
2006-02-24 22:36:10 +00:00
|
|
|
if (conn == NULL)
|
2006-03-15 12:13:25 +00:00
|
|
|
return (NULL);
|
|
|
|
return (&conn->err);
|
2006-02-24 22:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virConnCopyLastError:
|
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
* @to: target to receive the copy
|
|
|
|
*
|
|
|
|
* Copy the content of the last error caught on that connection
|
|
|
|
* 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
|
|
|
|
* of parameter error.
|
|
|
|
*/
|
|
|
|
int
|
2006-03-15 12:13:25 +00:00
|
|
|
virConnCopyLastError(virConnectPtr conn, virErrorPtr to)
|
|
|
|
{
|
2006-02-24 22:36:10 +00:00
|
|
|
if (conn == NULL)
|
2006-03-15 12:13:25 +00:00
|
|
|
return (-1);
|
2006-02-24 22:36:10 +00:00
|
|
|
if (to == NULL)
|
2006-03-15 12:13:25 +00:00
|
|
|
return (-1);
|
2006-02-24 22:36:10 +00:00
|
|
|
if (conn->err.code == VIR_ERR_OK)
|
2006-03-15 12:13:25 +00:00
|
|
|
return (0);
|
2006-02-24 22:36:10 +00:00
|
|
|
memcpy(to, &conn->err, sizeof(virError));
|
2006-03-15 12:13:25 +00:00
|
|
|
return (conn->err.code);
|
2006-02-24 22:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virConnResetLastError:
|
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
*
|
|
|
|
* Reset the last error caught on that connection
|
|
|
|
*/
|
|
|
|
void
|
2006-03-15 12:13:25 +00:00
|
|
|
virConnResetLastError(virConnectPtr conn)
|
|
|
|
{
|
2006-02-24 22:36:10 +00:00
|
|
|
if (conn == NULL)
|
|
|
|
return;
|
|
|
|
virResetError(&conn->err);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virSetErrorFunc:
|
|
|
|
* @userData: pointer to the user data provided in the handler callback
|
|
|
|
* @handler: the function to get called in case of error or NULL
|
|
|
|
*
|
|
|
|
* Set a library global error handling function, if @handler is NULL,
|
|
|
|
* it will reset to default printing on stderr. The error raised there
|
|
|
|
* are those for which no handler at the connection level could caught.
|
|
|
|
*/
|
|
|
|
void
|
2006-03-15 12:13:25 +00:00
|
|
|
virSetErrorFunc(void *userData, virErrorFunc handler)
|
|
|
|
{
|
2006-02-24 22:36:10 +00:00
|
|
|
virErrorHandler = handler;
|
|
|
|
virUserData = userData;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virConnSetErrorFunc:
|
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
* @userData: pointer to the user data provided in the handler callback
|
|
|
|
* @handler: the function to get called in case of error or NULL
|
|
|
|
*
|
|
|
|
* Set a connection error handling function, if @handler is NULL
|
|
|
|
* it will reset to default which is to pass error back to the global
|
|
|
|
* library handler.
|
|
|
|
*/
|
|
|
|
void
|
2006-03-15 12:13:25 +00:00
|
|
|
virConnSetErrorFunc(virConnectPtr conn, void *userData,
|
|
|
|
virErrorFunc handler)
|
|
|
|
{
|
2006-02-24 22:36:10 +00:00
|
|
|
if (conn == NULL)
|
|
|
|
return;
|
|
|
|
conn->handler = handler;
|
|
|
|
conn->userData = userData;
|
|
|
|
}
|
|
|
|
|
2006-02-27 16:27:18 +00:00
|
|
|
/**
|
2006-02-27 21:34:28 +00:00
|
|
|
* virDefaultErrorFunc:
|
2006-02-27 16:27:18 +00:00
|
|
|
* @err: pointer to the error.
|
|
|
|
*
|
2006-02-27 21:34:28 +00:00
|
|
|
* Default routine reporting an error to stderr.
|
2006-02-27 16:27:18 +00:00
|
|
|
*/
|
2006-02-27 21:34:28 +00:00
|
|
|
void
|
2006-03-15 12:13:25 +00:00
|
|
|
virDefaultErrorFunc(virErrorPtr err)
|
|
|
|
{
|
2006-02-27 16:27:18 +00:00
|
|
|
const char *lvl = "", *dom = "", *domain = "";
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if ((err == NULL) || (err->code == VIR_ERR_OK))
|
|
|
|
return;
|
|
|
|
switch (err->level) {
|
|
|
|
case VIR_ERR_NONE:
|
2006-03-15 12:13:25 +00:00
|
|
|
lvl = "";
|
|
|
|
break;
|
2006-02-27 16:27:18 +00:00
|
|
|
case VIR_ERR_WARNING:
|
2006-03-15 12:13:25 +00:00
|
|
|
lvl = "warning";
|
|
|
|
break;
|
2006-02-27 16:27:18 +00:00
|
|
|
case VIR_ERR_ERROR:
|
2006-03-15 12:13:25 +00:00
|
|
|
lvl = "error";
|
|
|
|
break;
|
|
|
|
}
|
2006-02-27 16:27:18 +00:00
|
|
|
switch (err->domain) {
|
|
|
|
case VIR_FROM_NONE:
|
2006-03-15 12:13:25 +00:00
|
|
|
dom = "";
|
|
|
|
break;
|
2006-02-27 16:27:18 +00:00
|
|
|
case VIR_FROM_XEN:
|
2006-03-15 12:13:25 +00:00
|
|
|
dom = "Xen ";
|
|
|
|
break;
|
2006-02-27 16:27:18 +00:00
|
|
|
case VIR_FROM_XEND:
|
2006-03-15 12:13:25 +00:00
|
|
|
dom = "Xen Daemon ";
|
|
|
|
break;
|
2006-03-23 15:42:10 +00:00
|
|
|
case VIR_FROM_XENSTORE:
|
|
|
|
dom = "Xen Store ";
|
|
|
|
break;
|
2006-02-27 16:27:18 +00:00
|
|
|
case VIR_FROM_DOM:
|
2006-03-15 12:13:25 +00:00
|
|
|
dom = "Domain ";
|
|
|
|
break;
|
2006-02-27 16:27:18 +00:00
|
|
|
}
|
|
|
|
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'))
|
2006-03-15 12:13:25 +00:00
|
|
|
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);
|
2006-02-27 16:27:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* __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,
|
2006-03-15 12:13:25 +00:00
|
|
|
int int1, int int2, const char *msg, ...)
|
|
|
|
{
|
2006-02-27 16:27:18 +00:00
|
|
|
virErrorPtr to = &lastErr;
|
|
|
|
void *userData = virUserData;
|
|
|
|
virErrorFunc handler = virErrorHandler;
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
if (code == VIR_ERR_OK)
|
2006-03-15 12:13:25 +00:00
|
|
|
return;
|
2006-02-27 16:27:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* try to find the best place to save and report the error
|
|
|
|
*/
|
|
|
|
if (conn != NULL) {
|
|
|
|
to = &conn->err;
|
2006-03-15 12:13:25 +00:00
|
|
|
if (conn->handler != NULL) {
|
|
|
|
handler = conn->handler;
|
|
|
|
userData = conn->userData;
|
|
|
|
}
|
2006-02-27 16:27:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 {
|
2006-02-27 21:34:28 +00:00
|
|
|
virDefaultErrorFunc(to);
|
2006-02-27 16:27:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* __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 *
|
2006-03-15 12:13:25 +00:00
|
|
|
__virErrorMsg(virErrorNumber error, const char *info)
|
|
|
|
{
|
2006-02-27 16:27:18 +00:00
|
|
|
const char *errmsg = NULL;
|
|
|
|
|
|
|
|
switch (error) {
|
|
|
|
case VIR_ERR_OK:
|
2006-03-15 12:13:25 +00:00
|
|
|
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;
|
|
|
|
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;
|
|
|
|
case VIR_ERR_SEXPR_SERIAL:
|
|
|
|
if (info != NULL)
|
|
|
|
errmsg = "failed to serialize S-Expr: %s";
|
|
|
|
else
|
|
|
|
errmsg = "failed to serialize S-Expr";
|
|
|
|
break;
|
|
|
|
case VIR_ERR_NO_XEN:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "could not use Xen hypervisor entry";
|
|
|
|
else
|
|
|
|
errmsg = "could not use Xen hypervisor entry %s";
|
|
|
|
break;
|
2006-03-25 10:38:30 +00:00
|
|
|
case VIR_ERR_NO_XENSTORE:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "could not connect to Xen Store";
|
|
|
|
else
|
|
|
|
errmsg = "could not connect to Xen Store %s";
|
|
|
|
break;
|
2006-03-15 12:13:25 +00:00
|
|
|
case VIR_ERR_XEN_CALL:
|
|
|
|
errmsg = "failed Xen syscall %s %d";
|
|
|
|
break;
|
|
|
|
case VIR_ERR_OS_TYPE:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "unknown OS type";
|
|
|
|
else
|
|
|
|
errmsg = "unknown OS type %s";
|
|
|
|
break;
|
|
|
|
case VIR_ERR_NO_KERNEL:
|
|
|
|
errmsg = "missing kernel informations";
|
|
|
|
break;
|
|
|
|
case VIR_ERR_NO_ROOT:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "missing root device informations";
|
|
|
|
else
|
|
|
|
errmsg = "missing root device informations in %s";
|
|
|
|
break;
|
|
|
|
case VIR_ERR_NO_SOURCE:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "missing source informations for device";
|
|
|
|
else
|
|
|
|
errmsg = "missing source informations for device %s";
|
|
|
|
break;
|
|
|
|
case VIR_ERR_NO_TARGET:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "missing target informations for device";
|
|
|
|
else
|
|
|
|
errmsg = "missing target informations for device %s";
|
|
|
|
break;
|
|
|
|
case VIR_ERR_NO_NAME:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "missing domain name informations";
|
|
|
|
else
|
|
|
|
errmsg = "missing domain name informations in %s";
|
|
|
|
break;
|
|
|
|
case VIR_ERR_NO_OS:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "missing operating system informations";
|
|
|
|
else
|
|
|
|
errmsg = "missing operating system informations for %s";
|
|
|
|
break;
|
|
|
|
case VIR_ERR_NO_DEVICE:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "missing devices informations";
|
|
|
|
else
|
|
|
|
errmsg = "missing devices informations for %s";
|
|
|
|
break;
|
2006-03-27 15:24:36 +00:00
|
|
|
case VIR_ERR_DRIVER_FULL:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "too many drivers registered";
|
|
|
|
else
|
|
|
|
errmsg = "too many drivers registered in %s";
|
|
|
|
break;
|
2006-03-29 12:46:03 +00:00
|
|
|
case VIR_ERR_CALL_FAILED:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "library call failed, possibly not supported";
|
|
|
|
else
|
|
|
|
errmsg = "library call %s failed, possibly not supported";
|
|
|
|
break;
|
2006-04-28 18:29:26 +00:00
|
|
|
case VIR_ERR_XML_ERROR:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "XML description not well formed or invalid";
|
|
|
|
else
|
|
|
|
errmsg = "XML description for %s is not well formed or invalid";
|
|
|
|
break;
|
|
|
|
case VIR_ERR_DOM_EXIST:
|
|
|
|
if (info == NULL)
|
|
|
|
errmsg = "this domain exists already";
|
|
|
|
else
|
|
|
|
errmsg = "domain %s exists already";
|
|
|
|
break;
|
2006-02-27 16:27:18 +00:00
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
return (errmsg);
|
2006-02-27 16:27:18 +00:00
|
|
|
}
|