This patch supports pool and volume management within Virtuozzo Storage. Virtuozzo Storage is a highly-available distributed software defined storage with built-in replication and disaster recovery. From client's point of view it looks like network attached storage (NFS or GlusterFS). More information about vzstorage can be found here: https://openvz.org/Virtuozzo_Storage It supports the same volume formats as directory, nfs, etc. Default format is ploop. Signed-off-by: Olga Krishtal <okrishtal@xxxxxxxxxxxxx> --- configure.ac | 28 +++++ docs/schemas/storagepool.rng | 13 +++ include/libvirt/libvirt-storage.h | 1 + src/Makefile.am | 7 +- src/conf/storage_conf.c | 19 ++- src/conf/storage_conf.h | 4 +- src/storage/storage_backend.c | 4 +- src/storage/storage_backend_fs.c | 235 +++++++++++++++++++++++++++++++++++++- src/storage/storage_backend_fs.h | 3 + src/storage/storage_driver.c | 2 + tools/virsh-pool.c | 2 + tools/virsh.c | 3 + 12 files changed, 311 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 1eb19ee..d6c14eb 100644 --- a/configure.ac +++ b/configure.ac @@ -1739,6 +1739,10 @@ AC_ARG_WITH([storage-zfs], [AS_HELP_STRING([--with-storage-zfs], [with ZFS backend for the storage driver @<:@default=check@:>@])], [],[with_storage_zfs=check]) +AC_ARG_WITH([storage-vz], + [AS_HELP_STRING([--with-storage-vz], + [with VZ backend for the storage driver @<:@default=check@:>@])], + [],[with_storage_vz=check]) if test "$with_libvirtd" = "no"; then with_storage_dir=no @@ -1752,6 +1756,7 @@ if test "$with_libvirtd" = "no"; then with_storage_sheepdog=no with_storage_gluster=no with_storage_zfs=no + with_storage_vz=no fi if test "$with_storage_dir" = "yes" ; then AC_DEFINE_UNQUOTED([WITH_STORAGE_DIR], 1, [whether directory backend for storage driver is enabled]) @@ -2007,6 +2012,28 @@ if test "$with_storage_fs" = "yes" || fi fi +if test "$with_storage_vz" = "yes" || test "$with_storage_vz" = "check"; then + AC_PATH_PROG([VZSTORAGE], [pstorage], [], [$PATH:/sbin:/usr/bin]) + AC_PATH_PROG([VZMOUNT], [pstorage-mount], [], [$PATH:/sbin/usr/bin]) + if test "$with_storage_vz" = "yes"; then + if test -z "$VZSTORAGE" ; then AC_MSG_ERROR([We need vzstorage tools for VZ storage driver]); fi + if test -z "$VZMOUNT" ; then AC_MSG_ERROR([We need vzstorage mount tool for VZ storage driver]); fi + else + if test -z "$VZSTORAGE" ; then with_storage_vz=no; fi + if test -z "$VZSTORAGE" ; then with_storage_vz=no; fi + + if test "$with_storage_vz" = "check" ; then with_storage_vz=yes ; fi + fi + if test "$with_storage_vz" = "yes"; then + AC_DEFINE_UNQUOTED([WITH_STORAGE_VZ], 1, [whether VZ backend for storage driver is enabled]) + AC_DEFINE_UNQUOTED([VZSTORAGE], ["$VZSTORAGE"], [Location or name of vzstorage program]) + AC_DEFINE_UNQUOTED([VZMOUNT], ["$VZMOUNT"], [Location or name of vzstorage mount program]) + fi + + if test "$with_storage_vz" = "check" ; then with_storage_vz=yes ; fi +fi +AM_CONDITIONAL([WITH_STORAGE_VZ], [test "$with_storage_vz" = "yes"]) + LIBPARTED_CFLAGS= LIBPARTED_LIBS= if test "$with_storage_disk" = "yes" || @@ -2812,6 +2839,7 @@ AC_MSG_NOTICE([ RBD: $with_storage_rbd]) AC_MSG_NOTICE([Sheepdog: $with_storage_sheepdog]) AC_MSG_NOTICE([ Gluster: $with_storage_gluster]) AC_MSG_NOTICE([ ZFS: $with_storage_zfs]) +AC_MSG_NOTICE([ VZ: $with_storage_vz]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([Security Drivers]) AC_MSG_NOTICE([]) diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng index 49d212f..b9bef7d 100644 --- a/docs/schemas/storagepool.rng +++ b/docs/schemas/storagepool.rng @@ -24,6 +24,7 @@ <ref name='poolsheepdog'/> <ref name='poolgluster'/> <ref name='poolzfs'/> + <ref name='poolvz'/> </choice> </element> </define> @@ -173,6 +174,18 @@ </interleave> </define> + <define name='poolvz'> + <attribute name='type'> + <value>vz</value> + </attribute> + <interleave> + <ref name='commonmetadata'/> + <ref name='sizing'/> + <ref name='sourceclustervz'/> + <ref name='target'/> + </interleave> + </define> + <define name='sourceinfovendor'> <interleave> <optional> diff --git a/include/libvirt/libvirt-storage.h b/include/libvirt/libvirt-storage.h index 57a26c4..0dd47b0 100644 --- a/include/libvirt/libvirt-storage.h +++ b/include/libvirt/libvirt-storage.h @@ -232,6 +232,7 @@ typedef enum { VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG = 1 << 15, VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER = 1 << 16, VIR_CONNECT_LIST_STORAGE_POOLS_ZFS = 1 << 17, + VIR_CONNECT_LIST_STORAGE_POOLS_VZ = 1 << 18, } virConnectListAllStoragePoolsFlags; int virConnectListAllStoragePools(virConnectPtr conn, diff --git a/src/Makefile.am b/src/Makefile.am index eda0365..0909618 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -978,6 +978,7 @@ STORAGE_DRIVER_GLUSTER_SOURCES = \ STORAGE_DRIVER_ZFS_SOURCES = \ storage/storage_backend_zfs.h storage/storage_backend_zfs.c + STORAGE_HELPER_DISK_SOURCES = \ storage/parthelper.c @@ -1670,6 +1671,10 @@ if WITH_STORAGE_ZFS libvirt_driver_storage_impl_la_SOURCES += $(STORAGE_DRIVER_ZFS_SOURCES) endif WITH_STORAGE_ZFS +if WITH_STORAGE_VZ +libvirt_driver_storage_impl_la_SOURCES += $(STORAGE_DRIVER_VZ_SOURCES) +endif WITH_STORAGE_VZ + if WITH_NODE_DEVICES # Needed to keep automake quiet about conditionals if WITH_DRIVER_MODULES @@ -1880,7 +1885,7 @@ EXTRA_DIST += \ $(STORAGE_DRIVER_SHEEPDOG_SOURCES) \ $(STORAGE_DRIVER_GLUSTER_SOURCES) \ $(STORAGE_DRIVER_ZFS_SOURCES) \ - $(NODE_DEVICE_DRIVER_SOURCES) \ + $(NODE_DEVICE_DRIVER_SOURCES) \ $(NODE_DEVICE_DRIVER_HAL_SOURCES) \ $(NODE_DEVICE_DRIVER_UDEV_SOURCES) \ $(NWFILTER_DRIVER_SOURCES) \ diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index daf8f99..b8ff3c5 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -60,7 +60,7 @@ VIR_ENUM_IMPL(virStoragePool, "dir", "fs", "netfs", "logical", "disk", "iscsi", "scsi", "mpath", "rbd", - "sheepdog", "gluster", "zfs") + "sheepdog", "gluster", "zfs", "vz") VIR_ENUM_IMPL(virStoragePoolFormatFileSystem, VIR_STORAGE_POOL_FS_LAST, @@ -274,6 +274,18 @@ static virStoragePoolTypeInfo poolTypeInfo[] = { .defaultFormat = VIR_STORAGE_FILE_RAW, }, }, + {.poolType = VIR_STORAGE_POOL_VZ, + .poolOptions = { + .flags = (VIR_STORAGE_POOL_SOURCE_HOST | + VIR_STORAGE_POOL_SOURCE_DEVICE | + VIR_STORAGE_POOL_SOURCE_DIR), + }, + .volOptions = { + .defaultFormat = VIR_STORAGE_FILE_PLOOP, + .formatFromString = virStorageVolumeFormatFromString, + .formatToString = virStorageFileFormatTypeToString, + }, + }, }; @@ -2595,6 +2607,11 @@ virStoragePoolSourceFindDuplicate(virConnectPtr conn, /* Only one mpath pool is valid per host */ matchpool = pool; break; + case VIR_STORAGE_POOL_VZ: + if (virStoragePoolSourceMatchSingleHost(&pool->def->source, + &def->source)) + matchpool = pool; + break; case VIR_STORAGE_POOL_RBD: case VIR_STORAGE_POOL_LAST: break; diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index 31b45be..f8086dd 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -94,6 +94,7 @@ typedef enum { VIR_STORAGE_POOL_SHEEPDOG, /* Sheepdog device */ VIR_STORAGE_POOL_GLUSTER, /* Gluster device */ VIR_STORAGE_POOL_ZFS, /* ZFS */ + VIR_STORAGE_POOL_VZ, /* vzstorage */ VIR_STORAGE_POOL_LAST, } virStoragePoolType; @@ -541,7 +542,8 @@ VIR_ENUM_DECL(virStoragePartedFs) 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_ZFS | \ + VIR_CONNECT_LIST_STORAGE_POOLS_VZ) # define VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL \ (VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE | \ diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index 372f5b1..d47a76a 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -95,7 +95,6 @@ #if WITH_STORAGE_ZFS # include "storage_backend_zfs.h" #endif - #define VIR_FROM_THIS VIR_FROM_STORAGE VIR_LOG_INIT("storage.storage_backend"); @@ -135,6 +134,9 @@ static virStorageBackendPtr backends[] = { #if WITH_STORAGE_ZFS &virStorageBackendZFS, #endif +#if WITH_STORAGE_VZ + &virStorageBackendVz, +#endif NULL }; diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index 5e57366..5754be8 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -397,7 +397,7 @@ virStorageBackendFileSystemGetPoolSource(virStoragePoolObjPtr pool) { char *src = NULL; - if (pool->def->type == VIR_STORAGE_POOL_NETFS) { + if (pool->def->type == VIR_STORAGE_POOL_NETFS || pool->def->type == VIR_STORAGE_POOL_VZ) { if (pool->def->source.format == VIR_STORAGE_POOL_NETFS_CIFS) { if (virAsprintf(&src, "//%s/%s", pool->def->source.hosts[0].name, @@ -826,6 +826,14 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, mode_t mode; bool needs_create_as_uid; unsigned int dir_create_flags; + char *target_path = pool->def->target.path; + char *path = NULL; + + if (pool->def->type == VIR_STORAGE_POOL_VZ) { + path = virStringReplace(pool->def->target.path, + pool->def->source.dir, "\0"); + target_path = path; + } virCheckFlags(VIR_STORAGE_POOL_BUILD_OVERWRITE | VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, ret); @@ -834,7 +842,7 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, error); - if (VIR_STRDUP(parent, pool->def->target.path) < 0) + if (VIR_STRDUP(parent, target_path) < 0) goto error; if (!(p = strrchr(parent, '/'))) { virReportError(VIR_ERR_INVALID_ARG, @@ -859,7 +867,7 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, mode = pool->def->target.perms.mode; if (mode == (mode_t) -1 && - (needs_create_as_uid || !virFileExists(pool->def->target.path))) + (needs_create_as_uid || !virFileExists(target_path))) mode = VIR_STORAGE_DEFAULT_POOL_PERM_MODE; if (needs_create_as_uid) dir_create_flags |= VIR_DIR_CREATE_AS_UID; @@ -867,7 +875,7 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, /* Now create the final dir in the path with the uid/gid/mode * requested in the config. If the dir already exists, just set * the perms. */ - if (virDirCreate(pool->def->target.path, + if (virDirCreate(target_path, mode, pool->def->target.perms.uid, pool->def->target.perms.gid, @@ -882,6 +890,7 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED, error: VIR_FREE(parent); + VIR_FREE(path); return ret; } @@ -1068,14 +1077,23 @@ virStorageBackendFileSystemDelete(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, unsigned int flags) { + char *path = NULL; + char *target_path = pool->def->target.path; + virCheckFlags(0, -1); /* XXX delete all vols first ? */ - if (rmdir(pool->def->target.path) < 0) { + if (pool->def->type == VIR_STORAGE_POOL_VZ) { + path = virStringReplace(pool->def->target.path, + pool->def->source.dir, "\0"); + target_path = path; + } + + if (rmdir(target_path) < 0) { virReportSystemError(errno, _("failed to remove pool '%s'"), - pool->def->target.path); + target_path); return -1; } @@ -1651,3 +1669,208 @@ virStorageFileBackend virStorageFileBackendDir = { }; #endif /* WITH_STORAGE_FS */ + +#if WITH_STORAGE_VZ + +static int +virStorageBackendVzStart(virConnectPtr conn ATTRIBUTE_UNUSED, + virStoragePoolObjPtr pool) +{ + int ret = -1; + virCommandPtr cmd = NULL; + char *logfile = NULL; + char *path = NULL; + char *target_path = pool->def->target.path; + char *unmounted = NULL; + + if (pool->def->source.dir) { + path = virStringReplace(pool->def->target.path, + pool->def->source.dir, "\0"); + target_path = path; + } + + if (virAsprintf(&logfile, "/var/log/pstorage/vz7-vzstorage/" + "%s-pstorage-mount.log.gz", + pool->def->name) < 0) + goto cleanup; + + if (virAsprintf(&unmounted, "/var/log/pstorage/vz7-vzstorage/" + "%s-pstorage-umounted.log.gz", + pool->def->name) < 0) + goto cleanup; + + if (virFileExists(unmounted)) { + cmd = virCommandNewArgList("mv", unmounted, logfile, NULL); + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + virCommandFree(cmd); + } + + cmd = virCommandNewArgList(VZMOUNT, "-c", pool->def->source.devices[0].path, + target_path, "-l", logfile, NULL); + + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + ret = 0; + + cleanup: + VIR_FREE(path); + VIR_FREE(logfile); + VIR_FREE(unmounted); + virCommandFree(cmd); + return ret; +} + +static int +virStorageBackendVzCheck(virStoragePoolObjPtr pool, + bool *active) +{ + char *logfile = NULL; + + if (virAsprintf(&logfile, "/var/log/pstorage/vz7-vzstorage/" + "%s-pstorage-mount.log.gz", + pool->def->name) < 0) + return -1; + + *active = virFileExists(logfile); + + VIR_FREE(logfile); + return 0; +} + +static int +virStorageBackendVzStop(virConnectPtr conn ATTRIBUTE_UNUSED, + virStoragePoolObjPtr pool) +{ + int ret = -1; + virCommandPtr cmd = NULL; + char *path = NULL; + char *target_path = pool->def->target.path; + char *logfile = NULL; + char *unmounted; + if (pool->def->source.dir) { + path = virStringReplace(pool->def->target.path, + pool->def->source.dir, "\0"); + target_path = path; + } + + if (virAsprintf(&logfile, "/var/log/pstorage/vz7-vzstorage/" + "%s-pstorage-mount.log.gz", + pool->def->name) < 0) + goto cleanup; + + if (virAsprintf(&unmounted, "/var/log/pstorage/vz7-vzstorage/" + "%s-pstorage-umounted.log.gz", + pool->def->name) < 0) + goto cleanup; + + if (virFileExists(logfile)) { + cmd = virCommandNewArgList("mv", logfile, unmounted, NULL); + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + virCommandFree(cmd); + } + + cmd = virCommandNewArgList(UMOUNT, target_path, NULL); + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + ret = 0; + + cleanup: + VIR_FREE(path); + VIR_FREE(logfile); + VIR_FREE(unmounted); + virCommandFree(cmd); + return ret; +} + +struct _virVzDiscoverState { + const char *host; + virStoragePoolSourceList list; +}; + +typedef struct _virVzDiscoverState virVzDiscoverState; + +static char* +virStorageBackendVzfindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED, + const char *srcSpec ATTRIBUTE_UNUSED, + unsigned int flags) +{ + + virCommandPtr cmd = NULL; + char *buf = NULL; + char *ret = NULL; + char **clusters; + size_t clusters_num = 0; + size_t i = 0; + + virVzDiscoverState vz = { + .host = NULL, + .list = { + .type = VIR_STORAGE_POOL_VZ, + .nsources = 0, + .sources = NULL + } + }; + + virCheckFlags(0, NULL); + cmd = virCommandNewArgList(VZSTORAGE, "discover", NULL); + virCommandSetOutputBuffer(cmd, &buf); + + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + if (!buf) + goto cleanup; + + if (!(clusters = virStringSplitCount(buf, "\n", 0, &clusters_num))) + goto cleanup; + + vz.list.nsources = clusters_num - 1; + + if (VIR_ALLOC_N(vz.list.sources, vz.list.nsources) < 0) + goto cleanup; + + for (; i < vz.list.nsources; i++) { + if (VIR_ALLOC(vz.list.sources[i].devices) < 0) + goto cleanup; + vz.list.sources[i].ndevice = 1; + if (VIR_STRDUP(vz.list.sources[i].devices->path, clusters[i]) < 0) + goto cleanup; + } + + if (!(ret = virStoragePoolSourceListFormat(&vz.list))) + goto cleanup; + + cleanup: + for (i = 0; i < vz.list.nsources; i++) + virStoragePoolSourceClear(&vz.list.sources[i]); + VIR_FREE(vz.list.sources); + VIR_FREE(buf); + virCommandFree(cmd); + return ret; + +} + +virStorageBackend virStorageBackendVz = { + .type = VIR_STORAGE_POOL_VZ, + + .startPool = virStorageBackendVzStart, + .checkPool = virStorageBackendVzCheck, + .stopPool = virStorageBackendVzStop, + .findPoolSources = virStorageBackendVzfindPoolSources, + .buildPool = virStorageBackendFileSystemBuild, + .deletePool = virStorageBackendFileSystemDelete, + .refreshPool = virStorageBackendFileSystemRefresh, + .buildVol = virStorageBackendFileSystemVolBuild, + .buildVolFrom = virStorageBackendFileSystemVolBuildFrom, + .createVol = virStorageBackendFileSystemVolCreate, + .refreshVol = virStorageBackendFileSystemVolRefresh, + .deleteVol = virStorageBackendFileSystemVolDelete, + .resizeVol = virStorageBackendFileSystemVolResize, + .uploadVol = virStorageBackendVolUploadLocal, + .downloadVol = virStorageBackendVolDownloadLocal, + .wipeVol = virStorageBackendVolWipeLocal, + +}; +#endif /* WITH_STORAGE_VZ */ diff --git a/src/storage/storage_backend_fs.h b/src/storage/storage_backend_fs.h index 347ea9b..f557639 100644 --- a/src/storage/storage_backend_fs.h +++ b/src/storage/storage_backend_fs.h @@ -30,6 +30,9 @@ extern virStorageBackend virStorageBackendFileSystem; extern virStorageBackend virStorageBackendNetFileSystem; # endif +#if WITH_STORAGE_VZ +extern virStorageBackend virStorageBackendVz; +#endif typedef enum { FILESYSTEM_PROBE_FOUND, diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 9999c2c..c691e05 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -1563,6 +1563,7 @@ storageVolLookupByPath(virConnectPtr conn, case VIR_STORAGE_POOL_ISCSI: case VIR_STORAGE_POOL_SCSI: case VIR_STORAGE_POOL_MPATH: + case VIR_STORAGE_POOL_VZ: stable_path = virStorageBackendStablePath(pool, cleanpath, false); @@ -3373,6 +3374,7 @@ virStorageTranslateDiskSourcePool(virConnectPtr conn, case VIR_STORAGE_POOL_DISK: case VIR_STORAGE_POOL_SCSI: case VIR_STORAGE_POOL_ZFS: + case VIR_STORAGE_POOL_VZ: if (!(def->src->path = virStorageVolGetPath(vol))) goto cleanup; diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c index f9299e2..2ac74fe 100644 --- a/tools/virsh-pool.c +++ b/tools/virsh-pool.c @@ -1165,6 +1165,8 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) case VIR_STORAGE_POOL_ZFS: flags |= VIR_CONNECT_LIST_STORAGE_POOLS_ZFS; break; + case VIR_STORAGE_POOL_VZ: + flags |= VIR_CONNECT_LIST_STORAGE_POOLS_VZ; case VIR_STORAGE_POOL_LAST: break; } diff --git a/tools/virsh.c b/tools/virsh.c index fe33839..e8428fb 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -666,6 +666,9 @@ virshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED) #ifdef WITH_STORAGE_ZFS vshPrint(ctl, " ZFS"); #endif +#ifdef WITH_STORAGE_VZ + vshPrint(ctl, " VZ"); +#endif vshPrint(ctl, "\n"); vshPrint(ctl, "%s", _(" Miscellaneous:")); -- 1.8.3.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list