libvirt/src/esx/esx_storage_driver.c

548 lines
14 KiB
C
Raw Normal View History

/*
* esx_storage_driver.c: storage driver functions for managing VMware ESX
* host storage
*
drivers: prefer unsigned int for flags Now that the public APIs always use unsigned flags, the internal driver callbacks might as well do likewise. * src/driver.h (vrDrvOpen, virDrvDomainCoreDump) (virDrvDomainGetXMLDesc, virDrvNetworkGetXMLDesc) (virDrvNWFilterGetXMLDesc): Update type. * src/remote/remote_protocol.x (remote_open_args) (remote_domain_core_dump_args, remote_domain_get_xml_desc_args) (remote_network_get_xml_desc_args) (remote_nwfilter_get_xml_desc_args): Likewise. * src/test/test_driver.c: Update clients. * src/remote/remote_driver.c: Likewise. * src/xen/xen_hypervisor.c: Likewise. * src/xen/xen_hypervisor.h: Likewise. * src/xen/xen_driver.c: Likewise. * src/xen/xend_internal.c: Likewise. * src/xen/xend_internal.h: Likewise. * src/xen/xm_internal.c: Likewise. * src/xen/xm_internal.h: Likewise. * src/xen/xs_internal.c: Likewise. * src/xen/xs_internal.h: Likewise. * src/xen/xen_inotify.c: Likewise. * src/xen/xen_inotify.h: Likewise. * src/phyp/phyp_driver.c: Likewise. * src/openvz/openvz_driver.c: Likewise. * src/vmware/vmware_driver.c: Likewise. * src/vbox/vbox_driver.c: Likewise. * src/vbox/vbox_tmpl.c: Likewise. * src/xenapi/xenapi_driver.c: Likewise. * src/esx/esx_driver.c: Likewise. * src/esx/esx_interface_driver.c: Likewise. * src/esx/esx_network_driver.c: Likewise. * src/esx/esx_storage_driver.c: Likewise. * src/esx/esx_device_monitor.c: Likewise. * src/esx/esx_secret_driver.c: Likewise. * src/esx/esx_nwfilter_driver.c: Likewise. * src/interface/netcf_driver.c: Likewise. * src/nwfilter/nwfilter_driver.c: Likewise. * src/libxl/libxl_driver.c: Likewise. * src/qemu/qemu_driver.c: Likewise. * src/lxc/lxc_driver.c: Likewise. * src/uml/uml_driver.c: Likewise. * src/network/bridge_driver.c: Likewise. * src/secret/secret_driver.c: Likewise. * src/storage/storage_driver.c: Likewise. * src/node_device/node_device_hal.c: Likewise. * src/node_device/node_device_udev.c: Likewise. * src/remote_protocol-structs: Likewise.
2011-07-06 20:40:19 +00:00
* Copyright (C) 2010-2011 Red Hat, Inc.
* Copyright (C) 2010-2012 Matthias Bolte <matthias.bolte@googlemail.com>
* Copyright (C) 2012 Ata E Husain Bohra <ata.husain@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/>.
*
*/
#include <config.h>
2012-12-13 18:01:25 +00:00
#include "viruuid.h"
2012-12-12 18:06:53 +00:00
#include "viralloc.h"
#include "storage_conf.h"
#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
/*
* ESX storage driver implements a facade pattern;
* the driver exposes the routines supported by libvirt
* public interface to manage ESX storage devices. Internally
* it uses backend drivers to perform the required task.
*/
enum {
VMFS = 0,
ISCSI,
LAST_BACKEND
};
static virStorageDriverPtr backends[] = {
&esxStorageBackendVMFS,
&esxStorageBackendISCSI
};
static int
esxConnectNumOfStoragePools(virConnectPtr conn)
{
int count = 0;
esxPrivate *priv = conn->privateData;
size_t i;
int tmp;
if (esxVI_EnsureSession(priv->primary) < 0)
return -1;
for (i = 0; i < LAST_BACKEND; ++i) {
tmp = backends[i]->connectNumOfStoragePools(conn);
if (tmp < 0)
return -1;
count += tmp;
}
return count;
}
static int
esxConnectListStoragePools(virConnectPtr conn, char **const names, int maxnames)
{
bool success = false;
esxPrivate *priv = conn->privateData;
int count = 0;
size_t i;
int tmp;
if (maxnames == 0)
return 0;
if (esxVI_EnsureSession(priv->primary) < 0)
return -1;
for (i = 0; i < LAST_BACKEND; ++i) {
tmp = backends[i]->connectListStoragePools(conn, &names[count], maxnames - count);
if (tmp < 0)
goto cleanup;
count += tmp;
}
success = true;
cleanup:
if (! success) {
for (i = 0; i < count; ++i)
VIR_FREE(names[i]);
count = -1;
}
return count;
}
static int
esxConnectNumOfDefinedStoragePools(virConnectPtr conn ATTRIBUTE_UNUSED)
{
/* ESX storage pools are always active */
return 0;
}
static int
esxConnectListDefinedStoragePools(virConnectPtr conn ATTRIBUTE_UNUSED,
char **const names ATTRIBUTE_UNUSED,
int maxnames ATTRIBUTE_UNUSED)
{
/* ESX storage pools are always active */
return 0;
}
static virStoragePoolPtr
esxStoragePoolLookupByName(virConnectPtr conn, const char *name)
{
esxPrivate *priv = conn->privateData;
size_t i;
virStoragePoolPtr pool;
virCheckNonNullArgReturn(name, NULL);
if (esxVI_EnsureSession(priv->primary) < 0)
return NULL;
for (i = 0; i < LAST_BACKEND; ++i) {
pool = backends[i]->storagePoolLookupByName(conn, name);
if (pool)
return pool;
}
virReportError(VIR_ERR_NO_STORAGE_POOL,
_("Could not find storage pool with name '%s'"), name);
return NULL;
}
static virStoragePoolPtr
esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
{
esxPrivate *priv = conn->privateData;
size_t i;
virStoragePoolPtr pool;
char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
if (esxVI_EnsureSession(priv->primary) < 0)
return NULL;
/* invoke backend drive method to search all known pools */
for (i = 0; i < LAST_BACKEND; ++i) {
pool = backends[i]->storagePoolLookupByUUID(conn, uuid);
if (pool)
return pool;
}
virUUIDFormat(uuid, uuid_string);
virReportError(VIR_ERR_NO_STORAGE_POOL,
_("Could not find storage pool with uuid '%s'"),
uuid_string);
return NULL;
}
static virStoragePoolPtr
esxStoragePoolLookupByVolume(virStorageVolPtr volume)
{
return esxStoragePoolLookupByName(volume->conn, volume->pool);
}
static int
esxStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags)
{
esxPrivate *priv = pool->conn->privateData;
virStorageDriverPtr backend = pool->privateData;
virCheckNonNullArgReturn(pool->privateData, -1);
if (esxVI_EnsureSession(priv->primary) < 0)
return -1;
return backend->storagePoolRefresh(pool, flags);
}
static int
esxStoragePoolGetInfo(virStoragePoolPtr pool, virStoragePoolInfoPtr info)
{
esxPrivate *priv = pool->conn->privateData;
virStorageDriverPtr backend = pool->privateData;
virCheckNonNullArgReturn(pool->privateData, -1);
memset(info, 0, sizeof(*info));
if (esxVI_EnsureSession(priv->primary) < 0)
return -1;
return backend->storagePoolGetInfo(pool, info);
}
static char *
esxStoragePoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
{
esxPrivate *priv = pool->conn->privateData;
virStorageDriverPtr backend = pool->privateData;
virCheckNonNullArgReturn(pool->privateData, NULL);
if (esxVI_EnsureSession(priv->primary) < 0)
return NULL;
return backend->storagePoolGetXMLDesc(pool, flags);
}
static int
esxStoragePoolGetAutostart(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
int *autostart)
{
/* ESX storage pools are always active */
*autostart = 1;
return 0;
}
static int
esxStoragePoolSetAutostart(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
int autostart)
{
/* Just accept autostart activation, but fail on autostart deactivation */
autostart = (autostart != 0);
if (! autostart) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot deactivate storage pool autostart"));
return -1;
}
return 0;
}
static int
esxStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
esxPrivate *priv = pool->conn->privateData;
virStorageDriverPtr backend = pool->privateData;
virCheckNonNullArgReturn(pool->privateData, -1);
if (esxVI_EnsureSession(priv->primary) < 0)
return -1;
return backend->storagePoolNumOfVolumes(pool);
}
static int
esxStoragePoolListVolumes(virStoragePoolPtr pool, char **const names,
int maxnames)
{
esxPrivate *priv = pool->conn->privateData;
virStorageDriverPtr backend = pool->privateData;
virCheckNonNullArgReturn(pool->privateData, -1);
if (esxVI_EnsureSession(priv->primary) < 0)
return -1;
return backend->storagePoolListVolumes(pool, names, maxnames);
}
static virStorageVolPtr
esxStorageVolLookupByName(virStoragePoolPtr pool, const char *name)
{
esxPrivate *priv = pool->conn->privateData;
virStorageDriverPtr backend = pool->privateData;
virCheckNonNullArgReturn(pool->privateData, NULL);
if (esxVI_EnsureSession(priv->primary) < 0)
return NULL;
return backend->storageVolLookupByName(pool, name);
}
static virStorageVolPtr
esxStorageVolLookupByPath(virConnectPtr conn, const char *path)
{
esxPrivate *priv = conn->privateData;
if (esxVI_EnsureSession(priv->primary) < 0)
return NULL;
/*
* FIXME: calling backends blindly may set unwanted error codes
*
* VMFS Datastore path follows canonical format i.e.:
* [<datastore_name>] <file_path>
* WHEREAS
* iSCSI LUNs device path follows normal linux path convention
*/
if (STRPREFIX(path, "[")) {
return backends[VMFS]->storageVolLookupByPath(conn, path);
} else if (STRPREFIX(path, "/")) {
return backends[ISCSI]->storageVolLookupByPath(conn, path);
} else {
virReportError(VIR_ERR_INVALID_ARG,
_("Unexpected volume path format: %s"), path);
return NULL;
}
}
static virStorageVolPtr
esxStorageVolLookupByKey(virConnectPtr conn, const char *key)
{
virStorageVolPtr volume;
esxPrivate *priv = conn->privateData;
size_t i;
if (esxVI_EnsureSession(priv->primary) < 0)
return NULL;
for (i = 0; i < LAST_BACKEND; ++i) {
volume = backends[i]->storageVolLookupByKey(conn, key);
if (volume)
return volume;
}
virReportError(VIR_ERR_NO_STORAGE_VOL,
_("Could not find storage volume with key '%s'"),
key);
return NULL;
}
2010-08-28 19:49:07 +00:00
static virStorageVolPtr
esxStorageVolCreateXML(virStoragePoolPtr pool, const char *xmldesc,
unsigned int flags)
2010-08-28 19:49:07 +00:00
{
esxPrivate *priv = pool->conn->privateData;
virStorageDriverPtr backend = pool->privateData;
2010-08-28 19:49:07 +00:00
virCheckNonNullArgReturn(pool->privateData, NULL);
2010-08-28 19:49:07 +00:00
if (esxVI_EnsureSession(priv->primary) < 0)
return NULL;
2010-08-28 19:49:07 +00:00
return backend->storageVolCreateXML(pool, xmldesc, flags);
2010-08-28 19:49:07 +00:00
}
static virStorageVolPtr
esxStorageVolCreateXMLFrom(virStoragePoolPtr pool, const char *xmldesc,
virStorageVolPtr sourceVolume, unsigned int flags)
{
esxPrivate *priv = pool->conn->privateData;
virStorageDriverPtr backend = pool->privateData;
virCheckNonNullArgReturn(pool->privateData, NULL);
if (esxVI_EnsureSession(priv->primary) < 0)
return NULL;
return backend->storageVolCreateXMLFrom(pool, xmldesc, sourceVolume, flags);
}
static int
esxStorageVolDelete(virStorageVolPtr volume, unsigned int flags)
{
esxPrivate *priv = volume->conn->privateData;
virStorageDriverPtr backend = volume->privateData;
virCheckNonNullArgReturn(volume->privateData, -1);
if (esxVI_EnsureSession(priv->primary) < 0)
return -1;
return backend->storageVolDelete(volume, flags);
}
static int
esxStorageVolWipe(virStorageVolPtr volume, unsigned int flags)
{
esxPrivate *priv = volume->conn->privateData;
virStorageDriverPtr backend = volume->privateData;
virCheckNonNullArgReturn(volume->privateData, -1);
if (esxVI_EnsureSession(priv->primary) < 0)
return -1;
return backend->storageVolWipe(volume, flags);
}
static int
esxStorageVolGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr info)
{
esxPrivate *priv = volume->conn->privateData;
virStorageDriverPtr backend = volume->privateData;
virCheckNonNullArgReturn(volume->privateData, -1);
if (esxVI_EnsureSession(priv->primary) < 0)
return -1;
return backend->storageVolGetInfo(volume, info);
}
static char *
esxStorageVolGetXMLDesc(virStorageVolPtr volume, unsigned int flags)
{
esxPrivate *priv = volume->conn->privateData;
virStorageDriverPtr backend = volume->privateData;
virCheckNonNullArgReturn(volume->privateData, NULL);
if (esxVI_EnsureSession(priv->primary) < 0)
return NULL;
return backend->storageVolGetXMLDesc(volume, flags);
}
static char *
esxStorageVolGetPath(virStorageVolPtr volume)
{
esxPrivate *priv = volume->conn->privateData;
virStorageDriverPtr backend = volume->privateData;
virCheckNonNullArgReturn(volume->privateData, NULL);
if (esxVI_EnsureSession(priv->primary) < 0)
return NULL;
return backend->storageVolGetPath(volume);
}
static int
esxStoragePoolIsActive(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
{
/* ESX storage pools are always active */
return 1;
}
static int
esxStoragePoolIsPersistent(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
{
/* ESX has no concept of transient pools, so all of them are persistent */
return 1;
}
virStorageDriver esxStorageDriver = {
.connectNumOfStoragePools = esxConnectNumOfStoragePools, /* 0.8.2 */
.connectListStoragePools = esxConnectListStoragePools, /* 0.8.2 */
.connectNumOfDefinedStoragePools = esxConnectNumOfDefinedStoragePools, /* 0.8.2 */
.connectListDefinedStoragePools = esxConnectListDefinedStoragePools, /* 0.8.2 */
.storagePoolLookupByName = esxStoragePoolLookupByName, /* 0.8.2 */
.storagePoolLookupByUUID = esxStoragePoolLookupByUUID, /* 0.8.2 */
.storagePoolLookupByVolume = esxStoragePoolLookupByVolume, /* 0.8.4 */
.storagePoolRefresh = esxStoragePoolRefresh, /* 0.8.2 */
.storagePoolGetInfo = esxStoragePoolGetInfo, /* 0.8.2 */
.storagePoolGetXMLDesc = esxStoragePoolGetXMLDesc, /* 0.8.2 */
.storagePoolGetAutostart = esxStoragePoolGetAutostart, /* 0.8.2 */
.storagePoolSetAutostart = esxStoragePoolSetAutostart, /* 0.8.2 */
.storagePoolNumOfVolumes = esxStoragePoolNumOfVolumes, /* 0.8.4 */
.storagePoolListVolumes = esxStoragePoolListVolumes, /* 0.8.4 */
.storageVolLookupByName = esxStorageVolLookupByName, /* 0.8.4 */
.storageVolLookupByPath = esxStorageVolLookupByPath, /* 0.8.4 */
.storageVolLookupByKey = esxStorageVolLookupByKey, /* 0.8.4 */
.storageVolCreateXML = esxStorageVolCreateXML, /* 0.8.4 */
.storageVolCreateXMLFrom = esxStorageVolCreateXMLFrom, /* 0.8.7 */
.storageVolDelete = esxStorageVolDelete, /* 0.8.7 */
.storageVolWipe = esxStorageVolWipe, /* 0.8.7 */
.storageVolGetInfo = esxStorageVolGetInfo, /* 0.8.4 */
.storageVolGetXMLDesc = esxStorageVolGetXMLDesc, /* 0.8.4 */
.storageVolGetPath = esxStorageVolGetPath, /* 0.8.4 */
.storagePoolIsActive = esxStoragePoolIsActive, /* 0.8.2 */
.storagePoolIsPersistent = esxStoragePoolIsPersistent, /* 0.8.2 */
};