2006-06-28 18:19:13 +00:00
|
|
|
/*
|
|
|
|
* proxy_client.c: client side of the communication with the libvirt proxy.
|
|
|
|
*
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
* Copyright (C) 2006, 2008 Red Hat, Inc.
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
|
|
|
* See COPYING.LIB for the License of this software
|
|
|
|
*
|
|
|
|
* Daniel Veillard <veillard@redhat.com>
|
|
|
|
*/
|
|
|
|
|
2008-01-29 18:15:54 +00:00
|
|
|
#include <config.h>
|
2007-12-05 21:40:15 +00:00
|
|
|
|
2006-06-28 18:19:13 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/poll.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#include <sys/wait.h>
|
2007-06-15 15:24:20 +00:00
|
|
|
#include <string.h>
|
2006-06-28 18:19:13 +00:00
|
|
|
#include "internal.h"
|
2006-06-29 22:12:47 +00:00
|
|
|
#include "driver.h"
|
|
|
|
#include "proxy_internal.h"
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
#include "util.h"
|
2007-04-04 14:19:49 +00:00
|
|
|
#include "xen_unified.h"
|
2008-06-06 11:09:57 +00:00
|
|
|
#include "memory.h"
|
2006-06-28 18:19:13 +00:00
|
|
|
|
|
|
|
#define STANDALONE
|
|
|
|
|
2006-06-29 22:12:47 +00:00
|
|
|
static int debug = 0;
|
|
|
|
|
|
|
|
static int xenProxyClose(virConnectPtr conn);
|
2007-12-05 18:28:05 +00:00
|
|
|
static int xenProxyOpen(virConnectPtr conn, xmlURIPtr uri, virConnectAuthPtr auth, int flags);
|
2006-06-29 22:12:47 +00:00
|
|
|
static int xenProxyGetVersion(virConnectPtr conn, unsigned long *hvVer);
|
|
|
|
static int xenProxyNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
|
2007-04-30 16:58:26 +00:00
|
|
|
static char *xenProxyGetCapabilities(virConnectPtr conn);
|
2006-06-29 22:12:47 +00:00
|
|
|
static int xenProxyListDomains(virConnectPtr conn, int *ids, int maxids);
|
|
|
|
static int xenProxyNumOfDomains(virConnectPtr conn);
|
|
|
|
static unsigned long xenProxyDomainGetMaxMemory(virDomainPtr domain);
|
|
|
|
static int xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
|
2006-11-07 16:28:16 +00:00
|
|
|
static char *xenProxyDomainGetOSType(virDomainPtr domain);
|
2006-06-29 22:12:47 +00:00
|
|
|
|
Fri Jul 6 16:08:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
* src/proxy_internal.c, src/proxy_internal.h,
src.xen_internal.c, src/xen_internal.h,
src/xen_unified.c, src/xen_unified.h,
src/xend_internal.c, src/xend_internal.h,
src/xm_internal.c, src/xm_internal.h,
src/xs_internal.c, src/xs_internal.h: The interface
between xen_unified.c and its underlying driver now uses
a custom structure (struct xenUnifiedDriver) instead
of reusing virDriver.
* src/xen_unified.c: virDomainLookup* functions in Xen
now throw VIR_ERR_NO_DOMAIN if the domain does not exist.
* src/xs_internal.c: Fix indentation.
2007-07-06 15:11:22 +00:00
|
|
|
struct xenUnifiedDriver xenProxyDriver = {
|
2006-06-29 22:12:47 +00:00
|
|
|
xenProxyOpen, /* open */
|
|
|
|
xenProxyClose, /* close */
|
|
|
|
xenProxyGetVersion, /* version */
|
2007-06-26 11:42:46 +00:00
|
|
|
NULL, /* hostname */
|
|
|
|
NULL, /* URI */
|
2006-07-03 11:12:12 +00:00
|
|
|
xenProxyNodeGetInfo, /* nodeGetInfo */
|
2007-04-30 16:58:26 +00:00
|
|
|
xenProxyGetCapabilities, /* getCapabilities */
|
2006-06-29 22:12:47 +00:00
|
|
|
xenProxyListDomains, /* listDomains */
|
|
|
|
xenProxyNumOfDomains, /* numOfDomains */
|
|
|
|
NULL, /* domainCreateLinux */
|
|
|
|
NULL, /* domainSuspend */
|
|
|
|
NULL, /* domainResume */
|
|
|
|
NULL, /* domainShutdown */
|
|
|
|
NULL, /* domainReboot */
|
|
|
|
NULL, /* domainDestroy */
|
2006-11-07 16:28:16 +00:00
|
|
|
xenProxyDomainGetOSType, /* domainGetOSType */
|
2006-06-29 22:12:47 +00:00
|
|
|
xenProxyDomainGetMaxMemory, /* domainGetMaxMemory */
|
|
|
|
NULL, /* domainSetMaxMemory */
|
|
|
|
NULL, /* domainSetMemory */
|
|
|
|
xenProxyDomainGetInfo, /* domainGetInfo */
|
|
|
|
NULL, /* domainSave */
|
2006-08-08 22:22:55 +00:00
|
|
|
NULL, /* domainRestore */
|
2006-11-22 17:48:29 +00:00
|
|
|
NULL, /* domainCoreDump */
|
2006-08-08 22:22:55 +00:00
|
|
|
NULL, /* domainSetVcpus */
|
|
|
|
NULL, /* domainPinVcpu */
|
2006-08-09 15:21:16 +00:00
|
|
|
NULL, /* domainGetVcpus */
|
2007-03-08 08:31:07 +00:00
|
|
|
NULL, /* domainGetMaxVcpus */
|
2006-08-30 14:21:03 +00:00
|
|
|
NULL, /* listDefinedDomains */
|
|
|
|
NULL, /* numOfDefinedDomains */
|
|
|
|
NULL, /* domainCreate */
|
|
|
|
NULL, /* domainDefineXML */
|
|
|
|
NULL, /* domainUndefine */
|
2006-11-16 18:11:28 +00:00
|
|
|
NULL, /* domainAttachDevice */
|
|
|
|
NULL, /* domainDetachDevice */
|
2007-02-23 08:51:30 +00:00
|
|
|
NULL, /* domainGetAutostart */
|
|
|
|
NULL, /* domainSetAutostart */
|
2007-06-05 12:06:08 +00:00
|
|
|
NULL, /* domainGetSchedulerType */
|
|
|
|
NULL, /* domainGetSchedulerParameters */
|
|
|
|
NULL, /* domainSetSchedulerParameters */
|
2006-06-29 22:12:47 +00:00
|
|
|
};
|
2006-06-28 18:19:13 +00:00
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2006-06-28 18:19:13 +00:00
|
|
|
/************************************************************************
|
|
|
|
* *
|
|
|
|
* Error handling *
|
|
|
|
* *
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virProxyError:
|
|
|
|
* @conn: the connection if available
|
2008-04-04 07:58:29 +00:00
|
|
|
* @error: the error number
|
2006-06-28 18:19:13 +00:00
|
|
|
* @info: extra information string
|
|
|
|
*
|
|
|
|
* Handle an error at the xend daemon interface
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
virProxyError(virConnectPtr conn, virErrorNumber error, const char *info)
|
|
|
|
{
|
2006-06-29 22:12:47 +00:00
|
|
|
const char *errmsg;
|
|
|
|
|
2006-06-28 18:19:13 +00:00
|
|
|
if (error == VIR_ERR_OK)
|
|
|
|
return;
|
|
|
|
|
|
|
|
errmsg = __virErrorMsg(error, info);
|
Tue Feb 14 15:37:17 EST 2007 Mark McLoughlin <markmc@redhat.com>
Note: potential ABI break here, but people should
only really be using virError structs returned from
libvirt itself.
* include/libvirt/virterror.h: add virNetwork
to virError
* src/internal.h, src/virterror.c: add network param
to __virRaiseError()
* src/conf.c, src/hash.c, src/libvirt.c, src/proxy_internal.c,
src/qemu_internal.c, src/sexpr.c, src/test.c, src/xen_internal.c,
src/xend_internal.c, src/xm_internal.c, src/xml.c, src/xmlrpc.c,
src/xs_internal.c: update.
2007-02-14 15:40:53 +00:00
|
|
|
__virRaiseError(conn, NULL, NULL, VIR_FROM_PROXY, error, VIR_ERR_ERROR,
|
2006-06-28 18:19:13 +00:00
|
|
|
errmsg, info, NULL, 0, 0, errmsg, info);
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* *
|
|
|
|
* Automatic startup of the proxy server if it is not running *
|
|
|
|
* *
|
|
|
|
************************************************************************/
|
|
|
|
/**
|
|
|
|
* virProxyFindServerPath:
|
|
|
|
*
|
|
|
|
* Tries to find the path to the gam_server binary.
|
2008-02-05 19:27:37 +00:00
|
|
|
*
|
2006-06-28 18:19:13 +00:00
|
|
|
* Returns path on success or NULL in case of error.
|
|
|
|
*/
|
|
|
|
static const char *
|
|
|
|
virProxyFindServerPath(void)
|
|
|
|
{
|
|
|
|
static const char *serverPaths[] = {
|
|
|
|
BINDIR "/libvirt_proxy",
|
2006-06-29 22:12:47 +00:00
|
|
|
"/usr/bin/libvirt_proxy_dbg",
|
2006-06-28 18:19:13 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
int i;
|
|
|
|
const char *debugProxy = getenv("LIBVIRT_DEBUG_PROXY");
|
|
|
|
|
|
|
|
if (debugProxy)
|
|
|
|
return(debugProxy);
|
|
|
|
|
|
|
|
for (i = 0; serverPaths[i]; i++) {
|
|
|
|
if (access(serverPaths[i], X_OK | R_OK) == 0) {
|
|
|
|
return serverPaths[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virProxyForkServer:
|
|
|
|
*
|
|
|
|
* Forks and try to launch the proxy server processing the requests for
|
|
|
|
* libvirt when communicating with Xen.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or -1 in case of detected error.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virProxyForkServer(void)
|
|
|
|
{
|
|
|
|
const char *proxyPath = virProxyFindServerPath();
|
|
|
|
int ret, pid, status;
|
|
|
|
|
|
|
|
if (!proxyPath) {
|
|
|
|
fprintf(stderr, "failed to find libvirt_proxy\n");
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (debug)
|
|
|
|
fprintf(stderr, "Asking to launch %s\n", proxyPath);
|
|
|
|
|
|
|
|
/* Become a daemon */
|
|
|
|
pid = fork();
|
|
|
|
if (pid == 0) {
|
|
|
|
long open_max;
|
2008-04-10 16:54:54 +00:00
|
|
|
long i;
|
2006-06-28 18:19:13 +00:00
|
|
|
|
|
|
|
/* don't hold open fd opened from the client of the library */
|
2008-04-10 16:54:54 +00:00
|
|
|
open_max = sysconf (_SC_OPEN_MAX);
|
|
|
|
for (i = 0; i < open_max; i++)
|
|
|
|
fcntl (i, F_SETFD, FD_CLOEXEC);
|
2006-06-28 18:19:13 +00:00
|
|
|
|
|
|
|
setsid();
|
|
|
|
if (fork() == 0) {
|
|
|
|
execl(proxyPath, proxyPath, NULL);
|
2006-09-21 15:24:37 +00:00
|
|
|
fprintf(stderr, _("failed to exec %s\n"), proxyPath);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* calling exit() generate troubles for termination handlers
|
|
|
|
*/
|
|
|
|
_exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* do a waitpid on the intermediate process to avoid zombies.
|
|
|
|
*/
|
|
|
|
retry_wait:
|
|
|
|
ret = waitpid(pid, &status, 0);
|
|
|
|
if (ret < 0) {
|
|
|
|
if (errno == EINTR)
|
|
|
|
goto retry_wait;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* *
|
|
|
|
* Processing of client sockets *
|
|
|
|
* *
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virProxyOpenClientSocket:
|
2008-05-15 06:12:32 +00:00
|
|
|
* @path: the filename for the socket
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
|
|
|
* try to connect to the socket open by libvirt_proxy
|
|
|
|
*
|
|
|
|
* Returns the associated file descriptor or -1 in case of failure
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virProxyOpenClientSocket(const char *path) {
|
|
|
|
int fd;
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
int trials = 0;
|
|
|
|
|
|
|
|
retry:
|
|
|
|
fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
|
|
|
if (fd < 0) {
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-02-05 19:27:37 +00:00
|
|
|
* Abstract socket do not hit the filesystem, way more secure and
|
2008-04-04 07:58:29 +00:00
|
|
|
* guaranteed to be atomic
|
2006-06-28 18:19:13 +00:00
|
|
|
*/
|
|
|
|
memset(&addr, 0, sizeof(addr));
|
|
|
|
addr.sun_family = AF_UNIX;
|
|
|
|
addr.sun_path[0] = '\0';
|
|
|
|
strncpy(&addr.sun_path[1], path, (sizeof(addr) - 4) - 2);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* now bind the socket to that address and listen on it
|
|
|
|
*/
|
|
|
|
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
2008-04-10 16:54:54 +00:00
|
|
|
close(fd);
|
|
|
|
if (trials < 3) {
|
|
|
|
if (virProxyForkServer() < 0)
|
|
|
|
return(-1);
|
|
|
|
trials++;
|
|
|
|
usleep(5000 * trials * trials);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
return (-1);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (debug > 0)
|
|
|
|
fprintf(stderr, "connected to unix socket %s via %d\n", path, fd);
|
|
|
|
|
|
|
|
return (fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virProxyCloseClientSocket:
|
|
|
|
* @fd: the file descriptor for the socket
|
|
|
|
*
|
|
|
|
* Close the socket from that client
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success and -1 in case of error
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virProxyCloseClientSocket(int fd) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
return(-1);
|
|
|
|
|
|
|
|
ret = close(fd);
|
|
|
|
if (ret != 0)
|
2006-09-21 15:24:37 +00:00
|
|
|
fprintf(stderr, _("Failed to close socket %d\n"), fd);
|
2006-06-28 18:19:13 +00:00
|
|
|
else if (debug > 0)
|
2008-04-10 16:54:54 +00:00
|
|
|
fprintf(stderr, "Closed socket %d\n", fd);
|
2006-06-28 18:19:13 +00:00
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virProxyReadClientSocket:
|
2008-02-05 19:27:37 +00:00
|
|
|
* @fd: the socket
|
2006-06-28 18:19:13 +00:00
|
|
|
* @buffer: the target memory area
|
2008-04-04 07:58:29 +00:00
|
|
|
* @len: the length in bytes
|
2006-07-03 15:48:49 +00:00
|
|
|
* @quiet: quiet access
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
|
|
|
* Process a read from a client socket
|
|
|
|
*
|
|
|
|
* Returns the number of byte read or -1 in case of error.
|
|
|
|
*/
|
|
|
|
static int
|
2006-07-03 15:48:49 +00:00
|
|
|
virProxyReadClientSocket(int fd, char *buffer, int len, int quiet) {
|
2006-06-28 18:19:13 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
if ((fd < 0) || (buffer == NULL) || (len < 0))
|
|
|
|
return(-1);
|
|
|
|
|
|
|
|
retry:
|
|
|
|
ret = read(fd, buffer, len);
|
|
|
|
if (ret < 0) {
|
|
|
|
if (errno == EINTR) {
|
2008-04-10 16:54:54 +00:00
|
|
|
if (debug > 0)
|
|
|
|
fprintf(stderr, "read socket %d interrupted\n", fd);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
if (!quiet)
|
2006-09-21 15:24:37 +00:00
|
|
|
fprintf(stderr, _("Failed to read socket %d\n"), fd);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (debug)
|
2008-04-10 16:54:54 +00:00
|
|
|
fprintf(stderr, "read %d bytes from socket %d\n",
|
|
|
|
ret, fd);
|
2006-06-28 18:19:13 +00:00
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virProxyWriteClientSocket:
|
2008-02-05 19:27:37 +00:00
|
|
|
* @fd: the socket
|
2006-06-28 18:19:13 +00:00
|
|
|
* @data: the data
|
2008-04-04 07:58:29 +00:00
|
|
|
* @len: the length of data in bytes
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
|
|
|
* Process a read from a client socket
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virProxyWriteClientSocket(int fd, const char *data, int len) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if ((fd < 0) || (data == NULL) || (len < 0))
|
|
|
|
return(-1);
|
|
|
|
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
ret = safewrite(fd, data, len);
|
2006-06-28 18:19:13 +00:00
|
|
|
if (ret < 0) {
|
2006-09-21 15:24:37 +00:00
|
|
|
fprintf(stderr, _("Failed to write to socket %d\n"), fd);
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
return(-1);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
if (debug)
|
2008-04-10 16:54:54 +00:00
|
|
|
fprintf(stderr, "wrote %d bytes to socket %d\n",
|
|
|
|
len, fd);
|
2006-06-28 18:19:13 +00:00
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* *
|
|
|
|
* Proxy commands processing *
|
|
|
|
* *
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xenProxyClose:
|
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
*
|
|
|
|
* Shutdown the Xen proxy communication layer
|
|
|
|
*/
|
2006-06-29 22:12:47 +00:00
|
|
|
static int
|
2007-04-04 14:19:49 +00:00
|
|
|
xenProxyClose(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
xenUnifiedPrivatePtr priv;
|
|
|
|
|
|
|
|
if (conn == NULL) {
|
|
|
|
virProxyError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if (!priv) {
|
|
|
|
virProxyError (NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fail silently. */
|
|
|
|
if (priv->proxy == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
virProxyCloseClientSocket (priv->proxy);
|
|
|
|
priv->proxy = -1;
|
|
|
|
|
|
|
|
return 0;
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-05 19:27:37 +00:00
|
|
|
static int
|
2006-06-28 18:19:13 +00:00
|
|
|
xenProxyCommand(virConnectPtr conn, virProxyPacketPtr request,
|
2006-07-03 15:48:49 +00:00
|
|
|
virProxyFullPacketPtr answer, int quiet) {
|
2006-06-28 18:19:13 +00:00
|
|
|
static int serial = 0;
|
|
|
|
int ret;
|
|
|
|
virProxyPacketPtr res = NULL;
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
2006-06-28 18:19:13 +00:00
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
if (conn == NULL) {
|
|
|
|
virProxyError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if (!priv) {
|
|
|
|
virProxyError (NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fail silently. */
|
|
|
|
if (priv->proxy == -1)
|
|
|
|
return -1;
|
2006-06-28 18:19:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* normal communication serial numbers are in 0..4095
|
|
|
|
*/
|
|
|
|
++serial;
|
|
|
|
if (serial >= 4096)
|
|
|
|
serial = 0;
|
|
|
|
request->version = PROXY_PROTO_VERSION;
|
|
|
|
request->serial = serial;
|
2007-04-04 14:19:49 +00:00
|
|
|
ret = virProxyWriteClientSocket(priv->proxy, (const char *) request,
|
2006-06-28 18:19:13 +00:00
|
|
|
request->len);
|
|
|
|
if (ret < 0)
|
|
|
|
return(-1);
|
|
|
|
retry:
|
|
|
|
if (answer == NULL) {
|
|
|
|
/* read in situ */
|
2008-04-10 16:54:54 +00:00
|
|
|
ret = virProxyReadClientSocket(priv->proxy, (char *) request,
|
|
|
|
sizeof(virProxyPacket), quiet);
|
|
|
|
if (ret < 0)
|
|
|
|
return(-1);
|
|
|
|
if (ret != sizeof(virProxyPacket)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
_("Communication error with proxy: got %d bytes of %d\n"),
|
|
|
|
ret, (int) sizeof(virProxyPacket));
|
|
|
|
xenProxyClose(conn);
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
res = request;
|
|
|
|
if (res->len != sizeof(virProxyPacket)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
_("Communication error with proxy: expected %d bytes got %d\n"),
|
|
|
|
(int) sizeof(virProxyPacket), res->len);
|
|
|
|
xenProxyClose(conn);
|
|
|
|
return(-1);
|
|
|
|
}
|
2006-06-28 18:19:13 +00:00
|
|
|
} else {
|
2006-06-29 14:44:37 +00:00
|
|
|
/* read in packet provided */
|
2007-04-04 14:19:49 +00:00
|
|
|
ret = virProxyReadClientSocket(priv->proxy, (char *) answer,
|
2008-04-10 16:54:54 +00:00
|
|
|
sizeof(virProxyPacket), quiet);
|
|
|
|
if (ret < 0)
|
|
|
|
return(-1);
|
|
|
|
if (ret != sizeof(virProxyPacket)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
_("Communication error with proxy: got %d bytes of %d\n"),
|
|
|
|
ret, (int) sizeof(virProxyPacket));
|
|
|
|
xenProxyClose(conn);
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
res = (virProxyPacketPtr) answer;
|
|
|
|
if ((res->len < sizeof(virProxyPacket)) ||
|
|
|
|
(res->len > sizeof(virProxyFullPacket))) {
|
|
|
|
fprintf(stderr,
|
|
|
|
_("Communication error with proxy: got %d bytes packet\n"),
|
|
|
|
res->len);
|
|
|
|
xenProxyClose(conn);
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
if (res->len > sizeof(virProxyPacket)) {
|
|
|
|
ret = virProxyReadClientSocket(priv->proxy,
|
|
|
|
(char *) &(answer->extra.arg[0]),
|
|
|
|
res->len - ret, quiet);
|
|
|
|
if (ret != (int) (res->len - sizeof(virProxyPacket))) {
|
|
|
|
fprintf(stderr,
|
|
|
|
_("Communication error with proxy: got %d bytes of %d\n"),
|
|
|
|
ret, (int) sizeof(virProxyPacket));
|
|
|
|
xenProxyClose(conn);
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
}
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* do more checks on the incoming packet.
|
|
|
|
*/
|
|
|
|
if ((res == NULL) || (res->version != PROXY_PROTO_VERSION) ||
|
|
|
|
(res->len < sizeof(virProxyPacket))) {
|
2008-01-16 17:13:23 +00:00
|
|
|
fprintf(stderr, "%s",
|
|
|
|
_("Communication error with proxy: malformed packet\n"));
|
|
|
|
xenProxyClose(conn);
|
|
|
|
return(-1);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
if (res->serial != serial) {
|
|
|
|
TODO /* Asynchronous communication */
|
2008-04-10 16:54:54 +00:00
|
|
|
fprintf(stderr, _("got asynchronous packet number %d\n"), res->serial);
|
2006-06-28 18:19:13 +00:00
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2006-07-03 13:45:55 +00:00
|
|
|
* xenProxyOpen:
|
2006-06-28 18:19:13 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
2006-06-29 22:12:47 +00:00
|
|
|
* @name: URL for the target, NULL for local
|
|
|
|
* @flags: combination of virDrvOpenFlag(s)
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
|
|
|
* Try to initialize the Xen proxy communication layer
|
2006-06-29 22:12:47 +00:00
|
|
|
* This can be opened only for a read-only kind of access
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
|
|
|
* Returns 0 in case of success, and -1 in case of failure
|
|
|
|
*/
|
|
|
|
int
|
2007-12-05 18:28:05 +00:00
|
|
|
xenProxyOpen(virConnectPtr conn,
|
|
|
|
xmlURIPtr uri ATTRIBUTE_UNUSED,
|
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
|
|
|
int flags)
|
2006-06-29 22:12:47 +00:00
|
|
|
{
|
2006-06-28 18:19:13 +00:00
|
|
|
virProxyPacket req;
|
|
|
|
int ret;
|
|
|
|
int fd;
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2007-12-05 18:28:05 +00:00
|
|
|
if (!(flags & VIR_CONNECT_RO))
|
2006-06-29 22:12:47 +00:00
|
|
|
return(-1);
|
2007-04-04 14:19:49 +00:00
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
priv->proxy = -1;
|
|
|
|
|
2006-06-29 22:12:47 +00:00
|
|
|
fd = virProxyOpenClientSocket(PROXY_SOCKET_PATH);
|
|
|
|
if (fd < 0) {
|
2008-04-10 16:54:54 +00:00
|
|
|
virProxyError(NULL, VIR_ERR_NO_XEN, PROXY_SOCKET_PATH);
|
2007-04-04 14:19:49 +00:00
|
|
|
return(-1);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
2007-04-04 14:19:49 +00:00
|
|
|
priv->proxy = fd;
|
2006-06-28 18:19:13 +00:00
|
|
|
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.command = VIR_PROXY_NONE;
|
|
|
|
req.len = sizeof(req);
|
2006-07-03 15:48:49 +00:00
|
|
|
ret = xenProxyCommand(conn, &req, NULL, 1);
|
2006-06-28 18:19:13 +00:00
|
|
|
if ((ret < 0) || (req.command != VIR_PROXY_NONE)) {
|
2008-04-10 16:54:54 +00:00
|
|
|
virProxyError(NULL, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
|
2006-06-28 18:19:13 +00:00
|
|
|
xenProxyClose(conn);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* *
|
|
|
|
* Driver entry points *
|
|
|
|
* *
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xenProxyGetVersion:
|
|
|
|
* @conn: pointer to the Xen Daemon block
|
|
|
|
* @hvVer: return value for the version of the running hypervisor (OUT)
|
|
|
|
*
|
|
|
|
* Get the version level of the Hypervisor running.
|
|
|
|
*
|
|
|
|
* Returns -1 in case of error, 0 otherwise. if the version can't be
|
|
|
|
* extracted by lack of capacities returns 0 and @hvVer is 0, otherwise
|
|
|
|
* @hvVer value is major * 1,000,000 + minor * 1,000 + release
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
xenProxyGetVersion(virConnectPtr conn, unsigned long *hvVer)
|
|
|
|
{
|
|
|
|
virProxyPacket req;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECT(conn)) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (hvVer == NULL) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2008-04-10 16:54:54 +00:00
|
|
|
return (-1);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.command = VIR_PROXY_VERSION;
|
|
|
|
req.len = sizeof(req);
|
2006-07-03 15:48:49 +00:00
|
|
|
ret = xenProxyCommand(conn, &req, NULL, 0);
|
2006-06-28 18:19:13 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
xenProxyClose(conn);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
*hvVer = req.data.larg;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xenProxyListDomains:
|
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
* @ids: array to collect the list of IDs of active domains
|
|
|
|
* @maxids: size of @ids
|
|
|
|
*
|
|
|
|
* Collect the list of active domains, and store their ID in @maxids
|
|
|
|
*
|
|
|
|
* Returns the number of domain found or -1 in case of error
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
xenProxyListDomains(virConnectPtr conn, int *ids, int maxids)
|
|
|
|
{
|
2006-06-29 14:44:37 +00:00
|
|
|
virProxyPacket req;
|
|
|
|
virProxyFullPacket ans;
|
|
|
|
int ret;
|
|
|
|
int nb;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECT(conn)) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if ((ids == NULL) || (maxids <= 0)) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2008-04-10 16:54:54 +00:00
|
|
|
return (-1);
|
2006-06-29 14:44:37 +00:00
|
|
|
}
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.command = VIR_PROXY_LIST;
|
|
|
|
req.len = sizeof(req);
|
2006-07-03 15:48:49 +00:00
|
|
|
ret = xenProxyCommand(conn, &req, &ans, 0);
|
2006-06-29 14:44:37 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
xenProxyClose(conn);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-06-29 14:44:37 +00:00
|
|
|
}
|
|
|
|
nb = ans.data.arg;
|
2006-06-29 22:12:47 +00:00
|
|
|
if ((nb > 1020) || (nb <= 0) ||
|
|
|
|
(ans.len <= sizeof(virProxyPacket)) ||
|
2008-04-10 16:54:54 +00:00
|
|
|
(ans.len > sizeof(virProxyFullPacket))) {
|
2006-06-29 22:12:47 +00:00
|
|
|
virProxyError(conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
|
2006-06-29 14:44:37 +00:00
|
|
|
return(-1);
|
2006-06-29 22:12:47 +00:00
|
|
|
}
|
2006-06-29 14:44:37 +00:00
|
|
|
if (nb > maxids)
|
|
|
|
nb = maxids;
|
|
|
|
memmove(ids, &ans.extra.arg[0], nb * sizeof(int));
|
|
|
|
|
|
|
|
return(nb);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xenProxyNumOfDomains:
|
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
*
|
|
|
|
* Provides the number of active domains.
|
|
|
|
*
|
|
|
|
* Returns the number of domain found or -1 in case of error
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
xenProxyNumOfDomains(virConnectPtr conn)
|
|
|
|
{
|
2006-06-29 14:44:37 +00:00
|
|
|
virProxyPacket req;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECT(conn)) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.command = VIR_PROXY_NUM_DOMAIN;
|
|
|
|
req.len = sizeof(req);
|
2006-07-03 15:48:49 +00:00
|
|
|
ret = xenProxyCommand(conn, &req, NULL, 0);
|
2006-06-29 14:44:37 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
xenProxyClose(conn);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-06-29 14:44:37 +00:00
|
|
|
}
|
|
|
|
return(req.data.arg);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
|
2006-06-29 22:12:47 +00:00
|
|
|
|
2006-06-28 18:19:13 +00:00
|
|
|
/**
|
2006-06-29 22:12:47 +00:00
|
|
|
* xenProxyDomainGetDomMaxMemory:
|
2006-06-28 18:19:13 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
* @id: the domain ID number
|
|
|
|
*
|
2006-06-29 22:12:47 +00:00
|
|
|
* Ask the Xen Daemon for the maximum memory allowed for a domain
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
2006-06-29 22:12:47 +00:00
|
|
|
* Returns the memory size in kilobytes or 0 in case of error.
|
2006-06-28 18:19:13 +00:00
|
|
|
*/
|
2006-06-29 22:12:47 +00:00
|
|
|
static unsigned long
|
|
|
|
xenProxyDomainGetDomMaxMemory(virConnectPtr conn, int id)
|
|
|
|
{
|
|
|
|
virProxyPacket req;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECT(conn)) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
2006-11-15 21:03:34 +00:00
|
|
|
return (0);
|
2006-06-29 22:12:47 +00:00
|
|
|
}
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.command = VIR_PROXY_MAX_MEMORY;
|
|
|
|
req.data.arg = id;
|
|
|
|
req.len = sizeof(req);
|
2006-07-03 15:48:49 +00:00
|
|
|
ret = xenProxyCommand(conn, &req, NULL, 0);
|
2006-06-29 22:12:47 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
xenProxyClose(conn);
|
2006-11-15 21:03:34 +00:00
|
|
|
return(0);
|
2006-06-29 22:12:47 +00:00
|
|
|
}
|
|
|
|
return(req.data.larg);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2006-06-29 22:12:47 +00:00
|
|
|
* xenProxyDomainGetMaxMemory:
|
|
|
|
* @domain: pointer to the domain block
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
2006-06-29 22:12:47 +00:00
|
|
|
* Ask the Xen Daemon for the maximum memory allowed for a domain
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
2006-06-29 22:12:47 +00:00
|
|
|
* Returns the memory size in kilobytes or 0 in case of error.
|
2006-06-28 18:19:13 +00:00
|
|
|
*/
|
2006-06-29 22:12:47 +00:00
|
|
|
static unsigned long
|
|
|
|
xenProxyDomainGetMaxMemory(virDomainPtr domain)
|
2006-06-28 18:19:13 +00:00
|
|
|
{
|
2006-06-29 22:12:47 +00:00
|
|
|
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
|
2008-04-10 16:54:54 +00:00
|
|
|
if (domain == NULL)
|
|
|
|
virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
|
|
|
else
|
|
|
|
virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
2006-06-29 22:12:47 +00:00
|
|
|
return (0);
|
|
|
|
}
|
2007-01-22 16:25:27 +00:00
|
|
|
if (domain->id < 0)
|
2006-11-15 21:03:34 +00:00
|
|
|
return (0);
|
2007-01-22 16:25:27 +00:00
|
|
|
return(xenProxyDomainGetDomMaxMemory(domain->conn, domain->id));
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2006-06-29 22:12:47 +00:00
|
|
|
* xenProxyDomainGetInfo:
|
|
|
|
* @domain: a domain object
|
|
|
|
* @info: pointer to a virDomainInfo structure allocated by the user
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
2006-06-29 22:12:47 +00:00
|
|
|
* This method looks up information about a domain and update the
|
|
|
|
* information block provided.
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
2006-06-29 22:12:47 +00:00
|
|
|
* Returns 0 in case of success, -1 in case of error
|
2006-06-28 18:19:13 +00:00
|
|
|
*/
|
|
|
|
static int
|
2006-06-29 22:12:47 +00:00
|
|
|
xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
|
2006-06-28 18:19:13 +00:00
|
|
|
{
|
2006-06-29 22:12:47 +00:00
|
|
|
virProxyPacket req;
|
|
|
|
virProxyFullPacket ans;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
|
2006-11-15 21:03:34 +00:00
|
|
|
if (domain == NULL)
|
|
|
|
virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
|
|
|
else
|
|
|
|
virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
|
|
|
return (-1);
|
2006-06-29 22:12:47 +00:00
|
|
|
}
|
2007-01-22 16:25:27 +00:00
|
|
|
if (domain->id < 0)
|
2006-11-15 21:03:34 +00:00
|
|
|
return (-1);
|
2006-06-29 22:12:47 +00:00
|
|
|
if (info == NULL) {
|
|
|
|
virProxyError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2006-11-15 21:03:34 +00:00
|
|
|
return (-1);
|
2006-06-29 22:12:47 +00:00
|
|
|
}
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.command = VIR_PROXY_DOMAIN_INFO;
|
2007-01-22 16:25:27 +00:00
|
|
|
req.data.arg = domain->id;
|
2006-06-29 22:12:47 +00:00
|
|
|
req.len = sizeof(req);
|
2006-07-03 15:48:49 +00:00
|
|
|
ret = xenProxyCommand(domain->conn, &req, &ans, 0);
|
2006-06-29 22:12:47 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
xenProxyClose(domain->conn);
|
2006-11-15 21:03:34 +00:00
|
|
|
return(-1);
|
2006-06-29 22:12:47 +00:00
|
|
|
}
|
|
|
|
if (ans.len != sizeof(virProxyPacket) + sizeof(virDomainInfo)) {
|
|
|
|
virProxyError(domain->conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
|
2006-11-15 21:03:34 +00:00
|
|
|
return (-1);
|
2006-06-29 22:12:47 +00:00
|
|
|
}
|
|
|
|
memmove(info, &ans.extra.dinfo, sizeof(virDomainInfo));
|
2006-06-28 18:19:13 +00:00
|
|
|
|
2006-06-29 22:12:47 +00:00
|
|
|
return(0);
|
|
|
|
}
|
2006-06-28 18:19:13 +00:00
|
|
|
|
|
|
|
/**
|
2006-06-29 22:12:47 +00:00
|
|
|
* xenProxyLookupByID:
|
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
* @id: the domain ID number
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
2006-06-29 22:12:47 +00:00
|
|
|
* Try to find a domain based on the hypervisor ID number
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
2006-06-29 22:12:47 +00:00
|
|
|
* Returns a new domain object or NULL in case of failure
|
2006-06-28 18:19:13 +00:00
|
|
|
*/
|
Fri Jul 6 16:08:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
* src/proxy_internal.c, src/proxy_internal.h,
src.xen_internal.c, src/xen_internal.h,
src/xen_unified.c, src/xen_unified.h,
src/xend_internal.c, src/xend_internal.h,
src/xm_internal.c, src/xm_internal.h,
src/xs_internal.c, src/xs_internal.h: The interface
between xen_unified.c and its underlying driver now uses
a custom structure (struct xenUnifiedDriver) instead
of reusing virDriver.
* src/xen_unified.c: virDomainLookup* functions in Xen
now throw VIR_ERR_NO_DOMAIN if the domain does not exist.
* src/xs_internal.c: Fix indentation.
2007-07-06 15:11:22 +00:00
|
|
|
virDomainPtr
|
2006-06-29 22:12:47 +00:00
|
|
|
xenProxyLookupByID(virConnectPtr conn, int id)
|
2006-06-28 18:19:13 +00:00
|
|
|
{
|
2006-06-29 23:53:31 +00:00
|
|
|
virProxyPacket req;
|
|
|
|
virProxyFullPacket ans;
|
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
2006-06-29 23:53:31 +00:00
|
|
|
const char *name;
|
|
|
|
int ret;
|
|
|
|
virDomainPtr res;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECT(conn)) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
|
|
|
return (NULL);
|
|
|
|
}
|
2006-06-30 16:23:16 +00:00
|
|
|
if (id < 0) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2008-04-10 16:54:54 +00:00
|
|
|
return (NULL);
|
2006-06-30 16:23:16 +00:00
|
|
|
}
|
2006-06-29 23:53:31 +00:00
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.command = VIR_PROXY_LOOKUP_ID;
|
|
|
|
req.data.arg = id;
|
|
|
|
req.len = sizeof(req);
|
2006-07-03 15:48:49 +00:00
|
|
|
ret = xenProxyCommand(conn, &req, &ans, 0);
|
2006-06-29 23:53:31 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
xenProxyClose(conn);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(NULL);
|
2006-06-29 23:53:31 +00:00
|
|
|
}
|
2006-07-03 13:45:55 +00:00
|
|
|
if (ans.data.arg == -1) {
|
2008-04-10 16:54:54 +00:00
|
|
|
return(NULL);
|
2006-06-29 23:53:31 +00:00
|
|
|
}
|
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
|
|
|
memcpy(uuid, &ans.extra.str[0], VIR_UUID_BUFLEN);
|
|
|
|
name = &ans.extra.str[VIR_UUID_BUFLEN];
|
2006-06-29 23:53:31 +00:00
|
|
|
res = virGetDomain(conn, name, uuid);
|
2008-04-10 16:54:54 +00:00
|
|
|
if (res) res->id = id;
|
2006-06-29 23:53:31 +00:00
|
|
|
return(res);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2006-06-29 22:12:47 +00:00
|
|
|
* xenProxyLookupByUUID:
|
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
* @uuid: the raw UUID for the domain
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
2006-06-29 22:12:47 +00:00
|
|
|
* Try to lookup a domain on xend based on its UUID.
|
2006-06-28 18:19:13 +00:00
|
|
|
*
|
2006-06-29 22:12:47 +00:00
|
|
|
* Returns a new domain object or NULL in case of failure
|
2006-06-28 18:19:13 +00:00
|
|
|
*/
|
Fri Jul 6 16:08:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
* src/proxy_internal.c, src/proxy_internal.h,
src.xen_internal.c, src/xen_internal.h,
src/xen_unified.c, src/xen_unified.h,
src/xend_internal.c, src/xend_internal.h,
src/xm_internal.c, src/xm_internal.h,
src/xs_internal.c, src/xs_internal.h: The interface
between xen_unified.c and its underlying driver now uses
a custom structure (struct xenUnifiedDriver) instead
of reusing virDriver.
* src/xen_unified.c: virDomainLookup* functions in Xen
now throw VIR_ERR_NO_DOMAIN if the domain does not exist.
* src/xs_internal.c: Fix indentation.
2007-07-06 15:11:22 +00:00
|
|
|
virDomainPtr
|
2006-06-29 22:12:47 +00:00
|
|
|
xenProxyLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
|
2006-06-28 18:19:13 +00:00
|
|
|
{
|
2006-06-30 16:23:16 +00:00
|
|
|
virProxyFullPacket req;
|
|
|
|
const char *name;
|
|
|
|
int ret;
|
|
|
|
virDomainPtr res;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECT(conn)) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
if (uuid == NULL) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2008-04-10 16:54:54 +00:00
|
|
|
return (NULL);
|
2006-06-30 16:23:16 +00:00
|
|
|
}
|
|
|
|
memset(&req, 0, sizeof(virProxyPacket));
|
|
|
|
req.command = VIR_PROXY_LOOKUP_UUID;
|
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
|
|
|
req.len = sizeof(virProxyPacket) + VIR_UUID_BUFLEN;
|
2007-08-14 12:29:40 +00:00
|
|
|
memcpy(&req.extra.str[0], uuid, VIR_UUID_BUFLEN);
|
|
|
|
|
2006-07-03 15:48:49 +00:00
|
|
|
ret = xenProxyCommand(conn, (virProxyPacketPtr) &req, &req, 0);
|
2006-06-30 16:23:16 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
xenProxyClose(conn);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(NULL);
|
2006-06-30 16:23:16 +00:00
|
|
|
}
|
|
|
|
if (req.data.arg == -1) {
|
2008-04-10 16:54:54 +00:00
|
|
|
return(NULL);
|
2006-06-30 16:23:16 +00:00
|
|
|
}
|
|
|
|
name = &req.extra.str[0];
|
|
|
|
res = virGetDomain(conn, name, uuid);
|
2008-04-10 16:54:54 +00:00
|
|
|
if (res) res->id = req.data.arg;
|
2006-06-30 16:23:16 +00:00
|
|
|
return(res);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
|
|
|
|
2006-06-29 22:12:47 +00:00
|
|
|
/**
|
Fri Jul 6 16:08:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
* src/proxy_internal.c, src/proxy_internal.h,
src.xen_internal.c, src/xen_internal.h,
src/xen_unified.c, src/xen_unified.h,
src/xend_internal.c, src/xend_internal.h,
src/xm_internal.c, src/xm_internal.h,
src/xs_internal.c, src/xs_internal.h: The interface
between xen_unified.c and its underlying driver now uses
a custom structure (struct xenUnifiedDriver) instead
of reusing virDriver.
* src/xen_unified.c: virDomainLookup* functions in Xen
now throw VIR_ERR_NO_DOMAIN if the domain does not exist.
* src/xs_internal.c: Fix indentation.
2007-07-06 15:11:22 +00:00
|
|
|
* xenProxyLookupByName:
|
2006-06-29 22:12:47 +00:00
|
|
|
* @conn: A xend instance
|
|
|
|
* @name: The name of the domain
|
|
|
|
*
|
|
|
|
* This method looks up information about a domain based on its name
|
|
|
|
*
|
|
|
|
* Returns a new domain object or NULL in case of failure
|
|
|
|
*/
|
Fri Jul 6 16:08:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
* src/proxy_internal.c, src/proxy_internal.h,
src.xen_internal.c, src/xen_internal.h,
src/xen_unified.c, src/xen_unified.h,
src/xend_internal.c, src/xend_internal.h,
src/xm_internal.c, src/xm_internal.h,
src/xs_internal.c, src/xs_internal.h: The interface
between xen_unified.c and its underlying driver now uses
a custom structure (struct xenUnifiedDriver) instead
of reusing virDriver.
* src/xen_unified.c: virDomainLookup* functions in Xen
now throw VIR_ERR_NO_DOMAIN if the domain does not exist.
* src/xs_internal.c: Fix indentation.
2007-07-06 15:11:22 +00:00
|
|
|
virDomainPtr
|
|
|
|
xenProxyLookupByName(virConnectPtr conn, const char *name)
|
2006-06-29 22:12:47 +00:00
|
|
|
{
|
2006-06-30 16:23:16 +00:00
|
|
|
virProxyFullPacket req;
|
|
|
|
int ret, len;
|
|
|
|
virDomainPtr res;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECT(conn)) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
if (name == NULL) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2008-04-10 16:54:54 +00:00
|
|
|
return (NULL);
|
2006-06-30 16:23:16 +00:00
|
|
|
}
|
|
|
|
len = strlen(name);
|
|
|
|
if (len > 1000) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2008-04-10 16:54:54 +00:00
|
|
|
return (NULL);
|
2006-06-30 16:23:16 +00:00
|
|
|
}
|
|
|
|
memset(&req, 0, sizeof(virProxyPacket));
|
|
|
|
req.command = VIR_PROXY_LOOKUP_NAME;
|
|
|
|
req.len = sizeof(virProxyPacket) + len + 1;
|
|
|
|
strcpy(&req.extra.str[0], name);
|
2006-07-03 15:48:49 +00:00
|
|
|
ret = xenProxyCommand(conn, (virProxyPacketPtr) &req, &req, 0);
|
2006-06-30 16:23:16 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
xenProxyClose(conn);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(NULL);
|
2006-06-30 16:23:16 +00:00
|
|
|
}
|
|
|
|
if (req.data.arg == -1) {
|
2008-04-10 16:54:54 +00:00
|
|
|
return(NULL);
|
2006-06-30 16:23:16 +00:00
|
|
|
}
|
|
|
|
res = virGetDomain(conn, name, (const unsigned char *)&req.extra.str[0]);
|
2008-04-10 16:54:54 +00:00
|
|
|
if (res) res->id = req.data.arg;
|
2006-06-30 16:23:16 +00:00
|
|
|
return(res);
|
2006-06-29 22:12:47 +00:00
|
|
|
}
|
2006-06-29 14:44:37 +00:00
|
|
|
|
2006-06-29 22:12:47 +00:00
|
|
|
/**
|
|
|
|
* xenProxyNodeGetInfo:
|
|
|
|
* @conn: pointer to the Xen Daemon block
|
|
|
|
* @info: pointer to a virNodeInfo structure allocated by the user
|
2008-02-05 19:27:37 +00:00
|
|
|
*
|
2006-06-29 22:12:47 +00:00
|
|
|
* Extract hardware information about the node.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success and -1 in case of failure.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
xenProxyNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) {
|
2006-07-03 11:12:12 +00:00
|
|
|
virProxyPacket req;
|
|
|
|
virProxyFullPacket ans;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECT(conn)) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (info == NULL) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2008-04-10 16:54:54 +00:00
|
|
|
return (-1);
|
2006-07-03 11:12:12 +00:00
|
|
|
}
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.command = VIR_PROXY_NODE_INFO;
|
|
|
|
req.data.arg = 0;
|
|
|
|
req.len = sizeof(req);
|
2006-07-03 15:48:49 +00:00
|
|
|
ret = xenProxyCommand(conn, &req, &ans, 0);
|
2006-07-03 11:12:12 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
xenProxyClose(conn);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-07-03 11:12:12 +00:00
|
|
|
}
|
|
|
|
if (ans.data.arg == -1) {
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-07-03 11:12:12 +00:00
|
|
|
}
|
|
|
|
if (ans.len != sizeof(virProxyPacket) + sizeof(virNodeInfo)) {
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-07-03 11:12:12 +00:00
|
|
|
}
|
|
|
|
memcpy(info, &ans.extra.ninfo, sizeof(virNodeInfo));
|
|
|
|
return(0);
|
2006-06-28 18:19:13 +00:00
|
|
|
}
|
2006-06-29 22:12:47 +00:00
|
|
|
|
2007-04-30 16:58:26 +00:00
|
|
|
/**
|
|
|
|
* xenProxyGetCapabilities:
|
|
|
|
* @conn: pointer to the Xen Daemon block
|
2008-02-05 19:27:37 +00:00
|
|
|
*
|
2007-04-30 16:58:26 +00:00
|
|
|
* Extract capabilities of the hypervisor.
|
|
|
|
*
|
|
|
|
* Returns capabilities in case of success (freed by caller)
|
|
|
|
* and NULL in case of failure.
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
xenProxyGetCapabilities (virConnectPtr conn)
|
|
|
|
{
|
|
|
|
virProxyPacket req;
|
|
|
|
virProxyFullPacket ans;
|
|
|
|
int ret, xmllen;
|
|
|
|
char *xml;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECT(conn)) {
|
|
|
|
virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.command = VIR_PROXY_GET_CAPABILITIES;
|
|
|
|
req.data.arg = 0;
|
|
|
|
req.len = sizeof(req);
|
|
|
|
ret = xenProxyCommand(conn, &req, &ans, 0);
|
|
|
|
if (ret < 0) {
|
|
|
|
xenProxyClose(conn);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (ans.data.arg == -1)
|
|
|
|
return NULL;
|
|
|
|
if (ans.len <= sizeof(virProxyPacket)) {
|
|
|
|
virProxyError(conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
xmllen = ans.len - sizeof (virProxyPacket);
|
2008-06-06 11:09:57 +00:00
|
|
|
if (VIR_ALLOC_N(xml, xmllen+1) < 0) {
|
2007-04-30 16:58:26 +00:00
|
|
|
virProxyError (conn, VIR_ERR_NO_MEMORY, __FUNCTION__);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
memmove (xml, ans.extra.str, xmllen);
|
|
|
|
xml[xmllen] = '\0';
|
|
|
|
|
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
2006-08-09 15:21:16 +00:00
|
|
|
/**
|
|
|
|
* xenProxyDomainDumpXML:
|
|
|
|
* @domain: a domain object
|
|
|
|
* @flags: xml generation flags
|
|
|
|
*
|
|
|
|
* This method generates an XML description of a domain.
|
|
|
|
*
|
2008-02-05 19:27:37 +00:00
|
|
|
* Returns the XML document on success, NULL otherwise.
|
2006-08-09 15:21:16 +00:00
|
|
|
*/
|
2007-10-31 09:39:13 +00:00
|
|
|
char *
|
2006-08-16 17:58:23 +00:00
|
|
|
xenProxyDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
|
2006-08-09 15:21:16 +00:00
|
|
|
{
|
|
|
|
virProxyPacket req;
|
|
|
|
virProxyFullPacket ans;
|
|
|
|
int ret;
|
|
|
|
int xmllen;
|
|
|
|
char *xml;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
|
2008-04-10 16:54:54 +00:00
|
|
|
if (domain == NULL)
|
|
|
|
virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
|
|
|
else
|
|
|
|
virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
2006-08-09 15:21:16 +00:00
|
|
|
return (NULL);
|
|
|
|
}
|
2007-01-22 16:25:27 +00:00
|
|
|
if (domain->id < 0)
|
2006-11-15 21:03:34 +00:00
|
|
|
return (NULL);
|
2006-08-09 15:21:16 +00:00
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.command = VIR_PROXY_DOMAIN_XML;
|
2007-01-22 16:25:27 +00:00
|
|
|
req.data.arg = domain->id;
|
2006-08-09 15:21:16 +00:00
|
|
|
req.len = sizeof(req);
|
|
|
|
ret = xenProxyCommand(domain->conn, &req, &ans, 0);
|
|
|
|
if (ret < 0) {
|
|
|
|
xenProxyClose(domain->conn);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(NULL);
|
2006-08-09 15:21:16 +00:00
|
|
|
}
|
|
|
|
if (ans.len <= sizeof(virProxyPacket)) {
|
|
|
|
virProxyError(domain->conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
|
2008-04-10 16:54:54 +00:00
|
|
|
return (NULL);
|
2006-08-09 15:21:16 +00:00
|
|
|
}
|
|
|
|
xmllen = ans.len - sizeof(virProxyPacket);
|
2008-06-06 11:09:57 +00:00
|
|
|
if (VIR_ALLOC_N(xml, xmllen+1) < 0) {
|
2008-04-10 16:54:54 +00:00
|
|
|
virProxyError(domain->conn, VIR_ERR_NO_MEMORY, __FUNCTION__);
|
2006-11-07 16:28:16 +00:00
|
|
|
return NULL;
|
2006-08-09 15:21:16 +00:00
|
|
|
}
|
|
|
|
memmove(xml, &ans.extra.dinfo, xmllen);
|
|
|
|
xml[xmllen] = '\0';
|
|
|
|
|
|
|
|
return(xml);
|
|
|
|
}
|
2006-11-07 16:28:16 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* xenProxyDomainGetOSType:
|
|
|
|
* @domain: a domain object
|
|
|
|
*
|
|
|
|
* Get the type of domain operation system.
|
|
|
|
*
|
|
|
|
* Returns the new string or NULL in case of error, the string must be
|
|
|
|
* freed by the caller.
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
xenProxyDomainGetOSType(virDomainPtr domain)
|
|
|
|
{
|
|
|
|
virProxyPacket req;
|
|
|
|
virProxyFullPacket ans;
|
|
|
|
int ret;
|
|
|
|
int oslen;
|
|
|
|
char *ostype;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
|
2008-04-10 16:54:54 +00:00
|
|
|
if (domain == NULL)
|
|
|
|
virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
|
|
|
else
|
|
|
|
virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
2006-11-07 16:28:16 +00:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.command = VIR_PROXY_DOMAIN_OSTYPE;
|
2007-01-22 16:25:27 +00:00
|
|
|
req.data.arg = domain->id;
|
2006-11-07 16:28:16 +00:00
|
|
|
req.len = sizeof(req);
|
|
|
|
ret = xenProxyCommand(domain->conn, &req, &ans, 0);
|
|
|
|
if (ret < 0) {
|
|
|
|
xenProxyClose(domain->conn);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(NULL);
|
2006-11-07 16:28:16 +00:00
|
|
|
}
|
2006-11-08 13:53:29 +00:00
|
|
|
if ((ans.len == sizeof(virProxyPacket)) && (ans.data.arg < 0)) {
|
2008-04-10 16:54:54 +00:00
|
|
|
return(NULL);
|
2006-11-08 13:53:29 +00:00
|
|
|
}
|
|
|
|
|
2006-11-07 16:28:16 +00:00
|
|
|
if (ans.len <= sizeof(virProxyPacket)) {
|
|
|
|
virProxyError(domain->conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
|
2008-04-10 16:54:54 +00:00
|
|
|
return (NULL);
|
2006-11-07 16:28:16 +00:00
|
|
|
}
|
|
|
|
oslen = ans.len - sizeof(virProxyPacket);
|
2008-06-06 11:09:57 +00:00
|
|
|
if (VIR_ALLOC_N(ostype, oslen+1) < 0) {
|
2008-04-10 16:54:54 +00:00
|
|
|
virProxyError(domain->conn, VIR_ERR_NO_MEMORY, __FUNCTION__);
|
2006-11-07 16:28:16 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
memmove(ostype, &ans.extra.dinfo, oslen);
|
|
|
|
ostype[oslen] = '\0';
|
|
|
|
|
|
|
|
return(ostype);
|
|
|
|
}
|
2007-03-15 17:24:56 +00:00
|
|
|
|
2008-08-20 20:48:35 +00:00
|
|
|
|