libvirt/src/storage/storage_backend_vstorage.c
Peter Krempa f813fe810f storage: backend: Refactor registration of the backend drivers
Add APIs that allow to dynamically register driver backends so that the
list of available drivers does not need to be known during compile time.

This will allow us to modularize the storage driver on runtime.
2017-02-21 09:34:30 +01:00

193 lines
4.8 KiB
C

#include <config.h>
#include "viralloc.h"
#include "virerror.h"
#include "virfile.h"
#include "storage_backend_vstorage.h"
#include "virlog.h"
#include "virstring.h"
#include <mntent.h>
#include <pwd.h>
#include <grp.h>
#include "storage_util.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
VIR_LOG_INIT("storage.storage_backend_vstorage");
/**
* @conn connection to report errors against
* @pool storage pool to build
* @flags controls the pool formatting behaviour
*
* Does not support @flags, if provided an error will occur.
*
* Returns 0 on success, -1 on error
*/
static int
virStorageBackendVzPoolBuild(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool,
unsigned int flags)
{
virCheckFlags(0, -1);
return virStorageBackendBuildLocal(pool);
}
static int
virStorageBackendVzPoolStart(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool)
{
int ret = -1;
virCommandPtr cmd = NULL;
char *grp_name = NULL;
char *usr_name = NULL;
char *mode = NULL;
/* Check the permissions */
if (pool->def->target.perms.mode == (mode_t) - 1)
pool->def->target.perms.mode = VIR_STORAGE_DEFAULT_POOL_PERM_MODE;
if (pool->def->target.perms.uid == (uid_t) -1)
pool->def->target.perms.uid = geteuid();
if (pool->def->target.perms.gid == (gid_t) -1)
pool->def->target.perms.gid = getegid();
/* Convert ids to names because vstorage uses names */
if (!(grp_name = virGetGroupName(pool->def->target.perms.gid)))
goto cleanup;
if (!(usr_name = virGetUserName(pool->def->target.perms.uid)))
goto cleanup;
if (virAsprintf(&mode, "%o", pool->def->target.perms.mode) < 0)
goto cleanup;
cmd = virCommandNewArgList(VSTORAGE_MOUNT,
"-c", pool->def->source.name,
pool->def->target.path,
"-m", mode,
"-g", grp_name, "-u", usr_name,
NULL);
if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
ret = 0;
cleanup:
virCommandFree(cmd);
VIR_FREE(mode);
VIR_FREE(grp_name);
VIR_FREE(usr_name);
return ret;
}
static int
virStorageBackendVzIsMounted(virStoragePoolObjPtr pool)
{
int ret = -1;
FILE *mtab;
struct mntent ent;
char buf[1024];
char *cluster = NULL;
if (virAsprintf(&cluster, "vstorage://%s", pool->def->source.name) < 0)
return -1;
if ((mtab = fopen(_PATH_MOUNTED, "r")) == NULL) {
virReportSystemError(errno,
_("cannot read mount list '%s'"),
_PATH_MOUNTED);
goto cleanup;
}
while ((getmntent_r(mtab, &ent, buf, sizeof(buf))) != NULL) {
if (STREQ(ent.mnt_dir, pool->def->target.path) &&
STREQ(ent.mnt_fsname, cluster)) {
ret = 1;
goto cleanup;
}
}
ret = 0;
cleanup:
VIR_FORCE_FCLOSE(mtab);
VIR_FREE(cluster);
return ret;
}
static int
virStorageBackendVzPoolStop(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool)
{
virCommandPtr cmd = NULL;
int ret = -1;
int rc;
/* Short-circuit if already unmounted */
if ((rc = virStorageBackendVzIsMounted(pool)) != 1)
return rc;
cmd = virCommandNewArgList(UMOUNT, pool->def->target.path, NULL);
if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
ret = 0;
cleanup:
virCommandFree(cmd);
return ret;
}
/*
* Check whether the cluster is mounted
*/
static int
virStorageBackendVzCheck(virStoragePoolObjPtr pool,
bool *isActive)
{
int ret = -1;
*isActive = false;
if ((ret = virStorageBackendVzIsMounted(pool)) != 0) {
if (ret < 0)
return -1;
*isActive = true;
}
return 0;
}
virStorageBackend virStorageBackendVstorage = {
.type = VIR_STORAGE_POOL_VSTORAGE,
.buildPool = virStorageBackendVzPoolBuild,
.startPool = virStorageBackendVzPoolStart,
.stopPool = virStorageBackendVzPoolStop,
.deletePool = virStorageBackendDeleteLocal,
.refreshPool = virStorageBackendRefreshLocal,
.checkPool = virStorageBackendVzCheck,
.buildVol = virStorageBackendVolBuildLocal,
.buildVolFrom = virStorageBackendVolBuildFromLocal,
.createVol = virStorageBackendVolCreateLocal,
.refreshVol = virStorageBackendVolRefreshLocal,
.deleteVol = virStorageBackendVolDeleteLocal,
.resizeVol = virStorageBackendVolResizeLocal,
.uploadVol = virStorageBackendVolUploadLocal,
.downloadVol = virStorageBackendVolDownloadLocal,
.wipeVol = virStorageBackendVolWipeLocal,
};
int
virStorageBackendVstorageRegister(void)
{
return virStorageBackendRegister(&virStorageBackendVstorage);
}