[libvirt] libvirt [PATCHv2 2/2] Add iSCSI backend storage driver for ESX.
by Ata E Husain Bohra
The patch adds the backend driver to support iSCSI format storage pools
and volumes for ESX host. The mapping of ESX iSCSI specifics to Libvirt
is as follows:
1. ESX static iSCSI target <------> Libvirt Storage Pools
2. ESX iSCSI LUNs <------> Libvirt Storage Volumes.
The above understanding is based on http://libvirt.org/storage.html.
The operation supported on iSCSI pools includes:
1. List storage pools & volumes.
2. Get xml descriptor operaion on pools & volumes.
3. Lookup operation on pools & volumes by name, uuid and path (if applicable).
iSCSI pools does not support operations such as: Create / remove pools
and volumes.
---
src/Makefile.am | 1 +
src/esx/esx_storage_backend_iscsi.c | 807 +++++++++++++++++++++++++++++++++++
src/esx/esx_storage_backend_iscsi.h | 29 ++
src/esx/esx_storage_driver.c | 8 +-
src/esx/esx_vi.c | 332 ++++++++++++++
src/esx/esx_vi.h | 18 +
src/esx/esx_vi_generator.input | 302 +++++++++++++
src/esx/esx_vi_generator.py | 19 +
8 files changed, 1515 insertions(+), 1 deletion(-)
create mode 100644 src/esx/esx_storage_backend_iscsi.c
create mode 100644 src/esx/esx_storage_backend_iscsi.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 4026a15..1668b84 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -494,6 +494,7 @@ ESX_DRIVER_SOURCES = \
esx/esx_network_driver.c esx/esx_network_driver.h \
esx/esx_storage_driver.c esx/esx_storage_driver.h \
esx/esx_storage_backend_vmfs.c esx/esx_storage_backend_vmfs.h \
+ esx/esx_storage_backend_iscsi.c esx/esx_storage_backend_iscsi.h \
esx/esx_device_monitor.c esx/esx_device_monitor.h \
esx/esx_secret_driver.c esx/esx_secret_driver.h \
esx/esx_nwfilter_driver.c esx/esx_nwfilter_driver.h \
diff --git a/src/esx/esx_storage_backend_iscsi.c b/src/esx/esx_storage_backend_iscsi.c
new file mode 100644
index 0000000..fa4bf45
--- /dev/null
+++ b/src/esx/esx_storage_backend_iscsi.c
@@ -0,0 +1,807 @@
+/*
+ * esx_storage_backend_iscsi.c: ESX storage backend for iSCSI handling
+ *
+ * Copyright (C) 2012 Ata E Husain Bohra <ata.husain(a)hotmail.com>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "internal.h"
+#include "md5.h"
+#include "util.h"
+#include "memory.h"
+#include "logging.h"
+#include "uuid.h"
+
+#include "storage_conf.h"
+#include "storage_file.h"
+#include "esx_storage_backend_iscsi.h"
+#include "esx_private.h"
+#include "esx_vi.h"
+#include "esx_vi_methods.h"
+#include "esx_util.h"
+
+#define VIR_FROM_THIS VIR_FROM_STORAGE
+
+/*
+ * The UUID of a storage pool is the MD5 sum of it's mount path. Therefore,
+ * verify that UUID and MD5 sum match in size, because we rely on that.
+ */
+verify(MD5_DIGEST_SIZE == VIR_UUID_BUFLEN);
+
+
+
+static int
+esxStorageBackendISCSINumberOfStoragePools(virConnectPtr conn)
+{
+ int count = 0;
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
+ const esxVI_HostInternetScsiHbaStaticTarget *target = NULL;
+ bool success = false;
+
+ if (esxVI_LookupHostInternetScsiHba(
+ priv->primary, &hostInternetScsiHba) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to obtain iSCSI adapter"));
+ goto cleanup;
+ }
+
+ /* FIXME: code looks for software iSCSI adapter only */
+ if (hostInternetScsiHba == NULL) {
+ /* iSCSI adapter may not be enabled for this host */
+ return 0;
+ }
+
+ /**
+ * ESX has two kind of targets:
+ * 1. staticIscsiTargets
+ * 2. dynamicIscsiTargets
+ * For each dynamic target if its reachable a static target is added.
+ * return iSCSI names for all static targets to avoid duplicate names.
+ */
+ for (target = hostInternetScsiHba->configuredStaticTarget;
+ target != NULL;
+ target = target->_next) {
+ ++count;
+ }
+
+ success = true;
+
+cleanup:
+
+ esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
+
+ return success ? count : -1;
+
+}
+
+
+
+static int
+esxStorageBackendISCSIListStoragePools(virConnectPtr conn,
+ char **const names,
+ const int maxnames)
+{
+ int count = 0;
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
+ const esxVI_HostInternetScsiHbaStaticTarget *target = NULL;
+ bool success = false;
+ int i = 0;
+
+ if (maxnames ==0) {
+ return 0;
+ }
+
+ if (esxVI_LookupHostInternetScsiHba(
+ priv->primary, &hostInternetScsiHba) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to obtain iSCSI adapter"));
+ goto cleanup;
+ }
+
+ /* FIXME: code looks for software iSCSI adapter only */
+ if (hostInternetScsiHba == NULL) {
+ /* iSCSI adapter may not be enabled for this host */
+ return 0;
+ }
+
+ /**
+ * ESX has two kind of targets:
+ * 1. staticIscsiTargets
+ * 2. dynamicIscsiTargets
+ * For each dynamic target if its reachable a static target is added.
+ * return iSCSI names for all static targets to avoid duplicate names.
+ */
+ for (target = hostInternetScsiHba->configuredStaticTarget;
+ target != NULL && count < maxnames;
+ target = target->_next, ++count) {
+ names[count] = strdup(target->iScsiName);
+
+ if (names[count] == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ success = true;
+
+cleanup:
+ if (! success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+ count = -1;
+ }
+
+ esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
+
+ return success ? count : -1;
+}
+
+
+
+static virStoragePoolPtr
+esxStorageBackendISCSIPoolLookupByName(virConnectPtr conn,
+ const char *name)
+{
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_HostInternetScsiHbaStaticTarget *target = NULL;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+ virStoragePoolPtr pool = NULL;
+
+ /* lookup routine are used by the base driver to determine
+ * appropriate backend driver, lookup targetName as optional
+ * parameter
+ */
+ if (esxVI_LookupHostInternetScsiHbaStaticTargetByName(
+ priv->primary, name, &target, esxVI_Occurrence_OptionalItem) < 0 ||
+ target == NULL) {
+ goto cleanup;
+ }
+
+ /**
+ * HostInternetScsiHbaStaticTarget does not provide a uuid field,
+ * but iScsiName (or widely known as IQN) is unique across the multiple
+ * hosts, using it to compute key
+ */
+
+ md5_buffer(target->iScsiName, strlen(target->iScsiName), md5);
+
+ pool = virGetStoragePool(conn, name, md5, &esxStorageBackendISCSIDrv, NULL);
+
+ cleanup:
+
+ esxVI_HostInternetScsiHbaStaticTarget_Free(&target);
+
+ return pool;
+
+}
+
+
+
+static virStoragePoolPtr
+esxStorageBackendISCSIPoolLookupByUUID(virConnectPtr conn,
+ const unsigned char *uuid)
+{
+ virStoragePoolPtr pool = NULL;
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
+ const esxVI_HostInternetScsiHbaStaticTarget *target = NULL;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+
+ if (esxVI_LookupHostInternetScsiHba(
+ priv->primary, &hostInternetScsiHba) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to obtain iSCSI adapter"));
+ goto cleanup;
+ }
+
+ /* FIXME: code just looks for software iSCSI adapter */
+ if (hostInternetScsiHba == NULL) {
+ /* iSCSI adapter may not be enabled for this host */
+ return NULL;
+ }
+
+ for (target = hostInternetScsiHba->configuredStaticTarget;
+ target != NULL;
+ target = target->_next) {
+ md5_buffer(target->iScsiName, strlen(target->iScsiName), md5);
+
+ if (memcmp(uuid, md5, VIR_UUID_STRING_BUFLEN) == 0) {
+ break;
+ }
+ }
+
+ if (target == NULL) {
+ /* pool not found, error handling done by the base driver */
+ goto cleanup;
+ }
+
+ pool = virGetStoragePool(conn,
+ target->iScsiName,
+ md5,
+ &esxStorageBackendISCSIDrv,
+ NULL);
+
+ cleanup:
+ esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
+
+ return pool;
+
+}
+
+
+
+static int
+esxStorageBackendISCSIPoolRefresh(virStoragePoolPtr pool,
+ unsigned int flags)
+{
+ int result = -1;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_ManagedObjectReference *hostStorageSystem = NULL;
+ esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_String *propertyNameList = NULL;
+
+ virCheckFlags(0, -1);
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "configManager.storageSystem\0") < 0 ||
+ esxVI_LookupHostSystemProperties(priv->primary,
+ propertyNameList, &hostSystem) < 0 ||
+ esxVI_GetManagedObjectReference(hostSystem,
+ "configManager.storageSystem", &hostStorageSystem,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_LookupHostInternetScsiHba(
+ priv->primary, &hostInternetScsiHba) < 0) {
+ goto cleanup;
+ }
+
+ /**
+ * ESX does not allow rescan on a particular target,
+ * rescan all the static targets
+ */
+ if (esxVI_RescanHba(priv->primary, hostStorageSystem,
+ hostInternetScsiHba->device) < 0) {
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ManagedObjectReference_Free(&hostStorageSystem);
+ esxVI_ObjectContent_Free(&hostSystem);
+ esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
+
+ return result;
+
+}
+
+
+
+static int
+esxStorageBackendISCSIPoolGetInfo(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
+ virStoragePoolInfoPtr info)
+{
+ /* these fields are not valid for iSCSI pool */
+ info->allocation = info->capacity = info->available = 0;
+ info->state = VIR_STORAGE_POOL_RUNNING;
+
+ return 0;
+}
+
+
+
+static char *
+esxStorageBackendISCSIPoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
+{
+ char *xml = NULL;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
+ const esxVI_HostInternetScsiHbaStaticTarget *target = NULL;
+ virStoragePoolDef def;
+
+ virCheckFlags(0, NULL);
+
+ memset(&def, 0, sizeof(def));
+
+ if (esxVI_LookupHostInternetScsiHba(priv->primary, &hostInternetScsiHba)) {
+ goto cleanup;
+ }
+
+ for (target = hostInternetScsiHba->configuredStaticTarget;
+ target != NULL;
+ target = target->_next) {
+ if (STREQ(target->iScsiName, pool->name)) {
+ break;
+ }
+ }
+
+ if (target == NULL) {
+ /* pool not found */
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find storage pool with name '%s'"), pool->name);
+ goto cleanup;
+ }
+
+ def.name = pool->name;
+ memcpy(def.uuid, pool->uuid, VIR_UUID_BUFLEN);
+
+ def.type = VIR_STORAGE_POOL_ISCSI;
+
+ def.source.initiator.iqn = target->iScsiName;
+
+ def.source.nhost = 1;
+ if (VIR_ALLOC_N(def.source.hosts, def.source.nhost) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ def.source.hosts[0].name = target->address;
+ if (target->port) {
+ def.source.hosts[0].port = target->port->value;
+ }
+
+ /* TODO: add CHAP authentication params */
+
+ xml = virStoragePoolDefFormat(&def);
+
+ cleanup:
+
+ VIR_FREE(def.source.hosts);
+ esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
+
+ return xml;
+
+}
+
+
+
+static int
+esxStorageBackendISCSIPoolNumberOfStorageVolumes(virStoragePoolPtr pool)
+{
+ int count = 0;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_HostScsiTopologyLun *hostScsiTopologyLunList = NULL;
+ const esxVI_HostScsiTopologyLun *hostScsiTopologyLun = NULL;
+ bool success = false;
+
+ if (esxVI_LookupHostScsiTopologyLunListByTargetName(
+ priv->primary, pool->name, &hostScsiTopologyLunList) < 0) {
+ goto cleanup;
+ }
+
+ for (hostScsiTopologyLun = hostScsiTopologyLunList ;
+ hostScsiTopologyLun != NULL;
+ hostScsiTopologyLun = hostScsiTopologyLun->_next) {
+ ++count;
+ }
+
+ success = true;
+
+ cleanup:
+
+ esxVI_HostScsiTopologyLun_Free(&hostScsiTopologyLunList);
+
+ return success ? count : -1;
+
+}
+
+
+static int
+esxStorageBackendISCSIPoolListStorageVolumes(virStoragePoolPtr pool,
+ char **const names,
+ int maxnames)
+{
+ int count = 0;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_HostScsiTopologyLun *hostScsiTopologyLunList = NULL;
+ const esxVI_HostScsiTopologyLun *hostScsiTopologyLun = NULL;
+ esxVI_ScsiLun *scsiLunList = NULL;
+ const esxVI_ScsiLun *scsiLun = NULL;
+ bool success = false;
+ int i = 0;
+
+ if (esxVI_LookupHostScsiTopologyLunListByTargetName(
+ priv->primary, pool->name, &hostScsiTopologyLunList) < 0) {
+ goto cleanup;
+ }
+
+ if (hostScsiTopologyLunList == NULL) {
+ /* iSCSI adapter may not be enabled on ESX host */
+ return 0;
+ }
+
+ if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
+ goto cleanup;
+ }
+
+ /* O^2 but still faster than hash given N is not that large */
+ for (scsiLun = scsiLunList; scsiLun != NULL && count < maxnames;
+ scsiLun = scsiLun->_next) {
+ for (hostScsiTopologyLun = hostScsiTopologyLunList;
+ hostScsiTopologyLun != NULL && count < maxnames;
+ hostScsiTopologyLun = hostScsiTopologyLun->_next) {
+ if (STREQ(hostScsiTopologyLun->scsiLun, scsiLun->key)) {
+ names[count] = strdup(scsiLun->deviceName);
+
+ if (names[count] == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ ++count;
+ }
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ if (! success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+ count = -1;
+ }
+
+ esxVI_HostScsiTopologyLun_Free(&hostScsiTopologyLunList);
+ esxVI_ScsiLun_Free(&scsiLunList);
+
+ return count;
+}
+
+
+static virStorageVolPtr
+esxStorageBackendISCSIVolumeLookupByName(virStoragePoolPtr pool,
+ const char *name)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_ScsiLun *scsiLunList = NULL;
+ const esxVI_ScsiLun *scsiLun = NULL;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+ char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+
+ if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
+ goto cleanup;
+ }
+
+ for (scsiLun = scsiLunList; scsiLun != NULL;
+ scsiLun = scsiLun->_next) {
+ if (STREQ(scsiLun->deviceName, name)) {
+ /**
+ * ScsiLun provides an UUID field that is unique accross
+ * multiple servers. But this field length is ~55 characters
+ * compute MD5 hash to transform it to an acceptable
+ * libvirt format
+ */
+ md5_buffer(scsiLun->uuid, strlen(scsiLun->uuid), md5);
+
+ virUUIDFormat(md5, uuid_string);
+
+ /**
+ * ScsiLun provides displayName and canonicalName but both are
+ * optional and its observed that they can be NULL, using
+ * deviceName to create volume.
+ */
+ volume = virGetStorageVol(pool->conn, pool->name, name, uuid_string,
+ &esxStorageBackendISCSIDrv, NULL);
+ break;
+ }
+ }
+
+ cleanup:
+
+ esxVI_ScsiLun_Free(&scsiLunList);
+
+ return volume;
+
+}
+
+
+static virStorageVolPtr
+esxStorageBackendISCSIVolumeLookupByPath(virConnectPtr conn, const char *path)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = conn->storagePrivateData;
+ char *poolName = NULL;
+ esxVI_ScsiLun *scsiLunList = NULL;
+ esxVI_ScsiLun *scsiLun = NULL;
+ const esxVI_HostScsiDisk *hostScsiDisk = NULL;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+ char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+
+ if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
+ goto cleanup;
+ }
+
+ for (scsiLun = scsiLunList ; scsiLun != NULL;
+ scsiLun = scsiLun->_next) {
+ hostScsiDisk = esxVI_HostScsiDisk_DynamicCast(scsiLun);
+
+ if (hostScsiDisk != NULL &&
+ STREQ(hostScsiDisk->devicePath, path)) {
+ /* Found matching device */
+ if (esxVI_LookupStoragePoolNameByScsiLunKey(
+ priv->primary, hostScsiDisk->key, &poolName) < 0) {
+ goto cleanup;
+ }
+
+ md5_buffer(scsiLun->uuid, strlen(scsiLun->uuid), md5);
+
+ virUUIDFormat(md5, uuid_string);
+
+ volume = virGetStorageVol(conn, poolName, path, uuid_string,
+ &esxStorageBackendISCSIDrv, NULL);
+ break;
+ }
+ }
+
+ cleanup:
+
+ esxVI_ScsiLun_Free(&scsiLunList);
+ VIR_FREE(poolName);
+
+ return volume;
+
+}
+
+
+static virStorageVolPtr
+esxStorageBackendISCSIVolumeLookupByKey(virConnectPtr conn, const char *key)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = conn->storagePrivateData;
+ char *poolName = NULL;
+ esxVI_ScsiLun *scsiLunList = NULL;
+ const esxVI_ScsiLun *scsiLun = NULL;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+ char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+
+
+ /* key may be LUN device path */
+ if (STRPREFIX(key, "/")) {
+ return esxStorageBackendISCSIVolumeLookupByPath(conn, key);
+ }
+
+ if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
+ goto cleanup;
+ }
+
+ for (scsiLun = scsiLunList; scsiLun != NULL;
+ scsiLun = scsiLun->_next) {
+
+ memset(uuid_string, '\0', sizeof(uuid_string));
+ memset(md5, '\0', sizeof(md5));
+
+ md5_buffer(scsiLun->uuid, strlen(scsiLun->uuid), md5);
+
+ virUUIDFormat(md5, uuid_string);
+
+ if (STREQ(key, uuid_string)) {
+ /* Found matching UUID */
+ if (esxVI_LookupStoragePoolNameByScsiLunKey(
+ priv->primary, scsiLun->key, &poolName) < 0) {
+ goto cleanup;
+ }
+
+ volume = virGetStorageVol(conn,
+ poolName,
+ scsiLun->deviceName,
+ uuid_string,
+ &esxStorageBackendISCSIDrv,
+ NULL);
+ break;
+ }
+ }
+
+ cleanup:
+
+ esxVI_ScsiLun_Free(&scsiLunList);
+ VIR_FREE(poolName);
+
+ return volume;
+
+}
+
+
+
+static virStorageVolPtr
+esxStorageBackendISCSIVolumeCreateXML(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
+ const char *xmldesc ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virCheckFlags(0, NULL);
+
+ /* not supported operation for iSCSI pools */
+ return NULL;
+}
+
+
+
+static virStorageVolPtr
+esxStorageBackendISCSIVolumeCreateXMLFrom(
+ virStoragePoolPtr pool ATTRIBUTE_UNUSED,
+ const char *xmldesc ATTRIBUTE_UNUSED,
+ virStorageVolPtr sourceVolume ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virCheckFlags(0, NULL);
+
+ /* not supported operation for iSCSI pools */
+ return NULL;
+}
+
+
+
+static char*
+esxStorageBackendISCSIVolumeGetXMLDesc(virStorageVolPtr volume,
+ unsigned int flags)
+{
+ char *xml = NULL;
+ esxPrivate *priv = volume->conn->storagePrivateData;
+ virStoragePoolDef pool;
+ esxVI_ScsiLun *scsiLunList = NULL;
+ const esxVI_ScsiLun *scsiLun = NULL;
+ const esxVI_HostScsiDisk *hostScsiDisk = NULL;
+ virStorageVolDef def;
+ /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ unsigned char md5[MD5_DIGEST_SIZE];
+ char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+
+ virCheckFlags(0, NULL);
+
+ memset(&pool, 0, sizeof(pool));
+ memset(&def, 0, sizeof(def));
+
+ if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
+ goto cleanup;
+ }
+
+ for (scsiLun = scsiLunList; scsiLun != NULL;
+ scsiLun = scsiLun->_next) {
+ hostScsiDisk =
+ esxVI_HostScsiDisk_DynamicCast((esxVI_ScsiLun *)scsiLun);
+
+ if (hostScsiDisk != NULL &&
+ STREQ(hostScsiDisk->deviceName, volume->name)) {
+ break;
+ }
+ }
+
+ if (hostScsiDisk == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could find volume with name: %s"), volume->name);
+ goto cleanup;
+ }
+
+ pool.type = VIR_STORAGE_POOL_ISCSI;
+
+ def.name = volume->name;
+
+ md5_buffer(scsiLun->uuid, strlen(hostScsiDisk->uuid), md5);
+
+ virUUIDFormat(md5, uuid_string);
+
+ if (esxVI_String_DeepCopyValue(&def.key, uuid_string) < 0) {
+ goto cleanup;
+ }
+
+ /* iSCSI LUN exposes a block device */
+ def.type = VIR_STORAGE_VOL_BLOCK;
+
+ def.target.path = hostScsiDisk->devicePath;
+
+ def.capacity = hostScsiDisk->capacity->block->value *
+ hostScsiDisk->capacity->blockSize->value;
+
+ def.allocation = def.capacity;
+
+ /* iSCSI LUN(s) hosting a datastore will be auto-mounted by
+ * ESX host
+ */
+ def.target.format = VIR_STORAGE_FILE_RAW;
+
+ xml = virStorageVolDefFormat(&pool, &def);
+
+ cleanup:
+
+ esxVI_ScsiLun_Free(&scsiLunList);
+ VIR_FREE(def.key);
+
+ return xml;
+
+}
+
+static int
+esxStorageBackendISCSIVolumeDelete(virStorageVolPtr volume ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
+
+ /* unsupported operation for iSCSI volume */
+ return 1;
+
+}
+
+
+
+static int
+esxStorageBackendISCSIVolumeWipe(virStorageVolPtr volume ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
+
+ /* unsupported operation for iSCSI volume */
+ return 1;
+
+}
+
+
+
+static char*
+esxStorageBackendISCSIVolumeGetPath(virStorageVolPtr volume)
+{
+ char *path;
+
+ if (virAsprintf(&path, "%s", volume->name) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ return path;
+
+}
+
+
+
+virStorageDriver esxStorageBackendISCSIDrv = {
+ .name = "ESX ISCSI backend",
+ .open = NULL, /* 1.0.0 */
+ .close = NULL, /* 1.0.0 */
+ .numOfPools = esxStorageBackendISCSINumberOfStoragePools, /* 1.0.0 */
+ .listPools = esxStorageBackendISCSIListStoragePools, /* 1.0.0 */
+ .poolLookupByName = esxStorageBackendISCSIPoolLookupByName, /* 1.0.0 */
+ .poolLookupByUUID = esxStorageBackendISCSIPoolLookupByUUID, /* 1.0.0 */
+ .poolRefresh = esxStorageBackendISCSIPoolRefresh, /* 1.0.0 */
+ .poolGetInfo = esxStorageBackendISCSIPoolGetInfo, /* 1.0.0 */
+ .poolGetXMLDesc = esxStorageBackendISCSIPoolGetXMLDesc, /* 1.0.0 */
+ .poolNumOfVolumes = esxStorageBackendISCSIPoolNumberOfStorageVolumes, /* 1.0.0 */
+ .poolListVolumes = esxStorageBackendISCSIPoolListStorageVolumes, /* 1.0.0 */
+ .volLookupByName = esxStorageBackendISCSIVolumeLookupByName, /* 1.0.0 */
+ .volLookupByKey = esxStorageBackendISCSIVolumeLookupByKey, /* 1.0.0 */
+ .volLookupByPath = esxStorageBackendISCSIVolumeLookupByPath, /* 1.0.0 */
+ .volCreateXML = esxStorageBackendISCSIVolumeCreateXML, /* 1.0.0 */
+ .volCreateXMLFrom = esxStorageBackendISCSIVolumeCreateXMLFrom, /* 1.0.0 */
+ .volGetXMLDesc = esxStorageBackendISCSIVolumeGetXMLDesc, /* 1.0.0 */
+ .volDelete = esxStorageBackendISCSIVolumeDelete, /* 1.0.0 */
+ .volWipe = esxStorageBackendISCSIVolumeWipe, /* 1.0.0 */
+ .volGetPath = esxStorageBackendISCSIVolumeGetPath, /* 1.0.0 */
+};
diff --git a/src/esx/esx_storage_backend_iscsi.h b/src/esx/esx_storage_backend_iscsi.h
new file mode 100644
index 0000000..f78da46
--- /dev/null
+++ b/src/esx/esx_storage_backend_iscsi.h
@@ -0,0 +1,29 @@
+/*
+ * esx_storage_backend_iscsi.h: ESX storage backend for iSCSI handling
+ *
+ * Copyright (C) 2012 Ata E Husain Bohra <ata.husain(a)hotmail.com>
+ *
+ * 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 __ESX_STORAGE_BACKEND_ISCSI_H__
+# define __ESX_STORAGE_BACKEND_ISCSI_H__
+
+# include "driver.h"
+
+extern virStorageDriver esxStorageBackendISCSIDrv;
+
+#endif /* __ESX_STORAGE_BACKEND_ISCSI_H__ */
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index 5530ea7..6952c69 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -31,6 +31,7 @@
#include "esx_private.h"
#include "esx_storage_driver.h"
#include "esx_storage_backend_vmfs.h"
+#include "esx_storage_backend_iscsi.h"
#define VIR_FROM_THIS VIR_FROM_ESX
@@ -42,11 +43,13 @@
*/
enum {
VMFS = 0,
+ ISCSI,
LAST_DRIVER
};
static virStorageDriverPtr backendDrv[] = {
- &esxStorageBackendVMFSDrv
+ &esxStorageBackendVMFSDrv,
+ &esxStorageBackendISCSIDrv
};
static virDrvOpenStatus
@@ -465,9 +468,12 @@ esxStorageVolumeLookupByPath(virConnectPtr conn, const char *path)
* VMFS Datastore path follows cannonical format i.e.:
* [<datastore_name>] <file_path>
* WHEREAS
+ * iSCSI LUNs device path follows normal linux path convention
*/
if (STRPREFIX(path, "[")) {
volume = backendDrv[VMFS]->volLookupByPath(conn, path);
+ } else if (STRPREFIX(path, "/")) {
+ volume = backendDrv[ISCSI]->volLookupByPath(conn, path);
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected volume path format: %s"), path);
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 9fb2c11..12100d7 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -4875,5 +4875,337 @@ esxVI_LookupManagedObjectHelper(esxVI_Context *ctx,
}
+int
+esxVI_LookupHostInternetScsiHbaStaticTargetByName(
+ esxVI_Context *ctx,
+ const char *name,
+ esxVI_HostInternetScsiHbaStaticTarget **ret,
+ esxVI_Occurrence occurrence)
+{
+ int result = -1;
+ esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
+ const esxVI_HostInternetScsiHbaStaticTarget *target = NULL;
+
+ if (esxVI_LookupHostInternetScsiHba(ctx, &hostInternetScsiHba) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to obtain hostInternetScsiHba"));
+ goto cleanup;
+ }
+
+ if (hostInternetScsiHba == NULL) {
+ /* iSCSI adapter may not be enabled for this host */
+ return 0;
+ }
+
+ for (target = hostInternetScsiHba->configuredStaticTarget;
+ target != NULL;
+ target = target->_next) {
+ if (STREQ(target->iScsiName, name)) {
+ break;
+ }
+ }
+
+ if (target == NULL) {
+ if (occurrence == esxVI_Occurrence_RequiredItem) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find storage pool with name: %s"), name);
+ }
+ goto cleanup;
+ }
+
+ if (esxVI_HostInternetScsiHbaStaticTarget_DeepCopy(
+ ret, (esxVI_HostInternetScsiHbaStaticTarget *)target) < 0) {
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+
+ esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);
+
+ return result;
+}
+
+
+int
+esxVI_LookupHostInternetScsiHba(
+ esxVI_Context *ctx,
+ esxVI_HostInternetScsiHba **hostInternetScsiHba)
+{
+ int result = -1;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_HostHostBusAdapter *hostHostBusAdapterList = NULL;
+ esxVI_HostHostBusAdapter *hostHostBusAdapter = NULL;
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "config.storageDevice.hostBusAdapter\0") < 0 ||
+ esxVI_LookupHostSystemProperties(ctx, propertyNameList,
+ &hostSystem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = hostSystem->propSet;
+ dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name,
+ "config.storageDevice.hostBusAdapter")) {
+ if (esxVI_HostHostBusAdapter_CastListFromAnyType(
+ dynamicProperty->val, &hostHostBusAdapterList) < 0 ||
+ hostHostBusAdapterList == NULL) {
+ goto cleanup;
+ }
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+
+ /* See vSphere API documentation about HostInternetScsiHba for details */
+ for (hostHostBusAdapter = hostHostBusAdapterList;
+ hostHostBusAdapter != NULL;
+ hostHostBusAdapter = hostHostBusAdapter->_next) {
+ esxVI_HostInternetScsiHba *candidate=
+ esxVI_HostInternetScsiHba_DynamicCast(hostHostBusAdapter);
+
+ if (candidate) {
+ if (esxVI_HostInternetScsiHba_DeepCopy(hostInternetScsiHba,
+ candidate) < 0) {
+ goto cleanup;
+ }
+ break;
+ }
+ }
+
+ result = 0;
+
+cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&hostSystem);
+ esxVI_HostHostBusAdapter_Free(&hostHostBusAdapterList);
+
+ return result;
+}
+
+
+int
+esxVI_LookupScsiLunList(esxVI_Context *ctx,
+ esxVI_ScsiLun **ret)
+{
+ int result = -1;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ScsiLun *scsiLunList = NULL;
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "config.storageDevice.scsiLun\0") < 0 ||
+ esxVI_LookupHostSystemProperties(
+ ctx, propertyNameList, &hostSystem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = hostSystem->propSet;
+ dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name,
+ "config.storageDevice.scsiLun")) {
+ if (esxVI_ScsiLun_CastListFromAnyType(dynamicProperty->val,
+ &scsiLunList) < 0) {
+ goto cleanup;
+ }
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+
+ if (scsiLunList == NULL ||
+ esxVI_ScsiLun_DeepCopyList(ret, scsiLunList) < 0) {
+ goto cleanup;
+ }
+
+ result = 0;
+
+cleanup:
+
+ esxVI_ScsiLun_Free(&scsiLunList);
+
+ return result;
+
+}
+
+
+int
+esxVI_LookupHostScsiTopologyLunListByTargetName(
+ esxVI_Context *ctx, const char *name, esxVI_HostScsiTopologyLun **ret)
+{
+ int result = -1;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_HostScsiTopologyInterface *hostScsiInterfaceList = NULL;
+ const esxVI_HostScsiTopologyInterface *hostScsiInterface = NULL;
+ const esxVI_HostScsiTopologyTarget *hostScsiTopologyTarget = NULL;
+ bool found = false;
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "config.storageDevice.scsiTopology.adapter\0") < 0 ||
+ esxVI_LookupHostSystemProperties(
+ ctx, propertyNameList, &hostSystem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = hostSystem->propSet;
+ dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name,
+ "config.storageDevice.scsiTopology.adapter")) {
+ esxVI_HostScsiTopologyInterface_Free(&hostScsiInterfaceList);
+
+ if ((esxVI_HostScsiTopologyInterface_CastListFromAnyType
+ (dynamicProperty->val, &hostScsiInterfaceList) < 0)) {
+ goto cleanup;
+ }
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+
+ if (hostScsiInterfaceList == NULL) {
+ /* iSCSI adapter may not be enabled */
+ return 0;
+ }
+
+ /* See vSphere API documentation about HostScsiTopologyInterface */
+ for (hostScsiInterface = hostScsiInterfaceList;
+ hostScsiInterface != NULL && !found;
+ hostScsiInterface = hostScsiInterface->_next) {
+ for (hostScsiTopologyTarget = hostScsiInterface->target;
+ hostScsiTopologyTarget != NULL;
+ hostScsiTopologyTarget = hostScsiTopologyTarget->_next) {
+ const esxVI_HostInternetScsiTargetTransport *candidate =
+ esxVI_HostInternetScsiTargetTransport_DynamicCast(
+ hostScsiTopologyTarget->transport);
+
+ if (candidate && STREQ(candidate->iScsiName, name)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found || hostScsiTopologyTarget == NULL) {
+ goto cleanup;
+ }
+
+ if (esxVI_HostScsiTopologyLun_DeepCopyList(
+ ret, hostScsiTopologyTarget->lun) < 0) {
+ goto cleanup;
+ }
+
+ if (*ret == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Target not found"));
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&hostSystem);
+ esxVI_HostScsiTopologyInterface_Free(&hostScsiInterfaceList);
+
+ return result;
+}
+
+
+int
+esxVI_LookupStoragePoolNameByScsiLunKey(esxVI_Context *ctx,
+ const char *key,
+ char **poolName)
+{
+ int result = -1;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_HostScsiTopologyInterface *hostScsiInterfaceList = NULL;
+ const esxVI_HostScsiTopologyInterface *hostScsiInterface = NULL;
+ const esxVI_HostScsiTopologyTarget *hostScsiTopologyTarget = NULL;
+ bool found = false;
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "config.storageDevice.scsiTopology.adapter\0") < 0 ||
+ esxVI_LookupHostSystemProperties(
+ ctx, propertyNameList, &hostSystem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = hostSystem->propSet;
+ dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name,
+ "config.storageDevice.scsiTopology.adapter")) {
+ esxVI_HostScsiTopologyInterface_Free(&hostScsiInterfaceList);
+
+ if ((esxVI_HostScsiTopologyInterface_CastListFromAnyType
+ (dynamicProperty->val, &hostScsiInterfaceList) < 0)) {
+ goto cleanup;
+ }
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+
+ if (hostScsiInterfaceList == NULL) {
+ /* iSCSI adapter may not be enabled */
+ return 0;
+ }
+
+ /* See vSphere API documentation about HostScsiTopologyInterface */
+ for (hostScsiInterface = hostScsiInterfaceList;
+ hostScsiInterface != NULL && !found;
+ hostScsiInterface = hostScsiInterface->_next) {
+ for (hostScsiTopologyTarget = hostScsiInterface->target;
+ hostScsiTopologyTarget != NULL;
+ hostScsiTopologyTarget = hostScsiTopologyTarget->_next) {
+ const esxVI_HostInternetScsiTargetTransport *candidate =
+ esxVI_HostInternetScsiTargetTransport_DynamicCast(
+ hostScsiTopologyTarget->transport);
+
+ if (candidate) {
+ /* iterate hostScsiTopologyLun list to find matching key */
+ const esxVI_HostScsiTopologyLun *hostScsiTopologyLun =
+ hostScsiTopologyTarget->lun;
+ for (; hostScsiTopologyLun != NULL;
+ hostScsiTopologyLun = hostScsiTopologyLun->_next) {
+ if (STREQ(hostScsiTopologyLun->scsiLun, key)) {
+ *poolName = strdup(candidate->iScsiName);
+
+ if (*poolName == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+ }
+ /* hostScsiTopologyLun iteration done, terminate loop */
+ break;
+ }
+ }
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_ObjectContent_Free(&hostSystem);
+ esxVI_String_Free(&propertyNameList);
+ esxVI_HostScsiTopologyInterface_Free(&hostScsiInterfaceList);
+
+ return result;
+}
+
+
#include "esx_vi.generated.c"
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index d7895a0..8e56044 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -528,6 +528,24 @@ int esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedHostCpuIdInfo,
int esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersion);
+int esxVI_LookupHostInternetScsiHbaStaticTargetByName(esxVI_Context *ctx,
+ const char *name, esxVI_HostInternetScsiHbaStaticTarget **ret,
+ esxVI_Occurrence occurrence);
+
+int esxVI_LookupHostInternetScsiHba(
+ esxVI_Context *ctx,
+ esxVI_HostInternetScsiHba **hostInternetScsiHba);
+
+int esxVI_LookupScsiLunList(esxVI_Context *ctx, esxVI_ScsiLun **ret);
+
+int esxVI_LookupHostScsiTopologyLunListByTargetName(
+ esxVI_Context *ctx, const char *name, esxVI_HostScsiTopologyLun **ret);
+
+int
+esxVI_LookupStoragePoolNameByScsiLunKey(esxVI_Context *ctx,
+ const char *key,
+ char **poolName);
+
# include "esx_vi.generated.h"
#endif /* __ESX_VI_H__ */
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index c4a3e56..21f5b10 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -58,6 +58,14 @@ enum AutoStartWaitHeartbeatSetting
end
+enum FibreChannelPortType
+ fabric
+ loop
+ pointToPoint
+ unknown
+end
+
+
enum ManagedEntityStatus
gray
green
@@ -128,6 +136,12 @@ enum VirtualMachinePowerState
end
+enum vStorageSupport
+ vStorageUnknown
+end
+
+
+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Objects
#
@@ -262,6 +276,13 @@ object HostAutoStartManagerConfig
AutoStartPowerInfo powerInfo ol
end
+object HostBlockAdapterTargetTransport extends HostTargetTransport
+end
+
+
+object HostBlockHba extends HostHostBusAdapter
+end
+
object HostConfigManager
ManagedObjectReference cpuScheduler o
@@ -309,6 +330,31 @@ object HostDatastoreBrowserSearchSpec
Boolean sortFoldersFirst o
end
+object HostDevice
+ String deviceName r
+ String deviceType r
+end
+
+
+object HostDiskDimensionsLba
+ Int blockSize r
+ Long block r
+end
+
+
+object HostFibreChannelHba extends HostHostBusAdapter
+ Long nodeWorldWideName r
+ FibreChannelPortType portType r
+ Long portWorldWideName r
+ Long speed r
+end
+
+
+object HostFibreChannelTargetTransport extends HostTargetTransport
+ Long nodeWorldWideName r
+ Long portWorldWideName r
+end
+
object HostFileSystemVolume
String type r
@@ -323,6 +369,164 @@ object HostIpConfig
String subnetMask o
end
+object HostHostBusAdapter
+ Int bus r
+ String device r
+ String driver o
+ String key o
+ String model r
+ String pci o
+ String status r
+end
+
+
+object HostInternetScsiTargetTransport extends HostTargetTransport
+ String iScsiName r
+ String iScsiAlias r
+ String address ol
+
+end
+
+
+object HostInternetScsiHba extends HostHostBusAdapter
+ HostInternetScsiHbaAuthenticationCapabilities authenticationCapabilities r
+ HostInternetScsiHbaAuthenticationProperties authenticationProperties r
+ HostInternetScsiHbaDiscoveryCapabilities discoveryCapabilities r
+ HostInternetScsiHbaDiscoveryProperties discoveryProperties r
+ HostInternetScsiHbaIPCapabilities ipCapabilities r
+ HostInternetScsiHbaIPProperties ipProperties r
+ String iScsiName r
+ Boolean isSoftwareBased r
+ HostInternetScsiHbaParamValue advancedOptions ol
+ HostInternetScsiHbaSendTarget configuredSendTarget ol
+ HostInternetScsiHbaStaticTarget configuredStaticTarget ol
+ Int currentSpeedMb o
+ HostInternetScsiHbaDigestCapabilities digestCapabilities o
+ HostInternetScsiHbaDigestProperties digestProperties o
+ String iScsiAlias o
+ Int maxSpeedMb o
+ OptionDef supportedAdvancedOptions ol
+end
+
+
+
+object HostInternetScsiHbaAuthenticationCapabilities
+ Boolean chapAuthSettable r
+ Boolean krb5AuthSettable r
+ Boolean spkmAuthSettable r
+ Boolean srpAuthSettable r
+ Boolean mutualChapSettable o
+ Boolean targetChapSettable o
+ Boolean targetMutualChapSettable o
+end
+
+
+object HostInternetScsiHbaAuthenticationProperties
+ Boolean chapAuthEnabled r
+ String chapAuthenticationType o
+ Boolean chapInherited o
+ String chapName o
+ String chapSecret o
+ String mutualChapAuthenticationType o
+ Boolean mutualChapInherited o
+ String mutualChapName o
+ String mutualChapSecret o
+end
+
+
+object HostInternetScsiHbaDigestCapabilities
+ Boolean dataDigestSettable o
+ Boolean headerDigestSettable o
+ Boolean targetDataDigestSettable o
+ Boolean targetHeaderDigestSettable o
+end
+
+
+object HostInternetScsiHbaDigestProperties
+ Boolean dataDigestInherited o
+ String dataDigestType o
+ Boolean headerDigestInherited o
+ String headerDigestType o
+end
+
+
+object HostInternetScsiHbaDiscoveryCapabilities
+ Boolean iSnsDiscoverySettable r
+ Boolean sendTargetsDiscoverySettable r
+ Boolean slpDiscoverySettable r
+ Boolean staticTargetDiscoverySettable r
+end
+
+
+object HostInternetScsiHbaDiscoveryProperties
+ Boolean iSnsDiscoveryEnabled r
+ Boolean sendTargetsDiscoveryEnabled r
+ Boolean slpDiscoveryEnabled r
+ Boolean staticTargetDiscoveryEnabled r
+ String iSnsDiscoveryMethod o
+ String iSnsHost o
+ String slpDiscoveryMethod o
+ String slpHost o
+end
+
+object HostInternetScsiHbaIPCapabilities
+ Boolean addressSettable r
+ Boolean alternateDnsServerAddressSettable r
+ Boolean defaultGatewaySettable r
+ Boolean ipConfigurationMethodSettable r
+ Boolean primaryDnsServerAddressSettable r
+ Boolean subnetMaskSettable r
+ Boolean arpRedirectSettable o
+ Boolean hostNameAsTargetAddress o
+ Boolean ipv6Supported o
+ Boolean mtuSettable o
+ Boolean nameAliasSettable o
+end
+
+
+object HostInternetScsiHbaIPProperties
+ Boolean dhcpConfigurationEnabled r
+ String address o
+ String alternateDnsServerAddress o
+ Boolean arpRedirectEnabled o
+ String defaultGateway o
+ String ipv6Address o
+ String ipv6DefaultGateway o
+ Boolean jumboFramesEnabled o
+ String mac o
+ Int mtu o
+ String primaryDnsServerAddress o
+ String subnetMask o
+end
+
+
+object HostInternetScsiHbaParamValue extends OptionValue
+ Boolean isInherited o
+end
+
+
+object HostInternetScsiHbaSendTarget
+ String address r
+ HostInternetScsiHbaParamValue advancedOptions ol
+ HostInternetScsiHbaAuthenticationProperties authenticationProperties o
+ HostInternetScsiHbaDigestProperties digestProperties o
+ String parent o
+ Int port o
+ OptionDef supportedAdvancedOptions ol
+end
+
+
+object HostInternetScsiHbaStaticTarget
+ String address r
+ String iScsiName r
+ HostInternetScsiHbaParamValue advancedOptions ol
+ HostInternetScsiHbaAuthenticationProperties authenticationProperties o
+ HostInternetScsiHbaDigestProperties digestProperties o
+ String parent o
+ Int port o
+ OptionDef supportedAdvancedOptions ol
+end
+
object HostMountInfo
String path o
@@ -418,12 +622,55 @@ object HostPortGroupSpec
HostNetworkPolicy policy r
end
+object HostParallelScsiHba extends HostHostBusAdapter
+end
+
+
+object HostParallelScsiTargetTransport extends HostTargetTransport
+end
+
+
+object HostScsiDisk extends ScsiLun
+ HostDiskDimensionsLba capacity r
+ String devicePath r
+end
+
object HostScsiDiskPartition
String diskName r
Int partition r
end
+object HostScsiTopology
+ HostScsiTopologyInterface adapater ol
+end
+
+
+object HostScsiTopologyInterface
+ String adapter r
+ String key r
+ HostScsiTopologyTarget target ol
+end
+
+
+object HostScsiTopologyLun
+ String key r
+ Int lun r
+ String scsiLun r
+end
+
+
+object HostScsiTopologyTarget
+ String key r
+ Int target r
+ HostScsiTopologyLun lun ol
+ HostTargetTransport transport o
+end
+
+
+object HostTargetTransport
+end
+
object HostVirtualSwitch
String name r
@@ -526,12 +773,22 @@ object ObjectUpdate
MissingProperty missingSet i
end
+object OptionDef extends ElementDescription
+ OptionType optionType r
+end
+
object OptionType
Boolean valueIsReadonly o
end
+object OptionValue
+ String key r
+ AnyType value r
+end
+
+
object PerfCounterInfo
Int key r
ElementDescription nameInfo r
@@ -664,6 +921,45 @@ object SelectionSpec
end
+object ScsiLun extends HostDevice
+ String lunType r
+ String operationalState rl
+ String uuid r
+ ScsiLunDurableName alternateName ol
+ String canonicalName o
+ ScsiLunCapabilities capabilities o
+ ScsiLunDescriptor descriptor ol
+ String displayName o
+ ScsiLunDurableName durableName o
+ String key o
+ String model o
+ Int queueDepth o
+ String revision o
+ Int scsiLevel o
+ String serialNumber o
+ Byte standardInquiry ol
+ String vendor o
+end
+
+
+object ScsiLunCapabilities
+ Boolean updateDisplayNameSupported r
+end
+
+
+object ScsiLunDescriptor
+ String id r
+ String quality r
+end
+
+
+object ScsiLunDurableName
+ String namespace r
+ Byte namespaceId r
+ Byte data ol
+end
+
+
object ServiceContent
ManagedObjectReference rootFolder r
ManagedObjectReference propertyCollector r
@@ -1138,6 +1434,12 @@ method RemoveVirtualSwitch
end
+method RescanHba
+ ManagedObjectReference _this r
+ String hbaDevice r
+end
+
+
method RetrieveProperties returns ObjectContent ol
ManagedObjectReference _this:propertyCollector r
PropertyFilterSpec specSet rl
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index 2883ac0..af4e7e8 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -1532,6 +1532,21 @@ additional_object_features = { "AutoStartDefaults" : Object.FEATURE__AN
Object.FEATURE__ANY_TYPE,
"HostDatastoreBrowserSearchResults" : Object.FEATURE__LIST |
Object.FEATURE__ANY_TYPE,
+ "HostHostBusAdapter" : Object.FEATURE__LIST |
+ Object.FEATURE__ANY_TYPE,
+ "HostInternetScsiHba" : Object.FEATURE__DYNAMIC_CAST |
+ Object.FEATURE__DEEP_COPY,
+ "HostInternetScsiTargetTransport" : Object.FEATURE__DYNAMIC_CAST,
+ "HostScsiDisk" : Object.FEATURE__LIST |
+ Object.FEATURE__ANY_TYPE |
+ Object.FEATURE__DYNAMIC_CAST,
+ "HostScsiTopologyInterface" : Object.FEATURE__LIST |
+ Object.FEATURE__ANY_TYPE,
+ "HostScsiTopologyLun" : Object.FEATURE__ANY_TYPE |
+ Object.FEATURE__LIST |
+ Object.FEATURE__DEEP_COPY,
+ "HostScsiTopologyTarget" : Object.FEATURE__ANY_TYPE |
+ Object.FEATURE__LIST,
"HostPortGroup" : Object.FEATURE__LIST |
Object.FEATURE__ANY_TYPE,
"HostVirtualSwitch" : Object.FEATURE__DEEP_COPY |
@@ -1543,6 +1558,10 @@ additional_object_features = { "AutoStartDefaults" : Object.FEATURE__AN
Object.FEATURE__LIST |
Object.FEATURE__ANY_TYPE,
"ResourcePoolResourceUsage" : Object.FEATURE__ANY_TYPE,
+ "ScsiLun" : Object.FEATURE__LIST |
+ Object.FEATURE__ANY_TYPE |
+ Object.FEATURE__DEEP_COPY,
+ "ScsiLunDurableName" : Object.FEATURE__LIST,
"ServiceContent" : Object.FEATURE__DESERIALIZE,
"SharesInfo" : Object.FEATURE__ANY_TYPE,
"TaskInfo" : Object.FEATURE__LIST |
--
1.7.9.5
11 years, 11 months
[libvirt] [PATCHv2 0/2] qemu: support live update of an interface's filter
by Laine Stump
These two patches enable making a live change to the nwfilter of a
guest's interface via virDomainUpdateDeviceFlags (virsh
update-device).
Differences from V1:
1) add patch from Stefan Berger to do a proper comparison of the
values stored in the filterparams hashtable.
2) simplify virNWFilterHashTableEqual to use Stefan's new function, and
remove a couple of pointless comparisons based on Stefan's review.
11 years, 11 months
[libvirt] [PATCH 0/?] Various issues found by coverity
by Ján Tomko
Ján Tomko (7):
nwfilter: fix NULL pointer check in virNWFilterSnoopReqNew
conf: prevent crash with no uuid in cephx auth secret
cgroup: fix impossible overrun in virCgroupAddTaskController
libssh2_session: support DSS keys as well
virsh: fix error messages in iface-bridge
conf: check the return value of virXPathNodeSet
conf: snapshot: check return value of virDomainSnapshotObjListNum
src/conf/domain_conf.c | 8 ++++++--
src/conf/snapshot_conf.c | 2 +-
src/conf/storage_conf.c | 12 ++++++------
src/nwfilter/nwfilter_dhcpsnoop.c | 4 ++--
src/rpc/virnetsshsession.c | 1 +
src/util/cgroup.c | 2 +-
tools/virsh-interface.c | 4 ++--
7 files changed, 19 insertions(+), 14 deletions(-)
--
1.7.8.6
11 years, 11 months
[libvirt] [PATCHv2 0/3] IPv6 enhancements; put dnsmasq parameters in conf-file
by Gene Czarcinski
Rebased 30 Nov 2012
These three patch files are packaged together because they serially
depend on each other. These files have been rebased to "v3" of
the dnsmasq capabilities and bind-dynamic patches.
The DHCPv6 support checks dnsmasq's version and requires a minimum of 2.64.
Also, using dnsmasq for providing the RA service is checked against the
dnsmasq version and is currently 2.64.
As with IPv4, IPv6 DHCP is only one subnetwork on an interface. Additionally,
if other IPv6 addresses are defined, a warning message is issued since
the Router Advertisement service will support only state-full (DHCP) or
state-less (SLAAC) addressing on a network interface (not both). Thus, the
additional subnetworks will need to be manually configured to properly function.
If dnsmasq provides the RA service, it also points to itself as a RDNSS
(Recursive DNS Server) as part of the information is supplies.
If IPv6 DHCP is not being run, then SLAAC addressing is supported for
any IPv6 addresses specified.
Gene Czarcinski (3):
v1: allow guest to guest IPv6 without gateway definition
v8.1 add support for DHCPv6
v7.9: put dnsmasq parameters into conf-file
docs/formatnetwork.html.in | 126 ++++-
docs/schemas/network.rng | 12 +-
src/conf/network_conf.c | 100 ++--
src/network/bridge_driver.c | 590 ++++++++++++++-------
src/network/bridge_driver.h | 7 +-
src/util/dnsmasq.c | 9 +-
tests/networkxml2argvdata/dhcp6-nat-network.argv | 14 +
tests/networkxml2argvdata/dhcp6-nat-network.xml | 24 +
tests/networkxml2argvdata/dhcp6-network.argv | 14 +
tests/networkxml2argvdata/dhcp6-network.xml | 14 +
.../dhcp6host-routed-network.argv | 12 +
.../dhcp6host-routed-network.xml | 19 +
tests/networkxml2argvdata/isolated-network.argv | 25 +-
.../networkxml2argvdata/nat-network-dns-hosts.argv | 14 +-
.../nat-network-dns-srv-record-minimal.argv | 34 +-
.../nat-network-dns-srv-record.argv | 24 +-
.../nat-network-dns-txt-record.argv | 22 +-
tests/networkxml2argvdata/nat-network.argv | 22 +-
tests/networkxml2argvdata/netboot-network.argv | 28 +-
.../networkxml2argvdata/netboot-proxy-network.argv | 26 +-
tests/networkxml2argvdata/routed-network.argv | 11 +-
tests/networkxml2argvtest.c | 47 +-
22 files changed, 838 insertions(+), 356 deletions(-)
create mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.argv
create mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.xml
create mode 100644 tests/networkxml2argvdata/dhcp6-network.argv
create mode 100644 tests/networkxml2argvdata/dhcp6-network.xml
create mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.argv
create mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.xml
--
1.7.11.7
11 years, 11 months
[libvirt] [PATCH] virsh: don't crash if shutdown --mode not provided
by Eric Blake
virStringSplit requires a non-NULL input, but commit cef78ed forgot
to follow the rule.
* tools/virsh-domain.c (cmdReboot, cmdShutdown): Avoid NULL deref.
---
Pushing under the build-breaker rule.
tools/virsh-domain.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 9f1a3d4..f12777c 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -4036,20 +4036,20 @@ cmdShutdown(vshControl *ctl, const vshCmd *cmd)
const char *mode = NULL;
int flags = 0;
int rv;
- char **modes, **tmp;
+ char **modes = NULL, **tmp;
if (vshCommandOptString(cmd, "mode", &mode) < 0) {
vshError(ctl, "%s", _("Invalid type"));
return false;
}
- if (!(modes = virStringSplit(mode, ",", 0))) {
+ if (mode && !(modes = virStringSplit(mode, ",", 0))) {
vshError(ctl, "%s", _("Cannot parse mode string"));
return false;
}
tmp = modes;
- while (*tmp) {
+ while (tmp && *tmp) {
mode = *tmp;
if (STREQ(mode, "acpi")) {
flags |= VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN;
@@ -4112,20 +4112,20 @@ cmdReboot(vshControl *ctl, const vshCmd *cmd)
const char *name;
const char *mode = NULL;
int flags = 0;
- char **modes, **tmp;
+ char **modes = NULL, **tmp;
if (vshCommandOptString(cmd, "mode", &mode) < 0) {
vshError(ctl, "%s", _("Invalid type"));
return false;
}
- if (!(modes = virStringSplit(mode, ",", 0))) {
+ if (mode && !(modes = virStringSplit(mode, ",", 0))) {
vshError(ctl, "%s", _("Cannot parse mode string"));
return false;
}
tmp = modes;
- while (*tmp) {
+ while (tmp && *tmp) {
mode = *tmp;
if (STREQ(mode, "acpi")) {
flags |= VIR_DOMAIN_REBOOT_ACPI_POWER_BTN;
--
1.7.1
11 years, 11 months
[libvirt] [PATCH] Convert libxl driver to Xen 4.2
by Jim Fehlig
Based on a patch originally authored by Daniel De Graaf
http://lists.xen.org/archives/html/xen-devel/2012-05/msg00565.html
This patch converts the Xen libxl driver to support only Xen >= 4.2.
Support for Xen 4.1 libxl is dropped since that version of libxl is
designated 'technology preview' only and is incompatible with Xen 4.2
libxl. Additionally, the default toolstack in Xen 4.1 is still xend,
for which libvirt has a stable, functional driver.
---
configure.ac | 8 +-
docs/drvxen.html.in | 8 +
libvirt.spec.in | 4 +-
src/libxl/libxl_conf.c | 370 ++++++++++++++---------------------
src/libxl/libxl_conf.h | 17 +-
src/libxl/libxl_driver.c | 488 +++++++++++++++++++++++++++-------------------
6 files changed, 459 insertions(+), 436 deletions(-)
diff --git a/configure.ac b/configure.ac
index 849d787..c1a9943 100644
--- a/configure.ac
+++ b/configure.ac
@@ -717,16 +717,14 @@ if test "$with_libxl" != "no" ; then
fi
CFLAGS="$CFLAGS $LIBXL_CFLAGS"
LIBS="$LIBS $LIBXL_LIBS"
- AC_CHECK_LIB([xenlight], [libxl_domain_create_new], [
+ AC_CHECK_LIB([xenlight], [libxl_ctx_alloc], [
with_libxl=yes
- LIBXL_LIBS="$LIBXL_LIBS -lxenlight -lxenstore -lxenctrl -lxenguest -luuid -lutil -lblktapctl"
+ LIBXL_LIBS="$LIBXL_LIBS -lxenlight"
],[
if test "$with_libxl" = "yes"; then
fail=1
fi
with_libxl=no
- ],[
- -lxenstore -lxenctrl -lxenguest -luuid -lutil -lblktapctl
])
fi
@@ -734,7 +732,7 @@ LIBS="$old_LIBS"
CFLAGS="$old_CFLAGS"
if test $fail = 1; then
- AC_MSG_ERROR([You must install the libxl Library to compile libxenlight driver with -lxl])
+ AC_MSG_ERROR([You must install the libxl Library from Xen >= 4.2 to compile libxenlight driver with -lxl])
fi
if test "$with_libxl" = "yes"; then
diff --git a/docs/drvxen.html.in b/docs/drvxen.html.in
index 0bca935..06bd911 100644
--- a/docs/drvxen.html.in
+++ b/docs/drvxen.html.in
@@ -53,6 +53,14 @@
the <code>/etc/xen</code> directory. It is important not to place
any other non-config files in this directory.
</li>
+ <li>
+ <strong>libxl</strong>: Starting with Xen 4.2, the legacy XenD/xm
+ toolstack is deprecated in favor of libxl, also commonly called
+ libxenlight. libvirt supports this new Xen toolstack via the
+ libxl driver. If XenD is enabled, the legacy xen driver consisting
+ of the above mentioned channels will be used. If XenD is disabled,
+ the libxl driver will be used.
+ </li>
</ul>
<h2><a name="uri">Connections to Xen driver</a></h2>
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 35c103b..bb274f5 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -188,8 +188,8 @@
%endif
%endif
-# Fedora doesn't have new enough Xen for libxl until F16
-%if 0%{?fedora} && 0%{?fedora} < 16
+# Fedora doesn't have new enough Xen for libxl until F18
+%if 0%{?fedora} && 0%{?fedora} < 18
%define with_libxl 0
%endif
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 1c3130b..73abdfa 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -41,6 +41,7 @@
#include "capabilities.h"
#include "libxl_driver.h"
#include "libxl_conf.h"
+#include "libxl_utils.h"
#include "storage_file.h"
@@ -62,6 +63,52 @@ struct guest_arch {
static const char *xen_cap_re = "(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(x86_32|x86_64|ia64|powerpc64)(p|be)?";
static regex_t xen_cap_rec;
+/*
+ * Copied from split_string_into_string_list() in
+ * $xen-sources/tools/libxl/xl_cmdimpl.c, which is licensed LGPL v2.1.
+ */
+static int
+libxlSplitStringIntoStringList(const char *str,
+ const char *delim,
+ libxl_string_list *psl)
+{
+ char *s, *saveptr;
+ const char *p;
+ libxl_string_list sl;
+ int i = 0, nr = 0;
+
+ s = strdup(str);
+ if (s == NULL) {
+ virReportOOMError();
+ return -1;
+ }
+
+ /* Count number of entries */
+ p = strtok_r(s, delim, &saveptr);
+ do {
+ nr++;
+ } while ((p = strtok_r(NULL, delim, &saveptr)));
+
+ VIR_FREE(s);
+ s = strdup(str);
+
+ if (VIR_ALLOC_N(sl, nr + 1) < 0) {
+ virReportOOMError();
+ VIR_FREE(s);
+ return -1;
+ }
+
+ p = strtok_r(s, delim, &saveptr);
+ do {
+ sl[i] = strdup(p);
+ i++;
+ } while ((p = strtok_r(NULL, delim, &saveptr)));
+ sl[i] = NULL;
+
+ *psl = sl;
+ VIR_FREE(s);
+ return 0;
+}
static int
libxlNextFreeVncPort(libxlDriverPrivatePtr driver, int startPort)
@@ -360,18 +407,36 @@ libxlMakeCapabilitiesInternal(const char *hostmachine,
}
static int
-libxlMakeDomCreateInfo(virDomainDefPtr def, libxl_domain_create_info *c_info)
+libxlMakeDomCreateInfo(libxlDriverPrivatePtr driver,
+ virDomainDefPtr def,
+ libxl_domain_create_info *c_info)
{
char uuidstr[VIR_UUID_STRING_BUFLEN];
- libxl_init_create_info(c_info);
+ libxl_domain_create_info_init(c_info);
+
+ if (STREQ(def->os.type, "hvm"))
+ c_info->type = LIBXL_DOMAIN_TYPE_HVM;
+ else
+ c_info->type = LIBXL_DOMAIN_TYPE_PV;
- c_info->hvm = STREQ(def->os.type, "hvm");
if ((c_info->name = strdup(def->name)) == NULL) {
virReportOOMError();
goto error;
}
+ if (def->nseclabels &&
+ def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_STATIC) {
+ if (libxl_flask_context_to_sid(driver->ctx,
+ def->seclabels[0]->label,
+ strlen(def->seclabels[0]->label),
+ &c_info->ssidref)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("libxenlight failed to resolve security label '%s'"),
+ def->seclabels[0]->label);
+ }
+ }
+
virUUIDFormat(def->uuid, uuidstr);
if (libxl_uuid_from_string(&c_info->uuid, uuidstr)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -382,7 +447,7 @@ libxlMakeDomCreateInfo(virDomainDefPtr def, libxl_domain_create_info *c_info)
return 0;
error:
- libxl_domain_create_info_destroy(c_info);
+ libxl_domain_create_info_dispose(c_info);
return -1;
}
@@ -393,26 +458,25 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_domain_config *d_config)
int hvm = STREQ(def->os.type, "hvm");
int i;
- /* Currently, libxenlight only supports 32 vcpus per domain.
- * cur_vcpus member of struct libxl_domain_build_info is defined
- * as an int, but its semantic is a bitmap of online vcpus, so
- * only 32 can be represented.
+ /*
+ * libxl in Xen 4.2 supports up to 128 vcpus, cur_vcpus was replaced
+ * by avail_vcpus of type libxl_bitmap
*/
- if (def->maxvcpus > 32 || def->vcpus > 32) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("This version of libxenlight only supports 32 "
- "vcpus per domain"));
+ if (def->maxvcpus > LIBXL_MAXVCPUS || def->vcpus > LIBXL_MAXVCPUS) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("This version of libxenlight only supports %u "
+ "vcpus per domain"), LIBXL_MAXVCPUS);
return -1;
}
- libxl_init_build_info(b_info, &d_config->c_info);
+ libxl_domain_build_info_init(b_info);
- b_info->hvm = hvm;
- b_info->max_vcpus = def->maxvcpus;
- if (def->vcpus == 32)
- b_info->cur_vcpus = (uint32_t) -1;
+ if (hvm)
+ libxl_domain_build_info_init_type(b_info, LIBXL_DOMAIN_TYPE_HVM);
else
- b_info->cur_vcpus = (1 << def->vcpus) - 1;
+ libxl_domain_build_info_init_type(b_info, LIBXL_DOMAIN_TYPE_PV);
+ b_info->max_vcpus = def->maxvcpus;
+ libxl_bitmap_set((&b_info->avail_vcpus), def->vcpus);
if (def->clock.ntimers > 0 &&
def->clock.timers[0]->name == VIR_DOMAIN_TIMER_NAME_TSC) {
switch (def->clock.timers[0]->mode) {
@@ -426,16 +490,20 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_domain_config *d_config)
b_info->tsc_mode = 1;
}
}
+ b_info->sched_params.weight = 1000;
b_info->max_memkb = def->mem.max_balloon;
b_info->target_memkb = def->mem.cur_balloon;
if (hvm) {
- b_info->u.hvm.pae = def->features & (1 << VIR_DOMAIN_FEATURE_PAE);
- b_info->u.hvm.apic = def->features & (1 << VIR_DOMAIN_FEATURE_APIC);
- b_info->u.hvm.acpi = def->features & (1 << VIR_DOMAIN_FEATURE_ACPI);
+ libxl_defbool_set(&b_info->u.hvm.pae,
+ def->features & (1 << VIR_DOMAIN_FEATURE_PAE));
+ libxl_defbool_set(&b_info->u.hvm.apic,
+ def->features & (1 << VIR_DOMAIN_FEATURE_APIC));
+ libxl_defbool_set(&b_info->u.hvm.acpi,
+ def->features & (1 << VIR_DOMAIN_FEATURE_ACPI));
for (i = 0; i < def->clock.ntimers; i++) {
if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET &&
def->clock.timers[i]->present == 1) {
- b_info->u.hvm.hpet = 1;
+ libxl_defbool_set(&b_info->u.hvm.hpet, 1);
}
}
@@ -446,7 +514,7 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_domain_config *d_config)
* 256 pages (1MB) per vcpu, plus 1 page per MiB of RAM for the P2M map,
* plus 1 page per MiB of RAM to shadow the resident processes.
*/
- b_info->shadow_memkb = 4 * (256 * b_info->cur_vcpus +
+ b_info->shadow_memkb = 4 * (256 * libxl_bitmap_count_set(&b_info->avail_vcpus) +
2 * (b_info->max_memkb / 1024));
} else {
if (def->os.bootloader) {
@@ -456,10 +524,11 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_domain_config *d_config)
}
}
if (def->os.bootloaderArgs) {
- if ((b_info->u.pv.bootloader_args = strdup(def->os.bootloaderArgs)) == NULL) {
- virReportOOMError();
+ if (libxlSplitStringIntoStringList(def->os.bootloaderArgs,
+ " \t\n",
+ &b_info->u.pv.bootloader_args)
+ < 0)
goto error;
- }
}
if (def->os.cmdline) {
if ((b_info->u.pv.cmdline = strdup(def->os.cmdline)) == NULL) {
@@ -469,14 +538,14 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_domain_config *d_config)
}
if (def->os.kernel) {
/* libxl_init_build_info() sets kernel.path = strdup("hvmloader") */
- VIR_FREE(b_info->kernel.path);
- if ((b_info->kernel.path = strdup(def->os.kernel)) == NULL) {
+ VIR_FREE(b_info->u.pv.kernel);
+ if ((b_info->u.pv.kernel = strdup(def->os.kernel)) == NULL) {
virReportOOMError();
goto error;
}
}
if (def->os.initrd) {
- if ((b_info->u.pv.ramdisk.path = strdup(def->os.initrd)) == NULL) {
+ if ((b_info->u.pv.ramdisk = strdup(def->os.initrd)) == NULL) {
virReportOOMError();
goto error;
}
@@ -486,13 +555,12 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_domain_config *d_config)
return 0;
error:
- libxl_domain_build_info_destroy(b_info);
+ libxl_domain_build_info_dispose(b_info);
return -1;
}
int
-libxlMakeDisk(virDomainDefPtr def, virDomainDiskDefPtr l_disk,
- libxl_device_disk *x_disk)
+libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk)
{
if (l_disk->src && (x_disk->pdev_path = strdup(l_disk->src)) == NULL) {
virReportOOMError();
@@ -509,22 +577,22 @@ libxlMakeDisk(virDomainDefPtr def, virDomainDiskDefPtr l_disk,
STREQ(l_disk->driverName, "tap2")) {
switch (l_disk->format) {
case VIR_STORAGE_FILE_QCOW:
- x_disk->format = DISK_FORMAT_QCOW;
- x_disk->backend = DISK_BACKEND_QDISK;
+ x_disk->format = LIBXL_DISK_FORMAT_QCOW;
+ x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
break;
case VIR_STORAGE_FILE_QCOW2:
- x_disk->format = DISK_FORMAT_QCOW2;
- x_disk->backend = DISK_BACKEND_QDISK;
+ x_disk->format = LIBXL_DISK_FORMAT_QCOW2;
+ x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
break;
case VIR_STORAGE_FILE_VHD:
- x_disk->format = DISK_FORMAT_VHD;
- x_disk->backend = DISK_BACKEND_TAP;
+ x_disk->format = LIBXL_DISK_FORMAT_VHD;
+ x_disk->backend = LIBXL_DISK_BACKEND_TAP;
break;
case VIR_STORAGE_FILE_NONE:
/* No subtype specified, default to raw/tap */
case VIR_STORAGE_FILE_RAW:
- x_disk->format = DISK_FORMAT_RAW;
- x_disk->backend = DISK_BACKEND_TAP;
+ x_disk->format = LIBXL_DISK_FORMAT_RAW;
+ x_disk->backend = LIBXL_DISK_BACKEND_TAP;
break;
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -533,11 +601,11 @@ libxlMakeDisk(virDomainDefPtr def, virDomainDiskDefPtr l_disk,
return -1;
}
} else if (STREQ(l_disk->driverName, "file")) {
- x_disk->format = DISK_FORMAT_RAW;
- x_disk->backend = DISK_BACKEND_TAP;
+ x_disk->format = LIBXL_DISK_FORMAT_RAW;
+ x_disk->backend = LIBXL_DISK_BACKEND_TAP;
} else if (STREQ(l_disk->driverName, "phy")) {
- x_disk->format = DISK_FORMAT_RAW;
- x_disk->backend = DISK_BACKEND_PHY;
+ x_disk->format = LIBXL_DISK_FORMAT_RAW;
+ x_disk->backend = LIBXL_DISK_BACKEND_PHY;
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("libxenlight does not support disk driver %s"),
@@ -546,12 +614,12 @@ libxlMakeDisk(virDomainDefPtr def, virDomainDiskDefPtr l_disk,
}
} else {
/* No driverName - default to raw/tap?? */
- x_disk->format = DISK_FORMAT_RAW;
- x_disk->backend = DISK_BACKEND_TAP;
+ x_disk->format = LIBXL_DISK_FORMAT_RAW;
+ x_disk->backend = LIBXL_DISK_BACKEND_TAP;
}
- /* How to set unpluggable? */
- x_disk->unpluggable = 1;
+ /* XXX is this right? */
+ x_disk->removable = 1;
x_disk->readwrite = !l_disk->readonly;
x_disk->is_cdrom = l_disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ? 1 : 0;
if (l_disk->transient) {
@@ -560,8 +628,6 @@ libxlMakeDisk(virDomainDefPtr def, virDomainDiskDefPtr l_disk,
return -1;
}
- x_disk->domid = def->id;
-
return 0;
}
@@ -579,7 +645,7 @@ libxlMakeDiskList(virDomainDefPtr def, libxl_domain_config *d_config)
}
for (i = 0; i < ndisks; i++) {
- if (libxlMakeDisk(def, l_disks[i], &x_disks[i]) < 0)
+ if (libxlMakeDisk(l_disks[i], &x_disks[i]) < 0)
goto error;
}
@@ -590,19 +656,19 @@ libxlMakeDiskList(virDomainDefPtr def, libxl_domain_config *d_config)
error:
for (i = 0; i < ndisks; i++)
- libxl_device_disk_destroy(&x_disks[i]);
+ libxl_device_disk_dispose(&x_disks[i]);
VIR_FREE(x_disks);
return -1;
}
int
-libxlMakeNic(virDomainDefPtr def, virDomainNetDefPtr l_nic,
- libxl_device_nic *x_nic)
+libxlMakeNic(virDomainNetDefPtr l_nic, libxl_device_nic *x_nic)
{
- // TODO: Where is mtu stored?
- //x_nics[i].mtu = 1492;
+ /* TODO: Where is mtu stored?
+ *
+ * x_nics[i].mtu = 1492;
+ */
- x_nic->domid = def->id;
virMacAddrGetRaw(&l_nic->mac, x_nic->mac);
if (l_nic->model && !STREQ(l_nic->model, "netfront")) {
@@ -610,9 +676,9 @@ libxlMakeNic(virDomainDefPtr def, virDomainNetDefPtr l_nic,
virReportOOMError();
return -1;
}
- x_nic->nictype = NICTYPE_IOEMU;
+ x_nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
} else {
- x_nic->nictype = NICTYPE_VIF;
+ x_nic->nictype = LIBXL_NIC_TYPE_VIF;
}
if (l_nic->ifname && (x_nic->ifname = strdup(l_nic->ifname)) == NULL) {
@@ -659,48 +725,49 @@ libxlMakeNicList(virDomainDefPtr def, libxl_domain_config *d_config)
for (i = 0; i < nnics; i++) {
x_nics[i].devid = i;
- if (libxlMakeNic(def, l_nics[i], &x_nics[i]))
+ if (libxlMakeNic(l_nics[i], &x_nics[i]))
goto error;
}
- d_config->vifs = x_nics;
- d_config->num_vifs = nnics;
+ d_config->nics = x_nics;
+ d_config->num_nics = nnics;
return 0;
error:
for (i = 0; i < nnics; i++)
- libxl_device_nic_destroy(&x_nics[i]);
+ libxl_device_nic_dispose(&x_nics[i]);
VIR_FREE(x_nics);
return -1;
}
int
-libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainDefPtr def,
- virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb)
+libxlMakeVfb(libxlDriverPrivatePtr driver,
+ virDomainGraphicsDefPtr l_vfb,
+ libxl_device_vfb *x_vfb)
{
int port;
const char *listenAddr;
switch (l_vfb->type) {
case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
- x_vfb->sdl = 1;
+ libxl_defbool_set(&x_vfb->sdl.enable, 1);
if (l_vfb->data.sdl.display &&
- (x_vfb->display = strdup(l_vfb->data.sdl.display)) == NULL) {
+ (x_vfb->sdl.display = strdup(l_vfb->data.sdl.display)) == NULL) {
virReportOOMError();
return -1;
}
if (l_vfb->data.sdl.xauth &&
- (x_vfb->xauthority =
+ (x_vfb->sdl.xauthority =
strdup(l_vfb->data.sdl.xauth)) == NULL) {
virReportOOMError();
return -1;
}
break;
case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
- x_vfb->vnc = 1;
+ libxl_defbool_set(&x_vfb->vnc.enable, 1);
/* driver handles selection of free port */
- x_vfb->vncunused = 0;
+ libxl_defbool_set(&x_vfb->vnc.findunused, 0);
if (l_vfb->data.vnc.autoport) {
port = libxlNextFreeVncPort(driver, LIBXL_VNC_PORT_MIN);
if (port < 0) {
@@ -710,13 +777,13 @@ libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainDefPtr def,
}
l_vfb->data.vnc.port = port;
}
- x_vfb->vncdisplay = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN;
+ x_vfb->vnc.display = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN;
listenAddr = virDomainGraphicsListenGetAddress(l_vfb, 0);
if (listenAddr) {
/* libxl_device_vfb_init() does strdup("127.0.0.1") */
- VIR_FREE(x_vfb->vnclisten);
- if ((x_vfb->vnclisten = strdup(listenAddr)) == NULL) {
+ VIR_FREE(x_vfb->vnc.listen);
+ if ((x_vfb->vnc.listen = strdup(listenAddr)) == NULL) {
virReportOOMError();
return -1;
}
@@ -729,13 +796,14 @@ libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainDefPtr def,
}
break;
}
- x_vfb->domid = def->id;
+
return 0;
}
static int
libxlMakeVfbList(libxlDriverPrivatePtr driver,
- virDomainDefPtr def, libxl_domain_config *d_config)
+ virDomainDefPtr def,
+ libxl_domain_config *d_config)
{
virDomainGraphicsDefPtr *l_vfbs = def->graphics;
int nvfbs = def->ngraphics;
@@ -757,10 +825,10 @@ libxlMakeVfbList(libxlDriverPrivatePtr driver,
}
for (i = 0; i < nvfbs; i++) {
- libxl_device_vfb_init(&x_vfbs[i], i);
- libxl_device_vkb_init(&x_vkbs[i], i);
+ libxl_device_vfb_init(&x_vfbs[i]);
+ libxl_device_vkb_init(&x_vkbs[i]);
- if (libxlMakeVfb(driver, def, l_vfbs[i], &x_vfbs[i]) < 0)
+ if (libxlMakeVfb(driver, l_vfbs[i], &x_vfbs[i]) < 0)
goto error;
}
@@ -772,148 +840,14 @@ libxlMakeVfbList(libxlDriverPrivatePtr driver,
error:
for (i = 0; i < nvfbs; i++) {
- libxl_device_vfb_destroy(&x_vfbs[i]);
- libxl_device_vkb_destroy(&x_vkbs[i]);
+ libxl_device_vfb_dispose(&x_vfbs[i]);
+ libxl_device_vkb_dispose(&x_vkbs[i]);
}
VIR_FREE(x_vfbs);
VIR_FREE(x_vkbs);
return -1;
}
-static int
-libxlMakeChrdevStr(virDomainChrDefPtr def, char **buf)
-{
- const char *type = virDomainChrTypeToString(def->source.type);
-
- if (!type) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("unexpected chr device type"));
- return -1;
- }
-
- switch (def->source.type) {
- case VIR_DOMAIN_CHR_TYPE_NULL:
- case VIR_DOMAIN_CHR_TYPE_STDIO:
- case VIR_DOMAIN_CHR_TYPE_VC:
- case VIR_DOMAIN_CHR_TYPE_PTY:
- if (virAsprintf(buf, "%s", type) < 0) {
- virReportOOMError();
- return -1;
- }
- break;
-
- case VIR_DOMAIN_CHR_TYPE_FILE:
- case VIR_DOMAIN_CHR_TYPE_PIPE:
- if (virAsprintf(buf, "%s:%s", type,
- def->source.data.file.path) < 0) {
- virReportOOMError();
- return -1;
- }
- break;
-
- case VIR_DOMAIN_CHR_TYPE_DEV:
- if (virAsprintf(buf, "%s", def->source.data.file.path) < 0) {
- virReportOOMError();
- return -1;
- }
- break;
- }
-
- return 0;
-}
-
-static int
-libxlMakeDeviceModelInfo(virDomainDefPtr def, libxl_domain_config *d_config)
-{
- libxl_device_model_info *dm_info = &d_config->dm_info;
- int i;
- char b_order[VIR_DOMAIN_BOOT_LAST+1];
-
- libxl_init_dm_info(dm_info, &d_config->c_info, &d_config->b_info);
-
- if (d_config->b_info.hvm) {
- /* HVM-specific device model info */
- dm_info->type = XENFV;
- if (def->os.nBootDevs > 0) {
- VIR_FREE(dm_info->boot);
- for (i = 0; i < def->os.nBootDevs; i++) {
- switch (def->os.bootDevs[i]) {
- case VIR_DOMAIN_BOOT_FLOPPY:
- b_order[i] = 'a';
- break;
- default:
- case VIR_DOMAIN_BOOT_DISK:
- b_order[i] = 'c';
- break;
- case VIR_DOMAIN_BOOT_CDROM:
- b_order[i] = 'd';
- break;
- case VIR_DOMAIN_BOOT_NET:
- b_order[i] = 'n';
- break;
- }
- }
- b_order[def->os.nBootDevs] = '\0';
- if ((dm_info->boot = strdup(b_order)) == NULL) {
- virReportOOMError();
- goto error;
- }
- }
- if (def->serials &&
- (libxlMakeChrdevStr(def->serials[0], &dm_info->serial) < 0))
- goto error;
- } else {
- /* PV-specific device model info */
- dm_info->type = XENPV;
- }
-
- /* Build qemu graphics options from previously parsed vfb */
- if (d_config->num_vfbs > 0) {
- if (d_config->vfbs[0].vnc) {
- dm_info->vnc = 1;
- /* driver handles selection of free port */
- dm_info->vncunused = 0;
- if (d_config->vfbs[0].vnclisten) {
- VIR_FREE(dm_info->vnclisten);
- if ((dm_info->vnclisten =
- strdup(d_config->vfbs[0].vnclisten)) == NULL) {
- virReportOOMError();
- goto error;
- }
- }
- if (d_config->vfbs[0].keymap &&
- (dm_info->keymap = strdup(d_config->vfbs[0].keymap)) == NULL) {
- virReportOOMError();
- goto error;
- }
- dm_info->vncdisplay = d_config->vfbs[0].vncdisplay;
- if (d_config->vfbs[0].vncpasswd &&
- (dm_info->vncpasswd =
- strdup(d_config->vfbs[0].vncpasswd)) == NULL) {
- virReportOOMError();
- goto error;
- }
- } else if (d_config->vfbs[0].sdl) {
- dm_info->sdl = 1;
- dm_info->vnc = 0;
- }
- } else if (d_config->num_vfbs == 0) {
- dm_info->nographic = 1;
- dm_info->vnc = 0;
- }
-
- // TODO
- //dm_info->usb = ;
- //dm_info->usbdevice = ;
- //dm_info->soundhw = ;
-
- return 0;
-
-error:
- libxl_device_model_info_destroy(dm_info);
- return -1;
-}
-
virCapsPtr
libxlMakeCapabilities(libxl_ctx *ctx)
{
@@ -947,7 +881,7 @@ libxlBuildDomainConfig(libxlDriverPrivatePtr driver,
virDomainDefPtr def, libxl_domain_config *d_config)
{
- if (libxlMakeDomCreateInfo(def, &d_config->c_info) < 0)
+ if (libxlMakeDomCreateInfo(driver, def, &d_config->c_info) < 0)
return -1;
if (libxlMakeDomBuildInfo(def, d_config) < 0) {
@@ -966,10 +900,6 @@ libxlBuildDomainConfig(libxlDriverPrivatePtr driver,
goto error;
}
- if (libxlMakeDeviceModelInfo(def, d_config) < 0) {
- goto error;
- }
-
d_config->on_reboot = def->onReboot;
d_config->on_poweroff = def->onPoweroff;
d_config->on_crash = def->onCrash;
@@ -977,6 +907,6 @@ libxlBuildDomainConfig(libxlDriverPrivatePtr driver,
return 0;
error:
- libxl_domain_config_destroy(d_config);
+ libxl_domain_config_dispose(d_config);
return -1;
}
diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
index 56bf85c..ea62b68 100644
--- a/src/libxl/libxl_conf.h
+++ b/src/libxl/libxl_conf.h
@@ -37,6 +37,7 @@
# include "bitmap.h"
+# define LIBXL_MAXVCPUS 128
# define LIBXL_VNC_PORT_MIN 5900
# define LIBXL_VNC_PORT_MAX 65535
@@ -58,7 +59,7 @@ struct _libxlDriverPrivate {
FILE *logger_file;
xentoollog_logger *logger;
/* libxl ctx for driver wide ops; getVersion, getNodeInfo, ... */
- libxl_ctx ctx;
+ libxl_ctx *ctx;
virBitmapPtr reservedVNCPorts;
virDomainObjList domains;
@@ -77,10 +78,8 @@ typedef struct _libxlDomainObjPrivate libxlDomainObjPrivate;
typedef libxlDomainObjPrivate *libxlDomainObjPrivatePtr;
struct _libxlDomainObjPrivate {
/* per domain libxl ctx */
- libxl_ctx ctx;
- libxl_waiter *dWaiter;
- int waiterFD;
- int eventHdl;
+ libxl_ctx *ctx;
+ libxl_evgen_domain_death *deathW;
};
# define LIBXL_SAVE_MAGIC "libvirt-xml\n \0 \r"
@@ -100,13 +99,11 @@ virCapsPtr
libxlMakeCapabilities(libxl_ctx *ctx);
int
-libxlMakeDisk(virDomainDefPtr def, virDomainDiskDefPtr l_dev,
- libxl_device_disk *x_dev);
+libxlMakeDisk(virDomainDiskDefPtr l_dev, libxl_device_disk *x_dev);
int
-libxlMakeNic(virDomainDefPtr def, virDomainNetDefPtr l_nic,
- libxl_device_nic *x_nic);
+libxlMakeNic(virDomainNetDefPtr l_nic, libxl_device_nic *x_nic);
int
-libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainDefPtr def,
+libxlMakeVfb(libxlDriverPrivatePtr driver,
virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb);
int
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index bc75730..f15129f 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -40,6 +40,7 @@
#include "memory.h"
#include "uuid.h"
#include "command.h"
+#include "libxl.h"
#include "libxl_driver.h"
#include "libxl_conf.h"
#include "xen_xm.h"
@@ -59,6 +60,19 @@
/* Number of Xen scheduler parameters */
#define XEN_SCHED_CREDIT_NPARAM 2
+struct libxlOSEventHookFDInfo {
+ libxlDomainObjPrivatePtr priv;
+ void *xl_priv;
+ int watch;
+};
+
+struct libxlOSEventHookTimerInfo {
+ libxlDomainObjPrivatePtr priv;
+ void *xl_priv;
+ int id;
+};
+
+
static void libxlDomainManagedSaveLoad(void *payload,
const void *n ATTRIBUTE_UNUSED,
void *opaque);
@@ -84,6 +98,163 @@ libxlDriverUnlock(libxlDriverPrivatePtr driver)
virMutexUnlock(&driver->lock);
}
+
+static void libxlFDEventCallback(int watch ATTRIBUTE_UNUSED,
+ int fd,
+ int vir_events,
+ void *fdinfo)
+{
+ struct libxlOSEventHookFDInfo *info = fdinfo;
+ int events = 0;
+
+ if (vir_events & VIR_EVENT_HANDLE_READABLE)
+ events |= POLLIN;
+ if (vir_events & VIR_EVENT_HANDLE_WRITABLE)
+ events |= POLLOUT;
+ if (vir_events & VIR_EVENT_HANDLE_ERROR)
+ events |= POLLERR;
+ if (vir_events & VIR_EVENT_HANDLE_HANGUP)
+ events |= POLLHUP;
+
+ libxl_osevent_occurred_fd(info->priv->ctx, info->xl_priv, fd, 0, events);
+}
+
+static void libxlFreeFDInfo(void *obj)
+{
+ VIR_FREE(obj);
+}
+
+static int libxlFDRegisterEventHook(void *priv, int fd, void **hndp,
+ short events, void *xl_priv)
+{
+ int vir_events = VIR_EVENT_HANDLE_ERROR;
+ struct libxlOSEventHookFDInfo *fdinfo;
+
+ if (VIR_ALLOC(fdinfo) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ fdinfo->priv = priv;
+ fdinfo->xl_priv = xl_priv;
+ *hndp = fdinfo;
+
+ if (events & POLLIN)
+ vir_events |= VIR_EVENT_HANDLE_READABLE;
+ if (events & POLLOUT)
+ vir_events |= VIR_EVENT_HANDLE_WRITABLE;
+ fdinfo->watch = virEventAddHandle(fd, vir_events, libxlFDEventCallback,
+ fdinfo, libxlFreeFDInfo);
+ if (fdinfo->watch < 0) {
+ VIR_FREE(fdinfo);
+ return fdinfo->watch;
+ }
+
+ return 0;
+}
+
+static int libxlFDModifyEventHook(void *priv ATTRIBUTE_UNUSED,
+ int fd ATTRIBUTE_UNUSED,
+ void **hndp,
+ short events)
+{
+ struct libxlOSEventHookFDInfo *fdinfo = *hndp;
+ int vir_events = VIR_EVENT_HANDLE_ERROR;
+
+ if (events & POLLIN)
+ vir_events |= VIR_EVENT_HANDLE_READABLE;
+ if (events & POLLOUT)
+ vir_events |= VIR_EVENT_HANDLE_WRITABLE;
+
+ virEventUpdateHandle(fdinfo->watch, vir_events);
+ return 0;
+}
+
+static void libxlFDDeregisterEventHook(void *priv ATTRIBUTE_UNUSED,
+ int fd ATTRIBUTE_UNUSED,
+ void *hnd)
+{
+ struct libxlOSEventHookFDInfo *fdinfo = hnd;
+
+ virEventRemoveHandle(fdinfo->watch);
+}
+
+
+static void libxlTimerCallback(int timer ATTRIBUTE_UNUSED, void *timer_v)
+{
+ struct libxlOSEventHookTimerInfo *timer_info = timer_v;
+
+ libxl_osevent_occurred_timeout(timer_info->priv->ctx, timer_info->xl_priv);
+}
+
+static void libxlTimerInfoFree(void* obj)
+{
+ VIR_FREE(obj);
+}
+
+static int libxlTimeoutRegisterEventHook(void *priv,
+ void **hndp,
+ struct timeval abs_t,
+ void *for_libxl)
+{
+ struct timeval now;
+ struct libxlOSEventHookTimerInfo *timer_info;
+ int timeout, timer_id;
+
+ if (VIR_ALLOC(timer_info) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ gettimeofday(&now, NULL);
+ timeout = (abs_t.tv_usec - now.tv_usec) / 1000;
+ timeout += (abs_t.tv_sec - now.tv_sec) * 1000;
+ timer_id = virEventAddTimeout(timeout, libxlTimerCallback,
+ timer_info, libxlTimerInfoFree);
+ if (timer_id < 0) {
+ VIR_FREE(timer_info);
+ return timer_id;
+ }
+
+ timer_info->priv = priv;
+ timer_info->xl_priv = for_libxl;
+ timer_info->id = timer_id;
+ *hndp = timer_info;
+ return 0;
+}
+
+static int libxlTimeoutModifyEventHook(void *priv ATTRIBUTE_UNUSED,
+ void **hndp,
+ struct timeval abs_t)
+{
+ struct timeval now;
+ int timeout;
+ struct libxlOSEventHookTimerInfo *timer_info = *hndp;
+
+ gettimeofday(&now, NULL);
+ timeout = (abs_t.tv_usec - now.tv_usec) / 1000;
+ timeout += (abs_t.tv_sec - now.tv_sec) * 1000;
+ virEventUpdateTimeout(timer_info->id, timeout);
+ return 0;
+}
+
+static void libxlTimeoutDeregisterEventHook(void *priv ATTRIBUTE_UNUSED,
+ void *hnd)
+{
+ struct libxlOSEventHookTimerInfo *timer_info = hnd;
+
+ virEventRemoveTimeout(timer_info->id);
+}
+
+static const libxl_osevent_hooks libxl_event_callbacks = {
+ .fd_register = libxlFDRegisterEventHook,
+ .fd_modify = libxlFDModifyEventHook,
+ .fd_deregister = libxlFDDeregisterEventHook,
+ .timeout_register = libxlTimeoutRegisterEventHook,
+ .timeout_modify = libxlTimeoutModifyEventHook,
+ .timeout_deregister = libxlTimeoutDeregisterEventHook,
+};
+
static void *
libxlDomainObjPrivateAlloc(void)
{
@@ -92,9 +263,9 @@ libxlDomainObjPrivateAlloc(void)
if (VIR_ALLOC(priv) < 0)
return NULL;
- libxl_ctx_init(&priv->ctx, LIBXL_VERSION, libxl_driver->logger);
- priv->waiterFD = -1;
- priv->eventHdl = -1;
+ libxl_ctx_alloc(&priv->ctx, LIBXL_VERSION, 0, libxl_driver->logger);
+ priv->deathW = NULL;
+ libxl_osevent_register_hooks(priv->ctx, &libxl_event_callbacks, priv);
return priv;
}
@@ -104,16 +275,12 @@ libxlDomainObjPrivateFree(void *data)
{
libxlDomainObjPrivatePtr priv = data;
- if (priv->eventHdl >= 0)
- virEventRemoveHandle(priv->eventHdl);
-
- if (priv->dWaiter) {
- libxl_stop_waiting(&priv->ctx, priv->dWaiter);
- libxl_free_waiter(priv->dWaiter);
- VIR_FREE(priv->dWaiter);
+ if (priv->deathW) {
+ libxl_evdisable_domain_death(priv->ctx, priv->deathW);
+ VIR_FREE(priv->deathW);
}
- libxl_ctx_free(&priv->ctx);
+ libxl_ctx_free(priv->ctx);
VIR_FREE(priv);
}
@@ -125,17 +292,6 @@ libxlDomainEventQueue(libxlDriverPrivatePtr driver, virDomainEventPtr event)
virDomainEventStateQueue(driver->domainEventState, event);
}
-/*
- * Remove reference to domain object.
- */
-static void
-libxlDomainObjUnref(void *data)
-{
- virDomainObjPtr vm = data;
-
- virObjectUnref(vm);
-}
-
static void
libxlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED,
void *opaque)
@@ -166,13 +322,13 @@ libxlDoNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info)
const libxl_version_info* ver_info;
struct utsname utsname;
- if (libxl_get_physinfo(&driver->ctx, &phy_info)) {
+ if (libxl_get_physinfo(driver->ctx, &phy_info)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("libxl_get_physinfo_info failed"));
return -1;
}
- if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) {
+ if ((ver_info = libxl_get_version_info(driver->ctx)) == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("libxl_get_version_info failed"));
return -1;
@@ -296,15 +452,9 @@ libxlVmCleanup(libxlDriverPrivatePtr driver,
char *file;
int i;
- if (priv->eventHdl >= 0) {
- virEventRemoveHandle(priv->eventHdl);
- priv->eventHdl = -1;
- }
-
- if (priv->dWaiter) {
- libxl_stop_waiting(&priv->ctx, priv->dWaiter);
- libxl_free_waiter(priv->dWaiter);
- VIR_FREE(priv->dWaiter);
+ if (priv->deathW) {
+ libxl_evdisable_domain_death(priv->ctx, priv->deathW);
+ priv->deathW = NULL;
}
if (vm->persistent) {
@@ -355,12 +505,11 @@ libxlVmCleanup(libxlDriverPrivatePtr driver,
static int
libxlVmReap(libxlDriverPrivatePtr driver,
virDomainObjPtr vm,
- int force,
virDomainShutoffReason reason)
{
libxlDomainObjPrivatePtr priv = vm->privateData;
- if (libxl_domain_destroy(&priv->ctx, vm->def->id, force) < 0) {
+ if (libxl_domain_destroy(priv->ctx, vm->def->id, NULL) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to cleanup domain %d"), vm->def->id);
return -1;
@@ -373,56 +522,26 @@ libxlVmReap(libxlDriverPrivatePtr driver,
/*
* Handle previously registered event notification from libxenlight
*/
-static void libxlEventHandler(int watch,
- int fd,
- int events,
- void *data)
+static void libxlEventHandler(void *data, const libxl_event *event)
{
libxlDriverPrivatePtr driver = libxl_driver;
virDomainObjPtr vm = data;
- libxlDomainObjPrivatePtr priv;
virDomainEventPtr dom_event = NULL;
- libxl_event event;
- libxl_dominfo info;
libxlDriverLock(driver);
virDomainObjLock(vm);
libxlDriverUnlock(driver);
- priv = vm->privateData;
-
- memset(&event, 0, sizeof(event));
- memset(&info, 0, sizeof(info));
-
- if (priv->waiterFD != fd || priv->eventHdl != watch) {
- virEventRemoveHandle(watch);
- priv->eventHdl = -1;
- goto cleanup;
- }
-
- if (!(events & VIR_EVENT_HANDLE_READABLE))
- goto cleanup;
-
- if (libxl_get_event(&priv->ctx, &event))
- goto cleanup;
-
- if (event.type == LIBXL_EVENT_DOMAIN_DEATH) {
+ if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) {
virDomainShutoffReason reason;
- /* libxl_event_get_domain_death_info returns 1 if death
- * event was for this domid */
- if (libxl_event_get_domain_death_info(&priv->ctx,
- vm->def->id,
- &event,
- &info) != 1)
+ if (event->domid != vm->def->id)
goto cleanup;
- virEventRemoveHandle(watch);
- priv->eventHdl = -1;
- switch (info.shutdown_reason) {
- case SHUTDOWN_poweroff:
- case SHUTDOWN_crash:
- if (info.shutdown_reason == SHUTDOWN_crash) {
+ switch (event->u.domain_shutdown.shutdown_reason) {
+ case LIBXL_SHUTDOWN_REASON_POWEROFF:
+ case LIBXL_SHUTDOWN_REASON_CRASH:
+ if (event->u.domain_shutdown.shutdown_reason == LIBXL_SHUTDOWN_REASON_CRASH) {
dom_event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_CRASHED);
@@ -430,18 +549,18 @@ static void libxlEventHandler(int watch,
} else {
reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
}
- libxlVmReap(driver, vm, 0, reason);
+ libxlVmReap(driver, vm, reason);
if (!vm->persistent) {
virDomainRemoveInactive(&driver->domains, vm);
vm = NULL;
}
break;
- case SHUTDOWN_reboot:
- libxlVmReap(driver, vm, 0, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
+ case LIBXL_SHUTDOWN_REASON_REBOOT:
+ libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
libxlVmStart(driver, vm, 0, -1);
break;
default:
- VIR_INFO("Unhandled shutdown_reason %d", info.shutdown_reason);
+ VIR_INFO("Unhandled shutdown_reason %d", event->u.domain_shutdown.shutdown_reason);
break;
}
}
@@ -454,9 +573,14 @@ cleanup:
libxlDomainEventQueue(driver, dom_event);
libxlDriverUnlock(driver);
}
- libxl_free_event(&event);
}
+static const struct libxl_event_hooks ev_hooks = {
+ .event_occurs_mask = LIBXL_EVENTMASK_ALL,
+ .event_occurs = libxlEventHandler,
+ .disaster = NULL,
+};
+
/*
* Register domain events with libxenlight and insert event handles
* in libvirt's event loop.
@@ -465,40 +589,18 @@ static int
libxlCreateDomEvents(virDomainObjPtr vm)
{
libxlDomainObjPrivatePtr priv = vm->privateData;
- int fd;
- if (VIR_ALLOC(priv->dWaiter) < 0) {
- virReportOOMError();
- return -1;
- }
-
- if (libxl_wait_for_domain_death(&priv->ctx, vm->def->id, priv->dWaiter))
- goto error;
-
- libxl_get_wait_fd(&priv->ctx, &fd);
- if (fd < 0)
- goto error;
+ libxl_event_register_callbacks(priv->ctx, &ev_hooks, vm);
- priv->waiterFD = fd;
- /* Add a reference to the domain object while it is injected in
- * the event loop.
- */
- virObjectRef(vm);
- if ((priv->eventHdl = virEventAddHandle(
- fd,
- VIR_EVENT_HANDLE_READABLE | VIR_EVENT_HANDLE_ERROR,
- libxlEventHandler,
- vm, libxlDomainObjUnref)) < 0) {
- virObjectUnref(vm);
+ if (libxl_evenable_domain_death(priv->ctx, vm->def->id, 0, &priv->deathW))
goto error;
- }
return 0;
error:
- libxl_free_waiter(priv->dWaiter);
- VIR_FREE(priv->dWaiter);
- priv->eventHdl = -1;
+ if (priv->deathW)
+ libxl_evdisable_domain_death(priv->ctx, priv->deathW);
+ VIR_FREE(priv->deathW);
return -1;
}
@@ -507,7 +609,7 @@ libxlDomainSetVcpuAffinites(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
{
libxlDomainObjPrivatePtr priv = vm->privateData;
virDomainDefPtr def = vm->def;
- libxl_cpumap map;
+ libxl_bitmap map;
uint8_t *cpumask = NULL;
uint8_t *cpumap = NULL;
virNodeInfo nodeinfo;
@@ -539,7 +641,7 @@ libxlDomainSetVcpuAffinites(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
map.size = cpumaplen;
map.map = cpumap;
- if (libxl_set_vcpuaffinity(&priv->ctx, def->id, vcpu, &map) != 0) {
+ if (libxl_set_vcpuaffinity(priv->ctx, def->id, vcpu, &map) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to pin vcpu '%d' with libxenlight"), vcpu);
goto cleanup;
@@ -565,11 +667,10 @@ libxlFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config)
int tries = 3;
int wait_secs = 10;
- if ((ret = libxl_domain_need_memory(&priv->ctx, &d_config->b_info,
- &d_config->dm_info,
+ if ((ret = libxl_domain_need_memory(priv->ctx, &d_config->b_info,
&needed_mem)) >= 0) {
for (i = 0; i < tries; ++i) {
- if ((ret = libxl_get_free_memory(&priv->ctx, &free_mem)) < 0)
+ if ((ret = libxl_get_free_memory(priv->ctx, &free_mem)) < 0)
break;
if (free_mem >= needed_mem) {
@@ -577,17 +678,17 @@ libxlFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config)
break;
}
- if ((ret = libxl_set_memory_target(&priv->ctx, 0,
+ if ((ret = libxl_set_memory_target(priv->ctx, 0,
free_mem - needed_mem,
/* relative */ 1, 0)) < 0)
break;
- ret = libxl_wait_for_free_memory(&priv->ctx, 0, needed_mem,
+ ret = libxl_wait_for_free_memory(priv->ctx, 0, needed_mem,
wait_secs);
if (ret == 0 || ret != ERROR_NOMEM)
break;
- if ((ret = libxl_wait_for_memory_target(&priv->ctx, 0, 1)) < 0)
+ if ((ret = libxl_wait_for_memory_target(priv->ctx, 0, 1)) < 0)
break;
}
}
@@ -613,7 +714,6 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
char *dom_xml = NULL;
char *managed_save_path = NULL;
int managed_save_fd = -1;
- pid_t child_console_pid = -1;
libxlDomainObjPrivatePtr priv = vm->privateData;
/* If there is a managed saved state restore it instead of starting
@@ -657,7 +757,7 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
VIR_FREE(managed_save_path);
}
- memset(&d_config, 0, sizeof(d_config));
+ libxl_domain_config_init(&d_config);
if (libxlBuildDomainConfig(driver, vm->def, &d_config) < 0)
return -1;
@@ -669,13 +769,14 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
goto error;
}
+ /* use as synchronous operations => ao_how = NULL and no intermediate reports => ao_progress = NULL */
+
if (restore_fd < 0)
- ret = libxl_domain_create_new(&priv->ctx, &d_config,
- NULL, &child_console_pid, &domid);
+ ret = libxl_domain_create_new(priv->ctx, &d_config,
+ &domid, NULL, NULL);
else
- ret = libxl_domain_create_restore(&priv->ctx, &d_config, NULL,
- &child_console_pid, &domid,
- restore_fd);
+ ret = libxl_domain_create_restore(priv->ctx, &d_config, &domid,
+ restore_fd, NULL, NULL);
if (ret) {
if (restore_fd < 0)
@@ -693,7 +794,7 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
if ((dom_xml = virDomainDefFormat(vm->def, 0)) == NULL)
goto error;
- if (libxl_userdata_store(&priv->ctx, domid, "libvirt-xml",
+ if (libxl_userdata_store(priv->ctx, domid, "libvirt-xml",
(uint8_t *)dom_xml, strlen(dom_xml) + 1)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("libxenlight failed to store userdata"));
@@ -707,7 +808,7 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
goto error;
if (!start_paused) {
- libxl_domain_unpause(&priv->ctx, domid);
+ libxl_domain_unpause(priv->ctx, domid);
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
} else {
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
@@ -723,18 +824,18 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
VIR_DOMAIN_EVENT_STARTED_RESTORED);
libxlDomainEventQueue(driver, event);
- libxl_domain_config_destroy(&d_config);
+ libxl_domain_config_dispose(&d_config);
VIR_FREE(dom_xml);
VIR_FORCE_CLOSE(managed_save_fd);
return 0;
error:
if (domid > 0) {
- libxl_domain_destroy(&priv->ctx, domid, 0);
+ libxl_domain_destroy(priv->ctx, domid, NULL);
vm->def->id = -1;
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_FAILED);
}
- libxl_domain_config_destroy(&d_config);
+ libxl_domain_config_dispose(&d_config);
VIR_FREE(dom_xml);
VIR_FREE(managed_save_path);
virDomainDefFree(def);
@@ -762,7 +863,7 @@ libxlReconnectDomain(void *payload,
virDomainObjLock(vm);
/* Does domain still exist? */
- rc = libxl_domain_info(&driver->ctx, &d_info, vm->def->id);
+ rc = libxl_domain_info(driver->ctx, &d_info, vm->def->id);
if (rc == ERROR_INVAL) {
goto out;
} else if (rc != 0) {
@@ -772,7 +873,7 @@ libxlReconnectDomain(void *payload,
}
/* Is this a domain that was under libvirt control? */
- if (libxl_userdata_retrieve(&driver->ctx, vm->def->id,
+ if (libxl_userdata_retrieve(driver->ctx, vm->def->id,
"libvirt-xml", &data, &len)) {
VIR_DEBUG("libxl_userdata_retrieve failed, ignoring domain %d", vm->def->id);
goto out;
@@ -810,7 +911,7 @@ libxlShutdown(void)
libxlDriverLock(libxl_driver);
virCapabilitiesFree(libxl_driver->caps);
virDomainObjListDeinit(&libxl_driver->domains);
- libxl_ctx_free(&libxl_driver->ctx);
+ libxl_ctx_free(libxl_driver->ctx);
xtl_logger_destroy(libxl_driver->logger);
if (libxl_driver->logger_file)
VIR_FORCE_FCLOSE(libxl_driver->logger_file);
@@ -943,14 +1044,14 @@ libxlStartup(int privileged) {
goto fail;
}
- if (libxl_ctx_init(&libxl_driver->ctx,
- LIBXL_VERSION,
+ if (libxl_ctx_alloc(&libxl_driver->ctx,
+ LIBXL_VERSION, 0,
libxl_driver->logger)) {
VIR_INFO("cannot initialize libxenlight context, probably not running in a Xen Dom0, disabling driver");
goto fail;
}
- if ((ver_info = libxl_get_version_info(&libxl_driver->ctx)) == NULL) {
+ if ((ver_info = libxl_get_version_info(libxl_driver->ctx)) == NULL) {
VIR_INFO("cannot version information from libxenlight, disabling driver");
goto fail;
}
@@ -958,7 +1059,7 @@ libxlStartup(int privileged) {
(ver_info->xen_version_minor * 1000);
if ((libxl_driver->caps =
- libxlMakeCapabilities(&libxl_driver->ctx)) == NULL) {
+ libxlMakeCapabilities(libxl_driver->ctx)) == NULL) {
VIR_ERROR(_("cannot create capabilities for libxenlight"));
goto error;
}
@@ -1115,7 +1216,7 @@ libxlGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
int ret;
libxlDriverPrivatePtr driver = conn->privateData;
- ret = libxl_get_max_cpus(&driver->ctx);
+ ret = libxl_get_max_cpus(driver->ctx);
/* libxl_get_max_cpus() will return 0 if there were any failures,
e.g. xc_physinfo() failing */
if (ret == 0)
@@ -1320,7 +1421,7 @@ libxlDomainSuspend(virDomainPtr dom)
priv = vm->privateData;
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
- if (libxl_domain_pause(&priv->ctx, dom->id) != 0) {
+ if (libxl_domain_pause(priv->ctx, dom->id) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to suspend domain '%d' with libxenlight"),
dom->id);
@@ -1379,7 +1480,7 @@ libxlDomainResume(virDomainPtr dom)
priv = vm->privateData;
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
- if (libxl_domain_unpause(&priv->ctx, dom->id) != 0) {
+ if (libxl_domain_unpause(priv->ctx, dom->id) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to resume domain '%d' with libxenlight"),
dom->id);
@@ -1436,7 +1537,7 @@ libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
}
priv = vm->privateData;
- if (libxl_domain_shutdown(&priv->ctx, dom->id, LIBXL_DOM_REQ_POWEROFF) != 0) {
+ if (libxl_domain_shutdown(priv->ctx, dom->id) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to shutdown domain '%d' with libxenlight"),
dom->id);
@@ -1489,7 +1590,7 @@ libxlDomainReboot(virDomainPtr dom, unsigned int flags)
}
priv = vm->privateData;
- if (libxl_domain_shutdown(&priv->ctx, dom->id, LIBXL_DOM_REQ_REBOOT) != 0) {
+ if (libxl_domain_reboot(priv->ctx, dom->id) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to reboot domain '%d' with libxenlight"),
dom->id);
@@ -1534,7 +1635,7 @@ libxlDomainDestroyFlags(virDomainPtr dom,
event = virDomainEventNewFromObj(vm,VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
- if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_DESTROYED) != 0) {
+ if (libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to destroy domain '%d'"), dom->id);
goto cleanup;
@@ -1672,7 +1773,7 @@ libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
if (flags & VIR_DOMAIN_MEM_LIVE) {
priv = vm->privateData;
- if (libxl_domain_setmaxmem(&priv->ctx, dom->id, newmem) < 0) {
+ if (libxl_domain_setmaxmem(priv->ctx, dom->id, newmem) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to set maximum memory for domain '%d'"
" with libxenlight"), dom->id);
@@ -1701,7 +1802,7 @@ libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
if (flags & VIR_DOMAIN_MEM_LIVE) {
priv = vm->privateData;
- if (libxl_set_memory_target(&priv->ctx, dom->id, newmem, 0,
+ if (libxl_set_memory_target(priv->ctx, dom->id, newmem, 0,
/* force */ 1) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to set memory for domain '%d'"
@@ -1761,7 +1862,7 @@ libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
info->memory = vm->def->mem.cur_balloon;
info->maxMem = vm->def->mem.max_balloon;
} else {
- if (libxl_domain_info(&driver->ctx, &d_info, dom->id) != 0) {
+ if (libxl_domain_info(driver->ctx, &d_info, dom->id) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("libxl_domain_info failed for domain '%d'"), dom->id);
goto cleanup;
@@ -1861,7 +1962,7 @@ libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
goto cleanup;
}
- if (libxl_domain_suspend(&priv->ctx, NULL, vm->def->id, fd) != 0) {
+ if (libxl_domain_suspend(priv->ctx, vm->def->id, fd, 0, NULL) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to save domain '%d' with libxenlight"),
vm->def->id);
@@ -1871,7 +1972,7 @@ libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_SAVED);
- if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_SAVED) != 0) {
+ if (libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to destroy domain '%d'"), vm->def->id);
goto cleanup;
@@ -2028,7 +2129,7 @@ libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
if (!(flags & VIR_DUMP_LIVE) &&
virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
- if (libxl_domain_pause(&priv->ctx, dom->id) != 0) {
+ if (libxl_domain_pause(priv->ctx, dom->id) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Before dumping core, failed to suspend domain '%d'"
" with libxenlight"),
@@ -2039,7 +2140,7 @@ libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
paused = true;
}
- if (libxl_domain_core_dump(&priv->ctx, dom->id, to) != 0) {
+ if (libxl_domain_core_dump(priv->ctx, dom->id, to, NULL) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to dump core of domain '%d' with libxenlight"),
dom->id);
@@ -2048,7 +2149,7 @@ libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
libxlDriverLock(driver);
if (flags & VIR_DUMP_CRASH) {
- if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_CRASHED) != 0) {
+ if (libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to destroy domain '%d'"), dom->id);
goto cleanup_unlock;
@@ -2069,7 +2170,7 @@ cleanup_unlock:
libxlDriverUnlock(driver);
cleanup_unpause:
if (virDomainObjIsActive(vm) && paused) {
- if (libxl_domain_unpause(&priv->ctx, dom->id) != 0) {
+ if (libxl_domain_unpause(priv->ctx, dom->id) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("After dumping core, failed to resume domain '%d' with"
" libxenlight"), dom->id);
@@ -2227,7 +2328,7 @@ libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
libxlDomainObjPrivatePtr priv;
virDomainDefPtr def;
virDomainObjPtr vm;
- libxl_cpumap map;
+ libxl_bitmap map;
uint8_t *bitmask = NULL;
unsigned int maplen;
unsigned int i, pos;
@@ -2322,7 +2423,7 @@ libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
break;
case VIR_DOMAIN_VCPU_LIVE:
- if (libxl_set_vcpuonline(&priv->ctx, dom->id, &map) != 0) {
+ if (libxl_set_vcpuonline(priv->ctx, dom->id, &map) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to set vcpus for domain '%d'"
" with libxenlight"), dom->id);
@@ -2331,7 +2432,7 @@ libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
break;
case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
- if (libxl_set_vcpuonline(&priv->ctx, dom->id, &map) != 0) {
+ if (libxl_set_vcpuonline(priv->ctx, dom->id, &map) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to set vcpus for domain '%d'"
" with libxenlight"), dom->id);
@@ -2427,7 +2528,7 @@ libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap,
libxlDomainObjPrivatePtr priv;
virDomainObjPtr vm;
int ret = -1;
- libxl_cpumap map;
+ libxl_bitmap map;
libxlDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -2448,7 +2549,7 @@ libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap,
map.size = maplen;
map.map = cpumap;
- if (libxl_set_vcpuaffinity(&priv->ctx, dom->id, vcpu, &map) != 0) {
+ if (libxl_set_vcpuaffinity(priv->ctx, dom->id, vcpu, &map) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to pin vcpu '%d' with libxenlight"), vcpu);
goto cleanup;
@@ -2511,7 +2612,7 @@ libxlDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo,
}
priv = vm->privateData;
- if ((vcpuinfo = libxl_list_vcpu(&priv->ctx, dom->id, &maxcpu,
+ if ((vcpuinfo = libxl_list_vcpu(priv->ctx, dom->id, &maxcpu,
&hostcpus)) == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to list vcpus for domain '%d' with libxenlight"),
@@ -2538,7 +2639,7 @@ libxlDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo,
MIN(maplen, vcpuinfo[i].cpumap.size));
}
- libxl_vcpuinfo_destroy(&vcpuinfo[i]);
+ libxl_vcpuinfo_dispose(&vcpuinfo[i]);
}
VIR_FREE(vcpuinfo);
@@ -2596,7 +2697,7 @@ libxlDomainXMLFromNative(virConnectPtr conn, const char * nativeFormat,
goto cleanup;
}
- if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) {
+ if ((ver_info = libxl_get_version_info(driver->ctx)) == NULL) {
VIR_ERROR(_("cannot get version information from libxenlight"));
goto cleanup;
}
@@ -2639,7 +2740,7 @@ libxlDomainXMLToNative(virConnectPtr conn, const char * nativeFormat,
goto cleanup;
}
- if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) {
+ if ((ver_info = libxl_get_version_info(driver->ctx)) == NULL) {
VIR_ERROR(_("cannot get version information from libxenlight"));
goto cleanup;
}
@@ -2899,10 +3000,10 @@ libxlDomainChangeEjectableMedia(libxlDomainObjPrivatePtr priv,
return -1;
}
- if (libxlMakeDisk(vm->def, disk, &x_disk) < 0)
+ if (libxlMakeDisk(disk, &x_disk) < 0)
goto cleanup;
- if ((ret = libxl_cdrom_insert(&priv->ctx, vm->def->id, &x_disk)) < 0) {
+ if ((ret = libxl_cdrom_insert(priv->ctx, vm->def->id, &x_disk, NULL)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("libxenlight failed to change media for disk '%s'"),
disk->dst);
@@ -2954,11 +3055,11 @@ libxlDomainAttachDeviceDiskLive(libxlDomainObjPrivatePtr priv,
goto cleanup;
}
- if (libxlMakeDisk(vm->def, l_disk, &x_disk) < 0)
+ if (libxlMakeDisk(l_disk, &x_disk) < 0)
goto cleanup;
- if ((ret = libxl_device_disk_add(&priv->ctx, vm->def->id,
- &x_disk)) < 0) {
+ if ((ret = libxl_device_disk_add(priv->ctx, vm->def->id,
+ &x_disk, NULL)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("libxenlight failed to attach disk '%s'"),
l_disk->dst);
@@ -2991,7 +3092,6 @@ libxlDomainDetachDeviceDiskLive(libxlDomainObjPrivatePtr priv,
virDomainDiskDefPtr l_disk = NULL;
libxl_device_disk x_disk;
int i;
- int wait_secs = 2;
int ret = -1;
switch (dev->data.disk->device) {
@@ -3008,11 +3108,11 @@ libxlDomainDetachDeviceDiskLive(libxlDomainObjPrivatePtr priv,
l_disk = vm->def->disks[i];
- if (libxlMakeDisk(vm->def, l_disk, &x_disk) < 0)
+ if (libxlMakeDisk(l_disk, &x_disk) < 0)
goto cleanup;
- if ((ret = libxl_device_disk_del(&priv->ctx, &x_disk,
- wait_secs)) < 0) {
+ if ((ret = libxl_device_disk_remove(priv->ctx, vm->def->id,
+ &x_disk, NULL)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("libxenlight failed to detach disk '%s'"),
l_disk->dst);
@@ -3383,13 +3483,13 @@ libxlNodeGetFreeMemory(virConnectPtr conn)
const libxl_version_info* ver_info;
libxlDriverPrivatePtr driver = conn->privateData;
- if (libxl_get_physinfo(&driver->ctx, &phy_info)) {
+ if (libxl_get_physinfo(driver->ctx, &phy_info)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("libxl_get_physinfo_info failed"));
return 0;
}
- if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) {
+ if ((ver_info = libxl_get_version_info(driver->ctx)) == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("libxl_get_version_info failed"));
return 0;
@@ -3536,7 +3636,7 @@ libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams)
libxlDomainObjPrivatePtr priv;
virDomainObjPtr vm;
char * ret = NULL;
- int sched_id;
+ libxl_scheduler sched_id;
libxlDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -3553,31 +3653,29 @@ libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams)
}
priv = vm->privateData;
- if ((sched_id = libxl_get_sched_id(&priv->ctx)) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Failed to get scheduler id for domain '%d'"
- " with libxenlight"), dom->id);
- goto cleanup;
- }
+ sched_id = libxl_get_scheduler(priv->ctx);
if (nparams)
*nparams = 0;
switch (sched_id) {
- case XEN_SCHEDULER_SEDF:
+ case LIBXL_SCHEDULER_SEDF:
ret = strdup("sedf");
break;
- case XEN_SCHEDULER_CREDIT:
+ case LIBXL_SCHEDULER_CREDIT:
ret = strdup("credit");
if (nparams)
*nparams = XEN_SCHED_CREDIT_NPARAM;
break;
- case XEN_SCHEDULER_CREDIT2:
+ case LIBXL_SCHEDULER_CREDIT2:
ret = strdup("credit2");
break;
- case XEN_SCHEDULER_ARINC653:
+ case LIBXL_SCHEDULER_ARINC653:
ret = strdup("arinc653");
break;
default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to get scheduler id for domain '%d'"
+ " with libxenlight"), dom->id);
goto cleanup;
}
@@ -3599,8 +3697,8 @@ libxlDomainGetSchedulerParametersFlags(virDomainPtr dom,
libxlDriverPrivatePtr driver = dom->conn->privateData;
libxlDomainObjPrivatePtr priv;
virDomainObjPtr vm;
- libxl_sched_credit sc_info;
- int sched_id;
+ libxl_domain_sched_params sc_info;
+ libxl_scheduler sched_id;
int ret = -1;
virCheckFlags(0, -1);
@@ -3610,31 +3708,28 @@ libxlDomainGetSchedulerParametersFlags(virDomainPtr dom,
libxlDriverUnlock(driver);
if (!vm) {
- virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid"));
+ virReportError(VIR_ERR_NO_DOMAIN, "%s",
+ _("no domain with matching uuid"));
goto cleanup;
}
if (!virDomainObjIsActive(vm)) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("Domain is not running"));
goto cleanup;
}
priv = vm->privateData;
- if ((sched_id = libxl_get_sched_id(&priv->ctx)) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Failed to get scheduler id for domain '%d'"
- " with libxenlight"), dom->id);
- goto cleanup;
- }
+ sched_id = libxl_get_scheduler(priv->ctx);
- if (sched_id != XEN_SCHEDULER_CREDIT) {
+ if (sched_id != LIBXL_SCHEDULER_CREDIT) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Only 'credit' scheduler is supported"));
goto cleanup;
}
- if (libxl_sched_credit_domain_get(&priv->ctx, dom->id, &sc_info) != 0) {
+ if (libxl_domain_sched_params_get(priv->ctx, dom->id, &sc_info) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to get scheduler parameters for domain '%d'"
" with libxenlight"), dom->id);
@@ -3677,7 +3772,7 @@ libxlDomainSetSchedulerParametersFlags(virDomainPtr dom,
libxlDriverPrivatePtr driver = dom->conn->privateData;
libxlDomainObjPrivatePtr priv;
virDomainObjPtr vm;
- libxl_sched_credit sc_info;
+ libxl_domain_sched_params sc_info;
int sched_id;
int i;
int ret = -1;
@@ -3707,20 +3802,15 @@ libxlDomainSetSchedulerParametersFlags(virDomainPtr dom,
priv = vm->privateData;
- if ((sched_id = libxl_get_sched_id(&priv->ctx)) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Failed to get scheduler id for domain '%d'"
- " with libxenlight"), dom->id);
- goto cleanup;
- }
+ sched_id = libxl_get_scheduler(priv->ctx);
- if (sched_id != XEN_SCHEDULER_CREDIT) {
+ if (sched_id != LIBXL_SCHEDULER_CREDIT) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Only 'credit' scheduler is supported"));
goto cleanup;
}
- if (libxl_sched_credit_domain_get(&priv->ctx, dom->id, &sc_info) != 0) {
+ if (libxl_domain_sched_params_get(priv->ctx, dom->id, &sc_info) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to get scheduler parameters for domain '%d'"
" with libxenlight"), dom->id);
@@ -3737,7 +3827,7 @@ libxlDomainSetSchedulerParametersFlags(virDomainPtr dom,
}
}
- if (libxl_sched_credit_domain_set(&priv->ctx, dom->id, &sc_info) != 0) {
+ if (libxl_domain_sched_params_set(priv->ctx, dom->id, &sc_info) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to set scheduler parameters for domain '%d'"
" with libxenlight"), dom->id);
--
1.7.10.4
11 years, 12 months
[libvirt] [PATCH v2] Allow comma separated list of shutdown/reboot modes with virsh
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
The shutdown and reboot commands in virsh allow a comma
separated list of mode values
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
tools/virsh-domain.c | 25 +++++++++++++++++++++++--
tools/virsh.pod | 16 ++++++++++++----
2 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index a7ffd2b..3ca246b 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -48,6 +48,7 @@
#include "virfile.h"
#include "virkeycode.h"
#include "virmacaddr.h"
+#include "virstring.h"
#include "virsh-domain-monitor.h"
#include "virterror_internal.h"
#include "virtypedparam.h"
@@ -4035,13 +4036,21 @@ cmdShutdown(vshControl *ctl, const vshCmd *cmd)
const char *mode = NULL;
int flags = 0;
int rv;
+ char **modes, **tmp;
if (vshCommandOptString(cmd, "mode", &mode) < 0) {
vshError(ctl, "%s", _("Invalid type"));
return false;
}
- if (mode) {
+ if (!(modes = virStringSplit(mode, ",", 0))) {
+ vshError(ctl, "%s", _("Cannot parse mode string"));
+ return false;
+ }
+
+ tmp = modes;
+ while (*tmp) {
+ mode = *tmp;
if (STREQ(mode, "acpi")) {
flags |= VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN;
} else if (STREQ(mode, "agent")) {
@@ -4055,7 +4064,9 @@ cmdShutdown(vshControl *ctl, const vshCmd *cmd)
"'acpi', 'agent', 'initctl' or 'signal'"), mode);
return false;
}
+ tmp++;
}
+ virStringFreeList(modes);
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return false;
@@ -4098,13 +4109,21 @@ cmdReboot(vshControl *ctl, const vshCmd *cmd)
const char *name;
const char *mode = NULL;
int flags = 0;
+ char **modes, **tmp;
if (vshCommandOptString(cmd, "mode", &mode) < 0) {
vshError(ctl, "%s", _("Invalid type"));
return false;
}
- if (mode) {
+ if (!(modes = virStringSplit(mode, ",", 0))) {
+ vshError(ctl, "%s", _("Cannot parse mode string"));
+ return false;
+ }
+
+ tmp = modes;
+ while (*tmp) {
+ mode = *tmp;
if (STREQ(mode, "acpi")) {
flags |= VIR_DOMAIN_REBOOT_ACPI_POWER_BTN;
} else if (STREQ(mode, "agent")) {
@@ -4118,7 +4137,9 @@ cmdReboot(vshControl *ctl, const vshCmd *cmd)
"'acpi', 'agent', 'initctl' or 'signal'"), mode);
return false;
}
+ tmp++;
}
+ virStringFreeList(modes);
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return false;
diff --git a/tools/virsh.pod b/tools/virsh.pod
index c901b11..7dde3df 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1137,7 +1137,7 @@ If I<--live> is specified, set scheduler information of a running guest.
If I<--config> is specified, affect the next boot of a persistent guest.
If I<--current> is specified, affect the current guest state.
-=item B<reboot> I<domain> [I<--mode acpi|agent>]
+=item B<reboot> I<domain> [I<--mode MODE-LIST>]
Reboot a domain. This acts just as if the domain had the B<reboot>
command run from the console. The command returns as soon as it has
@@ -1149,7 +1149,11 @@ I<on_reboot> parameter in the domain's XML definition.
By default the hypervisor will try to pick a suitable shutdown
method. To specify an alternative method, the I<--mode> parameter
-can specify C<acpi> or C<agent>.
+can specify a comma separated list which includes C<acpi>, C<agent>,
+C<initctl> and C<signal>. The order in which drivers will try each
+mode is undefined, and not related to the order specified to virsh.
+For strict control over ordering, use a single mode at a time and
+repeat the command.
=item B<reset> I<domain>
@@ -1567,7 +1571,7 @@ The I<--maximum> flag controls the maximum number of virtual cpus that can
be hot-plugged the next time the domain is booted. As such, it must only be
used with the I<--config> flag, and not with the I<--live> flag.
-=item B<shutdown> I<domain> [I<--mode acpi|agent>]
+=item B<shutdown> I<domain> [I<--mode MODE-LIST>]
Gracefully shuts down a domain. This coordinates with the domain OS
to perform graceful shutdown, so there is no guarantee that it will
@@ -1584,7 +1588,11 @@ snapshot metadata with B<snapshot-create>.
By default the hypervisor will try to pick a suitable shutdown
method. To specify an alternative method, the I<--mode> parameter
-can specify C<acpi> or C<agent>.
+can specify a comma separated list which includes C<acpi>, C<agent>,
+C<initctl> and C<signal>. The order in which drivers will try each
+mode is undefined, and not related to the order specified to virsh.
+For strict control over ordering, use a single mode at a time and
+repeat the command.
=item B<start> I<domain-name-or-uuid> [I<--console>] [I<--paused>]
[I<--autodestroy>] [I<--bypass-cache>] [I<--force-boot>]
--
1.7.11.7
11 years, 12 months
[libvirt] fwd: RA support in dnsmasq
by Gene Czarcinski
I am sort-of cross posting this to the libvir-list because the
bind-dynamic fix may have introduced an undesirable new "feature".
I will be troubleshooting this. One thing I want to try is to build a
dnsmasq with a fake version so that bind-interface is forced into use.
Since this is occurring with a SLAAC address, I do not need DHCPv6 for
this testing. Wait, since Laine put a lot of effort into parsing
dnsmasq --help, I will just remove the bind-dynamic rather than changing
the version.
Gene
-------- Original Message --------
Subject: Re: [Dnsmasq-discuss] RA support in dnsmasq
Date: Fri, 30 Nov 2012 12:20:36 -0500
From: Gene Czarcinski <gene(a)czarc.net>
To: dnsmasq-discuss(a)thekelleys.org.uk
On 11/30/2012 11:32 AM, Simon Kelley wrote:
> On 30/11/12 15:54, Gene Czarcinski wrote:
>> On 11/29/2012 04:18 PM, Simon Kelley wrote:
>>> On 29/11/12 20:31, Gene Czarcinski wrote:
>>>
>>>> I spoke too quickly.
>>>>
>>>> The cause of the problem is libvirt related but I am not sure what just
>>>> yet.
>>>>
>>>> I was running a libvirt that had a lot of "stuff" on it but seemed to
>>>> work OK. Then, earlier today I update to a point that appears to be
>>>> somewhat beyond the leading edge and, although I was not getting any
>>>> RTR-ADVERT messages, it turned out that there were/are big-time problems
>>>> running qemu-kvm. So, back off/downgrade to the previous version.
>>>> Qemu-kvm now works but the RTR-ADVERT messages are back.
>>>>
>>>> This may be a bit time-consuming to debug!
>>>>
>>> Are you seeing the new log message in netlink.c?
>>>
>>>
>> The good news is that libvirt is working again (I must have done a
>> git-pull in the middle of an update). Thus, I am not seeing the large
>> numbers of RTR-ADVERT.
>>
>> Yes, I am seeing the new log message and I have a question about that.
>> Every time a new virtual network interface is started, something must be
>> doing some type of broadcast because all of the dnsmasq instances (the
>> new one and all the "old" ones) suddenly wake up and issue a flurry of
>> RA packets and related syslog messages. To kick the flurry off, there
>> one of the new "unsolicited" syslog messages from each dnsmasq instance.
>>
>> Is this something you would expect? Is this "normal?" The libvirt
>> folks they are not doing it.
> I'd expect it. The code you instrumented gets run whenever a "new
> address" event happens, which is whenever an address is added to an
> interface. "Every time a new virtual network interface is started" is a
> good proxy for that.
>
> The dnsmasq code isn't very discriminating, it updates it's idea of
> which interfaces hace which addresses, and then does a minute of fast
> advertisements on all of them. It might be possible to only do the fast
> advertisements on new interfaces, but implementing that isn't totally
> trivial.
>
>
Yes, I doubt very much if it would be trivial. However, I do not
believe that this is the basic problem.
When the problem occurs, one of the networks "suddenly" attempts to work
with the real NIC rather than the virtual one defined in its config
file. I slightly changed the IPv4 and IPv6 addresses defined for this
network and the problem went away. I have also "just" seen the problem
happen on another system which also had that virtual address defined.
BTW, these configurations all use interface= and bind-dynamic rather
than the "old" bind-interface with listen-address= specified for each
specified IPv4 and IPv6 address. I had not noticed the problem
previously. Why it occurs at all with just this specific address is
puzzling.
The configuration in which causes problems is:
------------------------------------------
# dnsmasq conf file created by libvirt
strict-order
domain-needed
domain=net6
expand-hosts
local=/net6/
pid-file=/var/run/libvirt/network/net6.pid
bind-dynamic
interface=virbr11
dhcp-range=192.168.6.128,192.168.6.254
dhcp-no-override
dhcp-leasefile=/var/lib/libvirt/dnsmasq/net6.leases
dhcp-lease-max=127
dhcp-hostsfile=/var/lib/libvirt/dnsmasq/net6.hostsfile
addn-hosts=/var/lib/libvirt/dnsmasq/net6.addnhosts
dhcp-range=fd00:beef:10:6::1,ra-only
-------------------------------------------------
When I changed all the "6" to "160", the problem, disappeared. And
there is another network defined almost the same with "8" instead of "6"
and I have had no problems with it.
The real NIC is configured as a DHCP client for both IPv4 and IPv6.
It is assigned "nailed" addresses of 192.168.17.2/24 and
fd00:dead:beef:17::2.
And I just discovered why crazy stuff is happening (but I do not know
what causes it) ... the P33p1 NIC has:
inet6 fd00:beef:10:6:3285:a9ff:fe8f:e982/64 scope global dynamic
And the reason why may be related to that NetworkManager goes through a
verly long dance to bring up an interface. With dnsmasq autostarted for
net6, it may have gotten there first ... but it should have not
responded to p33p1 in any case. I am getting a little suspicious of
dnsmasq with bind-dynamic!
Gene
_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss(a)lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
11 years, 12 months
[libvirt] [PATCH] logging: more API needing to log flags
by Eric Blake
Commit a21f5112 fixed one API, but missed two others that also
failed to log their 'flags' argument.
* src/libvirt.c (virNodeSuspendForDuration, virDomainGetHostname):
Log flags parameter.
---
Pushing under the trivial rule.
src/libvirt.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/libvirt.c b/src/libvirt.c
index a5e2cc7..cdb63e7 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -6713,7 +6713,8 @@ virNodeSuspendForDuration(virConnectPtr conn,
unsigned int flags)
{
- VIR_DEBUG("conn=%p, target=%d, duration=%lld", conn, target, duration);
+ VIR_DEBUG("conn=%p, target=%d, duration=%lld, flags=%x",
+ conn, target, duration, flags);
virResetLastError();
@@ -20233,7 +20234,7 @@ virDomainGetHostname(virDomainPtr domain, unsigned int flags)
{
virConnectPtr conn;
- VIR_DOMAIN_DEBUG(domain);
+ VIR_DOMAIN_DEBUG(domain, "flags=%x", flags);
virResetLastError();
--
1.7.1
11 years, 12 months
[libvirt] [PATCH] qemu: Fix up the default machine type for QMP probing
by Viktor Mihajlovski
The default machine type must be stored in the first element of
the caps->machineTypes array. This was done for help output
parsing but not for QMP probing.
Added a helper function qemuSetDefaultMachine to apply the same
fix up for both probing methods.
Further, it was necessary to set caps->nmachineTypes after QMP
probing.
Signed-off-by: Viktor Mihajlovski <mihajlov(a)linux.vnet.ibm.com>
---
src/qemu/qemu_capabilities.c | 38 ++++++++++++++++++++++++++------------
1 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index d6affb9..6e34cdf 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -292,6 +292,23 @@ qemuCapsProbeCommand(const char *qemu,
}
+static void
+qemuSetDefaultMachine(qemuCapsPtr caps,
+ size_t defIdx)
+{
+ char *name = caps->machineTypes[defIdx];
+ char *alias = caps->machineAliases[defIdx];
+
+ memmove(caps->machineTypes + 1,
+ caps->machineTypes,
+ sizeof(caps->machineTypes[0]) * defIdx);
+ memmove(caps->machineAliases + 1,
+ caps->machineAliases,
+ sizeof(caps->machineAliases[0]) * defIdx);
+ caps->machineTypes[0] = name;
+ caps->machineAliases[0] = alias;
+}
+
/* Format is:
* <machine> <desc> [(default)|(alias of <canonical>)]
*/
@@ -352,18 +369,8 @@ qemuCapsParseMachineTypesStr(const char *output,
} while ((p = next));
- if (defIdx != 0) {
- char *name = caps->machineTypes[defIdx];
- char *alias = caps->machineAliases[defIdx];
- memmove(caps->machineTypes + 1,
- caps->machineTypes,
- sizeof(caps->machineTypes[0]) * defIdx);
- memmove(caps->machineAliases + 1,
- caps->machineAliases,
- sizeof(caps->machineAliases[0]) * defIdx);
- caps->machineTypes[0] = name;
- caps->machineAliases[0] = alias;
- }
+ if (defIdx)
+ qemuSetDefaultMachine(caps, defIdx);
return 0;
@@ -2020,6 +2027,7 @@ qemuCapsProbeQMPMachineTypes(qemuCapsPtr caps,
int nmachines = 0;
int ret = -1;
size_t i;
+ size_t defIdx = 0;
if ((nmachines = qemuMonitorGetMachines(mon, &machines)) < 0)
goto cleanup;
@@ -2049,7 +2057,13 @@ qemuCapsProbeQMPMachineTypes(qemuCapsPtr caps,
goto cleanup;
}
}
+ if (machines[i]->isDefault)
+ defIdx = i;
}
+ caps->nmachineTypes = nmachines;
+
+ if (defIdx)
+ qemuSetDefaultMachine(caps, defIdx);
ret = 0;
--
1.7.0.4
11 years, 12 months