/* * 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 * . */ #include #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. * * WARNING: When writing libvirt bindings in other languages, do * not use this function. Instead, store the connection and * the pool object together. * * 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 * * 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=%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); virCheckNonNullArgGoto(names, 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); virCheckNonNullArgGoto(names, 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=%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; } /** * 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=%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=%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=%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=%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=%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->object.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=%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=%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: new flag setting * * Sets the autostart flag * * 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=%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); virCheckNonNullArgGoto(names, 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. * * WARNING: When writing libvirt bindings in other languages, do * not use this function. Instead, store the connection and * the volume object together. * * 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=%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=%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: extra flags; not used yet, so callers should always pass 0 * * 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. * * 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=%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: extra flags; not used yet, so callers should always pass 0 * * 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. * * 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 the target storage pool will be refreshed 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=%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: extra flags; not used yet, so callers should always pass 0 * * 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=%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 * * Returns 0 on success, or -1 on error */ int virStorageVolWipe(virStorageVolPtr vol, unsigned int flags) { virConnectPtr conn; VIR_DEBUG("vol=%p, flags=%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. * * 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=%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->object.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; } /** * 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=%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=%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; }