virDomainBlockPeek call

* configure.in: Document AC_SYS_LARGEFILE.
	* docs/hvsupport.html.in: Document HV support for virDomainBlockPeek.
	* include/libvirt/libvirt.h.in, src/driver.h, src/libvirt.c,
	src/libvirt_sym.version: Add virDomainBlockPeek infrastructure.
	* src/qemu_driver.c, src/test.c: Null versions of this call.
	* src/xen_unified.c, src/xend_internal.c, src/xend_internal.h,
	src/xm_internal.c, src/xm_internal.h: Xen implementation.
	* tests/sexpr2xmldata/sexpr2xml-curmem.xml,
	tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml: XML output
	has been reordered slightly in the Xen driver, but should be
	functionally the same.
This commit is contained in:
Richard W.M. Jones 2008-06-05 13:17:45 +00:00
parent 0bd57cdbe1
commit 8354895e68
18 changed files with 826 additions and 470 deletions

View File

@ -1,3 +1,18 @@
Thu Jun 5 14:10:00 BST 2008 Richard W.M. Jones <rjones@redhat.com>
virDomainBlockPeek call
* configure.in: Document AC_SYS_LARGEFILE.
* docs/hvsupport.html.in: Document HV support for virDomainBlockPeek.
* include/libvirt/libvirt.h.in, src/driver.h, src/libvirt.c,
src/libvirt_sym.version: Add virDomainBlockPeek infrastructure.
* src/qemu_driver.c, src/test.c: Null versions of this call.
* src/xen_unified.c, src/xend_internal.c, src/xend_internal.h,
src/xm_internal.c, src/xm_internal.h: Xen implementation.
* tests/sexpr2xmldata/sexpr2xml-curmem.xml,
tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml: XML output
has been reordered slightly in the Xen driver, but should be
functionally the same.
Wed Jun 4 23:02:21 PST 2008 David L. Leskovec <dlesko@linux.vnet.ibm.com>
* src/lxc_driver.c: Add sanity of tty pid before kill()

View File

@ -60,6 +60,10 @@ AM_PROG_CC_C_O
LIBVIRT_COMPILE_WARNINGS([maximum])
dnl Support large files / 64 bit seek offsets.
dnl Use --disable-largefile if you don't want this.
AC_SYS_LARGEFILE
dnl Availability of various common functions (non-fatal if missing).
AC_CHECK_FUNCS([cfmakeraw regexec uname sched_getaffinity])
@ -982,8 +986,6 @@ AC_SUBST([CYGWIN_EXTRA_LIBADD])
AC_SUBST([CYGWIN_EXTRA_PYTHON_LIBADD])
AC_SUBST([MINGW_EXTRA_LDFLAGS])
AC_SYS_LARGEFILE
# Set LV_LIBTOOL_OBJDIR to "." or $lt_cv_objdir, depending on whether
# we're building shared libraries. This is the name of the directory
# in which .o files will be created.

View File

@ -137,7 +137,7 @@ in.
</p>
<p>
This information changes frequently. This page was last checked or
updated on <i>2007-08-20</i>.
updated on <i>2008-06-05</i>.
</p>
<h3>Domain functions</h3>
<p> x = not supported; empty cell means no information </p>
@ -254,6 +254,14 @@ updated on <i>2007-08-20</i>.
<td> &#8805; 0.2.0 </td>
<td> &#8805; 0.3.0 </td>
</tr>
<tr>
<td> virConnectOpenAuth </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> virConnectOpenReadOnly </td>
<td> All </td>
@ -270,6 +278,14 @@ updated on <i>2007-08-20</i>.
<td> x </td>
<td> &#8805; 0.3.0 </td>
</tr>
<tr>
<td> virDomainBlockPeek </td>
<td> 0.4.3 </td>
<td> x </td>
<td> x </td>
<td> x </td>
<td> x </td>
</tr>
<tr>
<td> virDomainBlockStats </td>
<td> 0.3.2 </td>

View File

