From 23b12455796ec453ca35e94ab49e7629d7f9aced Mon Sep 17 00:00:00 2001 From: Prasanna Kumar Kalever Date: Sun, 5 Feb 2017 20:23:20 +0530 Subject: gluster-block: migrate build to libtoolz and create rpm Till now we had simple makefile for checking dependencies and building. Using libtoolz will give more control on dependency checks and flexibility. This patch also introduce rpm build feature. Compiling: $ ./autogen.sh $ ./configure $ make -j $ make install Building RPMS: $ make rpms Running: $ systemctl start gluster-blockd.service Using CLI: $ gluster-block help Signed-off-by: Prasanna Kumar Kalever --- .gitignore | 27 +- Makefile | 69 ---- Makefile.am | 40 ++ autogen.sh | 82 ++++ cli/Makefile.am | 11 + cli/gluster-block.c | 413 ++++++++++++++++++ common.c | 73 ---- common.h | 27 -- configure.ac | 75 ++++ daemon/Makefile.am | 12 + daemon/gluster-blockd.c | 120 ++++++ glfs-operations.c | 270 ------------ glfs-operations.h | 61 --- gluster-block.c | 426 ------------------- gluster-block.spec.in | 42 ++ gluster-blockd.c | 849 -------------------------------------- rpc/Makefile.am | 15 + rpc/block.h | 21 + rpc/block.x | 59 --- rpc/block_svc.c | 114 +---- rpc/block_svc_routines.c | 832 +++++++++++++++++++++++++++++++++++++ rpc/glfs-operations.c | 270 ++++++++++++ rpc/glfs-operations.h | 61 +++ rpc/rpcl/block.x | 59 +++ systemd/Makefile.am | 10 + systemd/gluster-blockd.service | 12 - systemd/gluster-blockd.service.in | 12 + utils.c | 175 -------- utils.h | 297 ------------- utils/Makefile.am | 11 + utils/common.c | 74 ++++ utils/common.h | 26 ++ utils/utils.c | 179 ++++++++ utils/utils.h | 299 ++++++++++++++ 34 files changed, 2691 insertions(+), 2432 deletions(-) delete mode 100644 Makefile create mode 100644 Makefile.am create mode 100755 autogen.sh create mode 100644 cli/Makefile.am create mode 100644 cli/gluster-block.c delete mode 100644 common.c delete mode 100644 common.h create mode 100644 configure.ac create mode 100644 daemon/Makefile.am create mode 100644 daemon/gluster-blockd.c delete mode 100644 glfs-operations.c delete mode 100644 glfs-operations.h delete mode 100644 gluster-block.c create mode 100644 gluster-block.spec.in delete mode 100644 gluster-blockd.c create mode 100644 rpc/Makefile.am delete mode 100644 rpc/block.x create mode 100644 rpc/block_svc_routines.c create mode 100644 rpc/glfs-operations.c create mode 100644 rpc/glfs-operations.h create mode 100644 rpc/rpcl/block.x create mode 100644 systemd/Makefile.am delete mode 100644 systemd/gluster-blockd.service create mode 100644 systemd/gluster-blockd.service.in delete mode 100644 utils.c delete mode 100644 utils.h create mode 100644 utils/Makefile.am create mode 100644 utils/common.c create mode 100644 utils/common.h create mode 100644 utils/utils.c create mode 100644 utils/utils.h diff --git a/.gitignore b/.gitignore index 93d006a..c4f04a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,29 @@ -gluster-block -gluster-blockd +ar-lib +aclocal.m4 +autom4te.cache +build +config.* +configure +depcomp +install-sh +ltmain.sh +Makefile +Makefile.in +missing +.deps +compile +libtool +m4/ +*.libs *.o +*.lo +*.la +stamp-h1 +.deps +*.spec +*.service +*.tar.gz + cscope.* tags TAGS diff --git a/Makefile b/Makefile deleted file mode 100644 index cb9e5a2..0000000 --- a/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -######################################################################## -# # -# Copyright (c) 2016 Red Hat, Inc. # -# This file is part of gluster-block. # -# # -# This file is licensed to you under your choice of the GNU Lesser # -# General Public License, version 3 or any later version (LGPLv3 or # -# later), or the GNU General Public License, version 2 (GPLv2), in all# -# cases as published by the Free Software Foundation. # -# # -######################################################################## - - -CC = gcc - -COMMON = utils.o common.o rpc/block_xdr.o - -CLIENT = gluster-block -CDEP = rpc/block_clnt.o gluster-block.o - -SERVER = gluster-blockd -SDEP = glfs-operations.o rpc/block_svc.o rpc/block_clnt.o gluster-blockd.o - -CFLAGS = -g -ggdb -Wall -lpthread -LIBS := $(shell pkg-config --libs uuid glusterfs-api) - -DEPS_LIST = gcc tcmu-runner targetcli - -PREFIX ?= /usr/local/sbin -MKDIR_P = mkdir -p -INSTALL = /usr/bin/install -c -INSTALLDATA = /usr/bin/install -c -m 644 -SYSTEMD_DIR = /usr/lib/systemd/system -LOGDIR = /var/log/gluster-block - - -all: $(SERVER) $(CLIENT) - -$(CLIENT): $(CDEP) $(COMMON) - @$(MKDIR_P) $(LOGDIR)$@ - $(CC) $(CFLAGS) $(LIBS) $^ -o $@ - -$(SERVER): $(SDEP) $(COMMON) - $(CC) $(CFLAGS) $(LIBS) $^ -o $@ - -glfs-operations.o: glfs-operations.c glfs-operations.h - $(foreach x, $(DEPS_LIST),\ - $(if $(shell which $x), \ - $(info -- found $x),\ - $(else, \ - $(error "No $x in PATH, install '$x' and continue ...")))) - $(CC) $(CFLAGS) -c $< -o $@ - -$(CLIENT).o: $(CLIENT).c - $(CC) $(CFLAGS) -c $< -o $@ - -install: $(SERVER) $(CLIENT) - $(INSTALL) $^ $(PREFIX)/ - @if [ -d $(SYSTEMD_DIR) ]; then \ - $(MKDIR_P) $(SYSTEMD_DIR); \ - $(INSTALLDATA) systemd/$(SERVER).service $(SYSTEMD_DIR)/; \ - fi - -.PHONY: clean distclean -clean distclean: - $(RM) ./*.o ./rpc/*.o $(CLIENT) $(SERVER) - -uninstall: - $(RM) $(PREFIX)/$(CLIENT) $(PREFIX)/$(SERVER) $(SYSTEMD_DIR)/$(SERVER).service diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..a07333b --- /dev/null +++ b/Makefile.am @@ -0,0 +1,40 @@ +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = rpc utils cli daemon systemd + +DISTCLEANFILES = Makefile.in gluster-block.spec autom4te.cache + +CLEANFILES = *~ gluster-block.spec + +EXTRA_DIST = autogen.sh README.md + +rpms: prep + QA_RPATHS=17 rpmbuild --define '_topdir $(abs_top_builddir)/build/rpmbuild' \ + -ba $(abs_top_builddir)/build/rpmbuild/SPECS/gluster-block.spec + +prep: dist + mkdir -p build/rpmbuild && cd build/rpmbuild \ + && mkdir BUILD SPECS RPMS SRPM SOURCES && cd ../.. + rm -rf rpmbuild/SOURCES/* + cp *.tar.gz build/rpmbuild/SOURCES + cp gluster-block.spec build/rpmbuild/SPECS + +uninstall-local: + cd $(DESTDIR)$(bindir) && rm -f gluster-block gluster-blockd + +clean-local: + rm -rf build rpmbuild *.rpm + +gitclean: clean distclean + find . -path gnulib -prune -name Makefile.in -exec rm -f {} \; + find . -path gnulib -prune -name Makefile -exec rm -f {} \; + rm -f aclocal.m4 compile config.* configure depcomp install-sh libtool \ + ltmain.sh missing stamp-h1 + rm -rf autom4te.cache ar-lib *.tar.gz m4 + +dist-hook: gen-ChangeLog + +.PHONY: gen-ChangeLog + +gen-ChangeLog: + (cd $(srcdir) && git diff && echo ===== git log ==== && git log) > $(distdir)/ChangeLog diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..4bc5af7 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +set -e + +chmod +x $0 + +case "$(uname)" in + Darwin) + LIBTOOLIZE=${LIBTOOLIZE:-glibtoolize} + ;; + *) + LIBTOOLIZE=${LIBTOOLIZE:-libtoolize} + ;; +esac +AUTORECONF=${AUTORECONF:-autoreconf} +ACLOCAL=${ACLOCAL:-aclocal} +AUTOCONF=${AUTOCONF:-autoconf} +AUTOHEADER=${AUTOHEADER:-autoheader} +AUTOMAKE=${AUTOMAKE:-automake} + +# Check we have all tools installed +check_command() { + command -v "${1}" > /dev/null 2>&1 || { + >&2 echo "autogen.sh: could not find \`$1'. \`$1' is required to run autogen.sh." + exit 1 + } +} +check_command "$LIBTOOLIZE" +check_command "$AUTORECONF" +check_command "$ACLOCAL" +check_command "$AUTOCONF" +check_command "$AUTOHEADER" +check_command "$AUTOMAKE" + +# Absence of pkg-config or misconfiguration can make some odd error +# messages, we check if it is installed correctly. See: +# https://blogs.oracle.com/mandy/entry/autoconf_weirdness +# +# We cannot just check for pkg-config command, we need to check for +# PKG_* macros. The pkg-config command can be defined in ./configure, +# we cannot tell anything when not present. +check_pkg_config() { + grep -q '^AC_DEFUN.*PKG_CHECK_MODULES' aclocal.m4 || { + cat <&2 +autogen.sh: could not find PKG_CHECK_MODULES macro. + + Either pkg-config is not installed on your system or + \`pkg.m4' is missing or not found by aclocal. + + If \`pkg.m4' is installed at an unusual location, re-run + \`autogen.sh' by setting \`ACLOCAL_FLAGS': + + ACLOCAL_FLAGS="-I /share/aclocal" ./autogen.sh + +EOF + exit 1 + } +} + + +echo "autogen.sh: start libtoolize to get ltmain.sh" +${LIBTOOLIZE} --copy --force +echo "autogen.sh: reconfigure with autoreconf" +${AUTORECONF} -vif -I m4 || { + echo "autogen.sh: autoreconf has failed ($?), let's do it manually" + for dir in $PWD *; do + [ -d "$dir" ] || continue + [ -f "$dir"/configure.ac ] || [ -f "$dir"/configure.in ] || continue + echo "autogen.sh: configure `basename $dir`" + (cd "$dir" && ${ACLOCAL} -I m4 ${ACLOCAL_FLAGS}) + (cd "$dir" && check_pkg_config) + (cd "$dir" && ${LIBTOOLIZE} --automake --copy --force) + (cd "$dir" && ${ACLOCAL} -I m4 ${ACLOCAL_FLAGS}) + (cd "$dir" && ${AUTOCONF} --force) + (cd "$dir" && ${AUTOHEADER}) + (cd "$dir" && ${AUTOMAKE} --add-missing --copy --force-missing) + done +} + +echo "autogen.sh: for the next step, run ./configure" + +exit 0 diff --git a/cli/Makefile.am b/cli/Makefile.am new file mode 100644 index 0000000..4d908a9 --- /dev/null +++ b/cli/Makefile.am @@ -0,0 +1,11 @@ +sbin_PROGRAMS = gluster-block + +gluster_block_SOURCES = gluster-block.c + +gluster_block_LDADD = $(top_srcdir)/rpc/libgbxdr.la $(top_srcdir)/utils/libgb.la + +gluster_block_CFLAGS = -I$(top_srcdir)/utils/ -I$(top_srcdir)/rpc + +DISTCLEANFILES = Makefile.in + +CLEANFILES = *~ diff --git a/cli/gluster-block.c b/cli/gluster-block.c new file mode 100644 index 0000000..0605ef7 --- /dev/null +++ b/cli/gluster-block.c @@ -0,0 +1,413 @@ +/* + Copyright (c) 2016 Red Hat, Inc. + This file is part of gluster-block. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +# include "common.h" +# include "block.h" + + + +typedef enum clioperations { + CREATE_CLI = 1, + LIST_CLI = 2, + INFO_CLI = 3, + DELETE_CLI = 4 +} clioperations; + + +static int +glusterBlockCliRPC_1(void *cobj, operations opt, char **out) +{ + CLIENT *clnt = NULL; + int ret = -1; + int sockfd; + struct sockaddr_un saun; + blockResponse *reply; + + + if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + LOG("cli", GB_LOG_ERROR, "socket creation failed (%s)", strerror (errno)); + goto out; + } + + saun.sun_family = AF_UNIX; + strcpy(saun.sun_path, ADDRESS); + + if (connect(sockfd, (struct sockaddr *) &saun, + sizeof(struct sockaddr_un)) < 0) { + LOG("cli", GB_LOG_ERROR, "connect failed (%s)", strerror (errno)); + goto out; + } + + clnt = clntunix_create ((struct sockaddr_un *) &saun, + GLUSTER_BLOCK_CLI, GLUSTER_BLOCK_CLI_VERS, + &sockfd, 0, 0); + if (!clnt) { + LOG("cli", GB_LOG_ERROR, "%s, unix addr %s", + clnt_spcreateerror("client create failed"), ADDRESS); + goto out; + } + + switch(opt) { + case CREATE_CLI: + reply = block_create_cli_1((blockCreateCli *)cobj, clnt); + if (!reply) { + LOG("cli", GB_LOG_ERROR, "%s", clnt_sperror(clnt, "block create failed")); + goto out; + } + break; + case DELETE_CLI: + reply = block_delete_cli_1((blockDeleteCli *)cobj, clnt); + if (!reply) { + LOG("cli", GB_LOG_ERROR, "%s", clnt_sperror(clnt, "block delete failed")); + goto out; + } + break; + case INFO_CLI: + reply = block_info_cli_1((blockInfoCli *)cobj, clnt); + if (!reply) { + LOG("cli", GB_LOG_ERROR, "%s", clnt_sperror(clnt, "block info failed")); + goto out; + } + break; + case LIST_CLI: + reply = block_list_cli_1((blockListCli *)cobj, clnt); + if (!reply) { + LOG("cli", GB_LOG_ERROR, "%s", clnt_sperror(clnt, "block list failed")); + goto out; + } + break; + } + + if (GB_STRDUP(*out, reply->out) < 0) + goto out; + ret = reply->exit; + + out: + if (clnt) { + if (!reply || !clnt_freeres(clnt, (xdrproc_t)xdr_blockResponse, (char *)reply)) + LOG("cli", GB_LOG_ERROR, "%s", clnt_sperror(clnt, "clnt_freeres failed")); + + clnt_destroy (clnt); + } + + return ret; +} + + +static void +glusterBlockHelp(void) +{ + MSG("%s", + "gluster-block (Version 0.1) \n" + " create Create the gluster block\n" + " volserver [gluster-node] node addr from gluster pool(default: localhost)\n" + " size block storage size in KiB|MiB|GiB|TiB..\n" + " mpath multi path requirement for high availablity\n" + " servers block servers, clubbed with any option\n" + "\n" + " list List available gluster blocks\n" + "\n" + " info Details about gluster block\n" + "\n" + " modify Modify the metadata\n" + "\n" + " delete Delete the gluster block\n" + "\n" + " volume gluster volume name\n" + ); +} + + +static int +glusterBlockCreate(int argcount, char **options) +{ + size_t opt; + size_t optind = 2; + int ret = 0; + char *out = NULL; + bool volserver = FALSE; + static blockCreateCli cobj = {0, }; + + + if(argcount <= optind) { + MSG("%s\n", "Insufficient options for create"); + return -1; + } + + /* name of block */ + strcpy(cobj.block_name, options[optind++]); + + while (1) { + if(argcount <= optind) { + break; + } + + opt = glusterBlockCLICreateOptEnumParse(options[optind++]); + if (opt == GB_CLI_CREATE_OPT_MAX) { + MSG("unrecognized option '%s'\n", options[optind-1]); + return -1; + } else if (opt && !options[optind]) { + MSG("%s: require argument\n", options[optind-1]); + return -1; + } + + switch (opt) { + case GB_CLI_CREATE_VOLUME: + strcpy(cobj.volume, options[optind++]); + ret++; + break; + + case GB_CLI_CREATE_VOLSERVER: + strcpy(cobj.volfileserver, options[optind++]); + volserver = TRUE; + break; + + case GB_CLI_CREATE_MULTIPATH: + sscanf(options[optind++], "%u", &cobj.mpath); + ret++; + break; + + case GB_CLI_CREATE_SIZE: + cobj.size = glusterBlockCreateParseSize(options[optind++]); + if (cobj.size < 0) { + LOG("cli", GB_LOG_ERROR, "%s", "failed while parsing size"); + ret = -1; + goto out; + } + ret++; + break; + + case GB_CLI_CREATE_BACKEND_SERVESRS: + if (GB_STRDUP(cobj.block_hosts, options[optind++]) < 0) { + LOG("cli", GB_LOG_ERROR, "%s", "failed while parsing size"); + ret = -1; + goto out; + } + ret++; + break; + + default: + MSG("unrecognized option '%s'\n", options[optind-1]); + MSG("%s", "Hint: gluster-block help\n"); + goto out; + } + } + + /* check all options required by create command are specified */ + if(ret < 4) { + MSG("%s\n", "Insufficient options for create"); + ret = -1; + goto out; + } + + if(!volserver) { + strcpy(cobj.volfileserver, "localhost"); + } + + ret = glusterBlockCliRPC_1(&cobj, CREATE_CLI, &out); + + if(out) + MSG("%s", out); + + out: + GB_FREE(cobj.block_hosts); + GB_FREE(out); + + return ret; +} + + +static int +glusterBlockList(int argcount, char **options) +{ + size_t opt; + size_t optind = 2; + static blockListCli cobj; + char *out = NULL; + int ret = -1; + + + if(argcount <= optind) { + MSG("%s\n", "Insufficient options for list"); + return -1; + } + + opt = glusterBlockCLICommonOptEnumParse(options[optind++]); + if (opt == GB_CLI_COMMON_OPT_MAX) { + MSG("unrecognized option '%s'\n", options[optind-1]); + MSG("%s\n", "List needs 'volume' option"); + return -1; + } else if (!options[optind]) { + MSG("%s: require argument\n", options[optind-1]); + return -1; + } + + if ((opt == GB_CLI_COMMON_VOLUME)) { + strcpy(cobj.volume, options[optind]); + + ret = glusterBlockCliRPC_1(&cobj, LIST_CLI, &out); + + if(out) + MSG("%s", out); + + GB_FREE(out); + } + + return ret; +} + + +static int +glusterBlockDelete(int argcount, char **options) +{ + size_t opt; + size_t optind = 2; + static blockDeleteCli cobj; + char *out = NULL; + int ret = -1; + + + if(argcount <= optind) { + MSG("%s\n", "Insufficient options for delete"); + return -1; + } + + /* name of block */ + strcpy(cobj.block_name, options[optind++]); + + opt = glusterBlockCLICommonOptEnumParse(options[optind++]); + if (opt == GB_CLI_COMMON_OPT_MAX) { + MSG("unrecognized option '%s'\n", options[optind-1]); + MSG("%s\n", "Delete needs 'volume' option"); + return -1; + } else if (!options[optind]) { + MSG("%s: require argument\n", options[optind-1]); + return -1; + } + + if ((opt == GB_CLI_COMMON_VOLUME)) { + strcpy(cobj.volume, options[optind]); + ret = glusterBlockCliRPC_1(&cobj, DELETE_CLI, &out); + + if(out) + MSG("%s", out); + + GB_FREE(out); + } + + return ret; +} + + +static int +glusterBlockInfo(int argcount, char **options) +{ + size_t opt; + size_t optind = 2; + static blockInfoCli cobj; + char *out = NULL; + int ret = -1; + + + if(argcount <= optind) { + MSG("%s\n", "Insufficient options for info"); + return -1; + } + + /* name of block */ + strcpy(cobj.block_name, options[optind++]); + + opt = glusterBlockCLICommonOptEnumParse(options[optind++]); + if (opt == GB_CLI_COMMON_OPT_MAX) { + MSG("unrecognized option '%s'\n", options[optind-1]); + MSG("%s\n", "Info needs 'volume' option"); + return -1; + } else if (!options[optind]) { + MSG("%s: require argument\n", options[optind-1]); + return -1; + } + + if ((opt == GB_CLI_COMMON_VOLUME)) { + strcpy(cobj.volume, options[optind]); + ret = glusterBlockCliRPC_1(&cobj, INFO_CLI, &out); + + if(out) + MSG("%s", out); + + GB_FREE(out); + } + + return ret; +} + + +static int +glusterBlockParseArgs(int count, char **options) +{ + int ret = 0; + size_t opt = 0; + + + opt = glusterBlockCLIOptEnumParse(options[1]); + if (!opt || opt >= GB_CLI_OPT_MAX) { + MSG("unknow option: %s\n", options[1]); + return -1; + } + + while (1) { + switch (opt) { + case GB_CLI_CREATE: + ret = glusterBlockCreate(count, options); + if (ret && ret != EEXIST) { + LOG("cli", GB_LOG_ERROR, "%s", FAILED_CREATE); + } + goto out; + + case GB_CLI_LIST: + ret = glusterBlockList(count, options); + if (ret) { + LOG("cli", GB_LOG_ERROR, "%s", FAILED_LIST); + } + goto out; + + case GB_CLI_INFO: + ret = glusterBlockInfo(count, options); + if (ret) { + LOG("cli", GB_LOG_ERROR, "%s", FAILED_INFO); + } + goto out; + + case GB_CLI_DELETE: + ret = glusterBlockDelete(count, options); + if (ret) { + LOG("cli", GB_LOG_ERROR, "%s", FAILED_DELETE); + } + goto out; + + case GB_CLI_HELP: + glusterBlockHelp(); + goto out; + } + } + + out: + return ret; +} + + +int +main(int argc, char *argv[]) +{ + if (argc <= 1) + glusterBlockHelp(); + + return glusterBlockParseArgs(argc, argv); +} diff --git a/common.c b/common.c deleted file mode 100644 index 2efc127..0000000 --- a/common.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (c) 2016 Red Hat, Inc. - This file is part of gluster-block. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - - -# include "common.h" - - - -ssize_t -glusterBlockCreateParseSize(char *value) -{ - char *postfix; - char *tmp; - ssize_t sizef; - - if (!value) - return -1; - - sizef = strtod(value, &postfix); - if (sizef < 0) { - ERROR("%s", "size cannot be negative number\n"); - return -1; - } - - tmp = postfix; - if (*postfix == ' ') { - tmp = tmp + 1; - } - - switch (*tmp) { - case 'Y': - sizef *= 1024; - /* fall through */ - case 'Z': - sizef *= 1024; - /* fall through */ - case 'E': - sizef *= 1024; - /* fall through */ - case 'P': - sizef *= 1024; - /* fall through */ - case 'T': - sizef *= 1024; - /* fall through */ - case 'G': - sizef *= 1024; - /* fall through */ - case 'M': - sizef *= 1024; - /* fall through */ - case 'K': - case 'k': - sizef *= 1024; - /* fall through */ - case 'b': - case '\0': - return sizef; - break; - default: - /*TODO: Log this instead of printing - ERROR("%s", "You may use k/K, M, G or T suffixes for " - "kilobytes, megabytes, gigabytes and terabytes."); */ - return -1; - } -} diff --git a/common.h b/common.h deleted file mode 100644 index c230df8..0000000 --- a/common.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - Copyright (c) 2016 Red Hat, Inc. - This file is part of gluster-block. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - - -# ifndef _COMMON_H -# define _COMMON_H 1 - -# include "utils.h" - -# define DAEMON_LOG_FILE "/var/log/gluster-block/gluster-blockd.log" -# define CLI_LOG_FILE "/var/log/gluster-block/gluster-block-cli.log" - -# define GFAPI_LOG_FILE "/var/log/gluster-block/gluster-block-gfapi.log" -# define GFAPI_LOG_LEVEL 7 - - - -ssize_t glusterBlockCreateParseSize(char *value); - -# endif /* _COMMON_H */ diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..e18b3e2 --- /dev/null +++ b/configure.ac @@ -0,0 +1,75 @@ +dnl Copyright (c) 2016 Red Hat, Inc. +dnl This file is part of gluster-block. +dnl +dnl This file is licensed to you under your choice of the GNU Lesser +dnl General Public License, version 3 or any later version (LGPLv3 or +dnl later), or the GNU General Public License, version 2 (GPLv2), in all +dnl cases as published by the Free Software Foundation. + + +AC_PREREQ([2.69]) +AC_INIT([glusterfs-block], + m4_esyscmd(echo -n `git describe --always --tags`), + [pkalever@redhat.com],, + [https://github.com/pkalever/gluster-block.git]) + +AC_SUBST([PACKAGE_RELEASE], 1) + +AC_ARG_WITH(systemddir, + [ --with-systemddir=DIR systemd service files in DIR @<:@PREFIX/lib/systemd/system@:>@], + [systemddir=$withval], + [systemddir='${prefix}/lib/systemd/system']) +AC_SUBST(systemddir) +AM_CONDITIONAL([USE_SYSTEMD], test [ -d '/usr/lib/systemd/system' ]) + +AM_INIT_AUTOMAKE([-Wall -Werror foreign nostdinc silent-rules]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_FILES([gluster-block.spec + Makefile + rpc/Makefile + cli/Makefile + daemon/Makefile + utils/Makefile + systemd/Makefile + systemd/gluster-blockd.service]) +AC_CONFIG_MACRO_DIR([m4]) +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) + +AM_MAINTAINER_MODE + +# Configure libtool +LT_INIT + +# Checks for programs. +AC_PROG_CC + +# Checks for header files. +AC_CHECK_HEADERS([memory.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h]) + +# Checks for libraries. +AC_CHECK_LIB([gfapi], [glfs_init]) +PKG_CHECK_MODULES([GLFS], [glusterfs-api >= 3]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_CHECK_HEADER_STDBOOL +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T + +# Checks for library functions. +AC_FUNC_STRTOD +AC_CHECK_FUNCS([bzero gethostbyname memset socket strchr strdup strerror]) +AC_OUTPUT + +cat < + This file is part of gluster-block. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +# include +# include +# include + +# include "block.h" + + + +void * +glusterBlockCliThreadProc (void *vargp) +{ + register SVCXPRT *transp; + struct sockaddr_un saun; + int sockfd, len; + + + if ((sockfd = socket(AF_UNIX, SOCK_STREAM, IPPROTO_IP)) < 0) { + perror("server: socket"); + exit(1); + } + + saun.sun_family = AF_UNIX; + strcpy(saun.sun_path, ADDRESS); + + unlink(ADDRESS); + len = sizeof(saun.sun_family) + strlen(saun.sun_path); + + if (bind(sockfd, (struct sockaddr *) &saun, len) < 0) { + perror("server: bind"); + exit(1); + } + + transp = svcunix_create(sockfd, 0, 0, ADDRESS); + if (transp == NULL) { + fprintf (stderr, "%s", "cannot create tcp service"); + exit(1); + } + + if (!svc_register(transp, GLUSTER_BLOCK_CLI, GLUSTER_BLOCK_CLI_VERS, gluster_block_cli_1, IPPROTO_IP)) { + fprintf (stderr, "%s", "unable to register (GLUSTER_BLOCK_CLI, GLUSTER_BLOCK_CLI_VERS, unix|local)."); + exit(1); + } + + svc_run (); + + return NULL; +} + + +void * +glusterBlockServerThreadProc(void *vargp) +{ + register SVCXPRT *transp; + struct sockaddr_in sain; + int sockfd; + + + if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + perror("server: socket"); + exit(1); + } + + sain.sin_family = AF_INET; + sain.sin_addr.s_addr = INADDR_ANY; + sain.sin_port = htons(24006); + + if (bind(sockfd, (struct sockaddr *) &sain, sizeof (sain)) < 0) { + perror("server: bind"); + exit(1); + } + + transp = svctcp_create(sockfd, 0, 0); + if (transp == NULL) { + fprintf (stderr, "%s", "cannot create tcp service"); + exit(1); + } + + if (!svc_register(transp, GLUSTER_BLOCK, GLUSTER_BLOCK_VERS, gluster_block_1, IPPROTO_TCP)) { + fprintf (stderr, "%s", "unable to register (GLUSTER_BLOCK, GLUSTER_BLOCK_VERS, tcp)."); + exit(1); + } + + svc_run (); + + return NULL; +} + + +int +main (int argc, char **argv) +{ + pthread_t cli_thread; + pthread_t server_thread; + + + pmap_unset (GLUSTER_BLOCK_CLI, GLUSTER_BLOCK_CLI_VERS); + pmap_unset (GLUSTER_BLOCK, GLUSTER_BLOCK_VERS); + + pthread_create(&cli_thread, NULL, glusterBlockCliThreadProc , NULL); + pthread_create(&server_thread, NULL, glusterBlockServerThreadProc , NULL); + + pthread_join(cli_thread, NULL); + pthread_join(server_thread, NULL); + + + fprintf (stderr, "%s", "svc_run returned"); + exit (0); + /* NOTREACHED */ +} diff --git a/glfs-operations.c b/glfs-operations.c deleted file mode 100644 index 9712f64..0000000 --- a/glfs-operations.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - Copyright (c) 2016 Red Hat, Inc. - This file is part of gluster-block. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - - -# include "common.h" -# include "glfs-operations.h" - -# define METADIR "/block-meta" -# define TXLOCKFILE "meta.lock" - - - -struct glfs * -glusterBlockVolumeInit(char *volume, char *volfileserver) -{ - struct glfs *glfs; - int ret; - - - glfs = glfs_new(volume); - if (!glfs) { - LOG("gfapi", GB_LOG_ERROR, "glfs_new(%s) from %s failed[%s]", volume, - volfileserver, strerror(errno)); - return NULL; - } - - ret = glfs_set_volfile_server(glfs, "tcp", volfileserver, 24007); - if (ret) { - LOG("gfapi", GB_LOG_ERROR, "glfs_set_volfile_server(%s) of %s " - "failed[%s]", volfileserver, volume, strerror(errno)); - goto out; - } - - ret = glfs_set_logging(glfs, GFAPI_LOG_FILE, GFAPI_LOG_LEVEL); - if (ret) { - LOG("gfapi", GB_LOG_ERROR, "glfs_set_logging(%s, %d) on %s failed[%s]", - GFAPI_LOG_FILE, GFAPI_LOG_LEVEL, volume, strerror(errno)); - goto out; - } - - ret = glfs_init(glfs); - if (ret) { - LOG("gfapi", GB_LOG_ERROR, "glfs_init() on %s failed[%s]", volume, - strerror(errno) ); - goto out; - } - - return glfs; - - out: - glfs_fini(glfs); - - return NULL; -} - - -int -glusterBlockCreateEntry(blockCreateCli *blk, char *gbid) -{ - struct glfs *glfs; - struct glfs_fd *tgfd; - int ret = -1; - - - glfs = glusterBlockVolumeInit(blk->volume, blk->volfileserver); - if (!glfs) { - LOG("gfapi", GB_LOG_ERROR, "glusterBlockVolumeInit(%s): failed", - blk->volume); - goto out; - } - - tgfd = glfs_creat(glfs, gbid, - O_WRONLY | O_CREAT | O_EXCL, - S_IRUSR | S_IWUSR); - if (!tgfd) { - LOG("gfapi", GB_LOG_ERROR, "glfs_creat(%s) on volume %s failed[%s]", - gbid, blk->volume, strerror(errno)); - } else { - ret = glfs_ftruncate(tgfd, blk->size); - if (ret) { - LOG("gfapi", GB_LOG_ERROR, "glfs_ftruncate(%s): on volume %s " - "of size %zu failed[%s]", gbid, blk->volume, blk->size, - strerror(errno)); - goto out; - } - - if (glfs_close(tgfd) != 0) { - LOG("gfapi", GB_LOG_ERROR, "glfs_close(%s): on volume %s failed[%s]", - gbid, blk->volume, strerror(errno)); - goto out; - } - } - - out: - glfs_fini(glfs); - return ret; -} - - -int -glusterBlockDeleteEntry(char *volume, char *gbid) -{ - struct glfs *glfs; - int ret = -1; - - - glfs = glusterBlockVolumeInit(volume, "localhost"); - if (!glfs) { - LOG("gfapi", GB_LOG_ERROR, "glusterBlockVolumeInit(%s): failed", - volume); - goto out; - } - - ret = glfs_unlink(glfs, gbid); - if (ret) { - LOG("gfapi", GB_LOG_ERROR, "glfs_unlink(%s) on volume %s failed[%s]", - gbid, volume, strerror(errno)); - goto out; - } - - out: - glfs_fini(glfs); - return ret; -} - - -struct glfs_fd * -glusterBlockCreateMetaLockFile(struct glfs *glfs, char *volume) -{ - struct glfs_fd *lkfd; - int ret; - - - ret = glfs_mkdir (glfs, METADIR, 0); - if (ret && errno != EEXIST) { - LOG("gfapi", GB_LOG_ERROR, "glfs_mkdir(%s) on volume %s failed[%s]", - METADIR, volume, strerror(errno)); - goto out; - } - - ret = glfs_chdir (glfs, METADIR); - if (ret) { - LOG("gfapi", GB_LOG_ERROR, "glfs_chdir(%s) on volume %s failed[%s]", - METADIR, volume, strerror(errno)); - goto out; - } - - lkfd = glfs_creat(glfs, TXLOCKFILE, O_RDWR, S_IRUSR | S_IWUSR); - if (!lkfd) { - LOG("gfapi", GB_LOG_ERROR, "glfs_creat(%s) on volume %s failed[%s]", - TXLOCKFILE, volume, strerror(errno)); - goto out; - } - - return lkfd; - - out: - return NULL; -} - - -void -blockFreeMetaInfo(MetaInfo *info) -{ - int i; - - - if (!info) - return; - - for (i = 0; i < info->nhosts; i++) - GB_FREE(info->list[i]); - - GB_FREE(info->list); - GB_FREE(info); -} - - -static void -blockStuffMetaInfo(MetaInfo *info, char *line) -{ - char* tmp = strdup(line); - char* opt = strtok(tmp,":"); - int Flag = 0; - size_t i; - - - switch (blockMetaKeyEnumParse(opt)) { - case GB_META_VOLUME: - strcpy(info->volume, strchr(line, ' ')+1); - break; - case GB_META_GBID: - strcpy(info->gbid, strchr(line, ' ')+1); - break; - case GB_META_SIZE: - sscanf(strchr(line, ' ')+1, "%zu", &info->size); - break; - case GB_META_HA: - sscanf(strchr(line, ' ')+1, "%zu", &info->mpath); - break; - case GB_META_ENTRYCREATE: - strcpy(info->entry, strchr(line, ' ')+1); - break; - - default: - if(!info->list) { - if(GB_ALLOC(info->list) < 0) - return; - if(GB_ALLOC(info->list[0]) < 0) - return; - strcpy(info->list[0]->addr, opt); - strcpy(info->list[0]->status, strchr(line, ' ')+1); - info->nhosts = 1; - } else { - for (i = 0; i < info->nhosts; i++) { - if(!strcmp(info->list[i]->addr, opt)) { - strcpy(info->list[i]->status, strchr(line, ' ')+1); - Flag = 1; - break; - } - } - if (!Flag) { - if(GB_ALLOC(info->list[info->nhosts]) < 0) - return; - strcpy(info->list[info->nhosts]->addr, opt); - strcpy(info->list[info->nhosts]->status, strchr(line, ' ')+1); - info->nhosts++; - } - } - break; - } - - GB_FREE(tmp); -} - - -int -blockGetMetaInfo(struct glfs* glfs, char* metafile, MetaInfo *info) -{ - size_t count = 0; - struct glfs_fd *tgmfd; - char line[1024]; - char *tmp; - - - tgmfd = glfs_open(glfs, metafile, O_RDONLY); - if (!tgmfd) { - LOG("gfapi", GB_LOG_ERROR, "glfs_open(%s) on volume %s failed[%s]", - metafile, info->volume, strerror(errno)); - return -1; - } - - while (glfs_read (tgmfd, line, sizeof(line), 0) > 0) { - tmp = strtok(line,"\n"); - count += strlen(tmp) + 1; - blockStuffMetaInfo(info, tmp); - glfs_lseek(tgmfd, count, SEEK_SET); - } - - glfs_close(tgmfd); - - return 0; -} diff --git a/glfs-operations.h b/glfs-operations.h deleted file mode 100644 index 214a71c..0000000 --- a/glfs-operations.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (c) 2016 Red Hat, Inc. - This file is part of gluster-block. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - - -# ifndef _GLFS_OPERATIONS_H -# define _GLFS_OPERATIONS_H 1 - -# include -# include -# include -# include - -# include - -# include "rpc/block.h" - - - -typedef struct NodeInfo { - char addr[255]; - char status[16]; -} NodeInfo; - -typedef struct MetaInfo { - char volume[255]; - char gbid[38]; - size_t size; - size_t mpath; - char entry[16]; - - size_t nhosts; - NodeInfo **list; -} MetaInfo; - - -struct glfs * -glusterBlockVolumeInit(char *volume, char *volfileserver); - -int -glusterBlockCreateEntry(blockCreateCli *blk, char *gbid); - -int -glusterBlockDeleteEntry(char *volume, char *gbid); - -struct glfs_fd * -glusterBlockCreateMetaLockFile(struct glfs *glfs, char *volume); - -int -blockGetMetaInfo(struct glfs *glfs, char *metafile, MetaInfo *info); - -void -blockFreeMetaInfo(MetaInfo *info); - -#endif /* _GLFS_OPERATIONS_H */ diff --git a/gluster-block.c b/gluster-block.c deleted file mode 100644 index b9d21c2..0000000 --- a/gluster-block.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - Copyright (c) 2016 Red Hat, Inc. - This file is part of gluster-block. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - - -# define _GNU_SOURCE /* See feature_test_macros(7) */ - -# include -# include - -# include "common.h" -# include "rpc/block.h" - - -# define LIST "list" -# define CREATE "create" -# define DELETE "delete" -# define INFO "info" -# define MODIFY "modify" -# define BLOCKHOST "block-host" -# define VOLUME "volume" -# define HELP "help" - - - -typedef enum operations { - CREATE_CLI = 1, - LIST_CLI = 2, - INFO_CLI = 3, - DELETE_CLI = 4 -} operations; - - -static int -glusterBlockCliRPC_1(void *cobj, operations opt, char **out) -{ - CLIENT *clnt = NULL; - int ret = -1; - int sockfd; - struct sockaddr_un saun; - blockResponse *reply; - - - if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - LOG("cli", GB_LOG_ERROR, "socket creation failed (%s)", strerror (errno)); - goto out; - } - - saun.sun_family = AF_UNIX; - strcpy(saun.sun_path, ADDRESS); - - if (connect(sockfd, (struct sockaddr *) &saun, - sizeof(struct sockaddr_un)) < 0) { - LOG("cli", GB_LOG_ERROR, "connect failed (%s)", strerror (errno)); - goto out; - } - - clnt = clntunix_create ((struct sockaddr_un *) &saun, - GLUSTER_BLOCK_CLI, GLUSTER_BLOCK_CLI_VERS, - &sockfd, 0, 0); - if (!clnt) { - LOG("cli", GB_LOG_ERROR, "%s, unix addr %s", - clnt_spcreateerror("client create failed"), ADDRESS); - goto out; - } - - switch(opt) { - case CREATE_CLI: - reply = block_create_cli_1((blockCreateCli *)cobj, clnt); - if (!reply) { - LOG("cli", GB_LOG_ERROR, "%s", clnt_sperror(clnt, "block create failed")); - goto out; - } - break; - case DELETE_CLI: - reply = block_delete_cli_1((blockDeleteCli *)cobj, clnt); - if (!reply) { - LOG("cli", GB_LOG_ERROR, "%s", clnt_sperror(clnt, "block delete failed")); - goto out; - } - break; - case INFO_CLI: - reply = block_info_cli_1((blockInfoCli *)cobj, clnt); - if (!reply) { - LOG("cli", GB_LOG_ERROR, "%s", clnt_sperror(clnt, "block info failed")); - goto out; - } - break; - case LIST_CLI: - reply = block_list_cli_1((blockListCli *)cobj, clnt); - if (!reply) { - LOG("cli", GB_LOG_ERROR, "%s", clnt_sperror(clnt, "block list failed")); - goto out; - } - break; - } - - if (GB_STRDUP(*out, reply->out) < 0) - goto out; - ret = reply->exit; - - out: - if (clnt) { - if (!reply || !clnt_freeres(clnt, (xdrproc_t)xdr_blockResponse, (char *)reply)) - LOG("cli", GB_LOG_ERROR, "%s", clnt_sperror(clnt, "clnt_freeres failed")); - - clnt_destroy (clnt); - } - - return ret; -} - - -static void -glusterBlockHelp(void) -{ - MSG("%s", - "gluster-block (Version 0.1) \n" - " create Create the gluster block\n" - " volserver [gluster-node] node addr from gluster pool(default: localhost)\n" - " size block storage size in KiB|MiB|GiB|TiB..\n" - " mpath multi path requirement for high availablity\n" - " servers block servers, clubbed with any option\n" - "\n" - " list List available gluster blocks\n" - "\n" - " info Details about gluster block\n" - "\n" - " modify Modify the metadata\n" - "\n" - " delete Delete the gluster block\n" - "\n" - " volume gluster volume name\n" - ); -} - - -static int -glusterBlockCreate(int argcount, char **options) -{ - size_t opt; - size_t optind = 2; - int ret = 0; - char *out = NULL; - bool volserver = FALSE; - static blockCreateCli cobj = {0, }; - - - if(argcount <= optind) { - MSG("%s\n", "Insufficient options for create"); - return -1; - } - - /* name of block */ - strcpy(cobj.block_name, options[optind++]); - - while (1) { - if(argcount <= optind) { - break; - } - - opt = glusterBlockCLICreateOptEnumParse(options[optind++]); - if (opt == GB_CLI_CREATE_OPT_MAX) { - MSG("unrecognized option '%s'\n", options[optind-1]); - return -1; - } else if (opt && !options[optind]) { - MSG("%s: require argument\n", options[optind-1]); - return -1; - } - - - switch (opt) { - case GB_CLI_CREATE_VOLUME: - strcpy(cobj.volume, options[optind++]); - ret++; - break; - - case GB_CLI_CREATE_VOLSERVER: - strcpy(cobj.volfileserver, options[optind++]); - volserver = TRUE; - break; - - case GB_CLI_CREATE_MULTIPATH: - sscanf(options[optind++], "%u", &cobj.mpath); - ret++; - break; - - case GB_CLI_CREATE_SIZE: - cobj.size = glusterBlockCreateParseSize(options[optind++]); - if (cobj.size < 0) { - LOG("cli", GB_LOG_ERROR, "%s", "failed while parsing size"); - ret = -1; - goto out; - } - ret++; - break; - - case GB_CLI_CREATE_BACKEND_SERVESRS: - if (GB_STRDUP(cobj.block_hosts, options[optind++]) < 0) { - LOG("cli", GB_LOG_ERROR, "%s", "failed while parsing size"); - ret = -1; - goto out; - } - ret++; - break; - - default: - MSG("unrecognized option '%s'\n", options[optind-1]); - MSG("%s", "Hint: gluster-block help\n"); - goto out; - } - } - - /* check all options required by create command are specified */ - if(ret < 4) { - MSG("%s\n", "Insufficient options for create"); - ret = -1; - goto out; - } - - if(!volserver) { - strcpy(cobj.volfileserver, "localhost"); - } - - ret = glusterBlockCliRPC_1(&cobj, CREATE_CLI, &out); - - if(out) - MSG("%s", out); - - out: - GB_FREE(cobj.block_hosts); - GB_FREE(out); - - return ret; -} - - -static int -glusterBlockList(int argcount, char **options) -{ - size_t opt; - size_t optind = 2; - static blockListCli cobj; - char *out = NULL; - int ret = -1; - - - if(argcount <= optind) { - MSG("%s\n", "Insufficient options for list"); - return -1; - } - - opt = glusterBlockCLICommonOptEnumParse(options[optind++]); - if (opt == GB_CLI_COMMON_OPT_MAX) { - MSG("unrecognized option '%s'\n", options[optind-1]); - MSG("%s\n", "List needs 'volume' option"); - return -1; - } else if (!options[optind]) { - MSG("%s: require argument\n", options[optind-1]); - return -1; - } - - if ((opt == GB_CLI_COMMON_VOLUME)) { - strcpy(cobj.volume, options[optind]); - - ret = glusterBlockCliRPC_1(&cobj, LIST_CLI, &out); - - if(out) - MSG("%s", out); - - GB_FREE(out); - } - - return ret; -} - - -static int -glusterBlockDelete(int argcount, char **options) -{ - size_t opt; - size_t optind = 2; - static blockDeleteCli cobj; - char *out = NULL; - int ret = -1; - - if(argcount <= optind) { - MSG("%s\n", "Insufficient options for delete"); - return -1; - } - - /* name of block */ - strcpy(cobj.block_name, options[optind++]); - - opt = glusterBlockCLICommonOptEnumParse(options[optind++]); - if (opt == GB_CLI_COMMON_OPT_MAX) { - MSG("unrecognized option '%s'\n", options[optind-1]); - MSG("%s\n", "Delete needs 'volume' option"); - return -1; - } else if (!options[optind]) { - MSG("%s: require argument\n", options[optind-1]); - return -1; - } - - if ((opt == GB_CLI_COMMON_VOLUME)) { - strcpy(cobj.volume, options[optind]); - ret = glusterBlockCliRPC_1(&cobj, DELETE_CLI, &out); - - if(out) - MSG("%s", out); - - GB_FREE(out); - } - - return ret; -} - - -static int -glusterBlockInfo(int argcount, char **options) -{ - size_t opt; - size_t optind = 2; - static blockInfoCli cobj; - char *out = NULL; - int ret = -1; - - if(argcount <= optind) { - MSG("%s\n", "Insufficient options for info"); - return -1; - } - - /* name of block */ - strcpy(cobj.block_name, options[optind++]); - - opt = glusterBlockCLICommonOptEnumParse(options[optind++]); - if (opt == GB_CLI_COMMON_OPT_MAX) { - MSG("unrecognized option '%s'\n", options[optind-1]); - MSG("%s\n", "Info needs 'volume' option"); - return -1; - } else if (!options[optind]) { - MSG("%s: require argument\n", options[optind-1]); - return -1; - } - - if ((opt == GB_CLI_COMMON_VOLUME)) { - strcpy(cobj.volume, options[optind]); - ret = glusterBlockCliRPC_1(&cobj, INFO_CLI, &out); - - if(out) - MSG("%s", out); - - GB_FREE(out); - } - - return ret; -} - - -static int -glusterBlockParseArgs(int count, char **options) -{ - int ret = 0; - size_t opt = 0; - - opt = glusterBlockCLIOptEnumParse(options[1]); - if (!opt || opt >= GB_CLI_OPT_MAX) { - MSG("unknow option: %s\n", options[1]); - return -1; - } - - while (1) { - switch (opt) { - case GB_CLI_CREATE: - ret = glusterBlockCreate(count, options); - if (ret && ret != EEXIST) { - LOG("cli", GB_LOG_ERROR, "%s", FAILED_CREATE); - } - goto out; - - case GB_CLI_LIST: - ret = glusterBlockList(count, options); - if (ret) { - LOG("cli", GB_LOG_ERROR, "%s", FAILED_LIST); - } - goto out; - - case GB_CLI_INFO: - ret = glusterBlockInfo(count, options); - if (ret) { - LOG("cli", GB_LOG_ERROR, "%s", FAILED_INFO); - } - goto out; - - case GB_CLI_DELETE: - ret = glusterBlockDelete(count, options); - if (ret) { - LOG("cli", GB_LOG_ERROR, "%s", FAILED_DELETE); - } - goto out; - - case GB_CLI_HELP: - glusterBlockHelp(); - goto out; - } - } - - out: - return ret; -} - - -int -main(int argc, char *argv[]) -{ - if (argc <= 1) - glusterBlockHelp(); - - return glusterBlockParseArgs(argc, argv); -} diff --git a/gluster-block.spec.in b/gluster-block.spec.in new file mode 100644 index 0000000..c0a2ea9 --- /dev/null +++ b/gluster-block.spec.in @@ -0,0 +1,42 @@ + +Summary: Gluster block storage utility +Name: @PACKAGE_NAME@ +Version: @PACKAGE_VERSION@ +Vendor: Gluster Community +Release: @PACKAGE_RELEASE@ +License: GPLv2 or LGPLv3+ +Group: System Environment/Base +BuildRequires: glusterfs-api-devel >= 3.6.0 +BuildRequires: help2man >= 1.36 +Requires: glusterfs-api >= 3.6.0 +%if ( 0%{?_with_systemd:1} ) +BuildRequires: systemd +%endif +URL: http://www.gluster.org/docs/index.php/GlusterFS +Source0: @PACKAGE_NAME@-@PACKAGE_VERSION@.tar.gz + +%description +gluster-block is a CLI utility, which aims at making gluster backed +block storage creation and maintenance as simple as possible. + +%prep +rm -rf %{_topdir}/BUILD/* + +%setup + +%build +%configure +make + +%install +make DESTDIR=${RPM_BUILD_ROOT} install + +%clean +rm -rf ${RPM_BUILD_ROOT} + +%files +%{_sbindir}/gluster-block +%{_sbindir}/gluster-blockd +%if ( 0%{?_with_systemd:1} ) +%{_unitdir}/gluster-blockd.service +%endif diff --git a/gluster-blockd.c b/gluster-blockd.c deleted file mode 100644 index 9d1ace8..0000000 --- a/gluster-blockd.c +++ /dev/null @@ -1,849 +0,0 @@ -/* - Copyright (c) 2016 Red Hat, Inc. - This file is part of gluster-block. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - - -# define _GNU_SOURCE /* See feature_test_macros(7) */ - -# include -# include -# include -# include - -# include "rpc/block.h" -# include "common.h" -# include "glfs-operations.h" - - -# define UUID_BUF_SIZE 38 - -# define CREATE "create" -# define DELETE "delete" - -# define GLFS_PATH "/backstores/user:glfs" -# define TARGETCLI_GLFS "targetcli "GLFS_PATH -# define TARGETCLI_ISCSI "targetcli /iscsi" -# define TARGETCLI_SAVE "targetcli / saveconfig" -# define ATTRIBUTES "generate_node_acls=1 demo_mode_write_protect=0" -# define IQN_PREFIX "iqn.2016-12.org.gluster-block:" - -# define MSERVER_DELIMITER "," - - - -typedef struct blockServerDef { - size_t nhosts; - char **hosts; -} blockServerDef; -typedef blockServerDef *blockServerDefPtr; - -typedef enum operations { - CREATE_SRV = 1, - DELETE_SRV = 2, -} operations; - - -static int -glusterBlockCallRPC_1(char *host, void *cobj, - operations opt, char **out) -{ - CLIENT *clnt = NULL; - int ret = -1; - int sockfd; - blockResponse *reply; - struct hostent *server; - struct sockaddr_in sain; - - - if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { - LOG("mgmt", GB_LOG_ERROR, "socket creation failed (%s)", - strerror (errno)); - goto out; - } - - server = gethostbyname(host); - if (!server) { - LOG("mgmt", GB_LOG_ERROR, "gethostbyname failed (%s)", - strerror (errno)); - goto out; - } - - bzero((char *) &sain, sizeof(sain)); - sain.sin_family = AF_INET; - bcopy((char *)server->h_addr, (char *)&sain.sin_addr.s_addr, - server->h_length); - sain.sin_port = htons(24006); - - if (connect(sockfd, (struct sockaddr *) &sain, sizeof(sain)) < 0) { - LOG("mgmt", GB_LOG_ERROR, "connect failed (%s)", strerror (errno)); - goto out; - } - - clnt = clnttcp_create ((struct sockaddr_in *) &sain, GLUSTER_BLOCK, - GLUSTER_BLOCK_VERS, &sockfd, 0, 0); - if (!clnt) { - LOG("mgmt", GB_LOG_ERROR, "%s, inet host %s", - clnt_spcreateerror("client create failed"), host); - goto out; - } - - switch(opt) { - case CREATE_SRV: - reply = block_create_1((blockCreate *)cobj, clnt); - if (!reply) { - LOG("mgmt", GB_LOG_ERROR, "%s", - clnt_sperror(clnt, "block create failed")); - goto out; - } - break; - case DELETE_SRV: - reply = block_delete_1((blockDelete *)cobj, clnt); - if (!reply) { - LOG("mgmt", GB_LOG_ERROR, "%s", - clnt_sperror(clnt, "block delete failed")); - goto out; - } - break; - } - - if (GB_STRDUP(*out, reply->out) < 0){ - goto out; - } - ret = reply->exit; - - out: - if (clnt) { - if (!reply || - !clnt_freeres(clnt, (xdrproc_t)xdr_blockResponse, (char *)reply)) { - LOG("mgmt", GB_LOG_ERROR, "%s", - clnt_sperror(clnt, "clnt_freeres failed")); - - clnt_destroy (clnt); - } - } - - close(sockfd); - - return ret; -} - - -void -blockServerDefFree(blockServerDefPtr blkServers) -{ - size_t i; - - - if (!blkServers) { - return; - } - - for (i = 0; i < blkServers->nhosts; i++) { - GB_FREE(blkServers->hosts[i]); - } - GB_FREE(blkServers->hosts); - GB_FREE(blkServers); -} - - -static blockServerDefPtr -blockServerParse(char *blkServers) -{ - blockServerDefPtr list; - char *tmp = blkServers; - size_t i = 0; - - - if (GB_ALLOC(list) < 0) { - return NULL; - } - - if (!blkServers) { - blkServers = "localhost"; - } - - /* count number of servers */ - while (*tmp) { - if (*tmp == ',') { - list->nhosts++; - } - tmp++; - } - list->nhosts++; - tmp = blkServers; /* reset addr */ - - - if (GB_ALLOC_N(list->hosts, list->nhosts) < 0) { - goto fail; - } - - for (i = 0; tmp != NULL; i++) { - if (GB_STRDUP(list->hosts[i], strsep(&tmp, MSERVER_DELIMITER)) < 0) { - goto fail; - } - } - - return list; - - fail: - blockServerDefFree(list); - return NULL; -} - - -static void -glusterBlockCreateRemote(struct glfs_fd *tgmfd, char *volume, - blockCreate *cobj, char *addr, char **reply) -{ - int ret; - char *out = NULL; - char *tmp = *reply; - - - GB_METAUPDATE_OR_GOTO(tgmfd, cobj->gbid, volume, ret, out, - "%s: CONFIGINPROGRESS\n", addr); - - ret = glusterBlockCallRPC_1(addr, cobj, CREATE_SRV, &out); - if (ret) { - GB_METAUPDATE_OR_GOTO(tgmfd, cobj->gbid, volume, ret, out, - "%s: CONFIGFAIL\n", addr); - LOG("mgmt", GB_LOG_ERROR, "%s on host: %s", FAILED_CREATE, addr); - goto out; - } - - GB_METAUPDATE_OR_GOTO(tgmfd, cobj->gbid, volume, ret, out, - "%s: CONFIGSUCCESS\n", addr); - - out: - asprintf(reply, "%s%s\n", (tmp==NULL?"":tmp), out); - GB_FREE(tmp); - GB_FREE(out); -} - - -static int -glusterBlockAuditRequest(struct glfs *glfs, - struct glfs_fd *tgmfd, - blockCreateCli *blk, - blockCreate *cobj, - blockServerDefPtr list, - char **reply) -{ - int ret = -1; - size_t i; - size_t successcnt = 0; - size_t failcnt = 0; - size_t spent; - size_t spare; - size_t morereq; - MetaInfo *info; - - - if (GB_ALLOC(info) < 0) { - goto out; - } - - ret = blockGetMetaInfo(glfs, blk->block_name, info); - if (ret) { - goto out; - } - - for (i = 0; i < info->nhosts; i++) { - switch (blockMetaStatusEnumParse(info->list[i]->status)) { - case GB_CONFIG_SUCCESS: - successcnt++; - break; - case GB_CONFIG_INPROGRESS: - case GB_CONFIG_FAIL: - failcnt++; - } - } - - /* check if mpath is satisfied */ - if (blk->mpath == successcnt) { - ret = 0; - goto out; - } else { - spent = successcnt + failcnt; /* total spent */ - spare = list->nhosts - spent; /* spare after spent */ - morereq = blk->mpath - successcnt; /* needed nodes to complete req */ - if (spare == 0) { - LOG("mgmt", GB_LOG_WARNING, "%s", - "No Spare nodes: rewining the creation of target"); - ret = -1; - goto out; - } else if (spare < morereq) { - LOG("mgmt", GB_LOG_WARNING, "%s", - "Not enough Spare nodes: rewining the creation of target"); - ret = -1; - goto out; - } else { - /* create on spare */ - LOG("mgmt", GB_LOG_INFO, "%s", - "trying to serve the mpath from spare machines"); - for (i = spent; i < list->nhosts; i++) { - glusterBlockCreateRemote(tgmfd, info->volume, cobj, - list->hosts[i], reply); - } - } - } - - ret = glusterBlockAuditRequest(glfs, tgmfd, blk, cobj, list, reply); - - out: - blockFreeMetaInfo(info); - return ret; -} - - -static void -glusterBlockDeleteRemote(struct glfs_fd *tgmfd, MetaInfo *info, - blockDelete *cobj, char *addr, char **reply) -{ - int ret = -1; - char *out = NULL; - char *tmp = *reply; - - - GB_METAUPDATE_OR_GOTO(tgmfd, info->gbid, info->volume, ret, out, - "%s: CLEANUPINPROGRES\n", addr); - ret = glusterBlockCallRPC_1(addr, cobj, DELETE_SRV, &out); - if (ret) { - GB_METAUPDATE_OR_GOTO(tgmfd, info->gbid, info->volume, ret, out, - "%s: CLEANUPFAIL\n", addr); - LOG("mgmt", GB_LOG_ERROR, "%s on host: %s", - FAILED_GATHERING_INFO, addr); - goto out; - } - GB_METAUPDATE_OR_GOTO(tgmfd, info->gbid, info->volume, ret, out, - "%s: CLEANUPSUCCESS\n", addr); - - out: - asprintf(reply, "%s%s\n", (tmp==NULL?"":tmp), out); - GB_FREE(tmp); - GB_FREE(out); -} - - -static int -glusterBlockCleanUp(struct glfs *glfs, char *blockname, - bool deleteall, char **reply) -{ - int ret = -1; - size_t i; - static blockDelete cobj; - struct glfs_fd *tgmfd = NULL; - size_t cleanupsuccess = 0; - MetaInfo *info; - - - if (GB_ALLOC(info) < 0) { - goto out; - } - - ret = blockGetMetaInfo(glfs, blockname, info); - if (ret) { - goto out; - } - - strcpy(cobj.block_name, blockname); - strcpy(cobj.gbid, info->gbid); - - tgmfd = glfs_open(glfs, blockname, O_WRONLY|O_APPEND); - if (!tgmfd) { - LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_open: failed"); - goto out; - } - - for (i = 0; i < info->nhosts; i++) { - switch (blockMetaStatusEnumParse(info->list[i]->status)) { - case GB_CLEANUP_INPROGRES: - case GB_CLEANUP_FAIL: - case GB_CONFIG_FAIL: - case GB_CONFIG_INPROGRESS: - glusterBlockDeleteRemote(tgmfd, info, &cobj, - info->list[i]->addr, reply); - break; - } - if (deleteall && - blockMetaStatusEnumParse(info->list[i]->status) == GB_CONFIG_SUCCESS) { - glusterBlockDeleteRemote(tgmfd, info, &cobj, - info->list[i]->addr, reply); - } - } - blockFreeMetaInfo(info); - - if (GB_ALLOC(info) < 0) - goto out; - - ret = blockGetMetaInfo(glfs, blockname, info); - if (ret) - goto out; - - for (i = 0; i < info->nhosts; i++) { - if (blockMetaStatusEnumParse(info->list[i]->status) == GB_CLEANUP_SUCCESS) { - cleanupsuccess++; - } - } - - if (cleanupsuccess == info->nhosts) { - if (glusterBlockDeleteEntry(info->volume, info->gbid)) { - LOG("mgmt", GB_LOG_ERROR, "%s volume: %s host: %s", - FAILED_DELETING_FILE, info->volume, "localhost"); - } - ret = glfs_unlink(glfs, blockname); - if (ret && errno != ENOENT) { - LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_unlink: failed"); - goto out; - } - } - - out: - blockFreeMetaInfo(info); - - if (glfs_close(tgmfd) != 0) { - LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed"); - } - - return ret; -} - - -blockResponse * -block_create_cli_1_svc(blockCreateCli *blk, struct svc_req *rqstp) -{ - int ret = -1; - size_t i; - uuid_t uuid; - char *savereply = NULL; - char gbid[UUID_BUF_SIZE]; - static blockCreate cobj; - static blockResponse *reply; - struct glfs *glfs; - struct glfs_fd *lkfd = NULL; - struct glfs_fd *tgmfd = NULL; - blockServerDefPtr list = NULL; - - - if (GB_ALLOC(reply) < 0) { - goto out; - } - - list = blockServerParse(blk->block_hosts); - - /* Fail if mpath > list->nhosts */ - if (blk->mpath > list->nhosts) { - LOG("mgmt", GB_LOG_ERROR, "block multipath request:%d is greater " - "than provided block-hosts:%s", - blk->mpath, blk->block_hosts); - asprintf(&reply->out, "multipath req: %d > block-hosts: %s\n", - blk->mpath, blk->block_hosts); - reply->exit = ENODEV; - goto optfail; - } - - glfs = glusterBlockVolumeInit(blk->volume, blk->volfileserver); - if (!glfs) { - LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed"); - goto out; - } - - lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume); - if (!lkfd) { - LOG("mgmt", GB_LOG_ERROR, "%s", - "glusterBlockCreateMetaLockFile failed"); - goto out; - } - - GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out); - - if (!glfs_access(glfs, blk->block_name, F_OK)) { - asprintf(&reply->out, "BLOCK with name: '%s' already EXIST\n", - blk->block_name); - ret = EEXIST; - goto exist; - } - - tgmfd = glfs_creat(glfs, blk->block_name, O_RDWR, S_IRUSR | S_IWUSR); - if (!tgmfd) { - LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_creat: failed"); - goto out; - } - - uuid_generate(uuid); - uuid_unparse(uuid, gbid); - - GB_METAUPDATE_OR_GOTO(tgmfd, blk->block_name, blk->volume, ret, exist, - "VOLUME: %s\nGBID: %s\nSIZE: %zu\nHA: %d\n" - "ENTRYCREATE: INPROGRESS\n", - blk->volume, gbid, blk->size, blk->mpath); - - ret = glusterBlockCreateEntry(blk, gbid); - if (ret) { - GB_METAUPDATE_OR_GOTO(tgmfd, blk->block_name, blk->volume, ret, - exist, "ENTRYCREATE: FAIL\n"); - LOG("mgmt", GB_LOG_ERROR, "%s volume: %s host: %s", - FAILED_CREATING_FILE, blk->volume, blk->volfileserver); - goto out; - } - - GB_METAUPDATE_OR_GOTO(tgmfd, blk->block_name, blk->volume, ret, exist, - "ENTRYCREATE: SUCCESS\n"); - - strcpy(cobj.volume, blk->volume); - strcpy(cobj.volfileserver, blk->volfileserver); - strcpy(cobj.block_name, blk->block_name); - cobj.size = blk->size; - strcpy(cobj.gbid, gbid); - - for (i = 0; i < blk->mpath; i++) { - glusterBlockCreateRemote(tgmfd, blk->volume, &cobj, - list->hosts[i], &savereply); - } - - /* Check Point */ - ret = glusterBlockAuditRequest(glfs, tgmfd, blk, - &cobj, list, &savereply); - if (ret) { - LOG("mgmt", GB_LOG_ERROR, "%s", - "even spare nodes have exhausted rewinding"); - ret = glusterBlockCleanUp(glfs, - blk->block_name, FALSE, &savereply); - } - - out: - reply->out = savereply; - - if (glfs_close(tgmfd) != 0) - LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed"); - - exist: - GB_METAUNLOCK(lkfd, blk->volume, ret); - - reply->exit = ret; - - if (glfs_close(lkfd) != 0) { - LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed"); - } - - glfs_fini(glfs); - - optfail: - blockServerDefFree(list); - - return reply; -} - - -blockResponse * -block_create_1_svc(blockCreate *blk, struct svc_req *rqstp) -{ - FILE *fp; - char *backstore; - char *iqn; - char *lun; - char *attr; - char *exec; - blockResponse *reply = NULL; - - - asprintf(&backstore, "%s %s %s %zu %s@%s/%s %s", TARGETCLI_GLFS, - CREATE, blk->block_name, blk->size, blk->volume, - blk->volfileserver, blk->gbid, blk->gbid); - - asprintf(&iqn, "%s %s %s%s", TARGETCLI_ISCSI, CREATE, - IQN_PREFIX, blk->gbid); - - - asprintf(&lun, "%s/%s%s/tpg1/luns %s %s/%s", TARGETCLI_ISCSI, - IQN_PREFIX, blk->gbid, CREATE, GLFS_PATH, blk->block_name); - - asprintf(&attr, "%s/%s%s/tpg1 set attribute %s", - TARGETCLI_ISCSI, IQN_PREFIX, blk->gbid, ATTRIBUTES); - - - asprintf(&exec, "%s && %s && %s && %s && %s", backstore, iqn, lun, - attr, TARGETCLI_SAVE); - - if (GB_ALLOC(reply) < 0) { - goto out; - } - - if (GB_ALLOC_N(reply->out, 4096) < 0) { - GB_FREE(reply); - goto out; - } - - fp = popen(exec, "r"); - if (fp != NULL) { - size_t newLen = fread(reply->out, sizeof(char), 4096, fp); - if (ferror( fp ) != 0) { - LOG("mgmt", GB_LOG_ERROR, "Reading command %s output", exec); - } else { - reply->out[newLen++] = '\0'; - } - reply->exit = WEXITSTATUS(pclose(fp)); - } - - out: - GB_FREE(exec); - GB_FREE(attr); - GB_FREE(lun); - GB_FREE(iqn); - GB_FREE(backstore); - - return reply; -} - - -blockResponse * -block_delete_cli_1_svc(blockDeleteCli *blk, struct svc_req *rqstp) -{ - int ret = -1; - char *savereply = NULL; - static blockResponse *reply = NULL; - struct glfs *glfs; - struct glfs_fd *lkfd; - - - if (GB_ALLOC(reply) < 0) { - return NULL; - } - - glfs = glusterBlockVolumeInit(blk->volume, "localhost"); - if (!glfs) { - LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed"); - goto out; - } - - lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume); - if (!lkfd) { - LOG("mgmt", GB_LOG_ERROR, "%s", - "glusterBlockCreateMetaLockFile failed"); - goto out; - } - - GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out); - - if (glfs_access(glfs, blk->block_name, F_OK)) { - GB_STRDUP(reply->out, "BLOCK Doesn't EXIST"); - reply->exit = ENOENT; - goto out; - } - - ret = glusterBlockCleanUp(glfs, blk->block_name, TRUE, &savereply); - - out: - reply->out = savereply; - - GB_METAUNLOCK(lkfd, blk->volume, ret); - - reply->exit = ret; - - if (glfs_close(lkfd) != 0) - LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed"); - - glfs_fini(glfs); - - return reply; -} - - -blockResponse * -block_delete_1_svc(blockDelete *blk, struct svc_req *rqstp) -{ - FILE *fp; - char *iqn; - char *backstore; - char *exec; - blockResponse *reply = NULL; - - - asprintf(&iqn, "%s %s %s%s", TARGETCLI_ISCSI, DELETE, - IQN_PREFIX, blk->gbid); - - asprintf(&backstore, "%s %s %s", TARGETCLI_GLFS, - DELETE, blk->block_name); - - asprintf(&exec, "%s && %s && %s", backstore, iqn, TARGETCLI_SAVE); - - if (GB_ALLOC(reply) < 0) { - goto out; - } - - if (GB_ALLOC_N(reply->out, 4096) < 0) { - GB_FREE(reply); - goto out; - } - - fp = popen(exec, "r"); - if (fp != NULL) { - size_t newLen = fread(reply->out, sizeof(char), 4096, fp); - if (ferror( fp ) != 0) { - LOG("mgmt", GB_LOG_ERROR, "reading command %s output", exec); - } else { - reply->out[newLen++] = '\0'; - } - reply->exit = WEXITSTATUS(pclose(fp)); - } - - out: - GB_FREE(exec); - GB_FREE(backstore); - GB_FREE(iqn); - - return reply; -} - - -blockResponse * -block_list_cli_1_svc(blockListCli *blk, struct svc_req *rqstp) -{ - blockResponse *reply; - struct glfs *glfs; - struct glfs_fd *lkfd = NULL; - struct glfs_fd *tgmfd = NULL; - struct dirent *entry; - char *tmp = NULL; - char *filelist = NULL; - int ret = -1; - - - glfs = glusterBlockVolumeInit(blk->volume, "localhost"); - if (!glfs) { - LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed"); - goto out; - } - - lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume); - if (!lkfd) { - LOG("mgmt", GB_LOG_ERROR, "%s", - "glusterBlockCreateMetaLockFile failed"); - goto out; - } - - GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out); - - tgmfd = glfs_opendir (glfs, "/block-meta"); - if (!tgmfd) { - LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed"); - goto out; - } - - while ((entry = glfs_readdir (tgmfd))) { - if (strcmp(entry->d_name, ".") && - strcmp(entry->d_name, "..") && - strcmp(entry->d_name, "meta.lock")) { - asprintf(&filelist, "%s%s\n", (tmp==NULL?"":tmp), entry->d_name); - GB_FREE(tmp); - tmp = filelist; - } - } - - ret = 0; - - out: - if (GB_ALLOC(reply) < 0) { - return NULL; - } - - reply->out = filelist? filelist:strdup("*Nil*\n"); - - glfs_closedir (tgmfd); - - GB_METAUNLOCK(lkfd, blk->volume, ret); - - reply->exit = ret; - - if (glfs_close(lkfd) != 0) { - LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed"); - } - - glfs_fini(glfs); - - return reply; -} - - -blockResponse * -block_info_cli_1_svc(blockInfoCli *blk, struct svc_req *rqstp) -{ - blockResponse *reply; - char *out = NULL; - char *tmp = NULL; - struct glfs *glfs; - struct glfs_fd *lkfd = NULL; - MetaInfo *info = NULL; - int ret = -1; - size_t i; - - - glfs = glusterBlockVolumeInit(blk->volume, "localhost"); - if (!glfs) { - LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed"); - goto out; - } - - lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume); - if (!lkfd) { - LOG("mgmt", GB_LOG_ERROR, "%s", - "glusterBlockCreateMetaLockFile failed"); - goto out; - } - - GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out); - - if (GB_ALLOC(info) < 0) { - goto out; - } - - ret = blockGetMetaInfo(glfs, blk->block_name, info); - if (ret) { - goto out; - } - - asprintf(&tmp, "NAME: %s\nVOLUME: %s\nGBID: %s\nSIZE: %zu\n" - "MULTIPATH: %zu\nBLOCK CONFIG NODE(S):", - blk->block_name, info->volume, info->gbid, - info->size, info->mpath); - for (i = 0; i < info->nhosts; i++) { - if (blockMetaStatusEnumParse(info->list[i]->status) == GB_CONFIG_SUCCESS) { - asprintf(&out, "%s %s", (tmp==NULL?"":tmp), info->list[i]->addr); - GB_FREE(tmp); - tmp = out; - } - } - asprintf(&out, "%s\n", tmp); - ret = 0; - - out: - if (GB_ALLOC(reply) < 0) { - return NULL; - } - - if (!out) { - asprintf(&out, "No Block with name %s", blk->block_name); - } - - reply->out = out; - - GB_METAUNLOCK(lkfd, blk->volume, ret); - - reply->exit = ret; - - if (glfs_close(lkfd) != 0) { - LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed"); - } - - glfs_fini(glfs); - - blockFreeMetaInfo(info); - - return reply; -} diff --git a/rpc/Makefile.am b/rpc/Makefile.am new file mode 100644 index 0000000..20ed49d --- /dev/null +++ b/rpc/Makefile.am @@ -0,0 +1,15 @@ +noinst_LTLIBRARIES = libgbxdr.la + +libgbxdr_la_SOURCES = block_clnt.c block_xdr.c block_svc.c block_svc_routines.c glfs-operations.c + +noinst_HEADERS = block.h glfs-operations.h + +libgbxdr_la_CFLAGS = -I$(top_srcdir)/utils/ + +libgbxdr_la_LIBADD = -lgfapi + +libgbxdr_ladir = $(includedir)/gluster-block/rpc + +DISTCLEANFILES = Makefile.in + +CLEANFILES = *~ diff --git a/rpc/block.h b/rpc/block.h index 03d0ec4..7122632 100644 --- a/rpc/block.h +++ b/rpc/block.h @@ -69,6 +69,27 @@ struct blockResponse { }; typedef struct blockResponse blockResponse; +typedef struct blockServerDef { + size_t nhosts; + char **hosts; +} blockServerDef; +typedef blockServerDef *blockServerDefPtr; + +typedef enum operations { + CREATE_SRV = 1, + DELETE_SRV = 2, +} operations; + +void +gluster_block_cli_1(struct svc_req *rqstp, register SVCXPRT *transp); + +void +gluster_block_1(struct svc_req *rqstp, register SVCXPRT *transp); + + +int +glusterBlockCallRPC_1(char *host, void *cobj, operations opt, char **out); + #define GLUSTER_BLOCK_CLI 212153113 #define GLUSTER_BLOCK_CLI_VERS 1 diff --git a/rpc/block.x b/rpc/block.x deleted file mode 100644 index 0bc988c..0000000 --- a/rpc/block.x +++ /dev/null @@ -1,59 +0,0 @@ -struct blockCreate { - char volume[255]; - char volfileserver[255]; - char gbid[127]; /* uuid */ - u_quad_t size; - char block_name[255]; -}; - -struct blockCreateCli { - char volume[255]; - char volfileserver[255]; - u_quad_t size; - u_int mpath; /* HA request count */ - char block_name[255]; - string block_hosts<>; -}; - -struct blockDeleteCli { - char block_name[255]; - char volume[255]; -}; - -struct blockDelete { - char block_name[255]; - char gbid[127]; -}; - -struct blockInfoCli { - char block_name[255]; - char volume[255]; -}; - -struct blockListCli { - char volume[255]; - u_quad_t offset; /* dentry d_name offset */ -}; - -struct blockResponse { - int exit; /* exit code of the command */ - string out<>; /* json output */ - u_quad_t offset; /* dentry d_name offset */ - opaque xdata<>; /* future reserve */ -}; - -program GLUSTER_BLOCK_CLI { - version GLUSTER_BLOCK_CLI_VERS { - blockResponse BLOCK_CREATE_CLI(blockCreateCli) = 1; - blockResponse BLOCK_LIST_CLI(blockListCli) = 2; - blockResponse BLOCK_INFO_CLI(blockInfoCli) = 3; - blockResponse BLOCK_DELETE_CLI(blockDeleteCli) = 4; - } = 1; -} = 212153113; /* B2 L12 O15 C3 K11 C3 */ - -program GLUSTER_BLOCK { - version GLUSTER_BLOCK_VERS { - blockResponse BLOCK_CREATE(blockCreate) = 1; - blockResponse BLOCK_DELETE(blockDelete) = 2; - } = 1; -} = 21215311; /* B2 L12 O15 C3 K11 */ diff --git a/rpc/block_svc.c b/rpc/block_svc.c index 3722d51..8c94d30 100644 --- a/rpc/block_svc.c +++ b/rpc/block_svc.c @@ -4,23 +4,12 @@ */ #include "block.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include #ifndef SIG_PF #define SIG_PF void(*)(int) #endif - - -static void +void gluster_block_cli_1(struct svc_req *rqstp, register SVCXPRT *transp) { union { @@ -82,7 +71,7 @@ gluster_block_cli_1(struct svc_req *rqstp, register SVCXPRT *transp) return; } -static void +void gluster_block_1(struct svc_req *rqstp, register SVCXPRT *transp) { union { @@ -129,102 +118,3 @@ gluster_block_1(struct svc_req *rqstp, register SVCXPRT *transp) } return; } - -void * -cli_thread_proc (void *vargp) -{ - register SVCXPRT *transp; - struct sockaddr_un saun; - int sockfd, len; - - if ((sockfd = socket(AF_UNIX, SOCK_STREAM, IPPROTO_IP)) < 0) { - perror("server: socket"); - exit(1); - } - - saun.sun_family = AF_UNIX; - strcpy(saun.sun_path, ADDRESS); - - unlink(ADDRESS); - len = sizeof(saun.sun_family) + strlen(saun.sun_path); - - if (bind(sockfd, (struct sockaddr *) &saun, len) < 0) { - perror("server: bind"); - exit(1); - } - - transp = svcunix_create(sockfd, 0, 0, ADDRESS); - if (transp == NULL) { - fprintf (stderr, "%s", "cannot create tcp service"); - exit(1); - } - - if (!svc_register(transp, GLUSTER_BLOCK_CLI, GLUSTER_BLOCK_CLI_VERS, gluster_block_cli_1, IPPROTO_IP)) { - fprintf (stderr, "%s", "unable to register (GLUSTER_BLOCK_CLI, GLUSTER_BLOCK_CLI_VERS, unix|local)."); - exit(1); - } - - svc_run (); - - return NULL; -} - -void * -server_thread_proc(void *vargp) -{ - register SVCXPRT *transp; - struct sockaddr_in sain; - int sockfd; - - if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { - perror("server: socket"); - exit(1); - } - - sain.sin_family = AF_INET; - sain.sin_addr.s_addr = INADDR_ANY; - sain.sin_port = htons(24006); - - if (bind(sockfd, (struct sockaddr *) &sain, sizeof (sain)) < 0) { - perror("server: bind"); - exit(1); - } - - transp = svctcp_create(sockfd, 0, 0); - if (transp == NULL) { - fprintf (stderr, "%s", "cannot create tcp service"); - exit(1); - } - - if (!svc_register(transp, GLUSTER_BLOCK, GLUSTER_BLOCK_VERS, gluster_block_1, IPPROTO_TCP)) { - fprintf (stderr, "%s", "unable to register (GLUSTER_BLOCK, GLUSTER_BLOCK_VERS, tcp)."); - exit(1); - } - - svc_run (); - - return NULL; -} - - -int -main (int argc, char **argv) -{ - pthread_t cli_thread; - pthread_t server_thread; - - - pmap_unset (GLUSTER_BLOCK_CLI, GLUSTER_BLOCK_CLI_VERS); - pmap_unset (GLUSTER_BLOCK, GLUSTER_BLOCK_VERS); - - pthread_create(&cli_thread, NULL, cli_thread_proc , NULL); - pthread_create(&server_thread, NULL, server_thread_proc , NULL); - - pthread_join(cli_thread, NULL); - pthread_join(server_thread, NULL); - - - fprintf (stderr, "%s", "svc_run returned"); - exit (0); - /* NOTREACHED */ -} diff --git a/rpc/block_svc_routines.c b/rpc/block_svc_routines.c new file mode 100644 index 0000000..91ad630 --- /dev/null +++ b/rpc/block_svc_routines.c @@ -0,0 +1,832 @@ +/* + Copyright (c) 2016 Red Hat, Inc. + This file is part of gluster-block. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +# include "common.h" +# include "glfs-operations.h" + +# include +# include + + +# define UUID_BUF_SIZE 38 + +# define CREATE "create" +# define DELETE "delete" + +# define GLFS_PATH "/backstores/user:glfs" +# define TARGETCLI_GLFS "targetcli "GLFS_PATH +# define TARGETCLI_ISCSI "targetcli /iscsi" +# define TARGETCLI_SAVE "targetcli / saveconfig" +# define ATTRIBUTES "generate_node_acls=1 demo_mode_write_protect=0" +# define IQN_PREFIX "iqn.2016-12.org.gluster-block:" + +# define MSERVER_DELIMITER "," + + + +int +glusterBlockCallRPC_1(char *host, void *cobj, + operations opt, char **out) +{ + CLIENT *clnt = NULL; + int ret = -1; + int sockfd; + blockResponse *reply; + struct hostent *server; + struct sockaddr_in sain; + + + if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + LOG("mgmt", GB_LOG_ERROR, "socket creation failed (%s)", + strerror (errno)); + goto out; + } + + server = gethostbyname(host); + if (!server) { + LOG("mgmt", GB_LOG_ERROR, "gethostbyname failed (%s)", + strerror (errno)); + goto out; + } + + bzero((char *) &sain, sizeof(sain)); + sain.sin_family = AF_INET; + bcopy((char *)server->h_addr, (char *)&sain.sin_addr.s_addr, + server->h_length); + sain.sin_port = htons(24006); + + if (connect(sockfd, (struct sockaddr *) &sain, sizeof(sain)) < 0) { + LOG("mgmt", GB_LOG_ERROR, "connect failed (%s)", strerror (errno)); + goto out; + } + + clnt = clnttcp_create ((struct sockaddr_in *) &sain, GLUSTER_BLOCK, + GLUSTER_BLOCK_VERS, &sockfd, 0, 0); + if (!clnt) { + LOG("mgmt", GB_LOG_ERROR, "%s, inet host %s", + clnt_spcreateerror("client create failed"), host); + goto out; + } + + switch(opt) { + case CREATE_SRV: + reply = block_create_1((blockCreate *)cobj, clnt); + if (!reply) { + LOG("mgmt", GB_LOG_ERROR, "%s", + clnt_sperror(clnt, "block create failed")); + goto out; + } + break; + case DELETE_SRV: + reply = block_delete_1((blockDelete *)cobj, clnt); + if (!reply) { + LOG("mgmt", GB_LOG_ERROR, "%s", + clnt_sperror(clnt, "block delete failed")); + goto out; + } + break; + } + + if (GB_STRDUP(*out, reply->out) < 0){ + goto out; + } + ret = reply->exit; + + out: + if (clnt) { + if (!reply || + !clnt_freeres(clnt, (xdrproc_t)xdr_blockResponse, (char *)reply)) { + LOG("mgmt", GB_LOG_ERROR, "%s", + clnt_sperror(clnt, "clnt_freeres failed")); + + clnt_destroy (clnt); + } + } + + close(sockfd); + + return ret; +} + + +void +blockServerDefFree(blockServerDefPtr blkServers) +{ + size_t i; + + + if (!blkServers) { + return; + } + + for (i = 0; i < blkServers->nhosts; i++) { + GB_FREE(blkServers->hosts[i]); + } + GB_FREE(blkServers->hosts); + GB_FREE(blkServers); +} + + +static blockServerDefPtr +blockServerParse(char *blkServers) +{ + blockServerDefPtr list; + char *tmp = blkServers; + size_t i = 0; + + + if (GB_ALLOC(list) < 0) { + return NULL; + } + + if (!blkServers) { + blkServers = "localhost"; + } + + /* count number of servers */ + while (*tmp) { + if (*tmp == ',') { + list->nhosts++; + } + tmp++; + } + list->nhosts++; + tmp = blkServers; /* reset addr */ + + + if (GB_ALLOC_N(list->hosts, list->nhosts) < 0) { + goto fail; + } + + for (i = 0; tmp != NULL; i++) { + if (GB_STRDUP(list->hosts[i], strsep(&tmp, MSERVER_DELIMITER)) < 0) { + goto fail; + } + } + + return list; + + fail: + blockServerDefFree(list); + return NULL; +} + + +static void +glusterBlockCreateRemote(struct glfs_fd *tgmfd, char *volume, + blockCreate *cobj, char *addr, char **reply) +{ + int ret; + char *out = NULL; + char *tmp = *reply; + + + GB_METAUPDATE_OR_GOTO(tgmfd, cobj->gbid, volume, ret, out, + "%s: CONFIGINPROGRESS\n", addr); + + ret = glusterBlockCallRPC_1(addr, cobj, CREATE_SRV, &out); + if (ret) { + GB_METAUPDATE_OR_GOTO(tgmfd, cobj->gbid, volume, ret, out, + "%s: CONFIGFAIL\n", addr); + LOG("mgmt", GB_LOG_ERROR, "%s on host: %s", FAILED_CREATE, addr); + goto out; + } + + GB_METAUPDATE_OR_GOTO(tgmfd, cobj->gbid, volume, ret, out, + "%s: CONFIGSUCCESS\n", addr); + + out: + asprintf(reply, "%s%s\n", (tmp==NULL?"":tmp), out); + GB_FREE(tmp); + GB_FREE(out); +} + + +static int +glusterBlockAuditRequest(struct glfs *glfs, + struct glfs_fd *tgmfd, + blockCreateCli *blk, + blockCreate *cobj, + blockServerDefPtr list, + char **reply) +{ + int ret = -1; + size_t i; + size_t successcnt = 0; + size_t failcnt = 0; + size_t spent; + size_t spare; + size_t morereq; + MetaInfo *info; + + + if (GB_ALLOC(info) < 0) { + goto out; + } + + ret = blockGetMetaInfo(glfs, blk->block_name, info); + if (ret) { + goto out; + } + + for (i = 0; i < info->nhosts; i++) { + switch (blockMetaStatusEnumParse(info->list[i]->status)) { + case GB_CONFIG_SUCCESS: + successcnt++; + break; + case GB_CONFIG_INPROGRESS: + case GB_CONFIG_FAIL: + failcnt++; + } + } + + /* check if mpath is satisfied */ + if (blk->mpath == successcnt) { + ret = 0; + goto out; + } else { + spent = successcnt + failcnt; /* total spent */ + spare = list->nhosts - spent; /* spare after spent */ + morereq = blk->mpath - successcnt; /* needed nodes to complete req */ + if (spare == 0) { + LOG("mgmt", GB_LOG_WARNING, "%s", + "No Spare nodes: rewining the creation of target"); + ret = -1; + goto out; + } else if (spare < morereq) { + LOG("mgmt", GB_LOG_WARNING, "%s", + "Not enough Spare nodes: rewining the creation of target"); + ret = -1; + goto out; + } else { + /* create on spare */ + LOG("mgmt", GB_LOG_INFO, "%s", + "trying to serve the mpath from spare machines"); + for (i = spent; i < list->nhosts; i++) { + glusterBlockCreateRemote(tgmfd, info->volume, cobj, + list->hosts[i], reply); + } + } + } + + ret = glusterBlockAuditRequest(glfs, tgmfd, blk, cobj, list, reply); + + out: + blockFreeMetaInfo(info); + return ret; +} + + +static void +glusterBlockDeleteRemote(struct glfs_fd *tgmfd, MetaInfo *info, + blockDelete *cobj, char *addr, char **reply) +{ + int ret = -1; + char *out = NULL; + char *tmp = *reply; + + + GB_METAUPDATE_OR_GOTO(tgmfd, info->gbid, info->volume, ret, out, + "%s: CLEANUPINPROGRES\n", addr); + ret = glusterBlockCallRPC_1(addr, cobj, DELETE_SRV, &out); + if (ret) { + GB_METAUPDATE_OR_GOTO(tgmfd, info->gbid, info->volume, ret, out, + "%s: CLEANUPFAIL\n", addr); + LOG("mgmt", GB_LOG_ERROR, "%s on host: %s", + FAILED_GATHERING_INFO, addr); + goto out; + } + GB_METAUPDATE_OR_GOTO(tgmfd, info->gbid, info->volume, ret, out, + "%s: CLEANUPSUCCESS\n", addr); + + out: + asprintf(reply, "%s%s\n", (tmp==NULL?"":tmp), out); + GB_FREE(tmp); + GB_FREE(out); +} + + +static int +glusterBlockCleanUp(struct glfs *glfs, char *blockname, + bool deleteall, char **reply) +{ + int ret = -1; + size_t i; + static blockDelete cobj; + struct glfs_fd *tgmfd = NULL; + size_t cleanupsuccess = 0; + MetaInfo *info; + + + if (GB_ALLOC(info) < 0) { + goto out; + } + + ret = blockGetMetaInfo(glfs, blockname, info); + if (ret) { + goto out; + } + + strcpy(cobj.block_name, blockname); + strcpy(cobj.gbid, info->gbid); + + tgmfd = glfs_open(glfs, blockname, O_WRONLY|O_APPEND); + if (!tgmfd) { + LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_open: failed"); + goto out; + } + + for (i = 0; i < info->nhosts; i++) { + switch (blockMetaStatusEnumParse(info->list[i]->status)) { + case GB_CLEANUP_INPROGRES: + case GB_CLEANUP_FAIL: + case GB_CONFIG_FAIL: + case GB_CONFIG_INPROGRESS: + glusterBlockDeleteRemote(tgmfd, info, &cobj, + info->list[i]->addr, reply); + break; + } + if (deleteall && + blockMetaStatusEnumParse(info->list[i]->status) == GB_CONFIG_SUCCESS) { + glusterBlockDeleteRemote(tgmfd, info, &cobj, + info->list[i]->addr, reply); + } + } + blockFreeMetaInfo(info); + + if (GB_ALLOC(info) < 0) + goto out; + + ret = blockGetMetaInfo(glfs, blockname, info); + if (ret) + goto out; + + for (i = 0; i < info->nhosts; i++) { + if (blockMetaStatusEnumParse(info->list[i]->status) == GB_CLEANUP_SUCCESS) { + cleanupsuccess++; + } + } + + if (cleanupsuccess == info->nhosts) { + if (glusterBlockDeleteEntry(info->volume, info->gbid)) { + LOG("mgmt", GB_LOG_ERROR, "%s volume: %s host: %s", + FAILED_DELETING_FILE, info->volume, "localhost"); + } + ret = glfs_unlink(glfs, blockname); + if (ret && errno != ENOENT) { + LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_unlink: failed"); + goto out; + } + } + + out: + blockFreeMetaInfo(info); + + if (glfs_close(tgmfd) != 0) { + LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed"); + } + + return ret; +} + + +blockResponse * +block_create_cli_1_svc(blockCreateCli *blk, struct svc_req *rqstp) +{ + int ret = -1; + size_t i; + uuid_t uuid; + char *savereply = NULL; + char gbid[UUID_BUF_SIZE]; + static blockCreate cobj; + static blockResponse *reply; + struct glfs *glfs; + struct glfs_fd *lkfd = NULL; + struct glfs_fd *tgmfd = NULL; + blockServerDefPtr list = NULL; + + + if (GB_ALLOC(reply) < 0) { + goto out; + } + + list = blockServerParse(blk->block_hosts); + + /* Fail if mpath > list->nhosts */ + if (blk->mpath > list->nhosts) { + LOG("mgmt", GB_LOG_ERROR, "block multipath request:%d is greater " + "than provided block-hosts:%s", + blk->mpath, blk->block_hosts); + asprintf(&reply->out, "multipath req: %d > block-hosts: %s\n", + blk->mpath, blk->block_hosts); + reply->exit = ENODEV; + goto optfail; + } + + glfs = glusterBlockVolumeInit(blk->volume, blk->volfileserver); + if (!glfs) { + LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed"); + goto out; + } + + lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume); + if (!lkfd) { + LOG("mgmt", GB_LOG_ERROR, "%s", + "glusterBlockCreateMetaLockFile failed"); + goto out; + } + + GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out); + + if (!glfs_access(glfs, blk->block_name, F_OK)) { + asprintf(&reply->out, "BLOCK with name: '%s' already EXIST\n", + blk->block_name); + ret = EEXIST; + goto exist; + } + + tgmfd = glfs_creat(glfs, blk->block_name, O_RDWR, S_IRUSR | S_IWUSR); + if (!tgmfd) { + LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_creat: failed"); + goto out; + } + + uuid_generate(uuid); + uuid_unparse(uuid, gbid); + + GB_METAUPDATE_OR_GOTO(tgmfd, blk->block_name, blk->volume, ret, exist, + "VOLUME: %s\nGBID: %s\nSIZE: %zu\nHA: %d\n" + "ENTRYCREATE: INPROGRESS\n", + blk->volume, gbid, blk->size, blk->mpath); + + ret = glusterBlockCreateEntry(blk, gbid); + if (ret) { + GB_METAUPDATE_OR_GOTO(tgmfd, blk->block_name, blk->volume, ret, + exist, "ENTRYCREATE: FAIL\n"); + LOG("mgmt", GB_LOG_ERROR, "%s volume: %s host: %s", + FAILED_CREATING_FILE, blk->volume, blk->volfileserver); + goto out; + } + + GB_METAUPDATE_OR_GOTO(tgmfd, blk->block_name, blk->volume, ret, exist, + "ENTRYCREATE: SUCCESS\n"); + + strcpy(cobj.volume, blk->volume); + strcpy(cobj.volfileserver, blk->volfileserver); + strcpy(cobj.block_name, blk->block_name); + cobj.size = blk->size; + strcpy(cobj.gbid, gbid); + + for (i = 0; i < blk->mpath; i++) { + glusterBlockCreateRemote(tgmfd, blk->volume, &cobj, + list->hosts[i], &savereply); + } + + /* Check Point */ + ret = glusterBlockAuditRequest(glfs, tgmfd, blk, + &cobj, list, &savereply); + if (ret) { + LOG("mgmt", GB_LOG_ERROR, "%s", + "even spare nodes have exhausted rewinding"); + ret = glusterBlockCleanUp(glfs, + blk->block_name, FALSE, &savereply); + } + + out: + reply->out = savereply; + + if (glfs_close(tgmfd) != 0) + LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed"); + + exist: + GB_METAUNLOCK(lkfd, blk->volume, ret); + + reply->exit = ret; + + if (glfs_close(lkfd) != 0) { + LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed"); + } + + glfs_fini(glfs); + + optfail: + blockServerDefFree(list); + + return reply; +} + + +blockResponse * +block_create_1_svc(blockCreate *blk, struct svc_req *rqstp) +{ + FILE *fp; + char *backstore; + char *iqn; + char *lun; + char *attr; + char *exec; + blockResponse *reply = NULL; + + + asprintf(&backstore, "%s %s %s %zu %s@%s/%s %s", TARGETCLI_GLFS, + CREATE, blk->block_name, blk->size, blk->volume, + blk->volfileserver, blk->gbid, blk->gbid); + + asprintf(&iqn, "%s %s %s%s", TARGETCLI_ISCSI, CREATE, + IQN_PREFIX, blk->gbid); + + + asprintf(&lun, "%s/%s%s/tpg1/luns %s %s/%s", TARGETCLI_ISCSI, + IQN_PREFIX, blk->gbid, CREATE, GLFS_PATH, blk->block_name); + + asprintf(&attr, "%s/%s%s/tpg1 set attribute %s", + TARGETCLI_ISCSI, IQN_PREFIX, blk->gbid, ATTRIBUTES); + + + asprintf(&exec, "%s && %s && %s && %s && %s", backstore, iqn, lun, + attr, TARGETCLI_SAVE); + + if (GB_ALLOC(reply) < 0) { + goto out; + } + + if (GB_ALLOC_N(reply->out, 4096) < 0) { + GB_FREE(reply); + goto out; + } + + fp = popen(exec, "r"); + if (fp != NULL) { + size_t newLen = fread(reply->out, sizeof(char), 4096, fp); + if (ferror( fp ) != 0) { + LOG("mgmt", GB_LOG_ERROR, "Reading command %s output", exec); + } else { + reply->out[newLen++] = '\0'; + } + reply->exit = WEXITSTATUS(pclose(fp)); + } + + out: + GB_FREE(exec); + GB_FREE(attr); + GB_FREE(lun); + GB_FREE(iqn); + GB_FREE(backstore); + + return reply; +} + + +blockResponse * +block_delete_cli_1_svc(blockDeleteCli *blk, struct svc_req *rqstp) +{ + int ret = -1; + char *savereply = NULL; + static blockResponse *reply = NULL; + struct glfs *glfs; + struct glfs_fd *lkfd; + + + if (GB_ALLOC(reply) < 0) { + return NULL; + } + + glfs = glusterBlockVolumeInit(blk->volume, "localhost"); + if (!glfs) { + LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed"); + goto out; + } + + lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume); + if (!lkfd) { + LOG("mgmt", GB_LOG_ERROR, "%s", + "glusterBlockCreateMetaLockFile failed"); + goto out; + } + + GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out); + + if (glfs_access(glfs, blk->block_name, F_OK)) { + GB_STRDUP(reply->out, "BLOCK Doesn't EXIST"); + reply->exit = ENOENT; + goto out; + } + + ret = glusterBlockCleanUp(glfs, blk->block_name, TRUE, &savereply); + + out: + reply->out = savereply; + + GB_METAUNLOCK(lkfd, blk->volume, ret); + + reply->exit = ret; + + if (glfs_close(lkfd) != 0) + LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed"); + + glfs_fini(glfs); + + return reply; +} + + +blockResponse * +block_delete_1_svc(blockDelete *blk, struct svc_req *rqstp) +{ + FILE *fp; + char *iqn; + char *backstore; + char *exec; + blockResponse *reply = NULL; + + + asprintf(&iqn, "%s %s %s%s", TARGETCLI_ISCSI, DELETE, + IQN_PREFIX, blk->gbid); + + asprintf(&backstore, "%s %s %s", TARGETCLI_GLFS, + DELETE, blk->block_name); + + asprintf(&exec, "%s && %s && %s", backstore, iqn, TARGETCLI_SAVE); + + if (GB_ALLOC(reply) < 0) { + goto out; + } + + if (GB_ALLOC_N(reply->out, 4096) < 0) { + GB_FREE(reply); + goto out; + } + + fp = popen(exec, "r"); + if (fp != NULL) { + size_t newLen = fread(reply->out, sizeof(char), 4096, fp); + if (ferror( fp ) != 0) { + LOG("mgmt", GB_LOG_ERROR, "reading command %s output", exec); + } else { + reply->out[newLen++] = '\0'; + } + reply->exit = WEXITSTATUS(pclose(fp)); + } + + out: + GB_FREE(exec); + GB_FREE(backstore); + GB_FREE(iqn); + + return reply; +} + + +blockResponse * +block_list_cli_1_svc(blockListCli *blk, struct svc_req *rqstp) +{ + blockResponse *reply; + struct glfs *glfs; + struct glfs_fd *lkfd = NULL; + struct glfs_fd *tgmfd = NULL; + struct dirent *entry; + char *tmp = NULL; + char *filelist = NULL; + int ret = -1; + + + glfs = glusterBlockVolumeInit(blk->volume, "localhost"); + if (!glfs) { + LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed"); + goto out; + } + + lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume); + if (!lkfd) { + LOG("mgmt", GB_LOG_ERROR, "%s", + "glusterBlockCreateMetaLockFile failed"); + goto out; + } + + GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out); + + tgmfd = glfs_opendir (glfs, "/block-meta"); + if (!tgmfd) { + LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed"); + goto out; + } + + while ((entry = glfs_readdir (tgmfd))) { + if (strcmp(entry->d_name, ".") && + strcmp(entry->d_name, "..") && + strcmp(entry->d_name, "meta.lock")) { + asprintf(&filelist, "%s%s\n", (tmp==NULL?"":tmp), entry->d_name); + GB_FREE(tmp); + tmp = filelist; + } + } + + ret = 0; + + out: + if (GB_ALLOC(reply) < 0) { + return NULL; + } + + reply->out = filelist? filelist:strdup("*Nil*\n"); + + glfs_closedir (tgmfd); + + GB_METAUNLOCK(lkfd, blk->volume, ret); + + reply->exit = ret; + + if (glfs_close(lkfd) != 0) { + LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed"); + } + + glfs_fini(glfs); + + return reply; +} + + +blockResponse * +block_info_cli_1_svc(blockInfoCli *blk, struct svc_req *rqstp) +{ + blockResponse *reply; + char *out = NULL; + char *tmp = NULL; + struct glfs *glfs; + struct glfs_fd *lkfd = NULL; + MetaInfo *info = NULL; + int ret = -1; + size_t i; + + + glfs = glusterBlockVolumeInit(blk->volume, "localhost"); + if (!glfs) { + LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed"); + goto out; + } + + lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume); + if (!lkfd) { + LOG("mgmt", GB_LOG_ERROR, "%s", + "glusterBlockCreateMetaLockFile failed"); + goto out; + } + + GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out); + + if (GB_ALLOC(info) < 0) { + goto out; + } + + ret = blockGetMetaInfo(glfs, blk->block_name, info); + if (ret) { + goto out; + } + + asprintf(&tmp, "NAME: %s\nVOLUME: %s\nGBID: %s\nSIZE: %zu\n" + "MULTIPATH: %zu\nBLOCK CONFIG NODE(S):", + blk->block_name, info->volume, info->gbid, + info->size, info->mpath); + for (i = 0; i < info->nhosts; i++) { + if (blockMetaStatusEnumParse(info->list[i]->status) == GB_CONFIG_SUCCESS) { + asprintf(&out, "%s %s", (tmp==NULL?"":tmp), info->list[i]->addr); + GB_FREE(tmp); + tmp = out; + } + } + asprintf(&out, "%s\n", tmp); + ret = 0; + + out: + if (GB_ALLOC(reply) < 0) { + return NULL; + } + + if (!out) { + asprintf(&out, "No Block with name %s", blk->block_name); + } + + reply->out = out; + + GB_METAUNLOCK(lkfd, blk->volume, ret); + + reply->exit = ret; + + if (glfs_close(lkfd) != 0) { + LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed"); + } + + glfs_fini(glfs); + + blockFreeMetaInfo(info); + + return reply; +} diff --git a/rpc/glfs-operations.c b/rpc/glfs-operations.c new file mode 100644 index 0000000..9712f64 --- /dev/null +++ b/rpc/glfs-operations.c @@ -0,0 +1,270 @@ +/* + Copyright (c) 2016 Red Hat, Inc. + This file is part of gluster-block. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +# include "common.h" +# include "glfs-operations.h" + +# define METADIR "/block-meta" +# define TXLOCKFILE "meta.lock" + + + +struct glfs * +glusterBlockVolumeInit(char *volume, char *volfileserver) +{ + struct glfs *glfs; + int ret; + + + glfs = glfs_new(volume); + if (!glfs) { + LOG("gfapi", GB_LOG_ERROR, "glfs_new(%s) from %s failed[%s]", volume, + volfileserver, strerror(errno)); + return NULL; + } + + ret = glfs_set_volfile_server(glfs, "tcp", volfileserver, 24007); + if (ret) { + LOG("gfapi", GB_LOG_ERROR, "glfs_set_volfile_server(%s) of %s " + "failed[%s]", volfileserver, volume, strerror(errno)); + goto out; + } + + ret = glfs_set_logging(glfs, GFAPI_LOG_FILE, GFAPI_LOG_LEVEL); + if (ret) { + LOG("gfapi", GB_LOG_ERROR, "glfs_set_logging(%s, %d) on %s failed[%s]", + GFAPI_LOG_FILE, GFAPI_LOG_LEVEL, volume, strerror(errno)); + goto out; + } + + ret = glfs_init(glfs); + if (ret) { + LOG("gfapi", GB_LOG_ERROR, "glfs_init() on %s failed[%s]", volume, + strerror(errno) ); + goto out; + } + + return glfs; + + out: + glfs_fini(glfs); + + return NULL; +} + + +int +glusterBlockCreateEntry(blockCreateCli *blk, char *gbid) +{ + struct glfs *glfs; + struct glfs_fd *tgfd; + int ret = -1; + + + glfs = glusterBlockVolumeInit(blk->volume, blk->volfileserver); + if (!glfs) { + LOG("gfapi", GB_LOG_ERROR, "glusterBlockVolumeInit(%s): failed", + blk->volume); + goto out; + } + + tgfd = glfs_creat(glfs, gbid, + O_WRONLY | O_CREAT | O_EXCL, + S_IRUSR | S_IWUSR); + if (!tgfd) { + LOG("gfapi", GB_LOG_ERROR, "glfs_creat(%s) on volume %s failed[%s]", + gbid, blk->volume, strerror(errno)); + } else { + ret = glfs_ftruncate(tgfd, blk->size); + if (ret) { + LOG("gfapi", GB_LOG_ERROR, "glfs_ftruncate(%s): on volume %s " + "of size %zu failed[%s]", gbid, blk->volume, blk->size, + strerror(errno)); + goto out; + } + + if (glfs_close(tgfd) != 0) { + LOG("gfapi", GB_LOG_ERROR, "glfs_close(%s): on volume %s failed[%s]", + gbid, blk->volume, strerror(errno)); + goto out; + } + } + + out: + glfs_fini(glfs); + return ret; +} + + +int +glusterBlockDeleteEntry(char *volume, char *gbid) +{ + struct glfs *glfs; + int ret = -1; + + + glfs = glusterBlockVolumeInit(volume, "localhost"); + if (!glfs) { + LOG("gfapi", GB_LOG_ERROR, "glusterBlockVolumeInit(%s): failed", + volume); + goto out; + } + + ret = glfs_unlink(glfs, gbid); + if (ret) { + LOG("gfapi", GB_LOG_ERROR, "glfs_unlink(%s) on volume %s failed[%s]", + gbid, volume, strerror(errno)); + goto out; + } + + out: + glfs_fini(glfs); + return ret; +} + + +struct glfs_fd * +glusterBlockCreateMetaLockFile(struct glfs *glfs, char *volume) +{ + struct glfs_fd *lkfd; + int ret; + + + ret = glfs_mkdir (glfs, METADIR, 0); + if (ret && errno != EEXIST) { + LOG("gfapi", GB_LOG_ERROR, "glfs_mkdir(%s) on volume %s failed[%s]", + METADIR, volume, strerror(errno)); + goto out; + } + + ret = glfs_chdir (glfs, METADIR); + if (ret) { + LOG("gfapi", GB_LOG_ERROR, "glfs_chdir(%s) on volume %s failed[%s]", + METADIR, volume, strerror(errno)); + goto out; + } + + lkfd = glfs_creat(glfs, TXLOCKFILE, O_RDWR, S_IRUSR | S_IWUSR); + if (!lkfd) { + LOG("gfapi", GB_LOG_ERROR, "glfs_creat(%s) on volume %s failed[%s]", + TXLOCKFILE, volume, strerror(errno)); + goto out; + } + + return lkfd; + + out: + return NULL; +} + + +void +blockFreeMetaInfo(MetaInfo *info) +{ + int i; + + + if (!info) + return; + + for (i = 0; i < info->nhosts; i++) + GB_FREE(info->list[i]); + + GB_FREE(info->list); + GB_FREE(info); +} + + +static void +blockStuffMetaInfo(MetaInfo *info, char *line) +{ + char* tmp = strdup(line); + char* opt = strtok(tmp,":"); + int Flag = 0; + size_t i; + + + switch (blockMetaKeyEnumParse(opt)) { + case GB_META_VOLUME: + strcpy(info->volume, strchr(line, ' ')+1); + break; + case GB_META_GBID: + strcpy(info->gbid, strchr(line, ' ')+1); + break; + case GB_META_SIZE: + sscanf(strchr(line, ' ')+1, "%zu", &info->size); + break; + case GB_META_HA: + sscanf(strchr(line, ' ')+1, "%zu", &info->mpath); + break; + case GB_META_ENTRYCREATE: + strcpy(info->entry, strchr(line, ' ')+1); + break; + + default: + if(!info->list) { + if(GB_ALLOC(info->list) < 0) + return; + if(GB_ALLOC(info->list[0]) < 0) + return; + strcpy(info->list[0]->addr, opt); + strcpy(info->list[0]->status, strchr(line, ' ')+1); + info->nhosts = 1; + } else { + for (i = 0; i < info->nhosts; i++) { + if(!strcmp(info->list[i]->addr, opt)) { + strcpy(info->list[i]->status, strchr(line, ' ')+1); + Flag = 1; + break; + } + } + if (!Flag) { + if(GB_ALLOC(info->list[info->nhosts]) < 0) + return; + strcpy(info->list[info->nhosts]->addr, opt); + strcpy(info->list[info->nhosts]->status, strchr(line, ' ')+1); + info->nhosts++; + } + } + break; + } + + GB_FREE(tmp); +} + + +int +blockGetMetaInfo(struct glfs* glfs, char* metafile, MetaInfo *info) +{ + size_t count = 0; + struct glfs_fd *tgmfd; + char line[1024]; + char *tmp; + + + tgmfd = glfs_open(glfs, metafile, O_RDONLY); + if (!tgmfd) { + LOG("gfapi", GB_LOG_ERROR, "glfs_open(%s) on volume %s failed[%s]", + metafile, info->volume, strerror(errno)); + return -1; + } + + while (glfs_read (tgmfd, line, sizeof(line), 0) > 0) { + tmp = strtok(line,"\n"); + count += strlen(tmp) + 1; + blockStuffMetaInfo(info, tmp); + glfs_lseek(tgmfd, count, SEEK_SET); + } + + glfs_close(tgmfd); + + return 0; +} diff --git a/rpc/glfs-operations.h b/rpc/glfs-operations.h new file mode 100644 index 0000000..8ba12f5 --- /dev/null +++ b/rpc/glfs-operations.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2016 Red Hat, Inc. + This file is part of gluster-block. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +# ifndef _GLFS_OPERATIONS_H +# define _GLFS_OPERATIONS_H 1 + +# include +# include +# include +# include + +# include + +# include "block.h" + + + +typedef struct NodeInfo { + char addr[255]; + char status[16]; +} NodeInfo; + +typedef struct MetaInfo { + char volume[255]; + char gbid[38]; + size_t size; + size_t mpath; + char entry[16]; + + size_t nhosts; + NodeInfo **list; +} MetaInfo; + + +struct glfs * +glusterBlockVolumeInit(char *volume, char *volfileserver); + +int +glusterBlockCreateEntry(blockCreateCli *blk, char *gbid); + +int +glusterBlockDeleteEntry(char *volume, char *gbid); + +struct glfs_fd * +glusterBlockCreateMetaLockFile(struct glfs *glfs, char *volume); + +int +blockGetMetaInfo(struct glfs *glfs, char *metafile, MetaInfo *info); + +void +blockFreeMetaInfo(MetaInfo *info); + +#endif /* _GLFS_OPERATIONS_H */ diff --git a/rpc/rpcl/block.x b/rpc/rpcl/block.x new file mode 100644 index 0000000..0bc988c --- /dev/null +++ b/rpc/rpcl/block.x @@ -0,0 +1,59 @@ +struct blockCreate { + char volume[255]; + char volfileserver[255]; + char gbid[127]; /* uuid */ + u_quad_t size; + char block_name[255]; +}; + +struct blockCreateCli { + char volume[255]; + char volfileserver[255]; + u_quad_t size; + u_int mpath; /* HA request count */ + char block_name[255]; + string block_hosts<>; +}; + +struct blockDeleteCli { + char block_name[255]; + char volume[255]; +}; + +struct blockDelete { + char block_name[255]; + char gbid[127]; +}; + +struct blockInfoCli { + char block_name[255]; + char volume[255]; +}; + +struct blockListCli { + char volume[255]; + u_quad_t offset; /* dentry d_name offset */ +}; + +struct blockResponse { + int exit; /* exit code of the command */ + string out<>; /* json output */ + u_quad_t offset; /* dentry d_name offset */ + opaque xdata<>; /* future reserve */ +}; + +program GLUSTER_BLOCK_CLI { + version GLUSTER_BLOCK_CLI_VERS { + blockResponse BLOCK_CREATE_CLI(blockCreateCli) = 1; + blockResponse BLOCK_LIST_CLI(blockListCli) = 2; + blockResponse BLOCK_INFO_CLI(blockInfoCli) = 3; + blockResponse BLOCK_DELETE_CLI(blockDeleteCli) = 4; + } = 1; +} = 212153113; /* B2 L12 O15 C3 K11 C3 */ + +program GLUSTER_BLOCK { + version GLUSTER_BLOCK_VERS { + blockResponse BLOCK_CREATE(blockCreate) = 1; + blockResponse BLOCK_DELETE(blockDelete) = 2; + } = 1; +} = 21215311; /* B2 L12 O15 C3 K11 */ diff --git a/systemd/Makefile.am b/systemd/Makefile.am new file mode 100644 index 0000000..605e1f8 --- /dev/null +++ b/systemd/Makefile.am @@ -0,0 +1,10 @@ +DISTCLEANFILES = Makefile.in gluster-blockd.service + +CLEANFILES = *~ gluster-blockd.service + +EXTRA_DIST = gluster-blockd.service.in + +if USE_SYSTEMD +# systemddir is already defined through configure.ac +systemd_DATA = gluster-blockd.service +endif diff --git a/systemd/gluster-blockd.service b/systemd/gluster-blockd.service deleted file mode 100644 index d1fc67c..0000000 --- a/systemd/gluster-blockd.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=Gluster block storage utility -Requires=rpcbind.service target.service tcmu-runner.service -After=rpcbind.service target.service tcmu-runner.service - -[Service] -Type=simple -ExecStart=/usr/local/sbin/gluster-blockd -KillMode=process - -[Install] -WantedBy=multi-user.target diff --git a/systemd/gluster-blockd.service.in b/systemd/gluster-blockd.service.in new file mode 100644 index 0000000..a92c10c --- /dev/null +++ b/systemd/gluster-blockd.service.in @@ -0,0 +1,12 @@ +[Unit] +Description=Gluster block storage utility +Requires=rpcbind.service target.service tcmu-runner.service +After=rpcbind.service target.service tcmu-runner.service + +[Service] +Type=simple +ExecStart=@prefix@/sbin/gluster-blockd +KillMode=process + +[Install] +WantedBy=multi-user.target diff --git a/utils.c b/utils.c deleted file mode 100644 index 059fb6b..0000000 --- a/utils.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - Copyright (c) 2016 Red Hat, Inc. - This file is part of gluster-block. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - - -# include "utils.h" - - - -int -glusterBlockCLIOptEnumParse(const char *opt) -{ - int i; - - - if (!opt) { - return GB_CLI_OPT_MAX; - } - - for (i = 0; i < GB_CLI_OPT_MAX; i++) { - if (!strcmp(opt, gbCmdlineOptLookup[i])) { - return i; - } - } - - return i; -} - -int -glusterBlockCLICreateOptEnumParse(const char *opt) -{ - int i; - - - if (!opt) { - return GB_CLI_CREATE_OPT_MAX; - } - - /* i = 11, enum start look gbCmdlineCreateOption */ - for (i = 11; i < GB_CLI_CREATE_OPT_MAX; i++) { - if (!strcmp(opt, gbCmdlineCreateOptLookup[i])) { - return i; - } - } - - return i; -} - -int -glusterBlockCLICommonOptEnumParse(const char *opt) -{ - int i; - - - if (!opt) { - return GB_CLI_COMMON_OPT_MAX; - } - - /* i = 21, enum start look gbCmdlineCreateOption */ - for (i = 21; i < GB_CLI_COMMON_OPT_MAX; i++) { - if (!strcmp(opt, gbCmdlineCommonOptLookup[i])) { - return i; - } - } - - return i; -} - -int -blockMetaKeyEnumParse(const char *opt) -{ - int i; - - - if (!opt) { - return GB_METAKEY_MAX; - } - - for (i = 0; i < GB_METAKEY_MAX; i++) { - if (!strcmp(opt, MetakeyLookup[i])) { - return i; - } - } - - return i; -} - - -int -blockMetaStatusEnumParse(const char *opt) -{ - int i; - - - if (!opt) { - return GB_METASTATUS_MAX; - } - - for (i = 0; i < GB_METASTATUS_MAX; i++) { - if (!strcmp(opt, MetaStatusLookup[i])) { - return i; - } - } - - return i; -} - - -int -gbAlloc(void *ptrptr, size_t size, - const char *filename, const char *funcname, size_t linenr) -{ - *(void **)ptrptr = calloc(1, size); - - if (*(void **)ptrptr == NULL) { - errno = ENOMEM; - return -1; - } - - return 0; -} - - -int -gbAllocN(void *ptrptr, size_t size, size_t count, - const char *filename, const char *funcname, size_t linenr) -{ - *(void**)ptrptr = calloc(count, size); - - if (*(void**)ptrptr == NULL) { - errno = ENOMEM; - return -1; - } - - return 0; -} - - -void -gbFree(void *ptrptr) -{ - int save_errno = errno; - - if(*(void**)ptrptr == NULL) { - return; - } - - free(*(void**)ptrptr); - *(void**)ptrptr = NULL; - errno = save_errno; -} - - -int -gbStrdup(char **dest, const char *src, - const char *filename, const char *funcname, size_t linenr) -{ - *dest = NULL; - - if (!src) { - return 0; - } - - if (!(*dest = strdup(src))) { - return -1; - } - - return 0; -} diff --git a/utils.h b/utils.h deleted file mode 100644 index 4cc1347..0000000 --- a/utils.h +++ /dev/null @@ -1,297 +0,0 @@ -/* - Copyright (c) 2016 Red Hat, Inc. - This file is part of gluster-block. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - - -# ifndef _UTILS_H -# define _UTILS_H 1 - -# include -# include -# include -# include -# include -# include - - -/* Target Create */ -# define FAILED_CREATE "failed in create" -# define FAILED_CREATING_FILE "failed while creating block file in gluster volume" -# define FAILED_CREATING_BACKEND "failed while creating glfs backend" -# define FAILED_CREATING_IQN "failed while creating IQN" -# define FAILED_CREATING_LUN "failed while creating LUN" -# define FAILED_SETTING_ATTRIBUTES "failed while setting attributes" -# define FAILED_SAVEING_CONFIG "failed while saving configuration" - -/* Target List */ -# define FAILED_LIST "failed in list" -# define FAILED_LIST_BACKEND "failed while listing glfs backends" - -/* Target Info */ -# define FAILED_INFO "failed in info" -# define FAILED_GATHERING_INFO "failed while gathering target info" - -/* Target get cfgstring */ -# define FAILED_GATHERING_CFGSTR "failed while gathering backend cfgstring" - -/* Target Delete */ -# define FAILED_DELETE "failed in delete" -# define FAILED_DELETING_BACKEND "failed while deleting glfs backend" -# define FAILED_DELETING_IQN "failed while deleting IQN" -# define FAILED_DELETING_FILE "failed while deleting block file from gluster volume" - - -# define ERROR(fmt, ...) \ - do { \ - fprintf(stderr, "Error: " fmt " [at %s+%d :<%s>]\n", \ - __VA_ARGS__, __FILE__, __LINE__, __FUNCTION__); \ - } while (0) - -# define MSG(fmt, ...) \ - do { \ - fprintf(stdout, fmt, __VA_ARGS__); \ - } while (0) - -# define LOG(str, level, fmt, ...) \ - do { \ - FILE *fd; \ - if (!strcmp(str, "mgmt")) \ - fd = fopen (DAEMON_LOG_FILE, "a"); \ - else if (strcmp(str, "cli")) \ - fd = fopen (CLI_LOG_FILE, "a"); \ - else if (strcmp(str, "gfapi")) \ - fd = fopen (GFAPI_LOG_FILE, "a"); \ - else \ - fd = stderr; \ - fprintf(fd, "[%lu] %s: " fmt " [at %s+%d :<%s>]\n", \ - (unsigned long)time(NULL), LogLevelLookup[level],\ - __VA_ARGS__, __FILE__, __LINE__, __FUNCTION__); \ - if (fd != stderr) \ - fclose(fd); \ - } while (0) - -# define GB_METALOCK_OR_GOTO(lkfd, volume, ret, label) \ - do { \ - struct flock lock = {0, }; \ - lock.l_type = F_WRLCK; \ - if (glfs_posix_lock (lkfd, F_SETLKW, &lock)) { \ - LOG("mgmt", GB_LOG_ERROR, "glfs_posix_lock() on " \ - "volume %s failed[%s]", volume, strerror(errno)); \ - ret = -1; \ - goto label; \ - } \ - } while (0) - -# define GB_METAUPDATE_OR_GOTO(tgmfd, fname, volume, ret, label,...)\ - do { \ - char *write; \ - if (asprintf(&write, __VA_ARGS__) < 0) { \ - ret = -1; \ - goto label; \ - } \ - if(glfs_write (tgmfd, write, strlen(write), 0) < 0) { \ - LOG("mgmt", GB_LOG_ERROR, "glfs_write(%s): on " \ - "volume %s failed[%s]", fname, volume, \ - strerror(errno)); \ - ret = -1; \ - goto label; \ - } \ - GB_FREE(write); \ - } while (0) - -# define GB_METAUNLOCK(lkfd, volume, ret) \ - do { \ - struct flock lock = {0, }; \ - lock.l_type = F_UNLCK; \ - if (glfs_posix_lock(lkfd, F_SETLK, &lock)) { \ - LOG("mgmt", GB_LOG_ERROR, "glfs_posix_lock() on " \ - "volume %s failed[%s]", volume, strerror(errno)); \ - ret = -1; \ - } \ - } while (0) - - -# define CALLOC(x) \ - calloc(1, x) - -# define GB_ALLOC_N(ptr, count) \ - gbAllocN(&(ptr), sizeof(*(ptr)), (count), \ - __FILE__, __FUNCTION__, __LINE__) \ - -# define GB_ALLOC(ptr) \ - gbAlloc(&(ptr), sizeof(*(ptr)), \ - __FILE__, __FUNCTION__, __LINE__) - -# define GB_STRDUP(dst, src) \ - gbStrdup(&(dst), src, \ - __FILE__, __FUNCTION__, __LINE__) - -# define GB_FREE(ptr) \ - gbFree(1 ? (void *) &(ptr) : (ptr)) - - -typedef enum gbCmdlineCreateOption { - /* needed by create option */ - GB_CLI_CREATE_VOLUME = 11, - GB_CLI_CREATE_VOLSERVER = 12, /* optional (default: localhost)*/ - GB_CLI_CREATE_SIZE = 13, - GB_CLI_CREATE_MULTIPATH = 14, - GB_CLI_CREATE_BACKEND_SERVESRS = 15, - - GB_CLI_CREATE_OPT_MAX -} gbCmdlineCreateOption; - - -typedef enum gbCmdlineCommonOption { - /* common to all the cli options */ - GB_CLI_COMMON_VOLUME = 21, - - GB_CLI_COMMON_OPT_MAX -} gbCmdlineCommonOption; - - -typedef enum gbCmdlineOption { - GB_CLI_UNKNOWN = 0, - - GB_CLI_CREATE = 1, - GB_CLI_LIST = 2, - GB_CLI_INFO = 3, - GB_CLI_DELETE = 4, - GB_CLI_MODIFY = 5, - GB_CLI_HELP = 6, - - GB_CLI_OPT_MAX -} gbCmdlineOption; - - -static const char *const gbCmdlineOptLookup[] = { - [GB_CLI_UNKNOWN] = "NONE", - - [GB_CLI_CREATE] = "create", - [GB_CLI_LIST] = "list", - [GB_CLI_INFO] = "info", - [GB_CLI_DELETE] = "delete", - [GB_CLI_MODIFY] = "modify", - [GB_CLI_HELP] = "help", - - [GB_CLI_OPT_MAX] = NULL, -}; - -static const char *const gbCmdlineCreateOptLookup[] = { - [GB_CLI_CREATE_VOLUME] = "volume", - [GB_CLI_CREATE_VOLSERVER] = "volserver", - [GB_CLI_CREATE_SIZE] = "size", - [GB_CLI_CREATE_MULTIPATH] = "mpath", - [GB_CLI_CREATE_BACKEND_SERVESRS] = "backend-servers", - - - [GB_CLI_CREATE_OPT_MAX] = NULL -}; - -static const char *const gbCmdlineCommonOptLookup[] = { - [GB_CLI_COMMON_VOLUME] = "volume", - - [GB_CLI_COMMON_OPT_MAX] = NULL -}; - -typedef enum LogLevel { - GB_LOG_NONE = 0, - GB_LOG_EMERGENCY = 1, - GB_LOG_ALERT = 2, - GB_LOG_CRITICAL = 3, - GB_LOG_ERROR = 4, - GB_LOG_WARNING = 5, - GB_LOG_NOTICE = 6, - GB_LOG_INFO = 7, - GB_LOG_DEBUG = 8, - GB_LOG_TRACE = 9, - - GB_LOG_MAX -} LogLevel; - -static const char *const LogLevelLookup[] = { - [GB_LOG_NONE] = "NONE", - [GB_LOG_EMERGENCY] = "EMERGENCY", - [GB_LOG_ALERT] = "ALERT", - [GB_LOG_CRITICAL] = "CRITICAL", - [GB_LOG_ERROR] = "ERROR", - [GB_LOG_WARNING] = "WARNING", - [GB_LOG_NOTICE] = "NOTICE", - [GB_LOG_INFO] = "INFO", - [GB_LOG_DEBUG] = "DEBUG", - [GB_LOG_TRACE] = "TRACE", - - [GB_LOG_MAX] = NULL, -}; - -typedef enum Metakey { - GB_META_VOLUME = 0, - GB_META_GBID = 1, - GB_META_SIZE = 2, - GB_META_HA = 3, - GB_META_ENTRYCREATE = 4, - - GB_METAKEY_MAX -} Metakey; - -static const char *const MetakeyLookup[] = { - [GB_META_VOLUME] = "VOLUME", - [GB_META_GBID] = "GBID", - [GB_META_SIZE] = "SIZE", - [GB_META_HA] = "HA", - [GB_META_ENTRYCREATE] = "ENTRYCREATE", - - [GB_METAKEY_MAX] = NULL -}; - -typedef enum MetaStatus { - GB_CONFIG_SUCCESS = 0, - GB_CONFIG_FAIL = 1, - GB_CONFIG_INPROGRESS = 2, - GB_CLEANUP_SUCCESS = 3, - GB_CLEANUP_FAIL = 4, - GB_CLEANUP_INPROGRES = 5, - - GB_METASTATUS_MAX -} MetaStatus; - -static const char *const MetaStatusLookup[] = { - [GB_CONFIG_SUCCESS] = "CONFIGSUCCESS", - [GB_CONFIG_FAIL] = "CONFIGFAIL", - [GB_CONFIG_INPROGRESS] = "CONFIGINPROGRESS", - [GB_CLEANUP_INPROGRES] = "CLEANUPINPROGRESS", - [GB_CLEANUP_SUCCESS] = "CLEANUPSUCCESS", - [GB_CLEANUP_FAIL] = "CLEANUPFAIL", - - [GB_METASTATUS_MAX] = NULL, -}; - - -int glusterBlockCLIOptEnumParse(const char *opt); - -int glusterBlockCLICreateOptEnumParse(const char *opt); - -int glusterBlockCLICommonOptEnumParse(const char *opt); - -int blockMetaKeyEnumParse(const char *opt); - -int blockMetaStatusEnumParse(const char *opt); - -int gbAlloc(void *ptrptr, size_t size, - const char *filename, const char *funcname, size_t linenr); - -int gbAllocN(void *ptrptr, size_t size, size_t count, - const char *filename, const char *funcname, size_t linenr); - -int gbStrdup(char **dest, const char *src, - const char *filename, const char *funcname, size_t linenr); - -void gbFree(void *ptrptr); - -#endif /* _UTILS_H */ diff --git a/utils/Makefile.am b/utils/Makefile.am new file mode 100644 index 0000000..461c73c --- /dev/null +++ b/utils/Makefile.am @@ -0,0 +1,11 @@ +noinst_LTLIBRARIES = libgb.la + +libgb_la_SOURCES = common.c utils.c + +noinst_HEADERS = common.h utils.h + +libgb_ladir = $(includedir)/gluster-block/utils + +DISTCLEANFILES = Makefile.in + +CLEANFILES = *~ diff --git a/utils/common.c b/utils/common.c new file mode 100644 index 0000000..dfa6bc8 --- /dev/null +++ b/utils/common.c @@ -0,0 +1,74 @@ +/* + Copyright (c) 2016 Red Hat, Inc. + This file is part of gluster-block. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +# include "common.h" + + + +ssize_t +glusterBlockCreateParseSize(char *value) +{ + char *postfix; + char *tmp; + ssize_t sizef; + + + if (!value) + return -1; + + sizef = strtod(value, &postfix); + if (sizef < 0) { + ERROR("%s", "size cannot be negative number\n"); + return -1; + } + + tmp = postfix; + if (*postfix == ' ') { + tmp = tmp + 1; + } + + switch (*tmp) { + case 'Y': + sizef *= 1024; + /* fall through */ + case 'Z': + sizef *= 1024; + /* fall through */ + case 'E': + sizef *= 1024; + /* fall through */ + case 'P': + sizef *= 1024; + /* fall through */ + case 'T': + sizef *= 1024; + /* fall through */ + case 'G': + sizef *= 1024; + /* fall through */ + case 'M': + sizef *= 1024; + /* fall through */ + case 'K': + case 'k': + sizef *= 1024; + /* fall through */ + case 'b': + case '\0': + return sizef; + break; + default: + /*TODO: Log this instead of printing + ERROR("%s", "You may use k/K, M, G or T suffixes for " + "kilobytes, megabytes, gigabytes and terabytes."); */ + return -1; + } +} diff --git a/utils/common.h b/utils/common.h new file mode 100644 index 0000000..6b0983d --- /dev/null +++ b/utils/common.h @@ -0,0 +1,26 @@ +/* + Copyright (c) 2016 Red Hat, Inc. + This file is part of gluster-block. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +# ifndef _COMMON_H +# define _COMMON_H 1 + +# include "utils.h" + +# define DAEMON_LOG_FILE "/var/log/gluster-block/gluster-blockd.log" +# define CLI_LOG_FILE "/var/log/gluster-block/gluster-block-cli.log" + +# define GFAPI_LOG_FILE "/var/log/gluster-block/gluster-block-gfapi.log" +# define GFAPI_LOG_LEVEL 7 + + +ssize_t glusterBlockCreateParseSize(char *value); + +# endif /* _COMMON_H */ diff --git a/utils/utils.c b/utils/utils.c new file mode 100644 index 0000000..a43a347 --- /dev/null +++ b/utils/utils.c @@ -0,0 +1,179 @@ +/* + Copyright (c) 2016 Red Hat, Inc. + This file is part of gluster-block. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +# include "utils.h" + + + +int +glusterBlockCLIOptEnumParse(const char *opt) +{ + int i; + + + if (!opt) { + return GB_CLI_OPT_MAX; + } + + for (i = 0; i < GB_CLI_OPT_MAX; i++) { + if (!strcmp(opt, gbCmdlineOptLookup[i])) { + return i; + } + } + + return i; +} + + +int +glusterBlockCLICreateOptEnumParse(const char *opt) +{ + int i; + + + if (!opt) { + return GB_CLI_CREATE_OPT_MAX; + } + + /* i = 11, enum start look gbCmdlineCreateOption */ + for (i = 11; i < GB_CLI_CREATE_OPT_MAX; i++) { + if (!strcmp(opt, gbCmdlineCreateOptLookup[i])) { + return i; + } + } + + return i; +} + + +int +glusterBlockCLICommonOptEnumParse(const char *opt) +{ + int i; + + + if (!opt) { + return GB_CLI_COMMON_OPT_MAX; + } + + /* i = 21, enum start look gbCmdlineCreateOption */ + for (i = 21; i < GB_CLI_COMMON_OPT_MAX; i++) { + if (!strcmp(opt, gbCmdlineCommonOptLookup[i])) { + return i; + } + } + + return i; +} + + +int +blockMetaKeyEnumParse(const char *opt) +{ + int i; + + + if (!opt) { + return GB_METAKEY_MAX; + } + + for (i = 0; i < GB_METAKEY_MAX; i++) { + if (!strcmp(opt, MetakeyLookup[i])) { + return i; + } + } + + return i; +} + + +int +blockMetaStatusEnumParse(const char *opt) +{ + int i; + + + if (!opt) { + return GB_METASTATUS_MAX; + } + + for (i = 0; i < GB_METASTATUS_MAX; i++) { + if (!strcmp(opt, MetaStatusLookup[i])) { + return i; + } + } + + return i; +} + + +int +gbAlloc(void *ptrptr, size_t size, + const char *filename, const char *funcname, size_t linenr) +{ + *(void **)ptrptr = calloc(1, size); + + if (*(void **)ptrptr == NULL) { + errno = ENOMEM; + return -1; + } + + return 0; +} + + +int +gbAllocN(void *ptrptr, size_t size, size_t count, + const char *filename, const char *funcname, size_t linenr) +{ + *(void**)ptrptr = calloc(count, size); + + if (*(void**)ptrptr == NULL) { + errno = ENOMEM; + return -1; + } + + return 0; +} + + +void +gbFree(void *ptrptr) +{ + int save_errno = errno; + + + if(*(void**)ptrptr == NULL) { + return; + } + + free(*(void**)ptrptr); + *(void**)ptrptr = NULL; + errno = save_errno; +} + + +int +gbStrdup(char **dest, const char *src, + const char *filename, const char *funcname, size_t linenr) +{ + *dest = NULL; + + if (!src) { + return 0; + } + + if (!(*dest = strdup(src))) { + return -1; + } + + return 0; +} diff --git a/utils/utils.h b/utils/utils.h new file mode 100644 index 0000000..f9763eb --- /dev/null +++ b/utils/utils.h @@ -0,0 +1,299 @@ +/* + Copyright (c) 2016 Red Hat, Inc. + This file is part of gluster-block. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +# ifndef _UTILS_H +# define _UTILS_H 1 + +# define _GNU_SOURCE /* See feature_test_macros(7) */ +# include + +# include +# include +# include +# include +# include + + +/* Target Create */ +# define FAILED_CREATE "failed in create" +# define FAILED_CREATING_FILE "failed while creating block file in gluster volume" +# define FAILED_CREATING_BACKEND "failed while creating glfs backend" +# define FAILED_CREATING_IQN "failed while creating IQN" +# define FAILED_CREATING_LUN "failed while creating LUN" +# define FAILED_SETTING_ATTRIBUTES "failed while setting attributes" +# define FAILED_SAVEING_CONFIG "failed while saving configuration" + +/* Target List */ +# define FAILED_LIST "failed in list" +# define FAILED_LIST_BACKEND "failed while listing glfs backends" + +/* Target Info */ +# define FAILED_INFO "failed in info" +# define FAILED_GATHERING_INFO "failed while gathering target info" + +/* Target get cfgstring */ +# define FAILED_GATHERING_CFGSTR "failed while gathering backend cfgstring" + +/* Target Delete */ +# define FAILED_DELETE "failed in delete" +# define FAILED_DELETING_BACKEND "failed while deleting glfs backend" +# define FAILED_DELETING_IQN "failed while deleting IQN" +# define FAILED_DELETING_FILE "failed while deleting block file from gluster volume" + + +# define ERROR(fmt, ...) \ + do { \ + fprintf(stderr, "Error: " fmt " [at %s+%d :<%s>]\n", \ + __VA_ARGS__, __FILE__, __LINE__, __FUNCTION__); \ + } while (0) + +# define MSG(fmt, ...) \ + do { \ + fprintf(stdout, fmt, __VA_ARGS__); \ + } while (0) + +# define LOG(str, level, fmt, ...) \ + do { \ + FILE *fd; \ + if (!strcmp(str, "mgmt")) \ + fd = fopen (DAEMON_LOG_FILE, "a"); \ + else if (strcmp(str, "cli")) \ + fd = fopen (CLI_LOG_FILE, "a"); \ + else if (strcmp(str, "gfapi")) \ + fd = fopen (GFAPI_LOG_FILE, "a"); \ + else \ + fd = stderr; \ + fprintf(fd, "[%lu] %s: " fmt " [at %s+%d :<%s>]\n", \ + (unsigned long)time(NULL), LogLevelLookup[level],\ + __VA_ARGS__, __FILE__, __LINE__, __FUNCTION__); \ + if (fd != stderr) \ + fclose(fd); \ + } while (0) + +# define GB_METALOCK_OR_GOTO(lkfd, volume, ret, label) \ + do { \ + struct flock lock = {0, }; \ + lock.l_type = F_WRLCK; \ + if (glfs_posix_lock (lkfd, F_SETLKW, &lock)) { \ + LOG("mgmt", GB_LOG_ERROR, "glfs_posix_lock() on " \ + "volume %s failed[%s]", volume, strerror(errno)); \ + ret = -1; \ + goto label; \ + } \ + } while (0) + +# define GB_METAUPDATE_OR_GOTO(tgmfd, fname, volume, ret, label,...)\ + do { \ + char *write; \ + if (asprintf(&write, __VA_ARGS__) < 0) { \ + ret = -1; \ + goto label; \ + } \ + if(glfs_write (tgmfd, write, strlen(write), 0) < 0) { \ + LOG("mgmt", GB_LOG_ERROR, "glfs_write(%s): on " \ + "volume %s failed[%s]", fname, volume, \ + strerror(errno)); \ + ret = -1; \ + goto label; \ + } \ + GB_FREE(write); \ + } while (0) + +# define GB_METAUNLOCK(lkfd, volume, ret) \ + do { \ + struct flock lock = {0, }; \ + lock.l_type = F_UNLCK; \ + if (glfs_posix_lock(lkfd, F_SETLK, &lock)) { \ + LOG("mgmt", GB_LOG_ERROR, "glfs_posix_lock() on " \ + "volume %s failed[%s]", volume, strerror(errno)); \ + ret = -1; \ + } \ + } while (0) + + +# define CALLOC(x) \ + calloc(1, x) + +# define GB_ALLOC_N(ptr, count) \ + gbAllocN(&(ptr), sizeof(*(ptr)), (count), \ + __FILE__, __FUNCTION__, __LINE__) \ + +# define GB_ALLOC(ptr) \ + gbAlloc(&(ptr), sizeof(*(ptr)), \ + __FILE__, __FUNCTION__, __LINE__) + +# define GB_STRDUP(dst, src) \ + gbStrdup(&(dst), src, \ + __FILE__, __FUNCTION__, __LINE__) + +# define GB_FREE(ptr) \ + gbFree(1 ? (void *) &(ptr) : (ptr)) + + +typedef enum gbCmdlineCreateOption { + /* needed by create option */ + GB_CLI_CREATE_VOLUME = 11, + GB_CLI_CREATE_VOLSERVER = 12, /* optional (default: localhost)*/ + GB_CLI_CREATE_SIZE = 13, + GB_CLI_CREATE_MULTIPATH = 14, + GB_CLI_CREATE_BACKEND_SERVESRS = 15, + + GB_CLI_CREATE_OPT_MAX +} gbCmdlineCreateOption; + + +typedef enum gbCmdlineCommonOption { + /* common to all the cli options */ + GB_CLI_COMMON_VOLUME = 21, + + GB_CLI_COMMON_OPT_MAX +} gbCmdlineCommonOption; + + +typedef enum gbCmdlineOption { + GB_CLI_UNKNOWN = 0, + + GB_CLI_CREATE = 1, + GB_CLI_LIST = 2, + GB_CLI_INFO = 3, + GB_CLI_DELETE = 4, + GB_CLI_MODIFY = 5, + GB_CLI_HELP = 6, + + GB_CLI_OPT_MAX +} gbCmdlineOption; + + +static const char *const gbCmdlineOptLookup[] = { + [GB_CLI_UNKNOWN] = "NONE", + + [GB_CLI_CREATE] = "create", + [GB_CLI_LIST] = "list", + [GB_CLI_INFO] = "info", + [GB_CLI_DELETE] = "delete", + [GB_CLI_MODIFY] = "modify", + [GB_CLI_HELP] = "help", + + [GB_CLI_OPT_MAX] = NULL, +}; + +static const char *const gbCmdlineCreateOptLookup[] = { + [GB_CLI_CREATE_VOLUME] = "volume", + [GB_CLI_CREATE_VOLSERVER] = "volserver", + [GB_CLI_CREATE_SIZE] = "size", + [GB_CLI_CREATE_MULTIPATH] = "mpath", + [GB_CLI_CREATE_BACKEND_SERVESRS] = "backend-servers", + + + [GB_CLI_CREATE_OPT_MAX] = NULL +}; + +static const char *const gbCmdlineCommonOptLookup[] = { + [GB_CLI_COMMON_VOLUME] = "volume", + + [GB_CLI_COMMON_OPT_MAX] = NULL +}; + +typedef enum LogLevel { + GB_LOG_NONE = 0, + GB_LOG_EMERGENCY = 1, + GB_LOG_ALERT = 2, + GB_LOG_CRITICAL = 3, + GB_LOG_ERROR = 4, + GB_LOG_WARNING = 5, + GB_LOG_NOTICE = 6, + GB_LOG_INFO = 7, + GB_LOG_DEBUG = 8, + GB_LOG_TRACE = 9, + + GB_LOG_MAX +} LogLevel; + +static const char *const LogLevelLookup[] = { + [GB_LOG_NONE] = "NONE", + [GB_LOG_EMERGENCY] = "EMERGENCY", + [GB_LOG_ALERT] = "ALERT", + [GB_LOG_CRITICAL] = "CRITICAL", + [GB_LOG_ERROR] = "ERROR", + [GB_LOG_WARNING] = "WARNING", + [GB_LOG_NOTICE] = "NOTICE", + [GB_LOG_INFO] = "INFO", + [GB_LOG_DEBUG] = "DEBUG", + [GB_LOG_TRACE] = "TRACE", + + [GB_LOG_MAX] = NULL, +}; + +typedef enum Metakey { + GB_META_VOLUME = 0, + GB_META_GBID = 1, + GB_META_SIZE = 2, + GB_META_HA = 3, + GB_META_ENTRYCREATE = 4, + + GB_METAKEY_MAX +} Metakey; + +static const char *const MetakeyLookup[] = { + [GB_META_VOLUME] = "VOLUME", + [GB_META_GBID] = "GBID", + [GB_META_SIZE] = "SIZE", + [GB_META_HA] = "HA", + [GB_META_ENTRYCREATE] = "ENTRYCREATE", + + [GB_METAKEY_MAX] = NULL +}; + +typedef enum MetaStatus { + GB_CONFIG_SUCCESS = 0, + GB_CONFIG_FAIL = 1, + GB_CONFIG_INPROGRESS = 2, + GB_CLEANUP_SUCCESS = 3, + GB_CLEANUP_FAIL = 4, + GB_CLEANUP_INPROGRES = 5, + + GB_METASTATUS_MAX +} MetaStatus; + +static const char *const MetaStatusLookup[] = { + [GB_CONFIG_SUCCESS] = "CONFIGSUCCESS", + [GB_CONFIG_FAIL] = "CONFIGFAIL", + [GB_CONFIG_INPROGRESS] = "CONFIGINPROGRESS", + [GB_CLEANUP_INPROGRES] = "CLEANUPINPROGRESS", + [GB_CLEANUP_SUCCESS] = "CLEANUPSUCCESS", + [GB_CLEANUP_FAIL] = "CLEANUPFAIL", + + [GB_METASTATUS_MAX] = NULL, +}; + + +int glusterBlockCLIOptEnumParse(const char *opt); + +int glusterBlockCLICreateOptEnumParse(const char *opt); + +int glusterBlockCLICommonOptEnumParse(const char *opt); + +int blockMetaKeyEnumParse(const char *opt); + +int blockMetaStatusEnumParse(const char *opt); + +int gbAlloc(void *ptrptr, size_t size, + const char *filename, const char *funcname, size_t linenr); + +int gbAllocN(void *ptrptr, size_t size, size_t count, + const char *filename, const char *funcname, size_t linenr); + +int gbStrdup(char **dest, const char *src, + const char *filename, const char *funcname, size_t linenr); + +void gbFree(void *ptrptr); + +#endif /* _UTILS_H */ -- cgit