* - 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)
}
} else {
*typeVer = 0;
+ virLibConnError(NULL, VIR_ERR_NO_SUPPORT, "type");
return(-1);
}
}
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;
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)
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;
if (xend_setup(ret) == 0)
method++;
ret->domains = virHashCreate(20);
+ if (ret->domains == NULL)
+ goto failed;
ret->flags = VIR_CONNECT_RO;
- if ((ret->domains == NULL) || (method == 0))
+ if (method == 0) {
+ virLibConnError(NULL, VIR_ERR_NO_CONNECT,
+ "could not connect to Xen Daemon nor Xen Store");
goto failed;
+ }
return(ret);
failed:
*/
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");
}
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) {
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) {
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
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)
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) {
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;
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);
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
*/
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)
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)
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)
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
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.
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
*/
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);
}
*/
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 (uuid == NULL) {
+ virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
- if (domain->handle == 0)
+ }
+
+ 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) &&
*/
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);
}
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) {
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;
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)
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));
*/
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));
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
#include "libvirt.h"
#include "virterror.h"
#include "internal.h"
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:
*
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);
+}
+