@ -9,7 +9,7 @@ in.
</p>
<p>
This information changes frequently. This page was last checked or
updated on <i>2007-08-20</i>.
updated on <i>2008-06-05</i>.
</p>
<h3>Domain functions</h3>
<p> x = not supported; empty cell means no information </p>
@ -118,6 +118,14 @@ updated on <i>2007-08-20</i>.
<td> &#x2265; 0.2.0 </td>
<td> &#x2265; 0.3.0 </td>
</tr>
<tr>
<td> virConnectOpenAuth </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> virConnectOpenReadOnly </td>
<td> All </td>
@ -134,6 +142,14 @@ updated on <i>2007-08-20</i>.
<td> x </td>
<td> &#x2265; 0.3.0 </td>
</tr>
<tr>
<td> virDomainBlockPeek </td>
<td> 0.4.3 </td>
<td> x </td>
<td> x </td>
<td> x </td>
<td> x </td>
</tr>
<tr>
<td> virDomainBlockStats </td>
<td> 0.3.2 </td>

View File

@ -530,7 +530,12 @@ int virDomainInterfaceStats (virDomainPtr dom,
const char *path,
virDomainInterfaceStatsPtr stats,
size_t size);
int virDomainBlockPeek (virDomainPtr dom,
const char *path,
unsigned long long offset,
size_t size,
void *buffer,
unsigned int flags);
/*
* defined but not running domains

View File

@ -530,7 +530,12 @@ int virDomainInterfaceStats (virDomainPtr dom,
const char *path,
virDomainInterfaceStatsPtr stats,
size_t size);
int virDomainBlockPeek (virDomainPtr dom,
const char *path,
unsigned long long offset,
size_t size,
void *buffer,
unsigned int flags);
/*
* defined but not running domains

View File

@ -225,6 +225,13 @@ typedef int
const char *path,
struct _virDomainInterfaceStats *stats);
typedef int
(*virDrvDomainBlockPeek)
(virDomainPtr domain,
const char *path,
unsigned long long offset, size_t size,
void *buffer);
typedef int
(*virDrvDomainMigratePrepare)
(virConnectPtr dconn,
@ -337,6 +344,7 @@ struct _virDriver {
virDrvDomainMigrateFinish domainMigrateFinish;
virDrvDomainBlockStats domainBlockStats;
virDrvDomainInterfaceStats domainInterfaceStats;
virDrvDomainBlockPeek domainBlockPeek;
virDrvNodeGetCellsFreeMemory nodeGetCellsFreeMemory;
virDrvNodeGetFreeMemory getFreeMemory;
};

View File

@ -2586,7 +2586,84 @@ virDomainInterfaceStats (virDomainPtr dom, const char *path,
return -1;
}
/**
* virDomainBlockPeek:
* @dom: pointer to the domain object
* @path: path to the block device
* @offset: offset within block device
* @size: size to read
* @buffer: return buffer (must be at least size bytes)
* @flags: unused, always pass 0
*
* This function allows you to read the contents of a domain's
* disk device.
*
* Typical uses for this are to determine if the domain has
* written a Master Boot Record (indicating that the domain
* has completed installation), or to try to work out the state
* of the domain's filesystems.
*
* (Note that in the local case you might try to open the
* block device or file directly, but that won't work in the
* remote case, nor if you don't have sufficient permission.
* Hence the need for this call).
*
* 'path' must be a device or file corresponding to the domain.
* In other words it must be the precise string returned in
* a <disk><source dev='...'/></disk> from
* virDomainGetXMLDesc.
*
* 'offset' and 'size' represent an area which must lie entirely
* within the device or file. 'size' may be 0 to test if the
* call would succeed.
*
* 'buffer' is the return buffer and must be at least 'size' bytes.
*
* Returns: 0 in case of success or -1 in case of failure.
*/
int
virDomainBlockPeek (virDomainPtr dom,
const char *path,
unsigned long long offset /* really 64 bits */,
size_t size,
void *buffer,
unsigned int flags)
{
virConnectPtr conn;
DEBUG("domain=%p, path=%s, offset=%lld, size=%zi, buffer=%p",
dom, path, offset, size, buffer);
if (!VIR_IS_CONNECTED_DOMAIN (dom)) {
virLibDomainError (NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
return -1;
}
conn = dom->conn;
if (!path) {
virLibDomainError (dom, VIR_ERR_INVALID_ARG,
_("path is NULL"));
return -1;
}
if (flags != 0) {
virLibDomainError (dom, VIR_ERR_INVALID_ARG,
_("flags must be zero"));
return -1;
}
/* Allow size == 0 as an access test. */
if (size > 0 && !buffer) {
virLibDomainError (dom, VIR_ERR_INVALID_ARG,
_("buffer is NULL"));
return -1;
}
if (conn->driver->domainBlockPeek)
return conn->driver->domainBlockPeek (dom, path, offset, size, buffer);
virLibDomainError (dom, VIR_ERR_NO_SUPPORT, __FUNCTION__);
return -1;
}
/************************************************************************

View File

@ -73,6 +73,7 @@
virDomainSetSchedulerParameters;
virDomainBlockStats;
virDomainInterfaceStats;
virDomainBlockPeek;
virDomainAttachDevice;
virDomainDetachDevice;

View File

@ -3521,6 +3521,7 @@ static virDriver qemuDriver = {
NULL, /* domainMigrateFinish */
qemudDomainBlockStats, /* domainBlockStats */
qemudDomainInterfaceStats, /* domainInterfaceStats */
NULL, /* domainBlockPeek */
#if HAVE_NUMACTL
qemudNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
qemudNodeGetFreeMemory, /* getFreeMemory */

View File

@ -2060,6 +2060,7 @@ static virDriver testDriver = {
NULL, /* domainMigrateFinish */
NULL, /* domainBlockStats */
NULL, /* domainInterfaceStats */
NULL, /* domainBlockPeek */
testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
NULL, /* getFreeMemory */
};

View File

@ -1234,6 +1234,29 @@ xenUnifiedDomainInterfaceStats (virDomainPtr dom, const char *path,
return -1;
}
static int
xenUnifiedDomainBlockPeek (virDomainPtr dom, const char *path,
unsigned long long offset, size_t size,
void *buffer)
{
int r;
GET_PRIVATE (dom->conn);
if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
r = xenDaemonDomainBlockPeek (dom, path, offset, size, buffer);
if (r != -2) return r;
/* r == -2 means declined, so fall through to XM driver ... */
}
if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
if (xenXMDomainBlockPeek (dom, path, offset, size, buffer) == 0)
return 0;
}
xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
return -1;
}
static int
xenUnifiedNodeGetCellsFreeMemory (virConnectPtr conn, unsigned long long *freeMems,
int startCell, int maxCells)
@ -1329,6 +1352,7 @@ static virDriver xenUnifiedDriver = {
.domainMigrateFinish = xenUnifiedDomainMigrateFinish,
.domainBlockStats = xenUnifiedDomainBlockStats,
.domainInterfaceStats = xenUnifiedDomainInterfaceStats,
.domainBlockPeek = xenUnifiedDomainBlockPeek,
.nodeGetCellsFreeMemory = xenUnifiedNodeGetCellsFreeMemory,
.getFreeMemory = xenUnifiedNodeGetFreeMemory,
};

