[libvirt] [PATCH] fix typo in lxc_driver.c and virsh-nodedev.c
by Hongwei Bi
---
src/lxc/lxc_driver.c | 2 +-
tools/virsh-nodedev.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index e3a34d6..870e4a9 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -887,7 +887,7 @@ cleanup:
}
/**
- * lxcDomainCreateWithFlags:
+ * lxcDomainCreateWithFiles:
* @dom: domain to start
* @flags: Must be 0 for now
*
diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c
index 3a2d12b..ebfac94 100644
--- a/tools/virsh-nodedev.c
+++ b/tools/virsh-nodedev.c
@@ -308,7 +308,7 @@ fallback:
goto cleanup;
}
- /* Check if the device's capability matches with provied
+ /* Check if the device's capability matches with provided
* capabilities.
*/
size_t j, k;
--
1.8.1.2
11 years, 2 months
[libvirt] [PATCH] build: Add lxc testcase to dist list
by Daniel Hansel
Introduced by commit 3f029fb5319b9dc9cc2fbf8d1ba4505ee9e4b1e3 the RPM build
was broken due to a missing LXC textcase.
Signed-off-by: Daniel Hansel <daniel.hansel(a)linux.vnet.ibm.com>
---
tests/Makefile.am | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 250cd8c..a47d376 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -69,6 +69,7 @@ EXTRA_DIST = \
fchostdata \
interfaceschemadata \
lxcxml2xmldata \
+ lxcxml2xmloutdata \
networkschematest \
networkxml2xmlin \
networkxml2xmlout \
--
1.7.9.5
11 years, 2 months
[libvirt] [PATCH] qemu_migrate: Fix assign the same port when migrating concurrently
by Wangyufei (A)
>From f56b290eab36bbb7a9ac53778a55638d473504d1 Mon Sep 17 00:00:00 2001
From: WangYufei <james.wangyufei(a)huawei.com>
Date: Fri, 11 Oct 2013 11:27:13 +0800
Subject: [PATCH] qemu_migrate: Fix assign the same port when migrating concurrently
When we migrate vms concurrently, there's a chance that libvirtd on destination assign the same port for different migrations, which will lead to migration failed during migration prepare phase on destination. So we use virPortAllocator here to solve the problem.
Signed-off-by: WangYufei <james.wangyufei(a)huawei.com>
---
src/qemu/qemu_command.h | 3 +++
src/qemu/qemu_conf.h | 6 +++---
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_driver.c | 6 ++++++
src/qemu/qemu_migration.c | 28 +++++++++++++++++++++-------
5 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 2e2acfb..3277ba4 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -51,6 +51,9 @@
# define QEMU_WEBSOCKET_PORT_MIN 5700
# define QEMU_WEBSOCKET_PORT_MAX 65535
+# define QEMU_MIGRATION_PORT_MIN 49152
+# define QEMU_MIGRATION_PORT_MAX 49215
+
typedef struct _qemuBuildCommandLineCallbacks qemuBuildCommandLineCallbacks;
typedef qemuBuildCommandLineCallbacks *qemuBuildCommandLineCallbacksPtr;
struct _qemuBuildCommandLineCallbacks {
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index da29a2a..3176085 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -221,6 +221,9 @@ struct _virQEMUDriver {
/* Immutable pointer, self-locking APIs */
virPortAllocatorPtr webSocketPorts;
+ /* Immutable pointer, self-locking APIs */
+ virPortAllocatorPtr migrationPorts;
+
/* Immutable pointer, lockless APIs*/
virSysinfoDefPtr hostsysinfo;
@@ -242,9 +245,6 @@ struct _qemuDomainCmdlineDef {
char **env_value;
};
-/* Port numbers used for KVM migration. */
-# define QEMUD_MIGRATION_FIRST_PORT 49152
-# define QEMUD_MIGRATION_NUM_PORTS 64
void qemuDomainCmdlineDefFree(qemuDomainCmdlineDefPtr def);
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 21f116c..16c55a6 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -160,6 +160,7 @@ struct _qemuDomainObjPrivate {
unsigned long migMaxBandwidth;
char *origname;
int nbdPort; /* Port used for migration with NBD */
+ int migrationPort;
virChrdevsPtr devs;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index cfdbb9a..c08a73c 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -687,6 +687,11 @@ qemuStateInitialize(bool privileged,
cfg->webSocketPortMax)) == NULL)
goto error;
+ if ((qemu_driver->migrationPorts =
+ virPortAllocatorNew(QEMU_MIGRATION_PORT_MIN,
+ QEMU_MIGRATION_PORT_MAX)) == NULL)
+ goto error;
+
if (qemuSecurityInit(qemu_driver) < 0)
goto error;
@@ -993,6 +998,7 @@ qemuStateCleanup(void) {
virObjectUnref(qemu_driver->domains);
virObjectUnref(qemu_driver->remotePorts);
virObjectUnref(qemu_driver->webSocketPorts);
+ virObjectUnref(qemu_driver->migrationPorts);
virObjectUnref(qemu_driver->xmlopt);
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 3a1aab7..93ae237 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2147,6 +2147,9 @@ qemuMigrationPrepareCleanup(virQEMUDriverPtr driver,
qemuDomainJobTypeToString(priv->job.active),
qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
+ virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
+ priv->migrationPort = 0;
+
if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
return;
qemuDomainObjDiscardAsyncJob(driver, vm);
@@ -2297,6 +2300,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
*def = NULL;
priv = vm->privateData;
+ priv->migrationPort = port;
if (VIR_STRDUP(priv->origname, origname) < 0)
goto cleanup;
@@ -2415,6 +2419,11 @@ cleanup:
VIR_FREE(xmlout);
VIR_FORCE_CLOSE(dataFD[0]);
VIR_FORCE_CLOSE(dataFD[1]);
+ if (ret < 0) {
+ virPortAllocatorRelease(driver->migrationPorts, port);
+ if (priv)
+ priv->migrationPort = 0;
+ }
if (vm) {
if (ret >= 0 || vm->persistent)
virObjectUnlock(vm);
@@ -2493,7 +2502,6 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
const char *origname,
unsigned long flags)
{
- static int port = 0;
int this_port;
char *hostname = NULL;
const char *p;
@@ -2521,8 +2529,9 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
* to be a correct hostname which refers to the target machine).
*/
if (uri_in == NULL) {
- this_port = QEMUD_MIGRATION_FIRST_PORT + port++;
- if (port == QEMUD_MIGRATION_NUM_PORTS) port = 0;
+ if (virPortAllocatorAcquire(driver->migrationPorts,
+ (unsigned short *)&this_port) < 0)
+ goto cleanup;
/* Get hostname */
if ((hostname = virGetHostname()) == NULL)
@@ -2578,9 +2587,9 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
if (uri->port == 0) {
/* Generate a port */
- this_port = QEMUD_MIGRATION_FIRST_PORT + port++;
- if (port == QEMUD_MIGRATION_NUM_PORTS)
- port = 0;
+ if (virPortAllocatorAcquire(driver->migrationPorts,
+ (unsigned short *)&this_port) < 0)
+ goto cleanup;
/* Caller frees */
if (virAsprintf(uri_out, "%s:%d", uri_in, this_port) < 0)
@@ -2600,8 +2609,11 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
cleanup:
virURIFree(uri);
VIR_FREE(hostname);
- if (ret != 0)
+ if (ret != 0) {
VIR_FREE(*uri_out);
+ virPortAllocatorRelease(driver->migrationPorts,
+ (unsigned short)this_port);
+ }
return ret;
}
@@ -4370,6 +4382,8 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
}
qemuMigrationStopNBDServer(driver, vm, mig);
+ virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
+ priv->migrationPort = 0;
if (flags & VIR_MIGRATE_PERSIST_DEST) {
virDomainDefPtr vmdef;
--
1.7.3.1.msysgit.0
Best Regards,
-WangYufei
11 years, 2 months
[libvirt] [RFC] net-dhcp-leases: virNetworkDHCPLeases struct design
by Nehal J Wani
Continued from https://www.redhat.com/archives/libvir-list/2013-October/msg00325.html
Earlier, the virNetworkDHCPLeases struct design was:
struct _virNetworkDHCPLeases {
long long expirytime; /* Seconds since epoch */
union {
char *mac; /* MAC address */
unsigned long iaid; /* Identity association identifier (IAID) */
} id;
char *ipaddr; /* IP address */
char *hostname; /* Hostname */
char *clientid; /* Client ID or DUID */
int type; /* virIPAddrType */
unsigned int prefix; /* IP address prefix */
};
Since no one likes the idea of having a union, but we do want to
support dhcpv6, following is the new design:
struct _virNetworkDHCPLeases {
char *interface; /* Network interface name (non-null) */
long long expirytime; /* Seconds since epoch (non-null) */
int type; /* virIPAddrType (non-null) */
unsigned int prefix; /* IP address prefix (non-null) */
char *mac; /* MAC address (mostly non-null,
except rare cases) */
char *iaid; /* IAID (ipv6) (null, in case of ipv4) */
char *ipaddr; /* IP address (non-null) */
char *hostname; /* Hostname (can be null) */
char *clientid; /* Client ID(ipv4) or DUID(ipv6) (can
be null, in case of ipv4) */
};
--
Nehal J Wani
11 years, 2 months
[libvirt] [PATCH] rpc: Correct the wrong payload size checking
by Osier Yang
<...>
/* Size of message length field. Not counted in VIR_NET_MESSAGE_MAX
* and VIR_NET_MESSAGE_INITIAL.
*/
const VIR_NET_MESSAGE_LEN_MAX = 4;
</...>
However, msg->bufferLength includes the length word. The wrong checking
was introduced by commit e914dcfd.
* src/rpc/virnetmessage.c:
- Correct the checking in virNetMessageEncodePayloadRaw
- Use a new variable to track the new payload length in
virNetMessageEncodePayloadRaw
---
src/rpc/virnetmessage.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/src/rpc/virnetmessage.c b/src/rpc/virnetmessage.c
index 8f4e4bc..4c60424 100644
--- a/src/rpc/virnetmessage.c
+++ b/src/rpc/virnetmessage.c
@@ -346,15 +346,17 @@ int virNetMessageEncodePayload(virNetMessagePtr msg,
/* Try to encode the payload. If the buffer is too small increase it. */
while (!(*filter)(&xdr, data)) {
- if ((msg->bufferLength - VIR_NET_MESSAGE_LEN_MAX) * 4 > VIR_NET_MESSAGE_MAX) {
+ unsigned int newlen = (msg->bufferLength - VIR_NET_MESSAGE_LEN_MAX) * 4 +
+ VIR_NET_MESSAGE_LEN_MAX;
+
+ if (newlen > VIR_NET_MESSAGE_MAX + VIR_NET_MESSAGE_LEN_MAX) {
virReportError(VIR_ERR_RPC, "%s", _("Unable to encode message payload"));
goto error;
}
xdr_destroy(&xdr);
- msg->bufferLength = (msg->bufferLength - VIR_NET_MESSAGE_LEN_MAX) * 4 +
- VIR_NET_MESSAGE_LEN_MAX;
+ msg->bufferLength = newlen;
if (VIR_REALLOC_N(msg->buffer, msg->bufferLength) < 0)
goto error;
@@ -426,10 +428,15 @@ int virNetMessageEncodePayloadRaw(virNetMessagePtr msg,
/* If the message buffer is too small for the payload increase it accordingly. */
if ((msg->bufferLength - msg->bufferOffset) < len) {
- if ((msg->bufferOffset + len) > VIR_NET_MESSAGE_MAX) {
+ if ((msg->bufferOffset + len) >
+ VIR_NET_MESSAGE_MAX + VIR_NET_MESSAGE_LEN_MAX) {
virReportError(VIR_ERR_RPC,
- _("Stream data too long to send (%zu bytes needed, %zu bytes available)"),
- len, (VIR_NET_MESSAGE_MAX - msg->bufferOffset));
+ _("Stream data too long to send "
+ "(%zu bytes needed, %zu bytes available)"),
+ len,
+ VIR_NET_MESSAGE_MAX +
+ VIR_NET_MESSAGE_LEN_MAX -
+ msg->bufferOffset);
return -1;
}
--
1.8.1.4
11 years, 2 months
[libvirt] [RFC PATCH] storage: initial support for linking with libglfapi
by Eric Blake
We support gluster volumes in domain XML, so we also ought to
support them as a storage pool. Besides, a future patch will
want to take advantage of libgfapi to handle the case of a
gluster device holding qcow2 rather than raw storage, and for
that to work, we need a storage backend that can read gluster
storage volume contents. This sets up the framework.
* configure.ac (WITH_STORAGE_GLUSTER): New conditional.
* libvirt.spec.in (BuildRequires): Support it in spec file.
* src/conf/storage_conf.h (VIR_STORAGE_POOL_GLUSTER): New pool
type.
* src/conf/storage_conf.c (poolTypeInfo): Treat similar to
sheepdog and rbd.
* src/storage/storage_backend_gluster.h: New file.
* src/storage/storage_backend_gluster.c: Likewise.
* src/storage/storage_backend.c (backends): Register new type.
* src/Makefile.am (STORAGE_DRIVER_GLUSTER_SOURCES): Build new files.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
I'm interested in a couple of things beyond this patch:
representing a storage pool on top of gluster, and improving
the libvirt backing chain detection to allow a gluster pool
to contain qcow2 rather than raw format data (ie. where one
gluster image can call out another gluster file as its backing,
rather than forcefully treating all network files as raw).
Without at least one of those working, this patch should not
be applied in isolation. But I figured early review is
better to make sure I'm on track.
configure.ac | 32 ++++++++++++++++++++++++++++++++
libvirt.spec.in | 15 +++++++++++++++
src/Makefile.am | 9 +++++++++
src/conf/storage_conf.c | 13 ++++++++++++-
src/conf/storage_conf.h | 3 ++-
src/storage/storage_backend.c | 6 ++++++
src/storage/storage_backend_gluster.c | 35 +++++++++++++++++++++++++++++++++++
src/storage/storage_backend_gluster.h | 29 +++++++++++++++++++++++++++++
8 files changed, 140 insertions(+), 2 deletions(-)
create mode 100644 src/storage/storage_backend_gluster.c
create mode 100644 src/storage/storage_backend_gluster.h
diff --git a/configure.ac b/configure.ac
index 1993fab..3b7fde7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -118,6 +118,7 @@ PARTED_REQUIRED="1.8.0"
DEVMAPPER_REQUIRED=1.0.0
LIBPCAP_REQUIRED="1.0.0"
LIBNL_REQUIRED="1.1"
+GLFS_REQUIRED="3.0"
dnl Checks for C compiler.
AC_PROG_CC
@@ -1646,6 +1647,10 @@ AC_ARG_WITH([storage-sheepdog],
[AS_HELP_STRING([--with-storage-sheepdog],
[with Sheepdog backend for the storage driver @<:@default=check@:>@])],
[],[with_storage_sheepdog=check])
+AC_ARG_WITH([storage-gluster],
+ [AS_HELP_STRING([--with-storage-gluster],
+ [with Gluster backend for the storage driver @<:@default=check@:>@])],
+ [],[with_storage_gluster=check])
if test "$with_libvirtd" = "no"; then
with_storage_dir=no
@@ -1657,6 +1662,7 @@ if test "$with_libvirtd" = "no"; then
with_storage_disk=no
with_storage_rbd=no
with_storage_sheepdog=no
+ with_storage_gluster=no
fi
if test "$with_storage_dir" = "yes" ; then
AC_DEFINE_UNQUOTED([WITH_STORAGE_DIR], 1, [whether directory backend for storage driver is enabled])
@@ -1858,6 +1864,26 @@ fi
AM_CONDITIONAL([WITH_STORAGE_SHEEPDOG],
[test "$with_storage_sheepdog" = "yes"])
+LIBGLUSTER_LIBS=
+if test "$with_storage_gluster" = "yes" || \
+ test "$with_storage_gluster" = "check"; then
+ PKG_CHECK_MODULES([GLFS], [glusterfs-api >= $GLFS_REQUIRED],
+ [GLFS_FOUND=yes], [GLFS_FOUND=no])
+
+ AC_CHECK_HEADER([glusterfs/api/glfs.h], [GLFS_FOUND=yes; break;])
+
+ if test "$GLFS_FOUND" = "yes"; then
+ with_storage_gluster=yes
+ LIBGLUSTER_LIBS=$GLFS_LIBS
+ AC_DEFINE_UNQUOTED([WITH_STORAGE_GLUSTER], [1],
+ [whether Gluster backend for storage driver is enabled])
+ else
+ with_storage_gluster=no
+ fi
+fi
+AM_CONDITIONAL([WITH_STORAGE_GLUSTER], [test "$with_storage_gluster" = "yes"])
+AC_SUBST([LIBGLUSTER_LIBS])
+
LIBPARTED_CFLAGS=
LIBPARTED_LIBS=
@@ -2670,6 +2696,7 @@ AC_MSG_NOTICE([ mpath: $with_storage_mpath])
AC_MSG_NOTICE([ Disk: $with_storage_disk])
AC_MSG_NOTICE([ RBD: $with_storage_rbd])
AC_MSG_NOTICE([Sheepdog: $with_storage_sheepdog])
+AC_MSG_NOTICE([ Gluster: $with_storage_gluster])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Security Drivers])
AC_MSG_NOTICE([])
@@ -2769,6 +2796,11 @@ AC_MSG_NOTICE([ rbd: $LIBRBD_LIBS])
else
AC_MSG_NOTICE([ rbd: no])
fi
+if test "$with_storage_gluster" = "yes" ; then
+AC_MSG_NOTICE([ gluster: $LIBGLUSTER_LIBS])
+else
+AC_MSG_NOTICE([ gluster: no])
+fi
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Test suite])
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 7abc315..0917d59 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -98,6 +98,11 @@
%else
%define with_storage_sheepdog 0
%endif
+%if 0%{?fedora} >= 19
+ %define with_storage_gluster 0%{!?_without_storage_gluster:%{server_drivers}}
+%else
+ %define with_storage_gluster 0
+%endif
%define with_numactl 0%{!?_without_numactl:%{server_drivers}}
%define with_selinux 0%{!?_without_selinux:%{server_drivers}}
@@ -281,6 +286,7 @@
%define with_storage_mpath 0
%define with_storage_rbd 0
%define with_storage_sheepdog 0
+ %define with_storage_gluster 0
%define with_storage_disk 0
%endif
@@ -555,6 +561,10 @@ BuildRequires: device-mapper-devel
BuildRequires: ceph-devel
%endif
%endif
+%if %{with_storage_gluster}
+BuildRequires: glusterfs-api-devel
+BuildRequires: glusterfs-devel
+%endif
%if %{with_numactl}
# For QEMU/LXC numa info
BuildRequires: numactl-devel
@@ -1265,6 +1275,10 @@ of recent versions of Linux (and other OSes).
%define _without_storage_sheepdog --without-storage-sheepdog
%endif
+%if ! %{with_storage_gluster}
+ %define _without_storage_gluster --without-storage-gluster
+%endif
+
%if ! %{with_numactl}
%define _without_numactl --without-numactl
%endif
@@ -1387,6 +1401,7 @@ of recent versions of Linux (and other OSes).
%{?_without_storage_mpath} \
%{?_without_storage_rbd} \
%{?_without_storage_sheepdog} \
+ %{?_without_storage_gluster} \
%{?_without_numactl} \
%{?_without_numad} \
%{?_without_capng} \
diff --git a/src/Makefile.am b/src/Makefile.am
index e58d408..bfdb07a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -815,6 +815,9 @@ STORAGE_DRIVER_RBD_SOURCES = \
STORAGE_DRIVER_SHEEPDOG_SOURCES = \
storage/storage_backend_sheepdog.h storage/storage_backend_sheepdog.c
+STORAGE_DRIVER_GLUSTER_SOURCES = \
+ storage/storage_backend_gluster.h storage/storage_backend_gluster.c
+
STORAGE_HELPER_DISK_SOURCES = \
storage/parthelper.c
@@ -1429,6 +1432,11 @@ if WITH_STORAGE_SHEEPDOG
libvirt_driver_storage_impl_la_SOURCES += $(STORAGE_DRIVER_SHEEPDOG_SOURCES)
endif WITH_STORAGE_SHEEPDOG
+if WITH_STORAGE_GLUSTER
+libvirt_driver_storage_impl_la_SOURCES += $(STORAGE_DRIVER_GLUSTER_SOURCES)
+libvirt_driver_storage_impl_la_LIBADD += $(LIBGLUSTER_LIBS)
+endif WITH_STORAGE_GLUSTER
+
if WITH_NODE_DEVICES
# Needed to keep automake quiet about conditionals
if WITH_DRIVER_MODULES
@@ -1629,6 +1637,7 @@ EXTRA_DIST += \
$(STORAGE_DRIVER_DISK_SOURCES) \
$(STORAGE_DRIVER_RBD_SOURCES) \
$(STORAGE_DRIVER_SHEEPDOG_SOURCES) \
+ $(STORAGE_DRIVER_GLUSTER_SOURCES) \
$(NODE_DEVICE_DRIVER_SOURCES) \
$(NODE_DEVICE_DRIVER_HAL_SOURCES) \
$(NODE_DEVICE_DRIVER_UDEV_SOURCES) \
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 975e662..bcef0b3 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -55,7 +55,7 @@ VIR_ENUM_IMPL(virStoragePool,
VIR_STORAGE_POOL_LAST,
"dir", "fs", "netfs",
"logical", "disk", "iscsi",
- "scsi", "mpath", "rbd", "sheepdog")
+ "scsi", "mpath", "rbd", "sheepdog", "gluster")
VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
VIR_STORAGE_POOL_FS_LAST,
@@ -244,6 +244,17 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
.formatToString = virStoragePoolFormatDiskTypeToString,
}
},
+ {.poolType = VIR_STORAGE_POOL_GLUSTER,
+ .poolOptions = {
+ .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
+ VIR_STORAGE_POOL_SOURCE_NETWORK |
+ VIR_STORAGE_POOL_SOURCE_NAME),
+ },
+ .volOptions = {
+ .defaultFormat = VIR_STORAGE_FILE_RAW,
+ .formatToString = virStoragePoolFormatDiskTypeToString,
+ }
+ },
{.poolType = VIR_STORAGE_POOL_MPATH,
.volOptions = {
.formatToString = virStoragePoolFormatDiskTypeToString,
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 62ff1fd..251e897 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -1,7 +1,7 @@
/*
* storage_conf.h: config handling for storage driver
*
- * Copyright (C) 2006-2008, 2010-2012 Red Hat, Inc.
+ * Copyright (C) 2006-2008, 2010-2013 Red Hat, Inc.
* Copyright (C) 2006-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -128,6 +128,7 @@ enum virStoragePoolType {
VIR_STORAGE_POOL_MPATH, /* Multipath devices */
VIR_STORAGE_POOL_RBD, /* RADOS Block Device */
VIR_STORAGE_POOL_SHEEPDOG, /* Sheepdog device */
+ VIR_STORAGE_POOL_GLUSTER, /* Gluster device */
VIR_STORAGE_POOL_LAST,
};
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index c21e6ea..8f30ce2 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -80,6 +80,9 @@
#if WITH_STORAGE_SHEEPDOG
# include "storage_backend_sheepdog.h"
#endif
+#if WITH_STORAGE_GLUSTER
+# include "storage_backend_gluster.h"
+#endif
#define VIR_FROM_THIS VIR_FROM_STORAGE
@@ -112,6 +115,9 @@ static virStorageBackendPtr backends[] = {
#if WITH_STORAGE_SHEEPDOG
&virStorageBackendSheepdog,
#endif
+#if WITH_STORAGE_GLUSTER
+ &virStorageBackendGluster,
+#endif
NULL
};
diff --git a/src/storage/storage_backend_gluster.c b/src/storage/storage_backend_gluster.c
new file mode 100644
index 0000000..deb44dc
--- /dev/null
+++ b/src/storage/storage_backend_gluster.c
@@ -0,0 +1,35 @@
+/*
+ * storage_backend_gluster.c: storage backend for Gluster handling
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include <glusterfs/api/glfs.h>
+
+#include "virerror.h"
+#include "storage_backend_gluster.h"
+#include "storage_conf.h"
+
+#define VIR_FROM_THIS VIR_FROM_STORAGE
+
+
+virStorageBackend virStorageBackendGluster = {
+ .type = VIR_STORAGE_POOL_GLUSTER,
+};
diff --git a/src/storage/storage_backend_gluster.h b/src/storage/storage_backend_gluster.h
new file mode 100644
index 0000000..b21bda7
--- /dev/null
+++ b/src/storage/storage_backend_gluster.h
@@ -0,0 +1,29 @@
+/*
+ * storage_backend_gluster.h: storage backend for Gluster handling
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __VIR_STORAGE_BACKEND_GLUSTER_H__
+# define __VIR_STORAGE_BACKEND_GLUSTER_H__
+
+# include "storage_backend.h"
+
+extern virStorageBackend virStorageBackendGluster;
+
+#endif /* __VIR_STORAGE_BACKEND_GLUSTER_H__ */
--
1.8.3.1
11 years, 2 months
[libvirt] [PATCH] Convert uuid to a string before printing it
by Ján Tomko
Introduced by 1fa7946.
https://bugzilla.redhat.com/show_bug.cgi?id=1019023
---
src/qemu/qemu_command.c | 6 ++++--
src/storage/storage_backend_iscsi.c | 8 ++++++--
src/storage/storage_backend_rbd.c | 4 ++--
3 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 22cc5f2..af6c89e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3183,11 +3183,13 @@ qemuGetSecretString(virConnectPtr conn,
size_t secret_size;
virSecretPtr sec = NULL;
char *secret = NULL;
+ char uuidStr[VIR_UUID_STRING_BUFLEN];
/* look up secret */
switch (diskSecretType) {
case VIR_DOMAIN_DISK_SECRET_TYPE_UUID:
sec = virSecretLookupByUUID(conn, uuid);
+ virUUIDFormat(uuid, uuidStr);
break;
case VIR_DOMAIN_DISK_SECRET_TYPE_USAGE:
sec = virSecretLookupByUsage(conn, secretUsageType, usage);
@@ -3198,7 +3200,7 @@ qemuGetSecretString(virConnectPtr conn,
if (diskSecretType == VIR_DOMAIN_DISK_SECRET_TYPE_UUID) {
virReportError(VIR_ERR_NO_SECRET,
_("%s no secret matches uuid '%s'"),
- scheme, uuid);
+ scheme, uuidStr);
} else {
virReportError(VIR_ERR_NO_SECRET,
_("%s no secret matches usage value '%s'"),
@@ -3214,7 +3216,7 @@ qemuGetSecretString(virConnectPtr conn,
virReportError(VIR_ERR_INTERNAL_ERROR,
_("could not get value of the secret for "
"username '%s' using uuid '%s'"),
- username, uuid);
+ username, uuidStr);
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("could not get value of the secret for "
diff --git a/src/storage/storage_backend_iscsi.c b/src/storage/storage_backend_iscsi.c
index e71ea46..556c2cc 100644
--- a/src/storage/storage_backend_iscsi.c
+++ b/src/storage/storage_backend_iscsi.c
@@ -44,6 +44,7 @@
#include "virobject.h"
#include "virrandom.h"
#include "virstring.h"
+#include "viruuid.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
@@ -702,6 +703,7 @@ virStorageBackendISCSISetAuth(const char *portal,
unsigned char *secret_value = NULL;
virStoragePoolAuthChap chap;
int ret = -1;
+ char uuidStr[VIR_UUID_STRING_BUFLEN];
if (def->source.authType == VIR_STORAGE_POOL_AUTH_NONE)
return 0;
@@ -733,10 +735,11 @@ virStorageBackendISCSISetAuth(const char *portal,
VIR_SECRET_GET_VALUE_INTERNAL_CALL);
if (!secret_value) {
if (chap.secret.uuidUsable) {
+ virUUIDFormat(chap.secret.uuid, uuidStr);
virReportError(VIR_ERR_INTERNAL_ERROR,
_("could not get the value of the secret "
"for username %s using uuid '%s'"),
- chap.username, chap.secret.uuid);
+ chap.username, uuidStr);
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("could not get the value of the secret "
@@ -747,9 +750,10 @@ virStorageBackendISCSISetAuth(const char *portal,
}
} else {
if (chap.secret.uuidUsable) {
+ virUUIDFormat(chap.secret.uuid, uuidStr);
virReportError(VIR_ERR_NO_SECRET,
_("no secret matches uuid '%s'"),
- chap.secret.uuid);
+ uuidStr);
} else {
virReportError(VIR_ERR_NO_SECRET,
_("no secret matches usage value '%s'"),
diff --git a/src/storage/storage_backend_rbd.c b/src/storage/storage_backend_rbd.c
index d9e1789..60b48c2 100644
--- a/src/storage/storage_backend_rbd.c
+++ b/src/storage/storage_backend_rbd.c
@@ -94,7 +94,7 @@ static int virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr *ptr,
if (pool->def->source.auth.cephx.secret.uuidUsable) {
virReportError(VIR_ERR_NO_SECRET,
_("no secret matches uuid '%s'"),
- pool->def->source.auth.cephx.secret.uuid);
+ secretUuid);
} else {
virReportError(VIR_ERR_NO_SECRET,
_("no secret matches usage value '%s'"),
@@ -112,7 +112,7 @@ static int virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr *ptr,
_("could not get the value of the secret "
"for username '%s' using uuid '%s'"),
pool->def->source.auth.cephx.username,
- pool->def->source.auth.cephx.secret.uuid);
+ secretUuid);
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("could not get the value of the secret "
--
1.8.1.5
11 years, 2 months
[libvirt] [PATCH 0/2] enable attatch-disk command option '--mode' accept two parameters
by Chen Hanxiao
From: Chen Hanxiao <chenhanxiao(a)cn.fujitsu.com>
This patch set enable '--mode' accept
both 'readonly' and 'shareable' at the same time.
And remove duplicate option '--shareable'
Chen Hanxiao (2):
[libvirt]virsh: enable attatch-disk command option '--mode' accept two
parameters
[libvirt]virsh: remove attach-disk '--shareable' option
tools/virsh-domain.c | 29 +++++++++++++++++++----------
tools/virsh.pod | 5 ++---
2 files changed, 21 insertions(+), 13 deletions(-)
--
1.8.2.1
11 years, 2 months
[libvirt] [PATCH] Add some notes about secure usage of libvirt
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Start a page describing some of the things that applications
using libvirt need to bear in mind to ensure security of their
systems.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
docs/secureusage.html.in | 169 +++++++++++++++++++++++++++++++++++++++++++++++
docs/sitemap.html.in | 4 ++
2 files changed, 173 insertions(+)
create mode 100644 docs/secureusage.html.in
diff --git a/docs/secureusage.html.in b/docs/secureusage.html.in
new file mode 100644
index 0000000..998a692
--- /dev/null
+++ b/docs/secureusage.html.in
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <body>
+
+ <h1>Secure Usage of Libvirt</h1>
+
+ <ul id="toc"></ul>
+
+ <p>
+ This page details information that application developers and
+ administrators of libvirt should be aware of when working with
+ libvirt, that may have a bearing on security of the system.
+ </p>
+
+
+ <h2><a name="diskimage">Disk image handling</a></h2>
+
+ <h3><a name="diskimageformat">Disk image format probing</a></h3>
+
+ <p>
+ Historically there have been multiple flaws in QEMU and most
+ projects using QEMUs, related to handling of disk formats.
+ The problems occur when a guest is given a virtual disk backed
+ by raw disk format on the host. If the management application
+ on the host tries to auto-detect / probe the disk format, it
+ is vulnerable to a malicious guest which can write a qcow2
+ file header into its raw disk. If the management application
+ subsequently probes the disk, it will see it as a 'qcow2' disk
+ instead of a 'raw' disk. Since 'qcow2' disks can have a copy
+ on write backing file, such flaw can be leveraged to read
+ arbitrary files on the host. The same type of flaw may occur
+ if the management application allows users to upload pre-created
+ raw images
+ </p>
+
+ <p>
+ <strong>Recommendation:</strong> never attempt to automatically
+ detect the format of a disk image based on file contents which
+ are accessible to / originate from an untrusted source.
+ </p>
+
+ <h3><a name="diskimagebacking">Disk image backing files</a></h3>
+
+ <p>
+ If a management application allows users to upload pre-created
+ disk images in non-raw formats, it can be tricked into giving
+ the user access to arbitrary host files via the copy-on-write
+ backing file feature. This is because the qcow2 disk format
+ header contains a filename field which can point to any location.
+ It can also point to network protocols such as NBD, HTTP, GlusterFS,
+ RBD and more. This could allow for compromise of almost arbitrary
+ data accessible on the LAN/WAN.
+ </p>
+
+ <p>
+ <strong>Recommendation:</strong> always validate that a disk
+ image originating from an untrusted source has no backing
+ file set. If a backing file is seen, reject the image.
+ </p>
+
+ <h3><a name="diskimagesize">Disk image size validation</a></h3>
+
+ <p>
+ If an application allows users to upload pre-created disk
+ images in non-raw formats, it is essential to validate the
+ logical disk image size, rather than the physical disk
+ image size. Non-raw disk images have a grow-on-demand
+ capability, so a user can provide a qcow2 image that may
+ be only 1 MB in size, but is configured to grow to many
+ TB in size.
+ </p>
+
+ <p>
+ <strong>Recommendation:</strong> if receiving a non-raw disk
+ image from an untrusted source, validate the logical image
+ size stored in the disk image metadata against some finite
+ limit.
+ </p>
+
+ <h3><a name="diskimageaccess">Disk image data access</a></h3>
+
+ <p>
+ If an untrusted disk image is ever mounted on the host OS by
+ a management application or administrator, this opens an
+ avenue of attacker with which to potentially compromise the
+ host kernel. Filesystem drivers in OS kernels are often very
+ complex code and thus may have bugs lurking in them. With
+ Linux, there are a large number of filesystem drivers, many
+ of which attract little security analysis attention. Linux
+ will helpfull probe filesystem formats if not told to use an
+ explicit format, allowing an attacker the ability to target
+ specific weak filesystem drivers. Even commonly used and
+ widely audited filesystems such as <code>ext4</code> have had
+ <a href="https://lwn.net/Articles/538898/">bugs lurking in them</a>
+ undetected for years at a time.
+ </p>
+
+ <p>
+ <strong>Recommendation:</strong> if there is a need to access
+ the content of a disk image, use a single-use throwaway virtual
+ machine to access the data. Never mount disk images on the host
+ OS. Ideally make use of the <a href="http://libguestfs.org">libguestfs</a>
+ tools and APIs for accessing disks
+ </p>
+
+ <h2><a name="migration">Guest migration network</a></h2>
+
+ <p>
+ Most hypervisors with support for guest migration between hosts
+ make use of one (or more) network connections. Typically the source
+ host will connect to some port on the target host to initiate the
+ migration. There may be separate connections for co-ordinating the
+ migration, transferring memory state and transferring storage.
+ If the network over which migration takes place is accessible the
+ guest, or client applications, there is potential for data leakage
+ via packet snooping/capture. It is also possible for a malicious
+ guest or client to make attempts to connect to the target host
+ to trigger bogus migration operations, or at least inflict a denial
+ of service attack.
+ </p>
+
+ <p>
+ <strong>Recommendations:</strong> there are several things to consider
+ when performing migration
+ </p>
+
+ <ul>
+ <li>Use a specific address for establishing the migration
+ connection which is accessible only to the virtualization
+ hosts themselves, not libvirt clients or virtual guests.
+ Most hypervisors allow the mgmt application to provide
+ the IP address of the target host as a way to
+ determine which network migration takes place on</li>
+ <li>Use an encrypted migration protocol. Some hypervisors
+ have support for encrypting the migration memory/storage
+ data. In other cases it can be tunnelled over the libvirtd
+ RPC protocol connections.</li>
+ <li>Use a specific address for listening for incoming migration
+ connections which is accessible only to the virtualization
+ hosts themselves, not libvirt clients or virtual guests.
+ Most hypervisors allow the mgmt application to configure
+ the IP address on which the target host listens.</li>
+ </ul>
+
+ <h2><a name="storage">Storage encryption</a></h2>
+
+ <p>
+ Virtual disk images will typically contain confidential data
+ belonging to the owner of the virtual machine. It is desirable
+ to protect this against data center administrators as much as
+ possible. For example, a rogue storage administrator may attempt
+ to access disk contents directly from a storage host, or a network
+ administrator/attack may attempt to snoop on data packets relating
+ to storage access. Use of disk encryption on the virtualization
+ host can ensure that only the virtualization host administrator
+ can see the plain text contents of disk images.
+ </p>
+
+ <p>
+ <strong>Recommendation:</strong> make use of storage encryption
+ to protect non-local storage from attack by rogue network /
+ storage administrators or external attackers. This is particularly
+ important if the storage protocol itself does not offer any kind
+ of encryption capabilities.
+ </p>
+
+ </body>
+</html>
diff --git a/docs/sitemap.html.in b/docs/sitemap.html.in
index a8d2177..d821a9e 100644
--- a/docs/sitemap.html.in
+++ b/docs/sitemap.html.in
@@ -136,6 +136,10 @@
<a href="archnode.html">Node Devices</a>
<span>Enumerating host node devices</span>
</li>
+ <li>
+ <a href="secureusage.html">Secure usage</a>
+ <span>Secure usage of the libvirt APIs</span>
+ </li>
</ul>
</li>
<li>
--
1.8.3.1
11 years, 2 months
[libvirt] [PATCH] virsh: move command cpu-baseline from domain group to host group.
by liyang
cpu-baseline command can compute baseline CPU for a set of given CPUs,
I think it should not belong to domain group, but now it belongs to host
group,
so I moved the related source from virsh-domain.c to virsh-host.c
Signed-off-by: Li Yang <liyang.fnst(a)cn.fujitsu.com>
---
tools/virsh-domain.c | 116
-------------------------------------------------
tools/virsh-host.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 117 insertions(+), 116 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 42c9920..8fc6c59 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -6107,116 +6107,6 @@ cleanup:
}
/*
- * "cpu-baseline" command
- */
-static const vshCmdInfo info_cpu_baseline[] = {
- {.name = "help",
- .data = N_("compute baseline CPU")
- },
- {.name = "desc",
- .data = N_("Compute baseline CPU for a set of given CPUs.")
- },
- {.name = NULL}
-};
-
-static const vshCmdOptDef opts_cpu_baseline[] = {
- {.name = "file",
- .type = VSH_OT_DATA,
- .flags = VSH_OFLAG_REQ,
- .help = N_("file containing XML CPU descriptions")
- },
- {.name = "features",
- .type = VSH_OT_BOOL,
- .help = N_("Show features that are part of the CPU model type")
- },
- {.name = NULL}
-};
-
-static bool
-cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd)
-{
- const char *from = NULL;
- bool ret = false;
- char *buffer;
- char *result = NULL;
- char **list = NULL;
- unsigned int flags = 0;
- int count = 0;
-
- xmlDocPtr xml = NULL;
- xmlNodePtr *node_list = NULL;
- xmlXPathContextPtr ctxt = NULL;
- virBuffer buf = VIR_BUFFER_INITIALIZER;
- size_t i;
-
- if (vshCommandOptBool(cmd, "features"))
- flags |= VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES;
-
- if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
- return false;
-
- if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
- return false;
-
- /* add a separate container around the xml */
- virBufferStrcat(&buf, "<container>", buffer, "</container>", NULL);
- if (virBufferError(&buf))
- goto no_memory;
-
- VIR_FREE(buffer);
- buffer = virBufferContentAndReset(&buf);
-
-
- if (!(xml = virXMLParseStringCtxt(buffer, from, &ctxt)))
- goto cleanup;
-
- if ((count = virXPathNodeSet("//cpu[not(ancestor::cpus)]",
- ctxt, &node_list)) == -1)
- goto cleanup;
-
- if (count == 0) {
- vshError(ctl, _("No host CPU specified in '%s'"), from);
- goto cleanup;
- }
-
- list = vshCalloc(ctl, count, sizeof(const char *));
-
- for (i = 0; i < count; i++) {
- if (!(list[i] = virXMLNodeToString(xml, node_list[i]))) {
- vshSaveLibvirtError();
- goto cleanup;
- }
- }
-
- result = virConnectBaselineCPU(ctl->conn,
- (const char **)list, count, flags);
-
- if (result) {
- vshPrint(ctl, "%s", result);
- ret = true;
- }
-
-cleanup:
- xmlXPathFreeContext(ctxt);
- xmlFreeDoc(xml);
- VIR_FREE(result);
- if (list != NULL && count > 0) {
- for (i = 0; i < count; i++)
- VIR_FREE(list[i]);
- }
- VIR_FREE(list);
- VIR_FREE(buffer);
- VIR_FREE(node_list);
-
- return ret;
-
-no_memory:
- vshError(ctl, "%s", _("Out of memory"));
- ret = false;
- goto cleanup;
-}
-
-/*
* "cpu-stats" command
*/
static const vshCmdInfo info_cpu_stats[] = {
@@ -10517,12 +10407,6 @@ const vshCmdDef domManagementCmds[] = {
.flags = 0
},
#endif
- {.name = "cpu-baseline",
- .handler = cmdCPUBaseline,
- .opts = opts_cpu_baseline,
- .info = info_cpu_baseline,
- .flags = 0
- },
{.name = "cpu-compare",
.handler = cmdCPUCompare,
.opts = opts_cpu_compare,
diff --git a/tools/virsh-host.c b/tools/virsh-host.c
index 1d1bb97..b69de7c 100644
--- a/tools/virsh-host.c
+++ b/tools/virsh-host.c
@@ -35,6 +35,7 @@
#include "virbuffer.h"
#include "viralloc.h"
#include "virsh-domain.h"
+#include "virfile.h"
#include "virxml.h"
#include "virtypedparam.h"
#include "virstring.h"
@@ -193,6 +194,116 @@ cleanup:
}
/*
+ * "cpu-baseline" command
+ */
+static const vshCmdInfo info_cpu_baseline[] = {
+ {.name = "help",
+ .data = N_("compute baseline CPU")
+ },
+ {.name = "desc",
+ .data = N_("Compute baseline CPU for a set of given CPUs.")
+ },
+ {.name = NULL}
+};
+
+static const vshCmdOptDef opts_cpu_baseline[] = {
+ {.name = "file",
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_REQ,
+ .help = N_("file containing XML CPU descriptions")
+ },
+ {.name = "features",
+ .type = VSH_OT_BOOL,
+ .help = N_("Show features that are part of the CPU model type")
+ },
+ {.name = NULL}
+};
+
+static bool
+cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd)
+{
+ const char *from = NULL;
+ bool ret = false;
+ char *buffer;
+ char *result = NULL;
+ char **list = NULL;
+ unsigned int flags = 0;
+ int count = 0;
+
+ xmlDocPtr xml = NULL;
+ xmlNodePtr *node_list = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ size_t i;
+
+ if (vshCommandOptBool(cmd, "features"))
+ flags |= VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES;
+
+ if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
+ return false;
+
+ if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
+ return false;
+
+ /* add a separate container around the xml */
+ virBufferStrcat(&buf, "<container>", buffer, "</container>", NULL);
+ if (virBufferError(&buf))
+ goto no_memory;
+
+ VIR_FREE(buffer);
+ buffer = virBufferContentAndReset(&buf);
+
+
+ if (!(xml = virXMLParseStringCtxt(buffer, from, &ctxt)))
+ goto cleanup;
+
+ if ((count = virXPathNodeSet("//cpu[not(ancestor::cpus)]",
+ ctxt, &node_list)) == -1)
+ goto cleanup;
+
+ if (count == 0) {
+ vshError(ctl, _("No host CPU specified in '%s'"), from);
+ goto cleanup;
+ }
+
+ list = vshCalloc(ctl, count, sizeof(const char *));
+
+ for (i = 0; i < count; i++) {
+ if (!(list[i] = virXMLNodeToString(xml, node_list[i]))) {
+ vshSaveLibvirtError();
+ goto cleanup;
+ }
+ }
+
+ result = virConnectBaselineCPU(ctl->conn,
+ (const char **)list, count, flags);
+
+ if (result) {
+ vshPrint(ctl, "%s", result);
+ ret = true;
+ }
+
+cleanup:
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(xml);
+ VIR_FREE(result);
+ if (list != NULL && count > 0) {
+ for (i = 0; i < count; i++)
+ VIR_FREE(list[i]);
+ }
+ VIR_FREE(list);
+ VIR_FREE(buffer);
+ VIR_FREE(node_list);
+
+ return ret;
+
+no_memory:
+ vshError(ctl, "%s", _("Out of memory"));
+ ret = false;
+ goto cleanup;
+}
+
+/*
* "maxvcpus" command
*/
static const vshCmdInfo info_maxvcpus[] = {
@@ -955,6 +1066,12 @@ const vshCmdDef hostAndHypervisorCmds[] = {
.info = info_hostname,
.flags = 0
},
+ {.name = "cpu-baseline",
+ .handler = cmdCPUBaseline,
+ .opts = opts_cpu_baseline,
+ .info = info_cpu_baseline,
+ .flags = 0
+ },
{.name = "maxvcpus",
.handler = cmdMaxvcpus,
.opts = opts_maxvcpus,
--
1.7.1
--
Regards,
--------------------------------------------------
Li Yang
TEL:+86+25-86630566-8529
EMail:liyang.fnst(a)cn.fujitsu.com
--------------------------------------------------
11 years, 2 months