+Wed Aug 9 10:17:03 EDT 2006 Daniel Berrange <berrange@redhat.com>
+
+ * src/driver.h, src/libvirt.c: Made the virDomainGetXMLDesc
+ method use the driver backends.
+ * src/xend_internal.c: Surround all functions which are not
+ needed for proxy with #ifndef PROXY. Refactor XML generator
+ functions to allow calling from proxy based on domain id
+ instead of virDomainPtr object
+ * src/xs_internal.c, src/xs_internal.h: Change signature
+ of method for extracting VNC port & console TTY to use domain
+ id instead of virDomainPtr. Surround functions not used by
+ proxy in #ifndef PROXY
+ * src/xml.c:Surround functions not used by proxy in #ifndef PROXY
+ * src/test.c, src/xen_internal.c: Added NULL entry for new
+ driver method for fetching XML
+ * src/proxy_internal.c, src/proxy_internal.h, proxy/libvirt_proxy.c:
+ Added implmentation of virDomainGetXMLDesc driver method which
+ goes via proxy.
+
Tue Aug 8 23:24:51 CEST 2006 Daniel Veillard <veillard@redhat.com>
* src/driver.h src/libvirt.c src/proxy_internal.c src/test.c
libexec_PROGRAMS = libvirt_proxy
-LIBS=
libvirt_proxy_SOURCES = libvirt_proxy.c @top_srcdir@/src/xend_internal.c \
@top_srcdir@/src/xen_internal.c @top_srcdir@/src/virterror.c \
- @top_srcdir@/src/sexpr.c
+ @top_srcdir@/src/sexpr.c @top_srcdir@/src/xml.c \
+ @top_srcdir@/src/xs_internal.c
libvirt_proxy_LDFLAGS =
libvirt_proxy_DEPENDENCIES =
libvirt_proxy_LDADD =
#include "proxy_internal.h"
#include "xen_internal.h"
#include "xend_internal.h"
+#include "xs_internal.h"
static int fdServer = -1;
static int debug = 0;
fprintf(stderr, "Failed to connect to Xen daemon\n");
return(-1);
}
+ ret = xenStoreOpen(conn, NULL, VIR_DRV_OPEN_QUIET | VIR_DRV_OPEN_RO);
+ if (ret < 0) {
+ fprintf(stderr, "Failed to open XenStore connection");
+ return (-1);
+ }
ret = xenDaemonGetVersion(conn, &xenVersion2);
if (ret != 0) {
fprintf(stderr, "Failed to get Xen daemon version\n");
virProxyFullPacket request;
virProxyPacketPtr req = (virProxyPacketPtr) &request;
int ret;
+ char *xml;
retry:
ret = read(pollInfos[nr].fd, req, sizeof(virProxyPacket));
req->len = sizeof(virProxyPacket) + sizeof(virNodeInfo);
}
break;
+ case VIR_PROXY_DOMAIN_XML:
+ if (req->len != sizeof(virProxyPacket))
+ goto comm_error;
+
+ xml = xenDaemonDomainDumpXMLByID(conn, request.data.arg);
+ if (!xml) {
+ req->data.arg = -1;
+ req->len = sizeof(virProxyPacket);
+ } else {
+ int xmllen = strlen(xml);
+ if (xmllen > sizeof(request.extra.str)) {
+ req->data.arg = -2;
+ req->len = sizeof(virProxyPacket);
+ } else {
+ req->data.arg = 0;
+ memmove(&request.extra.str[0], xml, xmllen);
+ req->len = sizeof(virProxyPacket) + xmllen;
+ }
+ free(xml);
+ }
+ break;
default:
goto comm_error;
}
typedef int
(*virDrvDomainRestore) (virConnectPtr conn,
const char *from);
+typedef char *
+ (*virDrvDomainDumpXML) (virDomainPtr dom,
+ int flags);
typedef int
(*virDrvDomainSetVcpus) (virDomainPtr domain,
virDrvDomainSetVcpus domainSetVcpus;
virDrvDomainPinVcpu domainPinVcpu;
virDrvDomainGetVcpus domainGetVcpus;
+ virDrvDomainDumpXML domainDumpXML;
};
char *
virDomainGetXMLDesc(virDomainPtr domain, int flags)
{
+ int i;
+ char *ret = NULL;
if (!VIR_IS_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return (NULL);
return (NULL);
}
- return (xenDaemonDomainDumpXML(domain));
+ for (i = 0;i < domain->conn->nb_drivers;i++) {
+ if ((domain->conn->drivers[i] != NULL) &&
+ (domain->conn->drivers[i]->domainDumpXML != NULL)) {
+ ret = domain->conn->drivers[i]->domainDumpXML(domain, flags);
+ if (ret)
+ break;
+ }
+ }
+ if (!ret) {
+ virLibConnError(domain->conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
+ return (NULL);
+ }
+ return(ret);
}
/**
const char *domname);
static unsigned long xenProxyDomainGetMaxMemory(virDomainPtr domain);
static int xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
+static char *xenProxyDomainDumpXML(virDomainPtr domain, int flags);
static virDriver xenProxyDriver = {
VIR_DRV_XEN_PROXY,
NULL, /* domainRestore */
NULL, /* domainSetVcpus */
NULL, /* domainPinVcpu */
- NULL /* domainGetVcpus */
+ NULL, /* domainGetVcpus */
+ xenProxyDomainDumpXML, /* domainDumpXML */
};
/**
return(0);
}
+/**
+ * xenProxyDomainDumpXML:
+ * @domain: a domain object
+ * @flags: xml generation flags
+ *
+ * This method generates an XML description of a domain.
+ *
+ * Returns the XML document on success, NULL otherwise.
+ */
+static char *
+xenProxyDomainDumpXML(virDomainPtr domain, int flags)
+{
+ virProxyPacket req;
+ virProxyFullPacket ans;
+ int ret;
+ int xmllen;
+ char *xml;
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ if (domain == NULL)
+ virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ else
+ virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ return (NULL);
+ }
+ memset(&req, 0, sizeof(req));
+ req.command = VIR_PROXY_DOMAIN_XML;
+ req.data.arg = domain->handle;
+ req.len = sizeof(req);
+ ret = xenProxyCommand(domain->conn, &req, &ans, 0);
+ if (ret < 0) {
+ xenProxyClose(domain->conn);
+ return(NULL);
+ }
+ if (ans.len <= sizeof(virProxyPacket)) {
+ virProxyError(domain->conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
+ return (NULL);
+ }
+ xmllen = ans.len - sizeof(virProxyPacket);
+ if (!(xml = malloc(xmllen+1))) {
+ return NULL;
+ }
+ memmove(xml, &ans.extra.dinfo, xmllen);
+ xml[xmllen] = '\0';
+
+ return(xml);
+}
VIR_PROXY_LOOKUP_UUID = 6,
VIR_PROXY_LOOKUP_NAME = 7,
VIR_PROXY_MAX_MEMORY = 8,
- VIR_PROXY_DOMAIN_INFO = 9
+ VIR_PROXY_DOMAIN_INFO = 9,
+ VIR_PROXY_DOMAIN_XML = 10,
} virProxyCommand;
/*
NULL, /* domainRestore */
NULL, /* domainSetVcpus */
NULL, /* domainPinVcpu */
- NULL /* domainGetVcpus */
+ NULL, /* domainGetVcpus */
+ NULL, /* domainDumpXML */
};
/* Amount of time it takes to shutdown */
NULL, /* domainRestore */
xenHypervisorSetVcpus, /* domainSetVcpus */
xenHypervisorPinVcpu, /* domainPinVcpu */
- xenHypervisorGetVcpus /* domainGetVcpus */
+ xenHypervisorGetVcpus, /* domainGetVcpus */
+ NULL, /* domainDumpXML */
};
#endif /* !PROXY */
}
+#ifndef PROXY
/**
* xenHypervisorPauseDomain:
* @domain: pointer to the domain block
return (-1);
return (0);
}
+#endif /* PROXY */
/**
* xenHypervisorCheckID:
return (0);
}
+#ifndef PROXY
/**
* xenHypervisorSetVcpus:
* @domain: pointer to domain object
return (-1);
return 0;
}
+#endif
/**
* virDomainGetVcpus:
static virDomainPtr xenDaemonCreateLinux(virConnectPtr conn,
const char *xmlDesc,
unsigned int flags);
-#endif
+#endif /* PROXY */
#ifndef PROXY
static virDriver xenDaemonDriver = {
xenDaemonDomainRestore, /* domainRestore */
xenDaemonDomainSetVcpus, /* domainSetVcpus */
xenDaemonDomainPinVcpu, /* domainPinVcpu */
- xenDaemonDomainGetVcpus /* domainGetVcpus */
+ xenDaemonDomainGetVcpus, /* domainGetVcpus */
+ xenDaemonDomainDumpXML, /* domainDumpXML */
};
/**
return ret;
}
+#ifndef PROXY
/**
* xend_post:
* @xend: pointer to the Xen Daemon structure
return ret;
}
+#endif /* ! PROXY */
+
/**
* http2unix:
return -1;
}
+#ifndef PROXY
/**
* xend_op_ext2:
* @xend: pointer to the Xen Daemon structure
return http2unix(xend_post(xend, path, ops, error, n_error));
}
+
/**
* xend_node_op:
* @xend: pointer to the Xen Daemon structure
return ret;
}
+
/**
* xend_node_op:
* @xend: pointer to the Xen Daemon structure
}
#define xend_op(xend, name, key, ...) ({char error[1024]; xend_op_ext(xend, name, error, sizeof(error), key, __VA_ARGS__);})
+#endif /* ! PROXY */
/**
* sexpr_get:
}
+#ifndef PROXY
/**
* urlencode:
* @string: the input URL
return buffer;
}
+#endif /* ! PROXY */
/* PUBLIC FUNCTIONS */
return (0);
}
+#ifndef PROXY
/**
* xenDaemonOpen_tcp:
* @conn: an existing virtual connection block
return (0);
}
+
/**
* xend_wait_for_devices:
* @xend: pointer to the Xem Daemon block
return xend_op(xend, name, "op", "wait_for_devices", NULL);
}
+
/**
* xend_rename:
* @xend: pointer to the Xem Daemon block
return xend_op(xend, old, "op", "rename", "name", new, NULL);
}
+
/**
* xend_sysrq:
* @xend: pointer to the Xem Daemon block
}
return xend_op(xend, name, "op", "sysrq", "key", key, NULL);
}
+#endif /* PROXY */
+
/**
* xenDaemonListDomainsOld:
return ret;
}
+#ifndef PROXY
/**
* xenDaemonDomainCreateLinux:
* @xend: A xend instance
return ret;
}
+#endif /* ! PROXY */
/**
* xenDaemonDomainLookupByName_ids:
return node;
}
+#ifndef PROXY
/**
* xend_node_shutdown:
* @xend: A xend instance
return xend_node_op(xend, "/xend/node/", "op", "restart", NULL);
}
+
/**
* xend_dmesg:
* @xend: A xend instance
{
return http2unix(xend_get(xend, "/xend/node/log", buffer, n_buffer));
}
+#endif /* PROXY */
/*****************************************************************
******
******
******
*****************************************************************/
-#ifndef PROXY
/**
* xend_parse_sexp_desc_os:
* the caller must free() the returned value.
*/
static char *
-xend_parse_sexp_desc(virDomainPtr domain, struct sexpr *root)
+xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root)
{
char *ret;
struct sexpr *cur, *node;
char *tty;
virBuffer buf;
int hvm = 0;
+ int domid = -1;
if (root == NULL) {
/* ERROR */
buf.size = 1000;
buf.use = 0;
- virBufferVSprintf(&buf, "<domain type='xen' id='%d'>\n",
- sexpr_int(root, "domain/domid"));
+ domid = sexpr_int(root, "domain/domid");
+ virBufferVSprintf(&buf, "<domain type='xen' id='%d'>\n", domid);
+
tmp = sexpr_node(root, "domain/name");
if (tmp == NULL) {
virXendError(NULL, VIR_ERR_INTERNAL_ERROR,
tmp = sexpr_node(root, "domain/image/hvm/vnc");
if (tmp != NULL) {
if (tmp[0] == '1') {
- int port = xenStoreDomainGetVNCPort(domain);
+ int port = xenStoreDomainGetVNCPort(conn, domid);
if (port == -1)
- port = 5900 + sexpr_int(root, "domain/domid");
+ port = 5900 + domid;
virBufferVSprintf(&buf, " <graphics type='vnc' port='%d'/>\n", port);
}
}
*/
}
- tty = xenStoreDomainGetConsolePath(domain);
+ tty = xenStoreDomainGetConsolePath(conn, domid);
if (tty) {
virBufferVSprintf(&buf, " <console tty='%s'/>\n", tty);
free(tty);
free(ret);
return (NULL);
}
-#endif /* !PROXY */
+
/**
* sexpr_to_xend_domain_info:
xmlFreeURI(uri);
return(-1);
}
-#endif /* !PROXY */
+
/**
* xenDaemonClose:
}
return xend_op(conn, "", "op", "restore", "file", filename, NULL);
}
+#endif /* !PROXY */
/**
* xenDaemonDomainGetMaxMemory:
return(ret);
}
+#ifndef PROXY
/**
* xenDaemonDomainSetMaxMemory:
* @domain: pointer to the Domain block
"target", buf, NULL);
}
+#endif /* ! PROXY */
+
+char *
+xenDaemonDomainDumpXMLByID(virConnectPtr conn, int domid)
+{
+ char *ret = NULL;
+ struct sexpr *root;
+
+ root = sexpr_get(conn, "/xend/domain/%d?detail=1", domid);
+ if (root == NULL)
+ return (NULL);
+
+ ret = xend_parse_sexp_desc(conn, root);
+ sexpr_free(root);
+
+ return (ret);
+}
+
+
#ifndef PROXY
/**
* xenDaemonDomainDumpXML:
* the caller must free() the returned value.
*/
char *
-xenDaemonDomainDumpXML(virDomainPtr domain)
+xenDaemonDomainDumpXML(virDomainPtr domain, int flags)
{
- char *ret = NULL;
- struct sexpr *root;
-
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
return(NULL);
}
- root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
- if (root == NULL)
- return (NULL);
-
- ret = xend_parse_sexp_desc(domain, root);
- sexpr_free(root);
-
- return (ret);
+ return xenDaemonDomainDumpXMLByID(domain->conn, domain->handle);
}
#endif /* !PROXY */
sexpr_free(root);
return(ret);
}
-#endif
+#endif /* ! PROXY */
/**
* xenDaemonNodeGetInfo:
}
return("XenDaemon");
}
-#endif
+#endif /* ! PROXY */
/**
* xenDaemonGetVersion:
sexpr_free(root);
return(ret);
}
-#endif
+#endif /* ! PROXY */
#ifndef PROXY
/**
free(name);
return (NULL);
}
-
-#endif
+#endif /* ! PROXY */
char **name, unsigned char *uuid);
+char *xenDaemonDomainDumpXMLByID(virConnectPtr xend,
+ int domid);
+
/**
* \brief Lookup information about the host machine
* \param xend A xend instance
int xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory);
int xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory);
int xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
-char *xenDaemonDomainDumpXML(virDomainPtr domain);
+char *xenDaemonDomainDumpXML(virDomainPtr domain, int flags);
virDomainPtr xenDaemonDomainLookupByName(virConnectPtr conn, const char *domname);
unsigned long xenDaemonDomainGetMaxMemory(virDomainPtr domain);
char **xenDaemonListDomainsOld(virConnectPtr xend);
#endif
+#ifndef PROXY
/**
* virDomainParseXMLOSDescHVM:
* @node: node containing HVM OS description
free(ret);
return (NULL);
}
+
+#endif /* !PROXY */
#define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd"
+#ifndef PROXY
static virDriver xenStoreDriver = {
VIR_DRV_XEN_STORE,
"XenStore",
NULL, /* domainRestore */
NULL, /* domainSetVcpus */
NULL, /* domainPinVcpu */
- NULL /* domainGetVcpus */
+ NULL, /* domainGetVcpus */
+ NULL, /* domainDumpXML */
};
/**
{
virRegisterDriver(&xenStoreDriver);
}
+#endif /* ! PROXY */
/**
* virXenStoreError:
* Helper internal APIs *
* *
************************************************************************/
+#ifndef PROXY
/**
* virConnectDoStoreList:
* @conn: pointer to the hypervisor connection
return xs_directory(conn->xshandle, 0, path, nb);
}
+#endif /* ! PROXY */
/**
* virDomainDoStoreQuery:
- * @domain: a domain object
+ * @conn: pointer to the hypervisor connection
+ * @domid: id of the domain
* @path: the relative path of the data in the store to retrieve
*
* Internal API querying the Xenstore for a string value.
* Returns a string which must be freed by the caller or NULL in case of error
*/
static char *
-virDomainDoStoreQuery(virDomainPtr domain, const char *path)
+virDomainDoStoreQuery(virConnectPtr conn, int domid, const char *path)
{
char s[256];
unsigned int len = 0;
- if (!VIR_IS_CONNECTED_DOMAIN(domain))
- return (NULL);
- if (domain->conn->xshandle == NULL)
+ if (conn->xshandle == NULL)
return (NULL);
- snprintf(s, 255, "/local/domain/%d/%s", domain->handle, path);
+ snprintf(s, 255, "/local/domain/%d/%s", domid, path);
s[255] = 0;
- return xs_read(domain->conn->xshandle, 0, &s[0], &len);
+ return xs_read(conn->xshandle, 0, &s[0], &len);
}
-
+#ifndef PROXY
/**
* virDomainDoStoreWrite:
* @domain: a domain object
}
return (0);
}
+#endif /* ! PROXY */
/************************************************************************
* *
if ((name != NULL) && (strcasecmp(name, "xen")))
return(-1);
+#ifdef PROXY
+ conn->xshandle = xs_daemon_open_readonly();
+#else
if (flags & VIR_DRV_OPEN_RO)
conn->xshandle = xs_daemon_open_readonly();
else
conn->xshandle = xs_daemon_open();
+#endif /* ! PROXY */
if (conn->xshandle == NULL) {
if (!(flags & VIR_DRV_OPEN_QUIET))
return (0);
}
+#ifndef PROXY
/**
* xenStoreGetDomainInfo:
* @domain: pointer to the domain block
unsigned int nb_vcpus;
char request[200];
+ if (!VIR_IS_CONNECTED_DOMAIN(domain))
+ return (-1);
+
if ((domain == NULL) || (domain->conn == NULL) || (info == NULL)) {
virXenStoreError(domain ? domain->conn : NULL, VIR_ERR_INVALID_ARG,
__FUNCTION__);
if (domain->conn->xshandle == NULL)
return(-1);
- tmp = virDomainDoStoreQuery(domain, "running");
+ tmp = virDomainDoStoreQuery(domain->conn, domain->handle, "running");
if (tmp != NULL) {
if (tmp[0] == '1')
info->state = VIR_DOMAIN_RUNNING;
} else {
info->state = VIR_DOMAIN_NONE;
}
- tmp = virDomainDoStoreQuery(domain, "memory/target");
+ tmp = virDomainDoStoreQuery(domain->conn, domain->handle, "memory/target");
if (tmp != NULL) {
info->memory = atol(tmp);
info->maxMem = atol(tmp);
}
#if 0
/* doesn't seems to work */
- tmp = virDomainDoStoreQuery(domain, "cpu_time");
+ tmp = virDomainDoStoreQuery(domain->conn, domain->handle, "cpu_time");
if (tmp != NULL) {
info->cpuTime = atol(tmp);
free(tmp);
char *tmp;
unsigned long ret = 0;
- tmp = virDomainDoStoreQuery(domain, "memory/target");
+ if (!VIR_IS_CONNECTED_DOMAIN(domain))
+ return (ret);
+
+ tmp = virDomainDoStoreQuery(domain->conn, domain->handle, "memory/target");
if (tmp != NULL) {
ret = (unsigned long) atol(tmp);
free(tmp);
*/
return(virDomainDoStoreWrite(domain, "control/shutdown", "reboot"));
}
+#endif /* ! PROXY */
/**
* xenStoreDomainGetVNCPort:
- * @domain: pointer to the domain block
+ * @conn: the hypervisor connection
+ * @domid: id of the domain
*
* Return the port number on which the domain is listening for VNC
* connections.
*
* Returns the port number, -1 in case of error
*/
-int xenStoreDomainGetVNCPort(virDomainPtr domain) {
+int xenStoreDomainGetVNCPort(virConnectPtr conn, int domid) {
char *tmp;
int ret = -1;
- tmp = virDomainDoStoreQuery(domain, "console/vnc-port");
+ tmp = virDomainDoStoreQuery(conn, domid, "console/vnc-port");
if (tmp != NULL) {
char *end;
ret = strtol(tmp, &end, 10);
/**
* xenStoreDomainGetConsolePath:
- * @domain: pointer to the domain block
+ * @conn: the hypervisor connection
+ * @domid: id of the domain
*
* Return the path to the psuedo TTY on which the guest domain's
* serial console is attached.
* responsibilty to free() the return string. Returns NULL
* on error
*/
-char * xenStoreDomainGetConsolePath(virDomainPtr domain) {
- return virDomainDoStoreQuery(domain, "console/tty");
+char * xenStoreDomainGetConsolePath(virConnectPtr conn, int domid) {
+ return virDomainDoStoreQuery(conn, domid, "console/tty");
}
int xenStoreDomainShutdown (virDomainPtr domain);
int xenStoreDomainReboot (virDomainPtr domain,
unsigned int flags);
-int xenStoreDomainGetVNCPort(virDomainPtr domain);
-char * xenStoreDomainGetConsolePath(virDomainPtr domain);
+
+int xenStoreDomainGetVNCPort(virConnectPtr conn, int domid);
+char * xenStoreDomainGetConsolePath(virConnectPtr conn, int domid);
#ifdef __cplusplus
}