2006-03-23 15:42:10 +00:00
|
|
|
/*
|
|
|
|
* xs_internal.c: access to Xen Store
|
|
|
|
*
|
|
|
|
* Copyright (C) 2006 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* 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-03-23 15:42:10 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
2008-02-05 19:27:37 +00:00
|
|
|
#include <xen/dom0_ops.h>
|
2006-03-23 15:42:10 +00:00
|
|
|
#include <xen/version.h>
|
2007-11-20 18:57:41 +00:00
|
|
|
#include <xen/xen.h>
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
#include <xs.h>
|
|
|
|
|
2008-11-04 22:30:33 +00:00
|
|
|
#include "virterror_internal.h"
|
2008-11-04 23:22:06 +00:00
|
|
|
#include "datatypes.h"
|
2006-03-23 15:42:10 +00:00
|
|
|
#include "driver.h"
|
2008-11-25 10:44:52 +00:00
|
|
|
#include "memory.h"
|
|
|
|
#include "event.h"
|
|
|
|
#include "logging.h"
|
|
|
|
#include "uuid.h"
|
2007-04-04 14:19:49 +00:00
|
|
|
#include "xen_unified.h"
|
2006-03-23 15:42:10 +00:00
|
|
|
#include "xs_internal.h"
|
2006-06-16 15:28:26 +00:00
|
|
|
#include "xen_internal.h" /* for xenHypervisorCheckID */
|
2006-03-23 15:42:10 +00:00
|
|
|
|
2007-09-29 18:37:47 +00:00
|
|
|
#ifdef __linux__
|
2006-03-23 15:42:10 +00:00
|
|
|
#define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd"
|
2008-10-10 09:32:27 +00:00
|
|
|
#elif defined(__sun__)
|
2007-09-29 18:37:47 +00:00
|
|
|
#define XEN_HYPERVISOR_SOCKET "/dev/xen/privcmd"
|
|
|
|
#else
|
|
|
|
#error "unsupported platform"
|
|
|
|
#endif
|
2006-03-23 15:42:10 +00:00
|
|
|
|
2006-08-09 15:21:16 +00:00
|
|
|
#ifndef PROXY
|
2008-11-25 10:44:52 +00:00
|
|
|
/* A list of active domain name/uuids */
|
|
|
|
static xenUnifiedDomainInfoListPtr activeDomainList = NULL;
|
|
|
|
|
2006-11-07 16:28:16 +00:00
|
|
|
static char *xenStoreDomainGetOSType(virDomainPtr domain);
|
|
|
|
|
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 xenStoreDriver = {
|
2006-03-23 15:42:10 +00:00
|
|
|
xenStoreOpen, /* open */
|
|
|
|
xenStoreClose, /* close */
|
|
|
|
NULL, /* version */
|
2007-06-26 11:42:46 +00:00
|
|
|
NULL, /* hostname */
|
|
|
|
NULL, /* URI */
|
2006-03-29 12:46:03 +00:00
|
|
|
NULL, /* nodeGetInfo */
|
2007-03-15 17:24:56 +00:00
|
|
|
NULL, /* getCapabilities */
|
2006-03-23 15:42:10 +00:00
|
|
|
xenStoreListDomains, /* listDomains */
|
|
|
|
NULL, /* numOfDomains */
|
2008-10-10 09:32:27 +00:00
|
|
|
NULL, /* domainCreateXML */
|
2006-03-23 15:42:10 +00:00
|
|
|
NULL, /* domainSuspend */
|
|
|
|
NULL, /* domainResume */
|
2006-04-03 13:46:43 +00:00
|
|
|
xenStoreDomainShutdown, /* domainShutdown */
|
|
|
|
xenStoreDomainReboot, /* domainReboot */
|
2006-03-23 15:42:10 +00:00
|
|
|
NULL, /* domainDestroy */
|
2006-11-07 16:28:16 +00:00
|
|
|
xenStoreDomainGetOSType, /* domainGetOSType */
|
2006-03-23 15:42:10 +00:00
|
|
|
xenStoreDomainGetMaxMemory, /* domainGetMaxMemory */
|
2006-04-13 17:18:49 +00:00
|
|
|
NULL, /* domainSetMaxMemory */
|
|
|
|
xenStoreDomainSetMemory, /* domainSetMemory */
|
2006-03-23 15:42:10 +00:00
|
|
|
xenStoreGetDomainInfo, /* 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-03-23 15:42:10 +00:00
|
|
|
};
|
|
|
|
|
2006-08-09 15:21:16 +00:00
|
|
|
#endif /* ! PROXY */
|
2006-03-27 15:24:36 +00:00
|
|
|
|
2008-10-09 15:38:31 +00:00
|
|
|
#define virXenStoreError(conn, code, fmt...) \
|
2008-11-04 22:30:33 +00:00
|
|
|
virReportErrorHelper(NULL, VIR_FROM_XENSTORE, code, __FILE__, \
|
2008-10-09 15:38:31 +00:00
|
|
|
__FUNCTION__, __LINE__, fmt)
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* *
|
|
|
|
* Helper internal APIs *
|
|
|
|
* *
|
|
|
|
************************************************************************/
|
2006-08-09 15:21:16 +00:00
|
|
|
#ifndef PROXY
|
2006-03-23 15:42:10 +00:00
|
|
|
/**
|
|
|
|
* virConnectDoStoreList:
|
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
* @path: the absolute path of the directory in the store to list
|
|
|
|
* @nb: OUT pointer to the number of items found
|
|
|
|
*
|
|
|
|
* Internal API querying the Xenstore for a list
|
|
|
|
*
|
|
|
|
* Returns a string which must be freed by the caller or NULL in case of error
|
|
|
|
*/
|
|
|
|
static char **
|
|
|
|
virConnectDoStoreList(virConnectPtr conn, const char *path,
|
|
|
|
unsigned int *nb)
|
|
|
|
{
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
|
|
|
|
|
|
|
if (conn == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if (priv->xshandle == NULL || path == NULL || nb == NULL)
|
2006-03-23 15:42:10 +00:00
|
|
|
return (NULL);
|
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
return xs_directory (priv->xshandle, 0, path, nb);
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
2006-08-09 15:21:16 +00:00
|
|
|
#endif /* ! PROXY */
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainDoStoreQuery:
|
2006-08-09 15:21:16 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
* @domid: id of the domain
|
2006-03-23 15:42:10 +00:00
|
|
|
* @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 *
|
2006-08-09 15:21:16 +00:00
|
|
|
virDomainDoStoreQuery(virConnectPtr conn, int domid, const char *path)
|
2006-03-23 15:42:10 +00:00
|
|
|
{
|
|
|
|
char s[256];
|
|
|
|
unsigned int len = 0;
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
|
|
|
|
|
|
|
if (!conn)
|
|
|
|
return NULL;
|
2006-03-23 15:42:10 +00:00
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if (priv->xshandle == NULL)
|
2006-03-23 15:42:10 +00:00
|
|
|
return (NULL);
|
|
|
|
|
2006-08-09 15:21:16 +00:00
|
|
|
snprintf(s, 255, "/local/domain/%d/%s", domid, path);
|
2006-03-23 15:42:10 +00:00
|
|
|
s[255] = 0;
|
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
return xs_read(priv->xshandle, 0, &s[0], &len);
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-09 15:21:16 +00:00
|
|
|
#ifndef PROXY
|
2006-03-23 15:42:10 +00:00
|
|
|
/**
|
|
|
|
* virDomainDoStoreWrite:
|
|
|
|
* @domain: a domain object
|
|
|
|
* @path: the relative path of the data in the store to retrieve
|
|
|
|
*
|
|
|
|
* Internal API setting up a string value in the Xenstore
|
|
|
|
* Requires write access to the XenStore
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of failure
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virDomainDoStoreWrite(virDomainPtr domain, const char *path,
|
|
|
|
const char *value)
|
|
|
|
{
|
|
|
|
char s[256];
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
2006-03-23 15:42:10 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!VIR_IS_CONNECTED_DOMAIN(domain))
|
|
|
|
return (-1);
|
2007-04-04 14:19:49 +00:00
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
|
|
|
|
if (priv->xshandle == NULL)
|
2006-03-23 15:42:10 +00:00
|
|
|
return (-1);
|
|
|
|
if (domain->conn->flags & VIR_CONNECT_RO)
|
|
|
|
return (-1);
|
|
|
|
|
2007-01-22 16:25:27 +00:00
|
|
|
snprintf(s, 255, "/local/domain/%d/%s", domain->id, path);
|
2006-03-23 15:42:10 +00:00
|
|
|
s[255] = 0;
|
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
if (xs_write(priv->xshandle, 0, &s[0], value, strlen(value)))
|
2006-03-23 15:42:10 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainGetVM:
|
|
|
|
* @domain: a domain object
|
|
|
|
*
|
|
|
|
* Internal API extracting a xenstore vm path.
|
|
|
|
*
|
|
|
|
* Returns the new string or NULL in case of error
|
|
|
|
*/
|
2008-01-21 16:29:10 +00:00
|
|
|
static char *
|
2006-03-23 15:42:10 +00:00
|
|
|
virDomainGetVM(virDomainPtr domain)
|
|
|
|
{
|
|
|
|
char *vm;
|
|
|
|
char query[200];
|
|
|
|
unsigned int len;
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
if (!VIR_IS_CONNECTED_DOMAIN(domain))
|
|
|
|
return (NULL);
|
2007-04-04 14:19:49 +00:00
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
|
|
|
|
if (priv->xshandle == NULL)
|
2006-03-23 15:42:10 +00:00
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
snprintf(query, 199, "/local/domain/%d/vm", virDomainGetID(domain));
|
|
|
|
query[199] = 0;
|
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
vm = xs_read(priv->xshandle, 0, &query[0], &len);
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
return (vm);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainGetVMInfo:
|
|
|
|
* @domain: a domain object
|
|
|
|
* @vm: the xenstore vm path
|
|
|
|
* @name: the value's path
|
|
|
|
*
|
2008-02-05 19:27:37 +00:00
|
|
|
* Internal API extracting one information the device used
|
2006-03-23 15:42:10 +00:00
|
|
|
* by the domain from xensttore
|
|
|
|
*
|
|
|
|
* Returns the new string or NULL in case of error
|
|
|
|
*/
|
2008-01-21 16:29:10 +00:00
|
|
|
static char *
|
2006-03-23 15:42:10 +00:00
|
|
|
virDomainGetVMInfo(virDomainPtr domain, const char *vm, const char *name)
|
|
|
|
{
|
|
|
|
char s[256];
|
|
|
|
char *ret = NULL;
|
|
|
|
unsigned int len = 0;
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
if (!VIR_IS_CONNECTED_DOMAIN(domain))
|
|
|
|
return (NULL);
|
2007-04-04 14:19:49 +00:00
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
|
|
|
|
if (priv->xshandle == NULL)
|
2006-03-23 15:42:10 +00:00
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
snprintf(s, 255, "%s/%s", vm, name);
|
|
|
|
s[255] = 0;
|
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
ret = xs_read(priv->xshandle, 0, &s[0], &len);
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2006-08-09 15:21:16 +00:00
|
|
|
#endif /* ! PROXY */
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* *
|
|
|
|
* Canonical internal APIs *
|
|
|
|
* *
|
|
|
|
************************************************************************/
|
|
|
|
/**
|
|
|
|
* xenStoreOpen:
|
|
|
|
* @conn: pointer to the connection block
|
|
|
|
* @name: URL for the target, NULL for local
|
|
|
|
* @flags: combination of virDrvOpenFlag(s)
|
|
|
|
*
|
|
|
|
* Connects to the Xen hypervisor.
|
|
|
|
*
|
|
|
|
* Returns 0 or -1 in case of error.
|
|
|
|
*/
|
2008-12-17 21:26:16 +00:00
|
|
|
virDrvOpenStatus
|
2007-04-04 14:19:49 +00:00
|
|
|
xenStoreOpen(virConnectPtr conn,
|
2007-12-05 18:28:05 +00:00
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
2007-04-30 17:30:11 +00:00
|
|
|
int flags ATTRIBUTE_UNUSED)
|
2006-03-23 15:42:10 +00:00
|
|
|
{
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
|
2006-03-23 15:42:10 +00:00
|
|
|
|
2006-08-09 15:21:16 +00:00
|
|
|
#ifdef PROXY
|
2007-04-04 14:19:49 +00:00
|
|
|
priv->xshandle = xs_daemon_open_readonly();
|
2006-08-09 15:21:16 +00:00
|
|
|
#else
|
2007-12-05 18:28:05 +00:00
|
|
|
if (flags & VIR_CONNECT_RO)
|
2008-04-10 16:54:54 +00:00
|
|
|
priv->xshandle = xs_daemon_open_readonly();
|
2006-03-23 15:42:10 +00:00
|
|
|
else
|
2008-04-10 16:54:54 +00:00
|
|
|
priv->xshandle = xs_daemon_open();
|
2006-08-09 15:21:16 +00:00
|
|
|
#endif /* ! PROXY */
|
2006-03-23 15:42:10 +00:00
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
if (priv->xshandle == NULL) {
|
2008-04-10 16:54:54 +00:00
|
|
|
/*
|
2007-11-27 14:39:42 +00:00
|
|
|
* not being able to connect via the socket as a normal user
|
|
|
|
* is rather normal, this should fallback to the proxy (or
|
|
|
|
* remote) mechanism.
|
2008-04-10 16:54:54 +00:00
|
|
|
*/
|
2007-11-27 14:39:42 +00:00
|
|
|
if (getuid() == 0) {
|
2008-04-10 16:54:54 +00:00
|
|
|
virXenStoreError(NULL, VIR_ERR_NO_XEN,
|
avoid many format string warnings
Building with --disable-nls exposed many new warnings like these:
virsh.c:4952: warning: format not a string literal and no format ...
util.c:163: warning: format not a string literal and no format arguments
All but one of the following changes add a "%s" argument before
the offending _(...) argument.
This was the only manual change:
* src/lxc_driver.c (lxcVersion): Use %s and strerror(errno)
rather than %m, to avoid a warning from gcc -Wformat-security.
Add "%s" before each warned about format-string-with-no-%-directive:
* src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML)
(virDomainDefParseString, virDomainDefParseFile):
* src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain)
(__virGetNetwork, virReleaseNetwork, __virGetStoragePool)
(virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol):
* src/lxc_container.c (lxcContainerChild):
* src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine)
(lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML)
(lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart)
(lxcVersion, lxcGetSchedulerParameters):
* src/network_conf.c (virNetworkDefParseString)
(virNetworkDefParseFile):
* src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains):
* src/openvz_driver.c (openvzDomainDefineCmd)
(openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown)
(openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine)
(openvzDomainSetAutostart, openvzDomainGetAutostart)
(openvzDomainSetVcpus):
* src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek):
* src/remote_internal.c (remoteDomainBlockPeek)
(remoteDomainMemoryPeek, remoteAuthPolkit):
* src/sexpr.c (sexpr_new, _string2sexpr):
* src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol):
* src/storage_backend_fs.c
(virStorageBackendFileSystemNetFindPoolSources):
* src/storage_backend_logical.c (virStorageBackendLogicalFindLVs)
(virStorageBackendLogicalFindPoolSources):
* src/test.c (testOpenDefault, testOpenFromFile, testOpen)
(testGetDomainInfo, testDomainRestore)
(testNodeGetCellsFreeMemory):
* src/util.c (virExec):
* src/virsh.c (cmdAttachDevice, cmdDetachDevice)
(cmdAttachInterface, cmdDetachInterface, cmdAttachDisk)
(cmdDetachDisk, cmdEdit):
* src/xend_internal.c (do_connect, wr_sync, xend_op_ext)
(urlencode, xenDaemonDomainCreateXML)
(xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID)
(xenDaemonParseSxprOS, xend_parse_sexp_desc_char)
(xenDaemonParseSxprChar, xenDaemonParseSxprDisks)
(xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain)
(xenDaemonDomainFetch, xenDaemonDomainGetAutostart)
(xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform)
(xenDaemonDomainDefineXML, xenDaemonGetSchedulerType)
(xenDaemonGetSchedulerParameters)
(xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek)
(xenDaemonFormatSxprChr, virDomainXMLDevID):
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu)
(xenXMDomainCreate, xenXMDomainDefineXML)
(xenXMDomainAttachDevice, xenXMDomainDetachDevice):
* src/xml.c (virXPathString, virXPathNumber, virXPathLong)
(virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet):
* src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
|
|
|
"%s", _("failed to connect to Xen Store"));
|
2008-04-10 16:54:54 +00:00
|
|
|
}
|
2006-03-23 15:42:10 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2008-11-25 10:44:52 +00:00
|
|
|
|
|
|
|
#ifndef PROXY
|
|
|
|
/* Init activeDomainList */
|
|
|
|
if ( VIR_ALLOC(activeDomainList) < 0) {
|
|
|
|
virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("failed to allocate activeDomainList"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Init watch list before filling in domInfoList,
|
|
|
|
so we can know if it is the first time through
|
|
|
|
when the callback fires */
|
|
|
|
if ( VIR_ALLOC(priv->xsWatchList) < 0 ) {
|
|
|
|
virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("failed to allocate xsWatchList"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This will get called once at start */
|
|
|
|
if ( xenStoreAddWatch(conn, "@releaseDomain",
|
|
|
|
"releaseDomain", xenStoreDomainReleased, priv) < 0 )
|
|
|
|
{
|
|
|
|
virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("adding watch @releaseDomain"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The initial call of this will fill domInfoList */
|
|
|
|
if( xenStoreAddWatch(conn, "@introduceDomain",
|
|
|
|
"introduceDomain", xenStoreDomainIntroduced, priv) < 0 )
|
|
|
|
{
|
|
|
|
virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("adding watch @introduceDomain"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add an event handle */
|
|
|
|
if ((priv->xsWatch = virEventAddHandle(xs_fileno(priv->xshandle),
|
|
|
|
VIR_EVENT_HANDLE_READABLE,
|
|
|
|
xenStoreWatchEvent,
|
|
|
|
conn,
|
|
|
|
NULL)) < 0)
|
|
|
|
DEBUG0("Failed to add event handle, disabling events\n");
|
|
|
|
|
|
|
|
#endif //PROXY
|
|
|
|
return 0;
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xenStoreClose:
|
|
|
|
* @conn: pointer to the connection block
|
|
|
|
*
|
|
|
|
* Close the connection to the Xen hypervisor.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
xenStoreClose(virConnectPtr conn)
|
|
|
|
{
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
|
|
|
|
2006-03-23 15:42:10 +00:00
|
|
|
if (conn == NULL) {
|
|
|
|
virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2007-04-04 14:19:49 +00:00
|
|
|
return(-1);
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
2008-11-25 10:44:52 +00:00
|
|
|
|
|
|
|
if (xenStoreRemoveWatch(conn, "@introduceDomain", "introduceDomain") < 0) {
|
|
|
|
DEBUG0("Warning, could not remove @introduceDomain watch");
|
|
|
|
/* not fatal */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xenStoreRemoveWatch(conn, "@releaseDomain", "releaseDomain") < 0) {
|
|
|
|
DEBUG0("Warning, could not remove @releaseDomain watch");
|
|
|
|
/* not fatal */
|
|
|
|
}
|
|
|
|
|
|
|
|
xenStoreWatchListFree(priv->xsWatchList);
|
|
|
|
#ifndef PROXY
|
|
|
|
xenUnifiedDomainInfoListFree(activeDomainList);
|
|
|
|
#endif
|
2007-04-04 14:19:49 +00:00
|
|
|
if (priv->xshandle == NULL)
|
|
|
|
return(-1);
|
|
|
|
|
2008-11-25 10:44:52 +00:00
|
|
|
if (priv->xsWatch != -1)
|
|
|
|
virEventRemoveHandle(priv->xsWatch);
|
2007-04-04 14:19:49 +00:00
|
|
|
xs_daemon_close(priv->xshandle);
|
2008-11-25 10:44:52 +00:00
|
|
|
priv->xshandle = NULL;
|
|
|
|
|
2006-03-23 15:42:10 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2006-08-09 15:21:16 +00:00
|
|
|
#ifndef PROXY
|
2006-03-23 15:42:10 +00:00
|
|
|
/**
|
|
|
|
* xenStoreGetDomainInfo:
|
|
|
|
* @domain: pointer to the domain block
|
2006-07-19 22:24:37 +00:00
|
|
|
* @info: the place where information should be stored
|
2006-03-23 15:42:10 +00:00
|
|
|
*
|
2006-07-19 22:24:37 +00:00
|
|
|
* Do an hypervisor call to get the related set of domain information.
|
2006-03-23 15:42:10 +00:00
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
xenStoreGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info)
|
|
|
|
{
|
|
|
|
char *tmp, **tmp2;
|
|
|
|
unsigned int nb_vcpus;
|
|
|
|
char request[200];
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
2006-03-23 15:42:10 +00:00
|
|
|
|
2006-08-09 15:21:16 +00:00
|
|
|
if (!VIR_IS_CONNECTED_DOMAIN(domain))
|
|
|
|
return (-1);
|
|
|
|
|
2006-03-23 15:42:10 +00:00
|
|
|
if ((domain == NULL) || (domain->conn == NULL) || (info == NULL)) {
|
|
|
|
virXenStoreError(domain ? domain->conn : NULL, VIR_ERR_INVALID_ARG,
|
2008-04-10 16:54:54 +00:00
|
|
|
__FUNCTION__);
|
|
|
|
return(-1);
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
2007-04-04 14:19:49 +00:00
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
|
|
|
|
if (priv->xshandle == NULL)
|
2006-03-23 15:42:10 +00:00
|
|
|
return(-1);
|
2007-04-04 14:19:49 +00:00
|
|
|
|
2007-01-22 16:25:27 +00:00
|
|
|
if (domain->id == -1)
|
2006-11-15 21:03:34 +00:00
|
|
|
return(-1);
|
2006-03-23 15:42:10 +00:00
|
|
|
|
2007-01-22 16:25:27 +00:00
|
|
|
tmp = virDomainDoStoreQuery(domain->conn, domain->id, "running");
|
2006-03-23 15:42:10 +00:00
|
|
|
if (tmp != NULL) {
|
|
|
|
if (tmp[0] == '1')
|
|
|
|
info->state = VIR_DOMAIN_RUNNING;
|
|
|
|
free(tmp);
|
|
|
|
} else {
|
2008-07-08 17:49:26 +00:00
|
|
|
info->state = VIR_DOMAIN_NOSTATE;
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
2007-01-22 16:25:27 +00:00
|
|
|
tmp = virDomainDoStoreQuery(domain->conn, domain->id, "memory/target");
|
2006-03-23 15:42:10 +00:00
|
|
|
if (tmp != NULL) {
|
|
|
|
info->memory = atol(tmp);
|
|
|
|
info->maxMem = atol(tmp);
|
|
|
|
free(tmp);
|
|
|
|
} else {
|
|
|
|
info->memory = 0;
|
|
|
|
info->maxMem = 0;
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
/* doesn't seems to work */
|
2007-01-22 16:25:27 +00:00
|
|
|
tmp = virDomainDoStoreQuery(domain->conn, domain->id, "cpu_time");
|
2006-03-23 15:42:10 +00:00
|
|
|
if (tmp != NULL) {
|
|
|
|
info->cpuTime = atol(tmp);
|
|
|
|
free(tmp);
|
|
|
|
} else {
|
|
|
|
info->cpuTime = 0;
|
|
|
|
}
|
|
|
|
#endif
|
2007-01-22 16:25:27 +00:00
|
|
|
snprintf(request, 199, "/local/domain/%d/cpu", domain->id);
|
2006-03-23 15:42:10 +00:00
|
|
|
request[199] = 0;
|
|
|
|
tmp2 = virConnectDoStoreList(domain->conn, request, &nb_vcpus);
|
|
|
|
if (tmp2 != NULL) {
|
|
|
|
info->nrVirtCpu = nb_vcpus;
|
|
|
|
free(tmp2);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2006-04-13 17:18:49 +00:00
|
|
|
* xenStoreDomainSetMemory:
|
2006-03-23 15:42:10 +00:00
|
|
|
* @domain: pointer to the domain block
|
|
|
|
* @memory: the max memory size in kilobytes.
|
|
|
|
*
|
|
|
|
* Change the maximum amount of memory allowed in the xen store
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
2006-04-13 17:18:49 +00:00
|
|
|
xenStoreDomainSetMemory(virDomainPtr domain, unsigned long memory)
|
2006-03-23 15:42:10 +00:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
char value[20];
|
|
|
|
|
2007-03-08 14:17:32 +00:00
|
|
|
if ((domain == NULL) || (domain->conn == NULL) ||
|
|
|
|
(memory < 1024 * MIN_XEN_GUEST_SIZE)) {
|
2006-03-23 15:42:10 +00:00
|
|
|
virXenStoreError(domain ? domain->conn : NULL, VIR_ERR_INVALID_ARG,
|
2008-04-10 16:54:54 +00:00
|
|
|
__FUNCTION__);
|
|
|
|
return(-1);
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
2007-01-22 16:25:27 +00:00
|
|
|
if (domain->id == -1)
|
2006-11-15 21:03:34 +00:00
|
|
|
return(-1);
|
2007-03-08 14:17:32 +00:00
|
|
|
if ((domain->id == 0) && (memory < (2 * MIN_XEN_GUEST_SIZE * 1024)))
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-03-23 15:42:10 +00:00
|
|
|
snprintf(value, 19, "%lu", memory);
|
|
|
|
value[19] = 0;
|
|
|
|
ret = virDomainDoStoreWrite(domain, "memory/target", &value[0]);
|
|
|
|
if (ret < 0)
|
|
|
|
return (-1);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xenStoreDomainGetMaxMemory:
|
|
|
|
* @domain: pointer to the domain block
|
|
|
|
*
|
|
|
|
* Ask the xenstore for the maximum memory allowed for a domain
|
|
|
|
*
|
|
|
|
* Returns the memory size in kilobytes or 0 in case of error.
|
|
|
|
*/
|
|
|
|
unsigned long
|
|
|
|
xenStoreDomainGetMaxMemory(virDomainPtr domain)
|
|
|
|
{
|
|
|
|
char *tmp;
|
|
|
|
unsigned long ret = 0;
|
|
|
|
|
2006-08-09 15:21:16 +00:00
|
|
|
if (!VIR_IS_CONNECTED_DOMAIN(domain))
|
|
|
|
return (ret);
|
2007-01-22 16:25:27 +00:00
|
|
|
if (domain->id == -1)
|
2006-11-15 21:03:34 +00:00
|
|
|
return(-1);
|
2006-08-09 15:21:16 +00:00
|
|
|
|
2007-01-22 16:25:27 +00:00
|
|
|
tmp = virDomainDoStoreQuery(domain->conn, domain->id, "memory/target");
|
2006-03-23 15:42:10 +00:00
|
|
|
if (tmp != NULL) {
|
2008-04-10 16:54:54 +00:00
|
|
|
ret = (unsigned long) atol(tmp);
|
|
|
|
free(tmp);
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xenStoreNumOfDomains:
|
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
*
|
|
|
|
* Provides the number of active domains.
|
|
|
|
*
|
|
|
|
* Returns the number of domain found or -1 in case of error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
xenStoreNumOfDomains(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
unsigned int num;
|
|
|
|
char **idlist;
|
|
|
|
int ret = -1;
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
2006-03-23 15:42:10 +00:00
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
if (conn == NULL) {
|
2006-03-23 15:42:10 +00:00
|
|
|
virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2007-04-04 14:19:49 +00:00
|
|
|
return -1;
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
2007-04-04 14:19:49 +00:00
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if (priv->xshandle == NULL) {
|
|
|
|
virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
idlist = xs_directory(priv->xshandle, 0, "/local/domain", &num);
|
2006-03-23 15:42:10 +00:00
|
|
|
if (idlist) {
|
|
|
|
free(idlist);
|
2008-04-10 16:54:54 +00:00
|
|
|
ret = num;
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xenStoreListDomains:
|
|
|
|
* @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
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
xenStoreListDomains(virConnectPtr conn, int *ids, int maxids)
|
|
|
|
{
|
|
|
|
char **idlist = NULL, *endptr;
|
|
|
|
unsigned int num, i;
|
|
|
|
int ret;
|
|
|
|
long id;
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
if ((conn == NULL) || (ids == NULL)) {
|
|
|
|
virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
2007-04-04 14:19:49 +00:00
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if (priv->xshandle == NULL)
|
2006-03-23 15:42:10 +00:00
|
|
|
return(-1);
|
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
idlist = xs_directory (priv->xshandle, 0, "/local/domain", &num);
|
2006-03-23 15:42:10 +00:00
|
|
|
if (idlist == NULL)
|
2008-04-10 16:54:54 +00:00
|
|
|
return(-1);
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
for (ret = 0, i = 0; (i < num) && (ret < maxids); i++) {
|
2008-04-10 16:54:54 +00:00
|
|
|
id = strtol(idlist[i], &endptr, 10);
|
|
|
|
if ((endptr == idlist[i]) || (*endptr != 0)) {
|
|
|
|
ret = -1;
|
|
|
|
break;
|
|
|
|
}
|
2006-09-02 21:23:14 +00:00
|
|
|
#if 0
|
2008-04-10 16:54:54 +00:00
|
|
|
if (virConnectCheckStoreID(conn, (int) id) < 0)
|
|
|
|
continue;
|
2006-09-02 21:23:14 +00:00
|
|
|
#endif
|
2008-04-10 16:54:54 +00:00
|
|
|
ids[ret++] = (int) id;
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
2007-08-21 11:53:52 +00:00
|
|
|
free(idlist);
|
2006-03-23 15:42:10 +00:00
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
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
|
|
|
* xenStoreLookupByName:
|
2006-03-23 15:42:10 +00:00
|
|
|
* @conn: A xend instance
|
|
|
|
* @name: The name of the domain
|
|
|
|
*
|
|
|
|
* Try to lookup a domain on the Xen Store based on its name.
|
|
|
|
*
|
|
|
|
* Returns a new domain object or NULL in case of failure
|
|
|
|
*/
|
|
|
|
virDomainPtr
|
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
|
|
|
xenStoreLookupByName(virConnectPtr conn, const char *name)
|
2006-03-23 15:42:10 +00:00
|
|
|
{
|
|
|
|
virDomainPtr ret = NULL;
|
|
|
|
unsigned int num, i, len;
|
|
|
|
long id = -1;
|
|
|
|
char **idlist = NULL, *endptr;
|
2007-08-21 11:53:52 +00:00
|
|
|
char prop[200], *tmp;
|
2006-03-23 15:42:10 +00:00
|
|
|
int found = 0;
|
|
|
|
struct xend_domain *xenddomain = NULL;
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
if ((conn == NULL) || (name == NULL)) {
|
|
|
|
virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(NULL);
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
2007-04-04 14:19:49 +00:00
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if (priv->xshandle == NULL)
|
2006-03-23 15:42:10 +00:00
|
|
|
return(NULL);
|
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
idlist = xs_directory(priv->xshandle, 0, "/local/domain", &num);
|
2006-03-23 15:42:10 +00:00
|
|
|
if (idlist == NULL)
|
2008-04-10 16:54:54 +00:00
|
|
|
goto done;
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
for (i = 0; i < num; i++) {
|
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
|
|
|
id = strtol(idlist[i], &endptr, 10);
|
|
|
|
if ((endptr == idlist[i]) || (*endptr != 0)) {
|
|
|
|
goto done;
|
|
|
|
}
|
2006-09-02 21:23:14 +00:00
|
|
|
#if 0
|
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
|
|
|
if (virConnectCheckStoreID(conn, (int) id) < 0)
|
|
|
|
continue;
|
2006-09-02 21:23:14 +00:00
|
|
|
#endif
|
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
|
|
|
snprintf(prop, 199, "/local/domain/%s/name", idlist[i]);
|
|
|
|
prop[199] = 0;
|
|
|
|
tmp = xs_read(priv->xshandle, 0, prop, &len);
|
|
|
|
if (tmp != NULL) {
|
|
|
|
found = STREQ (name, tmp);
|
|
|
|
free(tmp);
|
|
|
|
if (found)
|
|
|
|
break;
|
|
|
|
}
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
|
|
|
if (!found)
|
2007-08-21 11:53:52 +00:00
|
|
|
goto done;
|
2006-03-23 15:42:10 +00:00
|
|
|
|
2006-04-09 13:11:22 +00:00
|
|
|
ret = virGetDomain(conn, name, NULL);
|
2007-08-21 11:53:52 +00:00
|
|
|
if (ret == NULL)
|
2007-07-06 15:02:09 +00:00
|
|
|
goto done;
|
2007-08-21 11:53:52 +00:00
|
|
|
|
2007-01-22 16:25:27 +00:00
|
|
|
ret->id = id;
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
done:
|
2008-04-10 16:54:54 +00:00
|
|
|
free(xenddomain);
|
|
|
|
free(idlist);
|
2006-03-23 15:42:10 +00:00
|
|
|
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xenStoreDomainShutdown:
|
|
|
|
* @domain: pointer to the Domain block
|
|
|
|
*
|
|
|
|
* Shutdown the domain, the OS is requested to properly shutdown
|
|
|
|
* and the domain may ignore it. It will return immediately
|
|
|
|
* after queuing the request.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
xenStoreDomainShutdown(virDomainPtr domain)
|
|
|
|
{
|
|
|
|
if ((domain == NULL) || (domain->conn == NULL)) {
|
|
|
|
virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
|
2008-04-10 16:54:54 +00:00
|
|
|
__FUNCTION__);
|
2006-03-23 15:42:10 +00:00
|
|
|
return(-1);
|
|
|
|
}
|
2007-02-22 16:49:12 +00:00
|
|
|
if (domain->id == -1 || domain->id == 0)
|
2006-11-15 21:03:34 +00:00
|
|
|
return(-1);
|
2006-03-23 15:42:10 +00:00
|
|
|
/*
|
2008-02-05 19:27:37 +00:00
|
|
|
* this is very hackish, the domU kernel probes for a special
|
2006-03-23 15:42:10 +00:00
|
|
|
* node in the xenstore and launch the shutdown command if found.
|
|
|
|
*/
|
2008-09-04 09:07:42 +00:00
|
|
|
return(virDomainDoStoreWrite(domain, "control/shutdown", "poweroff"));
|
2006-03-23 15:42:10 +00:00
|
|
|
}
|
|
|
|
|
2006-04-03 13:46:43 +00:00
|
|
|
/**
|
|
|
|
* xenStoreDomainReboot:
|
|
|
|
* @domain: pointer to the Domain block
|
|
|
|
* @flags: extra flags for the reboot operation, not used yet
|
|
|
|
*
|
|
|
|
* Reboot the domain, the OS is requested to properly shutdown
|
|
|
|
* and reboot but the domain may ignore it. It will return immediately
|
|
|
|
* after queuing the request.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
xenStoreDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
if ((domain == NULL) || (domain->conn == NULL)) {
|
|
|
|
virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
|
2008-04-10 16:54:54 +00:00
|
|
|
__FUNCTION__);
|
2006-04-03 13:46:43 +00:00
|
|
|
return(-1);
|
|
|
|
}
|
2007-02-22 16:49:12 +00:00
|
|
|
if (domain->id == -1 || domain->id == 0)
|
2006-11-15 21:03:34 +00:00
|
|
|
return(-1);
|
2006-04-03 13:46:43 +00:00
|
|
|
/*
|
2008-02-05 19:27:37 +00:00
|
|
|
* this is very hackish, the domU kernel probes for a special
|
2006-04-03 13:46:43 +00:00
|
|
|
* node in the xenstore and launch the shutdown command if found.
|
|
|
|
*/
|
|
|
|
return(virDomainDoStoreWrite(domain, "control/shutdown", "reboot"));
|
|
|
|
}
|
2006-11-07 16:28:16 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* xenStoreDomainGetOSType:
|
|
|
|
* @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 *
|
|
|
|
xenStoreDomainGetOSType(virDomainPtr domain) {
|
|
|
|
char *vm, *str = NULL;
|
|
|
|
|
|
|
|
if ((domain == NULL) || (domain->conn == NULL)) {
|
|
|
|
virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
|
2008-04-10 16:54:54 +00:00
|
|
|
__FUNCTION__);
|
2006-11-07 16:28:16 +00:00
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
vm = virDomainGetVM(domain);
|
|
|
|
if (vm) {
|
|
|
|
str = virDomainGetVMInfo(domain, vm, "image/ostype");
|
|
|
|
free(vm);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (str);
|
|
|
|
}
|
2006-08-09 15:21:16 +00:00
|
|
|
#endif /* ! PROXY */
|
2006-04-03 13:46:43 +00:00
|
|
|
|
2006-08-08 20:14:40 +00:00
|
|
|
/**
|
|
|
|
* xenStoreDomainGetVNCPort:
|
2006-08-09 15:21:16 +00:00
|
|
|
* @conn: the hypervisor connection
|
|
|
|
* @domid: id of the domain
|
2006-08-08 20:14:40 +00:00
|
|
|
*
|
|
|
|
* Return the port number on which the domain is listening for VNC
|
2008-02-05 19:27:37 +00:00
|
|
|
* connections.
|
2006-08-08 20:14:40 +00:00
|
|
|
*
|
|
|
|
* Returns the port number, -1 in case of error
|
|
|
|
*/
|
2006-08-09 15:21:16 +00:00
|
|
|
int xenStoreDomainGetVNCPort(virConnectPtr conn, int domid) {
|
2006-08-08 20:14:40 +00:00
|
|
|
char *tmp;
|
|
|
|
int ret = -1;
|
|
|
|
|
2006-08-09 15:21:16 +00:00
|
|
|
tmp = virDomainDoStoreQuery(conn, domid, "console/vnc-port");
|
2006-08-08 20:14:40 +00:00
|
|
|
if (tmp != NULL) {
|
|
|
|
char *end;
|
|
|
|
ret = strtol(tmp, &end, 10);
|
|
|
|
if (ret == 0 && end == tmp)
|
|
|
|
ret = -1;
|
|
|
|
free(tmp);
|
|
|
|
}
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* xenStoreDomainGetConsolePath:
|
2006-08-09 15:21:16 +00:00
|
|
|
* @conn: the hypervisor connection
|
|
|
|
* @domid: id of the domain
|
2006-08-08 20:14:40 +00:00
|
|
|
*
|
|
|
|
* Return the path to the psuedo TTY on which the guest domain's
|
|
|
|
* serial console is attached.
|
|
|
|
*
|
|
|
|
* Returns the path to the serial console. It is the callers
|
|
|
|
* responsibilty to free() the return string. Returns NULL
|
|
|
|
* on error
|
|
|
|
*/
|
2006-08-09 15:21:16 +00:00
|
|
|
char * xenStoreDomainGetConsolePath(virConnectPtr conn, int domid) {
|
|
|
|
return virDomainDoStoreQuery(conn, domid, "console/tty");
|
2006-08-08 20:14:40 +00:00
|
|
|
}
|
2006-11-07 16:28:16 +00:00
|
|
|
|
|
|
|
#ifdef PROXY
|
|
|
|
/*
|
|
|
|
* xenStoreDomainGetOSTypeID:
|
|
|
|
* @conn: pointer to the connection.
|
|
|
|
* @id: the domain id
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
xenStoreDomainGetOSTypeID(virConnectPtr conn, int id) {
|
|
|
|
char *vm, *str = NULL;
|
|
|
|
char query[200];
|
|
|
|
unsigned int len;
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
2006-11-07 16:28:16 +00:00
|
|
|
|
|
|
|
if (id < 0)
|
|
|
|
return(NULL);
|
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if (priv->xshandle == NULL)
|
2006-11-07 16:28:16 +00:00
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
snprintf(query, 199, "/local/domain/%d/vm", id);
|
|
|
|
query[199] = 0;
|
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
vm = xs_read(priv->xshandle, 0, &query[0], &len);
|
2006-11-07 16:28:16 +00:00
|
|
|
|
|
|
|
if (vm) {
|
|
|
|
snprintf(query, 199, "%s/image/ostype", vm);
|
2008-04-10 16:54:54 +00:00
|
|
|
str = xs_read(priv->xshandle, 0, &query[0], &len);
|
2006-11-07 16:28:16 +00:00
|
|
|
free(vm);
|
|
|
|
}
|
2006-11-08 13:53:29 +00:00
|
|
|
if (str == NULL)
|
|
|
|
str = strdup("linux");
|
|
|
|
|
2006-11-07 16:28:16 +00:00
|
|
|
|
|
|
|
return (str);
|
|
|
|
}
|
|
|
|
#endif /* PROXY */
|
2006-11-20 16:42:16 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* xenStoreDomainGetNetworkID:
|
|
|
|
* @conn: pointer to the connection.
|
|
|
|
* @id: the domain id
|
|
|
|
* @mac: the mac address
|
|
|
|
*
|
|
|
|
* Get the reference (i.e. the string number) for the device on that domain
|
|
|
|
* which uses the given mac address
|
|
|
|
*
|
|
|
|
* Returns the new string or NULL in case of error, the string must be
|
|
|
|
* freed by the caller.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
xenStoreDomainGetNetworkID(virConnectPtr conn, int id, const char *mac) {
|
|
|
|
char dir[80], path[128], **list = NULL, *val = NULL;
|
|
|
|
unsigned int maclen, len, i, num;
|
|
|
|
char *ret = NULL;
|
2007-04-04 14:19:49 +00:00
|
|
|
xenUnifiedPrivatePtr priv;
|
2006-11-20 16:42:16 +00:00
|
|
|
|
|
|
|
if (id < 0)
|
|
|
|
return(NULL);
|
2007-04-04 14:19:49 +00:00
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if (priv->xshandle == NULL)
|
2006-11-20 16:42:16 +00:00
|
|
|
return (NULL);
|
|
|
|
if (mac == NULL)
|
|
|
|
return (NULL);
|
|
|
|
maclen = strlen(mac);
|
|
|
|
if (maclen <= 0)
|
|
|
|
return (NULL);
|
|
|
|
|
2007-03-23 16:15:07 +00:00
|
|
|
snprintf(dir, sizeof(dir), "/local/domain/0/backend/vif/%d", id);
|
2007-04-04 14:19:49 +00:00
|
|
|
list = xs_directory(priv->xshandle, 0, dir, &num);
|
2006-11-20 16:42:16 +00:00
|
|
|
if (list == NULL)
|
2008-04-10 16:54:54 +00:00
|
|
|
return(NULL);
|
2006-11-20 16:42:16 +00:00
|
|
|
for (i = 0; i < num; i++) {
|
2008-04-10 16:54:54 +00:00
|
|
|
snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "mac");
|
|
|
|
val = xs_read(priv->xshandle, 0, path, &len);
|
|
|
|
if (val == NULL)
|
|
|
|
break;
|
|
|
|
if ((maclen != len) || memcmp(val, mac, len)) {
|
|
|
|
free(val);
|
|
|
|
} else {
|
|
|
|
ret = strdup(list[i]);
|
|
|
|
free(val);
|
|
|
|
break;
|
|
|
|
}
|
2006-11-20 16:42:16 +00:00
|
|
|
}
|
|
|
|
free(list);
|
|
|
|
return(ret);
|
|
|
|
}
|
2007-03-15 07:43:16 +00:00
|
|
|
|
2007-11-06 11:49:01 +00:00
|
|
|
/*
|
|
|
|
* xenStoreDomainGetDiskID:
|
|
|
|
* @conn: pointer to the connection.
|
|
|
|
* @id: the domain id
|
|
|
|
* @dev: the virtual block device name
|
|
|
|
*
|
|
|
|
* Get the reference (i.e. the string number) for the device on that domain
|
|
|
|
* which uses the given virtual block device name
|
|
|
|
*
|
|
|
|
* Returns the new string or NULL in case of error, the string must be
|
|
|
|
* freed by the caller.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
xenStoreDomainGetDiskID(virConnectPtr conn, int id, const char *dev) {
|
|
|
|
char dir[80], path[128], **list = NULL, *val = NULL;
|
|
|
|
unsigned int devlen, len, i, num;
|
|
|
|
char *ret = NULL;
|
|
|
|
xenUnifiedPrivatePtr priv;
|
|
|
|
|
|
|
|
if (id < 0)
|
|
|
|
return(NULL);
|
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if (priv->xshandle == NULL)
|
|
|
|
return (NULL);
|
|
|
|
if (dev == NULL)
|
|
|
|
return (NULL);
|
|
|
|
devlen = strlen(dev);
|
|
|
|
if (devlen <= 0)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
snprintf(dir, sizeof(dir), "/local/domain/0/backend/vbd/%d", id);
|
|
|
|
list = xs_directory(priv->xshandle, 0, dir, &num);
|
2007-12-14 15:38:02 +00:00
|
|
|
if (list != NULL) {
|
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev");
|
|
|
|
val = xs_read(priv->xshandle, 0, path, &len);
|
|
|
|
if (val == NULL)
|
|
|
|
break;
|
|
|
|
if ((devlen != len) || memcmp(val, dev, len)) {
|
|
|
|
free (val);
|
|
|
|
} else {
|
|
|
|
ret = strdup(list[i]);
|
|
|
|
free (val);
|
|
|
|
free (list);
|
|
|
|
return (ret);
|
|
|
|
}
|
2007-11-06 11:49:01 +00:00
|
|
|
}
|
2007-12-14 15:38:02 +00:00
|
|
|
free (list);
|
2007-11-06 11:49:01 +00:00
|
|
|
}
|
2007-12-14 15:38:02 +00:00
|
|
|
snprintf(dir, sizeof(dir), "/local/domain/0/backend/tap/%d", id);
|
|
|
|
list = xs_directory(priv->xshandle, 0, dir, &num);
|
|
|
|
if (list != NULL) {
|
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev");
|
|
|
|
val = xs_read(priv->xshandle, 0, path, &len);
|
|
|
|
if (val == NULL)
|
|
|
|
break;
|
|
|
|
if ((devlen != len) || memcmp(val, dev, len)) {
|
|
|
|
free (val);
|
|
|
|
} else {
|
|
|
|
ret = strdup(list[i]);
|
|
|
|
free (val);
|
|
|
|
free (list);
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free (list);
|
|
|
|
}
|
|
|
|
return (NULL);
|
2007-11-06 11:49:01 +00:00
|
|
|
}
|
|
|
|
|
2007-08-10 18:25:15 +00:00
|
|
|
char *xenStoreDomainGetName(virConnectPtr conn,
|
|
|
|
int id) {
|
|
|
|
char prop[200];
|
|
|
|
xenUnifiedPrivatePtr priv;
|
|
|
|
unsigned int len;
|
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if (priv->xshandle == NULL)
|
|
|
|
return(NULL);
|
|
|
|
|
|
|
|
snprintf(prop, 199, "/local/domain/%d/name", id);
|
|
|
|
prop[199] = 0;
|
|
|
|
return xs_read(priv->xshandle, 0, prop, &len);
|
|
|
|
}
|
|
|
|
|
2008-11-25 10:44:52 +00:00
|
|
|
#ifndef PROXY
|
|
|
|
int xenStoreDomainGetUUID(virConnectPtr conn,
|
|
|
|
int id,
|
|
|
|
unsigned char *uuid) {
|
|
|
|
char prop[200];
|
|
|
|
xenUnifiedPrivatePtr priv;
|
|
|
|
unsigned int len;
|
|
|
|
char *uuidstr;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if (priv->xshandle == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
snprintf(prop, 199, "/local/domain/%d/vm", id);
|
|
|
|
prop[199] = 0;
|
|
|
|
// This will return something like
|
|
|
|
// /vm/00000000-0000-0000-0000-000000000000
|
|
|
|
uuidstr = xs_read(priv->xshandle, 0, prop, &len);
|
|
|
|
|
|
|
|
// remove "/vm/"
|
|
|
|
ret = virUUIDParse(uuidstr + 4, uuid);
|
|
|
|
|
|
|
|
VIR_FREE(uuidstr);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif //PROXY
|
|
|
|
|
|
|
|
void xenStoreWatchListFree(xenStoreWatchListPtr list)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i=0; i<list->count; i++) {
|
|
|
|
VIR_FREE(list->watches[i]->path);
|
|
|
|
VIR_FREE(list->watches[i]->token);
|
|
|
|
VIR_FREE(list->watches[i]);
|
|
|
|
}
|
|
|
|
VIR_FREE(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
int xenStoreAddWatch(virConnectPtr conn,
|
|
|
|
const char *path,
|
|
|
|
const char *token,
|
|
|
|
xenStoreWatchCallback cb,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
xenStoreWatchPtr watch;
|
|
|
|
int n;
|
|
|
|
xenStoreWatchListPtr list;
|
|
|
|
xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
|
|
|
|
if (priv->xshandle == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
list = priv->xsWatchList;
|
|
|
|
if(!list)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* check if we already have this callback on our list */
|
|
|
|
for (n=0; n < list->count; n++) {
|
|
|
|
if( STREQ(list->watches[n]->path, path) &&
|
|
|
|
STREQ(list->watches[n]->token, token)) {
|
|
|
|
virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("watch already tracked"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(watch) < 0)
|
|
|
|
return -1;
|
|
|
|
watch->path = strdup(path);
|
|
|
|
watch->token = strdup(token);
|
|
|
|
watch->cb = cb;
|
|
|
|
watch->opaque = opaque;
|
|
|
|
|
|
|
|
/* Make space on list */
|
|
|
|
n = list->count;
|
|
|
|
if (VIR_REALLOC_N(list->watches, n + 1) < 0) {
|
|
|
|
virXenStoreError(NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("reallocating list"));
|
|
|
|
VIR_FREE(watch);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
list->watches[n] = watch;
|
|
|
|
list->count++;
|
|
|
|
|
|
|
|
conn->refs++;
|
|
|
|
|
|
|
|
return xs_watch(priv->xshandle, watch->path, watch->token);
|
|
|
|
}
|
|
|
|
|
|
|
|
int xenStoreRemoveWatch(virConnectPtr conn,
|
|
|
|
const char *path,
|
|
|
|
const char *token)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
xenStoreWatchListPtr list;
|
|
|
|
xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
|
|
|
|
if (priv->xshandle == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
list = priv->xsWatchList;
|
|
|
|
if(!list)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0 ; i < list->count ; i++) {
|
|
|
|
if( STREQ(list->watches[i]->path, path) &&
|
|
|
|
STREQ(list->watches[i]->token, token)) {
|
|
|
|
|
|
|
|
if (!xs_unwatch(priv->xshandle,
|
|
|
|
list->watches[i]->path,
|
|
|
|
list->watches[i]->path))
|
|
|
|
{
|
|
|
|
DEBUG0("WARNING: Could not remove watch");
|
|
|
|
/* Not fatal, continue */
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(list->watches[i]->path);
|
|
|
|
VIR_FREE(list->watches[i]->token);
|
|
|
|
VIR_FREE(list->watches[i]);
|
|
|
|
|
|
|
|
if (i < (list->count - 1))
|
|
|
|
memmove(list->watches + i,
|
|
|
|
list->watches + i + 1,
|
|
|
|
sizeof(*(list->watches)) *
|
|
|
|
(list->count - (i + 1)));
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(list->watches,
|
|
|
|
list->count - 1) < 0) {
|
|
|
|
; /* Failure to reduce memory allocation isn't fatal */
|
|
|
|
}
|
|
|
|
list->count--;
|
|
|
|
#ifndef PROXY
|
|
|
|
virUnrefConnect(conn);
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
xenStoreWatchPtr xenStoreFindWatch(xenStoreWatchListPtr list,
|
|
|
|
const char *path,
|
|
|
|
const char *token)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0 ; i < list->count ; i++)
|
|
|
|
if( STREQ(path, list->watches[i]->path) &&
|
|
|
|
STREQ(token, list->watches[i]->token) )
|
|
|
|
return list->watches[i];
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED,
|
|
|
|
int fd ATTRIBUTE_UNUSED,
|
|
|
|
int events ATTRIBUTE_UNUSED,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
char **event;
|
|
|
|
char *path;
|
|
|
|
char *token;
|
|
|
|
unsigned int stringCount;
|
|
|
|
xenStoreWatchPtr sw;
|
|
|
|
|
|
|
|
virConnectPtr conn = data;
|
|
|
|
xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
|
|
|
|
if(!priv) return;
|
|
|
|
if(!priv->xshandle) return;
|
|
|
|
|
|
|
|
event = xs_read_watch(priv->xshandle, &stringCount);
|
|
|
|
if (!event)
|
|
|
|
return;
|
|
|
|
|
|
|
|
path = event[XS_WATCH_PATH];
|
|
|
|
token = event[XS_WATCH_TOKEN];
|
|
|
|
|
|
|
|
sw = xenStoreFindWatch(priv->xsWatchList, path, token);
|
|
|
|
if( sw )
|
|
|
|
sw->cb(conn, path, token, sw->opaque);
|
|
|
|
VIR_FREE(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef PROXY
|
|
|
|
/* The domain callback for the @introduceDomain watch */
|
|
|
|
int xenStoreDomainIntroduced(virConnectPtr conn,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
|
|
|
const char *token ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
int i, j, found, missing = 0, retries = 20;
|
|
|
|
int new_domain_cnt;
|
|
|
|
int *new_domids;
|
|
|
|
int nread;
|
|
|
|
|
|
|
|
xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) opaque;
|
|
|
|
|
|
|
|
retry:
|
|
|
|
new_domain_cnt = xenStoreNumOfDomains(conn);
|
|
|
|
if( VIR_ALLOC_N(new_domids,new_domain_cnt) < 0 ) {
|
|
|
|
virXenStoreError(NULL, VIR_ERR_NO_MEMORY,
|
|
|
|
"%s", _("failed to allocate domids"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
nread = xenStoreListDomains(conn, new_domids, new_domain_cnt);
|
|
|
|
if (nread != new_domain_cnt) {
|
|
|
|
// mismatch. retry this read
|
|
|
|
VIR_FREE(new_domids);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
missing = 0;
|
|
|
|
for (i=0 ; i < new_domain_cnt ; i++) {
|
|
|
|
found = 0;
|
|
|
|
for (j = 0 ; j < activeDomainList->count ; j++) {
|
|
|
|
if (activeDomainList->doms[j]->id == new_domids[i]) {
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
2008-12-04 21:09:20 +00:00
|
|
|
virDomainEventPtr event;
|
2008-11-25 10:44:52 +00:00
|
|
|
char *name;
|
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
|
|
|
|
if (!(name = xenStoreDomainGetName(conn, new_domids[i]))) {
|
|
|
|
missing = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (xenStoreDomainGetUUID(conn, new_domids[i], uuid) < 0) {
|
|
|
|
missing = 1;
|
|
|
|
VIR_FREE(name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2008-12-04 21:09:20 +00:00
|
|
|
event = virDomainEventNew(new_domids[i], name, uuid,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
|
|
|
if (event)
|
|
|
|
xenUnifiedDomainEventDispatch(priv, event);
|
2008-11-25 10:44:52 +00:00
|
|
|
|
2008-12-04 21:09:20 +00:00
|
|
|
/* Add to the list */
|
|
|
|
xenUnifiedAddDomainInfo(activeDomainList,
|
|
|
|
new_domids[i], name, uuid);
|
2008-11-25 10:44:52 +00:00
|
|
|
|
|
|
|
VIR_FREE(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VIR_FREE(new_domids);
|
|
|
|
|
|
|
|
if (missing && retries--) {
|
|
|
|
DEBUG0("Some domains were missing, trying again");
|
|
|
|
usleep(100 * 1000);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The domain callback for the @destroyDomain watch */
|
|
|
|
int xenStoreDomainReleased(virConnectPtr conn,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
|
|
|
const char *token ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
int i, j, found, removed, retries = 20;
|
|
|
|
int new_domain_cnt;
|
|
|
|
int *new_domids;
|
|
|
|
int nread;
|
|
|
|
|
|
|
|
xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) opaque;
|
|
|
|
|
|
|
|
if(!activeDomainList->count) return 0;
|
|
|
|
|
|
|
|
retry:
|
|
|
|
new_domain_cnt = xenStoreNumOfDomains(conn);
|
|
|
|
|
|
|
|
if( VIR_ALLOC_N(new_domids,new_domain_cnt) < 0 ) {
|
|
|
|
virXenStoreError(NULL, VIR_ERR_NO_MEMORY,
|
|
|
|
"%s", _("failed to allocate domids"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
nread = xenStoreListDomains(conn, new_domids, new_domain_cnt);
|
|
|
|
if (nread != new_domain_cnt) {
|
|
|
|
// mismatch. retry this read
|
|
|
|
VIR_FREE(new_domids);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
removed = 0;
|
|
|
|
for (j=0 ; j < activeDomainList->count ; j++) {
|
|
|
|
found = 0;
|
|
|
|
for (i=0 ; i < new_domain_cnt ; i++) {
|
|
|
|
if (activeDomainList->doms[j]->id == new_domids[i]) {
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
2008-12-04 21:09:20 +00:00
|
|
|
virDomainEventPtr event =
|
|
|
|
virDomainEventNew(-1,
|
|
|
|
activeDomainList->doms[j]->name,
|
|
|
|
activeDomainList->doms[j]->uuid,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
|
|
|
|
if (event)
|
|
|
|
xenUnifiedDomainEventDispatch(priv, event);
|
|
|
|
|
|
|
|
/* Remove from the list */
|
|
|
|
xenUnifiedRemoveDomainInfo(activeDomainList,
|
|
|
|
activeDomainList->doms[j]->id,
|
|
|
|
activeDomainList->doms[j]->name,
|
|
|
|
activeDomainList->doms[j]->uuid);
|
|
|
|
|
|
|
|
removed = 1;
|
2008-11-25 10:44:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(new_domids);
|
|
|
|
|
|
|
|
if (!removed && retries--) {
|
|
|
|
DEBUG0("No domains removed, retrying");
|
|
|
|
usleep(100 * 1000);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif //PROXY
|