libvirt/src/esx/esx_storage_driver.c
Daniel P. Berrange 90430791ae Make driver method names consistent with public APIs
Ensure that all drivers implementing public APIs use a
naming convention for their implementation that matches
the public API name.

eg for the public API   virDomainCreate make sure QEMU
uses qemuDomainCreate and not qemuDomainStart

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-04-24 11:00:18 +01:00

615 lines
15 KiB
C

/*
* esx_storage_driver.c: storage driver functions for managing VMware ESX
* host storage
*
* 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>
#include "viruuid.h"
#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 virDrvOpenStatus
esxStorageOpen(virConnectPtr conn,
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
unsigned int flags)
{
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
if (conn->driver->no != VIR_DRV_ESX) {
return VIR_DRV_OPEN_DECLINED;
}
conn->storagePrivateData = conn->privateData;
return VIR_DRV_OPEN_SUCCESS;
}
static int
esxStorageClose(virConnectPtr conn)
{
conn->storagePrivateData = NULL;
return 0;
}
static int
esxConnectNumOfStoragePools(virConnectPtr conn)
{
int count = 0;
esxPrivate *priv = conn->storagePrivateData;
int 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->storagePrivateData;
int count = 0;
int 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->storagePrivateData;
int 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 != NULL) {
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->storagePrivateData;
int 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 != NULL) {
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->storagePrivateData;
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->storagePrivateData;
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->storagePrivateData;
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->storagePrivateData;
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->storagePrivateData;
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->storagePrivateData;
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->storagePrivateData;
if (esxVI_EnsureSession(priv->primary) < 0) {
return NULL;
}
/*
* FIXME: calling backends blindly may set unwanted error codes
*
* 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, "[")) {
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->storagePrivateData;
int i;
if (esxVI_EnsureSession(priv->primary) < 0) {
return NULL;
}
for (i = 0; i < LAST_BACKEND; ++i) {
volume = backends[i]->storageVolLookupByKey(conn, key);
if (volume != NULL) {
return volume;
}
}
virReportError(VIR_ERR_NO_STORAGE_VOL,
_("Could not find storage volume with key '%s'"),
key);
return NULL;
}
static virStorageVolPtr
esxStorageVolCreateXML(virStoragePoolPtr pool, const char *xmldesc,
unsigned int flags)
{
esxPrivate *priv = pool->conn->storagePrivateData;
virStorageDriverPtr backend = pool->privateData;
virCheckNonNullArgReturn(pool->privateData, NULL);
if (esxVI_EnsureSession(priv->primary) < 0) {
return NULL;
}
return backend->storageVolCreateXML(pool, xmldesc, flags);
}
static virStorageVolPtr
esxStorageVolCreateXMLFrom(virStoragePoolPtr pool, const char *xmldesc,
virStorageVolPtr sourceVolume, unsigned int flags)
{
esxPrivate *priv = pool->conn->storagePrivateData;
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->storagePrivateData;
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->storagePrivateData;
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->storagePrivateData;
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->storagePrivateData;
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->storagePrivateData;
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;
}
static virStorageDriver esxStorageDriver = {
.name = "ESX",
.storageOpen = esxStorageOpen, /* 0.7.6 */
.storageClose = esxStorageClose, /* 0.7.6 */
.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 */
};
int
esxStorageRegister(void)
{
return virRegisterStorageDriver(&esxStorageDriver);
}