View File

@ -18,6 +18,8 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
@ -1705,6 +1707,219 @@ error:
return ret;
}
typedef int
(*sexp_blockdevs_cb)
(virConnectPtr conn, void *data,
int isBlock, int cdrom, int isNoSrcCdrom, int hvm,
const char *drvName, const char *drvType,
const char *src, const char *dst,
const char *mode);
/**
* xend_parse_sexp_blockdevs:
* @conn: connection
* @root: root sexpr
* @xendConfigVersion: version of xend
* @fn: callback function
* @data: optional data for callback function
*
* This parses out block devices from the domain sexpr and calls
* fn (conn, data, ...) for each block device found.
*
* Returns 0 if successful or -1 if failed.
*/
static int
xend_parse_sexp_blockdevs (virConnectPtr conn, struct sexpr *root,
int xendConfigVersion,
sexp_blockdevs_cb fn, void *data)
{
struct sexpr *cur, *node;
int hvm;
hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0;
for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
node = cur->u.s.car;
/* Normally disks are in a (device (vbd ...)) block
but blktap disks ended up in a differently named
(device (tap ....)) block.... */
if (sexpr_lookup(node, "device/vbd") ||
sexpr_lookup(node, "device/tap")) {
char *offset;
int ret = -1;
int isBlock = 0;
int cdrom = 0;
int isNoSrcCdrom = 0;
char *drvName = NULL;
char *drvType = NULL;
const char *src = NULL;
const char *dst = NULL;
const char *mode = NULL;
/* Again dealing with (vbd...) vs (tap ...) differences */
if (sexpr_lookup(node, "device/vbd")) {
src = sexpr_node(node, "device/vbd/uname");
dst = sexpr_node(node, "device/vbd/dev");
mode = sexpr_node(node, "device/vbd/mode");
} else {
src = sexpr_node(node, "device/tap/uname");
dst = sexpr_node(node, "device/tap/dev");
mode = sexpr_node(node, "device/tap/mode");
}
if (dst == NULL) {
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
_("domain information incomplete, vbd has no dev"));
goto bad_parse;
}
if (src == NULL) {
/* There is a case without the uname to the CD-ROM device */
offset = strchr(dst, ':');
if (offset) {
if (hvm && STREQ(offset, ":cdrom")) {
isNoSrcCdrom = 1;
}
offset[0] = '\0';
}
if (!isNoSrcCdrom) {
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
_("domain information incomplete, vbd has no src"));
goto bad_parse;
}
}
if (!isNoSrcCdrom) {
offset = strchr(src, ':');
if (!offset) {
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
_("cannot parse vbd filename, missing driver name"));
goto bad_parse;
}
if (VIR_ALLOC_N(drvName, (offset-src)+1) < 0) {
virXendError(conn, VIR_ERR_NO_MEMORY,
_("allocate new buffer"));
goto bad_parse;
}
strncpy(drvName, src, (offset-src));
drvName[offset-src] = '\0';
src = offset + 1;
if (STREQ (drvName, "tap")) {
offset = strchr(src, ':');
if (!offset) {
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
_("cannot parse vbd filename, missing driver type"));
goto bad_parse;
}
if (VIR_ALLOC_N(drvType, (offset-src)+1)< 0) {
virXendError(conn, VIR_ERR_NO_MEMORY,
_("allocate new buffer"));
goto bad_parse;
}
strncpy(drvType, src, (offset-src));
drvType[offset-src] = '\0';
src = offset + 1;
/* Its possible to use blktap driver for block devs
too, but kinda pointless because blkback is better,
so we assume common case here. If blktap becomes
omnipotent, we can revisit this, perhaps stat()'ing
the src file in question */
isBlock = 0;
} else if (STREQ(drvName, "phy")) {
isBlock = 1;
} else if (STREQ(drvName, "file")) {
isBlock = 0;
}
}
if (STREQLEN (dst, "ioemu:", 6))
dst += 6;
/* New style disk config from Xen >= 3.0.3 */
if (xendConfigVersion > 1) {
offset = strrchr(dst, ':');
if (offset) {
if (STREQ (offset, ":cdrom")) {
cdrom = 1;
} else if (STREQ (offset, ":disk")) {
/* The default anyway */
} else {
/* Unknown, lets pretend its a disk too */
}
offset[0] = '\0';
}
}
/* Call the callback function. */
ret = fn (conn, data, isBlock, cdrom, isNoSrcCdrom, hvm,
drvName, drvType, src, dst, mode);
bad_parse:
VIR_FREE(drvName);
VIR_FREE(drvType);
if (ret == -1) return -1;
}
}
return 0;
}
static int
xend_parse_sexp_desc_blockdev (virConnectPtr conn ATTRIBUTE_UNUSED,
void *data,
int isBlock, int cdrom, int isNoSrcCdrom,
int hvm,
const char *drvName, const char *drvType,
const char *src, const char *dst,
const char *mode)
{
virBuffer *buf = (virBuffer *) data;
const char *bus = NULL;
if (!isNoSrcCdrom) {
virBufferVSprintf(buf, " <disk type='%s' device='%s'>\n",
isBlock ? "block" : "file",
cdrom ? "cdrom" : "disk");
if (drvType) {
virBufferVSprintf(buf, " <driver name='%s' type='%s'/>\n", drvName, drvType);
} else {
virBufferVSprintf(buf, " <driver name='%s'/>\n", drvName);
}
if (isBlock) {
virBufferVSprintf(buf, " <source dev='%s'/>\n", src);
} else {
virBufferVSprintf(buf, " <source file='%s'/>\n", src);
}
} else {
/* This case is the cdrom device only */
virBufferAddLit(buf, " <disk device='cdrom'>\n");
}
if (STRPREFIX(dst, "xvd") || !hvm) {
bus = "xen";
} else if (STRPREFIX(dst, "sd")) {
bus = "scsi";
} else {
bus = "ide";
}
virBufferVSprintf(buf, " <target dev='%s' bus='%s'/>\n",
dst, bus);
/* XXX should we force mode == r, if cdrom==1, or assume
xend has already done this ? */
if ((mode != NULL) && (STREQ (mode, "r")))
virBufferAddLit(buf, " <readonly/>\n");
else if ((mode != NULL) && (STREQ (mode, "w!")))
virBufferAddLit(buf, " <shareable/>\n");
virBufferAddLit(buf, " </disk>\n");
return 0;
}
/**
* xend_parse_sexp_desc:
* @conn: the connection associated with the XML
@ -1849,164 +2064,15 @@ xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root,
if ((tmp != NULL) && (tmp[0] != 0))
virBufferVSprintf(&buf, " <emulator>%s</emulator>\n", tmp);
/* append block devices */
if (xend_parse_sexp_blockdevs (conn, root, xendConfigVersion,
xend_parse_sexp_desc_blockdev, &buf) == -1)
goto error;
/* append network devices and framebuffer */
for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
node = cur->u.s.car;
/* Normally disks are in a (device (vbd ...)) block
but blktap disks ended up in a differently named
(device (tap ....)) block.... */
if (sexpr_lookup(node, "device/vbd") ||
sexpr_lookup(node, "device/tap")) {
char *offset;
int isBlock = 0;
int cdrom = 0;
int isNoSrcCdrom = 0;
char *drvName = NULL;
char *drvType = NULL;
const char *src = NULL;
const char *dst = NULL;
const char *mode = NULL;
const char *bus = NULL;
/* Again dealing with (vbd...) vs (tap ...) differences */
if (sexpr_lookup(node, "device/vbd")) {
src = sexpr_node(node, "device/vbd/uname");
dst = sexpr_node(node, "device/vbd/dev");
mode = sexpr_node(node, "device/vbd/mode");
} else {
src = sexpr_node(node, "device/tap/uname");
dst = sexpr_node(node, "device/tap/dev");
mode = sexpr_node(node, "device/tap/mode");
}
if (dst == NULL) {
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
_("domain information incomplete, vbd has no dev"));
goto bad_parse;
}
if (src == NULL) {
/* There is a case without the uname to the CD-ROM device */
offset = strchr(dst, ':');
if (offset) {
if (hvm && STREQ( offset , ":cdrom")) {
isNoSrcCdrom = 1;
}
offset[0] = '\0';
}
if (!isNoSrcCdrom) {
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
_("domain information incomplete, vbd has no src"));
goto bad_parse;
}
}
if (!isNoSrcCdrom) {
offset = strchr(src, ':');
if (!offset) {
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
_("cannot parse vbd filename, missing driver name"));
goto bad_parse;
}
if (VIR_ALLOC_N(drvName, (offset-src)+1) < 0) {
virXendError(conn, VIR_ERR_NO_MEMORY,
_("allocate new buffer"));
goto bad_parse;
}
strncpy(drvName, src, (offset-src));
drvName[offset-src] = '\0';
src = offset + 1;
if (STREQ(drvName, "tap")) {
offset = strchr(src, ':');
if (!offset) {
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
_("cannot parse vbd filename, missing driver type"));
goto bad_parse;
}
if (VIR_ALLOC_N(drvType, (offset-src)+1)< 0) {
virXendError(conn, VIR_ERR_NO_MEMORY,
_("allocate new buffer"));
goto bad_parse;
}
strncpy(drvType, src, (offset-src));
drvType[offset-src] = '\0';
src = offset + 1;
/* Its possible to use blktap driver for block devs
too, but kinda pointless because blkback is better,
so we assume common case here. If blktap becomes
omnipotent, we can revisit this, perhaps stat()'ing
the src file in question */
isBlock = 0;
} else if (STREQ(drvName, "phy")) {
isBlock = 1;
} else if (STREQ(drvName, "file")) {
isBlock = 0;
}
}
if (STRPREFIX(dst, "ioemu:"))
dst += 6;
/* New style disk config from Xen >= 3.0.3 */
if (xendConfigVersion > 1) {
offset = strrchr(dst, ':');
if (offset) {
if (STREQ(offset, ":cdrom")) {
cdrom = 1;
} else if (STREQ(offset, ":disk")) {
/* The default anyway */
} else {
/* Unknown, lets pretend its a disk too */
}
offset[0] = '\0';
}
}
if (!isNoSrcCdrom) {
virBufferVSprintf(&buf, " <disk type='%s' device='%s'>\n",
isBlock ? "block" : "file",
cdrom ? "cdrom" : "disk");
if (drvType) {
virBufferVSprintf(&buf, " <driver name='%s' type='%s'/>\n", drvName, drvType);
} else {
virBufferVSprintf(&buf, " <driver name='%s'/>\n", drvName);
}
if (isBlock) {
virBufferVSprintf(&buf, " <source dev='%s'/>\n", src);
} else {
virBufferVSprintf(&buf, " <source file='%s'/>\n", src);
}
} else {
/* This case is the cdrom device only */
virBufferAddLit(&buf, " <disk device='cdrom'>\n");
}
if (STRPREFIX(dst, "xvd") || !hvm) {
bus = "xen";
} else if (STRPREFIX(dst, "sd")) {
bus = "scsi";
} else {
bus = "ide";
}
virBufferVSprintf(&buf, " <target dev='%s' bus='%s'/>\n",
dst, bus);
/* XXX should we force mode == r, if cdrom==1, or assume
xend has already done this ? */
if ((mode != NULL) && (STREQ(mode, "r")))
virBufferAddLit(&buf, " <readonly/>\n");
else if ((mode != NULL) && (STREQ(mode, "w!")))
virBufferAddLit(&buf, " <shareable/>\n");
virBufferAddLit(&buf, " </disk>\n");
bad_parse:
VIR_FREE(drvName);
VIR_FREE(drvType);
} else if (sexpr_lookup(node, "device/vif")) {
if (sexpr_lookup(node, "device/vif")) {
const char *tmp2, *model;
tmp2 = sexpr_node(node, "device/vif/script");
tmp = sexpr_node(node, "device/vif/bridge");
@ -4433,5 +4499,110 @@ error:
return (ret);
}
struct check_path_data {
const char *path;
int ok;
};
static int
check_path (virConnectPtr conn ATTRIBUTE_UNUSED, void *vp,
int isBlock ATTRIBUTE_UNUSED,
int cdrom, int isNoSrcCdrom,
int hvm ATTRIBUTE_UNUSED,
const char *drvName ATTRIBUTE_UNUSED,
const char *drvType ATTRIBUTE_UNUSED,
const char *src, const char *dst ATTRIBUTE_UNUSED,
const char *mode ATTRIBUTE_UNUSED)
{
struct check_path_data *data = (struct check_path_data *) vp;
if (!isNoSrcCdrom && !cdrom && src && STREQ (src, data->path))
data->ok = 1;
return 0;
}
/**
* xenDaemonDomainBlockPeek:
* @dom: domain object
* @path: path to the file or device
* @offset: offset
* @size: size
* @buffer: return buffer
*
* Returns 0 if successful, -1 if error, -2 if declined.
*/
int
xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path,
unsigned long long offset, size_t size,
void *buffer)
{
xenUnifiedPrivatePtr priv;
struct sexpr *root;
struct check_path_data data;
int fd, ret = -1;
struct stat statbuf;
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
if (domain->id < 0 && priv->xendConfigVersion < 3)
return -2; /* Decline, allow XM to handle it. */
/* Security check: The path must correspond to a block device. */
if (domain->id > 0)
root = sexpr_get (domain->conn, "/xend/domain/%d?detail=1",
domain->id);
else if (domain->id < 0)
root = sexpr_get (domain->conn, "/xend/domain/%s?detail=1",
domain->name);
else {
/* This call always fails for dom0. */
virXendError (domain->conn, VIR_ERR_NO_SUPPORT,
_("domainBlockPeek is not supported for dom0"));
return -1;
}
if (!root) {
virXendError (domain->conn, VIR_ERR_XEN_CALL, __FUNCTION__);
return -1;
}
data.path = path;
data.ok = 0;
if (xend_parse_sexp_blockdevs (domain->conn, root,
priv->xendConfigVersion,
check_path, &data) == -1)
return -1;
if (!data.ok) {
virXendError (domain->conn, VIR_ERR_INVALID_ARG,
_("invalid path"));
return -1;
}
/* The path is correct, now try to open it and get its size. */
fd = open (path, O_RDONLY);
if (fd == -1 || fstat (fd, &statbuf) == -1) {
virXendError (domain->conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
goto done;
}
/* Seek and read. */
/* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
* be 64 bits on all platforms.
*/
if (lseek (fd, offset, SEEK_SET) == (off_t) -1 ||
saferead (fd, buffer, size) == (ssize_t) -1) {
virXendError (domain->conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
goto done;
}
ret = 0;
done:
if (fd >= 0) close (fd);
return ret;
}
#endif /* ! PROXY */
#endif /* WITH_XEN */

View File

@ -244,6 +244,8 @@ virDomainPtr xenDaemonLookupByName(virConnectPtr conn, const char *domname);
int xenDaemonDomainMigratePrepare (virConnectPtr dconn, char **cookie, int *cookielen, const char *uri_in, char **uri_out, unsigned long flags, const char *dname, unsigned long resource);
int xenDaemonDomainMigratePerform (virDomainPtr domain, const char *cookie, int cookielen, const char *uri, unsigned long flags, const char *dname, unsigned long resource);
int xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path, unsigned long long offset, size_t size, void *buffer);
#ifdef __cplusplus
}
#endif

View File

@ -3241,4 +3241,15 @@ xenXMDomainDetachDevice(virDomainPtr domain, const char *xml) {
return (ret);
}
int
xenXMDomainBlockPeek (virDomainPtr dom,
const char *path ATTRIBUTE_UNUSED,
unsigned long long offset ATTRIBUTE_UNUSED,
size_t size ATTRIBUTE_UNUSED,
void *buffer ATTRIBUTE_UNUSED)
{
xenXMError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
return -1;
}
#endif /* WITH_XEN */

View File

@ -60,6 +60,7 @@ int xenXMDomainUndefine(virDomainPtr domain);
virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml);
char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf);
int xenXMDomainBlockPeek (virDomainPtr dom, const char *path, unsigned long long offset, size_t size, void *buffer);
#ifdef __cplusplus
}

View File

@ -15,17 +15,17 @@
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<disk type='file' device='disk'>
<driver name='tap' type='aio'/>
<source file='/xen/rhel5.img'/>
<target dev='xvda' bus='xen'/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
<target dev='vif5.0'/>
<mac address='00:16:3e:1d:06:15'/>
<script path='vif-bridge'/>
</interface>
<disk type='file' device='disk'>
<driver name='tap' type='aio'/>
<source file='/xen/rhel5.img'/>
<target dev='xvda' bus='xen'/>
</disk>
<input type='mouse' bus='xen'/>
<graphics type='vnc' port='-1'/>
<console type='pty'>

View File

@ -20,11 +20,6 @@
<clock offset='utc'/>
<devices>
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
<interface type='bridge'>
<source bridge='xenbr0'/>
<target dev='vif6.0'/>
<mac address='00:16:3e:0a:7b:39'/>
</interface>
<disk type='block' device='disk'>
<driver name='phy'/>
<source dev='/dev/sda8'/>
@ -34,6 +29,11 @@
<target dev='hdc' bus='ide'/>
<readonly/>
</disk>
<interface type='bridge'>
<source bridge='xenbr0'/>
<target dev='vif6.0'/>
<mac address='00:16:3e:0a:7b:39'/>
</interface>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1'/>
<serial type='pty'>