mirror of https://gitee.com/openkylin/libvirt.git
* 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:
parent
4d9187a696
commit
596b601021
|
@ -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
1
TODO
|
@ -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/* ?)
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 */
|
||||
|
|
226
src/libvirt.c
226
src/libvirt.c
|
@ -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));
|
||||
}
|
||||
|
|
216
src/virterror.c
216
src/virterror.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue