mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-02 01:45:17 +00:00
Check whether pools are already active upon libvirtd startup
When libvirt starts up all storage pools default to the inactive state, even if the underlying storage is already active on the host. This introduces a new API into the internal storage backend drivers that checks whether a storage pool is already active. If the pool is active at libvirtd startup, the volume list will be immediately populated. * src/storage/storage_backend.h: New internal API for checking storage pool state * src/storage/storage_driver.c: Check whether a pool is active upon driver startup * src/storage/storage_backend_fs.c, src/storage/storage_backend_iscsi.c, src/storage/storage_backend_logical.c, src/storage/storage_backend_mpath.c, src/storage/storage_backend_scsi.c: Add checks for pool state
This commit is contained in:
parent
4d0350fc38
commit
1b7e0b1a9c
@ -25,10 +25,12 @@
|
||||
# define __VIR_STORAGE_BACKEND_H__
|
||||
|
||||
# include <stdint.h>
|
||||
# include <stdbool.h>
|
||||
# include "internal.h"
|
||||
# include "storage_conf.h"
|
||||
|
||||
typedef char * (*virStorageBackendFindPoolSources)(virConnectPtr conn, const char *srcSpec, unsigned int flags);
|
||||
typedef int (*virStorageBackendCheckPool)(virConnectPtr conn, virStoragePoolObjPtr pool, bool *active);
|
||||
typedef int (*virStorageBackendStartPool)(virConnectPtr conn, virStoragePoolObjPtr pool);
|
||||
typedef int (*virStorageBackendBuildPool)(virConnectPtr conn, virStoragePoolObjPtr pool, unsigned int flags);
|
||||
typedef int (*virStorageBackendRefreshPool)(virConnectPtr conn, virStoragePoolObjPtr pool);
|
||||
@ -65,6 +67,7 @@ struct _virStorageBackend {
|
||||
int type;
|
||||
|
||||
virStorageBackendFindPoolSources findPoolSources;
|
||||
virStorageBackendCheckPool checkPool;
|
||||
virStorageBackendStartPool startPool;
|
||||
virStorageBackendBuildPool buildPool;
|
||||
virStorageBackendRefreshPool refreshPool;
|
||||
|
@ -479,6 +479,30 @@ virStorageBackendFileSystemUnmount(virStoragePoolObjPtr pool) {
|
||||
#endif /* WITH_STORAGE_FS */
|
||||
|
||||
|
||||
static int
|
||||
virStorageBackendFileSystemCheck(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virStoragePoolObjPtr pool,
|
||||
bool *isActive)
|
||||
{
|
||||
*isActive = false;
|
||||
if (pool->def->type == VIR_STORAGE_POOL_DIR) {
|
||||
if (access(pool->def->target.path, F_OK) == 0)
|
||||
*isActive = true;
|
||||
#if WITH_STORAGE_FS
|
||||
} else {
|
||||
int ret;
|
||||
if ((ret = virStorageBackendFileSystemIsMounted(pool)) != 0) {
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
*isActive = true;
|
||||
}
|
||||
#endif /* WITH_STORAGE_FS */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if WITH_STORAGE_FS
|
||||
/**
|
||||
* @conn connection to report errors against
|
||||
* @pool storage pool to start
|
||||
@ -489,7 +513,6 @@ virStorageBackendFileSystemUnmount(virStoragePoolObjPtr pool) {
|
||||
*
|
||||
* Returns 0 on success, -1 on error
|
||||
*/
|
||||
#if WITH_STORAGE_FS
|
||||
static int
|
||||
virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virStoragePoolObjPtr pool)
|
||||
@ -937,6 +960,7 @@ virStorageBackend virStorageBackendDirectory = {
|
||||
.type = VIR_STORAGE_POOL_DIR,
|
||||
|
||||
.buildPool = virStorageBackendFileSystemBuild,
|
||||
.checkPool = virStorageBackendFileSystemCheck,
|
||||
.refreshPool = virStorageBackendFileSystemRefresh,
|
||||
.deletePool = virStorageBackendFileSystemDelete,
|
||||
.buildVol = virStorageBackendFileSystemVolBuild,
|
||||
@ -951,6 +975,7 @@ virStorageBackend virStorageBackendFileSystem = {
|
||||
.type = VIR_STORAGE_POOL_FS,
|
||||
|
||||
.buildPool = virStorageBackendFileSystemBuild,
|
||||
.checkPool = virStorageBackendFileSystemCheck,
|
||||
.startPool = virStorageBackendFileSystemStart,
|
||||
.refreshPool = virStorageBackendFileSystemRefresh,
|
||||
.stopPool = virStorageBackendFileSystemStop,
|
||||
@ -965,6 +990,7 @@ virStorageBackend virStorageBackendNetFileSystem = {
|
||||
.type = VIR_STORAGE_POOL_NETFS,
|
||||
|
||||
.buildPool = virStorageBackendFileSystemBuild,
|
||||
.checkPool = virStorageBackendFileSystemCheck,
|
||||
.startPool = virStorageBackendFileSystemStart,
|
||||
.findPoolSources = virStorageBackendFileSystemNetFindPoolSources,
|
||||
.refreshPool = virStorageBackendFileSystemRefresh,
|
||||
|
@ -633,6 +633,39 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
virStorageBackendISCSICheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virStoragePoolObjPtr pool,
|
||||
bool *isActive)
|
||||
{
|
||||
char *session = NULL;
|
||||
int ret = -1;
|
||||
|
||||
*isActive = false;
|
||||
|
||||
if (pool->def->source.host.name == NULL) {
|
||||
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("missing source host"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pool->def->source.ndevice != 1 ||
|
||||
pool->def->source.devices[0].path == NULL) {
|
||||
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("missing source device"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((session = virStorageBackendISCSISession(pool, 1)) != NULL) {
|
||||
*isActive = true;
|
||||
VIR_FREE(session);
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virStorageBackendISCSIStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virStoragePoolObjPtr pool)
|
||||
@ -730,6 +763,7 @@ cleanup:
|
||||
virStorageBackend virStorageBackendISCSI = {
|
||||
.type = VIR_STORAGE_POOL_ISCSI,
|
||||
|
||||
.checkPool = virStorageBackendISCSICheckPool,
|
||||
.startPool = virStorageBackendISCSIStartPool,
|
||||
.refreshPool = virStorageBackendISCSIRefreshPool,
|
||||
.stopPool = virStorageBackendISCSIStopPool,
|
||||
|
@ -360,6 +360,27 @@ virStorageBackendLogicalFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virStorageBackendLogicalCheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virStoragePoolObjPtr pool,
|
||||
bool *isActive)
|
||||
{
|
||||
char *path;
|
||||
|
||||
*isActive = false;
|
||||
if (virAsprintf(&path, "/dev/%s", pool->def->source.name) < 0) {
|
||||
virReportOOMError();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (access(path, F_OK) == 0)
|
||||
*isActive = true;
|
||||
|
||||
VIR_FREE(path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
virStorageBackendLogicalStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virStoragePoolObjPtr pool)
|
||||
@ -684,6 +705,7 @@ virStorageBackend virStorageBackendLogical = {
|
||||
.type = VIR_STORAGE_POOL_LOGICAL,
|
||||
|
||||
.findPoolSources = virStorageBackendLogicalFindPoolSources,
|
||||
.checkPool = virStorageBackendLogicalCheckPool,
|
||||
.startPool = virStorageBackendLogicalStartPool,
|
||||
.buildPool = virStorageBackendLogicalBuildPool,
|
||||
.refreshPool = virStorageBackendLogicalRefreshPool,
|
||||
|
@ -291,6 +291,22 @@ out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
virStorageBackendMpathCheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
|
||||
bool *isActive)
|
||||
{
|
||||
const char *path = "/dev/mpath";
|
||||
|
||||
*isActive = false;
|
||||
|
||||
if (access(path, F_OK) == 0)
|
||||
*isActive = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
virStorageBackendMpathRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
@ -313,5 +329,6 @@ virStorageBackendMpathRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virStorageBackend virStorageBackendMpath = {
|
||||
.type = VIR_STORAGE_POOL_MPATH,
|
||||
|
||||
.checkPool = virStorageBackendMpathCheckPool,
|
||||
.refreshPool = virStorageBackendMpathRefreshPool,
|
||||
};
|
||||
|
@ -587,6 +587,26 @@ out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
virStorageBackendSCSICheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virStoragePoolObjPtr pool,
|
||||
bool *isActive)
|
||||
{
|
||||
char *path;
|
||||
|
||||
*isActive = false;
|
||||
if (virAsprintf(&path, "/sys/class/scsi_host/%s", pool->def->source.adapter) < 0) {
|
||||
virReportOOMError();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (access(path, F_OK) == 0)
|
||||
*isActive = true;
|
||||
|
||||
VIR_FREE(path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
virStorageBackendSCSIRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
@ -621,5 +641,6 @@ out:
|
||||
virStorageBackend virStorageBackendSCSI = {
|
||||
.type = VIR_STORAGE_POOL_SCSI,
|
||||
|
||||
.checkPool = virStorageBackendSCSICheckPool,
|
||||
.refreshPool = virStorageBackendSCSIRefreshPool,
|
||||
};
|
||||
|
@ -69,34 +69,49 @@ storageDriverAutostart(virStorageDriverStatePtr driver) {
|
||||
|
||||
for (i = 0 ; i < driver->pools.count ; i++) {
|
||||
virStoragePoolObjPtr pool = driver->pools.objs[i];
|
||||
virStorageBackendPtr backend;
|
||||
bool started = false;
|
||||
|
||||
virStoragePoolObjLock(pool);
|
||||
if (pool->autostart &&
|
||||
!virStoragePoolObjIsActive(pool)) {
|
||||
virStorageBackendPtr backend;
|
||||
if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
|
||||
VIR_ERROR(_("Missing backend %d"), pool->def->type);
|
||||
virStoragePoolObjUnlock(pool);
|
||||
continue;
|
||||
}
|
||||
if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
|
||||
VIR_ERROR(_("Missing backend %d"), pool->def->type);
|
||||
virStoragePoolObjUnlock(pool);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (backend->checkPool &&
|
||||
backend->checkPool(NULL, pool, &started) < 0) {
|
||||
virErrorPtr err = virGetLastError();
|
||||
VIR_ERROR(_("Failed to initialize storage pool '%s': %s"),
|
||||
pool->def->name, err ? err->message :
|
||||
_("no error message found"));
|
||||
virStoragePoolObjUnlock(pool);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!started &&
|
||||
pool->autostart &&
|
||||
!virStoragePoolObjIsActive(pool)) {
|
||||
if (backend->startPool &&
|
||||
backend->startPool(NULL, pool) < 0) {
|
||||
virErrorPtr err = virGetLastError();
|
||||
VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
|
||||
pool->def->name, err ? err->message :
|
||||
"no error message found");
|
||||
_("no error message found"));
|
||||
virStoragePoolObjUnlock(pool);
|
||||
continue;
|
||||
}
|
||||
started = true;
|
||||
}
|
||||
|
||||
if (started) {
|
||||
if (backend->refreshPool(NULL, pool) < 0) {
|
||||
virErrorPtr err = virGetLastError();
|
||||
if (backend->stopPool)
|
||||
backend->stopPool(NULL, pool);
|
||||
VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
|
||||
pool->def->name, err ? err->message :
|
||||
"no error message found");
|
||||
_("no error message found"));
|
||||
virStoragePoolObjUnlock(pool);
|
||||
continue;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user