libvirt/src/libvirt-storage.c
Erik Skultety d6064e2759 libvirt-<module>: Check caller-provided buffers to be NULL with size > 0
Pre-Glib era which used malloc allowed the size of the client-side
buffers to be declared as 0, because malloc documents that it can either
return 0 or a unique pointer on 0 size allocations.
With glib this doesn't work anymore, because glib documents that for
such allocation requests NULL is always returned which results in an
error in our public API checks server-side.
This patch complements the fix in the RPC layer by explicitly erroring
out on the following combination of args used by our legacy APIs (their
moder equivalents don't suffer from this):

function(caller-allocated-array, size, ...) {
    if (!caller-allocated-array && size > 0)
        return error;
}

treating everything else as a valid input and potentially let that fail
on the server-side rather than client-side.

https://bugzilla.redhat.com/show_bug.cgi?id=1772842

Signed-off-by: Erik Skultety <eskultet@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2019-11-21 18:16:35 +01:00

2398 lines
64 KiB
C

/*
* libvirt-storage.c: entry points for virStorage{Pool,Vol}Ptr APIs
*
* Copyright (C) 2006-2015 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "datatypes.h"
#include "virlog.h"
VIR_LOG_INIT("libvirt.storage");
#define VIR_FROM_THIS VIR_FROM_STORAGE
/**
* virStoragePoolGetConnect:
* @pool: pointer to a pool
*
* Provides the connection pointer associated with a storage pool. The
* reference counter on the connection is not increased by this
* call.
*
* Returns the virConnectPtr or NULL in case of failure.
*/
virConnectPtr
virStoragePoolGetConnect(virStoragePoolPtr pool)
{
VIR_DEBUG("pool=%p", pool);
virResetLastError();
virCheckStoragePoolReturn(pool, NULL);
return pool->conn;
}
/**
* virConnectListAllStoragePools:
* @conn: Pointer to the hypervisor connection.
* @pools: Pointer to a variable to store the array containing storage pool
* objects or NULL if the list is not required (just returns number
* of pools).
* @flags: bitwise-OR of virConnectListAllStoragePoolsFlags.
*
* Collect the list of storage pools, and allocate an array to store those
* objects. This API solves the race inherent between
* virConnectListStoragePools and virConnectListDefinedStoragePools.
*
* Normally, all storage pools are returned; however, @flags can be used to
* filter the results for a smaller list of targeted pools. The valid
* flags are divided into groups, where each group contains bits that
* describe mutually exclusive attributes of a pool, and where all bits
* within a group describe all possible pools.
*
* The first group of @flags is VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE (online)
* and VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE (offline) to filter the pools
* by state.
*
* The second group of @flags is VIR_CONNECT_LIST_STORAGE_POOLS_PERSITENT
* (defined) and VIR_CONNECT_LIST_STORAGE_POOLS_TRANSIENT (running but not
* defined), to filter the pools by whether they have persistent config or not.
*
* The third group of @flags is VIR_CONNECT_LIST_STORAGE_POOLS_AUTOSTART
* and VIR_CONNECT_LIST_STORAGE_POOLS_NO_AUTOSTART, to filter the pools by
* whether they are marked as autostart or not.
*
* The last group of @flags is provided to filter the pools by the types,
* the flags include:
* VIR_CONNECT_LIST_STORAGE_POOLS_DIR
* VIR_CONNECT_LIST_STORAGE_POOLS_FS
* VIR_CONNECT_LIST_STORAGE_POOLS_NETFS
* VIR_CONNECT_LIST_STORAGE_POOLS_LOGICAL
* VIR_CONNECT_LIST_STORAGE_POOLS_DISK
* VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI
* VIR_CONNECT_LIST_STORAGE_POOLS_SCSI
* VIR_CONNECT_LIST_STORAGE_POOLS_MPATH
* VIR_CONNECT_LIST_STORAGE_POOLS_RBD
* VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG
* VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER
* VIR_CONNECT_LIST_STORAGE_POOLS_ZFS
* VIR_CONNECT_LIST_STORAGE_POOLS_VSTORAGE
* VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI_DIRECT
*
* Returns the number of storage pools found or -1 and sets @pools to
* NULL in case of error. On success, the array stored into @pools is
* guaranteed to have an extra allocated element set to NULL but not included
* in the return count, to make iteration easier. The caller is responsible
* for calling virStoragePoolFree() on each array element, then calling
* free() on @pools.
*/
int
virConnectListAllStoragePools(virConnectPtr conn,
virStoragePoolPtr **pools,
unsigned int flags)
{
VIR_DEBUG("conn=%p, pools=%p, flags=0x%x", conn, pools, flags);
virResetLastError();
if (pools)
*pools = NULL;
virCheckConnectReturn(conn, -1);
if (conn->storageDriver &&
conn->storageDriver->connectListAllStoragePools) {
int ret;
ret = conn->storageDriver->connectListAllStoragePools(conn, pools, flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return -1;
}
/**
* virConnectNumOfStoragePools:
* @conn: pointer to hypervisor connection
*
* Provides the number of active storage pools
*
* Returns the number of pools found, or -1 on error
*/
int
virConnectNumOfStoragePools(virConnectPtr conn)
{
VIR_DEBUG("conn=%p", conn);
virResetLastError();
virCheckConnectReturn(conn, -1);
if (conn->storageDriver && conn->storageDriver->connectNumOfStoragePools) {
int ret;
ret = conn->storageDriver->connectNumOfStoragePools(conn);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return -1;
}
/**
* virConnectListStoragePools:
* @conn: pointer to hypervisor connection
* @names: array of char * to fill with pool names (allocated by caller)
* @maxnames: size of the names array
*
* Provides the list of names of active storage pools up to maxnames.
* If there are more than maxnames, the remaining names will be silently
* ignored.
*
* For more control over the results, see virConnectListAllStoragePools().
*
* Returns the number of pools found or -1 in case of error. Note that
* this command is inherently racy; a pool can be started between a call to
* virConnectNumOfStoragePools() and this call; you are only guaranteed
* that all currently active pools were listed if the return is less than
* @maxnames. The client must call free() on each returned name.
*/
int
virConnectListStoragePools(virConnectPtr conn,
char **const names,
int maxnames)
{
VIR_DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames);
virResetLastError();
virCheckConnectReturn(conn, -1);
virCheckNonNullArrayArgGoto(names, maxnames, error);
virCheckNonNegativeArgGoto(maxnames, error);
if (conn->storageDriver && conn->storageDriver->connectListStoragePools) {
int ret;
ret = conn->storageDriver->connectListStoragePools(conn, names, maxnames);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return -1;
}
/**
* virConnectNumOfDefinedStoragePools:
* @conn: pointer to hypervisor connection
*
* Provides the number of inactive storage pools
*
* Returns the number of pools found, or -1 on error
*/
int
virConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
VIR_DEBUG("conn=%p", conn);
virResetLastError();
virCheckConnectReturn(conn, -1);
if (conn->storageDriver && conn->storageDriver->connectNumOfDefinedStoragePools) {
int ret;
ret = conn->storageDriver->connectNumOfDefinedStoragePools(conn);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return -1;
}
/**
* virConnectListDefinedStoragePools:
* @conn: pointer to hypervisor connection
* @names: array of char * to fill with pool names (allocated by caller)
* @maxnames: size of the names array
*
* Provides the list of names of inactive storage pools up to maxnames.
* If there are more than maxnames, the remaining names will be silently
* ignored.
*
* For more control over the results, see virConnectListAllStoragePools().
*
* Returns the number of names provided in the array or -1 in case of error.
* Note that this command is inherently racy; a pool can be defined between
* a call to virConnectNumOfDefinedStoragePools() and this call; you are only
* guaranteed that all currently defined pools were listed if the return
* is less than @maxnames. The client must call free() on each returned name.
*/
int
virConnectListDefinedStoragePools(virConnectPtr conn,
char **const names,
int maxnames)
{
VIR_DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames);
virResetLastError();
virCheckConnectReturn(conn, -1);
virCheckNonNullArrayArgGoto(names, maxnames, error);
virCheckNonNegativeArgGoto(maxnames, error);
if (conn->storageDriver && conn->storageDriver->connectListDefinedStoragePools) {
int ret;
ret = conn->storageDriver->connectListDefinedStoragePools(conn, names, maxnames);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return -1;
}
/**
* virConnectFindStoragePoolSources:
* @conn: pointer to hypervisor connection
* @type: type of storage pool sources to discover
* @srcSpec: XML document specifying discovery source
* @flags: extra flags; not used yet, so callers should always pass 0
*
* Talks to a storage backend and attempts to auto-discover the set of
* available storage pool sources. e.g. For iSCSI this would be a set of
* iSCSI targets. For NFS this would be a list of exported paths. The
* srcSpec (optional for some storage pool types, e.g. local ones) is
* an instance of the storage pool's source element specifying where
* to look for the pools.
*
* srcSpec is not required for some types (e.g., those querying
* local storage resources only)
*
* Returns an xml document consisting of a SourceList element
* containing a source document appropriate to the given pool
* type for each discovered source.
*/
char *
virConnectFindStoragePoolSources(virConnectPtr conn,
const char *type,
const char *srcSpec,
unsigned int flags)
{
VIR_DEBUG("conn=%p, type=%s, src=%s, flags=0x%x",
conn, NULLSTR(type), NULLSTR(srcSpec), flags);
virResetLastError();
virCheckConnectReturn(conn, NULL);
virCheckNonNullArgGoto(type, error);
virCheckReadOnlyGoto(conn->flags, error);
if (conn->storageDriver && conn->storageDriver->connectFindStoragePoolSources) {
char *ret;
ret = conn->storageDriver->connectFindStoragePoolSources(conn, type, srcSpec, flags);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return NULL;
}
/**
* virStoragePoolLookupByName:
* @conn: pointer to hypervisor connection
* @name: name of pool to fetch
*
* Fetch a storage pool based on its unique name
*
* virStoragePoolFree should be used to free the resources after the
* storage pool object is no longer needed.
*
* Returns a virStoragePoolPtr object, or NULL if no matching pool is found
*/
virStoragePoolPtr
virStoragePoolLookupByName(virConnectPtr conn,
const char *name)
{
VIR_DEBUG("conn=%p, name=%s", conn, NULLSTR(name));
virResetLastError();
virCheckConnectReturn(conn, NULL);
virCheckNonNullArgGoto(name, error);
if (conn->storageDriver && conn->storageDriver->storagePoolLookupByName) {
virStoragePoolPtr ret;
ret = conn->storageDriver->storagePoolLookupByName(conn, name);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return NULL;
}
/**
* virStoragePoolLookupByUUID:
* @conn: pointer to hypervisor connection
* @uuid: globally unique id of pool to fetch
*
* Fetch a storage pool based on its globally unique id
*
* virStoragePoolFree should be used to free the resources after the
* storage pool object is no longer needed.
*
* Returns a virStoragePoolPtr object, or NULL if no matching pool is found
*/
virStoragePoolPtr
virStoragePoolLookupByUUID(virConnectPtr conn,
const unsigned char *uuid)
{
VIR_UUID_DEBUG(conn, uuid);
virResetLastError();
virCheckConnectReturn(conn, NULL);
virCheckNonNullArgGoto(uuid, error);
if (conn->storageDriver && conn->storageDriver->storagePoolLookupByUUID) {
virStoragePoolPtr ret;
ret = conn->storageDriver->storagePoolLookupByUUID(conn, uuid);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return NULL;
}
/**
* virStoragePoolLookupByUUIDString:
* @conn: pointer to hypervisor connection
* @uuidstr: globally unique id of pool to fetch
*
* Fetch a storage pool based on its globally unique id
*
* virStoragePoolFree should be used to free the resources after the
* storage pool object is no longer needed.
*
* Returns a virStoragePoolPtr object, or NULL if no matching pool is found
*/
virStoragePoolPtr
virStoragePoolLookupByUUIDString(virConnectPtr conn,
const char *uuidstr)
{
unsigned char uuid[VIR_UUID_BUFLEN];
VIR_DEBUG("conn=%p, uuidstr=%s", conn, NULLSTR(uuidstr));
virResetLastError();
virCheckConnectReturn(conn, NULL);
virCheckNonNullArgGoto(uuidstr, error);
if (virUUIDParse(uuidstr, uuid) < 0) {
virReportInvalidArg(uuidstr,
_("uuidstr in %s must be a valid UUID"),
__FUNCTION__);
goto error;
}
return virStoragePoolLookupByUUID(conn, uuid);
error:
virDispatchError(conn);
return NULL;
}
/**
* virStoragePoolLookupByVolume:
* @vol: pointer to storage volume
*
* Fetch a storage pool which contains a particular volume
*
* virStoragePoolFree should be used to free the resources after the
* storage pool object is no longer needed.
*
* Returns a virStoragePoolPtr object, or NULL if no matching pool is found
*/
virStoragePoolPtr
virStoragePoolLookupByVolume(virStorageVolPtr vol)
{
VIR_DEBUG("vol=%p", vol);
virResetLastError();
virCheckStorageVolReturn(vol, NULL);
if (vol->conn->storageDriver && vol->conn->storageDriver->storagePoolLookupByVolume) {
virStoragePoolPtr ret;
ret = vol->conn->storageDriver->storagePoolLookupByVolume(vol);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(vol->conn);
return NULL;
}
/**
* virStoragePoolLookupByTargetPath:
* @conn: pointer to hypervisor connection
* @path: path at which the pool is exposed
*
* Fetch a storage pool which maps to a particular target directory.
* If more than one pool maps to the path, it is undefined which
* will be returned first.
*
* virStoragePoolFree should be used to free the resources after the
* storage pool object is no longer needed.
*
* Returns a virStoragePoolPtr object, or NULL if no matching pool is found
*/
virStoragePoolPtr
virStoragePoolLookupByTargetPath(virConnectPtr conn,
const char *path)
{
VIR_DEBUG("conn=%p, path=%s", conn, NULLSTR(path));
virResetLastError();
virCheckConnectReturn(conn, NULL);
virCheckNonNullArgGoto(path, error);
if (conn->storageDriver && conn->storageDriver->storagePoolLookupByTargetPath) {
virStoragePoolPtr ret;
ret = conn->storageDriver->storagePoolLookupByTargetPath(conn, path);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return NULL;
}
/**
* virStoragePoolCreateXML:
* @conn: pointer to hypervisor connection
* @xmlDesc: XML description for new pool
* @flags: bitwise-OR of virStoragePoolCreateFlags
*
* Create a new storage based on its XML description. The
* pool is not persistent, so its definition will disappear
* when it is destroyed, or if the host is restarted
*
* virStoragePoolFree should be used to free the resources after the
* storage pool object is no longer needed.
*
* Returns a virStoragePoolPtr object, or NULL if creation failed
*/
virStoragePoolPtr
virStoragePoolCreateXML(virConnectPtr conn,
const char *xmlDesc,
unsigned int flags)
{
VIR_DEBUG("conn=%p, xmlDesc=%s, flags=0x%x", conn, NULLSTR(xmlDesc), flags);
virResetLastError();
virCheckConnectReturn(conn, NULL);
virCheckNonNullArgGoto(xmlDesc, error);
virCheckReadOnlyGoto(conn->flags, error);
if (conn->storageDriver && conn->storageDriver->storagePoolCreateXML) {
virStoragePoolPtr ret;
ret = conn->storageDriver->storagePoolCreateXML(conn, xmlDesc, flags);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return NULL;
}
/**
* virStoragePoolDefineXML:
* @conn: pointer to hypervisor connection
* @xml: XML description for new pool
* @flags: extra flags; not used yet, so callers should always pass 0
*
* Define an inactive persistent storage pool or modify an existing persistent
* one from the XML description.
*
* virStoragePoolFree should be used to free the resources after the
* storage pool object is no longer needed.
*
* Returns a virStoragePoolPtr object, or NULL if creation failed
*/
virStoragePoolPtr
virStoragePoolDefineXML(virConnectPtr conn,
const char *xml,
unsigned int flags)
{
VIR_DEBUG("conn=%p, xml=%s, flags=0x%x", conn, NULLSTR(xml), flags);
virResetLastError();
virCheckConnectReturn(conn, NULL);
virCheckReadOnlyGoto(conn->flags, error);
virCheckNonNullArgGoto(xml, error);
if (conn->storageDriver && conn->storageDriver->storagePoolDefineXML) {
virStoragePoolPtr ret;
ret = conn->storageDriver->storagePoolDefineXML(conn, xml, flags);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return NULL;
}
/**
* virStoragePoolBuild:
* @pool: pointer to storage pool
* @flags: bitwise-OR of virStoragePoolBuildFlags
*
* Currently only filesystem pool accepts flags VIR_STORAGE_POOL_BUILD_OVERWRITE
* and VIR_STORAGE_POOL_BUILD_NO_OVERWRITE.
*
* Build the underlying storage pool
*
* Returns 0 on success, or -1 upon failure
*/
int
virStoragePoolBuild(virStoragePoolPtr pool,
unsigned int flags)
{
virConnectPtr conn;
VIR_DEBUG("pool=%p, flags=0x%x", pool, flags);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
conn = pool->conn;
virCheckReadOnlyGoto(conn->flags, error);
if (conn->storageDriver && conn->storageDriver->storagePoolBuild) {
int ret;
ret = conn->storageDriver->storagePoolBuild(pool, flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolUndefine:
* @pool: pointer to storage pool
*
* Undefine an inactive storage pool
*
* Returns 0 on success, -1 on failure
*/
int
virStoragePoolUndefine(virStoragePoolPtr pool)
{
virConnectPtr conn;
VIR_DEBUG("pool=%p", pool);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
conn = pool->conn;
virCheckReadOnlyGoto(conn->flags, error);
if (conn->storageDriver && conn->storageDriver->storagePoolUndefine) {
int ret;
ret = conn->storageDriver->storagePoolUndefine(pool);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolCreate:
* @pool: pointer to storage pool
* @flags: bitwise-OR of virStoragePoolCreateFlags
*
* Starts an inactive storage pool
*
* Returns 0 on success, or -1 if it could not be started
*/
int
virStoragePoolCreate(virStoragePoolPtr pool,
unsigned int flags)
{
virConnectPtr conn;
VIR_DEBUG("pool=%p, flags=0x%x", pool, flags);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
conn = pool->conn;
virCheckReadOnlyGoto(conn->flags, error);
if (conn->storageDriver && conn->storageDriver->storagePoolCreate) {
int ret;
ret = conn->storageDriver->storagePoolCreate(pool, flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolDestroy:
* @pool: pointer to storage pool
*
* Destroy an active storage pool. This will deactivate the
* pool on the host, but keep any persistent config associated
* with it. If it has a persistent config it can later be
* restarted with virStoragePoolCreate(). This does not free
* the associated virStoragePoolPtr object.
*
* Returns 0 on success, or -1 if it could not be destroyed
*/
int
virStoragePoolDestroy(virStoragePoolPtr pool)
{
virConnectPtr conn;
VIR_DEBUG("pool=%p", pool);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
conn = pool->conn;
virCheckReadOnlyGoto(conn->flags, error);
if (conn->storageDriver && conn->storageDriver->storagePoolDestroy) {
int ret;
ret = conn->storageDriver->storagePoolDestroy(pool);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolDelete:
* @pool: pointer to storage pool
* @flags: bitwise-OR of virStoragePoolDeleteFlags
*
* Delete the underlying pool resources. This is
* a non-recoverable operation. The virStoragePoolPtr object
* itself is not free'd.
*
* Returns 0 on success, or -1 if it could not be obliterate
*/
int
virStoragePoolDelete(virStoragePoolPtr pool,
unsigned int flags)
{
virConnectPtr conn;
VIR_DEBUG("pool=%p, flags=0x%x", pool, flags);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
conn = pool->conn;
virCheckReadOnlyGoto(conn->flags, error);
if (conn->storageDriver && conn->storageDriver->storagePoolDelete) {
int ret;
ret = conn->storageDriver->storagePoolDelete(pool, flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolFree:
* @pool: pointer to storage pool
*
* Free a storage pool object, releasing all memory associated with
* it. Does not change the state of the pool on the host.
*
* Returns 0 on success, or -1 if it could not be free'd.
*/
int
virStoragePoolFree(virStoragePoolPtr pool)
{
VIR_DEBUG("pool=%p", pool);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
virObjectUnref(pool);
return 0;
}
/**
* virStoragePoolRef:
* @pool: the pool to hold a reference on
*
* Increment the reference count on the pool. For each
* additional call to this method, there shall be a corresponding
* call to virStoragePoolFree to release the reference count, once
* the caller no longer needs the reference to this object.
*
* This method is typically useful for applications where multiple
* threads are using a connection, and it is required that the
* connection remain open until all threads have finished using
* it. ie, each new thread using a pool would increment
* the reference count.
*
* Returns 0 in case of success, -1 in case of failure.
*/
int
virStoragePoolRef(virStoragePoolPtr pool)
{
VIR_DEBUG("pool=%p refs=%d", pool, pool ? pool->parent.u.s.refs : 0);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
virObjectRef(pool);
return 0;
}
/**
* virStoragePoolRefresh:
* @pool: pointer to storage pool
* @flags: extra flags; not used yet, so callers should always pass 0
*
* Request that the pool refresh its list of volumes. This may
* involve communicating with a remote server, and/or initializing
* new devices at the OS layer
*
* Returns 0 if the volume list was refreshed, -1 on failure
*/
int
virStoragePoolRefresh(virStoragePoolPtr pool,
unsigned int flags)
{
virConnectPtr conn;
VIR_DEBUG("pool=%p, flags=0x%x", pool, flags);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
conn = pool->conn;
virCheckReadOnlyGoto(conn->flags, error);
if (conn->storageDriver && conn->storageDriver->storagePoolRefresh) {
int ret;
ret = conn->storageDriver->storagePoolRefresh(pool, flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolGetName:
* @pool: pointer to storage pool
*
* Fetch the locally unique name of the storage pool
*
* Returns the name of the pool, or NULL on error
*/
const char*
virStoragePoolGetName(virStoragePoolPtr pool)
{
VIR_DEBUG("pool=%p", pool);
virResetLastError();
virCheckStoragePoolReturn(pool, NULL);
return pool->name;
}
/**
* virStoragePoolGetUUID:
* @pool: pointer to storage pool
* @uuid: buffer of VIR_UUID_BUFLEN bytes in size
*
* Fetch the globally unique ID of the storage pool
*
* Returns 0 on success, or -1 on error;
*/
int
virStoragePoolGetUUID(virStoragePoolPtr pool,
unsigned char *uuid)
{
VIR_DEBUG("pool=%p, uuid=%p", pool, uuid);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
virCheckNonNullArgGoto(uuid, error);
memcpy(uuid, &pool->uuid[0], VIR_UUID_BUFLEN);
return 0;
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolGetUUIDString:
* @pool: pointer to storage pool
* @buf: buffer of VIR_UUID_STRING_BUFLEN bytes in size
*
* Fetch the globally unique ID of the storage pool as a string
*
* Returns 0 on success, or -1 on error;
*/
int
virStoragePoolGetUUIDString(virStoragePoolPtr pool,
char *buf)
{
VIR_DEBUG("pool=%p, buf=%p", pool, buf);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
virCheckNonNullArgGoto(buf, error);
virUUIDFormat(pool->uuid, buf);
return 0;
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolGetInfo:
* @pool: pointer to storage pool
* @info: pointer at which to store info
*
* Get volatile information about the storage pool
* such as free space / usage summary
*
* Returns 0 on success, or -1 on failure.
*/
int
virStoragePoolGetInfo(virStoragePoolPtr pool,
virStoragePoolInfoPtr info)
{
virConnectPtr conn;
VIR_DEBUG("pool=%p, info=%p", pool, info);
virResetLastError();
if (info)
memset(info, 0, sizeof(*info));
virCheckStoragePoolReturn(pool, -1);
virCheckNonNullArgGoto(info, error);
conn = pool->conn;
if (conn->storageDriver->storagePoolGetInfo) {
int ret;
ret = conn->storageDriver->storagePoolGetInfo(pool, info);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolGetXMLDesc:
* @pool: pointer to storage pool
* @flags: bitwise-OR of virStorageXMLFlags
*
* Fetch an XML document describing all aspects of the
* storage pool. This is suitable for later feeding back
* into the virStoragePoolCreateXML method.
*
* Returns a XML document (caller frees), or NULL on error
*/
char *
virStoragePoolGetXMLDesc(virStoragePoolPtr pool,
unsigned int flags)
{
virConnectPtr conn;
VIR_DEBUG("pool=%p, flags=0x%x", pool, flags);
virResetLastError();
virCheckStoragePoolReturn(pool, NULL);
conn = pool->conn;
if (conn->storageDriver && conn->storageDriver->storagePoolGetXMLDesc) {
char *ret;
ret = conn->storageDriver->storagePoolGetXMLDesc(pool, flags);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return NULL;
}
/**
* virStoragePoolGetAutostart:
* @pool: pointer to storage pool
* @autostart: location in which to store autostart flag
*
* Fetches the value of the autostart flag, which determines
* whether the pool is automatically started at boot time
*
* Returns 0 on success, -1 on failure
*/
int
virStoragePoolGetAutostart(virStoragePoolPtr pool,
int *autostart)
{
virConnectPtr conn;
VIR_DEBUG("pool=%p, autostart=%p", pool, autostart);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
virCheckNonNullArgGoto(autostart, error);
conn = pool->conn;
if (conn->storageDriver && conn->storageDriver->storagePoolGetAutostart) {
int ret;
ret = conn->storageDriver->storagePoolGetAutostart(pool, autostart);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolSetAutostart:
* @pool: pointer to storage pool
* @autostart: whether the storage pool should be automatically started 0 or 1
*
* Configure the storage pool to be automatically started
* when the host machine boots.
*
* Returns 0 on success, -1 on failure
*/
int
virStoragePoolSetAutostart(virStoragePoolPtr pool,
int autostart)
{
virConnectPtr conn;
VIR_DEBUG("pool=%p, autostart=%d", pool, autostart);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
conn = pool->conn;
virCheckReadOnlyGoto(conn->flags, error);
if (conn->storageDriver && conn->storageDriver->storagePoolSetAutostart) {
int ret;
ret = conn->storageDriver->storagePoolSetAutostart(pool, autostart);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolListAllVolumes:
* @pool: Pointer to storage pool
* @vols: Pointer to a variable to store the array containing storage volume
* objects or NULL if the list is not required (just returns number
* of volumes).
* @flags: extra flags; not used yet, so callers should always pass 0
*
* Collect the list of storage volumes, and allocate an array to store those
* objects.
*
* Returns the number of storage volumes found or -1 and sets @vols to
* NULL in case of error. On success, the array stored into @vols is
* guaranteed to have an extra allocated element set to NULL but not included
* in the return count, to make iteration easier. The caller is responsible
* for calling virStorageVolFree() on each array element, then calling
* free() on @vols.
*/
int
virStoragePoolListAllVolumes(virStoragePoolPtr pool,
virStorageVolPtr **vols,
unsigned int flags)
{
VIR_DEBUG("pool=%p, vols=%p, flags=0x%x", pool, vols, flags);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
if (pool->conn->storageDriver &&
pool->conn->storageDriver->storagePoolListAllVolumes) {
int ret;
ret = pool->conn->storageDriver->storagePoolListAllVolumes(pool, vols, flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolNumOfVolumes:
* @pool: pointer to storage pool
*
* Fetch the number of storage volumes within a pool
*
* Returns the number of storage pools, or -1 on failure
*/
int
virStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
VIR_DEBUG("pool=%p", pool);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
if (pool->conn->storageDriver && pool->conn->storageDriver->storagePoolNumOfVolumes) {
int ret;
ret = pool->conn->storageDriver->storagePoolNumOfVolumes(pool);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolListVolumes:
* @pool: pointer to storage pool
* @names: array in which to storage volume names
* @maxnames: size of names array
*
* Fetch list of storage volume names, limiting to
* at most maxnames.
*
* To list the volume objects directly, see virStoragePoolListAllVolumes().
*
* Returns the number of names fetched, or -1 on error
*/
int
virStoragePoolListVolumes(virStoragePoolPtr pool,
char **const names,
int maxnames)
{
VIR_DEBUG("pool=%p, names=%p, maxnames=%d", pool, names, maxnames);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
virCheckNonNullArrayArgGoto(names, maxnames, error);
virCheckNonNegativeArgGoto(maxnames, error);
if (pool->conn->storageDriver && pool->conn->storageDriver->storagePoolListVolumes) {
int ret;
ret = pool->conn->storageDriver->storagePoolListVolumes(pool, names, maxnames);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStorageVolGetConnect:
* @vol: pointer to a pool
*
* Provides the connection pointer associated with a storage volume. The
* reference counter on the connection is not increased by this
* call.
*
* Returns the virConnectPtr or NULL in case of failure.
*/
virConnectPtr
virStorageVolGetConnect(virStorageVolPtr vol)
{
VIR_DEBUG("vol=%p", vol);
virResetLastError();
virCheckStorageVolReturn(vol, NULL);
return vol->conn;
}
/**
* virStorageVolLookupByName:
* @pool: pointer to storage pool
* @name: name of storage volume
*
* Fetch a pointer to a storage volume based on its name
* within a pool
*
* virStorageVolFree should be used to free the resources after the
* storage volume object is no longer needed.
*
* Returns a storage volume, or NULL if not found / error
*/
virStorageVolPtr
virStorageVolLookupByName(virStoragePoolPtr pool,
const char *name)
{
VIR_DEBUG("pool=%p, name=%s", pool, NULLSTR(name));
virResetLastError();
virCheckStoragePoolReturn(pool, NULL);
virCheckNonNullArgGoto(name, error);
if (pool->conn->storageDriver && pool->conn->storageDriver->storageVolLookupByName) {
virStorageVolPtr ret;
ret = pool->conn->storageDriver->storageVolLookupByName(pool, name);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return NULL;
}
/**
* virStorageVolLookupByKey:
* @conn: pointer to hypervisor connection
* @key: globally unique key
*
* Fetch a pointer to a storage volume based on its
* globally unique key
*
* virStorageVolFree should be used to free the resources after the
* storage volume object is no longer needed.
*
* Returns a storage volume, or NULL if not found / error
*/
virStorageVolPtr
virStorageVolLookupByKey(virConnectPtr conn,
const char *key)
{
VIR_DEBUG("conn=%p, key=%s", conn, NULLSTR(key));
virResetLastError();
virCheckConnectReturn(conn, NULL);
virCheckNonNullArgGoto(key, error);
if (conn->storageDriver && conn->storageDriver->storageVolLookupByKey) {
virStorageVolPtr ret;
ret = conn->storageDriver->storageVolLookupByKey(conn, key);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return NULL;
}
/**
* virStorageVolLookupByPath:
* @conn: pointer to hypervisor connection
* @path: locally unique path
*
* Fetch a pointer to a storage volume based on its
* locally (host) unique path
*
* virStorageVolFree should be used to free the resources after the
* storage volume object is no longer needed.
*
* Returns a storage volume, or NULL if not found / error
*/
virStorageVolPtr
virStorageVolLookupByPath(virConnectPtr conn,
const char *path)
{
VIR_DEBUG("conn=%p, path=%s", conn, NULLSTR(path));
virResetLastError();
virCheckConnectReturn(conn, NULL);
virCheckNonNullArgGoto(path, error);
if (conn->storageDriver && conn->storageDriver->storageVolLookupByPath) {
virStorageVolPtr ret;
ret = conn->storageDriver->storageVolLookupByPath(conn, path);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return NULL;
}
/**
* virStorageVolGetName:
* @vol: pointer to storage volume
*
* Fetch the storage volume name. This is unique
* within the scope of a pool
*
* Returns the volume name, or NULL on error
*/
const char*
virStorageVolGetName(virStorageVolPtr vol)
{
VIR_DEBUG("vol=%p", vol);
virResetLastError();
virCheckStorageVolReturn(vol, NULL);
return vol->name;
}
/**
* virStorageVolGetKey:
* @vol: pointer to storage volume
*
* Fetch the storage volume key. This is globally
* unique, so the same volume will have the same
* key no matter what host it is accessed from
*
* Returns the volume key, or NULL on error
*/
const char*
virStorageVolGetKey(virStorageVolPtr vol)
{
VIR_DEBUG("vol=%p", vol);
virResetLastError();
virCheckStorageVolReturn(vol, NULL);
return vol->key;
}
/**
* virStorageVolCreateXML:
* @pool: pointer to storage pool
* @xmlDesc: description of volume to create
* @flags: bitwise-OR of virStorageVolCreateFlags
*
* Create a storage volume within a pool based
* on an XML description. Not all pools support
* creation of volumes.
*
* Since 1.0.1 VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA
* in flags can be used to get higher performance with
* qcow2 image files which don't support full preallocation,
* by creating a sparse image file with metadata.
*
* virStorageVolFree should be used to free the resources after the
* storage volume object is no longer needed.
*
* Returns the storage volume, or NULL on error
*/
virStorageVolPtr
virStorageVolCreateXML(virStoragePoolPtr pool,
const char *xmlDesc,
unsigned int flags)
{
VIR_DEBUG("pool=%p, xmlDesc=%s, flags=0x%x", pool, NULLSTR(xmlDesc), flags);
virResetLastError();
virCheckStoragePoolReturn(pool, NULL);
virCheckNonNullArgGoto(xmlDesc, error);
virCheckReadOnlyGoto(pool->conn->flags, error);
if (pool->conn->storageDriver && pool->conn->storageDriver->storageVolCreateXML) {
virStorageVolPtr ret;
ret = pool->conn->storageDriver->storageVolCreateXML(pool, xmlDesc, flags);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return NULL;
}
/**
* virStorageVolCreateXMLFrom:
* @pool: pointer to parent pool for the new volume
* @xmlDesc: description of volume to create
* @clonevol: storage volume to use as input
* @flags: bitwise-OR of virStorageVolCreateFlags
*
* Create a storage volume in the parent pool, using the
* 'clonevol' volume as input. Information for the new
* volume (name, perms) are passed via a typical volume
* XML description.
*
* Since 1.0.1 VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA
* in flags can be used to get higher performance with
* qcow2 image files which don't support full preallocation,
* by creating a sparse image file with metadata.
*
* virStorageVolFree should be used to free the resources after the
* storage volume object is no longer needed.
*
* Returns the storage volume, or NULL on error
*/
virStorageVolPtr
virStorageVolCreateXMLFrom(virStoragePoolPtr pool,
const char *xmlDesc,
virStorageVolPtr clonevol,
unsigned int flags)
{
VIR_DEBUG("pool=%p, xmlDesc=%s, clonevol=%p, flags=0x%x",
pool, NULLSTR(xmlDesc), clonevol, flags);
virResetLastError();
virCheckStoragePoolReturn(pool, NULL);
virCheckStorageVolGoto(clonevol, error);
virCheckNonNullArgGoto(xmlDesc, error);
virCheckReadOnlyGoto(pool->conn->flags | clonevol->conn->flags, error);
if (pool->conn->storageDriver &&
pool->conn->storageDriver->storageVolCreateXMLFrom) {
virStorageVolPtr ret;
ret = pool->conn->storageDriver->storageVolCreateXMLFrom(pool, xmlDesc,
clonevol, flags);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return NULL;
}
/**
* virStorageVolDownload:
* @vol: pointer to volume to download from
* @stream: stream to use as output
* @offset: position in @vol to start reading from
* @length: limit on amount of data to download
* @flags: bitwise-OR of virStorageVolDownloadFlags
*
* Download the content of the volume as a stream. If @length
* is zero, then the remaining contents of the volume after
* @offset will be downloaded.
*
* If VIR_STORAGE_VOL_DOWNLOAD_SPARSE_STREAM is set in @flags
* effective transmission of holes is enabled. This assumes using
* the @stream with combination of virStreamSparseRecvAll() or
* virStreamRecvFlags(stream, ..., flags =
* VIR_STREAM_RECV_STOP_AT_HOLE) for honouring holes sent by
* server.
*
* This call sets up an asynchronous stream; subsequent use of
* stream APIs is necessary to transfer the actual data,
* determine how much data is successfully transferred, and
* detect any errors. The results will be unpredictable if
* another active stream is writing to the storage volume.
*
* Returns 0, or -1 upon error.
*/
int
virStorageVolDownload(virStorageVolPtr vol,
virStreamPtr stream,
unsigned long long offset,
unsigned long long length,
unsigned int flags)
{
VIR_DEBUG("vol=%p, stream=%p, offset=%llu, length=%llu, flags=0x%x",
vol, stream, offset, length, flags);
virResetLastError();
virCheckStorageVolReturn(vol, -1);
virCheckStreamGoto(stream, error);
virCheckReadOnlyGoto(vol->conn->flags, error);
if (vol->conn != stream->conn) {
virReportInvalidArg(stream,
_("stream in %s must match connection of volume '%s'"),
__FUNCTION__, vol->name);
goto error;
}
if (vol->conn->storageDriver &&
vol->conn->storageDriver->storageVolDownload) {
int ret;
ret = vol->conn->storageDriver->storageVolDownload(vol,
stream,
offset,
length,
flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(vol->conn);
return -1;
}
/**
* virStorageVolUpload:
* @vol: pointer to volume to upload
* @stream: stream to use as input
* @offset: position to start writing to
* @length: limit on amount of data to upload
* @flags: bitwise-OR of virStorageVolUploadFlags
*
* Upload new content to the volume from a stream. This call
* will fail if @offset + @length exceeds the size of the
* volume. Otherwise, if @length is non-zero, an error
* will be raised if an attempt is made to upload greater
* than @length bytes of data.
*
* If VIR_STORAGE_VOL_UPLOAD_SPARSE_STREAM is set in @flags
* effective transmission of holes is enabled. This assumes using
* the @stream with combination of virStreamSparseSendAll() or
* virStreamSendHole() to preserve source file sparseness.
*
* This call sets up an asynchronous stream; subsequent use of
* stream APIs is necessary to transfer the actual data,
* determine how much data is successfully transferred, and
* detect any errors. The results will be unpredictable if
* another active stream is writing to the storage volume.
*
* When the data stream is closed whether the upload is successful
* or not an attempt will be made to refresh the target storage pool
* if an asynchronous build is not running in order to reflect pool
* and volume changes as a result of the upload. Depending on
* the target volume storage backend and the source stream type
* for a successful upload, the target volume may take on the
* characteristics from the source stream such as format type,
* capacity, and allocation.
*
* Returns 0, or -1 upon error.
*/
int
virStorageVolUpload(virStorageVolPtr vol,
virStreamPtr stream,
unsigned long long offset,
unsigned long long length,
unsigned int flags)
{
VIR_DEBUG("vol=%p, stream=%p, offset=%llu, length=%llu, flags=0x%x",
vol, stream, offset, length, flags);
virResetLastError();
virCheckStorageVolReturn(vol, -1);
virCheckStreamGoto(stream, error);
virCheckReadOnlyGoto(vol->conn->flags, error);
if (vol->conn != stream->conn) {
virReportInvalidArg(stream,
_("stream in %s must match connection of volume '%s'"),
__FUNCTION__, vol->name);
goto error;
}
if (vol->conn->storageDriver &&
vol->conn->storageDriver->storageVolUpload) {
int ret;
ret = vol->conn->storageDriver->storageVolUpload(vol,
stream,
offset,
length,
flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(vol->conn);
return -1;
}
/**
* virStorageVolDelete:
* @vol: pointer to storage volume
* @flags: bitwise-OR of virStorageVolDeleteFlags
*
* Delete the storage volume from the pool
*
* Returns 0 on success, or -1 on error
*/
int
virStorageVolDelete(virStorageVolPtr vol,
unsigned int flags)
{
virConnectPtr conn;
VIR_DEBUG("vol=%p, flags=0x%x", vol, flags);
virResetLastError();
virCheckStorageVolReturn(vol, -1);
conn = vol->conn;
virCheckReadOnlyGoto(conn->flags, error);
if (conn->storageDriver && conn->storageDriver->storageVolDelete) {
int ret;
ret = conn->storageDriver->storageVolDelete(vol, flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(vol->conn);
return -1;
}
/**
* virStorageVolWipe:
* @vol: pointer to storage volume
* @flags: extra flags; not used yet, so callers should always pass 0
*
* Ensure data previously on a volume is not accessible to future reads.
*
* The data to be wiped may include the format and possibly size information,
* so non-raw images might become raw with a different size. It is storage
* backend dependent whether the format and size information is regenerated
* once the initial volume wipe is completed.
*
* Depending on the actual volume representation, this call may not
* overwrite the physical location of the volume. For instance, files
* stored journaled, log structured, copy-on-write, versioned, and
* network file systems are known to be problematic.
*
* Returns 0 on success, or -1 on error
*/
int
virStorageVolWipe(virStorageVolPtr vol,
unsigned int flags)
{
virConnectPtr conn;
VIR_DEBUG("vol=%p, flags=0x%x", vol, flags);
virResetLastError();
virCheckStorageVolReturn(vol, -1);
conn = vol->conn;
virCheckReadOnlyGoto(conn->flags, error);
if (conn->storageDriver && conn->storageDriver->storageVolWipe) {
int ret;
ret = conn->storageDriver->storageVolWipe(vol, flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(vol->conn);
return -1;
}
/**
* virStorageVolWipePattern:
* @vol: pointer to storage volume
* @algorithm: one of virStorageVolWipeAlgorithm
* @flags: future flags, use 0 for now
*
* Similar to virStorageVolWipe, but one can choose between
* different wiping algorithms. Also note, that depending on the
* actual volume representation, this call may not really
* overwrite the physical location of the volume. For instance,
* files stored journaled, log structured, copy-on-write,
* versioned, and network file systems are known to be
* problematic.
*
* Returns 0 on success, or -1 on error.
*/
int
virStorageVolWipePattern(virStorageVolPtr vol,
unsigned int algorithm,
unsigned int flags)
{
virConnectPtr conn;
VIR_DEBUG("vol=%p, algorithm=%u, flags=0x%x", vol, algorithm, flags);
virResetLastError();
virCheckStorageVolReturn(vol, -1);
conn = vol->conn;
virCheckReadOnlyGoto(conn->flags, error);
if (conn->storageDriver && conn->storageDriver->storageVolWipePattern) {
int ret;
ret = conn->storageDriver->storageVolWipePattern(vol, algorithm, flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(vol->conn);
return -1;
}
/**
* virStorageVolFree:
* @vol: pointer to storage volume
*
* Release the storage volume handle. The underlying
* storage volume continues to exist.
*
* Returns 0 on success, or -1 on error
*/
int
virStorageVolFree(virStorageVolPtr vol)
{
VIR_DEBUG("vol=%p", vol);
virResetLastError();
virCheckStorageVolReturn(vol, -1);
virObjectUnref(vol);
return 0;
}
/**
* virStorageVolRef:
* @vol: the vol to hold a reference on
*
* Increment the reference count on the vol. For each
* additional call to this method, there shall be a corresponding
* call to virStorageVolFree to release the reference count, once
* the caller no longer needs the reference to this object.
*
* This method is typically useful for applications where multiple
* threads are using a connection, and it is required that the
* connection remain open until all threads have finished using
* it. ie, each new thread using a vol would increment
* the reference count.
*
* Returns 0 in case of success, -1 in case of failure.
*/
int
virStorageVolRef(virStorageVolPtr vol)
{
VIR_DEBUG("vol=%p refs=%d", vol, vol ? vol->parent.u.s.refs : 0);
virResetLastError();
virCheckStorageVolReturn(vol, -1);
virObjectRef(vol);
return 0;
}
/**
* virStorageVolGetInfo:
* @vol: pointer to storage volume
* @info: pointer at which to store info
*
* Fetches volatile information about the storage
* volume such as its current allocation
*
* Returns 0 on success, or -1 on failure
*/
int
virStorageVolGetInfo(virStorageVolPtr vol,
virStorageVolInfoPtr info)
{
virConnectPtr conn;
VIR_DEBUG("vol=%p, info=%p", vol, info);
virResetLastError();
if (info)
memset(info, 0, sizeof(*info));
virCheckStorageVolReturn(vol, -1);
virCheckNonNullArgGoto(info, error);
conn = vol->conn;
if (conn->storageDriver->storageVolGetInfo) {
int ret;
ret = conn->storageDriver->storageVolGetInfo(vol, info);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(vol->conn);
return -1;
}
/**
* virStorageVolGetInfoFlags:
* @vol: pointer to storage volume
* @info: pointer at which to store info
* @flags: bitwise-OR of virStorageVolInfoFlags
*
* Fetches volatile information about the storage
* volume such as its current allocation.
*
* If the @flags argument is VIR_STORAGE_VOL_GET_PHYSICAL, then the physical
* bytes used for the volume will be returned in the @info allocation field.
* This is useful for sparse files and certain volume file types where the
* physical on disk usage can be different than the calculated allocation value
* as is the case with qcow2 files.
*
* Returns 0 on success, or -1 on failure
*/
int
virStorageVolGetInfoFlags(virStorageVolPtr vol,
virStorageVolInfoPtr info,
unsigned int flags)
{
virConnectPtr conn;
VIR_DEBUG("vol=%p, info=%p, flags=0x%x", vol, info, flags);
virResetLastError();
if (info)
memset(info, 0, sizeof(*info));
virCheckStorageVolReturn(vol, -1);
virCheckNonNullArgGoto(info, error);
conn = vol->conn;
if (conn->storageDriver->storageVolGetInfoFlags) {
int ret;
ret = conn->storageDriver->storageVolGetInfoFlags(vol, info, flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(vol->conn);
return -1;
}
/**
* virStorageVolGetXMLDesc:
* @vol: pointer to storage volume
* @flags: extra flags; not used yet, so callers should always pass 0
*
* Fetch an XML document describing all aspects of
* the storage volume
*
* Returns the XML document, or NULL on error
*/
char *
virStorageVolGetXMLDesc(virStorageVolPtr vol,
unsigned int flags)
{
virConnectPtr conn;
VIR_DEBUG("vol=%p, flags=0x%x", vol, flags);
virResetLastError();
virCheckStorageVolReturn(vol, NULL);
conn = vol->conn;
if (conn->storageDriver && conn->storageDriver->storageVolGetXMLDesc) {
char *ret;
ret = conn->storageDriver->storageVolGetXMLDesc(vol, flags);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(vol->conn);
return NULL;
}
/**
* virStorageVolGetPath:
* @vol: pointer to storage volume
*
* Fetch the storage volume path. Depending on the pool
* configuration this is either persistent across hosts,
* or dynamically assigned at pool startup. Consult
* pool documentation for information on getting the
* persistent naming
*
* Returns the storage volume path, or NULL on error. The
* caller must free() the returned path after use.
*/
char *
virStorageVolGetPath(virStorageVolPtr vol)
{
virConnectPtr conn;
VIR_DEBUG("vol=%p", vol);
virResetLastError();
virCheckStorageVolReturn(vol, NULL);
conn = vol->conn;
if (conn->storageDriver && conn->storageDriver->storageVolGetPath) {
char *ret;
ret = conn->storageDriver->storageVolGetPath(vol);
if (!ret)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(vol->conn);
return NULL;
}
/**
* virStorageVolResize:
* @vol: pointer to storage volume
* @capacity: new capacity, in bytes
* @flags: bitwise-OR of virStorageVolResizeFlags
*
* Changes the capacity of the storage volume @vol to @capacity. The
* operation will fail if the new capacity requires allocation that would
* exceed the remaining free space in the parent pool. The contents of
* the new capacity will appear as all zero bytes. The capacity value will
* be rounded to the granularity supported by the hypervisor.
*
* Normally, the operation will attempt to affect capacity with a minimum
* impact on allocation (that is, the default operation favors a sparse
* resize). If @flags contains VIR_STORAGE_VOL_RESIZE_ALLOCATE, then the
* operation will ensure that allocation is sufficient for the new
* capacity; this may make the operation take noticeably longer.
*
* Normally, the operation treats @capacity as the new size in bytes;
* but if @flags contains VIR_STORAGE_VOL_RESIZE_DELTA, then @capacity
* represents the size difference to add to the current size. It is
* up to the storage pool implementation whether unaligned requests are
* rounded up to the next valid boundary, or rejected.
*
* Normally, this operation should only be used to enlarge capacity;
* but if @flags contains VIR_STORAGE_VOL_RESIZE_SHRINK, it is possible to
* attempt a reduction in capacity even though it might cause data loss.
* If VIR_STORAGE_VOL_RESIZE_DELTA is also present, then @capacity is
* subtracted from the current size; without it, @capacity represents
* the absolute new size regardless of whether it is larger or smaller
* than the current size.
*
* Returns 0 on success, or -1 on error.
*/
int
virStorageVolResize(virStorageVolPtr vol,
unsigned long long capacity,
unsigned int flags)
{
virConnectPtr conn;
VIR_DEBUG("vol=%p capacity=%llu flags=0x%x", vol, capacity, flags);
virResetLastError();
virCheckStorageVolReturn(vol, -1);
conn = vol->conn;
virCheckReadOnlyGoto(conn->flags, error);
/* Zero capacity is only valid with either delta or shrink. */
if (capacity == 0 && !((flags & VIR_STORAGE_VOL_RESIZE_DELTA) ||
(flags & VIR_STORAGE_VOL_RESIZE_SHRINK))) {
virReportInvalidArg(capacity,
_("capacity in %s cannot be zero without 'delta' "
"or 'shrink' flags set"),
__FUNCTION__);
goto error;
}
if (conn->storageDriver && conn->storageDriver->storageVolResize) {
int ret;
ret = conn->storageDriver->storageVolResize(vol, capacity, flags);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(vol->conn);
return -1;
}
/**
* virStoragePoolIsActive:
* @pool: pointer to the storage pool object
*
* Determine if the storage pool is currently running
*
* Returns 1 if running, 0 if inactive, -1 on error
*/
int
virStoragePoolIsActive(virStoragePoolPtr pool)
{
VIR_DEBUG("pool=%p", pool);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
if (pool->conn->storageDriver->storagePoolIsActive) {
int ret;
ret = pool->conn->storageDriver->storagePoolIsActive(pool);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virStoragePoolIsPersistent:
* @pool: pointer to the storage pool object
*
* Determine if the storage pool has a persistent configuration
* which means it will still exist after shutting down
*
* Returns 1 if persistent, 0 if transient, -1 on error
*/
int
virStoragePoolIsPersistent(virStoragePoolPtr pool)
{
VIR_DEBUG("pool=%p", pool);
virResetLastError();
virCheckStoragePoolReturn(pool, -1);
if (pool->conn->storageDriver->storagePoolIsPersistent) {
int ret;
ret = pool->conn->storageDriver->storagePoolIsPersistent(pool);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(pool->conn);
return -1;
}
/**
* virConnectStoragePoolEventRegisterAny:
* @conn: pointer to the connection
* @pool: pointer to the storage pool
* @eventID: the event type to receive
* @cb: callback to the function handling network events
* @opaque: opaque data to pass on to the callback
* @freecb: optional function to deallocate opaque when not used anymore
*
* Adds a callback to receive notifications of arbitrary storage pool events
* occurring on a storage pool. This function requires that an event loop
* has been previously registered with virEventRegisterImpl() or
* virEventRegisterDefaultImpl().
*
* If @pool is NULL, then events will be monitored for any storage pool.
* If @pool is non-NULL, then only the specific storage pool will be monitored.
*
* Most types of events have a callback providing a custom set of parameters
* for the event. When registering an event, it is thus necessary to use
* the VIR_STORAGE_POOL_EVENT_CALLBACK() macro to cast the
* supplied function pointer to match the signature of this method.
*
* The virStoragePoolPtr object handle passed into the callback upon delivery
* of an event is only valid for the duration of execution of the callback.
* If the callback wishes to keep the storage pool object after the callback
* returns, it shall take a reference to it, by calling virStoragePoolRef().
* The reference can be released once the object is no longer required
* by calling virStoragePoolFree().
*
* The return value from this method is a positive integer identifier
* for the callback. To unregister a callback, this callback ID should
* be passed to the virConnectStoragePoolEventDeregisterAny() method.
*
* Returns a callback identifier on success, -1 on failure.
*/
int
virConnectStoragePoolEventRegisterAny(virConnectPtr conn,
virStoragePoolPtr pool,
int eventID,
virConnectStoragePoolEventGenericCallback cb,
void *opaque,
virFreeCallback freecb)
{
VIR_DEBUG("conn=%p, pool=%p, eventID=%d, cb=%p, opaque=%p, freecb=%p",
conn, pool, eventID, cb, opaque, freecb);
virResetLastError();
virCheckConnectReturn(conn, -1);
if (pool) {
virCheckStoragePoolGoto(pool, error);
if (pool->conn != conn) {
virReportInvalidArg(pool,
_("storage pool '%s' in %s must match connection"),
pool->name, __FUNCTION__);
goto error;
}
}
virCheckNonNullArgGoto(cb, error);
virCheckNonNegativeArgGoto(eventID, error);
if (eventID >= VIR_STORAGE_POOL_EVENT_ID_LAST) {
virReportInvalidArg(eventID,
_("eventID in %s must be less than %d"),
__FUNCTION__, VIR_STORAGE_POOL_EVENT_ID_LAST);
goto error;
}
if (conn->storageDriver &&
conn->storageDriver->connectStoragePoolEventRegisterAny) {
int ret;
ret = conn->storageDriver->connectStoragePoolEventRegisterAny(conn,
pool,
eventID,
cb,
opaque,
freecb);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return -1;
}
/**
* virConnectStoragePoolEventDeregisterAny:
* @conn: pointer to the connection
* @callbackID: the callback identifier
*
* Removes an event callback. The callbackID parameter should be the
* value obtained from a previous virConnectStoragePoolEventRegisterAny() method.
*
* Returns 0 on success, -1 on failure
*/
int
virConnectStoragePoolEventDeregisterAny(virConnectPtr conn,
int callbackID)
{
VIR_DEBUG("conn=%p, callbackID=%d", conn, callbackID);
virResetLastError();
virCheckConnectReturn(conn, -1);
virCheckNonNegativeArgGoto(callbackID, error);
if (conn->storageDriver &&
conn->storageDriver->connectStoragePoolEventDeregisterAny) {
int ret;
ret = conn->storageDriver->connectStoragePoolEventDeregisterAny(conn,
callbackID);
if (ret < 0)
goto error;
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return -1;
}
/**
* virConnectGetStoragePoolCapabilities:
* @conn: pointer to the hypervisor connection
* @flags: extra flags; not used yet, so callers should always pass 0
*
* Prior creating a storage pool (for instance via virStoragePoolCreateXML
* or virStoragePoolDefineXML) it may be suitable to know what pool types
* are supported along with the file/disk formats for each pool.
*
* Returns NULL in case of error or an XML string defining the capabilities.
*/
char *
virConnectGetStoragePoolCapabilities(virConnectPtr conn,
unsigned int flags)
{
VIR_DEBUG("conn=%p, flags=0x%x", conn, flags);
virResetLastError();
virCheckConnectReturn(conn, NULL);
if (conn->storageDriver &&
conn->storageDriver->connectGetStoragePoolCapabilities) {
char *ret;
ret = conn->storageDriver->connectGetStoragePoolCapabilities(conn,
flags);
if (!ret)
goto error;
VIR_DEBUG("conn=%p, ret=%s", conn, ret);
return ret;
}
virReportUnsupportedError();
error:
virDispatchError(conn);
return NULL;
}