./PaxHeaders.5796/glusterfs-3.13.20000644000000000000000000000013213230627062014626 xustar000000000000000030 mtime=1516449330.418495406 30 atime=1516449330.837496377 30 ctime=1516449330.418495406 glusterfs-3.13.2/0002775000175100017510000000000013230627062015011 5ustar00jenkinsjenkins00000000000000glusterfs-3.13.2/PaxHeaders.5796/tools0000644000000000000000000000013213230627062015631 xustar000000000000000030 mtime=1516449330.038494525 30 atime=1516449330.837496377 30 ctime=1516449330.038494525 glusterfs-3.13.2/tools/0002775000175100017510000000000013230627062016151 5ustar00jenkinsjenkins00000000000000glusterfs-3.13.2/tools/PaxHeaders.5796/Makefile.am0000644000000000000000000000013213230626775017754 xustar000000000000000030 mtime=1516449277.363372344 30 atime=1516449286.686393975 30 ctime=1516449329.778493922 glusterfs-3.13.2/tools/Makefile.am0000664000175100017510000000010513230626775020211 0ustar00jenkinsjenkins00000000000000SUBDIRS = gfind_missing_files glusterfind setgfid2path CLEANFILES = glusterfs-3.13.2/tools/PaxHeaders.5796/setgfid2path0000644000000000000000000000013213230627062020215 xustar000000000000000030 mtime=1516449330.103494676 30 atime=1516449330.837496377 30 ctime=1516449330.103494676 glusterfs-3.13.2/tools/setgfid2path/0002775000175100017510000000000013230627062020535 5ustar00jenkinsjenkins00000000000000glusterfs-3.13.2/tools/setgfid2path/PaxHeaders.5796/Makefile.am0000644000000000000000000000013113230626775022337 xustar000000000000000030 mtime=1516449277.366372351 30 atime=1516449286.846394346 29 ctime=1516449330.09249465 glusterfs-3.13.2/tools/setgfid2path/Makefile.am0000664000175100017510000000012713230626775022601 0ustar00jenkinsjenkins00000000000000SUBDIRS = src EXTRA_DIST = gluster-setgfid2path.8 man8_MANS = gluster-setgfid2path.8 glusterfs-3.13.2/tools/setgfid2path/PaxHeaders.5796/src0000644000000000000000000000013213230627062021004 xustar000000000000000030 mtime=1516449330.166494822 30 atime=1516449330.837496377 30 ctime=1516449330.166494822 glusterfs-3.13.2/tools/setgfid2path/src/0002775000175100017510000000000013230627062021324 5ustar00jenkinsjenkins00000000000000glusterfs-3.13.2/tools/setgfid2path/src/PaxHeaders.5796/Makefile.am0000644000000000000000000000013113230626775023126 xustar000000000000000030 mtime=1516449277.366372351 29 atime=1516449286.88239443 30 ctime=1516449330.164494817 glusterfs-3.13.2/tools/setgfid2path/src/Makefile.am0000664000175100017510000000057713230626775023401 0ustar00jenkinsjenkins00000000000000gluster_setgfid2pathdir = $(sbindir) gluster_setgfid2path_PROGRAMS = gluster-setgfid2path gluster_setgfid2path_SOURCES = main.c gluster_setgfid2path_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la gluster_setgfid2path_LDFLAGS = $(GF_LDFLAGS) AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ -I$(top_builddir)/rpc/xdr/src AM_CFLAGS = -Wall $(GF_CFLAGS) glusterfs-3.13.2/tools/setgfid2path/src/PaxHeaders.5796/main.c0000644000000000000000000000013213230626775022163 xustar000000000000000030 mtime=1516449277.367372353 30 atime=1516449277.366372351 30 ctime=1516449330.166494822 glusterfs-3.13.2/tools/setgfid2path/src/main.c0000664000175100017510000001072113230626775022425 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2017 Red Hat, Inc. This file is part of GlusterFS. 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 "common-utils.h" #include "syscall.h" #define MAX_GFID2PATH_LINK_SUP 500 #define GFID_SIZE 16 #define GFID_XATTR_KEY "trusted.gfid" int main(int argc, char **argv) { int ret = 0; struct stat st; char *dname = NULL; char *bname = NULL; ssize_t ret_size = 0; uuid_t pgfid_raw = {0,}; char pgfid[36] = ""; char xxh64[GF_XXH64_DIGEST_LENGTH*2+1] = {0,}; char pgfid_bname[1024] = {0,}; char *key = NULL; char *val = NULL; size_t key_size = 0; size_t val_size = 0; const char *file_path = NULL; char *file_path1 = NULL; char *file_path2 = NULL; if (argc != 2) { fprintf (stderr, "Usage: setgfid2path \n"); return -1; } ret = sys_lstat (argv[1], &st); if (ret != 0) { fprintf (stderr, "Invalid File Path\n"); return -1; } if (st.st_nlink >= MAX_GFID2PATH_LINK_SUP) { fprintf (stderr, "Number of Hardlink support exceeded. " "max=%d\n", MAX_GFID2PATH_LINK_SUP); return -1; } file_path = argv[1]; file_path1 = strdup (file_path); file_path2 = strdup (file_path); dname = dirname (file_path1); bname = basename (file_path2); /* Get GFID of Parent directory */ ret_size = sys_lgetxattr (dname, GFID_XATTR_KEY, pgfid_raw, GFID_SIZE); if (ret_size != GFID_SIZE) { fprintf (stderr, "Failed to get GFID of parent directory. dir=%s\n", dname); ret = -1; goto out; } /* Convert to UUID format */ if (uuid_utoa_r (pgfid_raw, pgfid) == NULL) { fprintf (stderr, "Failed to format GFID of parent directory. " "dir=%s GFID=%s\n", dname, pgfid_raw); ret = -1; goto out; } /* Find xxhash for PGFID/BaseName */ snprintf (pgfid_bname, sizeof (pgfid_bname), "%s/%s", pgfid, bname); gf_xxh64_wrapper ( (unsigned char *)pgfid_bname, strlen (pgfid_bname), GF_XXHSUM64_DEFAULT_SEED, xxh64 ); key_size = strlen(GFID2PATH_XATTR_KEY_PREFIX) + GF_XXH64_DIGEST_LENGTH*2+1; key = alloca (key_size); snprintf (key, key_size, GFID2PATH_XATTR_KEY_PREFIX"%s", xxh64); val_size = UUID_CANONICAL_FORM_LEN + NAME_MAX + 2; val = alloca (val_size); snprintf (val, val_size, "%s/%s", pgfid, bname); /* Set the Xattr, ignore if same key xattr already exists */ ret = sys_lsetxattr (file_path, key, val, strlen(val), XATTR_CREATE); if (ret == -1) { if (errno == EEXIST) { printf ("Xattr already exists, ignoring..\n"); ret = 0; goto out; } fprintf (stderr, "Failed to set gfid2path xattr. errno=%d\n error=%s", errno, strerror(errno)); ret = -1; goto out; } printf ("Success. file=%s key=%s value=%s\n", file_path, key, val); out: if (file_path1 != NULL) free (file_path1); if (file_path2 != NULL) free (file_path2); return ret; } glusterfs-3.13.2/tools/setgfid2path/src/PaxHeaders.5796/Makefile.in0000644000000000000000000000013113230627006023123 xustar000000000000000030 mtime=1516449286.916394508 30 atime=1516449311.229450906 29 ctime=1516449330.16149481 glusterfs-3.13.2/tools/setgfid2path/src/Makefile.in0000664000175100017510000005674413230627006023405 0ustar00jenkinsjenkins00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ gluster_setgfid2path_PROGRAMS = gluster-setgfid2path$(EXEEXT) subdir = tools/setgfid2path/src DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/contrib/aclocal/mkdirp.m4 \ $(top_srcdir)/contrib/aclocal/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h $(top_builddir)/site.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(gluster_setgfid2pathdir)" PROGRAMS = $(gluster_setgfid2path_PROGRAMS) am_gluster_setgfid2path_OBJECTS = main.$(OBJEXT) gluster_setgfid2path_OBJECTS = $(am_gluster_setgfid2path_OBJECTS) gluster_setgfid2path_DEPENDENCIES = \ $(top_builddir)/libglusterfs/src/libglusterfs.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = gluster_setgfid2path_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(gluster_setgfid2path_LDFLAGS) \ $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(gluster_setgfid2path_SOURCES) DIST_SOURCES = $(gluster_setgfid2path_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACL_LIBS = @ACL_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LIBTOOLFLAGS = @AM_LIBTOOLFLAGS@ AM_MAKEFLAGS = @AM_MAKEFLAGS@ AR = @AR@ ARGP_STANDALONE_CPPFLAGS = @ARGP_STANDALONE_CPPFLAGS@ ARGP_STANDALONE_DIR = @ARGP_STANDALONE_DIR@ ARGP_STANDALONE_LDADD = @ARGP_STANDALONE_LDADD@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_PYTHON_INC = @BUILD_PYTHON_INC@ BUILD_PYTHON_LIB = @BUILD_PYTHON_LIB@ BUILD_PYTHON_SITE_PACKAGES = @BUILD_PYTHON_SITE_PACKAGES@ BUILD_PYTHON_SITE_PACKAGES_EXPANDED = @BUILD_PYTHON_SITE_PACKAGES_EXPANDED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONTRIBDIR = @CONTRIBDIR@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EVENTS_ENABLED = @EVENTS_ENABLED@ EVENTS_SUBDIR = @EVENTS_SUBDIR@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FUSERMOUNT_SUBDIR = @FUSERMOUNT_SUBDIR@ FUSE_CLIENT_SUBDIR = @FUSE_CLIENT_SUBDIR@ GEOREP_EXTRAS_SUBDIR = @GEOREP_EXTRAS_SUBDIR@ GFAPI_EXTRA_LDFLAGS = @GFAPI_EXTRA_LDFLAGS@ GFAPI_LIBS = @GFAPI_LIBS@ GFAPI_LT_VERSION = @GFAPI_LT_VERSION@ GFAPI_VERSION = @GFAPI_VERSION@ GF_CFLAGS = @GF_CFLAGS@ GF_CPPFLAGS = @GF_CPPFLAGS@ GF_DISTRIBUTION = @GF_DISTRIBUTION@ GF_FUSE_CFLAGS = @GF_FUSE_CFLAGS@ GF_FUSE_LDADD = @GF_FUSE_LDADD@ GF_HOST_OS = @GF_HOST_OS@ GF_LDADD = @GF_LDADD@ GF_LDFLAGS = @GF_LDFLAGS@ GF_XLATOR_DEFAULT_LDFLAGS = @GF_XLATOR_DEFAULT_LDFLAGS@ GLUPY_SUBDIR = @GLUPY_SUBDIR@ GLUPY_SUBDIR_MAKEFILE = @GLUPY_SUBDIR_MAKEFILE@ GLUPY_SUBDIR_SRC_MAKEFILE = @GLUPY_SUBDIR_SRC_MAKEFILE@ GLUSTERD_VOLFILE = @GLUSTERD_VOLFILE@ GLUSTERD_WORKDIR = @GLUSTERD_WORKDIR@ GLUSTERFSD_MISCDIR = @GLUSTERFSD_MISCDIR@ GLUSTERFS_LIBEXECDIR = @GLUSTERFS_LIBEXECDIR@ GREP = @GREP@ HAVE_ATOMIC_BUILTINS = @HAVE_ATOMIC_BUILTINS@ HAVE_BACKTRACE = @HAVE_BACKTRACE@ HAVE_LINKAT = @HAVE_LINKAT@ HAVE_MALLOC_STATS = @HAVE_MALLOC_STATS@ HAVE_SPINLOCK = @HAVE_SPINLOCK@ HAVE_STRNLEN = @HAVE_STRNLEN@ HAVE_SYNC_BUILTINS = @HAVE_SYNC_BUILTINS@ IBVERBS_SUBDIR = @IBVERBS_SUBDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBAIO = @LIBAIO@ LIBGFCHANGELOG_LT_VERSION = @LIBGFCHANGELOG_LT_VERSION@ LIBGFCHANGELOG_VERSION = @LIBGFCHANGELOG_VERSION@ LIBGFDB_VERSION = @LIBGFDB_VERSION@ LIBGFRPC_LT_VERSION = @LIBGFRPC_LT_VERSION@ LIBGFXDR_LT_VERSION = @LIBGFXDR_LT_VERSION@ LIBGLUSTERFS_LT_VERSION = @LIBGLUSTERFS_LT_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OCF_SUBDIR = @OCF_SUBDIR@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_RELEASE = @PACKAGE_RELEASE@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKGCONFIG_UUID = @PKGCONFIG_UUID@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHONDEV_CPPFLAGS = @PYTHONDEV_CPPFLAGS@ PYTHONDEV_LDFLAGS = @PYTHONDEV_LDFLAGS@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDMA_SUBDIR = @RDMA_SUBDIR@ RLLIBS = @RLLIBS@ RPCGEN = @RPCGEN@ SBIN_DIR = @SBIN_DIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SIZEOF_INT = @SIZEOF_INT@ SIZEOF_LONG = @SIZEOF_LONG@ SIZEOF_LONG_LONG = @SIZEOF_LONG_LONG@ SIZEOF_SHORT = @SIZEOF_SHORT@ SQLITE_CFLAGS = @SQLITE_CFLAGS@ SQLITE_LIBS = @SQLITE_LIBS@ STRIP = @STRIP@ SYNCDAEMON_COMPILE = @SYNCDAEMON_COMPILE@ SYNCDAEMON_SUBDIR = @SYNCDAEMON_SUBDIR@ SYSCONF_DIR = @SYSCONF_DIR@ UMOUNTD_SUBDIR = @UMOUNTD_SUBDIR@ UNITTEST_CFLAGS = @UNITTEST_CFLAGS@ UNITTEST_LDFLAGS = @UNITTEST_LDFLAGS@ UNITTEST_LIBS = @UNITTEST_LIBS@ URCU_CDS_CFLAGS = @URCU_CDS_CFLAGS@ URCU_CDS_LIBS = @URCU_CDS_LIBS@ URCU_CFLAGS = @URCU_CFLAGS@ URCU_LIBS = @URCU_LIBS@ USE_EC_DYNAMIC_AVX = @USE_EC_DYNAMIC_AVX@ USE_EC_DYNAMIC_NEON = @USE_EC_DYNAMIC_NEON@ USE_EC_DYNAMIC_SSE = @USE_EC_DYNAMIC_SSE@ USE_EC_DYNAMIC_X64 = @USE_EC_DYNAMIC_X64@ USE_POSIX_ACLS = @USE_POSIX_ACLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ initdir = @initdir@ install_sh = @install_sh@ launchddir = @launchddir@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mountutildir = @mountutildir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ shrext_cmds = @shrext_cmds@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ systemddir = @systemddir@ target_alias = @target_alias@ tmpfilesdir = @tmpfilesdir@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ gluster_setgfid2pathdir = $(sbindir) gluster_setgfid2path_SOURCES = main.c gluster_setgfid2path_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la gluster_setgfid2path_LDFLAGS = $(GF_LDFLAGS) AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ -I$(top_builddir)/rpc/xdr/src AM_CFLAGS = -Wall $(GF_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tools/setgfid2path/src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tools/setgfid2path/src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-gluster_setgfid2pathPROGRAMS: $(gluster_setgfid2path_PROGRAMS) @$(NORMAL_INSTALL) @list='$(gluster_setgfid2path_PROGRAMS)'; test -n "$(gluster_setgfid2pathdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(gluster_setgfid2pathdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(gluster_setgfid2pathdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(gluster_setgfid2pathdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(gluster_setgfid2pathdir)$$dir" || exit $$?; \ } \ ; done uninstall-gluster_setgfid2pathPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(gluster_setgfid2path_PROGRAMS)'; test -n "$(gluster_setgfid2pathdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(gluster_setgfid2pathdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(gluster_setgfid2pathdir)" && rm -f $$files clean-gluster_setgfid2pathPROGRAMS: @list='$(gluster_setgfid2path_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gluster-setgfid2path$(EXEEXT): $(gluster_setgfid2path_OBJECTS) $(gluster_setgfid2path_DEPENDENCIES) $(EXTRA_gluster_setgfid2path_DEPENDENCIES) @rm -f gluster-setgfid2path$(EXEEXT) $(AM_V_CCLD)$(gluster_setgfid2path_LINK) $(gluster_setgfid2path_OBJECTS) $(gluster_setgfid2path_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(gluster_setgfid2pathdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-gluster_setgfid2pathPROGRAMS \ clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-gluster_setgfid2pathPROGRAMS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-gluster_setgfid2pathPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-gluster_setgfid2pathPROGRAMS clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-gluster_setgfid2pathPROGRAMS \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-gluster_setgfid2pathPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: glusterfs-3.13.2/tools/setgfid2path/PaxHeaders.5796/Makefile.in0000644000000000000000000000013213230627006022335 xustar000000000000000030 mtime=1516449286.872394406 30 atime=1516449311.202450844 30 ctime=1516449330.089494643 glusterfs-3.13.2/tools/setgfid2path/Makefile.in0000664000175100017510000006077313230627006022613 0ustar00jenkinsjenkins00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tools/setgfid2path DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/contrib/aclocal/mkdirp.m4 \ $(top_srcdir)/contrib/aclocal/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h $(top_builddir)/site.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man8dir = $(mandir)/man8 am__installdirs = "$(DESTDIR)$(man8dir)" NROFF = nroff MANS = $(man8_MANS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ACL_LIBS = @ACL_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LIBTOOLFLAGS = @AM_LIBTOOLFLAGS@ AM_MAKEFLAGS = @AM_MAKEFLAGS@ AR = @AR@ ARGP_STANDALONE_CPPFLAGS = @ARGP_STANDALONE_CPPFLAGS@ ARGP_STANDALONE_DIR = @ARGP_STANDALONE_DIR@ ARGP_STANDALONE_LDADD = @ARGP_STANDALONE_LDADD@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_PYTHON_INC = @BUILD_PYTHON_INC@ BUILD_PYTHON_LIB = @BUILD_PYTHON_LIB@ BUILD_PYTHON_SITE_PACKAGES = @BUILD_PYTHON_SITE_PACKAGES@ BUILD_PYTHON_SITE_PACKAGES_EXPANDED = @BUILD_PYTHON_SITE_PACKAGES_EXPANDED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONTRIBDIR = @CONTRIBDIR@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EVENTS_ENABLED = @EVENTS_ENABLED@ EVENTS_SUBDIR = @EVENTS_SUBDIR@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FUSERMOUNT_SUBDIR = @FUSERMOUNT_SUBDIR@ FUSE_CLIENT_SUBDIR = @FUSE_CLIENT_SUBDIR@ GEOREP_EXTRAS_SUBDIR = @GEOREP_EXTRAS_SUBDIR@ GFAPI_EXTRA_LDFLAGS = @GFAPI_EXTRA_LDFLAGS@ GFAPI_LIBS = @GFAPI_LIBS@ GFAPI_LT_VERSION = @GFAPI_LT_VERSION@ GFAPI_VERSION = @GFAPI_VERSION@ GF_CFLAGS = @GF_CFLAGS@ GF_CPPFLAGS = @GF_CPPFLAGS@ GF_DISTRIBUTION = @GF_DISTRIBUTION@ GF_FUSE_CFLAGS = @GF_FUSE_CFLAGS@ GF_FUSE_LDADD = @GF_FUSE_LDADD@ GF_HOST_OS = @GF_HOST_OS@ GF_LDADD = @GF_LDADD@ GF_LDFLAGS = @GF_LDFLAGS@ GF_XLATOR_DEFAULT_LDFLAGS = @GF_XLATOR_DEFAULT_LDFLAGS@ GLUPY_SUBDIR = @GLUPY_SUBDIR@ GLUPY_SUBDIR_MAKEFILE = @GLUPY_SUBDIR_MAKEFILE@ GLUPY_SUBDIR_SRC_MAKEFILE = @GLUPY_SUBDIR_SRC_MAKEFILE@ GLUSTERD_VOLFILE = @GLUSTERD_VOLFILE@ GLUSTERD_WORKDIR = @GLUSTERD_WORKDIR@ GLUSTERFSD_MISCDIR = @GLUSTERFSD_MISCDIR@ GLUSTERFS_LIBEXECDIR = @GLUSTERFS_LIBEXECDIR@ GREP = @GREP@ HAVE_ATOMIC_BUILTINS = @HAVE_ATOMIC_BUILTINS@ HAVE_BACKTRACE = @HAVE_BACKTRACE@ HAVE_LINKAT = @HAVE_LINKAT@ HAVE_MALLOC_STATS = @HAVE_MALLOC_STATS@ HAVE_SPINLOCK = @HAVE_SPINLOCK@ HAVE_STRNLEN = @HAVE_STRNLEN@ HAVE_SYNC_BUILTINS = @HAVE_SYNC_BUILTINS@ IBVERBS_SUBDIR = @IBVERBS_SUBDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBAIO = @LIBAIO@ LIBGFCHANGELOG_LT_VERSION = @LIBGFCHANGELOG_LT_VERSION@ LIBGFCHANGELOG_VERSION = @LIBGFCHANGELOG_VERSION@ LIBGFDB_VERSION = @LIBGFDB_VERSION@ LIBGFRPC_LT_VERSION = @LIBGFRPC_LT_VERSION@ LIBGFXDR_LT_VERSION = @LIBGFXDR_LT_VERSION@ LIBGLUSTERFS_LT_VERSION = @LIBGLUSTERFS_LT_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OCF_SUBDIR = @OCF_SUBDIR@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_RELEASE = @PACKAGE_RELEASE@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKGCONFIG_UUID = @PKGCONFIG_UUID@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHONDEV_CPPFLAGS = @PYTHONDEV_CPPFLAGS@ PYTHONDEV_LDFLAGS = @PYTHONDEV_LDFLAGS@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDMA_SUBDIR = @RDMA_SUBDIR@ RLLIBS = @RLLIBS@ RPCGEN = @RPCGEN@ SBIN_DIR = @SBIN_DIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SIZEOF_INT = @SIZEOF_INT@ SIZEOF_LONG = @SIZEOF_LONG@ SIZEOF_LONG_LONG = @SIZEOF_LONG_LONG@ SIZEOF_SHORT = @SIZEOF_SHORT@ SQLITE_CFLAGS = @SQLITE_CFLAGS@ SQLITE_LIBS = @SQLITE_LIBS@ STRIP = @STRIP@ SYNCDAEMON_COMPILE = @SYNCDAEMON_COMPILE@ SYNCDAEMON_SUBDIR = @SYNCDAEMON_SUBDIR@ SYSCONF_DIR = @SYSCONF_DIR@ UMOUNTD_SUBDIR = @UMOUNTD_SUBDIR@ UNITTEST_CFLAGS = @UNITTEST_CFLAGS@ UNITTEST_LDFLAGS = @UNITTEST_LDFLAGS@ UNITTEST_LIBS = @UNITTEST_LIBS@ URCU_CDS_CFLAGS = @URCU_CDS_CFLAGS@ URCU_CDS_LIBS = @URCU_CDS_LIBS@ URCU_CFLAGS = @URCU_CFLAGS@ URCU_LIBS = @URCU_LIBS@ USE_EC_DYNAMIC_AVX = @USE_EC_DYNAMIC_AVX@ USE_EC_DYNAMIC_NEON = @USE_EC_DYNAMIC_NEON@ USE_EC_DYNAMIC_SSE = @USE_EC_DYNAMIC_SSE@ USE_EC_DYNAMIC_X64 = @USE_EC_DYNAMIC_X64@ USE_POSIX_ACLS = @USE_POSIX_ACLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ initdir = @initdir@ install_sh = @install_sh@ launchddir = @launchddir@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mountutildir = @mountutildir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ shrext_cmds = @shrext_cmds@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ systemddir = @systemddir@ target_alias = @target_alias@ tmpfilesdir = @tmpfilesdir@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src EXTRA_DIST = gluster-setgfid2path.8 man8_MANS = gluster-setgfid2path.8 all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tools/setgfid2path/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tools/setgfid2path/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man8: $(man8_MANS) @$(NORMAL_INSTALL) @list1='$(man8_MANS)'; \ list2=''; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(MANS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(man8dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-man install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man8 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-man uninstall-man: uninstall-man8 .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-man8 install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-man uninstall-man8 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: glusterfs-3.13.2/tools/setgfid2path/PaxHeaders.5796/gluster-setgfid2path.80000644000000000000000000000013213230626775024444 xustar000000000000000030 mtime=1516449277.366372351 30 atime=1516449277.366372351 30 ctime=1516449330.095494657 glusterfs-3.13.2/tools/setgfid2path/gluster-setgfid2path.80000664000175100017510000000301013230626775024677 0ustar00jenkinsjenkins00000000000000 .\" Copyright (c) 2017 Red Hat, Inc. .\" This file is part of GlusterFS. .\" .\" 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. .\" .\" .TH gluster-setgfid2path 8 "Command line utility to set GFID to Path Xattrs" .SH NAME gluster-setgfid2path - Gluster tool to set GFID to Path xattrs .SH SYNOPSIS .B gluster-setgfid2path .IR file .SH DESCRIPTION New feature introduced with Gluster release 3.12, to find full path from GFID. This feature can be enabled using Volume set command \fBgluster volume set storage.gfid2path enable\fR .PP Once \fBgfid2path\fR feature is enabled, it starts recording the necessary xattrs required for the feature. But it will not add xattrs for the already existing files. This tool provides facility to update the gfid2path xattrs for the given file path. .SH EXAMPLES To add xattrs of a single file, .PP .nf .RS gluster-setgfid2path /bricks/b1/hello.txt .RE .fi .PP To set xattr for all the existing files, run the below script on each bricks. .PP .nf .RS BRICK=/bricks/b1 find $BRICK -type d \\( -path "${BRICK}/.trashcan" -o -path \\ "${BRICK}/.glusterfs" \\) -prune -o -type f \\ -exec gluster-setgfid2path {} \\; .RE .fi .PP .SH SEE ALSO .nf \fBgluster\fR(8) \fR .fi .SH COPYRIGHT .nf Copyright(c) 2017 Red Hat, Inc. glusterfs-3.13.2/tools/PaxHeaders.5796/Makefile.in0000644000000000000000000000013113230627006017750 xustar000000000000000029 mtime=1516449286.71039403 30 atime=1516449310.994450361 30 ctime=1516449329.776493917 glusterfs-3.13.2/tools/Makefile.in0000664000175100017510000005302513230627006020217 0ustar00jenkinsjenkins00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tools DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/contrib/aclocal/mkdirp.m4 \ $(top_srcdir)/contrib/aclocal/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h $(top_builddir)/site.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ACL_LIBS = @ACL_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LIBTOOLFLAGS = @AM_LIBTOOLFLAGS@ AM_MAKEFLAGS = @AM_MAKEFLAGS@ AR = @AR@ ARGP_STANDALONE_CPPFLAGS = @ARGP_STANDALONE_CPPFLAGS@ ARGP_STANDALONE_DIR = @ARGP_STANDALONE_DIR@ ARGP_STANDALONE_LDADD = @ARGP_STANDALONE_LDADD@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_PYTHON_INC = @BUILD_PYTHON_INC@ BUILD_PYTHON_LIB = @BUILD_PYTHON_LIB@ BUILD_PYTHON_SITE_PACKAGES = @BUILD_PYTHON_SITE_PACKAGES@ BUILD_PYTHON_SITE_PACKAGES_EXPANDED = @BUILD_PYTHON_SITE_PACKAGES_EXPANDED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONTRIBDIR = @CONTRIBDIR@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EVENTS_ENABLED = @EVENTS_ENABLED@ EVENTS_SUBDIR = @EVENTS_SUBDIR@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FUSERMOUNT_SUBDIR = @FUSERMOUNT_SUBDIR@ FUSE_CLIENT_SUBDIR = @FUSE_CLIENT_SUBDIR@ GEOREP_EXTRAS_SUBDIR = @GEOREP_EXTRAS_SUBDIR@ GFAPI_EXTRA_LDFLAGS = @GFAPI_EXTRA_LDFLAGS@ GFAPI_LIBS = @GFAPI_LIBS@ GFAPI_LT_VERSION = @GFAPI_LT_VERSION@ GFAPI_VERSION = @GFAPI_VERSION@ GF_CFLAGS = @GF_CFLAGS@ GF_CPPFLAGS = @GF_CPPFLAGS@ GF_DISTRIBUTION = @GF_DISTRIBUTION@ GF_FUSE_CFLAGS = @GF_FUSE_CFLAGS@ GF_FUSE_LDADD = @GF_FUSE_LDADD@ GF_HOST_OS = @GF_HOST_OS@ GF_LDADD = @GF_LDADD@ GF_LDFLAGS = @GF_LDFLAGS@ GF_XLATOR_DEFAULT_LDFLAGS = @GF_XLATOR_DEFAULT_LDFLAGS@ GLUPY_SUBDIR = @GLUPY_SUBDIR@ GLUPY_SUBDIR_MAKEFILE = @GLUPY_SUBDIR_MAKEFILE@ GLUPY_SUBDIR_SRC_MAKEFILE = @GLUPY_SUBDIR_SRC_MAKEFILE@ GLUSTERD_VOLFILE = @GLUSTERD_VOLFILE@ GLUSTERD_WORKDIR = @GLUSTERD_WORKDIR@ GLUSTERFSD_MISCDIR = @GLUSTERFSD_MISCDIR@ GLUSTERFS_LIBEXECDIR = @GLUSTERFS_LIBEXECDIR@ GREP = @GREP@ HAVE_ATOMIC_BUILTINS = @HAVE_ATOMIC_BUILTINS@ HAVE_BACKTRACE = @HAVE_BACKTRACE@ HAVE_LINKAT = @HAVE_LINKAT@ HAVE_MALLOC_STATS = @HAVE_MALLOC_STATS@ HAVE_SPINLOCK = @HAVE_SPINLOCK@ HAVE_STRNLEN = @HAVE_STRNLEN@ HAVE_SYNC_BUILTINS = @HAVE_SYNC_BUILTINS@ IBVERBS_SUBDIR = @IBVERBS_SUBDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBAIO = @LIBAIO@ LIBGFCHANGELOG_LT_VERSION = @LIBGFCHANGELOG_LT_VERSION@ LIBGFCHANGELOG_VERSION = @LIBGFCHANGELOG_VERSION@ LIBGFDB_VERSION = @LIBGFDB_VERSION@ LIBGFRPC_LT_VERSION = @LIBGFRPC_LT_VERSION@ LIBGFXDR_LT_VERSION = @LIBGFXDR_LT_VERSION@ LIBGLUSTERFS_LT_VERSION = @LIBGLUSTERFS_LT_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OCF_SUBDIR = @OCF_SUBDIR@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_RELEASE = @PACKAGE_RELEASE@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKGCONFIG_UUID = @PKGCONFIG_UUID@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHONDEV_CPPFLAGS = @PYTHONDEV_CPPFLAGS@ PYTHONDEV_LDFLAGS = @PYTHONDEV_LDFLAGS@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDMA_SUBDIR = @RDMA_SUBDIR@ RLLIBS = @RLLIBS@ RPCGEN = @RPCGEN@ SBIN_DIR = @SBIN_DIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SIZEOF_INT = @SIZEOF_INT@ SIZEOF_LONG = @SIZEOF_LONG@ SIZEOF_LONG_LONG = @SIZEOF_LONG_LONG@ SIZEOF_SHORT = @SIZEOF_SHORT@ SQLITE_CFLAGS = @SQLITE_CFLAGS@ SQLITE_LIBS = @SQLITE_LIBS@ STRIP = @STRIP@ SYNCDAEMON_COMPILE = @SYNCDAEMON_COMPILE@ SYNCDAEMON_SUBDIR = @SYNCDAEMON_SUBDIR@ SYSCONF_DIR = @SYSCONF_DIR@ UMOUNTD_SUBDIR = @UMOUNTD_SUBDIR@ UNITTEST_CFLAGS = @UNITTEST_CFLAGS@ UNITTEST_LDFLAGS = @UNITTEST_LDFLAGS@ UNITTEST_LIBS = @UNITTEST_LIBS@ URCU_CDS_CFLAGS = @URCU_CDS_CFLAGS@ URCU_CDS_LIBS = @URCU_CDS_LIBS@ URCU_CFLAGS = @URCU_CFLAGS@ URCU_LIBS = @URCU_LIBS@ USE_EC_DYNAMIC_AVX = @USE_EC_DYNAMIC_AVX@ USE_EC_DYNAMIC_NEON = @USE_EC_DYNAMIC_NEON@ USE_EC_DYNAMIC_SSE = @USE_EC_DYNAMIC_SSE@ USE_EC_DYNAMIC_X64 = @USE_EC_DYNAMIC_X64@ USE_POSIX_ACLS = @USE_POSIX_ACLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ initdir = @initdir@ install_sh = @install_sh@ launchddir = @launchddir@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mountutildir = @mountutildir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ shrext_cmds = @shrext_cmds@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ systemddir = @systemddir@ target_alias = @target_alias@ tmpfilesdir = @tmpfilesdir@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = gfind_missing_files glusterfind setgfid2path CLEANFILES = all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tools/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tools/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: glusterfs-3.13.2/tools/PaxHeaders.5796/gfind_missing_files0000644000000000000000000000013213230627061021632 xustar000000000000000030 mtime=1516449329.861494115 30 atime=1516449330.837496377 30 ctime=1516449329.861494115 glusterfs-3.13.2/tools/gfind_missing_files/0002775000175100017510000000000013230627061022152 5ustar00jenkinsjenkins00000000000000glusterfs-3.13.2/tools/gfind_missing_files/PaxHeaders.5796/Makefile.am0000644000000000000000000000013213230626775023756 xustar000000000000000030 mtime=1516449277.364372346 30 atime=1516449286.720394054 30 ctime=1516449329.849494087 glusterfs-3.13.2/tools/gfind_missing_files/Makefile.am0000664000175100017510000000136213230626775024221 0ustar00jenkinsjenkins00000000000000gfindmissingfilesdir = $(GLUSTERFS_LIBEXECDIR)/gfind_missing_files gfindmissingfiles_SCRIPTS = gfind_missing_files.sh gfid_to_path.sh \ gfid_to_path.py EXTRA_DIST = gfind_missing_files.sh gfid_to_path.sh \ gfid_to_path.py gfindmissingfiles_PROGRAMS = gcrawler gcrawler_SOURCES = gcrawler.c gcrawler_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la gcrawler_LDFLAGS = $(GF_LDFLAGS) AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src AM_CFLAGS = -Wall $(GF_CFLAGS) uninstall-local: rm -f $(DESTDIR)$(sbindir)/gfind_missing_files install-data-local: rm -f $(DESTDIR)$(sbindir)/gfind_missing_files ln -s $(GLUSTERFS_LIBEXECDIR)/gfind_missing_files/gfind_missing_files.sh $(DESTDIR)$(sbindir)/gfind_missing_files CLEANFILES = glusterfs-3.13.2/tools/gfind_missing_files/PaxHeaders.5796/gfind_missing_files.sh0000644000000000000000000000013213230626775026260 xustar000000000000000030 mtime=1516449277.364372346 30 atime=1516449277.364372346 30 ctime=1516449329.855494101 glusterfs-3.13.2/tools/gfind_missing_files/gfind_missing_files.sh0000664000175100017510000000604513230626775026526 0ustar00jenkinsjenkins00000000000000#!/bin/sh ## Copyright (c) 2015 Red Hat, Inc. ## This file is part of GlusterFS. ## ## 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. BRICKPATH= #Brick path of gluster volume SLAVEHOST= #Slave hostname SLAVEVOL= #Slave volume SLAVEMNT= #Slave gluster volume mount point WORKERS=4 #Default number of worker threads out() { echo "$@"; } fatal() { out FATAL "$@"; exit 1 } ping_host () { ### Use bash internal socket support { exec 400<>/dev/tcp/$1/$2 if [ $? -ne '0' ]; then return 1; else exec 400>&- return 0; fi } 1>&2 2>/dev/null } mount_slave() { local i; # inode number SSH_PORT=22 SLAVEMNT=`mktemp -d` [ "x$SLAVEMNT" = "x" ] && fatal "Could not mktemp directory"; [ -d "$SLAVEMNT" ] || fatal "$SLAVEMNT not a directory"; ping_host ${SLAVEHOST} $SSH_PORT if [ $? -ne 0 ]; then echo "$SLAVEHOST not reachable."; exit 1; fi; glusterfs --volfile-id=$SLAVEVOL --aux-gfid-mount --volfile-server=$SLAVEHOST $SLAVEMNT; i=$(stat -c '%i' $SLAVEMNT); [ "x$i" = "x1" ] || fatal "Could not mount volume $2 on $SLAVEMNT Please check host and volume exists"; } parse_cli() { if [[ $# -ne 4 ]]; then echo "Usage: gfind_missing_files " exit 1 else BRICKPATH=$1; SLAVEHOST=$2; SLAVEVOL=$3; OUTFILE=$4; mount_slave; echo "Slave volume is mounted at ${SLAVEMNT}" echo fi } main() { parse_cli "$@"; echo "Calling crawler..."; path=$(readlink -e $0) $(dirname $path)/gcrawler ${BRICKPATH} ${SLAVEMNT} ${WORKERS} > ${OUTFILE} #Clean up the mount umount $SLAVEMNT; rmdir $SLAVEMNT; echo "Crawl Complete." num_files_missing=$(wc -l ${OUTFILE} | awk '{print $1}') if [ $num_files_missing -eq 0 ] then echo "Total Missing File Count : 0" exit 0; fi echo "gfids of skipped files are available in the file ${OUTFILE}" echo echo "Starting gfid to path conversion" #Call python script to convert gfids to full pathname INFILE=$(readlink -e ${OUTFILE}) python $(dirname $path)/gfid_to_path.py ${BRICKPATH} ${INFILE} 1> ${OUTFILE}_pathnames 2> ${OUTFILE}_gfids echo "Path names of skipped files are available in the file ${OUTFILE}_pathnames" gfid_to_path_failures=$(wc -l ${OUTFILE}_gfids | awk '{print $1}') if [ $gfid_to_path_failures -gt 0 ] then echo "WARNING: Unable to convert some GFIDs to Paths, GFIDs logged to ${OUTFILE}_gfids" echo "Use $(dirname $path)/gfid_to_path.sh ${OUTFILE}_gfids to convert those GFIDs to Path" fi #Output echo "Total Missing File Count : $(wc -l ${OUTFILE} | awk '{print $1}')" } main "$@"; glusterfs-3.13.2/tools/gfind_missing_files/PaxHeaders.5796/gcrawler.c0000644000000000000000000000013213230626775023674 xustar000000000000000030 mtime=1516449277.364372346 30 atime=1516449277.364372346 30 ctime=1516449329.852494094 glusterfs-3.13.2/tools/gfind_missing_files/gcrawler.c0000664000175100017510000003501013230626775024134 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2015 Red Hat, Inc. This file is part of GlusterFS. 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 #include #include #include #include #include "locking.h" #include "compat.h" #include "list.h" #include "syscall.h" #define THREAD_MAX 32 #define BUMP(name) INC(name, 1) #define DEFAULT_WORKERS 4 #define NEW(x) { \ x = calloc (1, sizeof (typeof (*x))); \ } #define err(x ...) fprintf(stderr, x) #define out(x ...) fprintf(stdout, x) #define dbg(x ...) do { if (debug) fprintf(stdout, x); } while (0) #define tout(x ...) do { out("[%ld] ", pthread_self()); out(x); } while (0) #define terr(x ...) do { err("[%ld] ", pthread_self()); err(x); } while (0) #define tdbg(x ...) do { dbg("[%ld] ", pthread_self()); dbg(x); } while (0) int debug = 0; const char *slavemnt = NULL; int workers = 0; struct stats { unsigned long long int cnt_skipped_gfids; }; pthread_spinlock_t stats_lock; struct stats stats_total; int stats = 0; #define INC(name, val) do { \ if (!stats) \ break; \ pthread_spin_lock(&stats_lock); \ { \ stats_total.cnt_##name += val; \ } \ pthread_spin_unlock(&stats_lock); \ } while (0) void stats_dump() { if (!stats) return; out("-------------------------------------------\n"); out("Skipped_Files : %10lld\n", stats_total.cnt_skipped_gfids); out("-------------------------------------------\n"); } struct dirjob { struct list_head list; char *dirname; struct dirjob *parent; int ret; /* final status of this subtree */ int refcnt; /* how many dirjobs have this as parent */ pthread_spinlock_t lock; }; struct xwork { pthread_t cthreads[THREAD_MAX]; /* crawler threads */ int count; int idle; int stop; struct dirjob crawl; struct dirjob *rootjob; /* to verify completion in xwork_fini() */ pthread_mutex_t mutex; pthread_cond_t cond; }; struct dirjob * dirjob_ref (struct dirjob *job) { pthread_spin_lock (&job->lock); { job->refcnt++; } pthread_spin_unlock (&job->lock); return job; } void dirjob_free (struct dirjob *job) { assert (list_empty (&job->list)); pthread_spin_destroy (&job->lock); free (job->dirname); free (job); } void dirjob_ret (struct dirjob *job, int err) { int ret = 0; int refcnt = 0; struct dirjob *parent = NULL; pthread_spin_lock (&job->lock); { refcnt = --job->refcnt; job->ret = (job->ret || err); } pthread_spin_unlock (&job->lock); if (refcnt == 0) { ret = job->ret; if (ret) terr ("Failed: %s (%d)\n", job->dirname, ret); else tdbg ("Finished: %s\n", job->dirname); parent = job->parent; if (parent) dirjob_ret (parent, ret); dirjob_free (job); job = NULL; } } struct dirjob * dirjob_new (const char *dir, struct dirjob *parent) { struct dirjob *job = NULL; NEW(job); if (!job) return NULL; job->dirname = strdup (dir); if (!job->dirname) { free (job); return NULL; } INIT_LIST_HEAD(&job->list); pthread_spin_init (&job->lock, PTHREAD_PROCESS_PRIVATE); job->ret = 0; if (parent) job->parent = dirjob_ref (parent); job->refcnt = 1; return job; } void xwork_addcrawl (struct xwork *xwork, struct dirjob *job) { pthread_mutex_lock (&xwork->mutex); { list_add_tail (&job->list, &xwork->crawl.list); pthread_cond_broadcast (&xwork->cond); } pthread_mutex_unlock (&xwork->mutex); } int xwork_add (struct xwork *xwork, const char *dir, struct dirjob *parent) { struct dirjob *job = NULL; job = dirjob_new (dir, parent); if (!job) return -1; xwork_addcrawl (xwork, job); return 0; } struct dirjob * xwork_pick (struct xwork *xwork, int block) { struct dirjob *job = NULL; struct list_head *head = NULL; head = &xwork->crawl.list; pthread_mutex_lock (&xwork->mutex); { for (;;) { if (xwork->stop) break; if (!list_empty (head)) { job = list_entry (head->next, typeof(*job), list); list_del_init (&job->list); break; } if (((xwork->count * 2) == xwork->idle) && list_empty (&xwork->crawl.list)) { /* no outstanding jobs, and no active workers */ tdbg ("Jobless. Terminating\n"); xwork->stop = 1; pthread_cond_broadcast (&xwork->cond); break; } if (!block) break; xwork->idle++; pthread_cond_wait (&xwork->cond, &xwork->mutex); xwork->idle--; } } pthread_mutex_unlock (&xwork->mutex); return job; } int skip_name (const char *dirname, const char *name) { if (strcmp (name, ".") == 0) return 1; if (strcmp (name, "..") == 0) return 1; if (strcmp (name, "changelogs") == 0) return 1; if (strcmp (name, "health_check") == 0) return 1; if (strcmp (name, "indices") == 0) return 1; if (strcmp (name, "landfill") == 0) return 1; return 0; } int skip_stat (struct dirjob *job, const char *name) { if (job == NULL) return 0; if (strcmp (job->dirname, ".glusterfs") == 0) { tdbg ("Directly adding directories under .glusterfs " "to global list: %s\n", name); return 1; } if (job->parent != NULL) { if (strcmp (job->parent->dirname, ".glusterfs") == 0) { tdbg ("Directly adding directories under .glusterfs/XX " "to global list: %s\n", name); return 1; } } return 0; } int xworker_do_crawl (struct xwork *xwork, struct dirjob *job) { DIR *dirp = NULL; int ret = -1; int boff; int plen; char *path = NULL; struct dirjob *cjob = NULL; struct stat statbuf = {0,}; struct dirent *entry; struct dirent scratch[2] = {{0,},}; char gfid_path[PATH_MAX] = {0,}; plen = strlen (job->dirname) + 256 + 2; path = alloca (plen); tdbg ("Entering: %s\n", job->dirname); dirp = sys_opendir (job->dirname); if (!dirp) { terr ("opendir failed on %s (%s)\n", job->dirname, strerror (errno)); goto out; } boff = sprintf (path, "%s/", job->dirname); for (;;) { errno = 0; entry = sys_readdir (dirp, scratch); if (!entry || errno != 0) { if (errno != 0) { err ("readdir(%s): %s\n", job->dirname, strerror (errno)); ret = errno; goto out; } break; } if (entry->d_ino == 0) continue; if (skip_name (job->dirname, entry->d_name)) continue; /* It is sure that, children and grandchildren of .glusterfs * are directories, just add them to global queue. */ if (skip_stat (job, entry->d_name)) { strncpy (path + boff, entry->d_name, (plen-boff)); cjob = dirjob_new (path, job); if (!cjob) { err ("dirjob_new(%s): %s\n", path, strerror (errno)); ret = -1; goto out; } xwork_addcrawl (xwork, cjob); continue; } (void) snprintf (gfid_path, sizeof(gfid_path), "%s/.gfid/%s", slavemnt, entry->d_name); ret = sys_lstat (gfid_path, &statbuf); if (ret && errno == ENOENT) { out ("%s\n", entry->d_name); BUMP (skipped_gfids); } if (ret && errno != ENOENT) { err ("stat on slave failed(%s): %s\n", gfid_path, strerror (errno)); goto out; } } ret = 0; out: if (dirp) (void) sys_closedir (dirp); return ret; } void * xworker_crawl (void *data) { struct xwork *xwork = data; struct dirjob *job = NULL; int ret = -1; while ((job = xwork_pick (xwork, 0))) { ret = xworker_do_crawl (xwork, job); dirjob_ret (job, ret); } return NULL; } int xwork_fini (struct xwork *xwork, int stop) { int i = 0; int ret = 0; void *tret = 0; pthread_mutex_lock (&xwork->mutex); { xwork->stop = (xwork->stop || stop); pthread_cond_broadcast (&xwork->cond); } pthread_mutex_unlock (&xwork->mutex); for (i = 0; i < xwork->count; i++) { pthread_join (xwork->cthreads[i], &tret); tdbg ("CThread id %ld returned %p\n", xwork->cthreads[i], tret); } if (debug) { assert (xwork->rootjob->refcnt == 1); dirjob_ret (xwork->rootjob, 0); } if (stats) pthread_spin_destroy(&stats_lock); return ret; } int xwork_init (struct xwork *xwork, int count) { int i = 0; int ret = 0; struct dirjob *rootjob = NULL; if (stats) pthread_spin_init (&stats_lock, PTHREAD_PROCESS_PRIVATE); pthread_mutex_init (&xwork->mutex, NULL); pthread_cond_init (&xwork->cond, NULL); INIT_LIST_HEAD (&xwork->crawl.list); rootjob = dirjob_new (".glusterfs", NULL); if (debug) xwork->rootjob = dirjob_ref (rootjob); xwork_addcrawl (xwork, rootjob); xwork->count = count; for (i = 0; i < count; i++) { ret = pthread_create (&xwork->cthreads[i], NULL, xworker_crawl, xwork); if (ret) break; tdbg ("Spawned crawler %d thread %ld\n", i, xwork->cthreads[i]); } return ret; } int xfind (const char *basedir) { struct xwork xwork; int ret = 0; char *cwd = NULL; ret = chdir (basedir); if (ret) { err ("%s: %s\n", basedir, strerror (errno)); return ret; } cwd = getcwd (0, 0); if (!cwd) { err ("getcwd(): %s\n", strerror (errno)); return -1; } tdbg ("Working directory: %s\n", cwd); free (cwd); memset (&xwork, 0, sizeof (xwork)); ret = xwork_init (&xwork, workers); if (ret == 0) xworker_crawl (&xwork); ret = xwork_fini (&xwork, ret); stats_dump (); return ret; } static char * parse_and_validate_args (int argc, char *argv[]) { char *basedir = NULL; struct stat d = {0, }; int ret = -1; #ifndef __FreeBSD__ unsigned char volume_id[16]; #endif /* __FreeBSD__ */ char *slv_mnt = NULL; if (argc != 4) { err ("Usage: %s \n", argv[0]); return NULL; } basedir = argv[1]; ret = sys_lstat (basedir, &d); if (ret) { err ("%s: %s\n", basedir, strerror (errno)); return NULL; } #ifndef __FreeBSD__ ret = sys_lgetxattr (basedir, "trusted.glusterfs.volume-id", volume_id, 16); if (ret != 16) { err ("%s:Not a valid brick path.\n", basedir); return NULL; } #endif /* __FreeBSD__ */ slv_mnt = argv[2]; ret = sys_lstat (slv_mnt, &d); if (ret) { err ("%s: %s\n", slv_mnt, strerror (errno)); return NULL; } slavemnt = argv[2]; workers = atoi(argv[3]); if (workers <= 0) workers = DEFAULT_WORKERS; return basedir; } int main (int argc, char *argv[]) { char *basedir = NULL; basedir = parse_and_validate_args (argc, argv); if (!basedir) return 1; xfind (basedir); return 0; } glusterfs-3.13.2/tools/gfind_missing_files/PaxHeaders.5796/Makefile.in0000644000000000000000000000013013230627006023751 xustar000000000000000030 mtime=1516449286.757394139 29 atime=1516449311.01545041 29 ctime=1516449329.84649408 glusterfs-3.13.2/tools/gfind_missing_files/Makefile.in0000664000175100017510000006531613230627006024227 0ustar00jenkinsjenkins00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ gfindmissingfiles_PROGRAMS = gcrawler$(EXEEXT) subdir = tools/gfind_missing_files DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/contrib/aclocal/mkdirp.m4 \ $(top_srcdir)/contrib/aclocal/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h $(top_builddir)/site.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(gfindmissingfilesdir)" \ "$(DESTDIR)$(gfindmissingfilesdir)" PROGRAMS = $(gfindmissingfiles_PROGRAMS) am_gcrawler_OBJECTS = gcrawler.$(OBJEXT) gcrawler_OBJECTS = $(am_gcrawler_OBJECTS) gcrawler_DEPENDENCIES = \ $(top_builddir)/libglusterfs/src/libglusterfs.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = gcrawler_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(gcrawler_LDFLAGS) $(LDFLAGS) -o $@ am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } SCRIPTS = $(gfindmissingfiles_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(gcrawler_SOURCES) DIST_SOURCES = $(gcrawler_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACL_LIBS = @ACL_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LIBTOOLFLAGS = @AM_LIBTOOLFLAGS@ AM_MAKEFLAGS = @AM_MAKEFLAGS@ AR = @AR@ ARGP_STANDALONE_CPPFLAGS = @ARGP_STANDALONE_CPPFLAGS@ ARGP_STANDALONE_DIR = @ARGP_STANDALONE_DIR@ ARGP_STANDALONE_LDADD = @ARGP_STANDALONE_LDADD@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_PYTHON_INC = @BUILD_PYTHON_INC@ BUILD_PYTHON_LIB = @BUILD_PYTHON_LIB@ BUILD_PYTHON_SITE_PACKAGES = @BUILD_PYTHON_SITE_PACKAGES@ BUILD_PYTHON_SITE_PACKAGES_EXPANDED = @BUILD_PYTHON_SITE_PACKAGES_EXPANDED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONTRIBDIR = @CONTRIBDIR@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EVENTS_ENABLED = @EVENTS_ENABLED@ EVENTS_SUBDIR = @EVENTS_SUBDIR@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FUSERMOUNT_SUBDIR = @FUSERMOUNT_SUBDIR@ FUSE_CLIENT_SUBDIR = @FUSE_CLIENT_SUBDIR@ GEOREP_EXTRAS_SUBDIR = @GEOREP_EXTRAS_SUBDIR@ GFAPI_EXTRA_LDFLAGS = @GFAPI_EXTRA_LDFLAGS@ GFAPI_LIBS = @GFAPI_LIBS@ GFAPI_LT_VERSION = @GFAPI_LT_VERSION@ GFAPI_VERSION = @GFAPI_VERSION@ GF_CFLAGS = @GF_CFLAGS@ GF_CPPFLAGS = @GF_CPPFLAGS@ GF_DISTRIBUTION = @GF_DISTRIBUTION@ GF_FUSE_CFLAGS = @GF_FUSE_CFLAGS@ GF_FUSE_LDADD = @GF_FUSE_LDADD@ GF_HOST_OS = @GF_HOST_OS@ GF_LDADD = @GF_LDADD@ GF_LDFLAGS = @GF_LDFLAGS@ GF_XLATOR_DEFAULT_LDFLAGS = @GF_XLATOR_DEFAULT_LDFLAGS@ GLUPY_SUBDIR = @GLUPY_SUBDIR@ GLUPY_SUBDIR_MAKEFILE = @GLUPY_SUBDIR_MAKEFILE@ GLUPY_SUBDIR_SRC_MAKEFILE = @GLUPY_SUBDIR_SRC_MAKEFILE@ GLUSTERD_VOLFILE = @GLUSTERD_VOLFILE@ GLUSTERD_WORKDIR = @GLUSTERD_WORKDIR@ GLUSTERFSD_MISCDIR = @GLUSTERFSD_MISCDIR@ GLUSTERFS_LIBEXECDIR = @GLUSTERFS_LIBEXECDIR@ GREP = @GREP@ HAVE_ATOMIC_BUILTINS = @HAVE_ATOMIC_BUILTINS@ HAVE_BACKTRACE = @HAVE_BACKTRACE@ HAVE_LINKAT = @HAVE_LINKAT@ HAVE_MALLOC_STATS = @HAVE_MALLOC_STATS@ HAVE_SPINLOCK = @HAVE_SPINLOCK@ HAVE_STRNLEN = @HAVE_STRNLEN@ HAVE_SYNC_BUILTINS = @HAVE_SYNC_BUILTINS@ IBVERBS_SUBDIR = @IBVERBS_SUBDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBAIO = @LIBAIO@ LIBGFCHANGELOG_LT_VERSION = @LIBGFCHANGELOG_LT_VERSION@ LIBGFCHANGELOG_VERSION = @LIBGFCHANGELOG_VERSION@ LIBGFDB_VERSION = @LIBGFDB_VERSION@ LIBGFRPC_LT_VERSION = @LIBGFRPC_LT_VERSION@ LIBGFXDR_LT_VERSION = @LIBGFXDR_LT_VERSION@ LIBGLUSTERFS_LT_VERSION = @LIBGLUSTERFS_LT_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OCF_SUBDIR = @OCF_SUBDIR@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_RELEASE = @PACKAGE_RELEASE@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKGCONFIG_UUID = @PKGCONFIG_UUID@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHONDEV_CPPFLAGS = @PYTHONDEV_CPPFLAGS@ PYTHONDEV_LDFLAGS = @PYTHONDEV_LDFLAGS@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDMA_SUBDIR = @RDMA_SUBDIR@ RLLIBS = @RLLIBS@ RPCGEN = @RPCGEN@ SBIN_DIR = @SBIN_DIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SIZEOF_INT = @SIZEOF_INT@ SIZEOF_LONG = @SIZEOF_LONG@ SIZEOF_LONG_LONG = @SIZEOF_LONG_LONG@ SIZEOF_SHORT = @SIZEOF_SHORT@ SQLITE_CFLAGS = @SQLITE_CFLAGS@ SQLITE_LIBS = @SQLITE_LIBS@ STRIP = @STRIP@ SYNCDAEMON_COMPILE = @SYNCDAEMON_COMPILE@ SYNCDAEMON_SUBDIR = @SYNCDAEMON_SUBDIR@ SYSCONF_DIR = @SYSCONF_DIR@ UMOUNTD_SUBDIR = @UMOUNTD_SUBDIR@ UNITTEST_CFLAGS = @UNITTEST_CFLAGS@ UNITTEST_LDFLAGS = @UNITTEST_LDFLAGS@ UNITTEST_LIBS = @UNITTEST_LIBS@ URCU_CDS_CFLAGS = @URCU_CDS_CFLAGS@ URCU_CDS_LIBS = @URCU_CDS_LIBS@ URCU_CFLAGS = @URCU_CFLAGS@ URCU_LIBS = @URCU_LIBS@ USE_EC_DYNAMIC_AVX = @USE_EC_DYNAMIC_AVX@ USE_EC_DYNAMIC_NEON = @USE_EC_DYNAMIC_NEON@ USE_EC_DYNAMIC_SSE = @USE_EC_DYNAMIC_SSE@ USE_EC_DYNAMIC_X64 = @USE_EC_DYNAMIC_X64@ USE_POSIX_ACLS = @USE_POSIX_ACLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ initdir = @initdir@ install_sh = @install_sh@ launchddir = @launchddir@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mountutildir = @mountutildir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ shrext_cmds = @shrext_cmds@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ systemddir = @systemddir@ target_alias = @target_alias@ tmpfilesdir = @tmpfilesdir@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ gfindmissingfilesdir = $(GLUSTERFS_LIBEXECDIR)/gfind_missing_files gfindmissingfiles_SCRIPTS = gfind_missing_files.sh gfid_to_path.sh \ gfid_to_path.py EXTRA_DIST = gfind_missing_files.sh gfid_to_path.sh \ gfid_to_path.py gcrawler_SOURCES = gcrawler.c gcrawler_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la gcrawler_LDFLAGS = $(GF_LDFLAGS) AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src AM_CFLAGS = -Wall $(GF_CFLAGS) CLEANFILES = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tools/gfind_missing_files/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tools/gfind_missing_files/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-gfindmissingfilesPROGRAMS: $(gfindmissingfiles_PROGRAMS) @$(NORMAL_INSTALL) @list='$(gfindmissingfiles_PROGRAMS)'; test -n "$(gfindmissingfilesdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(gfindmissingfilesdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(gfindmissingfilesdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(gfindmissingfilesdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(gfindmissingfilesdir)$$dir" || exit $$?; \ } \ ; done uninstall-gfindmissingfilesPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(gfindmissingfiles_PROGRAMS)'; test -n "$(gfindmissingfilesdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(gfindmissingfilesdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(gfindmissingfilesdir)" && rm -f $$files clean-gfindmissingfilesPROGRAMS: @list='$(gfindmissingfiles_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gcrawler$(EXEEXT): $(gcrawler_OBJECTS) $(gcrawler_DEPENDENCIES) $(EXTRA_gcrawler_DEPENDENCIES) @rm -f gcrawler$(EXEEXT) $(AM_V_CCLD)$(gcrawler_LINK) $(gcrawler_OBJECTS) $(gcrawler_LDADD) $(LIBS) install-gfindmissingfilesSCRIPTS: $(gfindmissingfiles_SCRIPTS) @$(NORMAL_INSTALL) @list='$(gfindmissingfiles_SCRIPTS)'; test -n "$(gfindmissingfilesdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(gfindmissingfilesdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(gfindmissingfilesdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(gfindmissingfilesdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(gfindmissingfilesdir)$$dir" || exit $$?; \ } \ ; done uninstall-gfindmissingfilesSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(gfindmissingfiles_SCRIPTS)'; test -n "$(gfindmissingfilesdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(gfindmissingfilesdir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gcrawler.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(SCRIPTS) installdirs: for dir in "$(DESTDIR)$(gfindmissingfilesdir)" "$(DESTDIR)$(gfindmissingfilesdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-gfindmissingfilesPROGRAMS clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-gfindmissingfilesPROGRAMS \ install-gfindmissingfilesSCRIPTS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-gfindmissingfilesPROGRAMS \ uninstall-gfindmissingfilesSCRIPTS uninstall-local .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-gfindmissingfilesPROGRAMS clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-data-local install-dvi install-dvi-am \ install-exec install-exec-am install-gfindmissingfilesPROGRAMS \ install-gfindmissingfilesSCRIPTS install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am \ uninstall-gfindmissingfilesPROGRAMS \ uninstall-gfindmissingfilesSCRIPTS uninstall-local uninstall-local: rm -f $(DESTDIR)$(sbindir)/gfind_missing_files install-data-local: rm -f $(DESTDIR)$(sbindir)/gfind_missing_files ln -s $(GLUSTERFS_LIBEXECDIR)/gfind_missing_files/gfind_missing_files.sh $(DESTDIR)$(sbindir)/gfind_missing_files # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: glusterfs-3.13.2/tools/gfind_missing_files/PaxHeaders.5796/gfid_to_path.sh0000644000000000000000000000013213230626775024705 xustar000000000000000030 mtime=1516449277.364372346 30 atime=1516449277.364372346 30 ctime=1516449329.858494107 glusterfs-3.13.2/tools/gfind_missing_files/gfid_to_path.sh0000664000175100017510000000155413230626775025153 0ustar00jenkinsjenkins00000000000000#!/bin/sh ## Copyright (c) 2015 Red Hat, Inc. ## This file is part of GlusterFS. ## ## 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. E_BADARGS=65 gfid_to_path () { brick_dir=$1; gfid_file=$(readlink -e $2); current_dir=$(pwd); cd $brick_dir; while read gfid do to_search=`echo .glusterfs/${gfid:0:2}"/"${gfid:2:2}"/"$gfid`; find . -samefile $to_search | grep -v $to_search; done < $gfid_file; cd $current_dir; } main () { if [ $# -ne 2 ] then echo "Usage: `basename $0` BRICK_DIR GFID_FILE"; exit $E_BADARGS; fi gfid_to_path $1 $2; } main "$@"; glusterfs-3.13.2/tools/gfind_missing_files/PaxHeaders.5796/gfid_to_path.py0000644000000000000000000000013213230626775024723 xustar000000000000000030 mtime=1516449277.364372346 30 atime=1516449277.364372346 30 ctime=1516449329.861494115 glusterfs-3.13.2/tools/gfind_missing_files/gfid_to_path.py0000664000175100017510000001073413230626775025171 0ustar00jenkinsjenkins00000000000000#!/usr/bin/env python # Copyright (c) 2015 Red Hat, Inc. # This file is part of GlusterFS. # # 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. import sys import os import xattr import uuid import re import errno CHANGELOG_SEARCH_MAX_TRY = 31 DEC_CTIME_START = 5 ROOT_GFID = "00000000-0000-0000-0000-000000000001" MAX_NUM_CHANGELOGS_TRY = 2 def output_not_found(gfid): # Write GFID to stderr sys.stderr.write("%s\n" % gfid) def output_success(path): # Write converted Path to Stdout sys.stdout.write("%s\n" % path) def full_dir_path(gfid): out_path = "" while True: path = os.path.join(".glusterfs", gfid[0:2], gfid[2:4], gfid) path_readlink = os.readlink(path) pgfid = os.path.dirname(path_readlink) out_path = os.path.join(os.path.basename(path_readlink), out_path) if pgfid == "../../00/00/%s" % ROOT_GFID: out_path = os.path.join("./", out_path) break gfid = os.path.basename(pgfid) return out_path def find_path_from_changelog(fd, gfid): """ In given Changelog File, finds using following pattern \x00\x00\x00\x00\x00/ Pattern search finds PARGFID and BASENAME, Convert PARGFID to Path Using readlink and add basename to form Full path. """ content = fd.read() pattern = "E%s" % gfid pattern += "\x00(3|23)\x00\d+\x00\d+\x00\d+\x00([^\x00]+)/([^\x00]+)" pat = re.compile(pattern) match = pat.search(content) if match: pgfid = match.group(2) basename = match.group(3) if pgfid == ROOT_GFID: return os.path.join("./", basename) else: full_path_parent = full_dir_path(pgfid) if full_path_parent: return os.path.join(full_path_parent, basename) return None def gfid_to_path(gfid): """ Try readlink, if it is directory it succeeds. Get ctime of the GFID file, Decrement by 5 sec Search for Changelog filename, Since Changelog file generated every 15 sec, Search and get immediate next Changelog after the file Creation. Get the Path by searching in Changelog file. Get the resultant file's GFID and Compare with the input, If these GFIDs are different then Some thing is changed(May be Rename) """ gfid = gfid.strip() gpath = os.path.join(".glusterfs", gfid[0:2], gfid[2:4], gfid) try: output_success(full_dir_path(gfid)) return except OSError: # Not an SymLink pass try: ctime = int(os.stat(gpath).st_ctime) ctime -= DEC_CTIME_START except (OSError, IOError): output_not_found(gfid) return path = None found_changelog = False changelog_parse_try = 0 for i in range(CHANGELOG_SEARCH_MAX_TRY): cl = os.path.join(".glusterfs/changelogs", "CHANGELOG.%s" % ctime) try: with open(cl, "rb") as f: changelog_parse_try += 1 found_changelog = True path = find_path_from_changelog(f, gfid) if not path and changelog_parse_try < MAX_NUM_CHANGELOGS_TRY: ctime += 1 continue break except (IOError, OSError) as e: if e.errno == errno.ENOENT: ctime += 1 else: break if not found_changelog: output_not_found(gfid) return if not path: output_not_found(gfid) return gfid1 = str(uuid.UUID(bytes=xattr.get(path, "trusted.gfid"))) if gfid != gfid1: output_not_found(gfid) return output_success(path) def main(): num_arguments = 3 if not sys.stdin.isatty(): num_arguments = 2 if len(sys.argv) != num_arguments: sys.stderr.write("Invalid arguments\nUsage: " "%s \n" % sys.argv[0]) sys.exit(1) path = sys.argv[1] if sys.stdin.isatty(): gfid_list = os.path.abspath(sys.argv[2]) os.chdir(path) with open(gfid_list) as f: for gfid in f: gfid_to_path(gfid) else: os.chdir(path) for gfid in sys.stdin: gfid_to_path(gfid) if __name__ == "__main__": main() glusterfs-3.13.2/tools/PaxHeaders.5796/glusterfind0000644000000000000000000000013213230627061020156 xustar000000000000000030 mtime=1516449329.937494291 30 atime=1516449330.837496377 30 ctime=1516449329.937494291 glusterfs-3.13.2/tools/glusterfind/0002775000175100017510000000000013230627061020476 5ustar00jenkinsjenkins00000000000000glusterfs-3.13.2/tools/glusterfind/PaxHeaders.5796/Makefile.am0000644000000000000000000000013213230626775022302 xustar000000000000000030 mtime=1516449277.364372346 30 atime=1516449286.768394165 30 ctime=1516449329.923494258 glusterfs-3.13.2/tools/glusterfind/Makefile.am0000664000175100017510000000131513230626775022543 0ustar00jenkinsjenkins00000000000000SUBDIRS = src EXTRA_DIST = S57glusterfind-delete-post.py bin_SCRIPTS = glusterfind CLEANFILES = $(bin_SCRIPTS) deletehookscriptsdir = $(GLUSTERFS_LIBEXECDIR)/glusterfind/ deletehookscripts_SCRIPTS = S57glusterfind-delete-post.py uninstall-local: rm -f $(DESTDIR)$(GLUSTERD_WORKDIR)/hooks/1/delete/post/S57glusterfind-delete-post install-data-local: $(mkdir_p) $(DESTDIR)$(GLUSTERD_WORKDIR)/glusterfind/.keys $(mkdir_p) $(DESTDIR)$(GLUSTERD_WORKDIR)/hooks/1/delete/post/ rm -f $(DESTDIR)$(GLUSTERD_WORKDIR)/hooks/1/delete/post/S57glusterfind-delete-post ln -s $(GLUSTERFS_LIBEXECDIR)/glusterfind/S57glusterfind-delete-post.py \ $(DESTDIR)$(GLUSTERD_WORKDIR)/hooks/1/delete/post/S57glusterfind-delete-post glusterfs-3.13.2/tools/glusterfind/PaxHeaders.5796/src0000644000000000000000000000013213230627062020746 xustar000000000000000030 mtime=1516449330.032494511 30 atime=1516449330.837496377 30 ctime=1516449330.032494511 glusterfs-3.13.2/tools/glusterfind/src/0002775000175100017510000000000013230627062021266 5ustar00jenkinsjenkins00000000000000glusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/conf.py0000644000000000000000000000013213230626775022334 xustar000000000000000030 mtime=1516449277.365372348 30 atime=1516449277.365372348 30 ctime=1516449330.007494453 glusterfs-3.13.2/tools/glusterfind/src/conf.py0000664000175100017510000000141413230626775022575 0ustar00jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2015 Red Hat, Inc. # This file is part of GlusterFS. # # 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. import os import ConfigParser config = ConfigParser.ConfigParser() config.read(os.path.join(os.path.dirname(os.path.abspath(__file__)), "tool.conf")) def list_change_detectors(): return dict(config.items("change_detectors")).keys() def get_opt(opt): return config.get("vars", opt) def get_change_detector(opt): return config.get("change_detectors", opt) glusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/Makefile.am0000644000000000000000000000013213230626775023071 xustar000000000000000030 mtime=1516449277.365372348 30 atime=1516449286.806394253 30 ctime=1516449330.002494441 glusterfs-3.13.2/tools/glusterfind/src/Makefile.am0000664000175100017510000000052613230626775023335 0ustar00jenkinsjenkins00000000000000glusterfinddir = $(GLUSTERFS_LIBEXECDIR)/glusterfind glusterfind_PYTHON = conf.py utils.py __init__.py \ main.py libgfchangelog.py changelogdata.py glusterfind_SCRIPTS = changelog.py nodeagent.py \ brickfind.py glusterfind_DATA = tool.conf EXTRA_DIST = changelog.py nodeagent.py brickfind.py \ tool.conf changelogdata.py CLEANFILES = glusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/changelog.py0000644000000000000000000000013213230626775023336 xustar000000000000000030 mtime=1516449277.365372348 30 atime=1516449277.365372348 30 ctime=1516449330.024494493 glusterfs-3.13.2/tools/glusterfind/src/changelog.py0000664000175100017510000003570613230626775023612 0ustar00jenkinsjenkins00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2015 Red Hat, Inc. # This file is part of GlusterFS. # # 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. import os import sys import time import xattr import logging from argparse import ArgumentParser, RawDescriptionHelpFormatter import hashlib import urllib import codecs import libgfchangelog from utils import mkdirp, symlink_gfid_to_path from utils import fail, setup_logger, find from utils import get_changelog_rollover_time from utils import output_path_prepare from changelogdata import ChangelogData import conf CHANGELOG_LOG_LEVEL = 9 CHANGELOG_CONN_RETRIES = 5 CHANGELOGAPI_NUM_WORKERS = 3 PROG_DESCRIPTION = """ Changelog Crawler """ history_turns = 0 history_turn_time = 0 logger = logging.getLogger() def pgfid_to_path(brick, changelog_data): """ For all the pgfids in table, converts into path using recursive readlink. """ # pgfid1 to path1 in case of CREATE/MKNOD/MKDIR/LINK/SYMLINK for row in changelog_data.gfidpath_get_distinct("pgfid1", {"path1": ""}): # In case of Data/Metadata only, pgfid1 will not be their if row[0] == "": continue try: path = symlink_gfid_to_path(brick, row[0]) path = output_path_prepare(path, args) changelog_data.gfidpath_set_path1(path, row[0]) except (IOError, OSError) as e: logger.warn("Error converting to path: %s" % e) continue # pgfid2 to path2 in case of RENAME for row in changelog_data.gfidpath_get_distinct("pgfid2", {"type": "RENAME", "path2": ""}): # Only in case of Rename pgfid2 exists if row[0] == "": continue try: path = symlink_gfid_to_path(brick, row[0]) path = output_path_prepare(path, args) changelog_data.gfidpath_set_path2(path, row[0]) except (IOError, OSError) as e: logger.warn("Error converting to path: %s" % e) continue def populate_pgfid_and_inodegfid(brick, changelog_data): """ For all the DATA/METADATA modifications GFID, If symlink, directly convert to Path using Readlink. If not symlink, try to get PGFIDs via xattr query and populate it to pgfid table, collect inodes in inodegfid table """ for row in changelog_data.gfidpath_get({"path1": "", "type": "MODIFY"}): gfid = row[3].strip() p = os.path.join(brick, ".glusterfs", gfid[0:2], gfid[2:4], gfid) if os.path.islink(p): # It is a Directory if GFID backend path is symlink try: path = symlink_gfid_to_path(brick, gfid) path = output_path_prepare(path, args) changelog_data.gfidpath_update({"path1": path}, {"gfid": gfid}) except (IOError, OSError) as e: logger.warn("Error converting to path: %s" % e) continue else: try: # INODE and GFID to inodegfid table changelog_data.inodegfid_add(os.stat(p).st_ino, gfid) file_xattrs = xattr.list(p) for x in file_xattrs: if x.startswith("trusted.pgfid."): # PGFID in pgfid table changelog_data.pgfid_add(x.split(".")[-1]) except (IOError, OSError): # All OS Errors ignored, since failures will be logged # in End. All GFIDs present in gfidpath table continue def gfid_to_path_using_pgfid(brick, changelog_data, args): """ For all the pgfids collected, Converts to Path and does readdir on those directories and looks up inodegfid table for matching inode number. """ populate_pgfid_and_inodegfid(brick, changelog_data) # If no GFIDs needs conversion to Path if not changelog_data.inodegfid_exists({"converted": 0}): return def inode_filter(path): # Looks in inodegfid table, if exists returns # inode number else None try: st = os.lstat(path) except (OSError, IOError): st = None if st and changelog_data.inodegfid_exists({"inode": st.st_ino}): return st.st_ino return None # Length of brick path, to remove from output path brick_path_len = len(brick) def output_callback(path, inode): # For each path found, encodes it and updates path1 # Also updates converted flag in inodegfid table as 1 path = path.strip() path = path[brick_path_len+1:] path = output_path_prepare(path, args) changelog_data.append_path1(path, inode) changelog_data.inodegfid_update({"converted": 1}, {"inode": inode}) ignore_dirs = [os.path.join(brick, dirname) for dirname in conf.get_opt("brick_ignore_dirs").split(",")] for row in changelog_data.pgfid_get(): try: path = symlink_gfid_to_path(brick, row[0]) find(os.path.join(brick, path), callback_func=output_callback, filter_func=inode_filter, ignore_dirs=ignore_dirs, subdirs_crawl=False) except (IOError, OSError) as e: logger.warn("Error converting to path: %s" % e) continue def gfid_to_path_using_batchfind(brick, changelog_data): # If all the GFIDs converted using gfid_to_path_using_pgfid if not changelog_data.inodegfid_exists({"converted": 0}): return def inode_filter(path): # Looks in inodegfid table, if exists returns # inode number else None try: st = os.lstat(path) except (OSError, IOError): st = None if st and changelog_data.inodegfid_exists({"inode": st.st_ino}): return st.st_ino return None # Length of brick path, to remove from output path brick_path_len = len(brick) def output_callback(path, inode): # For each path found, encodes it and updates path1 # Also updates converted flag in inodegfid table as 1 path = path.strip() path = path[brick_path_len+1:] path = output_path_prepare(path, args) changelog_data.append_path1(path, inode) ignore_dirs = [os.path.join(brick, dirname) for dirname in conf.get_opt("brick_ignore_dirs").split(",")] # Full Namespace Crawl find(brick, callback_func=output_callback, filter_func=inode_filter, ignore_dirs=ignore_dirs) def parse_changelog_to_db(changelog_data, filename, args): """ Parses a Changelog file and populates data in gfidpath table """ with codecs.open(filename, encoding="utf-8") as f: changelogfile = os.path.basename(filename) for line in f: data = line.strip().split(" ") if data[0] == "E" and data[2] in ["CREATE", "MKNOD", "MKDIR"]: # CREATE/MKDIR/MKNOD changelog_data.when_create_mknod_mkdir(changelogfile, data) elif data[0] in ["D", "M"]: # DATA/META if not args.only_namespace_changes: changelog_data.when_data_meta(changelogfile, data) elif data[0] == "E" and data[2] in ["LINK", "SYMLINK"]: # LINK/SYMLINK changelog_data.when_link_symlink(changelogfile, data) elif data[0] == "E" and data[2] == "RENAME": # RENAME changelog_data.when_rename(changelogfile, data) elif data[0] == "E" and data[2] in ["UNLINK", "RMDIR"]: # UNLINK/RMDIR changelog_data.when_unlink_rmdir(changelogfile, data) def get_changes(brick, hash_dir, log_file, start, end, args): """ Makes use of libgfchangelog's history API to get changelogs containing changes from start and end time. Further collects the modified gfids from the changelogs and writes the list of gfid to 'gfid_list' file. """ session_dir = os.path.join(conf.get_opt("session_dir"), args.session) status_file = os.path.join(session_dir, args.volume, "%s.status" % urllib.quote_plus(args.brick)) # Get previous session try: with open(status_file) as f: start = int(f.read().strip()) except (ValueError, OSError, IOError): start = args.start try: libgfchangelog.cl_init() libgfchangelog.cl_register(brick, hash_dir, log_file, CHANGELOG_LOG_LEVEL, CHANGELOG_CONN_RETRIES) except libgfchangelog.ChangelogException as e: fail("%s Changelog register failed: %s" % (brick, e), logger=logger) # Output files to record GFIDs and GFID to Path failure GFIDs changelog_data = ChangelogData(args.outfile, args) # Changelogs path(Hard coded to BRICK/.glusterfs/changelogs cl_path = os.path.join(brick, ".glusterfs/changelogs") # Fail if History fails for requested Start and End try: actual_end = libgfchangelog.cl_history_changelog( cl_path, start, end, CHANGELOGAPI_NUM_WORKERS) except libgfchangelog.ChangelogException as e: fail("%s: %s Historical Changelogs not available: %s" % (args.node, brick, e), logger=logger) try: # scan followed by getchanges till scan returns zero. # history_scan() is blocking call, till it gets the number # of changelogs to process. Returns zero when no changelogs # to be processed. returns positive value as number of changelogs # to be processed, which will be fetched using # history_getchanges() changes = [] while libgfchangelog.cl_history_scan() > 0: changes = libgfchangelog.cl_history_getchanges() for change in changes: # Ignore if last processed changelog comes # again in list if change.endswith(".%s" % start): continue try: parse_changelog_to_db(changelog_data, change, args) libgfchangelog.cl_history_done(change) except IOError as e: logger.warn("Error parsing changelog file %s: %s" % (change, e)) changelog_data.commit() except libgfchangelog.ChangelogException as e: fail("%s Error during Changelog Crawl: %s" % (brick, e), logger=logger) # Convert all pgfid available from Changelogs pgfid_to_path(brick, changelog_data) changelog_data.commit() # Convert all GFIDs for which no other additional details available gfid_to_path_using_pgfid(brick, changelog_data, args) changelog_data.commit() # If some GFIDs fail to get converted from previous step, # convert using find gfid_to_path_using_batchfind(brick, changelog_data) changelog_data.commit() return actual_end def changelog_crawl(brick, start, end, args): """ Init function, prepares working dir and calls Changelog query """ if brick.endswith("/"): brick = brick[0:len(brick)-1] # WORKING_DIR/BRICKHASH/OUTFILE working_dir = os.path.dirname(args.outfile) brickhash = hashlib.sha1(brick) brickhash = str(brickhash.hexdigest()) working_dir = os.path.join(working_dir, brickhash) mkdirp(working_dir, exit_on_err=True, logger=logger) log_file = os.path.join(conf.get_opt("log_dir"), args.session, args.volume, "changelog.%s.log" % brickhash) logger.info("%s Started Changelog Crawl. Start: %s, End: %s" % (brick, start, end)) return get_changes(brick, working_dir, log_file, start, end, args) def _get_args(): parser = ArgumentParser(formatter_class=RawDescriptionHelpFormatter, description=PROG_DESCRIPTION) parser.add_argument("session", help="Session Name") parser.add_argument("volume", help="Volume Name") parser.add_argument("node", help="Node Name") parser.add_argument("brick", help="Brick Name") parser.add_argument("outfile", help="Output File") parser.add_argument("start", help="Start Time", type=int) parser.add_argument("end", help="End Time", type=int) parser.add_argument("--only-query", help="Query mode only (no session)", action="store_true") parser.add_argument("--debug", help="Debug", action="store_true") parser.add_argument("--no-encode", help="Do not encode path in outfile", action="store_true") parser.add_argument("--output-prefix", help="File prefix in output", default=".") parser.add_argument("-N", "--only-namespace-changes", help="List only namespace changes", action="store_true") return parser.parse_args() if __name__ == "__main__": args = _get_args() mkdirp(os.path.join(conf.get_opt("log_dir"), args.session, args.volume), exit_on_err=True) log_file = os.path.join(conf.get_opt("log_dir"), args.session, args.volume, "changelog.log") setup_logger(logger, log_file, args.debug) session_dir = os.path.join(conf.get_opt("session_dir"), args.session) status_file = os.path.join(session_dir, args.volume, "%s.status" % urllib.quote_plus(args.brick)) status_file_pre = status_file + ".pre" mkdirp(os.path.join(session_dir, args.volume), exit_on_err=True, logger=logger) end = -1 if args.only_query: start = args.start end = args.end else: try: with open(status_file) as f: start = int(f.read().strip()) except (ValueError, OSError, IOError): start = args.start # end time is optional; so a -1 may be sent to use the default method of # identifying the end time if end == -1: end = int(time.time()) - get_changelog_rollover_time(args.volume) logger.info("%s Started Changelog Crawl - Start: %s End: %s" % (args.brick, start, end)) actual_end = changelog_crawl(args.brick, start, end, args) if not args.only_query: with open(status_file_pre, "w", buffering=0) as f: f.write(str(actual_end)) logger.info("%s Finished Changelog Crawl - End: %s" % (args.brick, actual_end)) sys.exit(0) glusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/Makefile.in0000644000000000000000000000013113230627006023065 xustar000000000000000029 mtime=1516449286.83539432 30 atime=1516449311.177450786 30 ctime=1516449329.999494434 glusterfs-3.13.2/tools/glusterfind/src/Makefile.in0000664000175100017510000005347113230627006023341 0ustar00jenkinsjenkins00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tools/glusterfind/src DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/tool.conf.in $(glusterfind_PYTHON) \ $(top_srcdir)/py-compile ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/contrib/aclocal/mkdirp.m4 \ $(top_srcdir)/contrib/aclocal/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h $(top_builddir)/site.h CONFIG_CLEAN_FILES = tool.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(glusterfinddir)" \ "$(DESTDIR)$(glusterfinddir)" "$(DESTDIR)$(glusterfinddir)" SCRIPTS = $(glusterfind_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile) am__pep3147_tweak = \ sed -e 's|\.py$$||' -e 's|[^/]*$$|__pycache__/&.*.py|' py_compile = $(top_srcdir)/py-compile DATA = $(glusterfind_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACL_LIBS = @ACL_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LIBTOOLFLAGS = @AM_LIBTOOLFLAGS@ AM_MAKEFLAGS = @AM_MAKEFLAGS@ AR = @AR@ ARGP_STANDALONE_CPPFLAGS = @ARGP_STANDALONE_CPPFLAGS@ ARGP_STANDALONE_DIR = @ARGP_STANDALONE_DIR@ ARGP_STANDALONE_LDADD = @ARGP_STANDALONE_LDADD@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_PYTHON_INC = @BUILD_PYTHON_INC@ BUILD_PYTHON_LIB = @BUILD_PYTHON_LIB@ BUILD_PYTHON_SITE_PACKAGES = @BUILD_PYTHON_SITE_PACKAGES@ BUILD_PYTHON_SITE_PACKAGES_EXPANDED = @BUILD_PYTHON_SITE_PACKAGES_EXPANDED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONTRIBDIR = @CONTRIBDIR@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EVENTS_ENABLED = @EVENTS_ENABLED@ EVENTS_SUBDIR = @EVENTS_SUBDIR@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FUSERMOUNT_SUBDIR = @FUSERMOUNT_SUBDIR@ FUSE_CLIENT_SUBDIR = @FUSE_CLIENT_SUBDIR@ GEOREP_EXTRAS_SUBDIR = @GEOREP_EXTRAS_SUBDIR@ GFAPI_EXTRA_LDFLAGS = @GFAPI_EXTRA_LDFLAGS@ GFAPI_LIBS = @GFAPI_LIBS@ GFAPI_LT_VERSION = @GFAPI_LT_VERSION@ GFAPI_VERSION = @GFAPI_VERSION@ GF_CFLAGS = @GF_CFLAGS@ GF_CPPFLAGS = @GF_CPPFLAGS@ GF_DISTRIBUTION = @GF_DISTRIBUTION@ GF_FUSE_CFLAGS = @GF_FUSE_CFLAGS@ GF_FUSE_LDADD = @GF_FUSE_LDADD@ GF_HOST_OS = @GF_HOST_OS@ GF_LDADD = @GF_LDADD@ GF_LDFLAGS = @GF_LDFLAGS@ GF_XLATOR_DEFAULT_LDFLAGS = @GF_XLATOR_DEFAULT_LDFLAGS@ GLUPY_SUBDIR = @GLUPY_SUBDIR@ GLUPY_SUBDIR_MAKEFILE = @GLUPY_SUBDIR_MAKEFILE@ GLUPY_SUBDIR_SRC_MAKEFILE = @GLUPY_SUBDIR_SRC_MAKEFILE@ GLUSTERD_VOLFILE = @GLUSTERD_VOLFILE@ GLUSTERD_WORKDIR = @GLUSTERD_WORKDIR@ GLUSTERFSD_MISCDIR = @GLUSTERFSD_MISCDIR@ GLUSTERFS_LIBEXECDIR = @GLUSTERFS_LIBEXECDIR@ GREP = @GREP@ HAVE_ATOMIC_BUILTINS = @HAVE_ATOMIC_BUILTINS@ HAVE_BACKTRACE = @HAVE_BACKTRACE@ HAVE_LINKAT = @HAVE_LINKAT@ HAVE_MALLOC_STATS = @HAVE_MALLOC_STATS@ HAVE_SPINLOCK = @HAVE_SPINLOCK@ HAVE_STRNLEN = @HAVE_STRNLEN@ HAVE_SYNC_BUILTINS = @HAVE_SYNC_BUILTINS@ IBVERBS_SUBDIR = @IBVERBS_SUBDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBAIO = @LIBAIO@ LIBGFCHANGELOG_LT_VERSION = @LIBGFCHANGELOG_LT_VERSION@ LIBGFCHANGELOG_VERSION = @LIBGFCHANGELOG_VERSION@ LIBGFDB_VERSION = @LIBGFDB_VERSION@ LIBGFRPC_LT_VERSION = @LIBGFRPC_LT_VERSION@ LIBGFXDR_LT_VERSION = @LIBGFXDR_LT_VERSION@ LIBGLUSTERFS_LT_VERSION = @LIBGLUSTERFS_LT_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OCF_SUBDIR = @OCF_SUBDIR@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_RELEASE = @PACKAGE_RELEASE@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKGCONFIG_UUID = @PKGCONFIG_UUID@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHONDEV_CPPFLAGS = @PYTHONDEV_CPPFLAGS@ PYTHONDEV_LDFLAGS = @PYTHONDEV_LDFLAGS@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDMA_SUBDIR = @RDMA_SUBDIR@ RLLIBS = @RLLIBS@ RPCGEN = @RPCGEN@ SBIN_DIR = @SBIN_DIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SIZEOF_INT = @SIZEOF_INT@ SIZEOF_LONG = @SIZEOF_LONG@ SIZEOF_LONG_LONG = @SIZEOF_LONG_LONG@ SIZEOF_SHORT = @SIZEOF_SHORT@ SQLITE_CFLAGS = @SQLITE_CFLAGS@ SQLITE_LIBS = @SQLITE_LIBS@ STRIP = @STRIP@ SYNCDAEMON_COMPILE = @SYNCDAEMON_COMPILE@ SYNCDAEMON_SUBDIR = @SYNCDAEMON_SUBDIR@ SYSCONF_DIR = @SYSCONF_DIR@ UMOUNTD_SUBDIR = @UMOUNTD_SUBDIR@ UNITTEST_CFLAGS = @UNITTEST_CFLAGS@ UNITTEST_LDFLAGS = @UNITTEST_LDFLAGS@ UNITTEST_LIBS = @UNITTEST_LIBS@ URCU_CDS_CFLAGS = @URCU_CDS_CFLAGS@ URCU_CDS_LIBS = @URCU_CDS_LIBS@ URCU_CFLAGS = @URCU_CFLAGS@ URCU_LIBS = @URCU_LIBS@ USE_EC_DYNAMIC_AVX = @USE_EC_DYNAMIC_AVX@ USE_EC_DYNAMIC_NEON = @USE_EC_DYNAMIC_NEON@ USE_EC_DYNAMIC_SSE = @USE_EC_DYNAMIC_SSE@ USE_EC_DYNAMIC_X64 = @USE_EC_DYNAMIC_X64@ USE_POSIX_ACLS = @USE_POSIX_ACLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ initdir = @initdir@ install_sh = @install_sh@ launchddir = @launchddir@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mountutildir = @mountutildir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ shrext_cmds = @shrext_cmds@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ systemddir = @systemddir@ target_alias = @target_alias@ tmpfilesdir = @tmpfilesdir@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ glusterfinddir = $(GLUSTERFS_LIBEXECDIR)/glusterfind glusterfind_PYTHON = conf.py utils.py __init__.py \ main.py libgfchangelog.py changelogdata.py glusterfind_SCRIPTS = changelog.py nodeagent.py \ brickfind.py glusterfind_DATA = tool.conf EXTRA_DIST = changelog.py nodeagent.py brickfind.py \ tool.conf changelogdata.py CLEANFILES = all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tools/glusterfind/src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tools/glusterfind/src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): tool.conf: $(top_builddir)/config.status $(srcdir)/tool.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-glusterfindSCRIPTS: $(glusterfind_SCRIPTS) @$(NORMAL_INSTALL) @list='$(glusterfind_SCRIPTS)'; test -n "$(glusterfinddir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(glusterfinddir)'"; \ $(MKDIR_P) "$(DESTDIR)$(glusterfinddir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(glusterfinddir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(glusterfinddir)$$dir" || exit $$?; \ } \ ; done uninstall-glusterfindSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(glusterfind_SCRIPTS)'; test -n "$(glusterfinddir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(glusterfinddir)'; $(am__uninstall_files_from_dir) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-glusterfindPYTHON: $(glusterfind_PYTHON) @$(NORMAL_INSTALL) @list='$(glusterfind_PYTHON)'; dlist=; list2=; test -n "$(glusterfinddir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(glusterfinddir)'"; \ $(MKDIR_P) "$(DESTDIR)$(glusterfinddir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(glusterfinddir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(glusterfinddir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(glusterfinddir)" $$dlist; \ else :; fi uninstall-glusterfindPYTHON: @$(NORMAL_UNINSTALL) @list='$(glusterfind_PYTHON)'; test -n "$(glusterfinddir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ dir='$(DESTDIR)$(glusterfinddir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ echo "$$py_files_pep3147";\ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ for files in \ "$$py_files" \ "$$pyc_files" \ "$$pyo_files" \ "$$pyc_files_pep3147" \ "$$pyo_files_pep3147" \ ; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st install-glusterfindDATA: $(glusterfind_DATA) @$(NORMAL_INSTALL) @list='$(glusterfind_DATA)'; test -n "$(glusterfinddir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(glusterfinddir)'"; \ $(MKDIR_P) "$(DESTDIR)$(glusterfinddir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(glusterfinddir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(glusterfinddir)" || exit $$?; \ done uninstall-glusterfindDATA: @$(NORMAL_UNINSTALL) @list='$(glusterfind_DATA)'; test -n "$(glusterfinddir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(glusterfinddir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(SCRIPTS) $(DATA) installdirs: for dir in "$(DESTDIR)$(glusterfinddir)" "$(DESTDIR)$(glusterfinddir)" "$(DESTDIR)$(glusterfinddir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-glusterfindDATA install-glusterfindPYTHON \ install-glusterfindSCRIPTS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-glusterfindDATA uninstall-glusterfindPYTHON \ uninstall-glusterfindSCRIPTS .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am \ install-glusterfindDATA install-glusterfindPYTHON \ install-glusterfindSCRIPTS install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-glusterfindDATA \ uninstall-glusterfindPYTHON uninstall-glusterfindSCRIPTS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: glusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/tool.conf.in0000644000000000000000000000013213230626775023266 xustar000000000000000030 mtime=1516449277.366372351 30 atime=1516449311.107450623 30 ctime=1516449330.005494448 glusterfs-3.13.2/tools/glusterfind/src/tool.conf.in0000664000175100017510000000056113230626775023531 0ustar00jenkinsjenkins00000000000000[vars] session_dir=@GLUSTERD_WORKDIR@/glusterfind/ working_dir=@GLUSTERFSD_MISCDIR@/glusterfind/ log_dir=/var/log/glusterfs/glusterfind/ nodeagent=@GLUSTERFS_LIBEXECDIR@/glusterfind/nodeagent.py brick_ignore_dirs=.glusterfs,.trashcan [change_detectors] changelog=@GLUSTERFS_LIBEXECDIR@/glusterfind/changelog.py brickfind=@GLUSTERFS_LIBEXECDIR@/glusterfind/brickfind.pyglusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/libgfchangelog.py0000644000000000000000000000013213230626775024342 xustar000000000000000030 mtime=1516449277.365372348 30 atime=1516449277.365372348 30 ctime=1516449330.018494479 glusterfs-3.13.2/tools/glusterfind/src/libgfchangelog.py0000664000175100017510000000427213230626775024610 0ustar00jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2015 Red Hat, Inc. # This file is part of GlusterFS. # # 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. import os from ctypes import CDLL, get_errno, create_string_buffer, c_ulong, byref from ctypes import RTLD_GLOBAL from ctypes.util import find_library class ChangelogException(OSError): pass libgfc = CDLL(find_library("gfchangelog"), use_errno=True, mode=RTLD_GLOBAL) def raise_oserr(): errn = get_errno() raise ChangelogException(errn, os.strerror(errn)) def cl_init(): ret = libgfc.gf_changelog_init(None) if ret == -1: raise_oserr() def cl_register(brick, path, log_file, log_level, retries=0): ret = libgfc.gf_changelog_register(brick, path, log_file, log_level, retries) if ret == -1: raise_oserr() def cl_history_scan(): ret = libgfc.gf_history_changelog_scan() if ret == -1: raise_oserr() return ret def cl_history_changelog(changelog_path, start, end, num_parallel): actual_end = c_ulong() ret = libgfc.gf_history_changelog(changelog_path, start, end, num_parallel, byref(actual_end)) if ret == -1: raise_oserr() return actual_end.value def cl_history_startfresh(): ret = libgfc.gf_history_changelog_start_fresh() if ret == -1: raise_oserr() def cl_history_getchanges(): """ remove hardcoding for path name length """ def clsort(f): return f.split('.')[-1] changes = [] buf = create_string_buffer('\0', 4096) while True: ret = libgfc.gf_history_changelog_next_change(buf, 4096) if ret in (0, -1): break changes.append(buf.raw[:ret - 1]) if ret == -1: raise_oserr() return sorted(changes, key=clsort) def cl_history_done(clfile): ret = libgfc.gf_history_changelog_done(clfile) if ret == -1: raise_oserr() glusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/changelogdata.py0000644000000000000000000000013213230626775024170 xustar000000000000000030 mtime=1516449277.365372348 30 atime=1516449277.365372348 30 ctime=1516449330.021494485 glusterfs-3.13.2/tools/glusterfind/src/changelogdata.py0000664000175100017510000003711213230626775024435 0ustar00jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2015 Red Hat, Inc. # This file is part of GlusterFS. # # 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. import sqlite3 import os from utils import RecordType, unquote_plus_space_newline from utils import output_path_prepare class OutputMerger(object): """ Class to merge the output files collected from different nodes """ def __init__(self, db_path, all_dbs): self.conn = sqlite3.connect(db_path) self.cursor = self.conn.cursor() self.cursor_reader = self.conn.cursor() query = "DROP TABLE IF EXISTS finallist" self.cursor.execute(query) query = """ CREATE TABLE finallist( id INTEGER PRIMARY KEY AUTOINCREMENT, ts VARCHAR, type VARCHAR, gfid VARCHAR, path1 VARCHAR, path2 VARCHAR, UNIQUE (type, path1, path2) ON CONFLICT IGNORE ) """ self.cursor.execute(query) # If node database exists, read each db and insert into # final table. Ignore if combination of TYPE PATH1 PATH2 # already exists for node_db in all_dbs: if os.path.exists(node_db): conn = sqlite3.connect(node_db) cursor = conn.cursor() query = """ SELECT ts, type, gfid, path1, path2 FROM gfidpath WHERE path1 != '' ORDER BY id ASC """ for row in cursor.execute(query): self.add_if_not_exists(row[0], row[1], row[2], row[3], row[4]) self.conn.commit() def add_if_not_exists(self, ts, ty, gfid, path1, path2=""): # Adds record to finallist only if not exists query = """ INSERT INTO finallist(ts, type, gfid, path1, path2) VALUES(?, ?, ?, ?, ?) """ self.cursor.execute(query, (ts, ty, gfid, path1, path2)) def get(self): query = """SELECT type, path1, path2 FROM finallist ORDER BY ts ASC, id ASC""" return self.cursor_reader.execute(query) def get_failures(self): query = """ SELECT gfid FROM finallist WHERE path1 = '' OR (path2 = '' AND type = 'RENAME') """ return self.cursor_reader.execute(query) class ChangelogData(object): def __init__(self, dbpath, args): self.conn = sqlite3.connect(dbpath) self.cursor = self.conn.cursor() self.cursor_reader = self.conn.cursor() self._create_table_gfidpath() self._create_table_pgfid() self._create_table_inodegfid() self.args = args self.path_sep = "/" def _create_table_gfidpath(self): drop_table = "DROP TABLE IF EXISTS gfidpath" self.cursor.execute(drop_table) create_table = """ CREATE TABLE gfidpath( id INTEGER PRIMARY KEY AUTOINCREMENT, ts VARCHAR, type VARCHAR, gfid VARCHAR(40), pgfid1 VARCHAR(40) DEFAULT '', bn1 VARCHAR(500) DEFAULT '', pgfid2 VARCHAR(40) DEFAULT '', bn2 VARCHAR(500) DEFAULT '', path1 VARCHAR DEFAULT '', path2 VARCHAR DEFAULT '' ) """ self.cursor.execute(create_table) def _create_table_inodegfid(self): drop_table = "DROP TABLE IF EXISTS inodegfid" self.cursor.execute(drop_table) create_table = """ CREATE TABLE inodegfid( inode INTEGER PRIMARY KEY, gfid VARCHAR(40), converted INTEGER DEFAULT 0, UNIQUE (inode, gfid) ON CONFLICT IGNORE ) """ self.cursor.execute(create_table) def _create_table_pgfid(self): drop_table = "DROP TABLE IF EXISTS pgfid" self.cursor.execute(drop_table) create_table = """ CREATE TABLE pgfid( pgfid VARCHAR(40) PRIMARY KEY, UNIQUE (pgfid) ON CONFLICT IGNORE ) """ self.cursor.execute(create_table) def _get(self, tablename, filters): # SELECT * FROM WHERE params = [] query = "SELECT * FROM %s WHERE 1=1" % tablename for key, value in filters.items(): query += " AND %s = ?" % key params.append(value) return self.cursor_reader.execute(query, params) def _get_distinct(self, tablename, distinct_field, filters): # SELECT DISTINCT FROM WHERE params = [] query = "SELECT DISTINCT %s FROM %s WHERE 1=1" % (distinct_field, tablename) for key, value in filters.items(): query += " AND %s = ?" % key params.append(value) return self.cursor_reader.execute(query, params) def _delete(self, tablename, filters): # DELETE FROM WHERE query = "DELETE FROM %s WHERE 1=1" % tablename params = [] for key, value in filters.items(): query += " AND %s = ?" % key params.append(value) self.cursor.execute(query, params) def _add(self, tablename, data): # INSERT INTO (, ..) VALUES(?,?..) query = "INSERT INTO %s(" % tablename fields = [] params = [] for key, value in data.items(): fields.append(key) params.append(value) values_substitute = len(fields)*["?"] query += "%s) VALUES(%s)" % (",".join(fields), ",".join(values_substitute)) self.cursor.execute(query, params) def _update(self, tablename, data, filters): # UPDATE SET col1 = ?,.. WHERE col1=? AND .. params = [] update_fields = [] for key, value in data.items(): update_fields.append("%s = ?" % key) params.append(value) query = "UPDATE %s SET %s WHERE 1 = 1" % (tablename, ", ".join(update_fields)) for key, value in filters.items(): query += " AND %s = ?" % key params.append(value) self.cursor.execute(query, params) def _exists(self, tablename, filters): if not filters: return False query = "SELECT COUNT(1) FROM %s WHERE 1=1" % tablename params = [] for key, value in filters.items(): query += " AND %s = ?" % key params.append(value) self.cursor.execute(query, params) row = self.cursor.fetchone() return True if row[0] > 0 else False def gfidpath_add(self, changelogfile, ty, gfid, pgfid1="", bn1="", pgfid2="", bn2="", path1="", path2=""): self._add("gfidpath", { "ts": changelogfile.split(".")[-1], "type": ty, "gfid": gfid, "pgfid1": pgfid1, "bn1": bn1, "pgfid2": pgfid2, "bn2": bn2, "path1": path1, "path2": path2 }) def gfidpath_update(self, data, filters): self._update("gfidpath", data, filters) def gfidpath_delete(self, filters): self._delete("gfidpath", filters) def gfidpath_exists(self, filters): return self._exists("gfidpath", filters) def gfidpath_get(self, filters={}): return self._get("gfidpath", filters) def gfidpath_get_distinct(self, distinct_field, filters={}): return self._get_distinct("gfidpath", distinct_field, filters) def pgfid_add(self, pgfid): self._add("pgfid", { "pgfid": pgfid }) def pgfid_update(self, data, filters): self._update("pgfid", data, filters) def pgfid_get(self, filters={}): return self._get("pgfid", filters) def pgfid_get_distinct(self, distinct_field, filters={}): return self._get_distinct("pgfid", distinct_field, filters) def pgfid_exists(self, filters): return self._exists("pgfid", filters) def inodegfid_add(self, inode, gfid, converted=0): self._add("inodegfid", { "inode": inode, "gfid": gfid, "converted": converted }) def inodegfid_update(self, data, filters): self._update("inodegfid", data, filters) def inodegfid_get(self, filters={}): return self._get("inodegfid", filters) def inodegfid_get_distinct(self, distinct_field, filters={}): return self._get_distinct("inodegfid", distinct_field, filters) def inodegfid_exists(self, filters): return self._exists("inodegfid", filters) def append_path1(self, path, inode): # || is for concatenate in SQL query = """UPDATE gfidpath SET path1 = path1 || ',' || ? WHERE gfid IN (SELECT gfid FROM inodegfid WHERE inode = ?)""" self.cursor.execute(query, (path, inode)) def gfidpath_set_path1(self, path1, pgfid1): # || is for concatenate in SQL if path1 == "": update_str1 = "? || bn1" update_str2 = "? || bn2" else: update_str1 = "? || '{0}' || bn1".format(self.path_sep) update_str2 = "? || '{0}' || bn2".format(self.path_sep) query = """UPDATE gfidpath SET path1 = %s WHERE pgfid1 = ?""" % update_str1 self.cursor.execute(query, (path1, pgfid1)) # Set Path2 if pgfid1 and pgfid2 are same query = """UPDATE gfidpath SET path2 = %s WHERE pgfid2 = ?""" % update_str2 self.cursor.execute(query, (path1, pgfid1)) def gfidpath_set_path2(self, path2, pgfid2): # || is for concatenate in SQL if path2 == "": update_str = "? || bn2" else: update_str = "? || '{0}' || bn2".format(self.path_sep) query = """UPDATE gfidpath SET path2 = %s WHERE pgfid2 = ?""" % update_str self.cursor.execute(query, (path2, pgfid2)) def when_create_mknod_mkdir(self, changelogfile, data): # E / # Add the Entry to DB pgfid1, bn1 = data[6].split("/", 1) if self.args.no_encode: bn1 = unquote_plus_space_newline(bn1).strip() self.gfidpath_add(changelogfile, RecordType.NEW, data[1], pgfid1, bn1) def when_rename(self, changelogfile, data): # E RENAME / / pgfid1, bn1 = data[3].split("/", 1) pgfid2, bn2 = data[4].split("/", 1) if self.args.no_encode: bn1 = unquote_plus_space_newline(bn1).strip() bn2 = unquote_plus_space_newline(bn2).strip() if self.gfidpath_exists({"gfid": data[1], "type": "NEW", "pgfid1": pgfid1, "bn1": bn1}): # If / is same as CREATE, Update # / in NEW. self.gfidpath_update({"pgfid1": pgfid2, "bn1": bn2}, {"gfid": data[1], "type": "NEW", "pgfid1": pgfid1, "bn1": bn1}) elif self.gfidpath_exists({"gfid": data[1], "type": "RENAME", "pgfid2": pgfid1, "bn2": bn1}): # If we are renaming file back to original name then just # delete the entry since it will effectively be a no-op if self.gfidpath_exists({"gfid": data[1], "type": "RENAME", "pgfid2": pgfid1, "bn2": bn1, "pgfid1": pgfid2, "bn1": bn2}): self.gfidpath_delete({"gfid": data[1], "type": "RENAME", "pgfid2": pgfid1, "bn2": bn1}) else: # If / is same as / # (may be previous RENAME) # then UPDATE / as / self.gfidpath_update({"pgfid2": pgfid2, "bn2": bn2}, {"gfid": data[1], "type": "RENAME", "pgfid2": pgfid1, "bn2": bn1}) else: # Else insert as RENAME self.gfidpath_add(changelogfile, RecordType.RENAME, data[1], pgfid1, bn1, pgfid2, bn2) if self.gfidpath_exists({"gfid": data[1], "type": "MODIFY"}): # If MODIFY exists already for that GFID, remove it and insert # again so that MODIFY entry comes after RENAME entry # Output will have MODIFY self.gfidpath_delete({"gfid": data[1], "type": "MODIFY"}) self.gfidpath_add(changelogfile, RecordType.MODIFY, data[1]) def when_link_symlink(self, changelogfile, data): # E / # Add as New record in Db as Type NEW pgfid1, bn1 = data[3].split("/", 1) if self.args.no_encode: bn1 = unquote_plus_space_newline(bn1).strip() self.gfidpath_add(changelogfile, RecordType.NEW, data[1], pgfid1, bn1) def when_data_meta(self, changelogfile, data): # If GFID row exists, Ignore else Add to Db if not self.gfidpath_exists({"gfid": data[1], "type": "NEW"}) and \ not self.gfidpath_exists({"gfid": data[1], "type": "MODIFY"}): self.gfidpath_add(changelogfile, RecordType.MODIFY, data[1]) def when_unlink_rmdir(self, changelogfile, data): # E / pgfid1, bn1 = data[3].split("/", 1) if self.args.no_encode: bn1 = unquote_plus_space_newline(bn1).strip() deleted_path = data[4] if len(data) == 5 else "" if deleted_path != "": deleted_path = unquote_plus_space_newline(deleted_path) deleted_path = output_path_prepare(deleted_path, self.args) if self.gfidpath_exists({"gfid": data[1], "type": "NEW", "pgfid1": pgfid1, "bn1": bn1}): # If path exists in table as NEW with same GFID # Delete that row self.gfidpath_delete({"gfid": data[1], "type": "NEW", "pgfid1": pgfid1, "bn1": bn1}) else: # Else Record as DELETE self.gfidpath_add(changelogfile, RecordType.DELETE, data[1], pgfid1, bn1, path1=deleted_path) # Update path1 as deleted_path if pgfid1 and bn1 is same as deleted self.gfidpath_update({"path1": deleted_path}, {"gfid": data[1], "pgfid1": pgfid1, "bn1": bn1}) # Update path2 as deleted_path if pgfid2 and bn2 is same as deleted self.gfidpath_update({"path2": deleted_path}, { "type": RecordType.RENAME, "gfid": data[1], "pgfid2": pgfid1, "bn2": bn1}) # If deleted directory is parent for somebody query1 = """UPDATE gfidpath SET path1 = ? || '{0}' || bn1 WHERE pgfid1 = ? AND path1 != ''""".format(self.path_sep) self.cursor.execute(query1, (deleted_path, data[1])) query1 = """UPDATE gfidpath SET path2 = ? || '{0}' || bn1 WHERE pgfid2 = ? AND path2 != ''""".format(self.path_sep) self.cursor.execute(query1, (deleted_path, data[1])) def commit(self): self.conn.commit() glusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/tool.conf0000644000000000000000000000013213230627037022651 xustar000000000000000030 mtime=1516449311.112450635 30 atime=1516449316.815463861 30 ctime=1516449330.032494511 glusterfs-3.13.2/tools/glusterfind/src/tool.conf0000664000175100017510000000062113230627037023111 0ustar00jenkinsjenkins00000000000000[vars] session_dir=/var/lib/glusterd/glusterfind/ working_dir=/usr/local/var/lib/misc/glusterfsd/glusterfind/ log_dir=/var/log/glusterfs/glusterfind/ nodeagent=/usr/local/libexec/glusterfs/glusterfind/nodeagent.py brick_ignore_dirs=.glusterfs,.trashcan [change_detectors] changelog=/usr/local/libexec/glusterfs/glusterfind/changelog.py brickfind=/usr/local/libexec/glusterfs/glusterfind/brickfind.py glusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/nodeagent.py0000644000000000000000000000013213230626775023353 xustar000000000000000030 mtime=1516449277.366372351 30 atime=1516449277.366372351 30 ctime=1516449330.027494499 glusterfs-3.13.2/tools/glusterfind/src/nodeagent.py0000664000175100017510000001167413230626775023625 0ustar00jenkinsjenkins00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2015 Red Hat, Inc. # This file is part of GlusterFS. # # 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. import shutil import sys import os import logging from argparse import ArgumentParser, RawDescriptionHelpFormatter import urllib from errno import ENOTEMPTY from utils import setup_logger, mkdirp, handle_rm_error import conf logger = logging.getLogger() def mode_cleanup(args): working_dir = os.path.join(conf.get_opt("working_dir"), args.session, args.volume, args.tmpfilename) mkdirp(os.path.join(conf.get_opt("log_dir"), args.session, args.volume), exit_on_err=True) log_file = os.path.join(conf.get_opt("log_dir"), args.session, args.volume, "changelog.log") setup_logger(logger, log_file) try: shutil.rmtree(working_dir, onerror=handle_rm_error) except (OSError, IOError) as e: logger.error("Failed to delete working directory: %s" % e) sys.exit(1) def mode_create(args): session_dir = os.path.join(conf.get_opt("session_dir"), args.session) status_file = os.path.join(session_dir, args.volume, "%s.status" % urllib.quote_plus(args.brick)) mkdirp(os.path.join(session_dir, args.volume), exit_on_err=True, logger=logger) if not os.path.exists(status_file) or args.reset_session_time: with open(status_file, "w", buffering=0) as f: f.write(args.time_to_update) sys.exit(0) def mode_post(args): session_dir = os.path.join(conf.get_opt("session_dir"), args.session) status_file = os.path.join(session_dir, args.volume, "%s.status" % urllib.quote_plus(args.brick)) mkdirp(os.path.join(session_dir, args.volume), exit_on_err=True, logger=logger) status_file_pre = status_file + ".pre" if os.path.exists(status_file_pre): os.rename(status_file_pre, status_file) sys.exit(0) def mode_delete(args): session_dir = os.path.join(conf.get_opt("session_dir"), args.session) shutil.rmtree(os.path.join(session_dir, args.volume), onerror=handle_rm_error) # If the session contains only this volume, then cleanup the # session directory. If a session contains multiple volumes # then os.rmdir will fail with ENOTEMPTY try: os.rmdir(session_dir) except OSError as e: if not e.errno == ENOTEMPTY: logger.warn("Failed to delete session directory: %s" % e) def _get_args(): parser = ArgumentParser(formatter_class=RawDescriptionHelpFormatter, description="Node Agent") subparsers = parser.add_subparsers(dest="mode") parser_cleanup = subparsers.add_parser('cleanup') parser_cleanup.add_argument("session", help="Session Name") parser_cleanup.add_argument("volume", help="Volume Name") parser_cleanup.add_argument("tmpfilename", help="Temporary File Name") parser_cleanup.add_argument("--debug", help="Debug", action="store_true") parser_session_create = subparsers.add_parser('create') parser_session_create.add_argument("session", help="Session Name") parser_session_create.add_argument("volume", help="Volume Name") parser_session_create.add_argument("brick", help="Brick Path") parser_session_create.add_argument("time_to_update", help="Time to Update") parser_session_create.add_argument("--reset-session-time", help="Reset Session Time", action="store_true") parser_session_create.add_argument("--debug", help="Debug", action="store_true") parser_post = subparsers.add_parser('post') parser_post.add_argument("session", help="Session Name") parser_post.add_argument("volume", help="Volume Name") parser_post.add_argument("brick", help="Brick Path") parser_post.add_argument("--debug", help="Debug", action="store_true") parser_delete = subparsers.add_parser('delete') parser_delete.add_argument("session", help="Session Name") parser_delete.add_argument("volume", help="Volume Name") parser_delete.add_argument("--debug", help="Debug", action="store_true") return parser.parse_args() if __name__ == "__main__": args = _get_args() # globals() will have all the functions already defined. # mode_ will be the function name to be called globals()["mode_" + args.mode](args) glusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/main.py0000644000000000000000000000013213230626775022333 xustar000000000000000030 mtime=1516449277.366372351 30 atime=1516449277.365372348 30 ctime=1516449330.016494474 glusterfs-3.13.2/tools/glusterfind/src/main.py0000664000175100017510000007752313230626775022612 0ustar00jenkinsjenkins00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2015 Red Hat, Inc. # This file is part of GlusterFS. # # 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. import sys from errno import ENOENT, ENOTEMPTY import time from multiprocessing import Process import os import xml.etree.cElementTree as etree from argparse import ArgumentParser, RawDescriptionHelpFormatter, Action import logging import shutil import tempfile import signal from datetime import datetime import codecs from utils import execute, is_host_local, mkdirp, fail from utils import setup_logger, human_time, handle_rm_error from utils import get_changelog_rollover_time, cache_output, create_file import conf from changelogdata import OutputMerger PROG_DESCRIPTION = """ GlusterFS Incremental API """ ParseError = etree.ParseError if hasattr(etree, 'ParseError') else SyntaxError logger = logging.getLogger() node_outfiles = [] vol_statusStr = "" gtmpfilename = None class StoreAbsPath(Action): def __init__(self, option_strings, dest, nargs=None, **kwargs): super(StoreAbsPath, self).__init__(option_strings, dest, **kwargs) def __call__(self, parser, namespace, values, option_string=None): setattr(namespace, self.dest, os.path.abspath(values)) def get_pem_key_path(session, volume): return os.path.join(conf.get_opt("session_dir"), session, volume, "%s_%s_secret.pem" % (session, volume)) def node_cmd(host, host_uuid, task, cmd, args, opts): """ Runs command via ssh if host is not local """ try: localdir = is_host_local(host_uuid) # this is so to avoid deleting the ssh keys on local node which # otherwise cause ssh password prompts on the console (race conditions) # mode_delete() should be cleaning up the session tree if localdir and task == "delete": return pem_key_path = get_pem_key_path(args.session, args.volume) if not localdir: # prefix with ssh command if not local node cmd = ["ssh", "-oNumberOfPasswordPrompts=0", "-oStrictHostKeyChecking=no", "-t", "-t", "-i", pem_key_path, "root@%s" % host] + cmd execute(cmd, exit_msg="%s - %s failed" % (host, task), logger=logger) if opts.get("copy_outfile", False) and not localdir: cmd_copy = ["scp", "-oNumberOfPasswordPrompts=0", "-oStrictHostKeyChecking=no", "-i", pem_key_path, "root@%s:/%s" % (host, opts.get("node_outfile")), os.path.dirname(opts.get("node_outfile"))] execute(cmd_copy, exit_msg="%s - Copy command failed" % host, logger=logger) except KeyboardInterrupt: sys.exit(2) def run_cmd_nodes(task, args, **kwargs): global node_outfiles nodes = get_nodes(args.volume) pool = [] for num, node in enumerate(nodes): host, brick = node[1].split(":") host_uuid = node[0] cmd = [] opts = {} # tmpfilename is valid only for tasks: pre, query and cleanup tmpfilename = kwargs.get("tmpfilename", "BADNAME") node_outfile = os.path.join(conf.get_opt("working_dir"), args.session, args.volume, tmpfilename, "tmp_output_%s" % num) if task == "pre": if vol_statusStr != "Started": fail("Volume %s is not online" % args.volume, logger=logger) # If Full backup is requested or start time is zero, use brickfind change_detector = conf.get_change_detector("changelog") tag = None if args.full: change_detector = conf.get_change_detector("brickfind") tag = args.tag_for_full_find.strip() if tag == "": tag = '""' if not is_host_local(host_uuid) else "" node_outfiles.append(node_outfile) # remote file will be copied into this directory mkdirp(os.path.dirname(node_outfile), exit_on_err=True, logger=logger) FS = args.field_separator if not is_host_local(host_uuid): FS = "'" + FS + "'" cmd = [change_detector, args.session, args.volume, host, brick, node_outfile] + \ ([str(kwargs.get("start")), str(kwargs.get("end"))] if not args.full else []) + \ ([tag] if tag is not None else []) + \ ["--output-prefix", args.output_prefix] + \ (["--debug"] if args.debug else []) + \ (["--no-encode"] if args.no_encode else []) + \ (["--only-namespace-changes"] if args.only_namespace_changes else []) + \ (["--field-separator", FS] if args.full else []) opts["node_outfile"] = node_outfile opts["copy_outfile"] = True elif task == "query": # If Full backup is requested or start time is zero, use brickfind tag = None change_detector = conf.get_change_detector("changelog") if args.full: change_detector = conf.get_change_detector("brickfind") tag = args.tag_for_full_find.strip() if tag == "": tag = '""' if not is_host_local(host_uuid) else "" node_outfiles.append(node_outfile) # remote file will be copied into this directory mkdirp(os.path.dirname(node_outfile), exit_on_err=True, logger=logger) FS = args.field_separator if not is_host_local(host_uuid): FS = "'" + FS + "'" cmd = [change_detector, args.session, args.volume, host, brick, node_outfile] + \ ([str(kwargs.get("start")), str(kwargs.get("end"))] if not args.full else []) + \ ([tag] if tag is not None else []) + \ ["--only-query"] + \ ["--output-prefix", args.output_prefix] + \ (["--debug"] if args.debug else []) + \ (["--no-encode"] if args.no_encode else []) + \ (["--only-namespace-changes"] if args.only_namespace_changes else []) + \ (["--field-separator", FS] if args.full else []) opts["node_outfile"] = node_outfile opts["copy_outfile"] = True elif task == "cleanup": # After pre/query run, cleanup the working directory and other # temp files. Remove the directory to which node_outfile has # been copied in main node try: os.remove(node_outfile) except (OSError, IOError): logger.warn("Failed to cleanup temporary file %s" % node_outfile) pass cmd = [conf.get_opt("nodeagent"), "cleanup", args.session, args.volume, os.path.dirname(node_outfile)] + \ (["--debug"] if args.debug else []) elif task == "create": if vol_statusStr != "Started": fail("Volume %s is not online" % args.volume, logger=logger) # When glusterfind create, create session directory in # each brick nodes cmd = [conf.get_opt("nodeagent"), "create", args.session, args.volume, brick, kwargs.get("time_to_update")] + \ (["--debug"] if args.debug else []) + \ (["--reset-session-time"] if args.reset_session_time else []) elif task == "post": # Rename pre status file to actual status file in each node cmd = [conf.get_opt("nodeagent"), "post", args.session, args.volume, brick] + \ (["--debug"] if args.debug else []) elif task == "delete": # When glusterfind delete, cleanup all the session files/dirs # from each node. cmd = [conf.get_opt("nodeagent"), "delete", args.session, args.volume] + \ (["--debug"] if args.debug else []) if cmd: p = Process(target=node_cmd, args=(host, host_uuid, task, cmd, args, opts)) p.start() pool.append(p) for num, p in enumerate(pool): p.join() if p.exitcode != 0: logger.warn("Command %s failed in %s" % (task, nodes[num][1])) if task in ["create", "delete"]: fail("Command %s failed in %s" % (task, nodes[num][1])) elif task == "pre" and args.disable_partial: sys.exit(1) @cache_output def get_nodes(volume): """ Get the gluster volume info xml output and parse to get the brick details. """ global vol_statusStr cmd = ["gluster", 'volume', 'info', volume, "--xml"] _, data, _ = execute(cmd, exit_msg="Failed to Run Gluster Volume Info", logger=logger) tree = etree.fromstring(data) # Test to check if volume has been deleted after session creation count_el = tree.find('volInfo/volumes/count') if int(count_el.text) == 0: fail("Unable to get volume details", logger=logger) # this status is used in caller: run_cmd_nodes vol_statusStr = tree.find('volInfo/volumes/volume/statusStr').text vol_typeStr = tree.find('volInfo/volumes/volume/typeStr').text nodes = [] volume_el = tree.find('volInfo/volumes/volume') try: brick_elems = [] if vol_typeStr == "Tier": brick_elems.append('bricks/hotBricks/brick') brick_elems.append('bricks/coldBricks/brick') else: brick_elems.append('bricks/brick') for elem in brick_elems: for b in volume_el.findall(elem): nodes.append((b.find('hostUuid').text, b.find('name').text)) except (ParseError, AttributeError, ValueError) as e: fail("Failed to parse Volume Info: %s" % e, logger=logger) return nodes def _get_args(): parser = ArgumentParser(formatter_class=RawDescriptionHelpFormatter, description=PROG_DESCRIPTION) subparsers = parser.add_subparsers(dest="mode") # create [--debug] [--force] parser_create = subparsers.add_parser('create') parser_create.add_argument("session", help="Session Name") parser_create.add_argument("volume", help="Volume Name") parser_create.add_argument("--debug", help="Debug", action="store_true") parser_create.add_argument("--force", help="Force option to recreate " "the session", action="store_true") parser_create.add_argument("--reset-session-time", help="Reset Session Time to Current Time", action="store_true") # delete [--debug] parser_delete = subparsers.add_parser('delete') parser_delete.add_argument("session", help="Session Name") parser_delete.add_argument("volume", help="Volume Name") parser_delete.add_argument("--debug", help="Debug", action="store_true") # list [--session ] [--volume ] parser_list = subparsers.add_parser('list') parser_list.add_argument("--session", help="Session Name", default="") parser_list.add_argument("--volume", help="Volume Name", default="") parser_list.add_argument("--debug", help="Debug", action="store_true") # pre # [--output-prefix ] [--full] parser_pre = subparsers.add_parser('pre') parser_pre.add_argument("session", help="Session Name") parser_pre.add_argument("volume", help="Volume Name") parser_pre.add_argument("outfile", help="Output File", action=StoreAbsPath) parser_pre.add_argument("--debug", help="Debug", action="store_true") parser_pre.add_argument("--no-encode", help="Do not encode path in output file", action="store_true") parser_pre.add_argument("--full", help="Full find", action="store_true") parser_pre.add_argument("--disable-partial", help="Disable Partial find, " "Fail when one node fails", action="store_true") parser_pre.add_argument("--output-prefix", help="File prefix in output", default=".") parser_pre.add_argument("--regenerate-outfile", help="Regenerate outfile, discard the outfile " "generated from last pre command", action="store_true") parser_pre.add_argument("-N", "--only-namespace-changes", help="List only namespace changes", action="store_true") parser_pre.add_argument("--tag-for-full-find", help="Tag prefix for file names emitted during" " a full find operation; default: \"NEW\"", default="NEW") parser_pre.add_argument("--field-separator", help="Field separator string", default=" ") # query --since-time # [--output-prefix ] [--full] parser_query = subparsers.add_parser('query') parser_query.add_argument("volume", help="Volume Name") parser_query.add_argument("outfile", help="Output File", action=StoreAbsPath) parser_query.add_argument("--since-time", help="UNIX epoch time since " "which listing is required", type=int) parser_query.add_argument("--end-time", help="UNIX epoch time upto " "which listing is required", type=int) parser_query.add_argument("--no-encode", help="Do not encode path in output file", action="store_true") parser_query.add_argument("--full", help="Full find", action="store_true") parser_query.add_argument("--debug", help="Debug", action="store_true") parser_query.add_argument("--disable-partial", help="Disable Partial find," " Fail when one node fails", action="store_true") parser_query.add_argument("--output-prefix", help="File prefix in output", default=".") parser_query.add_argument("-N", "--only-namespace-changes", help="List only namespace changes", action="store_true") parser_query.add_argument("--tag-for-full-find", help="Tag prefix for file names emitted during" " a full find operation; default: \"NEW\"", default="NEW") parser_query.add_argument("--field-separator", help="Field separator string", default=" ") # post parser_post = subparsers.add_parser('post') parser_post.add_argument("session", help="Session Name") parser_post.add_argument("volume", help="Volume Name") parser_post.add_argument("--debug", help="Debug", action="store_true") return parser.parse_args() def ssh_setup(args): pem_key_path = get_pem_key_path(args.session, args.volume) if not os.path.exists(pem_key_path): # Generate ssh-key cmd = ["ssh-keygen", "-N", "", "-f", pem_key_path] execute(cmd, exit_msg="Unable to generate ssh key %s" % pem_key_path, logger=logger) logger.info("Ssh key generated %s" % pem_key_path) try: shutil.copyfile(pem_key_path + ".pub", os.path.join(conf.get_opt("session_dir"), ".keys", "%s_%s_secret.pem.pub" % (args.session, args.volume))) except (IOError, OSError) as e: fail("Failed to copy public key to %s: %s" % (os.path.join(conf.get_opt("session_dir"), ".keys"), e), logger=logger) # Copy pub file to all nodes cmd = ["gluster", "system::", "copy", "file", "/glusterfind/.keys/%s.pub" % os.path.basename(pem_key_path)] execute(cmd, exit_msg="Failed to distribute ssh keys", logger=logger) logger.info("Distributed ssh key to all nodes of Volume") # Add to authorized_keys file in each node cmd = ["gluster", "system::", "execute", "add_secret_pub", "root", "/glusterfind/.keys/%s.pub" % os.path.basename(pem_key_path)] execute(cmd, exit_msg="Failed to add ssh keys to authorized_keys file", logger=logger) logger.info("Ssh key added to authorized_keys of Volume nodes") def enable_volume_options(args): execute(["gluster", "volume", "set", args.volume, "build-pgfid", "on"], exit_msg="Failed to set volume option build-pgfid on", logger=logger) logger.info("Volume option set %s, build-pgfid on" % args.volume) execute(["gluster", "volume", "set", args.volume, "changelog.changelog", "on"], exit_msg="Failed to set volume option " "changelog.changelog on", logger=logger) logger.info("Volume option set %s, changelog.changelog on" % args.volume) execute(["gluster", "volume", "set", args.volume, "changelog.capture-del-path", "on"], exit_msg="Failed to set volume option " "changelog.capture-del-path on", logger=logger) logger.info("Volume option set %s, changelog.capture-del-path on" % args.volume) def write_output(outfile, outfilemerger, field_separator): with codecs.open(outfile, "a", encoding="utf-8") as f: for row in outfilemerger.get(): # Multiple paths in case of Hardlinks paths = row[1].split(",") row_2_rep = None for p in paths: if p == "": continue p_rep = p.replace("//", "/") if not row_2_rep: row_2_rep = row[2].replace("//", "/") if p_rep == row_2_rep: continue if row_2_rep and row_2_rep != "": f.write(u"{0}{1}{2}{3}{4}\n".format(row[0], field_separator, p_rep, field_separator, row_2_rep)) else: f.write(u"{0}{1}{2}\n".format(row[0], field_separator, p_rep)) def mode_create(session_dir, args): logger.debug("Init is called - Session: %s, Volume: %s" % (args.session, args.volume)) cmd = ["gluster", 'volume', 'info', args.volume, "--xml"] _, data, _ = execute(cmd, exit_msg="Failed to Run Gluster Volume Info", logger=logger) try: tree = etree.fromstring(data) statusStr = tree.find('volInfo/volumes/volume/statusStr').text except (ParseError, AttributeError) as e: fail("Invalid Volume: %s" % e, logger=logger) if statusStr != "Started": fail("Volume %s is not online" % args.volume, logger=logger) mkdirp(session_dir, exit_on_err=True, logger=logger) mkdirp(os.path.join(session_dir, args.volume), exit_on_err=True, logger=logger) status_file = os.path.join(session_dir, args.volume, "status") if os.path.exists(status_file) and not args.force: fail("Session %s already created" % args.session, logger=logger) if not os.path.exists(status_file) or args.force: ssh_setup(args) enable_volume_options(args) # Add Rollover time to current time to make sure changelogs # will be available if we use this time as start time time_to_update = int(time.time()) + get_changelog_rollover_time( args.volume) run_cmd_nodes("create", args, time_to_update=str(time_to_update)) if not os.path.exists(status_file) or args.reset_session_time: with open(status_file, "w", buffering=0) as f: f.write(str(time_to_update)) sys.stdout.write("Session %s created with volume %s\n" % (args.session, args.volume)) sys.exit(0) def mode_query(session_dir, args): global gtmpfilename # Verify volume status cmd = ["gluster", 'volume', 'info', args.volume, "--xml"] _, data, _ = execute(cmd, exit_msg="Failed to Run Gluster Volume Info", logger=logger) try: tree = etree.fromstring(data) statusStr = tree.find('volInfo/volumes/volume/statusStr').text except (ParseError, AttributeError) as e: fail("Invalid Volume: %s" % e, logger=logger) if statusStr != "Started": fail("Volume %s is not online" % args.volume, logger=logger) mkdirp(session_dir, exit_on_err=True, logger=logger) mkdirp(os.path.join(session_dir, args.volume), exit_on_err=True, logger=logger) mkdirp(os.path.dirname(args.outfile), exit_on_err=True, logger=logger) # Configure cluster for pasword-less SSH ssh_setup(args) # Enable volume options for changelog capture enable_volume_options(args) # Test options if not args.since_time and not args.end_time and not args.full: fail("Please specify either {--since-time and optionally --end-time} " "or --full", logger=logger) if args.since_time and args.end_time and args.full: fail("Please specify either {--since-time and optionally --end-time} " "or --full, but not both", logger=logger) if args.end_time and not args.since_time: fail("Please specify --since-time as well", logger=logger) # Start query command processing start = -1 end = -1 if args.since_time: start = args.since_time if args.end_time: end = args.end_time else: start = 0 # --full option is handled separately logger.debug("Query is called - Session: %s, Volume: %s, " "Start time: %s, End time: %s" % ("default", args.volume, start, end)) prefix = datetime.now().strftime("%Y%m%d-%H%M%S-%f-") gtmpfilename = prefix + next(tempfile._get_candidate_names()) run_cmd_nodes("query", args, start=start, end=end, tmpfilename=gtmpfilename) # Merger if args.full: cmd = ["sort", "-u"] + node_outfiles + ["-o", args.outfile] execute(cmd, exit_msg="Failed to merge output files " "collected from nodes", logger=logger) else: # Read each Changelogs db and generate finaldb create_file(args.outfile, exit_on_err=True, logger=logger) outfilemerger = OutputMerger(args.outfile + ".db", node_outfiles) write_output(args.outfile, outfilemerger, args.field_separator) try: os.remove(args.outfile + ".db") except (IOError, OSError): pass run_cmd_nodes("cleanup", args, tmpfilename=gtmpfilename) sys.stdout.write("Generated output file %s\n" % args.outfile) def mode_pre(session_dir, args): global gtmpfilename """ Read from Session file and write to session.pre file """ endtime_to_update = int(time.time()) - get_changelog_rollover_time( args.volume) status_file = os.path.join(session_dir, args.volume, "status") status_file_pre = status_file + ".pre" mkdirp(os.path.dirname(args.outfile), exit_on_err=True, logger=logger) # If Pre status file exists and running pre command again if os.path.exists(status_file_pre) and not args.regenerate_outfile: fail("Post command is not run after last pre, " "use --regenerate-outfile") start = 0 try: with open(status_file) as f: start = int(f.read().strip()) except ValueError: pass except (OSError, IOError) as e: fail("Error Opening Session file %s: %s" % (status_file, e), logger=logger) logger.debug("Pre is called - Session: %s, Volume: %s, " "Start time: %s, End time: %s" % (args.session, args.volume, start, endtime_to_update)) prefix = datetime.now().strftime("%Y%m%d-%H%M%S-%f-") gtmpfilename = prefix + next(tempfile._get_candidate_names()) run_cmd_nodes("pre", args, start=start, end=-1, tmpfilename=gtmpfilename) # Merger if args.full: cmd = ["sort", "-u"] + node_outfiles + ["-o", args.outfile] execute(cmd, exit_msg="Failed to merge output files " "collected from nodes", logger=logger) else: # Read each Changelogs db and generate finaldb create_file(args.outfile, exit_on_err=True, logger=logger) outfilemerger = OutputMerger(args.outfile + ".db", node_outfiles) write_output(args.outfile, outfilemerger, args.field_separator) try: os.remove(args.outfile + ".db") except (IOError, OSError): pass run_cmd_nodes("cleanup", args, tmpfilename=gtmpfilename) with open(status_file_pre, "w", buffering=0) as f: f.write(str(endtime_to_update)) sys.stdout.write("Generated output file %s\n" % args.outfile) def mode_post(session_dir, args): """ If pre session file exists, overwrite session file If pre session file does not exists, return ERROR """ status_file = os.path.join(session_dir, args.volume, "status") logger.debug("Post is called - Session: %s, Volume: %s" % (args.session, args.volume)) status_file_pre = status_file + ".pre" if os.path.exists(status_file_pre): run_cmd_nodes("post", args) os.rename(status_file_pre, status_file) sys.stdout.write("Session %s with volume %s updated\n" % (args.session, args.volume)) sys.exit(0) else: fail("Pre script is not run", logger=logger) def mode_delete(session_dir, args): run_cmd_nodes("delete", args) shutil.rmtree(os.path.join(session_dir, args.volume), onerror=handle_rm_error) sys.stdout.write("Session %s with volume %s deleted\n" % (args.session, args.volume)) # If the session contains only this volume, then cleanup the # session directory. If a session contains multiple volumes # then os.rmdir will fail with ENOTEMPTY try: os.rmdir(session_dir) except OSError as e: if not e.errno == ENOTEMPTY: logger.warn("Failed to delete session directory: %s" % e) def mode_list(session_dir, args): """ List available sessions to stdout, if session name is set only list that session. """ if args.session: if not os.path.exists(os.path.join(session_dir, args.session)): fail("Invalid Session", logger=logger) sessions = [args.session] else: sessions = [] for d in os.listdir(session_dir): if d != ".keys": sessions.append(d) output = [] for session in sessions: # Session Volume Last Processed volnames = os.listdir(os.path.join(session_dir, session)) for volname in volnames: if args.volume and args.volume != volname: continue status_file = os.path.join(session_dir, session, volname, "status") last_processed = None try: with open(status_file) as f: last_processed = f.read().strip() except (OSError, IOError) as e: if e.errno == ENOENT: continue else: raise output.append((session, volname, last_processed)) if output: sys.stdout.write("%s %s %s\n" % ("SESSION".ljust(25), "VOLUME".ljust(25), "SESSION TIME".ljust(25))) sys.stdout.write("-"*75) sys.stdout.write("\n") for session, volname, last_processed in output: sess_time = 'Session Corrupted' if last_processed: try: sess_time = human_time(last_processed) except TypeError: sess_time = 'Session Corrupted' sys.stdout.write("%s %s %s\n" % (session.ljust(25), volname.ljust(25), sess_time.ljust(25))) if not output: if args.session or args.volume: fail("Invalid Session", logger=logger) else: sys.stdout.write("No sessions found.\n") def main(): global gtmpfilename args = None try: args = _get_args() mkdirp(conf.get_opt("session_dir"), exit_on_err=True) # force the default session name if mode is "query" if args.mode == "query": args.session = "default" if args.mode == "list": session_dir = conf.get_opt("session_dir") else: session_dir = os.path.join(conf.get_opt("session_dir"), args.session) if not os.path.exists(session_dir) and \ args.mode not in ["create", "list", "query"]: fail("Invalid session %s" % args.session) # "default" is a system defined session name if args.mode in ["create", "post", "pre", "delete"] and \ args.session == "default": fail("Invalid session %s" % args.session) vol_dir = os.path.join(session_dir, args.volume) if not os.path.exists(vol_dir) and args.mode not in \ ["create", "list", "query"]: fail("Session %s not created with volume %s" % (args.session, args.volume)) mkdirp(os.path.join(conf.get_opt("log_dir"), args.session, args.volume), exit_on_err=True) log_file = os.path.join(conf.get_opt("log_dir"), args.session, args.volume, "cli.log") setup_logger(logger, log_file, args.debug) # globals() will have all the functions already defined. # mode_ will be the function name to be called globals()["mode_" + args.mode](session_dir, args) except KeyboardInterrupt: if args is not None: if args.mode == "pre" or args.mode == "query": # cleanup session if gtmpfilename is not None: # no more interrupts until we clean up signal.signal(signal.SIGINT, signal.SIG_IGN) run_cmd_nodes("cleanup", args, tmpfilename=gtmpfilename) # Interrupted, exit with non zero error code sys.exit(2) glusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/__init__.py0000644000000000000000000000013213230626775023146 xustar000000000000000030 mtime=1516449277.365372348 30 atime=1516449277.365372348 30 ctime=1516449330.013494467 glusterfs-3.13.2/tools/glusterfind/src/__init__.py0000664000175100017510000000057513230626775023416 0ustar00jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2015 Red Hat, Inc. # This file is part of GlusterFS. # # 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. glusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/utils.py0000644000000000000000000000013113230626775022546 xustar000000000000000030 mtime=1516449277.366372351 30 atime=1516449277.366372351 29 ctime=1516449330.01049446 glusterfs-3.13.2/tools/glusterfind/src/utils.py0000664000175100017510000001603613230626775023016 0ustar00jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2015 Red Hat, Inc. # This file is part of GlusterFS. # # 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. import sys from subprocess import PIPE, Popen from errno import EEXIST, ENOENT import xml.etree.cElementTree as etree import logging import os from datetime import datetime ROOT_GFID = "00000000-0000-0000-0000-000000000001" DEFAULT_CHANGELOG_INTERVAL = 15 SPACE_ESCAPE_CHAR = "%20" NEWLINE_ESCAPE_CHAR = "%0A" PERCENTAGE_ESCAPE_CHAR = "%25" ParseError = etree.ParseError if hasattr(etree, 'ParseError') else SyntaxError cache_data = {} class RecordType(object): NEW = "NEW" MODIFY = "MODIFY" RENAME = "RENAME" DELETE = "DELETE" def cache_output(func): def wrapper(*args, **kwargs): global cache_data if cache_data.get(func.func_name, None) is None: cache_data[func.func_name] = func(*args, **kwargs) return cache_data[func.func_name] return wrapper def handle_rm_error(func, path, exc_info): if exc_info[1].errno == ENOENT: return raise exc_info[1] def find(path, callback_func=lambda x: True, filter_func=lambda x: True, ignore_dirs=[], subdirs_crawl=True): if path in ignore_dirs: return # Capture filter_func output and pass it to callback function filter_result = filter_func(path) if filter_result is not None: callback_func(path, filter_result) for p in os.listdir(path): full_path = os.path.join(path, p) if os.path.isdir(full_path): if subdirs_crawl: find(full_path, callback_func, filter_func, ignore_dirs) else: filter_result = filter_func(full_path) if filter_result is not None: callback_func(full_path, filter_result) else: filter_result = filter_func(full_path) if filter_result is not None: callback_func(full_path, filter_result) def output_write(f, path, prefix=".", encode=False, tag="", field_separator=" "): if path == "": return if prefix != ".": path = os.path.join(prefix, path) if encode: path = quote_plus_space_newline(path) # set the field separator FS = "" if tag == "" else field_separator f.write("%s%s%s\n" % (tag.strip(), FS, path)) def human_time(ts): return datetime.fromtimestamp(float(ts)).strftime("%Y-%m-%d %H:%M:%S") def setup_logger(logger, path, debug=False): if debug: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) # create the logging file handler fh = logging.FileHandler(path) formatter = logging.Formatter("[%(asctime)s] %(levelname)s " "[%(module)s - %(lineno)s:%(funcName)s] " "- %(message)s") fh.setFormatter(formatter) # add handler to logger object logger.addHandler(fh) def create_file(path, exit_on_err=False, logger=None): """ If file exists overwrite. Print error to stderr and exit if exit_on_err is set, else raise the exception. Consumer should handle the exception. """ try: open(path, 'w').close() except (OSError, IOError) as e: if exit_on_err: fail("Failed to create file %s: %s" % (path, e), logger=logger) else: raise def mkdirp(path, exit_on_err=False, logger=None): """ Try creating required directory structure ignore EEXIST and raise exception for rest of the errors. Print error in stderr and exit if exit_on_err is set, else raise exception. """ try: os.makedirs(path) except (OSError, IOError) as e: if e.errno == EEXIST and os.path.isdir(path): pass else: if exit_on_err: fail("Fail to create dir %s: %s" % (path, e), logger=logger) else: raise def fail(msg, code=1, logger=None): """ Write error to stderr and exit """ if logger: logger.error(msg) sys.stderr.write("%s\n" % msg) sys.exit(code) def execute(cmd, exit_msg=None, logger=None): """ If failure_msg is not None then return returncode, out and error. If failure msg is set, write to stderr and exit. """ p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) (out, err) = p.communicate() if p.returncode != 0 and exit_msg is not None: fail("%s: %s" % (exit_msg, err), p.returncode, logger=logger) return (p.returncode, out, err) def symlink_gfid_to_path(brick, gfid): """ Each directories are symlinked to file named GFID in .glusterfs directory of brick backend. Using readlink we get PARGFID/basename of dir. readlink recursively till we get PARGFID as ROOT_GFID. """ if gfid == ROOT_GFID: return "" out_path = "" while True: path = os.path.join(brick, ".glusterfs", gfid[0:2], gfid[2:4], gfid) path_readlink = os.readlink(path) pgfid = os.path.dirname(path_readlink) out_path = os.path.join(os.path.basename(path_readlink), out_path) if pgfid == "../../00/00/%s" % ROOT_GFID: break gfid = os.path.basename(pgfid) return out_path @cache_output def get_my_uuid(): cmd = ["gluster", "system::", "uuid", "get", "--xml"] rc, out, err = execute(cmd) if rc != 0: return None tree = etree.fromstring(out) uuid_el = tree.find("uuidGenerate/uuid") return uuid_el.text def is_host_local(host_uuid): # Get UUID only if it is not done previously # else Cache the UUID value my_uuid = get_my_uuid() if my_uuid == host_uuid: return True return False def get_changelog_rollover_time(volumename): cmd = ["gluster", "volume", "get", volumename, "changelog.rollover-time", "--xml"] rc, out, err = execute(cmd) if rc != 0: return DEFAULT_CHANGELOG_INTERVAL try: tree = etree.fromstring(out) return int(tree.find('volGetopts/Opt/Value').text) except ParseError: return DEFAULT_CHANGELOG_INTERVAL def output_path_prepare(path, args): """ If Prefix is set, joins to Path, removes ending slash and encodes it. """ if args.output_prefix != ".": path = os.path.join(args.output_prefix, path) if path.endswith("/"): path = path[0:len(path)-1] if args.no_encode: return path else: return quote_plus_space_newline(path) def unquote_plus_space_newline(s): return s.replace(SPACE_ESCAPE_CHAR, " ")\ .replace(NEWLINE_ESCAPE_CHAR, "\n")\ .replace(PERCENTAGE_ESCAPE_CHAR, "%") def quote_plus_space_newline(s): return s.replace("%", PERCENTAGE_ESCAPE_CHAR)\ .replace(" ", SPACE_ESCAPE_CHAR)\ .replace("\n", NEWLINE_ESCAPE_CHAR) glusterfs-3.13.2/tools/glusterfind/src/PaxHeaders.5796/brickfind.py0000644000000000000000000000013213230626775023342 xustar000000000000000030 mtime=1516449277.365372348 30 atime=1516449277.365372348 30 ctime=1516449330.029494504 glusterfs-3.13.2/tools/glusterfind/src/brickfind.py0000664000175100017510000000714713230626775023614 0ustar00jenkinsjenkins00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2015 Red Hat, Inc. # This file is part of GlusterFS. # # 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. import os import sys import logging from argparse import ArgumentParser, RawDescriptionHelpFormatter import urllib import time from utils import mkdirp, setup_logger, create_file, output_write, find import conf PROG_DESCRIPTION = """ Changelog Crawler """ logger = logging.getLogger() def brickfind_crawl(brick, args): if brick.endswith("/"): brick = brick[0:len(brick)-1] working_dir = os.path.dirname(args.outfile) mkdirp(working_dir, exit_on_err=True, logger=logger) create_file(args.outfile, exit_on_err=True, logger=logger) with open(args.outfile, "a+") as fout: brick_path_len = len(brick) def output_callback(path, filter_result): path = path.strip() path = path[brick_path_len+1:] output_write(fout, path, args.output_prefix, encode=(not args.no_encode), tag=args.tag, field_separator=args.field_separator) ignore_dirs = [os.path.join(brick, dirname) for dirname in conf.get_opt("brick_ignore_dirs").split(",")] find(brick, callback_func=output_callback, ignore_dirs=ignore_dirs) fout.flush() os.fsync(fout.fileno()) def _get_args(): parser = ArgumentParser(formatter_class=RawDescriptionHelpFormatter, description=PROG_DESCRIPTION) parser.add_argument("session", help="Session Name") parser.add_argument("volume", help="Volume Name") parser.add_argument("node", help="Node Name") parser.add_argument("brick", help="Brick Name") parser.add_argument("outfile", help="Output File") parser.add_argument("tag", help="Tag to prefix file name with") parser.add_argument("--only-query", help="Only query, No session update", action="store_true") parser.add_argument("--debug", help="Debug", action="store_true") parser.add_argument("--no-encode", help="Do not encode path in outfile", action="store_true") parser.add_argument("--output-prefix", help="File prefix in output", default=".") parser.add_argument("--field-separator", help="Field separator", default=" ") return parser.parse_args() if __name__ == "__main__": args = _get_args() session_dir = os.path.join(conf.get_opt("session_dir"), args.session) status_file = os.path.join(session_dir, args.volume, "%s.status" % urllib.quote_plus(args.brick)) status_file_pre = status_file + ".pre" mkdirp(os.path.join(session_dir, args.volume), exit_on_err=True, logger=logger) mkdirp(os.path.join(conf.get_opt("log_dir"), args.session, args.volume), exit_on_err=True) log_file = os.path.join(conf.get_opt("log_dir"), args.session, args.volume, "brickfind.log") setup_logger(logger, log_file, args.debug) time_to_update = int(time.time()) brickfind_crawl(args.brick, args) if not args.only_query: with open(status_file_pre, "w", buffering=0) as f: f.write(str(time_to_update)) sys.exit(0) glusterfs-3.13.2/tools/glusterfind/PaxHeaders.5796/S57glusterfind-delete-post.py0000644000000000000000000000013213230626775025670 xustar000000000000000030 mtime=1516449277.364372346 30 atime=1516449277.364372346 30 ctime=1516449329.929494272 glusterfs-3.13.2/tools/glusterfind/S57glusterfind-delete-post.py0000775000175100017510000000346513230626775026144 0ustar00jenkinsjenkins00000000000000#!/usr/bin/python import os import shutil from errno import ENOENT from subprocess import Popen, PIPE from argparse import ArgumentParser DEFAULT_GLUSTERD_WORKDIR = "/var/lib/glusterd" def handle_rm_error(func, path, exc_info): if exc_info[1].errno == ENOENT: return raise exc_info[1] def get_glusterd_workdir(): p = Popen(["gluster", "system::", "getwd"], stdout=PIPE, stderr=PIPE) out, _ = p.communicate() if p.returncode == 0: return out.strip() else: return DEFAULT_GLUSTERD_WORKDIR def get_args(): parser = ArgumentParser(description="Volume delete post hook script") parser.add_argument("--volname") return parser.parse_args() def main(): args = get_args() glusterfind_dir = os.path.join(get_glusterd_workdir(), "glusterfind") # Check all session directories, if any directory found for # the deleted volume, cleanup all the session directories try: ls_glusterfind_dir = os.listdir(glusterfind_dir) except OSError: ls_glusterfind_dir = [] for session in ls_glusterfind_dir: # don't blow away the keys directory if session == ".keys": continue # Possible session directory volume_session_path = os.path.join(glusterfind_dir, session, args.volname) if os.path.exists(volume_session_path): shutil.rmtree(volume_session_path, onerror=handle_rm_error) # Try to Remove directory, if any other dir exists for different # volume, then rmdir will fail with ENOTEMPTY which is fine try: os.rmdir(os.path.join(glusterfind_dir, session)) except (OSError, IOError): pass if __name__ == "__main__": main() glusterfs-3.13.2/tools/glusterfind/PaxHeaders.5796/glusterfind.in0000644000000000000000000000013213230626775023124 xustar000000000000000030 mtime=1516449277.365372348 30 atime=1516449311.130450677 30 ctime=1516449329.926494265 glusterfs-3.13.2/tools/glusterfind/glusterfind.in0000664000175100017510000000077713230626775023400 0ustar00jenkinsjenkins00000000000000#!/usr/bin/env python # Copyright (c) 2015 Red Hat, Inc. # This file is part of GlusterFS. # # 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. import sys sys.path.insert(1, '@GLUSTERFS_LIBEXECDIR@/') from glusterfind.main import main if __name__ == "__main__": main() glusterfs-3.13.2/tools/glusterfind/PaxHeaders.5796/Makefile.in0000644000000000000000000000013213230627006022277 xustar000000000000000030 mtime=1516449286.795394228 30 atime=1516449311.154450732 30 ctime=1516449329.920494251 glusterfs-3.13.2/tools/glusterfind/Makefile.in0000664000175100017510000006603113230627006022546 0ustar00jenkinsjenkins00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tools/glusterfind DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/glusterfind.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/contrib/aclocal/mkdirp.m4 \ $(top_srcdir)/contrib/aclocal/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h $(top_builddir)/site.h CONFIG_CLEAN_FILES = glusterfind CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(deletehookscriptsdir)" SCRIPTS = $(bin_SCRIPTS) $(deletehookscripts_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ACL_LIBS = @ACL_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LIBTOOLFLAGS = @AM_LIBTOOLFLAGS@ AM_MAKEFLAGS = @AM_MAKEFLAGS@ AR = @AR@ ARGP_STANDALONE_CPPFLAGS = @ARGP_STANDALONE_CPPFLAGS@ ARGP_STANDALONE_DIR = @ARGP_STANDALONE_DIR@ ARGP_STANDALONE_LDADD = @ARGP_STANDALONE_LDADD@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_PYTHON_INC = @BUILD_PYTHON_INC@ BUILD_PYTHON_LIB = @BUILD_PYTHON_LIB@ BUILD_PYTHON_SITE_PACKAGES = @BUILD_PYTHON_SITE_PACKAGES@ BUILD_PYTHON_SITE_PACKAGES_EXPANDED = @BUILD_PYTHON_SITE_PACKAGES_EXPANDED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONTRIBDIR = @CONTRIBDIR@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EVENTS_ENABLED = @EVENTS_ENABLED@ EVENTS_SUBDIR = @EVENTS_SUBDIR@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FUSERMOUNT_SUBDIR = @FUSERMOUNT_SUBDIR@ FUSE_CLIENT_SUBDIR = @FUSE_CLIENT_SUBDIR@ GEOREP_EXTRAS_SUBDIR = @GEOREP_EXTRAS_SUBDIR@ GFAPI_EXTRA_LDFLAGS = @GFAPI_EXTRA_LDFLAGS@ GFAPI_LIBS = @GFAPI_LIBS@ GFAPI_LT_VERSION = @GFAPI_LT_VERSION@ GFAPI_VERSION = @GFAPI_VERSION@ GF_CFLAGS = @GF_CFLAGS@ GF_CPPFLAGS = @GF_CPPFLAGS@ GF_DISTRIBUTION = @GF_DISTRIBUTION@ GF_FUSE_CFLAGS = @GF_FUSE_CFLAGS@ GF_FUSE_LDADD = @GF_FUSE_LDADD@ GF_HOST_OS = @GF_HOST_OS@ GF_LDADD = @GF_LDADD@ GF_LDFLAGS = @GF_LDFLAGS@ GF_XLATOR_DEFAULT_LDFLAGS = @GF_XLATOR_DEFAULT_LDFLAGS@ GLUPY_SUBDIR = @GLUPY_SUBDIR@ GLUPY_SUBDIR_MAKEFILE = @GLUPY_SUBDIR_MAKEFILE@ GLUPY_SUBDIR_SRC_MAKEFILE = @GLUPY_SUBDIR_SRC_MAKEFILE@ GLUSTERD_VOLFILE = @GLUSTERD_VOLFILE@ GLUSTERD_WORKDIR = @GLUSTERD_WORKDIR@ GLUSTERFSD_MISCDIR = @GLUSTERFSD_MISCDIR@ GLUSTERFS_LIBEXECDIR = @GLUSTERFS_LIBEXECDIR@ GREP = @GREP@ HAVE_ATOMIC_BUILTINS = @HAVE_ATOMIC_BUILTINS@ HAVE_BACKTRACE = @HAVE_BACKTRACE@ HAVE_LINKAT = @HAVE_LINKAT@ HAVE_MALLOC_STATS = @HAVE_MALLOC_STATS@ HAVE_SPINLOCK = @HAVE_SPINLOCK@ HAVE_STRNLEN = @HAVE_STRNLEN@ HAVE_SYNC_BUILTINS = @HAVE_SYNC_BUILTINS@ IBVERBS_SUBDIR = @IBVERBS_SUBDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBAIO = @LIBAIO@ LIBGFCHANGELOG_LT_VERSION = @LIBGFCHANGELOG_LT_VERSION@ LIBGFCHANGELOG_VERSION = @LIBGFCHANGELOG_VERSION@ LIBGFDB_VERSION = @LIBGFDB_VERSION@ LIBGFRPC_LT_VERSION = @LIBGFRPC_LT_VERSION@ LIBGFXDR_LT_VERSION = @LIBGFXDR_LT_VERSION@ LIBGLUSTERFS_LT_VERSION = @LIBGLUSTERFS_LT_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OCF_SUBDIR = @OCF_SUBDIR@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_RELEASE = @PACKAGE_RELEASE@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKGCONFIG_UUID = @PKGCONFIG_UUID@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHONDEV_CPPFLAGS = @PYTHONDEV_CPPFLAGS@ PYTHONDEV_LDFLAGS = @PYTHONDEV_LDFLAGS@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDMA_SUBDIR = @RDMA_SUBDIR@ RLLIBS = @RLLIBS@ RPCGEN = @RPCGEN@ SBIN_DIR = @SBIN_DIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SIZEOF_INT = @SIZEOF_INT@ SIZEOF_LONG = @SIZEOF_LONG@ SIZEOF_LONG_LONG = @SIZEOF_LONG_LONG@ SIZEOF_SHORT = @SIZEOF_SHORT@ SQLITE_CFLAGS = @SQLITE_CFLAGS@ SQLITE_LIBS = @SQLITE_LIBS@ STRIP = @STRIP@ SYNCDAEMON_COMPILE = @SYNCDAEMON_COMPILE@ SYNCDAEMON_SUBDIR = @SYNCDAEMON_SUBDIR@ SYSCONF_DIR = @SYSCONF_DIR@ UMOUNTD_SUBDIR = @UMOUNTD_SUBDIR@ UNITTEST_CFLAGS = @UNITTEST_CFLAGS@ UNITTEST_LDFLAGS = @UNITTEST_LDFLAGS@ UNITTEST_LIBS = @UNITTEST_LIBS@ URCU_CDS_CFLAGS = @URCU_CDS_CFLAGS@ URCU_CDS_LIBS = @URCU_CDS_LIBS@ URCU_CFLAGS = @URCU_CFLAGS@ URCU_LIBS = @URCU_LIBS@ USE_EC_DYNAMIC_AVX = @USE_EC_DYNAMIC_AVX@ USE_EC_DYNAMIC_NEON = @USE_EC_DYNAMIC_NEON@ USE_EC_DYNAMIC_SSE = @USE_EC_DYNAMIC_SSE@ USE_EC_DYNAMIC_X64 = @USE_EC_DYNAMIC_X64@ USE_POSIX_ACLS = @USE_POSIX_ACLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ initdir = @initdir@ install_sh = @install_sh@ launchddir = @launchddir@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mountutildir = @mountutildir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ shrext_cmds = @shrext_cmds@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ systemddir = @systemddir@ target_alias = @target_alias@ tmpfilesdir = @tmpfilesdir@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src EXTRA_DIST = S57glusterfind-delete-post.py bin_SCRIPTS = glusterfind CLEANFILES = $(bin_SCRIPTS) deletehookscriptsdir = $(GLUSTERFS_LIBEXECDIR)/glusterfind/ deletehookscripts_SCRIPTS = S57glusterfind-delete-post.py all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tools/glusterfind/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tools/glusterfind/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): glusterfind: $(top_builddir)/config.status $(srcdir)/glusterfind.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) install-deletehookscriptsSCRIPTS: $(deletehookscripts_SCRIPTS) @$(NORMAL_INSTALL) @list='$(deletehookscripts_SCRIPTS)'; test -n "$(deletehookscriptsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(deletehookscriptsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(deletehookscriptsdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(deletehookscriptsdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(deletehookscriptsdir)$$dir" || exit $$?; \ } \ ; done uninstall-deletehookscriptsSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(deletehookscripts_SCRIPTS)'; test -n "$(deletehookscriptsdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(deletehookscriptsdir)'; $(am__uninstall_files_from_dir) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(SCRIPTS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(deletehookscriptsdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-data-local install-deletehookscriptsSCRIPTS install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binSCRIPTS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binSCRIPTS uninstall-deletehookscriptsSCRIPTS \ uninstall-local .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binSCRIPTS install-data \ install-data-am install-data-local \ install-deletehookscriptsSCRIPTS install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binSCRIPTS \ uninstall-deletehookscriptsSCRIPTS uninstall-local uninstall-local: rm -f $(DESTDIR)$(GLUSTERD_WORKDIR)/hooks/1/delete/post/S57glusterfind-delete-post install-data-local: $(mkdir_p) $(DESTDIR)$(GLUSTERD_WORKDIR)/glusterfind/.keys $(mkdir_p) $(DESTDIR)$(GLUSTERD_WORKDIR)/hooks/1/delete/post/ rm -f $(DESTDIR)$(GLUSTERD_WORKDIR)/hooks/1/delete/post/S57glusterfind-delete-post ln -s $(GLUSTERFS_LIBEXECDIR)/glusterfind/S57glusterfind-delete-post.py \ $(DESTDIR)$(GLUSTERD_WORKDIR)/hooks/1/delete/post/S57glusterfind-delete-post # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: glusterfs-3.13.2/PaxHeaders.5796/cli0000644000000000000000000000013213230627061015237 xustar000000000000000030 mtime=1516449329.289492788 30 atime=1516449330.837496377 30 ctime=1516449329.289492788 glusterfs-3.13.2/cli/0002775000175100017510000000000013230627061015557 5ustar00jenkinsjenkins00000000000000glusterfs-3.13.2/cli/PaxHeaders.5796/Makefile.am0000644000000000000000000000013213230626775017363 xustar000000000000000030 mtime=1516449277.172371901 30 atime=1516449284.071387908 30 ctime=1516449329.284492776 glusterfs-3.13.2/cli/Makefile.am0000664000175100017510000000003413230626775017621 0ustar00jenkinsjenkins00000000000000SUBDIRS = src CLEANFILES = glusterfs-3.13.2/cli/PaxHeaders.5796/src0000644000000000000000000000013113230627061016025 xustar000000000000000030 mtime=1516449329.368492971 29 atime=1516449330.83849638 30 ctime=1516449329.368492971 glusterfs-3.13.2/cli/src/0002775000175100017510000000000013230627061016346 5ustar00jenkinsjenkins00000000000000glusterfs-3.13.2/cli/src/PaxHeaders.5796/cli-cmd.c0000644000000000000000000000013013230626775017570 xustar000000000000000029 mtime=1516449277.17637191 29 atime=1516449277.17637191 30 ctime=1516449329.348492925 glusterfs-3.13.2/cli/src/cli-cmd.c0000664000175100017510000002314613230626775020041 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2010-2012 Red Hat, Inc. This file is part of GlusterFS. 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 #include #include "cli.h" #include "cli-cmd.h" #include "cli-mem-types.h" #include "protocol-common.h" #include static int cmd_done; static int cmd_sent; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t conn = PTHREAD_COND_INITIALIZER; static pthread_mutex_t conn_mutex = PTHREAD_MUTEX_INITIALIZER; int cli_op_ret = 0; int connected = 0; int cli_cmd_log_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word, const char **words, int wordcount); static unsigned cli_cmd_needs_connection (struct cli_cmd_word *word) { if (!strcasecmp ("quit", word->word)) return 0; if (!strcasecmp ("help", word->word)) return 0; if (!strcasecmp ("getwd", word->word)) return 1; if (!strcasecmp ("exit", word->word)) return 0; return cli_default_conn_timeout; } int cli_cmd_status_reset (void) { int ret = 0; ret = cli_cmd_lock (); { if (ret == 0) { cmd_sent = 0; cmd_done = 0; } } ret = cli_cmd_unlock (); return ret; } int cli_cmd_sent_status_get (int *status) { int ret = 0; GF_ASSERT (status); ret = cli_cmd_lock (); { if (ret == 0) *status = cmd_sent; } ret = cli_cmd_unlock (); return ret; } int cli_cmd_process (struct cli_state *state, int argc, char **argv) { int ret = 0; struct cli_cmd_word *word = NULL; struct cli_cmd_word *next = NULL; int i = 0; word = &state->tree.root; if (!argc) return 0; for (i = 0; i < argc; i++) { next = cli_cmd_nextword (word, argv[i]); word = next; if (!word) break; if (word->cbkfn) break; } if (!word) { cli_out ("unrecognized word: %s (position %d)", argv[i], i); return -1; } if (!word->cbkfn) { cli_out ("unrecognized command"); return -1; } if ( strcmp (word->word,"help")==0 ) goto callback; state->await_connected = cli_cmd_needs_connection (word); ret = cli_cmd_await_connected (state->await_connected); if (ret) { cli_out ("Connection failed. Please check if gluster " "daemon is operational."); gf_log ("", GF_LOG_INFO, "Exiting with: %d", ret); exit (ret); } callback: ret = word->cbkfn (state, word, (const char **)argv, argc); (void) cli_cmd_status_reset (); return ret; } int cli_cmd_input_token_count (const char *text) { int count = 0; const char *trav = NULL; int is_spc = 1; for (trav = text; *trav; trav++) { if (*trav == ' ') { is_spc = 1; } else { if (is_spc) { count++; is_spc = 0; } } } return count; } int cli_cmd_process_line (struct cli_state *state, const char *text) { int count = 0; char **tokens = NULL; char **tokenp = NULL; char *token = NULL; char *copy = NULL; char *saveptr = NULL; int i = 0; int ret = -1; count = cli_cmd_input_token_count (text); tokens = calloc (count + 1, sizeof (*tokens)); if (!tokens) return -1; copy = strdup (text); if (!copy) goto out; tokenp = tokens; for (token = strtok_r (copy, " \t\r\n", &saveptr); token; token = strtok_r (NULL, " \t\r\n", &saveptr)) { *tokenp = strdup (token); if (!*tokenp) goto out; tokenp++; i++; } ret = cli_cmd_process (state, count, tokens); out: free (copy); if (tokens) cli_cmd_tokens_destroy (tokens); return ret; } int cli_cmds_register (struct cli_state *state) { int ret = 0; ret = cli_cmd_volume_register (state); if (ret) goto out; ret = cli_cmd_probe_register (state); if (ret) goto out; ret = cli_cmd_system_register (state); if (ret) goto out; ret = cli_cmd_misc_register (state); if (ret) goto out; ret = cli_cmd_snapshot_register (state); if (ret) goto out; ret = cli_cmd_global_register (state); if (ret) goto out; out: return ret; } int cli_cmd_cond_init () { pthread_mutex_init (&cond_mutex, NULL); pthread_cond_init (&cond, NULL); pthread_mutex_init (&conn_mutex, NULL); pthread_cond_init (&conn, NULL); return 0; } int cli_cmd_lock () { pthread_mutex_lock (&cond_mutex); return 0; } int cli_cmd_unlock () { pthread_mutex_unlock (&cond_mutex); return 0; } static void seconds_from_now (unsigned secs, struct timespec *ts) { struct timeval tv = {0,}; gettimeofday (&tv, NULL); ts->tv_sec = tv.tv_sec + secs; ts->tv_nsec = tv.tv_usec * 1000; } int cli_cmd_await_response (unsigned time) { struct timespec ts = {0,}; int ret = 0; cli_op_ret = -1; seconds_from_now (time, &ts); while (!cmd_done && !ret) { ret = pthread_cond_timedwait (&cond, &cond_mutex, &ts); } if (!cmd_done) { if (ret == ETIMEDOUT) cli_out ("Error : Request timed out"); else cli_out ("Error : Command returned with error code:%d", ret); } cmd_done = 0; return cli_op_ret; } /* This function must be called _only_ after all actions associated with * command processing is complete. Otherwise, gluster process may exit before * reporting results to stdout/stderr. */ int cli_cmd_broadcast_response (int32_t status) { pthread_mutex_lock (&cond_mutex); { if (!cmd_sent) goto out; cmd_done = 1; cli_op_ret = status; pthread_cond_broadcast (&cond); } out: pthread_mutex_unlock (&cond_mutex); return 0; } int32_t cli_cmd_await_connected (unsigned conn_timo) { int32_t ret = 0; struct timespec ts = {0,}; if (!conn_timo) return 0; pthread_mutex_lock (&conn_mutex); { seconds_from_now (conn_timo, &ts); while (!connected && !ret) { ret = pthread_cond_timedwait (&conn, &conn_mutex, &ts); } } pthread_mutex_unlock (&conn_mutex); return ret; } int32_t cli_cmd_broadcast_connected () { pthread_mutex_lock (&conn_mutex); { connected = 1; pthread_cond_broadcast (&conn); } pthread_mutex_unlock (&conn_mutex); return 0; } int cli_cmd_submit (struct rpc_clnt* rpc, void *req, call_frame_t *frame, rpc_clnt_prog_t *prog, int procnum, struct iobref *iobref, xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc) { int ret = -1; unsigned timeout = 0; if ((GLUSTER_CLI_PROFILE_VOLUME == procnum) || (GLUSTER_CLI_HEAL_VOLUME == procnum)) timeout = cli_ten_minutes_timeout; else timeout = cli_default_conn_timeout; cli_cmd_lock (); cmd_sent = 0; ret = cli_submit_request (rpc, req, frame, prog, procnum, NULL, this, cbkfn, xdrproc); if (!ret) { cmd_sent = 1; ret = cli_cmd_await_response (timeout); } cli_cmd_unlock (); gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_cmd_pattern_cmp (void *a, void *b) { struct cli_cmd *ia = NULL; struct cli_cmd *ib = NULL; int ret = 0; ia = a; ib = b; if (strcmp (ia->pattern, ib->pattern) > 0) ret = 1; else if (strcmp (ia->pattern, ib->pattern) < 0) ret = -1; else ret = 0; return ret; } void cli_cmd_sort (struct cli_cmd *cmd, int count) { gf_array_insertionsort (cmd, 1, count - 2, sizeof(struct cli_cmd), cli_cmd_pattern_cmp); } glusterfs-3.13.2/cli/src/PaxHeaders.5796/cli-rpc-ops.c0000644000000000000000000000013213230626775020412 xustar000000000000000030 mtime=1516449277.181371921 30 atime=1516449277.178371915 30 ctime=1516449329.357492946 glusterfs-3.13.2/cli/src/cli-rpc-ops.c0000664000175100017510000151255013230626775020664 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2010-2012 Red Hat, Inc. This file is part of GlusterFS. 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. */ /* Widths of various columns in top read/write-perf output * Total width of top read/write-perf should be 80 chars * including one space between column */ #define VOL_TOP_PERF_FILENAME_DEF_WIDTH 47 #define VOL_TOP_PERF_FILENAME_ALT_WIDTH 44 #define VOL_TOP_PERF_SPEED_WIDTH 4 #define VOL_TOP_PERF_TIME_WIDTH 26 #define INDENT_MAIN_HEAD "%-25s %s " /* Do not show estimates if greater than this number */ #define REBAL_ESTIMATE_SEC_UPPER_LIMIT (60*24*3600) #define REBAL_ESTIMATE_START_TIME 600 #include "cli.h" #include "compat-errno.h" #include "cli-cmd.h" #include #include #include #include "cli1-xdr.h" #include "xdr-generic.h" #include "protocol-common.h" #include "cli-mem-types.h" #include "compat.h" #include "upcall-utils.h" #include "syscall.h" #include "glusterfs3.h" #include "portmap-xdr.h" #include "byte-order.h" #include "cli-quotad-client.h" #include "run.h" #include "quota-common-utils.h" #include "events.h" enum gf_task_types { GF_TASK_TYPE_REBALANCE, GF_TASK_TYPE_REMOVE_BRICK }; extern struct rpc_clnt *global_quotad_rpc; extern rpc_clnt_prog_t cli_quotad_clnt; extern rpc_clnt_prog_t *cli_rpc_prog; extern int cli_op_ret; extern int connected; int32_t gf_cli_remove_brick (call_frame_t *frame, xlator_t *this, void *data); char *cli_vol_status_str[] = {"Created", "Started", "Stopped", }; char *cli_vol_task_status_str[] = {"not started", "in progress", "stopped", "completed", "failed", "fix-layout in progress", "fix-layout stopped", "fix-layout completed", "fix-layout failed", "unknown" }; int32_t gf_cli_snapshot (call_frame_t *frame, xlator_t *this, void *data); int32_t gf_cli_get_volume (call_frame_t *frame, xlator_t *this, void *data); int cli_to_glusterd (gf_cli_req *req, call_frame_t *frame, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc, dict_t *dict, int procnum, xlator_t *this, rpc_clnt_prog_t *prog, struct iobref *iobref); rpc_clnt_prog_t cli_handshake_prog = { .progname = "cli handshake", .prognum = GLUSTER_HNDSK_PROGRAM, .progver = GLUSTER_HNDSK_VERSION, }; rpc_clnt_prog_t cli_pmap_prog = { .progname = "cli portmap", .prognum = GLUSTER_PMAP_PROGRAM, .progver = GLUSTER_PMAP_VERSION, }; int gf_cli_probe_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); //rsp.op_ret = -1; //rsp.op_errno = EINVAL; goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to probe"); if (rsp.op_errstr && (strlen (rsp.op_errstr) > 0)) { snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); if (rsp.op_ret) gf_log ("cli", GF_LOG_ERROR, "%s", msg); } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str (NULL, (rsp.op_ret)? NULL : msg, rsp.op_ret, rsp.op_errno, (rsp.op_ret)? msg : NULL); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (!rsp.op_ret) cli_out ("peer probe: success. %s", msg); else cli_err ("peer probe: failed: %s", msg); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int gf_cli_deprobe_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); //rsp.op_ret = -1; //rsp.op_errno = EINVAL; goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to deprobe"); if (rsp.op_ret) { if (strlen (rsp.op_errstr) > 0) { snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); gf_log ("cli", GF_LOG_ERROR, "%s", rsp.op_errstr); } } else { snprintf (msg, sizeof (msg), "success"); } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str (NULL, (rsp.op_ret)? NULL : msg, rsp.op_ret, rsp.op_errno, (rsp.op_ret)? msg : NULL); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (!rsp.op_ret) cli_out ("peer detach: %s", msg); else cli_err ("peer detach: failed: %s", msg); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int gf_cli_output_peer_hostnames (dict_t *dict, int count, char *prefix) { int ret = -1; char key[256] = {0,}; int i = 0; char *hostname = NULL; cli_out ("Other names:"); /* Starting from friend.hostname1, as friend.hostname0 will be the same * as friend.hostname */ for (i = 1; i < count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.hostname%d", prefix, i); ret = dict_get_str (dict, key, &hostname); if (ret) break; cli_out ("%s", hostname); hostname = NULL; } return ret; } int gf_cli_output_peer_status (dict_t *dict, int count) { int ret = -1; char *uuid_buf = NULL; char *hostname_buf = NULL; int32_t i = 1; char key[256] = {0,}; char *state = NULL; int32_t connected = 0; char *connected_str = NULL; int hostname_count = 0; cli_out ("Number of Peers: %d", count); i = 1; while ( i <= count) { snprintf (key, 256, "friend%d.uuid", i); ret = dict_get_str (dict, key, &uuid_buf); if (ret) goto out; snprintf (key, 256, "friend%d.hostname", i); ret = dict_get_str (dict, key, &hostname_buf); if (ret) goto out; snprintf (key, 256, "friend%d.connected", i); ret = dict_get_int32 (dict, key, &connected); if (ret) goto out; if (connected) connected_str = "Connected"; else connected_str = "Disconnected"; snprintf (key, 256, "friend%d.state", i); ret = dict_get_str (dict, key, &state); if (ret) goto out; cli_out ("\nHostname: %s\nUuid: %s\nState: %s (%s)", hostname_buf, uuid_buf, state, connected_str); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "friend%d.hostname_count", i); ret = dict_get_int32 (dict, key, &hostname_count); /* Print other addresses only if there are more than 1. */ if ((ret == 0) && (hostname_count > 1)) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "friend%d", i); ret = gf_cli_output_peer_hostnames (dict, hostname_count, key); } i++; } ret = 0; out: return ret; } int gf_cli_output_pool_list (dict_t *dict, int count) { int ret = -1; char *uuid_buf = NULL; char *hostname_buf = NULL; int32_t hostname_len = 8; /*min len 8 chars*/ int32_t i = 1; char key[256] = {0,}; int32_t connected = 0; char *connected_str = NULL; if (count <= 0) goto out; while (i <= count) { snprintf (key, 256, "friend%d.hostname", i); ret = dict_get_str (dict, key, &hostname_buf); if (ret) goto out; ret = strlen(hostname_buf); if (ret > hostname_len) hostname_len = ret; i++; } cli_out ("UUID\t\t\t\t\t%-*s\tState", hostname_len, "Hostname"); i = 1; while ( i <= count) { snprintf (key, 256, "friend%d.uuid", i); ret = dict_get_str (dict, key, &uuid_buf); if (ret) goto out; snprintf (key, 256, "friend%d.hostname", i); ret = dict_get_str (dict, key, &hostname_buf); if (ret) goto out; snprintf (key, 256, "friend%d.connected", i); ret = dict_get_int32 (dict, key, &connected); if (ret) goto out; if (connected) connected_str = "Connected"; else connected_str = "Disconnected"; cli_out ("%s\t%-*s\t%s ", uuid_buf, hostname_len, hostname_buf, connected_str); i++; } ret = 0; out: return ret; } /* function pointer for gf_cli_output_{pool_list,peer_status} */ typedef int (*cli_friend_output_fn) (dict_t*, int); int gf_cli_list_friends_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf1_cli_peer_list_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; char msg[1024] = {0,}; char *cmd = NULL; cli_friend_output_fn friend_output_fn; call_frame_t *frame = NULL; unsigned long flags = 0; GF_ASSERT (myframe); frame = myframe; flags = (long)frame->local; if (flags == GF_CLI_LIST_POOL_NODES) { cmd = "pool list"; friend_output_fn = &gf_cli_output_pool_list; } else { cmd = "peer status"; friend_output_fn = &gf_cli_output_peer_status; } /* 'free' the flags set by gf_cli_list_friends */ frame->local = NULL; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf1_cli_peer_list_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); //rsp.op_ret = -1; //rsp.op_errno = EINVAL; goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received resp to list: %d", rsp.op_ret); ret = rsp.op_ret; if (!rsp.op_ret) { if (!rsp.friends.friends_len) { snprintf (msg, sizeof (msg), "%s: No peers present", cmd); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_peer_status (dict, rsp.op_ret, rsp.op_errno, msg); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } cli_err ("%s", msg); ret = 0; goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.friends.friends_val, rsp.friends.friends_len, &dict); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); goto out; } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_peer_status (dict, rsp.op_ret, rsp.op_errno, msg); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } ret = dict_get_int32 (dict, "count", &count); if (ret) { goto out; } ret = friend_output_fn (dict, count); if (ret) { goto out; } } else { if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_peer_status (dict, rsp.op_ret, rsp.op_errno, NULL); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); } else { ret = -1; } goto out; } ret = 0; out: if (ret) cli_err ("%s: failed", cmd); cli_cmd_broadcast_response (ret); if (dict) dict_unref (dict); return ret; } int gf_cli_get_state_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; char *daemon_name = NULL; char *ofilepath = NULL; GF_VALIDATE_OR_GOTO ("cli", myframe, out); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) goto out; if (rsp.op_ret) { if (strcmp (rsp.op_errstr, "")) cli_err ("Failed to get daemon state: %s", rsp.op_errstr); else cli_err ("Failed to get daemon state. Check glusterd" " log file for more details"); } else { ret = dict_get_str (dict, "daemon", &daemon_name); if (ret) gf_log ("cli", GF_LOG_ERROR, "Couldn't get daemon name"); ret = dict_get_str (dict, "ofilepath", &ofilepath); if (ret) gf_log ("cli", GF_LOG_ERROR, "Couldn't get filepath"); if (daemon_name && ofilepath) cli_out ("%s state dumped to %s", daemon_name, ofilepath); } ret = rsp.op_ret; out: free (rsp.dict.dict_val); free (rsp.op_errstr); if (dict) dict_unref (dict); cli_cmd_broadcast_response (ret); return ret; } void cli_out_options ( char *substr, char *optstr, char *valstr) { char *ptr1 = NULL; char *ptr2 = NULL; ptr1 = substr; ptr2 = optstr; while (ptr1) { /* Avoiding segmentation fault. */ if (!ptr2) return; if (*ptr1 != *ptr2) break; ptr1++; ptr2++; } if (*ptr2 == '\0') return; cli_out ("%s: %s",ptr2 , valstr); } static int _gf_cli_output_volinfo_opts (dict_t *d, char *k, data_t *v, void *tmp) { int ret = 0; char *key = NULL; char *ptr = NULL; data_t *value = NULL; key = tmp; ptr = strstr (k, "option."); if (ptr) { value = v; if (!value) { ret = -1; goto out; } cli_out_options (key, k, v->data); } out: return ret; } static int print_brick_details (dict_t *dict, int volcount, int start_index, int end_index, int replica_count) { char key[1024] = {0,}; int index = start_index; int isArbiter = 0; int ret = -1; char *brick = NULL; #ifdef HAVE_BD_XLATOR char *caps = NULL; #endif while (index <= end_index) { memset (key, 0, sizeof (key)); snprintf (key, 1024, "volume%d.brick%d", volcount, index); ret = dict_get_str (dict, key, &brick); if (ret) goto out; memset (key, 0, sizeof(key)); snprintf (key, sizeof (key), "volume%d.brick%d.isArbiter", volcount, index); if (dict_get (dict, key)) isArbiter = 1; else isArbiter = 0; if (isArbiter) cli_out ("Brick%d: %s (arbiter)", index, brick); else cli_out ("Brick%d: %s", index, brick); #ifdef HAVE_BD_XLATOR snprintf (key, 1024, "volume%d.vg%d", volcount, index); ret = dict_get_str (dict, key, &caps); if (!ret) cli_out ("Brick%d VG: %s", index, caps); #endif index++; } ret = 0; out: return ret; } void gf_cli_print_number_of_bricks (int type, int brick_count, int dist_count, int stripe_count, int replica_count, int disperse_count, int redundancy_count, int arbiter_count) { if (type == GF_CLUSTER_TYPE_STRIPE_REPLICATE) { if (arbiter_count == 0) { cli_out ("Number of Bricks: %d x %d x %d = %d", (brick_count / dist_count), stripe_count, replica_count, brick_count); } else { cli_out ("Number of Bricks: %d x %d x (%d + %d) = %d", (brick_count / dist_count), stripe_count, replica_count - arbiter_count, arbiter_count, brick_count); } } else if (type == GF_CLUSTER_TYPE_NONE || type == GF_CLUSTER_TYPE_TIER) { cli_out ("Number of Bricks: %d", brick_count); } else if (type == GF_CLUSTER_TYPE_DISPERSE) { cli_out ("Number of Bricks: %d x (%d + %d) = %d", (brick_count / dist_count), disperse_count - redundancy_count, redundancy_count, brick_count); } else { /* For both replicate and stripe, dist_count is good enough */ if (arbiter_count == 0) { cli_out ("Number of Bricks: %d x %d = %d", (brick_count / dist_count), dist_count, brick_count); } else { cli_out ("Number of Bricks: %d x (%d + %d) = %d", (brick_count / dist_count), dist_count - arbiter_count, arbiter_count, brick_count); } } } int gf_cli_print_tier_info (dict_t *dict, int i, int brick_count) { int hot_brick_count = -1; int cold_type = 0; int cold_brick_count = 0; int cold_replica_count = 0; int cold_arbiter_count = 0; int cold_disperse_count = 0; int cold_redundancy_count = 0; int cold_dist_count = 0; int hot_type = 0; int hot_replica_count = 0; int hot_dist_count = 0; int ret = -1; int vol_type = -1; char key[256] = {0,}; GF_ASSERT (dict); memset (key, 0, sizeof (key)); snprintf (key, 256, "volume%d.cold_brick_count", i); ret = dict_get_int32 (dict, key, &cold_brick_count); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, 256, "volume%d.cold_type", i); ret = dict_get_int32 (dict, key, &cold_type); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, 256, "volume%d.cold_dist_count", i); ret = dict_get_int32 (dict, key, &cold_dist_count); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, 256, "volume%d.cold_replica_count", i); ret = dict_get_int32 (dict, key, &cold_replica_count); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, 256, "volume%d.cold_arbiter_count", i); ret = dict_get_int32 (dict, key, &cold_arbiter_count); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, 256, "volume%d.cold_disperse_count", i); ret = dict_get_int32 (dict, key, &cold_disperse_count); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, 256, "volume%d.cold_redundancy_count", i); ret = dict_get_int32 (dict, key, &cold_redundancy_count); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, 256, "volume%d.hot_brick_count", i); ret = dict_get_int32 (dict, key, &hot_brick_count); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, 256, "volume%d.hot_type", i); ret = dict_get_int32 (dict, key, &hot_type); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, 256, "volume%d.hot_replica_count", i); ret = dict_get_int32 (dict, key, &hot_replica_count); if (ret) goto out; cli_out ("Hot Tier :"); vol_type = hot_type; hot_dist_count = (hot_replica_count ? hot_replica_count : 1); vol_type = get_vol_type (hot_type, hot_dist_count, hot_brick_count); cli_out ("Hot Tier Type : %s", vol_type_str[vol_type]); gf_cli_print_number_of_bricks (hot_type, hot_brick_count, hot_dist_count, 0, hot_replica_count, 0, 0, 0); ret = print_brick_details (dict, i, 1, hot_brick_count, hot_replica_count); if (ret) goto out; cli_out ("Cold Tier:"); vol_type = get_vol_type (cold_type, cold_dist_count, cold_brick_count); cli_out ("Cold Tier Type : %s", vol_type_str[vol_type]); gf_cli_print_number_of_bricks (cold_type, cold_brick_count, cold_dist_count, 0, cold_replica_count, cold_disperse_count, cold_redundancy_count, cold_arbiter_count); ret = print_brick_details (dict, i, hot_brick_count+1, brick_count, cold_replica_count); if (ret) goto out; out: return ret; } int gf_cli_get_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { int ret = -1; int opt_count = 0; int32_t i = 0; int32_t j = 1; int32_t status = 0; int32_t type = 0; int32_t brick_count = 0; int32_t dist_count = 0; int32_t stripe_count = 0; int32_t replica_count = 0; int32_t disperse_count = 0; int32_t redundancy_count = 0; int32_t arbiter_count = 0; int32_t snap_count = 0; int32_t vol_type = 0; int32_t transport = 0; char *volume_id_str = NULL; char *volname = NULL; dict_t *dict = NULL; cli_local_t *local = NULL; char key[1024] = {0}; char err_str[2048] = {0}; gf_cli_rsp rsp = {0}; char *caps __attribute__((unused)) = NULL; int k __attribute__((unused)) = 0; call_frame_t *frame = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) goto out; frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to get vol: %d", rsp.op_ret); if (!rsp.dict.dict_len) { if (global_state->mode & GLUSTER_MODE_XML) goto xml_output; cli_err ("No volumes present"); ret = 0; goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to allocate memory"); goto out; } ret = dict_get_int32 (dict, "count", &count); if (ret) goto out; if (!count) { switch (local->get_vol.flags) { case GF_CLI_GET_NEXT_VOLUME: GF_FREE (local->get_vol.volname); local->get_vol.volname = NULL; ret = 0; goto out; case GF_CLI_GET_VOLUME: memset (err_str, 0, sizeof (err_str)); snprintf (err_str, sizeof (err_str), "Volume %s does not exist", local->get_vol.volname); ret = -1; if (!(global_state->mode & GLUSTER_MODE_XML)) goto out; } } if (rsp.op_ret) { if (global_state->mode & GLUSTER_MODE_XML) goto xml_output; ret = -1; goto out; } xml_output: if (global_state->mode & GLUSTER_MODE_XML) { /* For GET_NEXT_VOLUME output is already begun in * and will also end in gf_cli_get_next_volume() */ if (local->get_vol.flags == GF_CLI_GET_VOLUME) { ret = cli_xml_output_vol_info_begin (local, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } } if (dict) { ret = cli_xml_output_vol_info (local, dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } } if (local->get_vol.flags == GF_CLI_GET_VOLUME) { ret = cli_xml_output_vol_info_end (local); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); } goto out; } while ( i < count) { cli_out (" "); snprintf (key, 256, "volume%d.name", i); ret = dict_get_str (dict, key, &volname); if (ret) goto out; snprintf (key, 256, "volume%d.type", i); ret = dict_get_int32 (dict, key, &type); if (ret) goto out; snprintf (key, 256, "volume%d.status", i); ret = dict_get_int32 (dict, key, &status); if (ret) goto out; snprintf (key, 256, "volume%d.brick_count", i); ret = dict_get_int32 (dict, key, &brick_count); if (ret) goto out; snprintf (key, 256, "volume%d.dist_count", i); ret = dict_get_int32 (dict, key, &dist_count); if (ret) goto out; snprintf (key, 256, "volume%d.stripe_count", i); ret = dict_get_int32 (dict, key, &stripe_count); if (ret) goto out; snprintf (key, 256, "volume%d.replica_count", i); ret = dict_get_int32 (dict, key, &replica_count); if (ret) goto out; snprintf (key, 256, "volume%d.disperse_count", i); ret = dict_get_int32 (dict, key, &disperse_count); if (ret) goto out; snprintf (key, 256, "volume%d.redundancy_count", i); ret = dict_get_int32 (dict, key, &redundancy_count); if (ret) goto out; snprintf (key, sizeof(key), "volume%d.arbiter_count", i); ret = dict_get_int32 (dict, key, &arbiter_count); if (ret) goto out; snprintf (key, 256, "volume%d.transport", i); ret = dict_get_int32 (dict, key, &transport); if (ret) goto out; snprintf (key, 256, "volume%d.volume_id", i); ret = dict_get_str (dict, key, &volume_id_str); if (ret) goto out; snprintf (key, 256, "volume%d.snap_count", i); ret = dict_get_int32 (dict, key, &snap_count); if (ret) goto out; // Distributed (stripe/replicate/stripe-replica) setups vol_type = get_vol_type (type, dist_count, brick_count); cli_out ("Volume Name: %s", volname); cli_out ("Type: %s", vol_type_str[vol_type]); cli_out ("Volume ID: %s", volume_id_str); cli_out ("Status: %s", cli_vol_status_str[status]); cli_out ("Snapshot Count: %d", snap_count); #ifdef HAVE_BD_XLATOR k = 0; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.xlator%d", i, k); ret = dict_get_str (dict, key, &caps); if (ret) goto next; do { j = 0; cli_out ("Xlator %d: %s", k + 1, caps); do { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.xlator%d.caps%d", i, k, j++); ret = dict_get_str (dict, key, &caps); if (ret) break; cli_out ("Capability %d: %s", j, caps); } while (1); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.xlator%d", i, ++k); ret = dict_get_str (dict, key, &caps); if (ret) break; } while (1); next: #endif gf_cli_print_number_of_bricks (type, brick_count, dist_count, stripe_count, replica_count, disperse_count, redundancy_count, arbiter_count); cli_out ("Transport-type: %s", ((transport == 0)?"tcp": (transport == 1)?"rdma": "tcp,rdma")); j = 1; GF_FREE (local->get_vol.volname); local->get_vol.volname = gf_strdup (volname); if (type == GF_CLUSTER_TYPE_TIER) { ret = gf_cli_print_tier_info (dict, i, brick_count); if (ret) goto out; } else { cli_out ("Bricks:"); ret = print_brick_details (dict, i, j, brick_count, replica_count); if (ret) goto out; } snprintf (key, 256, "volume%d.opt_count",i); ret = dict_get_int32 (dict, key, &opt_count); if (ret) goto out; if (!opt_count) goto out; cli_out ("Options Reconfigured:"); snprintf (key, 256, "volume%d.option.",i); ret = dict_foreach (dict, _gf_cli_output_volinfo_opts, key); if (ret) goto out; i++; } ret = 0; out: if (ret) cli_err ("%s", err_str); cli_cmd_broadcast_response (ret); if (dict) dict_unref (dict); free (rsp.dict.dict_val); free (rsp.op_errstr); gf_log ("cli", GF_LOG_DEBUG, "Returning: %d", ret); return ret; } int gf_cli_create_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; cli_local_t *local = NULL; char *volname = NULL; dict_t *rsp_dict = NULL; call_frame_t *frame = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to create volume"); ret = dict_get_str (local->dict, "volname", &volname); if (ret) goto out; if (global_state->mode & GLUSTER_MODE_XML) { if (rsp.op_ret == 0) { rsp_dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &rsp_dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed rsp_dict unserialization"); goto out; } } ret = cli_xml_output_vol_create (rsp_dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret && strcmp (rsp.op_errstr, "")) cli_err ("volume create: %s: failed: %s", volname, rsp.op_errstr); else if (rsp.op_ret) cli_err ("volume create: %s: failed", volname); else cli_out ("volume create: %s: success: " "please start the volume to access data", volname); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); free (rsp.op_errstr); return ret; } int gf_cli_delete_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; cli_local_t *local = NULL; char *volname = NULL; call_frame_t *frame = NULL; dict_t *rsp_dict = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } ret = dict_get_str (local->dict, "volname", &volname); if (ret) { gf_log (frame->this->name, GF_LOG_ERROR, "dict get failed"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to delete volume"); if (global_state->mode & GLUSTER_MODE_XML) { if (rsp.op_ret == 0) { rsp_dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &rsp_dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed rsp_dict unserialization"); goto out; } } ret = cli_xml_output_generic_volume ("volDelete", rsp_dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret && strcmp (rsp.op_errstr, "")) cli_err ("volume delete: %s: failed: %s", volname, rsp.op_errstr); else if (rsp.op_ret) cli_err ("volume delete: %s: failed", volname); else cli_out ("volume delete: %s: success", volname); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); return ret; } int gf_cli3_1_uuid_get_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { char *uuid_str = NULL; gf_cli_rsp rsp = {0,}; int ret = -1; cli_local_t *local = NULL; call_frame_t *frame = NULL; dict_t *dict = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) goto out; frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } frame->local = NULL; gf_log ("cli", GF_LOG_INFO, "Received resp to uuid get"); dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to unserialize " "response for uuid get"); goto out; } ret = dict_get_str (dict, "uuid", &uuid_str); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get uuid " "from dictionary"); goto out; } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_dict ("uuidGenerate", dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) { if (strcmp (rsp.op_errstr, "") == 0) cli_err ("Get uuid was unsuccessful"); else cli_err ("%s", rsp.op_errstr); } else { cli_out ("UUID: %s", uuid_str); } ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); cli_local_wipe (local); if (rsp.dict.dict_val) free (rsp.dict.dict_val); gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); return ret; } int gf_cli3_1_uuid_reset_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; cli_local_t *local = NULL; call_frame_t *frame = NULL; dict_t *dict = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } frame->local = NULL; gf_log ("cli", GF_LOG_INFO, "Received resp to uuid reset"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_dict ("uuidReset", dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret && strcmp (rsp.op_errstr, "")) cli_err ("%s", rsp.op_errstr); else cli_out ("resetting the peer uuid has been %s", (rsp.op_ret) ? "unsuccessful": "successful"); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); cli_local_wipe (local); if (rsp.dict.dict_val) free (rsp.dict.dict_val); if (dict) dict_unref (dict); gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); return ret; } int gf_cli_start_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; cli_local_t *local = NULL; char *volname = NULL; call_frame_t *frame = NULL; dict_t *rsp_dict = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } ret = dict_get_str (local->dict, "volname", &volname); if (ret) { gf_log ("cli", GF_LOG_ERROR, "dict get failed"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to start volume"); if (global_state->mode & GLUSTER_MODE_XML) { if (rsp.op_ret == 0) { rsp_dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &rsp_dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed rsp_dict unserialization"); goto out; } } ret = cli_xml_output_generic_volume ("volStart", rsp_dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret && strcmp (rsp.op_errstr, "")) cli_err ("volume start: %s: failed: %s", volname, rsp.op_errstr); else if (rsp.op_ret) cli_err ("volume start: %s: failed", volname); else cli_out ("volume start: %s: success", volname); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); free (rsp.op_errstr); return ret; } int gf_cli_stop_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; cli_local_t *local = NULL; char *volname = NULL; call_frame_t *frame = NULL; dict_t *rsp_dict = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } ret = dict_get_str (local->dict, "volname", &volname); if (ret) { gf_log (frame->this->name, GF_LOG_ERROR, "Unable to get volname from dict"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to stop volume"); if (global_state->mode & GLUSTER_MODE_XML) { if (rsp.op_ret == 0) { rsp_dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &rsp_dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed rsp_dict unserialization"); goto out; } } ret = cli_xml_output_generic_volume ("volStop", rsp_dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret && strcmp (rsp.op_errstr, "")) cli_err ("volume stop: %s: failed: %s", volname, rsp.op_errstr); else if (rsp.op_ret) cli_err ("volume stop: %s: failed", volname); else cli_out ("volume stop: %s: success", volname); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); free (rsp.op_errstr); free (rsp.dict.dict_val); return ret; } int gf_cli_print_rebalance_status (dict_t *dict, enum gf_task_types task_type, gf_boolean_t is_tier) { int ret = -1; int count = 0; int i = 1; char key[256] = {0,}; gf_defrag_status_t status_rcd = GF_DEFRAG_STATUS_NOT_STARTED; uint64_t files = 0; uint64_t size = 0; uint64_t lookup = 0; char *node_name = NULL; uint64_t failures = 0; uint64_t skipped = 0; double elapsed = 0; char *status_str = NULL; char *size_str = NULL; int32_t hrs = 0; uint32_t min = 0; uint32_t sec = 0; gf_boolean_t down = _gf_false; gf_boolean_t fix_layout = _gf_false; uint64_t max_time = 0; uint64_t max_elapsed = 0; uint64_t time_left = 0; gf_boolean_t show_estimates = _gf_false; ret = dict_get_int32 (dict, "count", &count); if (ret) { gf_log ("cli", GF_LOG_ERROR, "count not set"); goto out; } memset (key, 0, 256); snprintf (key, 256, "status-1"); ret = dict_get_int32 (dict, key, (int32_t *)&status_rcd); if (ret) { gf_log ("cli", GF_LOG_TRACE, "count %d %d", count, 1); gf_log ("cli", GF_LOG_TRACE, "failed to get status"); goto out; } /* Fix layout will be sent to all nodes for the volume so every status should be of type GF_DEFRAG_STATUS_LAYOUT_FIX* */ if ((task_type == GF_TASK_TYPE_REBALANCE) && (status_rcd >= GF_DEFRAG_STATUS_LAYOUT_FIX_STARTED)) { fix_layout = _gf_true; } if (fix_layout) { cli_out ("%35s %41s %27s", "Node", "status", "run time in h:m:s"); cli_out ("%35s %41s %27s", "---------", "-----------", "------------"); } else { cli_out ("%40s %16s %13s %13s %13s %13s %20s %18s", "Node", "Rebalanced-files", "size", "scanned", "failures", "skipped", "status", "run time in" " h:m:s"); cli_out ("%40s %16s %13s %13s %13s %13s %20s %18s", "---------", "-----------", "-----------", "-----------", "-----------", "-----------", "------------", "--------------"); } for (i = 1; i <= count; i++) { /* Reset the variables to prevent carryover of values */ node_name = NULL; files = 0; size = 0; lookup = 0; skipped = 0; status_str = NULL; elapsed = 0; time_left = 0; /* Check if status is NOT_STARTED, and continue early */ memset (key, 0, 256); snprintf (key, 256, "status-%d", i); ret = dict_get_int32 (dict, key, (int32_t *)&status_rcd); if (ret == -ENOENT) { gf_log ("cli", GF_LOG_TRACE, "count %d %d", count, i); gf_log ("cli", GF_LOG_TRACE, "failed to get status"); gf_log ("cli", GF_LOG_ERROR, "node down and has failed" " to set dict"); down = _gf_true; continue; /* skip this node if value not available*/ } else if (ret) { gf_log ("cli", GF_LOG_TRACE, "count %d %d", count, i); gf_log ("cli", GF_LOG_TRACE, "failed to get status"); continue; /* skip this node if value not available*/ } if (GF_DEFRAG_STATUS_NOT_STARTED == status_rcd) continue; if (GF_DEFRAG_STATUS_STARTED == status_rcd) show_estimates = _gf_true; snprintf (key, 256, "node-name-%d", i); ret = dict_get_str (dict, key, &node_name); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get node-name"); memset (key, 0, 256); snprintf (key, 256, "files-%d", i); ret = dict_get_uint64 (dict, key, &files); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get file count"); memset (key, 0, 256); snprintf (key, 256, "size-%d", i); ret = dict_get_uint64 (dict, key, &size); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get size of xfer"); memset (key, 0, 256); snprintf (key, 256, "lookups-%d", i); ret = dict_get_uint64 (dict, key, &lookup); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get lookedup file count"); memset (key, 0, 256); snprintf (key, 256, "failures-%d", i); ret = dict_get_uint64 (dict, key, &failures); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get failures count"); memset (key, 0, 256); snprintf (key, 256, "skipped-%d", i); ret = dict_get_uint64 (dict, key, &skipped); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get skipped count"); /* For remove-brick include skipped count into failure count*/ if (task_type != GF_TASK_TYPE_REBALANCE) { failures += skipped; skipped = 0; } memset (key, 0, 256); snprintf (key, 256, "run-time-%d", i); ret = dict_get_double (dict, key, &elapsed); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get run-time"); memset (key, 0, 256); snprintf (key, 256, "time-left-%d", i); ret = dict_get_uint64 (dict, key, &time_left); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get time left"); if (elapsed > max_elapsed) max_elapsed = elapsed; if (time_left > max_time) max_time = time_left; /* Check for array bound */ if (status_rcd >= GF_DEFRAG_STATUS_MAX) status_rcd = GF_DEFRAG_STATUS_MAX; status_str = cli_vol_task_status_str[status_rcd]; size_str = gf_uint64_2human_readable(size); hrs = elapsed / 3600; min = ((uint64_t) elapsed % 3600) / 60; sec = ((uint64_t) elapsed % 3600) % 60; if (fix_layout) { cli_out ("%35s %50s %8d:%d:%d", node_name, status_str, hrs, min, sec); } else { if (size_str) { cli_out ("%40s %16"PRIu64 " %13s" " %13"PRIu64 " %13" PRIu64" %13"PRIu64 " %20s " "%8d:%02d:%02d", node_name, files, size_str, lookup, failures, skipped, status_str, hrs, min, sec); } else { cli_out ("%40s %16"PRIu64 " %13"PRIu64 " %13" PRIu64 " %13"PRIu64" %13"PRIu64 " %20s" " %8d:%02d:%02d", node_name, files, size, lookup, failures, skipped, status_str, hrs, min, sec); } } GF_FREE(size_str); } if (is_tier && down) cli_out ("WARNING: glusterd might be down on one or more nodes." " Please check the nodes that are down using \'gluster" " peer status\' and start the glusterd on those nodes," " else tier detach commit might fail!"); /* Max time will be non-zero if rebalance is still running */ if (max_time) { hrs = max_time / 3600; min = (max_time % 3600) / 60; sec = (max_time % 3600) % 60; if (hrs < REBAL_ESTIMATE_SEC_UPPER_LIMIT) { cli_out ("Estimated time left for rebalance to " "complete : %8d:%02d:%02d", hrs, min, sec); } else { cli_out ("Estimated time left for rebalance to " "complete : > 2 months. Please try again " "later."); } } else { /* Rebalance will return 0 if it could not calculate the * estimates or if it is complete. */ if (!show_estimates) { goto out; } if (max_elapsed <= REBAL_ESTIMATE_START_TIME) { cli_out ("The estimated time for rebalance to complete " "will be unavailable for the first 10 " "minutes."); } else { cli_out ("Rebalance estimated time unavailable. Please " "try again later."); } } out: return ret; } int gf_cli_print_tier_status (dict_t *dict, enum gf_task_types task_type) { int ret = -1; int count = 0; int i = 1; uint64_t promoted = 0; uint64_t demoted = 0; char key[256] = {0,}; char *node_name = NULL; gf_defrag_status_t status_rcd = GF_DEFRAG_STATUS_NOT_STARTED; char *status_str = NULL; gf_boolean_t down = _gf_false; double elapsed = 0; int hrs = 0; int min = 0; int sec = 0; ret = dict_get_int32 (dict, "count", &count); if (ret) { gf_log ("cli", GF_LOG_ERROR, "count not set"); goto out; } cli_out ("%-20s %-20s %-20s %-20s %-20s", "Node", "Promoted files", "Demoted files", "Status", "run time in h:m:s"); cli_out ("%-20s %-20s %-20s %-20s %-20s", "---------", "---------", "---------", "---------", "---------"); for (i = 1; i <= count; i++) { /* Reset the variables to prevent carryover of values */ node_name = NULL; promoted = 0; demoted = 0; /* Check if status is NOT_STARTED, and continue early */ memset (key, 0, 256); snprintf (key, 256, "status-%d", i); ret = dict_get_int32 (dict, key, (int32_t *)&status_rcd); if (ret == -ENOENT) { gf_log ("cli", GF_LOG_TRACE, "count: %d, %d," "failed to get status", count, i); gf_log ("cli", GF_LOG_ERROR, "node down and has failed" " to set dict"); down = _gf_true; continue; /*skipping this node as value unavailable*/ } else if (ret) { gf_log ("cli", GF_LOG_TRACE, "count: %d, %d," "failed to get status", count, i); continue; } if (GF_DEFRAG_STATUS_NOT_STARTED == status_rcd) continue; memset (key, 0, 256); snprintf (key, 256, "node-name-%d", i); ret = dict_get_str (dict, key, &node_name); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get node-name"); memset (key, 0, 256); snprintf (key, 256, "promoted-%d", i); ret = dict_get_uint64 (dict, key, &promoted); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get promoted count"); memset (key, 0, 256); snprintf (key, 256, "demoted-%d", i); ret = dict_get_uint64 (dict, key, &demoted); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get demoted count"); memset (key, 0, 256); snprintf (key, 256, "run-time-%d", i); ret = dict_get_double (dict, key, &elapsed); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get run-time"); /* Check for array bound */ if (status_rcd >= GF_DEFRAG_STATUS_MAX) status_rcd = GF_DEFRAG_STATUS_MAX; hrs = elapsed / 3600; min = ((int) elapsed % 3600) / 60; sec = ((int) elapsed % 3600) % 60; status_str = cli_vol_task_status_str[status_rcd]; cli_out ("%-20s %-20"PRIu64" %-20"PRIu64" %-20s" " %d:%d:%d", node_name, promoted, demoted, status_str, hrs, min, sec); } if (down) cli_out ("WARNING: glusterd might be down on one or more nodes." " Please check the nodes that are down using \'gluster" " peer status\' and start the glusterd on those nodes."); out: return ret; } int gf_cli_defrag_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; cli_local_t *local = NULL; char *volname = NULL; call_frame_t *frame = NULL; int cmd = 0; int ret = -1; dict_t *dict = NULL; char msg[1024] = {0,}; char *task_id_str = NULL; if (-1 == req->rpc_status) { goto out; } GF_ASSERT (myframe); frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } ret = dict_get_str (local->dict, "volname", &volname); if (ret) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to get volname"); goto out; } ret = dict_get_int32 (local->dict, "rebalance-command", (int32_t *)&cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get command"); goto out; } if (rsp.dict.dict_len) { /* Unserialize the dictionary */ dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret < 0) { gf_log ("glusterd", GF_LOG_ERROR, "failed to " "unserialize req-buffer to dictionary"); goto out; } } if (!((cmd == GF_DEFRAG_CMD_STOP) || (cmd == GF_DEFRAG_CMD_STATUS) || (cmd == GF_DEFRAG_CMD_STATUS_TIER)) && !(global_state->mode & GLUSTER_MODE_XML)) { ret = dict_get_str (dict, GF_REBALANCE_TID_KEY, &task_id_str); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) { snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); } else { if (!rsp.op_ret) { /* append errstr in the cli msg for successful * case since unlock failures can be highlighted * event though rebalance command was successful */ if (cmd == GF_DEFRAG_CMD_START_TIER) { snprintf (msg, sizeof (msg), "Tier " "start is successful on %s.", volname); } else if (cmd == GF_DEFRAG_CMD_STOP_TIER) { snprintf (msg, sizeof (msg), "Tier " "daemon stopped " "on %s.", volname); } else { snprintf (msg, sizeof (msg), "Rebalance on %s has been " "started successfully. Use " "rebalance status command to" " check status of the " "rebalance process.\nID: %s", volname, task_id_str); } } else { snprintf (msg, sizeof (msg), "Starting rebalance on volume %s has " "been unsuccessful.", volname); } } goto done; } if (cmd == GF_DEFRAG_CMD_STOP) { if (rsp.op_ret == -1) { if (strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "rebalance volume %s stop failed", volname); goto done; } else { /* append errstr in the cli msg for successful case * since unlock failures can be highlighted event though * rebalance command was successful */ snprintf (msg, sizeof (msg), "rebalance process may be in the middle of a " "file migration.\nThe process will be fully " "stopped once the migration of the file is " "complete.\nPlease check rebalance process " "for completion before doing any further " "brick related tasks on the volume.\n%s", rsp.op_errstr); } } if (cmd == GF_DEFRAG_CMD_STATUS || cmd == GF_DEFRAG_CMD_STATUS_TIER) { if (rsp.op_ret == -1) { if (strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "Failed to get the status of " "rebalance process"); goto done; } else { snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); } } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_rebalance (cmd, dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); goto out; } if (cmd == GF_DEFRAG_CMD_STATUS_TIER) ret = gf_cli_print_tier_status (dict, GF_TASK_TYPE_REBALANCE); else if (cmd == GF_DEFRAG_CMD_DETACH_STATUS) ret = gf_cli_print_rebalance_status (dict, GF_TASK_TYPE_REBALANCE, _gf_true); else ret = gf_cli_print_rebalance_status (dict, GF_TASK_TYPE_REBALANCE, _gf_false); if (ret) gf_log ("cli", GF_LOG_ERROR, "Failed to print rebalance status"); done: if (global_state->mode & GLUSTER_MODE_XML) cli_xml_output_str ("volRebalance", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); else { if (rsp.op_ret) if (cmd == GF_DEFRAG_CMD_START_TIER || cmd == GF_DEFRAG_CMD_STATUS_TIER) { cli_err ("Tiering Migration Functionality: %s:" " failed%s%s", volname, strlen (msg) ? ": " : "", msg); } else cli_err ("volume rebalance: %s: failed%s%s", volname, strlen (msg) ? ": " : "", msg); else if (cmd == GF_DEFRAG_CMD_START_TIER || cmd == GF_DEFRAG_CMD_STATUS_TIER) { cli_out ("Tiering Migration Functionality: %s:" " success%s%s", volname, strlen (msg) ? ": " : "", msg); } else cli_out ("volume rebalance: %s: success%s%s", volname, strlen (msg) ? ": " : "", msg); } ret = rsp.op_ret; out: free (rsp.op_errstr); //malloced by xdr free (rsp.dict.dict_val); //malloced by xdr if (dict) dict_unref (dict); cli_cmd_broadcast_response (ret); return ret; } int gf_cli_rename_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to probe"); snprintf (msg, sizeof (msg), "Rename volume %s", (rsp.op_ret) ? "unsuccessful": "successful"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volRename", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) cli_err ("volume rename: failed"); else cli_out ("volume rename: success"); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int gf_cli_reset_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to reset"); if (strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "reset volume %s", (rsp.op_ret) ? "unsuccessful": "successful"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volReset", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) cli_err ("volume reset: failed: %s", msg); else cli_out ("volume reset: success: %s", msg); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } char * is_server_debug_xlator (void *myframe) { call_frame_t *frame = NULL; cli_local_t *local = NULL; char **words = NULL; char *key = NULL; char *value = NULL; char *debug_xlator = NULL; frame = myframe; local = frame->local; words = (char **)local->words; while (*words != NULL) { if (strstr (*words, "trace") == NULL && strstr (*words, "error-gen") == NULL) { words++; continue; } key = *words; words++; value = *words; if (value == NULL) break; if (strstr (value, "client")) { words++; continue; } else { if (!(strstr (value, "posix") || strstr (value, "acl") || strstr (value, "locks") || strstr (value, "io-threads") || strstr (value, "marker") || strstr (value, "index"))) { words++; continue; } else { debug_xlator = gf_strdup (key); break; } } } return debug_xlator; } int gf_cli_set_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; char *help_str = NULL; char msg[1024] = {0,}; char *debug_xlator = NULL; char tmp_str[512] = {0,}; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to set"); dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); /* For brick processes graph change does not happen on the fly. * The process has to be restarted. So this is a check from the * volume set option such that if debug xlators such as trace/errorgen * are provided in the set command, warn the user. */ debug_xlator = is_server_debug_xlator (myframe); if (dict_get_str (dict, "help-str", &help_str) && !msg[0]) snprintf (msg, sizeof (msg), "Set volume %s", (rsp.op_ret) ? "unsuccessful": "successful"); if (rsp.op_ret == 0 && debug_xlator) { snprintf (tmp_str, sizeof (tmp_str), "\n%s translator has been " "added to the server volume file. Please restart the" " volume for enabling the translator", debug_xlator); } if ((global_state->mode & GLUSTER_MODE_XML) && (help_str == NULL)) { ret = cli_xml_output_str ("volSet", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) { if (strcmp (rsp.op_errstr, "")) cli_err ("volume set: failed: %s", rsp.op_errstr); else cli_err ("volume set: failed"); } else { if (help_str == NULL) { if (debug_xlator == NULL) cli_out ("volume set: success"); else cli_out ("volume set: success%s", tmp_str); }else { cli_out ("%s", help_str); } } ret = rsp.op_ret; out: if (dict) dict_unref (dict); GF_FREE (debug_xlator); cli_cmd_broadcast_response (ret); return ret; } int gf_cli_add_tier_brick_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; GF_VALIDATE_OR_GOTO ("cli", myframe, out); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to attach tier"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "Attach tier %s", (rsp.op_ret) ? "unsuccessful" : "successful"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volAttachTier", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) cli_err ("volume attach-tier: failed: %s", msg); else cli_out ("volume attach-tier: success"); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); free (rsp.op_errstr); return ret; } int gf_cli_attach_tier_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; GF_VALIDATE_OR_GOTO ("cli", myframe, out); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to attach tier"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "Attach tier %s", (rsp.op_ret) ? "unsuccessful" : "successful"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volAttachTier", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) cli_err ("volume attach-tier: failed: %s", msg); else cli_out ("volume attach-tier: success"); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); free (rsp.op_errstr); return ret; } int gf_cli_remove_tier_brick_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; char *cmd_str = "unknown"; cli_local_t *local = NULL; call_frame_t *frame = NULL; char *task_id_str = NULL; dict_t *rsp_dict = NULL; int32_t command = 0; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } ret = dict_get_int32 (local->dict, "command", &command); if (ret) { gf_log ("", GF_LOG_ERROR, "failed to get command"); goto out; } if (rsp.dict.dict_len) { rsp_dict = dict_new (); if (!rsp_dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &rsp_dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to unserialize rsp_dict"); goto out; } } switch (command) { case GF_DEFRAG_CMD_DETACH_START: cmd_str = "start"; ret = dict_get_str (rsp_dict, GF_REMOVE_BRICK_TID_KEY, &task_id_str); if (ret) { gf_log ("cli", GF_LOG_ERROR, "remove-brick-id is not present in dict"); } break; case GF_DEFRAG_CMD_DETACH_COMMIT: cmd_str = "commit"; break; case GF_DEFRAG_CMD_DETACH_COMMIT_FORCE: cmd_str = "commit force"; break; case GF_DEFRAG_CMD_DETACH_STOP: cmd_str = "stop"; break; case GF_DEFRAG_CMD_DETACH_STATUS: cmd_str = "status"; break; default: cmd_str = "unknown"; break; } gf_log ("cli", GF_LOG_INFO, "Received resp to detach tier"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "Detach tier %s %s", cmd_str, (rsp.op_ret) ? "unsuccessful" : "successful"); ret = rsp.op_ret; if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_remove_brick_detach_tier ( _gf_true, rsp_dict, rsp.op_ret, rsp.op_errno, msg, "volDetachTier"); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } else { if (rsp.op_ret) { if (strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "volume tier " "detach %s: failed: %s", cmd_str, rsp.op_errstr); else snprintf (msg, sizeof (msg), "volume tier " "detach %s: failed", cmd_str); cli_err ("%s", msg); goto out; } else { cli_out ("volume detach tier %s: success", cmd_str); if (GF_DEFRAG_CMD_DETACH_START == command && task_id_str != NULL) cli_out ("ID: %s", task_id_str); if (GF_DEFRAG_CMD_DETACH_COMMIT == command) cli_out ("Check the detached bricks to ensure " "all files are migrated.\nIf files " "with data are found on the brick " "path, copy them via a gluster mount " "point before re-purposing the " "removed brick. "); } } if (command == GF_DEFRAG_CMD_DETACH_STOP || command == GF_DEFRAG_CMD_DETACH_STATUS) ret = gf_cli_print_rebalance_status (rsp_dict, GF_TASK_TYPE_REMOVE_BRICK, _gf_true); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to print remove-brick " "rebalance status"); goto out; } if ((command == GF_DEFRAG_CMD_DETACH_STOP) && (rsp.op_ret == 0)) { cli_out ("'detach tier' process may be in the middle of a " "file migration.\nThe process will be fully stopped " "once the migration of the file is complete.\nPlease " "check detach tier process for completion before " "doing any further brick related tasks on the " "volume."); } ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); free (rsp.op_errstr); return ret; } int gf_cli_detach_tier_status_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; char msg[1024] = {0,}; int32_t command = 0; gf1_op_commands cmd = GF_OP_CMD_NONE; cli_local_t *local = NULL; call_frame_t *frame = NULL; char *cmd_str = "unknown"; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } ret = dict_get_int32 (local->dict, "command", &command); if (ret) goto out; cmd = command; switch (cmd) { case GF_OP_CMD_STOP_DETACH_TIER: cmd_str = "stop"; break; case GF_OP_CMD_STATUS: cmd_str = "status"; break; default: break; } ret = rsp.op_ret; if (rsp.op_ret == -1) { if (strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "volume tier detach %s: " "failed: %s", cmd_str, rsp.op_errstr); else snprintf (msg, sizeof (msg), "volume tier detach %s: " "failed", cmd_str); if (global_state->mode & GLUSTER_MODE_XML) goto xml_output; cli_err ("%s", msg); goto out; } if (rsp.dict.dict_len) { /* Unserialize the dictionary */ dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret < 0) { strncpy (msg, "failed to unserialize req-buffer to " "dictionary", sizeof (msg)); if (global_state->mode & GLUSTER_MODE_XML) { rsp.op_ret = -1; goto xml_output; } gf_log ("cli", GF_LOG_ERROR, "%s", msg); goto out; } } xml_output: if (global_state->mode & GLUSTER_MODE_XML) { if (strcmp (rsp.op_errstr, "")) { ret = cli_xml_output_vol_remove_brick_detach_tier ( _gf_true, dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr, "volDetachTier"); } else { ret = cli_xml_output_vol_remove_brick_detach_tier (_gf_true, dict, rsp.op_ret, rsp.op_errno, msg, "volDetachTier"); } goto out; } ret = gf_cli_print_rebalance_status (dict, GF_TASK_TYPE_REMOVE_BRICK, _gf_true); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to print remove-brick " "rebalance status"); goto out; } if ((cmd == GF_OP_CMD_STOP_DETACH_TIER) && (rsp.op_ret == 0)) { cli_out ("'detach tier' process may be in the middle of a " "file migration.\nThe process will be fully stopped " "once the migration of the file is complete.\nPlease " "check detach tier process for completion before " "doing any further brick related tasks on the " "volume."); } out: free (rsp.dict.dict_val); /* malloced by xdr */ if (dict) dict_unref (dict); cli_cmd_broadcast_response (ret); return ret; } int gf_cli_add_brick_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to add brick"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "Add Brick %s", (rsp.op_ret) ? "unsuccessful": "successful"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volAddBrick", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) cli_err ("volume add-brick: failed: %s", rsp.op_errstr); else cli_out ("volume add-brick: success"); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); free (rsp.op_errstr); return ret; } int gf_cli3_remove_brick_status_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; char msg[1024] = {0,}; int32_t command = 0; gf1_op_commands cmd = GF_OP_CMD_NONE; cli_local_t *local = NULL; call_frame_t *frame = NULL; char *cmd_str = "unknown"; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } ret = dict_get_int32 (local->dict, "command", &command); if (ret) goto out; cmd = command; switch (cmd) { case GF_OP_CMD_STOP: cmd_str = "stop"; break; case GF_OP_CMD_STATUS: cmd_str = "status"; break; default: break; } ret = rsp.op_ret; if (rsp.op_ret == -1) { if (strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "volume remove-brick %s: " "failed: %s", cmd_str, rsp.op_errstr); else snprintf (msg, sizeof (msg), "volume remove-brick %s: " "failed", cmd_str); if (global_state->mode & GLUSTER_MODE_XML) goto xml_output; cli_err ("%s", msg); goto out; } if (rsp.dict.dict_len) { /* Unserialize the dictionary */ dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret < 0) { strncpy (msg, "failed to unserialize req-buffer to " "dictionary", sizeof (msg)); if (global_state->mode & GLUSTER_MODE_XML) { rsp.op_ret = -1; goto xml_output; } gf_log ("cli", GF_LOG_ERROR, "%s", msg); goto out; } } xml_output: if (global_state->mode & GLUSTER_MODE_XML) { if (strcmp (rsp.op_errstr, "")) { ret = cli_xml_output_vol_remove_brick_detach_tier ( _gf_true, dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr, "volRemoveBrick"); } else { ret = cli_xml_output_vol_remove_brick_detach_tier ( _gf_true, dict, rsp.op_ret, rsp.op_errno, msg, "volRemoveBrick"); } goto out; } ret = gf_cli_print_rebalance_status (dict, GF_TASK_TYPE_REMOVE_BRICK, _gf_false); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to print remove-brick " "rebalance status"); goto out; } if ((cmd == GF_OP_CMD_STOP) && (rsp.op_ret == 0)) { cli_out ("'remove-brick' process may be in the middle of a " "file migration.\nThe process will be fully stopped " "once the migration of the file is complete.\nPlease " "check remove-brick process for completion before " "doing any further brick related tasks on the " "volume."); } out: free (rsp.dict.dict_val); //malloced by xdr if (dict) dict_unref (dict); cli_cmd_broadcast_response (ret); return ret; } int gf_cli_remove_brick_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; gf1_op_commands cmd = GF_OP_CMD_NONE; char *cmd_str = "unknown"; cli_local_t *local = NULL; call_frame_t *frame = NULL; char *task_id_str = NULL; dict_t *rsp_dict = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } ret = dict_get_int32 (local->dict, "command", (int32_t *)&cmd); if (ret) { gf_log ("", GF_LOG_ERROR, "failed to get command"); goto out; } if (rsp.dict.dict_len) { rsp_dict = dict_new (); if (!rsp_dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &rsp_dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to unserialize rsp_dict"); goto out; } } switch (cmd) { case GF_OP_CMD_DETACH_START: case GF_OP_CMD_START: cmd_str = "start"; ret = dict_get_str (rsp_dict, GF_REMOVE_BRICK_TID_KEY, &task_id_str); if (ret) { gf_log ("cli", GF_LOG_ERROR, "remove-brick-id is not present in dict"); } break; case GF_OP_CMD_COMMIT: cmd_str = "commit"; break; case GF_OP_CMD_COMMIT_FORCE: cmd_str = "commit force"; break; default: cmd_str = "unknown"; break; } gf_log ("cli", GF_LOG_INFO, "Received resp to remove brick"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "Remove Brick %s %s", cmd_str, (rsp.op_ret) ? "unsuccessful": "successful"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_remove_brick_detach_tier ( _gf_false, rsp_dict, rsp.op_ret, rsp.op_errno, msg, "volRemoveBrick"); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) { cli_err ("volume remove-brick %s: failed: %s", cmd_str, msg); } else { cli_out ("volume remove-brick %s: success", cmd_str); if (GF_OP_CMD_START == cmd && task_id_str != NULL) cli_out ("ID: %s", task_id_str); if (GF_OP_CMD_COMMIT == cmd) cli_out ("Check the removed bricks to ensure all files " "are migrated.\nIf files with data are " "found on the brick path, copy them via a " "gluster mount point before re-purposing the " "removed brick. "); } ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); free (rsp.op_errstr); return ret; } int gf_cli_reset_brick_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; cli_local_t *local = NULL; call_frame_t *frame = NULL; char *rb_operation_str = NULL; dict_t *rsp_dict = NULL; char msg[1024] = {0,}; char *reset_op = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } ret = dict_get_str (local->dict, "operation", &reset_op); if (ret) { gf_log (frame->this->name, GF_LOG_ERROR, "dict_get on operation failed"); goto out; } if (rsp.dict.dict_len) { /* Unserialize the dictionary */ rsp_dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &rsp_dict); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "failed to " "unserialize rsp buffer to dictionary"); goto out; } } if (strcmp (reset_op, "GF_RESET_OP_START") && strcmp (reset_op, "GF_RESET_OP_COMMIT") && strcmp (reset_op, "GF_RESET_OP_COMMIT_FORCE")) { rb_operation_str = gf_strdup ("Unknown operation"); ret = -1; goto out; } if (rsp.op_ret && (strcmp (rsp.op_errstr, ""))) { rb_operation_str = gf_strdup (rsp.op_errstr); } else { if (!strcmp (reset_op, "GF_RESET_OP_START")) { if (rsp.op_ret) rb_operation_str = gf_strdup ("reset-brick " "start " "operation " "failed"); else rb_operation_str = gf_strdup ("reset-brick " "start " "operation " "successful"); } else if (!strcmp (reset_op, "GF_RESET_OP_COMMIT")) { if (rsp.op_ret) rb_operation_str = gf_strdup ("reset-brick " "commit " "operation " "failed"); else rb_operation_str = gf_strdup ("reset-brick " "commit " "operation " "successful"); } else if (!strcmp (reset_op, "GF_RESET_OP_COMMIT_FORCE")) { if (rsp.op_ret) rb_operation_str = gf_strdup ("reset-brick " "commit " "force operation " "failed"); else rb_operation_str = gf_strdup ("reset-brick " "commit " "force operation " "successful"); } } gf_log ("cli", GF_LOG_INFO, "Received resp to reset brick"); snprintf (msg, sizeof (msg), "%s", rb_operation_str ? rb_operation_str : "Unknown operation"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_replace_brick (rsp_dict, rsp.op_ret, rsp.op_errno, msg); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) cli_err ("volume reset-brick: failed: %s", msg); else cli_out ("volume reset-brick: success: %s", msg); ret = rsp.op_ret; out: if (frame) frame->local = NULL; if (local) cli_local_wipe (local); if (rb_operation_str) GF_FREE (rb_operation_str); cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); if (rsp_dict) dict_unref (rsp_dict); return ret; } int gf_cli_replace_brick_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; cli_local_t *local = NULL; call_frame_t *frame = NULL; char *rb_operation_str = NULL; dict_t *rsp_dict = NULL; char msg[1024] = {0,}; char *replace_op = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } ret = dict_get_str (local->dict, "operation", &replace_op); if (ret) { gf_log (frame->this->name, GF_LOG_ERROR, "dict_get on operation failed"); goto out; } if (rsp.dict.dict_len) { /* Unserialize the dictionary */ rsp_dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &rsp_dict); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "failed to " "unserialize rsp buffer to dictionary"); goto out; } } if (!strcmp (replace_op, "GF_REPLACE_OP_COMMIT_FORCE")) { if (rsp.op_ret || ret) rb_operation_str = gf_strdup ("replace-brick commit " "force operation failed"); else rb_operation_str = gf_strdup ("replace-brick commit " "force operation " "successful"); } else { gf_log (frame->this->name, GF_LOG_DEBUG, "Unknown operation"); } if (rsp.op_ret && (strcmp (rsp.op_errstr, ""))) { rb_operation_str = gf_strdup (rsp.op_errstr); } gf_log ("cli", GF_LOG_INFO, "Received resp to replace brick"); snprintf (msg, sizeof (msg), "%s", rb_operation_str ? rb_operation_str : "Unknown operation"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_replace_brick (rsp_dict, rsp.op_ret, rsp.op_errno, msg); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) cli_err ("volume replace-brick: failed: %s", msg); else cli_out ("volume replace-brick: success: %s", msg); ret = rsp.op_ret; out: if (frame) frame->local = NULL; if (local) cli_local_wipe (local); if (rb_operation_str) GF_FREE (rb_operation_str); cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); if (rsp_dict) dict_unref (rsp_dict); return ret; } static int gf_cli_log_rotate_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received resp to log rotate"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "log rotate %s", (rsp.op_ret) ? "unsuccessful": "successful"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volLogRotate", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) cli_err ("volume log-rotate: failed: %s", msg); else cli_out ("volume log-rotate: success"); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); return ret; } static int gf_cli_sync_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received resp to sync"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "volume sync: failed: %s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "volume sync: %s", (rsp.op_ret) ? "failed": "success"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volSync", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) cli_err ("%s", msg); else cli_out ("%s", msg); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } static int print_quota_list_usage_output (cli_local_t *local, char *path, int64_t avail, char *sl_str, quota_limits_t *limits, quota_meta_t *used_space, gf_boolean_t sl, gf_boolean_t hl, double sl_num, gf_boolean_t limit_set) { int32_t ret = -1; char *used_str = NULL; char *avail_str = NULL; char *hl_str = NULL; char *sl_val = NULL; used_str = gf_uint64_2human_readable (used_space->size); if (limit_set) { hl_str = gf_uint64_2human_readable (limits->hl); avail_str = gf_uint64_2human_readable (avail); sl_val = gf_uint64_2human_readable (sl_num); } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_quota_xml_output (local, path, limits->hl, sl_str, sl_num, used_space->size, avail, sl ? "Yes" : "No", hl ? "Yes" : "No", limit_set); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to " "output in xml format for quota " "list command"); } goto out; } if (limit_set) { if (!used_str) { cli_out ("%-40s %7s %7s(%s) %8"PRIu64 "%9"PRIu64"" "%15s %18s", path, hl_str, sl_str, sl_val, used_space->size, avail, sl ? "Yes" : "No", hl ? "Yes" : "No"); } else { cli_out ("%-40s %7s %7s(%s) %8s %7s %15s %20s", path, hl_str, sl_str, sl_val, used_str, avail_str, sl ? "Yes" : "No", hl ? "Yes" : "No"); } } else { cli_out ("%-36s %10s %10s %14s %9s %15s %18s", path, "N/A", "N/A", used_str, "N/A", "N/A", "N/A"); } ret = 0; out: GF_FREE (hl_str); GF_FREE (used_str); GF_FREE (avail_str); GF_FREE (sl_val); return ret; } static int print_quota_list_object_output (cli_local_t *local, char *path, int64_t avail, char *sl_str, quota_limits_t *limits, quota_meta_t *used_space, gf_boolean_t sl, gf_boolean_t hl, double sl_num, gf_boolean_t limit_set) { int32_t ret = -1; int64_t sl_val = sl_num; if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_quota_object_xml_output (local, path, sl_str, sl_val, limits, used_space, avail, sl ? "Yes" : "No", hl ? "Yes" : "No", limit_set); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to " "output in xml format for quota " "list command"); } goto out; } if (limit_set) { cli_out ("%-40s %9"PRIu64" %9s(%"PRId64") %10"PRIu64"" "%10"PRIu64" %11"PRIu64" %15s %20s", path, limits->hl, sl_str, sl_val, used_space->file_count, used_space->dir_count, avail, sl ? "Yes" : "No", hl ? "Yes" : "No"); } else { cli_out ("%-40s %9s %9s %10"PRIu64" %10"PRIu64" %11s %15s %20s", path, "N/A", "N/A", used_space->file_count, used_space->dir_count, "N/A", "N/A", "N/A"); } ret = 0; out: return ret; } static int print_quota_list_output (cli_local_t *local, char *path, char *default_sl, quota_limits_t *limits, quota_meta_t *used_space, int type, gf_boolean_t limit_set) { int64_t avail = 0; char percent_str[20] = {0}; char *sl_final = NULL; int ret = -1; double sl_num = 0; gf_boolean_t sl = _gf_false; gf_boolean_t hl = _gf_false; int64_t used_size = 0; GF_ASSERT (local); GF_ASSERT (path); if (limit_set) { if (limits->sl < 0) { ret = gf_string2percent (default_sl, &sl_num); sl_num = (sl_num * limits->hl) / 100; sl_final = default_sl; } else { sl_num = (limits->sl * limits->hl) / 100; snprintf (percent_str, sizeof (percent_str), "%"PRIu64"%%", limits->sl); sl_final = percent_str; } if (type == GF_QUOTA_OPTION_TYPE_LIST) used_size = used_space->size; else used_size = used_space->file_count + used_space->dir_count; if (limits->hl > used_size) { avail = limits->hl - used_size; hl = _gf_false; if (used_size > sl_num) sl = _gf_true; else sl = _gf_false; } else { avail = 0; hl = sl = _gf_true; } } if (type == GF_QUOTA_OPTION_TYPE_LIST) ret = print_quota_list_usage_output (local, path, avail, sl_final, limits, used_space, sl, hl, sl_num, limit_set); else ret = print_quota_list_object_output (local, path, avail, sl_final, limits, used_space, sl, hl, sl_num, limit_set); return ret; } static int print_quota_list_from_mountdir (cli_local_t *local, char *mountdir, char *default_sl, char *path, int type) { int ret = -1; ssize_t xattr_size = 0; quota_limits_t limits = {0,}; quota_meta_t used_space = {0,}; char *key = NULL; gf_boolean_t limit_set = _gf_true; GF_ASSERT (local); GF_ASSERT (mountdir); GF_ASSERT (path); if (type == GF_QUOTA_OPTION_TYPE_LIST) key = QUOTA_LIMIT_KEY; else key = QUOTA_LIMIT_OBJECTS_KEY; ret = sys_lgetxattr (mountdir, key, (void *)&limits, sizeof (limits)); if (ret < 0) { gf_log ("cli", GF_LOG_ERROR, "Failed to get the xattr %s " "on %s. Reason : %s", key, mountdir, strerror (errno)); switch (errno) { #if defined(ENODATA) case ENODATA: #endif #if defined(ENOATTR) && (ENOATTR != ENODATA) case ENOATTR: #endif /* If it's an ENOATTR, quota/inode-quota is * configured(limit is set atleast for one directory). * The user is trying to issue 'list/list-objects' * command for a directory on which quota limit is * not set and we are showing the used-space in case * of list-usage and showing (dir_count, file_count) * in case of list-objects. Other labels are * shown "N/A". */ limit_set = _gf_false; goto enoattr; break; default: cli_err ("%-40s %s", path, strerror (errno)); break; } goto out; } limits.hl = ntoh64 (limits.hl); limits.sl = ntoh64 (limits.sl); enoattr: xattr_size = sys_lgetxattr (mountdir, QUOTA_SIZE_KEY, NULL, 0); if (xattr_size < (sizeof (int64_t) * 2) && type == GF_QUOTA_OPTION_TYPE_LIST_OBJECTS) { ret = -1; /* This can happen when glusterfs is upgraded from 3.6 to 3.7 * and the xattr healing is not completed. */ } else if (xattr_size > (sizeof (int64_t) * 2)) { ret = sys_lgetxattr (mountdir, QUOTA_SIZE_KEY, &used_space, sizeof (used_space)); } else if (xattr_size > 0) { /* This is for compatibility. * Older version had only file usage */ ret = sys_lgetxattr (mountdir, QUOTA_SIZE_KEY, &(used_space.size), sizeof (used_space.size)); used_space.file_count = 0; used_space.dir_count = 0; } else { ret = -1; } if (ret < 0) { gf_log ("cli", GF_LOG_ERROR, "Failed to get quota size " "on path %s: %s", mountdir, strerror (errno)); print_quota_list_empty (path, type); goto out; } used_space.size = ntoh64 (used_space.size); used_space.file_count = ntoh64 (used_space.file_count); used_space.dir_count = ntoh64 (used_space.dir_count); ret = print_quota_list_output (local, path, default_sl, &limits, &used_space, type, limit_set); out: return ret; } int gluster_remove_auxiliary_mount (char *volname) { int ret = -1; char mountdir[PATH_MAX] = {0,}; xlator_t *this = NULL; this = THIS; GF_ASSERT (this); GLUSTERD_GET_QUOTA_LIST_MOUNT_PATH (mountdir, volname, "/"); ret = gf_umount_lazy (this->name, mountdir, 1); if (ret) { gf_log("cli", GF_LOG_ERROR, "umount on %s failed, " "reason : %s", mountdir, strerror (errno)); } return ret; } int gf_cli_print_limit_list_from_dict (cli_local_t *local, char *volname, dict_t *dict, char *default_sl, int count, int op_ret, int op_errno, char *op_errstr) { int ret = -1; int i = 0; char key[1024] = {0,}; char mountdir[PATH_MAX] = {0,}; char *path = NULL; gf_boolean_t xml_err_flag = _gf_false; char err_str[NAME_MAX] = {0,}; int type = -1; if (!dict|| count <= 0) goto out; ret = dict_get_int32 (dict, "type", &type); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get quota type"); goto out; } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_quota_limit_list_begin (local, op_ret, op_errno, op_errstr); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting xml begin"); goto out; } } else { print_quota_list_header (type); } while (count--) { snprintf (key, sizeof (key), "path%d", i++); ret = dict_get_str (dict, key, &path); if (ret < 0) { gf_log ("cli", GF_LOG_DEBUG, "Path not present in limit" " list"); continue; } ret = gf_canonicalize_path (path); if (ret) goto out; GLUSTERD_GET_QUOTA_LIST_MOUNT_PATH (mountdir, volname, path); ret = print_quota_list_from_mountdir (local, mountdir, default_sl, path, type); } out: if (xml_err_flag) { ret = cli_xml_output_str ("volQuota", NULL, -1, 0, err_str); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting in xml " "format"); } } return ret; } int print_quota_list_from_quotad (call_frame_t *frame, dict_t *rsp_dict) { char *path = NULL; char *default_sl = NULL; int ret = -1; cli_local_t *local = NULL; dict_t *gd_rsp_dict = NULL; quota_meta_t used_space = {0, }; quota_limits_t limits = {0, }; quota_limits_t *size_limits = NULL; int32_t type = 0; int32_t success_count = 0; GF_ASSERT (frame); local = frame->local; gd_rsp_dict = local->dict; ret = dict_get_int32 (rsp_dict, "type", &type); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get type"); goto out; } ret = dict_get_str (rsp_dict, GET_ANCESTRY_PATH_KEY, &path); if (ret) { gf_log ("cli", GF_LOG_WARNING, "path key is not present " "in dict"); goto out; } ret = dict_get_str (gd_rsp_dict, "default-soft-limit", &default_sl); if (ret) { gf_log (frame->this->name, GF_LOG_ERROR, "failed to " "get default soft limit"); goto out; } if (type == GF_QUOTA_OPTION_TYPE_LIST) { ret = dict_get_bin (rsp_dict, QUOTA_LIMIT_KEY, (void **)&size_limits); if (ret) { gf_log ("cli", GF_LOG_WARNING, "limit key not present in dict on %s", path); goto out; } } else { ret = dict_get_bin (rsp_dict, QUOTA_LIMIT_OBJECTS_KEY, (void **)&size_limits); if (ret) { gf_log ("cli", GF_LOG_WARNING, "object limit key not present in dict on %s", path); goto out; } } limits.hl = ntoh64 (size_limits->hl); limits.sl = ntoh64 (size_limits->sl); if (type == GF_QUOTA_OPTION_TYPE_LIST) ret = quota_dict_get_meta (rsp_dict, QUOTA_SIZE_KEY, &used_space); else ret = quota_dict_get_inode_meta (rsp_dict, QUOTA_SIZE_KEY, &used_space); if (ret < 0) { gf_log ("cli", GF_LOG_WARNING, "size key not present in dict"); print_quota_list_empty (path, type); goto out; } LOCK (&local->lock); { ret = dict_get_int32 (gd_rsp_dict, "quota-list-success-count", &success_count); if (ret) success_count = 0; ret = dict_set_int32 (gd_rsp_dict, "quota-list-success-count", success_count + 1); } UNLOCK (&local->lock); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set " "quota-list-success-count in dict"); goto out; } if (success_count == 0) { if (!(global_state->mode & GLUSTER_MODE_XML)) { print_quota_list_header (type); } else { ret = cli_xml_output_vol_quota_limit_list_begin (local, 0, 0, NULL); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error in " "printing xml output"); goto out; } } } ret = print_quota_list_output (local, path, default_sl, &limits, &used_space, type, _gf_true); out: return ret; } void* cli_cmd_broadcast_response_detached (void *opaque) { int32_t ret = 0; ret = (intptr_t) opaque; cli_cmd_broadcast_response (ret); return NULL; } int32_t cli_quota_compare_path (struct list_head *list1, struct list_head *list2) { struct list_node *node1 = NULL; struct list_node *node2 = NULL; dict_t *dict1 = NULL; dict_t *dict2 = NULL; char *path1 = NULL; char *path2 = NULL; int ret = 0; node1 = list_entry (list1, struct list_node, list); node2 = list_entry (list2, struct list_node, list); dict1 = node1->ptr; dict2 = node2->ptr; ret = dict_get_str (dict1, GET_ANCESTRY_PATH_KEY, &path1); if (ret < 0) return 0; ret = dict_get_str (dict2, GET_ANCESTRY_PATH_KEY, &path2); if (ret < 0) return 0; return strcmp (path1, path2); } int cli_quotad_getlimit_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { /*TODO: we need to gather the path, hard-limit, soft-limit and used space*/ gf_cli_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; struct list_node *node = NULL; struct list_node *tmpnode = NULL; call_frame_t *frame = NULL; cli_local_t *local = NULL; int32_t list_count = 0; pthread_t th_id = {0, }; int32_t max_count = 0; GF_ASSERT (myframe); frame = myframe; GF_ASSERT (frame->local); local = frame->local; LOCK (&local->lock); { ret = dict_get_int32 (local->dict, "quota-list-count", &list_count); if (ret) list_count = 0; list_count++; ret = dict_set_int32 (local->dict, "quota-list-count", list_count); } UNLOCK (&local->lock); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set " "quota-list-count in dict"); goto out; } if (-1 == req->rpc_status) { if (list_count == 0) cli_err ("Connection failed. Please check if quota " "daemon is operational."); ret = -1; goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } if (rsp.op_ret) { ret = -1; if (strcmp (rsp.op_errstr, "")) cli_err ("quota command failed : %s", rsp.op_errstr); else cli_err ("quota command : failed"); goto out; } if (rsp.dict.dict_len) { /* Unserialize the dictionary */ dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret < 0) { gf_log ("cli", GF_LOG_ERROR, "failed to " "unserialize req-buffer to dictionary"); goto out; } node = list_node_add_order (dict, &local->dict_list, cli_quota_compare_path); if (node == NULL) { gf_log ("cli", GF_LOG_ERROR, "failed to add node to the list"); dict_unref (dict); goto out; } } ret = dict_get_int32 (local->dict, "max_count", &max_count); if (ret < 0) { gf_log ("cli", GF_LOG_ERROR, "failed to get max_count"); goto out; } if (list_count == max_count) { list_for_each_entry_safe (node, tmpnode, &local->dict_list, list) { dict = node->ptr; print_quota_list_from_quotad (frame, dict); list_node_del (node); dict_unref (dict); } } out: /* Bad Fix: CLI holds the lock to process a command. * When processing quota list command, below sequence of steps executed * in the same thread and causing deadlock * * 1) CLI holds the lock * 2) Send rpc_clnt_submit request to quotad for quota usage * 3) If quotad is down, rpc_clnt_submit invokes cbk function with error * 4) cbk function cli_quotad_getlimit_cbk invokes * cli_cmd_broadcast_response which tries to hold lock to broadcast * the results and hangs, because same thread has already holding * the lock * * Broadcasting response in a seperate thread which is not a * good fix. This needs to be re-visted with better solution */ if (ret == -1) { ret = pthread_create (&th_id, NULL, cli_cmd_broadcast_response_detached, (void *)-1); if (ret) gf_log ("cli", GF_LOG_ERROR, "pthread_create failed: " "%s", strerror (errno)); } else { cli_cmd_broadcast_response (ret); } free (rsp.dict.dict_val); return ret; } int cli_quotad_getlimit (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, &req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to serialize the data"); goto out; } ret = cli_cmd_submit (global_quotad_rpc, &req, frame, &cli_quotad_clnt, GF_AGGREGATOR_GETLIMIT, NULL, this, cli_quotad_getlimit_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } void gf_cli_quota_list (cli_local_t *local, char *volname, dict_t *dict, char *default_sl, int count, int op_ret, int op_errno, char *op_errstr) { GF_VALIDATE_OR_GOTO ("cli", volname, out); if (!connected) goto out; if (count > 0) gf_cli_print_limit_list_from_dict (local, volname, dict, default_sl, count, op_ret, op_errno, op_errstr); out: return; } int gf_cli_quota_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; char *volname = NULL; int32_t type = 0; call_frame_t *frame = NULL; char *default_sl = NULL; cli_local_t *local = NULL; char *default_sl_dup = NULL; int32_t entry_count = 0; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } if (rsp.op_ret) { ret = -1; if (global_state->mode & GLUSTER_MODE_XML) goto xml_output; if (strcmp (rsp.op_errstr, "")) { cli_err ("quota command failed : %s", rsp.op_errstr); if (rsp.op_ret == -ENOENT) cli_err ("please enter the path relative to " "the volume"); } else { cli_err ("quota command : failed"); } goto out; } if (rsp.dict.dict_len) { /* Unserialize the dictionary */ dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret < 0) { gf_log ("cli", GF_LOG_ERROR, "failed to " "unserialize req-buffer to dictionary"); goto out; } } gf_log ("cli", GF_LOG_DEBUG, "Received resp to quota command"); ret = dict_get_str (dict, "volname", &volname); if (ret) gf_log (frame->this->name, GF_LOG_ERROR, "failed to get volname"); ret = dict_get_str (dict, "default-soft-limit", &default_sl); if (ret) gf_log (frame->this->name, GF_LOG_TRACE, "failed to get " "default soft limit"); // default-soft-limit is part of rsp_dict only iff we sent // GLUSTER_CLI_QUOTA with type being GF_QUOTA_OPTION_TYPE_LIST if (default_sl) { default_sl_dup = gf_strdup (default_sl); if (!default_sl_dup) { ret = -1; goto out; } ret = dict_set_dynstr (local->dict, "default-soft-limit", default_sl_dup); if (ret) { gf_log (frame->this->name, GF_LOG_TRACE, "failed to set default soft limit"); GF_FREE (default_sl_dup); } } ret = dict_get_int32 (dict, "type", &type); if (ret) gf_log (frame->this->name, GF_LOG_TRACE, "failed to get type"); ret = dict_get_int32 (dict, "count", &entry_count); if (ret) gf_log (frame->this->name, GF_LOG_TRACE, "failed to get count"); if ((type == GF_QUOTA_OPTION_TYPE_LIST) || (type == GF_QUOTA_OPTION_TYPE_LIST_OBJECTS)) { gf_cli_quota_list (local, volname, dict, default_sl, entry_count, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_quota_limit_list_end (local); if (ret < 0) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Error in printing" " xml output"); } goto out; } } xml_output: if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volQuota", NULL, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (!rsp.op_ret && type != GF_QUOTA_OPTION_TYPE_LIST && type != GF_QUOTA_OPTION_TYPE_LIST_OBJECTS) cli_out ("volume quota : success"); ret = rsp.op_ret; out: if ((type == GF_QUOTA_OPTION_TYPE_LIST) || (type == GF_QUOTA_OPTION_TYPE_LIST_OBJECTS)) { gluster_remove_auxiliary_mount (volname); } cli_cmd_broadcast_response (ret); if (dict) dict_unref (dict); free (rsp.dict.dict_val); return ret; } int gf_cli_getspec_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_getspec_rsp rsp = {0,}; int ret = -1; char *spec = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_getspec_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } if (rsp.op_ret == -1) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "getspec failed"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to getspec"); spec = GF_MALLOC (rsp.op_ret + 1, cli_mt_char); if (!spec) { gf_log("", GF_LOG_ERROR, "out of memory"); goto out; } memcpy (spec, rsp.spec, rsp.op_ret); spec[rsp.op_ret] = '\0'; cli_out ("%s", spec); GF_FREE (spec); ret = 0; out: cli_cmd_broadcast_response (ret); return ret; } int gf_cli_pmap_b2p_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { pmap_port_by_brick_rsp rsp = {0,}; int ret = -1; char *spec = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_pmap_port_by_brick_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } if (rsp.op_ret == -1) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "pump_b2p failed"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to pmap b2p"); cli_out ("%d", rsp.port); GF_FREE (spec); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli_probe (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,},}; int ret = 0; dict_t *dict = NULL; int port = 0; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_int32 (dict, "port", &port); if (ret) { ret = dict_set_int32 (dict, "port", CLI_GLUSTERD_PORT); if (ret) goto out; } ret = cli_to_glusterd (&req, frame, gf_cli_probe_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_PROBE, this, cli_rpc_prog, NULL); out: GF_FREE (req.dict.dict_val); gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_deprobe (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,},}; int ret = 0; dict_t *dict = NULL; int port = 0; int flags = 0; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_int32 (dict, "port", &port); if (ret) { ret = dict_set_int32 (dict, "port", CLI_GLUSTERD_PORT); if (ret) goto out; } ret = dict_get_int32 (dict, "flags", &flags); if (ret) { ret = dict_set_int32 (dict, "flags", 0); if (ret) goto out; } ret = cli_to_glusterd (&req, frame, gf_cli_deprobe_cbk, (xdrproc_t)xdr_gf_cli_req, dict, GLUSTER_CLI_DEPROBE, this, cli_rpc_prog, NULL); out: GF_FREE (req.dict.dict_val); gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_list_friends (call_frame_t *frame, xlator_t *this, void *data) { gf1_cli_peer_list_req req = {0,}; int ret = 0; unsigned long flags = 0; if (!frame || !this) { ret = -1; goto out; } GF_ASSERT (frame->local == NULL); flags = (long)data; req.flags = flags; frame->local = (void*)flags; ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog, GLUSTER_CLI_LIST_FRIENDS, NULL, this, gf_cli_list_friends_cbk, (xdrproc_t) xdr_gf1_cli_peer_list_req); out: if (ret) { /* * If everything goes fine, gf_cli_list_friends_cbk() * [invoked through cli_cmd_submit()]resets the * frame->local to NULL. In case cli_cmd_submit() * fails in between, RESET frame->local here. */ frame->local = NULL; } gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_get_state (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,},}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_get_state_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_GET_STATE, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_get_next_volume (call_frame_t *frame, xlator_t *this, void *data) { int ret = 0; cli_cmd_volume_get_ctx_t *ctx = NULL; cli_local_t *local = NULL; if (!frame || !this || !data) { ret = -1; goto out; } ctx = data; local = frame->local; if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_info_begin (local, 0, 0, ""); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } } ret = gf_cli_get_volume (frame, this, data); if (!local || !local->get_vol.volname) { if ((global_state->mode & GLUSTER_MODE_XML)) goto end_xml; cli_err ("No volumes present"); goto out; } ctx->volname = local->get_vol.volname; while (ctx->volname) { ret = gf_cli_get_volume (frame, this, ctx); if (ret) goto out; ctx->volname = local->get_vol.volname; } end_xml: if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_info_end (local); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_get_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; cli_cmd_volume_get_ctx_t *ctx = NULL; dict_t *dict = NULL; int32_t flags = 0; if (!frame || !this || !data) { ret = -1; goto out; } ctx = data; dict = dict_new (); if (!dict) goto out; if (ctx->volname) { ret = dict_set_str (dict, "volname", ctx->volname); if (ret) goto out; } flags = ctx->flags; ret = dict_set_int32 (dict, "flags", flags); if (ret) { gf_log (frame->this->name, GF_LOG_ERROR, "failed to set flags"); goto out; } ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, &req.dict.dict_len); ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog, GLUSTER_CLI_GET_VOLUME, NULL, this, gf_cli_get_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: if (dict) dict_unref (dict); GF_FREE (req.dict.dict_val); gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_uuid_get (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli3_1_uuid_get_cbk, (xdrproc_t)xdr_gf_cli_req, dict, GLUSTER_CLI_UUID_GET, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_uuid_reset (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli3_1_uuid_reset_cbk, (xdrproc_t)xdr_gf_cli_req, dict, GLUSTER_CLI_UUID_RESET, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_create_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_create_volume_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_CREATE_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_delete_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_delete_volume_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_DELETE_VOLUME, this, cli_rpc_prog, NULL); out: GF_FREE (req.dict.dict_val); gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_start_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_start_volume_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_START_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_stop_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = data; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_stop_volume_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_STOP_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_defrag_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_defrag_volume_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_DEFRAG_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_rename_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, &req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to serialize the data"); goto out; } ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog, GLUSTER_CLI_RENAME_VOLUME, NULL, this, gf_cli_rename_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_reset_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,} }; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_reset_volume_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_RESET_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_set_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,} }; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_set_volume_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_SET_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_add_brick (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,} }; int ret = 0; dict_t *dict = NULL; char *volname = NULL; int32_t count = 0; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = dict_get_int32 (dict, "count", &count); if (ret) goto out; ret = cli_to_glusterd (&req, frame, gf_cli_add_brick_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_ADD_BRICK, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_tier (call_frame_t *frame, xlator_t *this, void *data) { int ret = 0; int32_t command = 0; gf_cli_req req = { {0,} }; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_int32 (dict, "rebalance-command", &command); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get rebalance-command"); goto out; } ret = cli_to_glusterd (&req, frame, gf_cli_defrag_volume_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_TIER, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_add_tier_brick (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = { {0,} }; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_add_tier_brick_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_ADD_TIER_BRICK, this, cli_rpc_prog, NULL); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to send request to " "glusterd"); goto out; } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_attach_tier (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,} }; int ret = 0; dict_t *dict = NULL; dict_t *newdict = NULL; char *tierwords[] = {"volume", "tier", "", "start", NULL}; const char **words = (const char **)tierwords; char *volname = NULL; cli_local_t *local = NULL; cli_local_t *oldlocal = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_attach_tier_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_ATTACH_TIER, this, cli_rpc_prog, NULL); if (ret) goto out; ret = dict_get_str (dict, "volname", &volname); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get volume name"); goto notify_cli; } words[2] = volname; ret = cli_cmd_volume_old_tier_parse ((const char **)words, 4, &newdict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to parse tier start " "command"); goto notify_cli; } gf_log ("cli", GF_LOG_DEBUG, "Sending tier start"); oldlocal = frame->local; CLI_LOCAL_INIT (local, words, frame, newdict); ret = gf_cli_tier (frame, this, newdict); frame->local = oldlocal; cli_local_wipe (local); notify_cli: if (ret) { cli_out ("Failed to run tier start. Please execute tier start " "command explicitly"); cli_out ("Usage : gluster volume tier start"); } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_remove_tier_brick (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req status_req = { {0,} }; int ret = 0; dict_t *dict = NULL; int32_t command = 0; char *volname = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = dict_get_int32 (dict, "command", &command); if (ret) goto out; ret = dict_set_int32 (dict, "rebalance-command", (int32_t) command); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to set dict"); goto out; } ret = cli_to_glusterd (&status_req, frame, gf_cli_remove_tier_brick_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_TIER, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (status_req.dict.dict_val); return ret; } int32_t gf_cli_remove_brick (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}};; gf_cli_req status_req = {{0,}};; int ret = 0; dict_t *dict = NULL; int32_t command = 0; char *volname = NULL; int32_t cmd = 0; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = dict_get_int32 (dict, "command", &command); if (ret) goto out; if ((command != GF_OP_CMD_STATUS) && (command != GF_OP_CMD_STOP)) { ret = cli_to_glusterd (&req, frame, gf_cli_remove_brick_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_REMOVE_BRICK, this, cli_rpc_prog, NULL); } else { /* Need rebalance status to be sent :-) */ if (command == GF_OP_CMD_STATUS) cmd |= GF_DEFRAG_CMD_STATUS; else cmd |= GF_DEFRAG_CMD_STOP; ret = dict_set_int32 (dict, "rebalance-command", (int32_t) cmd); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to set dict"); goto out; } ret = cli_to_glusterd (&status_req, frame, gf_cli3_remove_brick_status_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_DEFRAG_VOLUME, this, cli_rpc_prog, NULL); } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); GF_FREE (status_req.dict.dict_val); return ret; } int32_t gf_cli_reset_brick (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = { {0,} }; int ret = 0; dict_t *dict = NULL; char *dst_brick = NULL; char *src_brick = NULL; char *volname = NULL; char *op = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "operation", &op); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "dict_get on operation failed"); goto out; } ret = dict_get_str (dict, "volname", &volname); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "dict_get on volname failed"); goto out; } ret = dict_get_str (dict, "src-brick", &src_brick); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "dict_get on src-brick failed"); goto out; } if (!strcmp (op, "GF_RESET_OP_COMMIT") || !strcmp (op, "GF_RESET_OP_COMMIT_FORCE")) { ret = dict_get_str (dict, "dst-brick", &dst_brick); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "dict_get on dst-brick failed"); goto out; } } gf_log (this->name, GF_LOG_DEBUG, "Received command reset-brick %s on %s.", op, src_brick); ret = cli_to_glusterd (&req, frame, gf_cli_reset_brick_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_RESET_BRICK, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_replace_brick (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; char *src_brick = NULL; char *dst_brick = NULL; char *volname = NULL; int32_t op = 0; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_int32 (dict, "operation", &op); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "dict_get on operation failed"); goto out; } ret = dict_get_str (dict, "volname", &volname); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "dict_get on volname failed"); goto out; } ret = dict_get_str (dict, "src-brick", &src_brick); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "dict_get on src-brick failed"); goto out; } ret = dict_get_str (dict, "dst-brick", &dst_brick); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "dict_get on dst-brick failed"); goto out; } gf_log (this->name, GF_LOG_DEBUG, "Received command replace-brick %s with " "%s with operation=%d", src_brick, dst_brick, op); ret = cli_to_glusterd (&req, frame, gf_cli_replace_brick_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_REPLACE_BRICK, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_log_rotate (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_log_rotate_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_LOG_ROTATE, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_sync_volume (call_frame_t *frame, xlator_t *this, void *data) { int ret = 0; gf_cli_req req = {{0,}}; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_sync_volume_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_SYNC_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_getspec (call_frame_t *frame, xlator_t *this, void *data) { gf_getspec_req req = {0,}; int ret = 0; dict_t *dict = NULL; dict_t *op_dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "volid", &req.key); if (ret) goto out; op_dict = dict_new (); if (!op_dict) { ret = -1; goto out; } // Set the supported min and max op-versions, so glusterd can make a // decision ret = dict_set_int32 (op_dict, "min-op-version", GD_OP_VERSION_MIN); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "Failed to set min-op-version" " in request dict"); goto out; } ret = dict_set_int32 (op_dict, "max-op-version", GD_OP_VERSION_MAX); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "Failed to set max-op-version" " in request dict"); goto out; } ret = dict_allocate_and_serialize (op_dict, &req.xdata.xdata_val, &req.xdata.xdata_len); if (ret < 0) { gf_log (THIS->name, GF_LOG_ERROR, "Failed to serialize dictionary"); goto out; } ret = cli_cmd_submit (NULL, &req, frame, &cli_handshake_prog, GF_HNDSK_GETSPEC, NULL, this, gf_cli_getspec_cbk, (xdrproc_t) xdr_gf_getspec_req); out: if (op_dict) { dict_unref(op_dict); } gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_quota (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_quota_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_QUOTA, this, cli_rpc_prog, NULL); out: GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_pmap_b2p (call_frame_t *frame, xlator_t *this, void *data) { pmap_port_by_brick_req req = {0,}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "brick", &req.brick); if (ret) goto out; ret = cli_cmd_submit (NULL, &req, frame, &cli_pmap_prog, GF_PMAP_PORTBYBRICK, NULL, this, gf_cli_pmap_b2p_cbk, (xdrproc_t) xdr_pmap_port_by_brick_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } static int gf_cli_fsm_log_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf1_cli_fsm_log_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; int tr_count = 0; char key[256] = {0}; int i = 0; char *old_state = NULL; char *new_state = NULL; char *event = NULL; char *time = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf1_cli_fsm_log_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } if (rsp.op_ret) { if (strcmp (rsp.op_errstr, "")) cli_err ("%s", rsp.op_errstr); cli_err ("fsm log unsuccessful"); ret = rsp.op_ret; goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.fsm_log.fsm_log_val, rsp.fsm_log.fsm_log_len, &dict); if (ret) { cli_err ("bad response"); goto out; } ret = dict_get_int32 (dict, "count", &tr_count); if (tr_count) cli_out("number of transitions: %d", tr_count); else cli_err("No transitions"); for (i = 0; i < tr_count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "log%d-old-state", i); ret = dict_get_str (dict, key, &old_state); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "log%d-event", i); ret = dict_get_str (dict, key, &event); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "log%d-new-state", i); ret = dict_get_str (dict, key, &new_state); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "log%d-time", i); ret = dict_get_str (dict, key, &time); if (ret) goto out; cli_out ("Old State: [%s]\n" "New State: [%s]\n" "Event : [%s]\n" "timestamp: [%s]\n", old_state, new_state, event, time); } ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli_fsm_log (call_frame_t *frame, xlator_t *this, void *data) { int ret = -1; gf1_cli_fsm_log_req req = {0,}; GF_ASSERT (frame); GF_ASSERT (this); GF_ASSERT (data); if (!frame || !this || !data) goto out; req.name = data; ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog, GLUSTER_CLI_FSM_LOG, NULL, this, gf_cli_fsm_log_cbk, (xdrproc_t) xdr_gf1_cli_fsm_log_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int gf_cli_gsync_config_command (dict_t *dict) { runner_t runner = {0,}; char *subop = NULL; char *gwd = NULL; char *slave = NULL; char *confpath = NULL; char *master = NULL; char *op_name = NULL; int ret = -1; char conf_path[PATH_MAX] = ""; if (dict_get_str (dict, "subop", &subop) != 0) return -1; if (strcmp (subop, "get") != 0 && strcmp (subop, "get-all") != 0) { cli_out (GEOREP" config updated successfully"); return 0; } if (dict_get_str (dict, "glusterd_workdir", &gwd) != 0 || dict_get_str (dict, "slave", &slave) != 0) return -1; if (dict_get_str (dict, "master", &master) != 0) master = NULL; if (dict_get_str (dict, "op_name", &op_name) != 0) op_name = NULL; ret = dict_get_str (dict, "conf_path", &confpath); if (!confpath) { ret = snprintf (conf_path, sizeof(conf_path) - 1, "%s/"GEOREP"/gsyncd_template.conf", gwd); conf_path[ret] = '\0'; confpath = conf_path; } runinit (&runner); runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); runner_argprintf (&runner, "%s", confpath); runner_argprintf (&runner, "--iprefix=%s", DATADIR); if (master) runner_argprintf (&runner, ":%s", master); runner_add_arg (&runner, slave); runner_argprintf (&runner, "--config-%s", subop); if (op_name) runner_add_arg (&runner, op_name); return runner_run (&runner); } int gf_cli_print_status (char **title_values, gf_gsync_status_t **sts_vals, int *spacing, int gsync_count, int number_of_fields, int is_detail) { int i = 0; int j = 0; int ret = 0; int status_fields = 8; /* Indexed at 0 */ int total_spacing = 0; char **output_values = NULL; char *tmp = NULL; char *hyphens = NULL; /* calculating spacing for hyphens */ for (i = 0; i < number_of_fields; i++) { /* Suppressing detail output for status */ if ((!is_detail) && (i > status_fields)) { /* Suppressing detailed output for * status */ continue; } spacing[i] += 3; /* Adding extra space to distinguish between fields */ total_spacing += spacing[i]; } total_spacing += 4; /* For the spacing between the fields */ /* char pointers for each field */ output_values = GF_CALLOC (number_of_fields, sizeof (char *), gf_common_mt_char); if (!output_values) { ret = -1; goto out; } for (i = 0; i < number_of_fields; i++) { output_values[i] = GF_CALLOC (spacing[i] + 1, sizeof (char), gf_common_mt_char); if (!output_values[i]) { ret = -1; goto out; } } hyphens = GF_CALLOC (total_spacing + 1, sizeof (char), gf_common_mt_char); if (!hyphens) { ret = -1; goto out; } cli_out (" "); /* setting the title "NODE", "MASTER", etc. from title_values[] and printing the same */ for (j = 0; j < number_of_fields; j++) { if ((!is_detail) && (j > status_fields)) { /* Suppressing detailed output for * status */ output_values[j][0] = '\0'; continue; } memset (output_values[j], ' ', spacing[j]); memcpy (output_values[j], title_values[j], strlen(title_values[j])); output_values[j][spacing[j]] = '\0'; } cli_out ("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", output_values[0], output_values[1], output_values[2], output_values[3], output_values[4], output_values[5], output_values[6], output_values[7], output_values[8], output_values[9], output_values[10], output_values[11], output_values[12], output_values[13], output_values[14], output_values[15]); /* setting and printing the hyphens */ memset (hyphens, '-', total_spacing); hyphens[total_spacing] = '\0'; cli_out ("%s", hyphens); for (i = 0; i < gsync_count; i++) { for (j = 0; j < number_of_fields; j++) { if ((!is_detail) && (j > status_fields)) { /* Suppressing detailed output for * status */ output_values[j][0] = '\0'; continue; } tmp = get_struct_variable(j, sts_vals[i]); if (!tmp) { gf_log ("", GF_LOG_ERROR, "struct member empty."); ret = -1; goto out; } memset (output_values[j], ' ', spacing[j]); memcpy (output_values[j], tmp, strlen (tmp)); output_values[j][spacing[j]] = '\0'; } cli_out ("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", output_values[0], output_values[1], output_values[2], output_values[3], output_values[4], output_values[5], output_values[6], output_values[7], output_values[8], output_values[9], output_values[10], output_values[11], output_values[12], output_values[13], output_values[14], output_values[15]); } out: if (output_values) { for (i = 0; i < number_of_fields; i++) { if (output_values[i]) GF_FREE (output_values[i]); } GF_FREE (output_values); } if (hyphens) GF_FREE (hyphens); return ret; } int gf_gsync_status_t_comparator (const void *p, const void *q) { char *slavekey1 = NULL; char *slavekey2 = NULL; slavekey1 = get_struct_variable (20, (*(gf_gsync_status_t **)p)); slavekey2 = get_struct_variable (20, (*(gf_gsync_status_t **)q)); if (!slavekey1 || !slavekey2) { gf_log ("cli", GF_LOG_ERROR, "struct member empty."); return 0; } return strcmp (slavekey1, slavekey2); } int gf_cli_read_status_data (dict_t *dict, gf_gsync_status_t **sts_vals, int *spacing, int gsync_count, int number_of_fields) { char *tmp = NULL; char sts_val_name[PATH_MAX] = ""; int ret = 0; int i = 0; int j = 0; /* Storing per node status info in each object */ for (i = 0; i < gsync_count; i++) { snprintf (sts_val_name, sizeof(sts_val_name), "status_value%d", i); /* Fetching the values from dict, and calculating the max length for each field */ ret = dict_get_bin (dict, sts_val_name, (void **)&(sts_vals[i])); if (ret) goto out; for (j = 0; j < number_of_fields; j++) { tmp = get_struct_variable(j, sts_vals[i]); if (!tmp) { gf_log ("", GF_LOG_ERROR, "struct member empty."); ret = -1; goto out; } if (strlen (tmp) > spacing[j]) spacing[j] = strlen (tmp); } } /* Sort based on Session Slave */ qsort(sts_vals, gsync_count, sizeof(gf_gsync_status_t *), gf_gsync_status_t_comparator); out: return ret; } int gf_cli_gsync_status_output (dict_t *dict, gf_boolean_t is_detail) { int gsync_count = 0; int i = 0; int ret = 0; int spacing[16] = {0}; int num_of_fields = 16; char errmsg[1024] = ""; char *master = NULL; char *slave = NULL; char *title_values[] = {"MASTER NODE", "MASTER VOL", "MASTER BRICK", "SLAVE USER", "SLAVE", "SLAVE NODE", "STATUS", "CRAWL STATUS", "LAST_SYNCED", "ENTRY", "DATA", "META", "FAILURES", "CHECKPOINT TIME", "CHECKPOINT COMPLETED", "CHECKPOINT COMPLETION TIME"}; gf_gsync_status_t **sts_vals = NULL; /* Checks if any session is active or not */ ret = dict_get_int32 (dict, "gsync-count", &gsync_count); if (ret) { ret = dict_get_str (dict, "master", &master); ret = dict_get_str (dict, "slave", &slave); if (master) { if (slave) snprintf (errmsg, sizeof(errmsg), "No active " "geo-replication sessions between %s" " and %s", master, slave); else snprintf (errmsg, sizeof(errmsg), "No active " "geo-replication sessions for %s", master); } else snprintf (errmsg, sizeof(errmsg), "No active " "geo-replication sessions"); gf_log ("cli", GF_LOG_INFO, "%s", errmsg); cli_out ("%s", errmsg); ret = -1; goto out; } for (i = 0; i < num_of_fields; i++) spacing[i] = strlen(title_values[i]); /* gsync_count = number of nodes reporting output. each sts_val object will store output of each node */ sts_vals = GF_CALLOC (gsync_count, sizeof (gf_gsync_status_t *), gf_common_mt_char); if (!sts_vals) { ret = -1; goto out; } for (i = 0; i < gsync_count; i++) { sts_vals[i] = GF_CALLOC (1, sizeof (gf_gsync_status_t), gf_common_mt_char); if (!sts_vals[i]) { ret = -1; goto out; } } ret = gf_cli_read_status_data (dict, sts_vals, spacing, gsync_count, num_of_fields); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to read status data"); goto out; } ret = gf_cli_print_status (title_values, sts_vals, spacing, gsync_count, num_of_fields, is_detail); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to print status output"); goto out; } out: if (sts_vals) GF_FREE (sts_vals); return ret; } static int32_t write_contents_to_common_pem_file (dict_t *dict, int output_count) { char *workdir = NULL; char common_pem_file[PATH_MAX] = ""; char *output = NULL; char output_name[PATH_MAX] = ""; int bytes_written = 0; int fd = -1; int ret = -1; int i = -1; ret = dict_get_str (dict, "glusterd_workdir", &workdir); if (ret || !workdir) { gf_log ("", GF_LOG_ERROR, "Unable to fetch workdir"); ret = -1; goto out; } snprintf (common_pem_file, sizeof(common_pem_file), "%s/geo-replication/common_secret.pem.pub", workdir); sys_unlink (common_pem_file); fd = open (common_pem_file, O_WRONLY | O_CREAT, 0600); if (fd == -1) { gf_log ("", GF_LOG_ERROR, "Failed to open %s" " Error : %s", common_pem_file, strerror (errno)); ret = -1; goto out; } for (i = 1; i <= output_count; i++) { memset (output_name, '\0', sizeof (output_name)); snprintf (output_name, sizeof (output_name), "output_%d", i); ret = dict_get_str (dict, output_name, &output); if (ret) { gf_log ("", GF_LOG_ERROR, "Failed to get %s.", output_name); cli_out ("Unable to fetch output."); } if (output) { bytes_written = sys_write (fd, output, strlen(output)); if (bytes_written != strlen(output)) { gf_log ("", GF_LOG_ERROR, "Failed to write " "to %s", common_pem_file); ret = -1; goto out; } /* Adding the new line character */ bytes_written = sys_write (fd, "\n", strlen("\n")); if (bytes_written != strlen("\n")) { gf_log ("", GF_LOG_ERROR, "Failed to add new line char"); ret = -1; goto out; } output = NULL; } } cli_out ("Common secret pub file present at %s", common_pem_file); ret = 0; out: if (fd >= 0) sys_close (fd); gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int gf_cli_sys_exec_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { int ret = -1; int output_count = -1; int i = -1; char *output = NULL; char *command = NULL; char output_name[PATH_MAX] = ""; gf_cli_rsp rsp = {0, }; dict_t *dict = NULL; GF_ASSERT (myframe); if (req->rpc_status == -1) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) goto out; if (rsp.op_ret) { cli_err ("%s", rsp.op_errstr ? rsp.op_errstr : "Command failed."); ret = rsp.op_ret; goto out; } ret = dict_get_int32 (dict, "output_count", &output_count); if (ret) { cli_out ("Command executed successfully."); ret = 0; goto out; } ret = dict_get_str (dict, "command", &command); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to get command from dict"); goto out; } if (!strcmp (command, "gsec_create")) { ret = write_contents_to_common_pem_file (dict, output_count); if (!ret) goto out; } for (i = 1; i <= output_count; i++) { memset (output_name, '\0', sizeof (output_name)); snprintf (output_name, sizeof (output_name), "output_%d", i); ret = dict_get_str (dict, output_name, &output); if (ret) { gf_log ("", GF_LOG_ERROR, "Failed to get %s.", output_name); cli_out ("Unable to fetch output."); } if (output) { cli_out ("%s", output); output = NULL; } } ret = 0; out: if (dict) dict_unref (dict); cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); return ret; } int gf_cli_copy_file_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { int ret = -1; gf_cli_rsp rsp = {0, }; dict_t *dict = NULL; GF_ASSERT (myframe); if (req->rpc_status == -1) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) goto out; if (rsp.op_ret) { cli_err ("%s", rsp.op_errstr ? rsp.op_errstr : "Copy unsuccessful"); ret = rsp.op_ret; goto out; } cli_out ("Successfully copied file."); out: if (dict) dict_unref (dict); cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); return ret; } int gf_cli_gsync_set_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { int ret = -1; gf_cli_rsp rsp = {0, }; dict_t *dict = NULL; char *gsync_status = NULL; char *master = NULL; char *slave = NULL; int32_t type = 0; gf_boolean_t status_detail = _gf_false; GF_ASSERT (myframe); if (req->rpc_status == -1) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) goto out; if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_gsync (dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) { cli_err ("%s", rsp.op_errstr ? rsp.op_errstr : GEOREP" command unsuccessful"); ret = rsp.op_ret; goto out; } ret = dict_get_str (dict, "gsync-status", &gsync_status); if (!ret) cli_out ("%s", gsync_status); else ret = 0; ret = dict_get_int32 (dict, "type", &type); if (ret) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "failed to get type"); goto out; } switch (type) { case GF_GSYNC_OPTION_TYPE_START: case GF_GSYNC_OPTION_TYPE_STOP: if (dict_get_str (dict, "master", &master) != 0) master = "???"; if (dict_get_str (dict, "slave", &slave) != 0) slave = "???"; cli_out ("%s " GEOREP " session between %s & %s" " has been successful", type == GF_GSYNC_OPTION_TYPE_START ? "Starting" : "Stopping", master, slave); break; case GF_GSYNC_OPTION_TYPE_PAUSE: case GF_GSYNC_OPTION_TYPE_RESUME: if (dict_get_str (dict, "master", &master) != 0) master = "???"; if (dict_get_str (dict, "slave", &slave) != 0) slave = "???"; cli_out ("%s " GEOREP " session between %s & %s" " has been successful", type == GF_GSYNC_OPTION_TYPE_PAUSE ? "Pausing" : "Resuming", master, slave); break; case GF_GSYNC_OPTION_TYPE_CONFIG: ret = gf_cli_gsync_config_command (dict); break; case GF_GSYNC_OPTION_TYPE_STATUS: status_detail = dict_get_str_boolean (dict, "status-detail", _gf_false); ret = gf_cli_gsync_status_output (dict, status_detail); break; case GF_GSYNC_OPTION_TYPE_DELETE: if (dict_get_str (dict, "master", &master) != 0) master = "???"; if (dict_get_str (dict, "slave", &slave) != 0) slave = "???"; cli_out ("Deleting " GEOREP " session between %s & %s" " has been successful", master, slave); break; case GF_GSYNC_OPTION_TYPE_CREATE: if (dict_get_str (dict, "master", &master) != 0) master = "???"; if (dict_get_str (dict, "slave", &slave) != 0) slave = "???"; cli_out ("Creating " GEOREP " session between %s & %s" " has been successful", master, slave); break; default: cli_out (GEOREP" command executed successfully"); } out: if (dict) dict_unref (dict); cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); return ret; } int32_t gf_cli_sys_exec (call_frame_t *frame, xlator_t *this, void *data) { int ret = 0; dict_t *dict = NULL; gf_cli_req req = {{0,}}; if (!frame || !this || !data) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid data"); goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_sys_exec_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_SYS_EXEC, this, cli_rpc_prog, NULL); out: GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_copy_file (call_frame_t *frame, xlator_t *this, void *data) { int ret = 0; dict_t *dict = NULL; gf_cli_req req = {{0,}}; if (!frame || !this || !data) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid data"); goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_copy_file_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_COPY_FILE, this, cli_rpc_prog, NULL); out: GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_gsync_set (call_frame_t *frame, xlator_t *this, void *data) { int ret = 0; dict_t *dict = NULL; gf_cli_req req = {{0,}}; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_gsync_set_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_GSYNC_SET, this, cli_rpc_prog, NULL); out: GF_FREE (req.dict.dict_val); return ret; } int cli_profile_info_percentage_cmp (void *a, void *b) { cli_profile_info_t *ia = NULL; cli_profile_info_t *ib = NULL; int ret = 0; ia = a; ib = b; if (ia->percentage_avg_latency < ib->percentage_avg_latency) ret = -1; else if (ia->percentage_avg_latency > ib->percentage_avg_latency) ret = 1; else ret = 0; return ret; } void cmd_profile_volume_brick_out (dict_t *dict, int count, int interval) { char key[256] = {0}; int i = 0; uint64_t sec = 0; uint64_t r_count = 0; uint64_t w_count = 0; uint64_t rb_counts[32] = {0}; uint64_t wb_counts[32] = {0}; cli_profile_info_t profile_info[GF_FOP_MAXVALUE] = {{0}}; cli_profile_info_t upcall_info[GF_UPCALL_FLAGS_MAXVALUE] = {{0},}; char output[128] = {0}; int per_line = 0; char read_blocks[128] = {0}; char write_blocks[128] = {0}; int index = 0; int is_header_printed = 0; int ret = 0; double total_percentage_latency = 0; for (i = 0; i < 32; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-read-%d", count, interval, (1 << i)); ret = dict_get_uint64 (dict, key, &rb_counts[i]); } for (i = 0; i < 32; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-write-%d", count, interval, (1<rpc_status) { goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received resp to profile"); ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); goto out; } else { dict->extra_stdfree = rsp.dict.dict_val; } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_profile (dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = dict_get_int32 (dict, "op", (int32_t*)&op); if (ret) goto out; if (rsp.op_ret && strcmp (rsp.op_errstr, "")) { cli_err ("%s", rsp.op_errstr); } else { switch (op) { case GF_CLI_STATS_START: cli_out ("Starting volume profile on %s has been %s ", volname, (rsp.op_ret) ? "unsuccessful": "successful"); break; case GF_CLI_STATS_STOP: cli_out ("Stopping volume profile on %s has been %s ", volname, (rsp.op_ret) ? "unsuccessful": "successful"); break; case GF_CLI_STATS_INFO: break; default: cli_out ("volume profile on %s has been %s ", volname, (rsp.op_ret) ? "unsuccessful": "successful"); break; } } if (rsp.op_ret) { ret = rsp.op_ret; goto out; } if (GF_CLI_STATS_INFO != op) { ret = 0; goto out; } ret = dict_get_int32 (dict, "info-op", (int32_t*)&info_op); if (ret) goto out; ret = dict_get_int32 (dict, "count", &brick_count); if (ret) goto out; if (!brick_count) { cli_err ("All bricks of volume %s are down.", volname); goto out; } while (i <= brick_count) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-brick", i); ret = dict_get_str (dict, key, &brick); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Couldn't get brick name"); goto out; } ret = dict_get_str_boolean (dict, "nfs", _gf_false); if (ret) snprintf (str, sizeof (str), "NFS Server : %s", brick); else snprintf (str, sizeof (str), "Brick: %s", brick); cli_out ("%s", str); memset (str, '-', strlen (str)); cli_out ("%s", str); if (GF_CLI_INFO_CLEAR == info_op) { snprintf (key, sizeof (key), "%d-stats-cleared", i); ret = dict_get_int32 (dict, key, &stats_cleared); if (ret) goto out; cli_out (stats_cleared ? "Cleared stats." : "Failed to clear stats."); } else { snprintf (key, sizeof (key), "%d-cumulative", i); ret = dict_get_int32 (dict, key, &interval); if (ret == 0) cmd_profile_volume_brick_out (dict, i, interval); snprintf (key, sizeof (key), "%d-interval", i); ret = dict_get_int32 (dict, key, &interval); if (ret == 0) cmd_profile_volume_brick_out (dict, i, interval); } i++; } ret = rsp.op_ret; out: if (dict) dict_unref (dict); free (rsp.op_errstr); cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli_profile_volume (call_frame_t *frame, xlator_t *this, void *data) { int ret = -1; gf_cli_req req = {{0,}}; dict_t *dict = NULL; GF_ASSERT (frame); GF_ASSERT (this); GF_ASSERT (data); if (!frame || !this || !data) goto out; dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_profile_volume_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_PROFILE_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_top_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; gf1_cli_stats_op op = GF_CLI_STATS_NONE; char key[256] = {0}; int i = 0; int32_t brick_count = 0; char brick[1024]; int32_t members = 0; char *filename; char *bricks; uint64_t value = 0; int32_t j = 0; gf1_cli_top_op top_op = GF_CLI_TOP_NONE; uint64_t nr_open = 0; uint64_t max_nr_open = 0; double throughput = 0; double time = 0; int32_t time_sec = 0; long int time_usec = 0; char timestr[256] = {0, }; char *openfd_str = NULL; gf_boolean_t nfs = _gf_false; gf_boolean_t clear_stats = _gf_false; int stats_cleared = 0; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received resp to top"); ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } if (rsp.op_ret) { if (strcmp (rsp.op_errstr, "")) cli_err ("%s", rsp.op_errstr); cli_err ("volume top unsuccessful"); ret = rsp.op_ret; goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); goto out; } ret = dict_get_int32 (dict, "op", (int32_t*)&op); if (op != GF_CLI_STATS_TOP) { ret = 0; goto out; } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_top (dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); } goto out; } ret = dict_get_int32 (dict, "count", &brick_count); if (ret) goto out; snprintf (key, sizeof (key), "%d-top-op", 1); ret = dict_get_int32 (dict, key, (int32_t*)&top_op); if (ret) goto out; clear_stats = dict_get_str_boolean (dict, "clear-stats", _gf_false); while (i < brick_count) { i++; snprintf (brick, sizeof (brick), "%d-brick", i); ret = dict_get_str (dict, brick, &bricks); if (ret) goto out; nfs = dict_get_str_boolean (dict, "nfs", _gf_false); if (clear_stats) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-stats-cleared", i); ret = dict_get_int32 (dict, key, &stats_cleared); if (ret) goto out; cli_out (stats_cleared ? "Cleared stats for %s %s" : "Failed to clear stats for %s %s", nfs ? "NFS server on" : "brick", bricks); continue; } if (nfs) cli_out ("NFS Server : %s", bricks); else cli_out ("Brick: %s", bricks); snprintf(key, sizeof (key), "%d-members", i); ret = dict_get_int32 (dict, key, &members); switch (top_op) { case GF_CLI_TOP_OPEN: snprintf (key, sizeof (key), "%d-current-open", i); ret = dict_get_uint64 (dict, key, &nr_open); if (ret) break; snprintf (key, sizeof (key), "%d-max-open", i); ret = dict_get_uint64 (dict, key, &max_nr_open); if (ret) goto out; snprintf (key, sizeof (key), "%d-max-openfd-time", i); ret = dict_get_str (dict, key, &openfd_str); if (ret) goto out; cli_out ("Current open fds: %"PRIu64", Max open" " fds: %"PRIu64", Max openfd time: %s", nr_open, max_nr_open, openfd_str); case GF_CLI_TOP_READ: case GF_CLI_TOP_WRITE: case GF_CLI_TOP_OPENDIR: case GF_CLI_TOP_READDIR: if (!members) { continue; } cli_out ("Count\t\tfilename\n======================="); break; case GF_CLI_TOP_READ_PERF: case GF_CLI_TOP_WRITE_PERF: snprintf (key, sizeof (key), "%d-throughput", i); ret = dict_get_double (dict, key, &throughput); if (!ret) { snprintf (key, sizeof (key), "%d-time", i); ret = dict_get_double (dict, key, &time); } if (!ret) cli_out ("Throughput %.2f MBps time %.4f secs", throughput, time / 1e6); if (!members) { continue; } cli_out ("%*s %-*s %-*s", VOL_TOP_PERF_SPEED_WIDTH, "MBps", VOL_TOP_PERF_FILENAME_DEF_WIDTH, "Filename", VOL_TOP_PERF_TIME_WIDTH, "Time"); cli_out ("%*s %-*s %-*s", VOL_TOP_PERF_SPEED_WIDTH, "====", VOL_TOP_PERF_FILENAME_DEF_WIDTH, "========", VOL_TOP_PERF_TIME_WIDTH, "===="); break; default: goto out; } for (j = 1; j <= members; j++) { snprintf (key, sizeof (key), "%d-filename-%d", i, j); ret = dict_get_str (dict, key, &filename); if (ret) break; snprintf (key, sizeof (key), "%d-value-%d", i, j); ret = dict_get_uint64 (dict, key, &value); if (ret) goto out; if ( top_op == GF_CLI_TOP_READ_PERF || top_op == GF_CLI_TOP_WRITE_PERF) { snprintf (key, sizeof (key), "%d-time-sec-%d", i, j); ret = dict_get_int32 (dict, key, (int32_t *)&time_sec); if (ret) goto out; snprintf (key, sizeof (key), "%d-time-usec-%d", i, j); ret = dict_get_int32 (dict, key, (int32_t *)&time_usec); if (ret) goto out; gf_time_fmt (timestr, sizeof timestr, time_sec, gf_timefmt_FT); snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr), ".%ld", time_usec); if (strlen (filename) < VOL_TOP_PERF_FILENAME_DEF_WIDTH) cli_out ("%*"PRIu64" %-*s %-*s", VOL_TOP_PERF_SPEED_WIDTH, value, VOL_TOP_PERF_FILENAME_DEF_WIDTH, filename, VOL_TOP_PERF_TIME_WIDTH, timestr); else cli_out ("%*"PRIu64" ...%-*s %-*s", VOL_TOP_PERF_SPEED_WIDTH, value, VOL_TOP_PERF_FILENAME_ALT_WIDTH , filename + strlen (filename) - VOL_TOP_PERF_FILENAME_ALT_WIDTH, VOL_TOP_PERF_TIME_WIDTH, timestr); } else { cli_out ("%"PRIu64"\t\t%s", value, filename); } } } ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); if (dict) dict_unref (dict); free (rsp.dict.dict_val); return ret; } int32_t gf_cli_top_volume (call_frame_t *frame, xlator_t *this, void *data) { int ret = -1; gf_cli_req req = {{0,}}; dict_t *dict = NULL; GF_ASSERT (frame); GF_ASSERT (this); GF_ASSERT (data); if (!frame || !this || !data) goto out; dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_top_volume_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_PROFILE_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int gf_cli_getwd_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf1_cli_getwd_rsp rsp = {0,}; int ret = -1; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf1_cli_getwd_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } if (rsp.op_ret == -1) { cli_err ("getwd failed"); ret = rsp.op_ret; goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to getwd"); cli_out ("%s", rsp.wd); ret = 0; out: cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli_getwd (call_frame_t *frame, xlator_t *this, void *data) { int ret = -1; gf1_cli_getwd_req req = {0,}; GF_ASSERT (frame); GF_ASSERT (this); if (!frame || !this) goto out; ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog, GLUSTER_CLI_GETWD, NULL, this, gf_cli_getwd_cbk, (xdrproc_t) xdr_gf1_cli_getwd_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } void cli_print_volume_status_mempool (dict_t *dict, char *prefix) { int ret = -1; int32_t mempool_count = 0; char *name = NULL; int32_t hotcount = 0; int32_t coldcount = 0; uint64_t paddedsizeof = 0; uint64_t alloccount = 0; int32_t maxalloc = 0; uint64_t pool_misses = 0; int32_t maxstdalloc = 0; char key[1024] = {0,}; int i = 0; GF_ASSERT (dict); GF_ASSERT (prefix); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.mempool-count",prefix); ret = dict_get_int32 (dict, key, &mempool_count); if (ret) goto out; cli_out ("Mempool Stats\n-------------"); cli_out ("%-30s %9s %9s %12s %10s %8s %8s %12s", "Name", "HotCount", "ColdCount", "PaddedSizeof", "AllocCount", "MaxAlloc", "Misses", "Max-StdAlloc"); cli_out ("%-30s %9s %9s %12s %10s %8s %8s %12s", "----", "--------", "---------", "------------", "----------", "--------", "--------", "------------"); for (i = 0; i < mempool_count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.name", prefix, i); ret = dict_get_str (dict, key, &name); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.hotcount", prefix, i); ret = dict_get_int32 (dict, key, &hotcount); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.coldcount", prefix, i); ret = dict_get_int32 (dict, key, &coldcount); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.paddedsizeof", prefix, i); ret = dict_get_uint64 (dict, key, &paddedsizeof); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.alloccount", prefix, i); ret = dict_get_uint64 (dict, key, &alloccount); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.max_alloc", prefix, i); ret = dict_get_int32 (dict, key, &maxalloc); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.max-stdalloc", prefix, i); ret = dict_get_int32 (dict, key, &maxstdalloc); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.pool-misses", prefix, i); ret = dict_get_uint64 (dict, key, &pool_misses); if (ret) goto out; cli_out ("%-30s %9d %9d %12"PRIu64" %10"PRIu64" %8d %8"PRIu64 " %12d", name, hotcount, coldcount, paddedsizeof, alloccount, maxalloc, pool_misses, maxstdalloc); } out: return; } void cli_print_volume_status_mem (dict_t *dict, gf_boolean_t notbrick) { int ret = -1; char *volname = NULL; char *hostname = NULL; char *path = NULL; int online = -1; char key[1024] = {0,}; int brick_index_max = -1; int other_count = 0; int index_max = 0; int val = 0; int i = 0; GF_ASSERT (dict); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; cli_out ("Memory status for volume : %s", volname); ret = dict_get_int32 (dict, "brick-index-max", &brick_index_max); if (ret) goto out; ret = dict_get_int32 (dict, "other-count", &other_count); if (ret) goto out; index_max = brick_index_max + other_count; for (i = 0; i <= index_max; i++) { cli_out ("----------------------------------------------"); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.hostname", i); ret = dict_get_str (dict, key, &hostname); if (ret) continue; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.path", i); ret = dict_get_str (dict, key, &path); if (ret) continue; if (notbrick) cli_out ("%s : %s", hostname, path); else cli_out ("Brick : %s:%s", hostname, path); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", i); ret = dict_get_int32 (dict, key, &online); if (ret) goto out; if (!online) { if (notbrick) cli_out ("%s is offline", hostname); else cli_out ("Brick is offline"); continue; } cli_out ("Mallinfo\n--------"); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.arena", i); ret = dict_get_int32 (dict, key, &val); if (ret) goto out; cli_out ("%-8s : %d","Arena", val); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.ordblks", i); ret = dict_get_int32 (dict, key, &val); if(ret) goto out; cli_out ("%-8s : %d","Ordblks", val); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.smblks", i); ret = dict_get_int32 (dict, key, &val); if(ret) goto out; cli_out ("%-8s : %d","Smblks", val); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.hblks", i); ret = dict_get_int32 (dict, key, &val); if(ret) goto out; cli_out ("%-8s : %d", "Hblks", val); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.hblkhd", i); ret = dict_get_int32 (dict, key, &val); if (ret) goto out; cli_out ("%-8s : %d", "Hblkhd", val); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.usmblks", i); ret = dict_get_int32 (dict, key, &val); if (ret) goto out; cli_out ("%-8s : %d", "Usmblks", val); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.fsmblks", i); ret = dict_get_int32 (dict, key, &val); if (ret) goto out; cli_out ("%-8s : %d", "Fsmblks", val); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.uordblks", i); ret = dict_get_int32 (dict, key, &val); if (ret) goto out; cli_out ("%-8s : %d", "Uordblks", val); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.fordblks", i); ret = dict_get_int32 (dict, key, &val); if (ret) goto out; cli_out ("%-8s : %d", "Fordblks", val); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.keepcost", i); ret = dict_get_int32 (dict, key, &val); if (ret) goto out; cli_out ("%-8s : %d", "Keepcost", val); cli_out (" "); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d", i); cli_print_volume_status_mempool (dict, key); } out: cli_out ("----------------------------------------------\n"); return; } void cli_print_volume_status_client_list (dict_t *dict, gf_boolean_t notbrick) { int ret = -1; char *volname = NULL; int client_count = 0; int current_count = 0; char key[1024] = {0,}; int i = 0; int total = 0; char *name = NULL; gf_boolean_t is_fuse_done = _gf_false; gf_boolean_t is_gfapi_done = _gf_false; gf_boolean_t is_tierd_done = _gf_false; gf_boolean_t is_rebalance_done = _gf_false; gf_boolean_t is_glustershd_done = _gf_false; gf_boolean_t is_quotad_done = _gf_false; gf_boolean_t is_snapd_done = _gf_false; GF_ASSERT (dict); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; cli_out ("Client connections for volume %s", volname); ret = dict_get_int32 (dict, "client-count", &client_count); if (ret) goto out; cli_out ("%-48s %15s", "Name", "count"); cli_out ("%-48s %15s", "-----", "------"); for (i = 0; i < client_count; i++) { name = NULL; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "client%d.name", i); ret = dict_get_str (dict, key, &name); if (!strncmp (name, "fuse", 4)) { if (!is_fuse_done) { is_fuse_done = _gf_true; ret = dict_get_int32 (dict, "fuse-count", ¤t_count); if (ret) goto out; total = total + current_count; goto print; } continue; } else if (!strncmp (name, "gfapi", 5)) { if (!is_gfapi_done) { is_gfapi_done = _gf_true; ret = dict_get_int32 (dict, "gfapi-count", ¤t_count); if (ret) goto out; total = total + current_count; goto print; } continue; } else if (!strcmp(name, "tierd")) { if (!is_tierd_done) { is_tierd_done = _gf_true; ret = dict_get_int32 (dict, "tierd-count", ¤t_count); if (ret) goto out; total = total + current_count; goto print; } continue; } else if (!strcmp(name, "rebalance")) { if (!is_rebalance_done) { is_rebalance_done = _gf_true; ret = dict_get_int32 (dict, "rebalance-count", ¤t_count); if (ret) goto out; total = total + current_count; goto print; } continue; } else if (!strcmp(name, "glustershd")) { if (!is_glustershd_done) { is_glustershd_done = _gf_true; ret = dict_get_int32 (dict, "glustershd-count", ¤t_count); if (ret) goto out; total = total + current_count; goto print; } continue; } else if (!strcmp(name, "quotad")) { if (!is_quotad_done) { is_quotad_done = _gf_true; ret = dict_get_int32 (dict, "quotad-count", ¤t_count); if (ret) goto out; total = total + current_count; goto print; } continue; } else if (!strcmp(name, "snapd")) { if (!is_snapd_done) { is_snapd_done = _gf_true; ret = dict_get_int32 (dict, "snapd-count", ¤t_count); if (ret) goto out; total = total + current_count; goto print; } continue; } print: cli_out ("%-48s %15d", name, current_count); } out: cli_out ("\ntotal clients for volume %s : %d ", volname, total); cli_out ("-----------------------------------------------------------------\n"); return; } void cli_print_volume_status_clients (dict_t *dict, gf_boolean_t notbrick) { int ret = -1; char *volname = NULL; int brick_index_max = -1; int other_count = 0; int index_max = 0; char *hostname = NULL; char *path = NULL; int online = -1; int client_count = 0; char *clientname = NULL; uint64_t bytesread = 0; uint64_t byteswrite = 0; uint32_t opversion = 0; char key[1024] = {0,}; int i = 0; int j = 0; GF_ASSERT (dict); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; cli_out ("Client connections for volume %s", volname); ret = dict_get_int32 (dict, "brick-index-max", &brick_index_max); if (ret) goto out; ret = dict_get_int32 (dict, "other-count", &other_count); if (ret) goto out; index_max = brick_index_max + other_count; for (i = 0; i <= index_max; i++) { hostname = NULL; path = NULL; online = -1; client_count = 0; clientname = NULL; bytesread = 0; byteswrite = 0; cli_out ("----------------------------------------------"); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.hostname", i); ret = dict_get_str (dict, key, &hostname); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.path", i); ret = dict_get_str (dict, key, &path); if (hostname && path) { if (notbrick) cli_out ("%s : %s", hostname, path); else cli_out ("Brick : %s:%s", hostname, path); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", i); ret = dict_get_int32 (dict, key, &online); if (!online) { if (notbrick) cli_out ("%s is offline", hostname); else cli_out ("Brick is offline"); continue; } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.clientcount", i); ret = dict_get_int32 (dict, key, &client_count); if (hostname && path) cli_out ("Clients connected : %d", client_count); if (client_count == 0) continue; cli_out ("%-48s %15s %15s %15s", "Hostname", "BytesRead", "BytesWritten", "OpVersion"); cli_out ("%-48s %15s %15s %15s", "--------", "---------", "------------", "---------"); for (j =0; j < client_count; j++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.client%d.hostname", i, j); ret = dict_get_str (dict, key, &clientname); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.client%d.bytesread", i, j); ret = dict_get_uint64 (dict, key, &bytesread); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.client%d.byteswrite", i, j); ret = dict_get_uint64 (dict, key, &byteswrite); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.client%d.opversion", i, j); ret = dict_get_uint32 (dict, key, &opversion); cli_out ("%-48s %15"PRIu64" %15"PRIu64" %15"PRIu32, clientname, bytesread, byteswrite, opversion); } } out: cli_out ("----------------------------------------------\n"); return; } void cli_print_volume_status_inode_entry (dict_t *dict, char *prefix) { int ret = -1; char key[1024] = {0,}; char *gfid = NULL; uint64_t nlookup = 0; uint32_t ref = 0; int ia_type = 0; char inode_type; GF_ASSERT (dict); GF_ASSERT (prefix); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.gfid", prefix); ret = dict_get_str (dict, key, &gfid); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.nlookup", prefix); ret = dict_get_uint64 (dict, key, &nlookup); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.ref", prefix); ret = dict_get_uint32 (dict, key, &ref); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.ia_type", prefix); ret = dict_get_int32 (dict, key, &ia_type); if (ret) goto out; switch (ia_type) { case IA_IFREG: inode_type = 'R'; break; case IA_IFDIR: inode_type = 'D'; break; case IA_IFLNK: inode_type = 'L'; break; case IA_IFBLK: inode_type = 'B'; break; case IA_IFCHR: inode_type = 'C'; break; case IA_IFIFO: inode_type = 'F'; break; case IA_IFSOCK: inode_type = 'S'; break; default: inode_type = 'I'; break; } cli_out ("%-40s %14"PRIu64" %14"PRIu32" %9c", gfid, nlookup, ref, inode_type); out: return; } void cli_print_volume_status_itables (dict_t *dict, char *prefix) { int ret = -1; char key[1024] = {0,}; uint32_t active_size = 0; uint32_t lru_size = 0; uint32_t purge_size = 0; int i =0; GF_ASSERT (dict); GF_ASSERT (prefix); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.active_size", prefix); ret = dict_get_uint32 (dict, key, &active_size); if (ret) goto out; if (active_size != 0) { cli_out ("Active inodes:"); cli_out ("%-40s %14s %14s %9s", "GFID", "Lookups", "Ref", "IA type"); cli_out ("%-40s %14s %14s %9s", "----", "-------", "---", "-------"); } for (i = 0; i < active_size; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.active%d", prefix, i); cli_print_volume_status_inode_entry (dict, key); } cli_out (" "); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.lru_size", prefix); ret = dict_get_uint32 (dict, key, &lru_size); if (ret) goto out; if (lru_size != 0) { cli_out ("LRU inodes:"); cli_out ("%-40s %14s %14s %9s", "GFID", "Lookups", "Ref", "IA type"); cli_out ("%-40s %14s %14s %9s", "----", "-------", "---", "-------"); } for (i = 0; i < lru_size; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.lru%d", prefix, i); cli_print_volume_status_inode_entry (dict, key); } cli_out (" "); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.purge_size", prefix); ret = dict_get_uint32 (dict, key, &purge_size); if (ret) goto out; if (purge_size != 0) { cli_out ("Purged inodes:"); cli_out ("%-40s %14s %14s %9s", "GFID", "Lookups", "Ref", "IA type"); cli_out ("%-40s %14s %14s %9s", "----", "-------", "---", "-------"); } for (i = 0; i < purge_size; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.purge%d", prefix, i); cli_print_volume_status_inode_entry (dict, key); } out: return; } void cli_print_volume_status_inode (dict_t *dict, gf_boolean_t notbrick) { int ret = -1; char *volname = NULL; int brick_index_max = -1; int other_count = 0; int index_max = 0; char *hostname = NULL; char *path = NULL; int online = -1; int conn_count = 0; char key[1024] = {0,}; int i = 0; int j = 0; GF_ASSERT (dict); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; cli_out ("Inode tables for volume %s", volname); ret = dict_get_int32 (dict, "brick-index-max", &brick_index_max); if (ret) goto out; ret = dict_get_int32 (dict, "other-count", &other_count); if (ret) goto out; index_max = brick_index_max + other_count; for ( i = 0; i <= index_max; i++) { cli_out ("----------------------------------------------"); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.hostname", i); ret = dict_get_str (dict, key, &hostname); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.path", i); ret = dict_get_str (dict, key, &path); if (ret) goto out; if (notbrick) cli_out ("%s : %s", hostname, path); else cli_out ("Brick : %s:%s", hostname, path); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", i); ret = dict_get_int32 (dict, key, &online); if (ret) goto out; if (!online) { if (notbrick) cli_out ("%s is offline", hostname); else cli_out ("Brick is offline"); continue; } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.conncount", i); ret = dict_get_int32 (dict, key, &conn_count); if (ret) goto out; for (j = 0; j < conn_count; j++) { if (conn_count > 1) cli_out ("Connection %d:", j+1); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.conn%d.itable", i, j); cli_print_volume_status_itables (dict, key); cli_out (" "); } } out: cli_out ("----------------------------------------------"); return; } void cli_print_volume_status_fdtable (dict_t *dict, char *prefix) { int ret = -1; char key[1024] = {0,}; int refcount = 0; uint32_t maxfds = 0; int firstfree = 0; int openfds = 0; int fd_pid = 0; int fd_refcount = 0; int fd_flags = 0; int i = 0; GF_ASSERT (dict); GF_ASSERT (prefix); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.refcount", prefix); ret = dict_get_int32 (dict, key, &refcount); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.maxfds", prefix); ret = dict_get_uint32 (dict, key, &maxfds); if (ret) goto out; memset (key, 0 ,sizeof (key)); snprintf (key, sizeof (key), "%s.firstfree", prefix); ret = dict_get_int32 (dict, key, &firstfree); if (ret) goto out; cli_out ("RefCount = %d MaxFDs = %d FirstFree = %d", refcount, maxfds, firstfree); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.openfds", prefix); ret = dict_get_int32 (dict, key, &openfds); if (ret) goto out; if (0 == openfds) { cli_err ("No open fds"); goto out; } cli_out ("%-19s %-19s %-19s %-19s", "FD Entry", "PID", "RefCount", "Flags"); cli_out ("%-19s %-19s %-19s %-19s", "--------", "---", "--------", "-----"); for (i = 0; i < maxfds ; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.fdentry%d.pid", prefix, i); ret = dict_get_int32 (dict, key, &fd_pid); if (ret) continue; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.fdentry%d.refcount", prefix, i); ret = dict_get_int32 (dict, key, &fd_refcount); if (ret) continue; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.fdentry%d.flags", prefix, i); ret = dict_get_int32 (dict, key, &fd_flags); if (ret) continue; cli_out ("%-19d %-19d %-19d %-19d", i, fd_pid, fd_refcount, fd_flags); } out: return; } void cli_print_volume_status_fd (dict_t *dict, gf_boolean_t notbrick) { int ret = -1; char *volname = NULL; int brick_index_max = -1; int other_count = 0; int index_max = 0; char *hostname = NULL; char *path = NULL; int online = -1; int conn_count = 0; char key[1024] = {0,}; int i = 0; int j = 0; GF_ASSERT (dict); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; cli_out ("FD tables for volume %s", volname); ret = dict_get_int32 (dict, "brick-index-max", &brick_index_max); if (ret) goto out; ret = dict_get_int32 (dict, "other-count", &other_count); if (ret) goto out; index_max = brick_index_max + other_count; for (i = 0; i <= index_max; i++) { cli_out ("----------------------------------------------"); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.hostname", i); ret = dict_get_str (dict, key, &hostname); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.path", i); ret = dict_get_str (dict, key, &path); if (ret) goto out; if (notbrick) cli_out ("%s : %s", hostname, path); else cli_out ("Brick : %s:%s", hostname, path); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", i); ret = dict_get_int32 (dict, key, &online); if (ret) goto out; if (!online) { if (notbrick) cli_out ("%s is offline", hostname); else cli_out ("Brick is offline"); continue; } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.conncount", i); ret = dict_get_int32 (dict, key, &conn_count); if (ret) goto out; for (j = 0; j < conn_count; j++) { cli_out ("Connection %d:", j+1); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.conn%d.fdtable", i, j); cli_print_volume_status_fdtable (dict, key); cli_out (" "); } } out: cli_out ("----------------------------------------------"); return; } void cli_print_volume_status_call_frame (dict_t *dict, char *prefix) { int ret = -1; char key[1024] = {0,}; int ref_count = 0; char *translator = 0; int complete = 0; char *parent = NULL; char *wind_from = NULL; char *wind_to = NULL; char *unwind_from = NULL; char *unwind_to = NULL; if (!dict || !prefix) return; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.refcount", prefix); ret = dict_get_int32 (dict, key, &ref_count); if (ret) return; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.translator", prefix); ret = dict_get_str (dict, key, &translator); if (ret) return; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.complete", prefix); ret = dict_get_int32 (dict, key, &complete); if (ret) return; cli_out (" Ref Count = %d", ref_count); cli_out (" Translator = %s", translator); cli_out (" Completed = %s", (complete ? "Yes" : "No")); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.parent", prefix); ret = dict_get_str (dict, key, &parent); if (!ret) cli_out (" Parent = %s", parent); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.windfrom", prefix); ret = dict_get_str (dict, key, &wind_from); if (!ret) cli_out (" Wind From = %s", wind_from); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.windto", prefix); ret = dict_get_str (dict, key, &wind_to); if (!ret) cli_out (" Wind To = %s", wind_to); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.unwindfrom", prefix); ret = dict_get_str (dict, key, &unwind_from); if (!ret) cli_out (" Unwind From = %s", unwind_from); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.unwindto", prefix); ret = dict_get_str (dict, key, &unwind_to); if (!ret) cli_out (" Unwind To = %s", unwind_to); } void cli_print_volume_status_call_stack (dict_t *dict, char *prefix) { int ret = -1; char key[1024] = {0,}; int uid = 0; int gid = 0; int pid = 0; uint64_t unique = 0; //char *op = NULL; int count = 0; int i = 0; if (!dict || !prefix) return; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.uid", prefix); ret = dict_get_int32 (dict, key, &uid); if (ret) return; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.gid", prefix); ret = dict_get_int32 (dict, key, &gid); if (ret) return; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pid", prefix); ret = dict_get_int32 (dict, key, &pid); if (ret) return; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.unique", prefix); ret = dict_get_uint64 (dict, key, &unique); if (ret) return; /* memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.op", prefix); ret = dict_get_str (dict, key, &op); if (ret) return; */ memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.count", prefix); ret = dict_get_int32 (dict, key, &count); if (ret) return; cli_out (" UID : %d", uid); cli_out (" GID : %d", gid); cli_out (" PID : %d", pid); cli_out (" Unique : %"PRIu64, unique); //cli_out ("\tOp : %s", op); cli_out (" Frames : %d", count); for (i = 0; i < count; i++) { cli_out (" Frame %d", i+1); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.frame%d", prefix, i); cli_print_volume_status_call_frame (dict, key); } cli_out (" "); } void cli_print_volume_status_callpool (dict_t *dict, gf_boolean_t notbrick) { int ret = -1; char *volname = NULL; int brick_index_max = -1; int other_count = 0; int index_max = 0; char *hostname = NULL; char *path = NULL; int online = -1; int call_count = 0; char key[1024] = {0,}; int i = 0; int j = 0; GF_ASSERT (dict); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; cli_out ("Pending calls for volume %s", volname); ret = dict_get_int32 (dict, "brick-index-max", &brick_index_max); if (ret) goto out; ret = dict_get_int32 (dict, "other-count", &other_count); if (ret) goto out; index_max = brick_index_max + other_count; for (i = 0; i <= index_max; i++) { cli_out ("----------------------------------------------"); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.hostname", i); ret = dict_get_str (dict, key, &hostname); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.path", i); ret = dict_get_str (dict, key, &path); if (ret) goto out; if (notbrick) cli_out ("%s : %s", hostname, path); else cli_out ("Brick : %s:%s", hostname, path); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", i); ret = dict_get_int32 (dict, key, &online); if (ret) goto out; if (!online) { if (notbrick) cli_out ("%s is offline", hostname); else cli_out ("Brick is offline"); continue; } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.callpool.count", i); ret = dict_get_int32 (dict, key, &call_count); if (ret) goto out; cli_out ("Pending calls: %d", call_count); if (0 == call_count) continue; for (j = 0; j < call_count; j++) { cli_out ("Call Stack%d", j+1); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.callpool.stack%d", i, j); cli_print_volume_status_call_stack (dict, key); } } out: cli_out ("----------------------------------------------"); return; } static void cli_print_volume_status_tasks (dict_t *dict) { int ret = -1; int i = 0; int j = 0; int count = 0; int task_count = 0; int status = 0; char *op = NULL; char *task_id_str = NULL; char *volname = NULL; char key[1024] = {0,}; char task[1024] = {0,}; char *brick = NULL; ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = dict_get_int32 (dict, "tasks", &task_count); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get tasks count"); return; } cli_out ("Task Status of Volume %s", volname); cli_print_line (CLI_BRICK_STATUS_LINE_LEN); if (task_count == 0) { cli_out ("There are no active volume tasks"); cli_out (" "); return; } for (i = 0; i < task_count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "task%d.type", i); ret = dict_get_str(dict, key, &op); if (ret) return; cli_out ("%-20s : %-20s", "Task", op); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "task%d.id", i); ret = dict_get_str (dict, key, &task_id_str); if (ret) return; cli_out ("%-20s : %-20s", "ID", task_id_str); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "task%d.status", i); ret = dict_get_int32 (dict, key, &status); if (ret) return; snprintf (task, sizeof (task), "task%d", i); if (!strcmp (op, "Remove brick")) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.count", task); ret = dict_get_int32 (dict, key, &count); if (ret) goto out; cli_out ("%-20s", "Removed bricks:"); for (j = 1; j <= count; j++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key),"%s.brick%d", task, j); ret = dict_get_str (dict, key, &brick); if (ret) goto out; cli_out ("%-20s", brick); } } cli_out ("%-20s : %-20s", "Status", cli_vol_task_status_str[status]); cli_out (" "); } out: return; } static int gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { int ret = -1; int brick_index_max = -1; int other_count = 0; int index_max = 0; int i = 0; int type = -1; int hot_brick_count = -1; int pid = -1; uint32_t cmd = 0; gf_boolean_t notbrick = _gf_false; char key[1024] = {0,}; char *hostname = NULL; char *path = NULL; char *volname = NULL; dict_t *dict = NULL; gf_cli_rsp rsp = {0,}; cli_volume_status_t status = {0}; cli_local_t *local = NULL; gf_boolean_t wipe_local = _gf_false; char msg[1024] = {0,}; GF_ASSERT (myframe); if (req->rpc_status == -1) goto out; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received response to status cmd"); local = ((call_frame_t *) myframe)->local; if (!local) { local = cli_local_get (); if (!local) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Failed to get local"); goto out; } wipe_local = _gf_true; } if (rsp.op_ret) { if (strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "Unable to obtain volume " "status information."); if (global_state->mode & GLUSTER_MODE_XML) { if (!local->all) cli_xml_output_str ("volStatus", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); ret = 0; goto out; } cli_err ("%s", msg); if (local && local->all) { ret = 0; cli_out (" "); } else ret = -1; goto out; } dict = dict_new (); if (!dict) goto out; ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) goto out; ret = dict_get_uint32 (dict, "cmd", &cmd); if (ret) goto out; if ((cmd & GF_CLI_STATUS_ALL)) { if (local && local->dict) { dict_ref (dict); ret = dict_set_static_ptr (local->dict, "rsp-dict", dict); ret = 0; } else { gf_log ("cli", GF_LOG_ERROR, "local not found"); ret = -1; } goto out; } if ((cmd & GF_CLI_STATUS_NFS) || (cmd & GF_CLI_STATUS_SHD) || (cmd & GF_CLI_STATUS_QUOTAD) || (cmd & GF_CLI_STATUS_SNAPD) || (cmd & GF_CLI_STATUS_BITD) || (cmd & GF_CLI_STATUS_SCRUB) || (cmd & GF_CLI_STATUS_TIERD)) notbrick = _gf_true; if (global_state->mode & GLUSTER_MODE_XML) { if (!local->all) { ret = cli_xml_output_vol_status_begin (local, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto xml_end; } } if (cmd & GF_CLI_STATUS_TASKS) { ret = cli_xml_output_vol_status_tasks_detail (local, dict); if (ret) { gf_log ("cli", GF_LOG_ERROR,"Error outputting " "to xml"); goto xml_end; } } else { ret = cli_xml_output_vol_status (local, dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto xml_end; } } xml_end: if (!local->all) { ret = cli_xml_output_vol_status_end (local); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); } } goto out; } status.brick = GF_CALLOC (1, PATH_MAX + 256, gf_common_mt_strdup); if (!status.brick) { errno = ENOMEM; ret = -1; goto out; } switch (cmd & GF_CLI_STATUS_MASK) { case GF_CLI_STATUS_MEM: cli_print_volume_status_mem (dict, notbrick); goto cont; break; case GF_CLI_STATUS_CLIENTS: cli_print_volume_status_clients (dict, notbrick); goto cont; break; case GF_CLI_STATUS_CLIENT_LIST: cli_print_volume_status_client_list (dict, notbrick); goto cont; break; case GF_CLI_STATUS_INODE: cli_print_volume_status_inode (dict, notbrick); goto cont; break; case GF_CLI_STATUS_FD: cli_print_volume_status_fd (dict, notbrick); goto cont; break; case GF_CLI_STATUS_CALLPOOL: cli_print_volume_status_callpool (dict, notbrick); goto cont; break; case GF_CLI_STATUS_TASKS: cli_print_volume_status_tasks (dict); goto cont; break; default: break; } ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = dict_get_int32 (dict, "brick-index-max", &brick_index_max); if (ret) goto out; ret = dict_get_int32 (dict, "other-count", &other_count); if (ret) goto out; index_max = brick_index_max + other_count; ret = dict_get_int32 (dict, "type", &type); if (ret) goto out; ret = dict_get_int32 (dict, "hot_brick_count", &hot_brick_count); if (ret) goto out; cli_out ("Status of volume: %s", volname); if ((cmd & GF_CLI_STATUS_DETAIL) == 0) { cli_out ("%-*s %s %s %s %s", CLI_VOL_STATUS_BRICK_LEN, "Gluster process", "TCP Port", "RDMA Port", "Online", "Pid"); cli_print_line (CLI_BRICK_STATUS_LINE_LEN); } if (type == GF_CLUSTER_TYPE_TIER) { cli_out ("Hot Bricks:"); } for (i = 0; i <= index_max; i++) { if (type == GF_CLUSTER_TYPE_TIER && i == hot_brick_count) { cli_out ("Cold Bricks:"); } status.rdma_port = 0; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.hostname", i); ret = dict_get_str (dict, key, &hostname); if (ret) continue; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.path", i); ret = dict_get_str (dict, key, &path); if (ret) continue; /* Brick/not-brick is handled separately here as all * types of nodes are contained in the default output */ memset (status.brick, 0, PATH_MAX + 255); if (!strcmp (hostname, "NFS Server") || !strcmp (hostname, "Self-heal Daemon") || !strcmp (hostname, "Quota Daemon") || !strcmp (hostname, "Snapshot Daemon") || !strcmp (hostname, "Scrubber Daemon") || !strcmp (hostname, "Bitrot Daemon") || !strcmp (hostname, "Tier Daemon")) snprintf (status.brick, PATH_MAX + 255, "%s on %s", hostname, path); else { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.rdma_port", i); ret = dict_get_int32 (dict, key, &(status.rdma_port)); if (ret) continue; snprintf (status.brick, PATH_MAX + 255, "Brick %s:%s", hostname, path); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.port", i); ret = dict_get_int32 (dict, key, &(status.port)); if (ret) continue; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", i); ret = dict_get_int32 (dict, key, &(status.online)); if (ret) continue; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.pid", i); ret = dict_get_int32 (dict, key, &pid); if (ret) continue; if (pid == -1) ret = gf_asprintf (&(status.pid_str), "%s", "N/A"); else ret = gf_asprintf (&(status.pid_str), "%d", pid); if (ret == -1) goto out; if ((cmd & GF_CLI_STATUS_DETAIL)) { ret = cli_get_detail_status (dict, i, &status); if (ret) goto out; cli_print_line (CLI_BRICK_STATUS_LINE_LEN); cli_print_detailed_status (&status); } else { cli_print_brick_status (&status); } } cli_out (" "); if ((cmd & GF_CLI_STATUS_MASK) == GF_CLI_STATUS_NONE) cli_print_volume_status_tasks (dict); cont: ret = rsp.op_ret; out: if (dict) dict_unref (dict); GF_FREE (status.brick); if (local && wipe_local) { cli_local_wipe (local); } cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli_status_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = -1; dict_t *dict = NULL; if (!frame || !this || !data) goto out; dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_status_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_STATUS_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning: %d", ret); return ret; } int gf_cli_status_volume_all (call_frame_t *frame, xlator_t *this, void *data) { int i = 0; int ret = -1; int vol_count = -1; uint32_t cmd = 0; char key[1024] = {0}; char *volname = NULL; void *vol_dict = NULL; dict_t *dict = NULL; cli_local_t *local = NULL; if (!frame) goto out; if (!frame->local) goto out; local = frame->local; ret = dict_get_uint32 (local->dict, "cmd", &cmd); if (ret) goto out; local->all = _gf_true; ret = gf_cli_status_volume (frame, this, data); if (ret) goto out; ret = dict_get_ptr (local->dict, "rsp-dict", &vol_dict); if (ret) goto out; ret = dict_get_int32 ((dict_t *)vol_dict, "vol_count", &vol_count); if (ret) { cli_err ("Failed to get names of volumes"); goto out; } /* remove the "all" flag in cmd */ cmd &= ~GF_CLI_STATUS_ALL; cmd |= GF_CLI_STATUS_VOL; if (global_state->mode & GLUSTER_MODE_XML) { //TODO: Pass proper op_* values ret = cli_xml_output_vol_status_begin (local, 0,0, NULL); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto xml_end; } } if (vol_count == 0 && !(global_state->mode & GLUSTER_MODE_XML)) { cli_err ("No volumes present"); ret = 0; goto out; } for (i = 0; i < vol_count; i++) { dict = dict_new (); if (!dict) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "vol%d", i); ret = dict_get_str (vol_dict, key, &volname); if (ret) goto out; ret = dict_set_str (dict, "volname", volname); if (ret) goto out; ret = dict_set_uint32 (dict, "cmd", cmd); if (ret) goto out; ret = gf_cli_status_volume (frame, this, dict); if (ret) goto out; dict_unref (dict); } xml_end: if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_status_end (local); } out: if (ret) gf_log ("cli", GF_LOG_ERROR, "status all failed"); if (vol_dict) dict_unref (vol_dict); if (ret && dict) dict_unref (dict); if (local) cli_local_wipe (local); if (frame) frame->local = NULL; return ret; } static int gf_cli_mount_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf1_cli_mount_rsp rsp = {0,}; int ret = -1; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf1_cli_mount_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to mount"); if (rsp.op_ret == 0) { ret = 0; cli_out ("%s", rsp.path); } else { /* weird sounding but easy to parse... */ cli_err ("%d : failed with this errno (%s)", rsp.op_errno, strerror (rsp.op_errno)); ret = -1; } out: cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli_mount (call_frame_t *frame, xlator_t *this, void *data) { gf1_cli_mount_req req = {0,}; int ret = -1; void **dataa = data; char *label = NULL; dict_t *dict = NULL; if (!frame || !this || !data) goto out; label = dataa[0]; dict = dataa[1]; req.label = label; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, &req.dict.dict_len); if (ret) { ret = -1; goto out; } ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog, GLUSTER_CLI_MOUNT, NULL, this, gf_cli_mount_cbk, (xdrproc_t)xdr_gf1_cli_mount_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } static int gf_cli_umount_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf1_cli_umount_rsp rsp = {0,}; int ret = -1; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf1_cli_umount_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to mount"); if (rsp.op_ret == 0) ret = 0; else { cli_err ("umount failed"); ret = -1; } out: cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli_umount (call_frame_t *frame, xlator_t *this, void *data) { gf1_cli_umount_req req = {0,}; int ret = -1; dict_t *dict = NULL; if (!frame || !this || !data) goto out; dict = data; ret = dict_get_str (dict, "path", &req.path); if (ret == 0) ret = dict_get_int32 (dict, "lazy", &req.lazy); if (ret) { ret = -1; goto out; } ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog, GLUSTER_CLI_UMOUNT, NULL, this, gf_cli_umount_cbk, (xdrproc_t)xdr_gf1_cli_umount_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } void cmd_heal_volume_statistics_out (dict_t *dict, int brick) { uint64_t num_entries = 0; int ret = 0; char key[256] = {0}; char *hostname = NULL; uint64_t i = 0; uint64_t healed_count = 0; uint64_t split_brain_count = 0; uint64_t heal_failed_count = 0; char *start_time_str = NULL; char *end_time_str = NULL; char *crawl_type = NULL; int progress = -1; snprintf (key, sizeof key, "%d-hostname", brick); ret = dict_get_str (dict, key, &hostname); if (ret) goto out; cli_out ("------------------------------------------------"); cli_out ("\nCrawl statistics for brick no %d", brick); cli_out ("Hostname of brick %s", hostname); snprintf (key, sizeof key, "statistics-%d-count", brick); ret = dict_get_uint64 (dict, key, &num_entries); if (ret) goto out; for (i = 0; i < num_entries; i++) { snprintf (key, sizeof key, "statistics_crawl_type-%d-%"PRIu64, brick, i); ret = dict_get_str (dict, key, &crawl_type); if (ret) goto out; snprintf (key, sizeof key, "statistics_healed_cnt-%d-%"PRIu64, brick,i); ret = dict_get_uint64 (dict, key, &healed_count); if (ret) goto out; snprintf (key, sizeof key, "statistics_sb_cnt-%d-%"PRIu64, brick, i); ret = dict_get_uint64 (dict, key, &split_brain_count); if (ret) goto out; snprintf (key, sizeof key, "statistics_heal_failed_cnt-%d-%"PRIu64, brick, i); ret = dict_get_uint64 (dict, key, &heal_failed_count); if (ret) goto out; snprintf (key, sizeof key, "statistics_strt_time-%d-%"PRIu64, brick, i); ret = dict_get_str (dict, key, &start_time_str); if (ret) goto out; snprintf (key, sizeof key, "statistics_end_time-%d-%"PRIu64, brick, i); ret = dict_get_str (dict, key, &end_time_str); if (ret) goto out; snprintf (key, sizeof key, "statistics_inprogress-%d-%"PRIu64, brick, i); ret = dict_get_int32 (dict, key, &progress); if (ret) goto out; cli_out ("\nStarting time of crawl: %s", start_time_str); if (progress == 1) cli_out ("Crawl is in progress"); else cli_out ("Ending time of crawl: %s", end_time_str); cli_out ("Type of crawl: %s", crawl_type); cli_out ("No. of entries healed: %"PRIu64, healed_count); cli_out ("No. of entries in split-brain: %"PRIu64, split_brain_count); cli_out ("No. of heal failed entries: %"PRIu64, heal_failed_count); } out: return; } void cmd_heal_volume_brick_out (dict_t *dict, int brick) { uint64_t num_entries = 0; int ret = 0; char key[256] = {0}; char *hostname = NULL; char *path = NULL; char *status = NULL; uint64_t i = 0; uint32_t time = 0; char timestr[32] = {0}; char *shd_status = NULL; snprintf (key, sizeof key, "%d-hostname", brick); ret = dict_get_str (dict, key, &hostname); if (ret) goto out; snprintf (key, sizeof key, "%d-path", brick); ret = dict_get_str (dict, key, &path); if (ret) goto out; cli_out ("\nBrick %s:%s", hostname, path); snprintf (key, sizeof key, "%d-status", brick); ret = dict_get_str (dict, key, &status); if (status && strlen (status)) cli_out ("Status: %s", status); snprintf (key, sizeof key, "%d-shd-status",brick); ret = dict_get_str (dict, key, &shd_status); if(!shd_status) { snprintf (key, sizeof key, "%d-count", brick); ret = dict_get_uint64 (dict, key, &num_entries); cli_out ("Number of entries: %"PRIu64, num_entries); for (i = 0; i < num_entries; i++) { snprintf (key, sizeof key, "%d-%"PRIu64, brick, i); ret = dict_get_str (dict, key, &path); if (ret) continue; time = 0; snprintf (key, sizeof key, "%d-%"PRIu64"-time", brick, i); ret = dict_get_uint32 (dict, key, &time); if (!time) { cli_out ("%s", path); } else { gf_time_fmt (timestr, sizeof timestr, time, gf_timefmt_FT); if (i == 0) { cli_out ("at path on brick"); cli_out ("-----------------------------------"); } cli_out ("%s %s", timestr, path); } } } out: return; } void cmd_heal_volume_statistics_heal_count_out (dict_t *dict, int brick) { uint64_t num_entries = 0; int ret = 0; char key[256] = {0}; char *hostname = NULL; char *path = NULL; char *status = NULL; char *shd_status = NULL; snprintf (key, sizeof key, "%d-hostname", brick); ret = dict_get_str (dict, key, &hostname); if (ret) goto out; snprintf (key, sizeof key, "%d-path", brick); ret = dict_get_str (dict, key, &path); if (ret) goto out; cli_out ("\nBrick %s:%s", hostname, path); snprintf (key, sizeof key, "%d-status", brick); ret = dict_get_str (dict, key, &status); if (status && strlen (status)) cli_out ("Status: %s", status); snprintf (key, sizeof key, "%d-shd-status",brick); ret = dict_get_str (dict, key, &shd_status); if(!shd_status) { snprintf (key, sizeof key, "%d-hardlinks", brick); ret = dict_get_uint64 (dict, key, &num_entries); if (ret) cli_out ("No gathered input for this brick"); else cli_out ("Number of entries: %"PRIu64, num_entries); } out: return; } int gf_is_cli_heal_get_command (gf_xl_afr_op_t heal_op) { /* If the command is get command value is 1 otherwise 0, for invalid commands -1 */ int get_cmds[GF_SHD_OP_HEAL_DISABLE + 1] = { [GF_SHD_OP_INVALID] = -1, [GF_SHD_OP_HEAL_INDEX] = 0, [GF_SHD_OP_HEAL_FULL] = 0, [GF_SHD_OP_INDEX_SUMMARY] = 1, [GF_SHD_OP_HEALED_FILES] = 1, [GF_SHD_OP_HEAL_FAILED_FILES] = 1, [GF_SHD_OP_SPLIT_BRAIN_FILES] = 1, [GF_SHD_OP_STATISTICS] = 1, [GF_SHD_OP_STATISTICS_HEAL_COUNT] = 1, [GF_SHD_OP_STATISTICS_HEAL_COUNT_PER_REPLICA] = 1, [GF_SHD_OP_HEAL_ENABLE] = 0, [GF_SHD_OP_HEAL_DISABLE] = 0, }; if (heal_op > GF_SHD_OP_INVALID && heal_op <= GF_SHD_OP_HEAL_DISABLE) return get_cmds[heal_op] == 1; return _gf_false; } int gf_cli_heal_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; cli_local_t *local = NULL; char *volname = NULL; call_frame_t *frame = NULL; dict_t *dict = NULL; int brick_count = 0; int i = 0; gf_xl_afr_op_t heal_op = GF_SHD_OP_INVALID; char *operation = NULL; char *substr = NULL; char *heal_op_str = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) { goto out; } frame = myframe; GF_ASSERT (frame->local); local = frame->local; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } ret = dict_get_int32 (local->dict, "heal-op", (int32_t *)&heal_op); //TODO: Proper XML output //#if (HAVE_LIB_XML) // if (global_state->mode & GLUSTER_MODE_XML) { // ret = cli_xml_output_dict ("volHeal", dict, rsp.op_ret, // rsp.op_errno, rsp.op_errstr); // if (ret) // gf_log ("cli", GF_LOG_ERROR, // "Error outputting to xml"); // goto out; // } //#endif ret = dict_get_str (local->dict, "volname", &volname); if (ret) { gf_log (frame->this->name, GF_LOG_ERROR, "failed to get volname"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to heal volume"); operation = "Gathering "; substr = ""; switch (heal_op) { case GF_SHD_OP_HEAL_INDEX: operation = "Launching heal operation "; heal_op_str = "to perform index self heal"; substr = "\nUse heal info commands to check" " status."; break; case GF_SHD_OP_HEAL_FULL: operation = "Launching heal operation "; heal_op_str = "to perform full self heal"; substr = "\nUse heal info commands to check" " status."; break; case GF_SHD_OP_INDEX_SUMMARY: heal_op_str = "list of entries to be healed"; break; case GF_SHD_OP_HEALED_FILES: heal_op_str = "list of healed entries"; break; case GF_SHD_OP_HEAL_FAILED_FILES: heal_op_str = "list of heal failed entries"; break; case GF_SHD_OP_SPLIT_BRAIN_FILES: heal_op_str = "list of split brain entries"; break; case GF_SHD_OP_STATISTICS: heal_op_str = "crawl statistics"; break; case GF_SHD_OP_STATISTICS_HEAL_COUNT: heal_op_str = "count of entries to be healed"; break; case GF_SHD_OP_STATISTICS_HEAL_COUNT_PER_REPLICA: heal_op_str = "count of entries to be healed per replica"; break; /* The below 4 cases are never hit; they're coded only to make * compiler warnings go away.*/ case GF_SHD_OP_SBRAIN_HEAL_FROM_BIGGER_FILE: case GF_SHD_OP_SBRAIN_HEAL_FROM_LATEST_MTIME: case GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK: case GF_SHD_OP_HEAL_SUMMARY: break; case GF_SHD_OP_INVALID: heal_op_str = "invalid heal op"; break; case GF_SHD_OP_HEAL_ENABLE: operation = ""; heal_op_str = "Enable heal"; break; case GF_SHD_OP_HEAL_DISABLE: operation = ""; heal_op_str = "Disable heal"; break; case GF_SHD_OP_GRANULAR_ENTRY_HEAL_ENABLE: operation = ""; heal_op_str = "Enable granular entry heal"; break; case GF_SHD_OP_GRANULAR_ENTRY_HEAL_DISABLE: operation = ""; heal_op_str = "Disable granular entry heal"; break; } if (rsp.op_ret) { if (strcmp (rsp.op_errstr, "")) { cli_err ("%s%s on volume %s has been unsuccessful:", operation, heal_op_str, volname); cli_err ("%s", rsp.op_errstr); } ret = rsp.op_ret; goto out; } else { cli_out ("%s%s on volume %s has been successful %s", operation, heal_op_str, volname, substr); } ret = rsp.op_ret; if (!gf_is_cli_heal_get_command (heal_op)) goto out; dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); goto out; } else { dict->extra_stdfree = rsp.dict.dict_val; } ret = dict_get_int32 (dict, "count", &brick_count); if (ret) goto out; if (!brick_count) { cli_err ("All bricks of volume %s are down.", volname); goto out; } switch (heal_op) { case GF_SHD_OP_STATISTICS: for (i = 0; i < brick_count; i++) cmd_heal_volume_statistics_out (dict, i); break; case GF_SHD_OP_STATISTICS_HEAL_COUNT: case GF_SHD_OP_STATISTICS_HEAL_COUNT_PER_REPLICA: for (i = 0; i < brick_count; i++) cmd_heal_volume_statistics_heal_count_out (dict, i); break; case GF_SHD_OP_INDEX_SUMMARY: case GF_SHD_OP_HEALED_FILES: case GF_SHD_OP_HEAL_FAILED_FILES: case GF_SHD_OP_SPLIT_BRAIN_FILES: for (i = 0; i < brick_count; i++) cmd_heal_volume_brick_out (dict, i); break; default: break; } ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); free (rsp.op_errstr); if (dict) dict_unref (dict); return ret; } int32_t gf_cli_heal_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = cli_to_glusterd (&req, frame, gf_cli_heal_volume_cbk, (xdrproc_t) xdr_gf_cli_req, dict, GLUSTER_CLI_HEAL_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_statedump_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; GF_ASSERT (myframe); if (-1 == req->rpc_status) goto out; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received response to statedump"); if (rsp.op_ret) snprintf (msg, sizeof(msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "Volume statedump successful"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volStatedump", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) cli_err ("volume statedump: failed: %s", msg); else cli_out ("volume statedump: success"); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli_statedump_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; dict_t *options = NULL; int ret = -1; if (!frame || !this || !data) goto out; options = data; ret = cli_to_glusterd (&req, frame, gf_cli_statedump_volume_cbk, (xdrproc_t) xdr_gf_cli_req, options, GLUSTER_CLI_STATEDUMP_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_list_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { int ret = -1; gf_cli_rsp rsp = {0,}; dict_t *dict = NULL; int vol_count = 0;; char *volname = NULL; char key[1024] = {0,}; int i = 0; GF_ASSERT (myframe); if (-1 == req->rpc_status) goto out; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to allocate memory"); goto out; } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_list (dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (rsp.op_ret) cli_err ("%s", rsp.op_errstr); else { ret = dict_get_int32 (dict, "count", &vol_count); if (ret) goto out; if (vol_count == 0) { cli_err ("No volumes present in cluster"); goto out; } for (i = 0; i < vol_count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d", i); ret = dict_get_str (dict, key, &volname); if (ret) goto out; cli_out ("%s", volname); } } ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli_list_volume (call_frame_t *frame, xlator_t *this, void *data) { int ret = -1; gf_cli_req req = {{0,}}; if (!frame || !this) goto out; ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog, GLUSTER_CLI_LIST_VOLUME, NULL, this, gf_cli_list_volume_cbk, (xdrproc_t)xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli_clearlocks_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char *lk_summary = NULL; char *volname = NULL; dict_t *dict = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) goto out; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received response to clear-locks"); if (rsp.op_ret) { cli_err ("Volume clear-locks unsuccessful"); cli_err ("%s", rsp.op_errstr); } else { if (!rsp.dict.dict_len) { cli_err ("Possibly no locks cleared"); ret = 0; goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to serialize response dictionary"); goto out; } ret = dict_get_str (dict, "volname", &volname); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get volname " "from dictionary"); goto out; } ret = dict_get_str (dict, "lk-summary", &lk_summary); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get lock " "summary from dictionary"); goto out; } cli_out ("Volume clear-locks successful"); cli_out ("%s", lk_summary); } ret = rsp.op_ret; out: if (dict) dict_unref (dict); cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli_clearlocks_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; dict_t *options = NULL; int ret = -1; if (!frame || !this || !data) goto out; options = data; ret = cli_to_glusterd (&req, frame, gf_cli_clearlocks_volume_cbk, (xdrproc_t) xdr_gf_cli_req, options, GLUSTER_CLI_CLRLOCKS_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t cli_snapshot_remove_reply (gf_cli_rsp *rsp, dict_t *dict, call_frame_t *frame) { int32_t ret = -1; char *snap_name = NULL; int32_t delete_cmd = -1; cli_local_t *local = NULL; GF_ASSERT (frame); GF_ASSERT (rsp); GF_ASSERT (dict); local = frame->local; ret = dict_get_int32 (dict, "sub-cmd", &delete_cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not get sub-cmd"); goto end; } if ((global_state->mode & GLUSTER_MODE_XML) && (delete_cmd == GF_SNAP_DELETE_TYPE_SNAP)) { ret = cli_xml_output_snap_delete_begin (local, rsp->op_ret, rsp->op_errno, rsp->op_errstr); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create " "xml output for delete"); goto end; } } if (rsp->op_ret && !(global_state->mode & GLUSTER_MODE_XML)) { cli_err ("snapshot delete: failed: %s", rsp->op_errstr ? rsp->op_errstr : "Please check log file for details"); ret = rsp->op_ret; goto out; } if (delete_cmd == GF_SNAP_DELETE_TYPE_ALL || delete_cmd == GF_SNAP_DELETE_TYPE_VOL) { local = ((call_frame_t *) frame) -> local; if (!local) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "frame->local is NULL"); goto out; } /* During first call back of snapshot delete of type * ALL and VOL, We will get the snapcount and snapnames. * Hence to make the subsequent rpc calls for individual * snapshot delete, We need to save it in local dictionary. */ dict_copy (dict, local->dict); ret = 0; goto out; } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_snapshot_delete (local, dict, rsp); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create " "xml output for snapshot delete command"); goto out; } /* Error out in case of the op already failed */ if (rsp->op_ret) { ret = rsp->op_ret; goto out; } } else { ret = dict_get_str (dict, "snapname", &snap_name); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snapname"); goto out; } cli_out ("snapshot delete: %s: snap removed successfully", snap_name); } ret = 0; out: if ((global_state->mode & GLUSTER_MODE_XML) && (delete_cmd == GF_SNAP_DELETE_TYPE_SNAP)) { ret = cli_xml_output_snap_delete_end (local); } end: return ret; } int cli_snapshot_config_display (dict_t *dict, gf_cli_rsp *rsp) { char buf[PATH_MAX] = ""; char *volname = NULL; int ret = -1; int config_command = 0; uint64_t value = 0; uint64_t hard_limit = 0; uint64_t soft_limit = 0; uint64_t i = 0; uint64_t voldisplaycount = 0; char *auto_delete = NULL; char *snap_activate = NULL; GF_ASSERT (dict); GF_ASSERT (rsp); if (rsp->op_ret) { cli_err ("Snapshot Config : failed: %s", rsp->op_errstr ? rsp->op_errstr : "Please check log file for details"); ret = rsp->op_ret; goto out; } ret = dict_get_int32 (dict, "config-command", &config_command); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch config type"); goto out; } ret = dict_get_str (dict, "volname", &volname); /* Ignore the error, as volname is optional */ if (!volname) { volname = "System"; } ret = dict_get_uint64 (dict, "snap-max-hard-limit", &hard_limit); /* Ignore the error, as the key specified is optional */ ret = dict_get_uint64 (dict, "snap-max-soft-limit", &soft_limit); ret = dict_get_str (dict, "auto-delete", &auto_delete); ret = dict_get_str (dict, "snap-activate-on-create", &snap_activate); if (!hard_limit && !soft_limit && config_command != GF_SNAP_CONFIG_DISPLAY && !auto_delete && !snap_activate) { ret = -1; gf_log(THIS->name, GF_LOG_ERROR, "Could not fetch config-key"); goto out; } switch (config_command) { case GF_SNAP_CONFIG_TYPE_SET: if (hard_limit && soft_limit) { cli_out ("snapshot config: snap-max-hard-limit " "& snap-max-soft-limit for system set " "successfully"); } else if (hard_limit) { cli_out ("snapshot config: snap-max-hard-limit " "for %s set successfully", volname); } else if (soft_limit) { cli_out ("snapshot config: snap-max-soft-limit " "for %s set successfully", volname); } else if (auto_delete) { cli_out ("snapshot config: auto-delete " "successfully set"); } else if (snap_activate) { cli_out ("snapshot config: activate-on-create " "successfully set"); } break; case GF_SNAP_CONFIG_DISPLAY: cli_out ("\nSnapshot System Configuration:"); ret = dict_get_uint64 (dict, "snap-max-hard-limit", &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch " "snap_max_hard_limit for %s", volname); ret = -1; goto out; } cli_out ("snap-max-hard-limit : %"PRIu64, value); ret = dict_get_uint64 (dict, "snap-max-soft-limit", &soft_limit); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch " "snap-max-soft-limit for %s", volname); ret = -1; goto out; } cli_out ("snap-max-soft-limit : %"PRIu64"%%", soft_limit); cli_out ("auto-delete : %s", auto_delete); cli_out ("activate-on-create : %s\n", snap_activate); cli_out ("Snapshot Volume Configuration:"); ret = dict_get_uint64 (dict, "voldisplaycount", &voldisplaycount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch voldisplaycount"); ret = -1; goto out; } for (i = 0; i < voldisplaycount; i++) { snprintf (buf, sizeof(buf), "volume%"PRIu64"-volname", i); ret = dict_get_str (dict, buf, &volname); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch " " %s", buf); ret = -1; goto out; } cli_out ("\nVolume : %s", volname); snprintf (buf, sizeof(buf), "volume%"PRIu64"-snap-max-hard-limit", i); ret = dict_get_uint64 (dict, buf, &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch " " %s", buf); ret = -1; goto out; } cli_out ("snap-max-hard-limit : %"PRIu64, value); snprintf (buf, sizeof(buf), "volume%"PRIu64"-active-hard-limit", i); ret = dict_get_uint64 (dict, buf, &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch" " effective snap_max_hard_limit for " "%s", volname); ret = -1; goto out; } cli_out ("Effective snap-max-hard-limit : %"PRIu64, value); snprintf (buf, sizeof(buf), "volume%"PRIu64"-snap-max-soft-limit", i); ret = dict_get_uint64 (dict, buf, &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch " " %s", buf); ret = -1; goto out; } cli_out ("Effective snap-max-soft-limit : %"PRIu64" " "(%"PRIu64"%%)", value, soft_limit); } break; default: break; } ret = 0; out: return ret; } /* This function is used to print the volume related information * of a snap. * * arg - 0, dict : Response Dictionary. * arg - 1, prefix str : snaplist.snap{0..}.vol{0..}.* */ int cli_get_each_volinfo_in_snap (dict_t *dict, char *keyprefix, gf_boolean_t snap_driven) { char key[PATH_MAX] = ""; char *get_buffer = NULL; int value = 0; int ret = -1; char indent[5] = "\t"; char *volname = NULL; GF_ASSERT (dict); GF_ASSERT (keyprefix); if (snap_driven) { ret = snprintf (key, sizeof (key), "%s.volname", keyprefix); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &get_buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); goto out; } cli_out ("%s" INDENT_MAIN_HEAD "%s", indent, "Snap Volume Name", ":", get_buffer); ret = snprintf (key, sizeof (key), "%s.origin-volname", keyprefix); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &volname); if (ret) { gf_log ("cli", GF_LOG_WARNING, "Failed to get %s", key); cli_out ("%-12s", "Origin:"); } cli_out ("%s" INDENT_MAIN_HEAD "%s", indent, "Origin Volume name", ":", volname); ret = snprintf (key, sizeof (key), "%s.snapcount", keyprefix); if (ret < 0) { goto out; } ret = dict_get_int32 (dict, key, &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); goto out; } cli_out ("%s%s %s %s %d", indent, "Snaps taken for", volname, ":", value); ret = snprintf (key, sizeof (key), "%s.snaps-available", keyprefix); if (ret < 0) { goto out; } ret = dict_get_int32 (dict, key, &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); goto out; } cli_out ("%s%s %s %s %d", indent, "Snaps available for", volname, ":", value); } ret = snprintf (key, sizeof (key), "%s.vol-status", keyprefix); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &get_buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); goto out; } cli_out ("%s" INDENT_MAIN_HEAD "%s", indent, "Status", ":", get_buffer); out: return ret; } /* This function is used to print snap related information * arg - 0, dict : Response dictionary. * arg - 1, prefix_str : snaplist.snap{0..}.* */ int cli_get_volinfo_in_snap (dict_t *dict, char *keyprefix) { char key[PATH_MAX] = ""; int i = 0; int volcount = 0; int ret = -1; GF_ASSERT (dict); GF_ASSERT (keyprefix); ret = snprintf (key, sizeof (key), "%s.vol-count", keyprefix); if (ret < 0) { goto out; } ret = dict_get_int32 (dict, key, &volcount); for (i = 1 ; i <= volcount ; i++) { ret = snprintf (key, sizeof (key), "%s.vol%d", keyprefix, i); if (ret < 0) { goto out; } ret = cli_get_each_volinfo_in_snap (dict, key, _gf_true); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not list " "details of volume in a snap"); goto out; } cli_out (" "); } out: return ret; } int cli_get_each_snap_info (dict_t *dict, char *prefix_str, gf_boolean_t snap_driven) { char key_buffer[PATH_MAX] = ""; char *get_buffer = NULL; int ret = -1; char indent[5] = ""; GF_ASSERT (dict); GF_ASSERT (prefix_str); if (!snap_driven) strcat (indent, "\t"); ret = snprintf (key_buffer, sizeof (key_buffer), "%s.snapname", prefix_str); if (ret < 0) { goto out; } ret = dict_get_str (dict, key_buffer, &get_buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to fetch snapname %s ", key_buffer); goto out; } cli_out ("%s" INDENT_MAIN_HEAD "%s", indent, "Snapshot", ":", get_buffer); ret = snprintf (key_buffer, sizeof (key_buffer), "%s.snap-id", prefix_str); if (ret < 0) { goto out; } ret = dict_get_str (dict, key_buffer, &get_buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to fetch snap-id %s ", key_buffer); goto out; } cli_out ("%s" INDENT_MAIN_HEAD "%s", indent, "Snap UUID", ":", get_buffer); ret = snprintf (key_buffer, sizeof (key_buffer), "%s.snap-desc", prefix_str); if (ret < 0) { goto out; } ret = dict_get_str (dict, key_buffer, &get_buffer); if (!ret) { /* Ignore error for description */ cli_out ("%s" INDENT_MAIN_HEAD "%s", indent, "Description", ":", get_buffer); } ret = snprintf (key_buffer, sizeof (key_buffer), "%s.snap-time", prefix_str); if (ret < 0) { goto out; } ret = dict_get_str (dict, key_buffer, &get_buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to fetch snap-time %s ", prefix_str); goto out; } cli_out ("%s" INDENT_MAIN_HEAD "%s", indent, "Created", ":", get_buffer); if (snap_driven) { cli_out ("%-12s", "Snap Volumes:\n"); ret = cli_get_volinfo_in_snap (dict, prefix_str); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to list details " "of the snaps"); goto out; } } out: return ret; } /* This is a generic function to print snap related information. * arg - 0, dict : Response Dictionary */ int cli_call_snapshot_info (dict_t *dict, gf_boolean_t bool_snap_driven) { int snap_count = 0; char key[PATH_MAX] = ""; int ret = -1; int i = 0; GF_ASSERT (dict); ret = dict_get_int32 (dict, "snapcount", &snap_count); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get snapcount"); goto out; } if (snap_count == 0) { cli_out ("No snapshots present"); } for (i = 1 ; i <= snap_count ; i++) { ret = snprintf (key, sizeof (key), "snap%d", i); if (ret < 0) { goto out; } ret = cli_get_each_snap_info (dict, key, bool_snap_driven); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to print snap details"); goto out; } } out: return ret; } int cli_get_snaps_in_volume (dict_t *dict) { int ret = -1; int i = 0; int count = 0; int avail = 0; char key[PATH_MAX] = ""; char *get_buffer = NULL; GF_ASSERT (dict); ret = dict_get_str (dict, "origin-volname", &get_buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch origin-volname"); goto out; } cli_out (INDENT_MAIN_HEAD "%s", "Volume Name", ":", get_buffer); ret = dict_get_int32 (dict, "snapcount", &avail); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch snapcount"); goto out; } cli_out (INDENT_MAIN_HEAD "%d", "Snaps Taken", ":", avail); ret = dict_get_int32 (dict, "snaps-available", &count); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch snaps-available"); goto out; } cli_out (INDENT_MAIN_HEAD "%d", "Snaps Available", ":", count); for (i = 1 ; i <= avail ; i++) { snprintf (key, sizeof (key), "snap%d", i); ret = cli_get_each_snap_info (dict, key, _gf_false); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to print snap details"); goto out; } ret = snprintf (key, sizeof (key), "snap%d.vol1", i); if (ret < 0) { goto out; } ret = cli_get_each_volinfo_in_snap (dict, key, _gf_false); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not get volume " "related information"); goto out; } cli_out (" "); } out: return ret; } int cli_snapshot_list (dict_t *dict) { int snapcount = 0; char key[PATH_MAX] = ""; int ret = -1; int i = 0; char *get_buffer = NULL; GF_ASSERT (dict); ret = dict_get_int32 (dict, "snapcount", &snapcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch snap count"); goto out; } if (snapcount == 0) { cli_out ("No snapshots present"); } for (i = 1 ; i <= snapcount ; i++) { ret = snprintf (key, sizeof (key), "snapname%d", i); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &get_buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not get %s ", key); goto out; } else { cli_out ("%s", get_buffer); } } out: return ret; } int cli_get_snap_volume_status (dict_t *dict, char *key_prefix) { int ret = -1; char key[PATH_MAX] = ""; char *buffer = NULL; int brickcount = 0; int i = 0; int pid = 0; GF_ASSERT (dict); GF_ASSERT (key_prefix); ret = snprintf (key, sizeof (key), "%s.brickcount", key_prefix); if (ret < 0) { goto out; } ret = dict_get_int32 (dict, key, &brickcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to fetch brickcount"); goto out; } for (i = 0 ; i < brickcount ; i++) { ret = snprintf (key, sizeof (key), "%s.brick%d.path", key_prefix, i); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_INFO, "Unable to get Brick Path"); continue; } cli_out ("\n\t%-17s %s %s", "Brick Path", ":", buffer); ret = snprintf (key, sizeof (key), "%s.brick%d.vgname", key_prefix, i); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_INFO, "Unable to get Volume Group"); cli_out ("\t%-17s %s %s", "Volume Group", ":", "N/A"); } else cli_out ("\t%-17s %s %s", "Volume Group", ":", buffer); ret = snprintf (key, sizeof (key), "%s.brick%d.status", key_prefix, i); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_INFO, "Unable to get Brick Running"); cli_out ("\t%-17s %s %s", "Brick Running", ":", "N/A"); } else cli_out ("\t%-17s %s %s", "Brick Running", ":", buffer); ret = snprintf (key, sizeof (key), "%s.brick%d.pid", key_prefix, i); if (ret < 0) { goto out; } ret = dict_get_int32 (dict, key, &pid); if (ret) { gf_log ("cli", GF_LOG_INFO, "Unable to get pid"); cli_out ("\t%-17s %s %s", "Brick PID", ":", "N/A"); } else cli_out ("\t%-17s %s %d", "Brick PID", ":", pid); ret = snprintf (key, sizeof (key), "%s.brick%d.data", key_prefix, i); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_INFO, "Unable to get Data Percent"); cli_out ("\t%-17s %s %s", "Data Percentage", ":", "N/A"); } else cli_out ("\t%-17s %s %s", "Data Percentage", ":", buffer); ret = snprintf (key, sizeof (key), "%s.brick%d.lvsize", key_prefix, i); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_INFO, "Unable to get LV Size"); cli_out ("\t%-17s %s %s", "LV Size", ":", "N/A"); } else cli_out ("\t%-17s %s %s", "LV Size", ":", buffer); } ret = 0; out: return ret; } int cli_get_single_snap_status (dict_t *dict, char *keyprefix) { int ret = -1; char key[PATH_MAX] = ""; int i = 0; int volcount = 0; char *get_buffer = NULL; GF_ASSERT (dict); GF_ASSERT (keyprefix); ret = snprintf (key, sizeof (key), "%s.snapname", keyprefix); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &get_buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get snapname"); goto out; } cli_out ("\nSnap Name : %s", get_buffer); ret = snprintf (key, sizeof (key), "%s.uuid", keyprefix); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &get_buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get snap UUID"); goto out; } cli_out ("Snap UUID : %s", get_buffer); ret = snprintf (key, sizeof (key), "%s.volcount", keyprefix); if (ret < 0) { goto out; } ret = dict_get_int32 (dict, key, &volcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get volume count"); goto out; } for (i = 0 ; i < volcount ; i++) { ret = snprintf (key, sizeof (key), "%s.vol%d", keyprefix, i); if (ret < 0) { goto out; } ret = cli_get_snap_volume_status (dict, key); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not get snap volume status"); goto out; } } out: return ret; } int32_t cli_populate_req_dict_for_delete (dict_t *snap_dict, dict_t *dict, size_t index) { int32_t ret = -1; char key[PATH_MAX] = ""; char *buffer = NULL; GF_ASSERT (snap_dict); GF_ASSERT (dict); ret = dict_set_int32 (snap_dict, "sub-cmd", GF_SNAP_DELETE_TYPE_ITER); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save command " "type in snap dictionary"); goto out; } ret = snprintf (key, sizeof (key), "snapname%zu", index); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snapname"); goto out; } ret = dict_set_dynstr_with_alloc (snap_dict, "snapname", buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to save snapname"); goto out; } ret = dict_set_int32 (snap_dict, "type", GF_SNAP_OPTION_TYPE_DELETE); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to save command type"); goto out; } ret = dict_set_dynstr_with_alloc (snap_dict, "cmd-str", "snapshot delete"); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save command string as delete"); goto out; } out: return ret; } int cli_populate_req_dict_for_status (dict_t *snap_dict, dict_t *dict, int index) { int ret = -1; char key[PATH_MAX] = ""; char *buffer = NULL; GF_ASSERT (snap_dict); GF_ASSERT (dict); ret = dict_set_uint32 (snap_dict, "sub-cmd", GF_SNAP_STATUS_TYPE_ITER); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save command " "type in snap dict"); goto out; } ret = snprintf (key, sizeof (key), "status.snap%d.snapname", index); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not get snapname"); goto out; } ret = dict_set_str (snap_dict, "snapname", buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save snapname " "in snap dict"); goto out; } ret = dict_set_int32 (snap_dict, "type", GF_SNAP_OPTION_TYPE_STATUS); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save command type"); goto out; } ret = dict_set_dynstr_with_alloc (snap_dict, "cmd-str", "snapshot status"); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save command string as status"); goto out; } ret = dict_set_int32 (snap_dict, "hold_vol_locks", _gf_false); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Setting volume lock flag failed"); goto out; } out: return ret; } int cli_snapshot_status (dict_t *dict, gf_cli_rsp *rsp, call_frame_t *frame) { char key[PATH_MAX] = ""; int ret = -1; int status_cmd = -1; cli_local_t *local = NULL; GF_ASSERT (dict); GF_ASSERT (rsp); GF_ASSERT (frame); local = ((call_frame_t *) frame) -> local; if (!local) { gf_log ("cli", GF_LOG_ERROR, "frame->local is NULL"); goto out; } if (rsp->op_ret) { if (rsp->op_errstr) { ret = dict_set_dynstr_with_alloc (local->dict, "op_err_str", rsp->op_errstr); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set " "op_errstr in local dictionary"); goto out; } } ret = rsp->op_ret; goto out; } ret = dict_get_int32 (dict, "sub-cmd", &status_cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch status type"); goto out; } if ((status_cmd != GF_SNAP_STATUS_TYPE_SNAP) && (status_cmd != GF_SNAP_STATUS_TYPE_ITER)) { dict_copy (dict, local->dict); goto out; } ret = snprintf (key, sizeof (key), "status.snap0"); if (ret < 0) { goto out; } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_snapshot_status_single_snap (local, dict, key); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create " "xml output for snapshot status"); goto out; } } else { ret = cli_get_single_snap_status (dict, key); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch " "status of snap"); goto out; } } ret = 0; out: return ret; } int gf_cli_generate_snapshot_event (gf_cli_rsp *rsp, dict_t *dict, int32_t type, char *snap_name, char *volname, char *snap_uuid, char *clone_name) { int ret = -1; int config_command = 0; int32_t delete_cmd = -1; uint64_t hard_limit = 0; uint64_t soft_limit = 0; char *auto_delete = NULL; char *snap_activate = NULL; char msg[PATH_MAX] = {0, }; char option[PATH_MAX] = {0, }; GF_VALIDATE_OR_GOTO ("cli", dict, out); GF_VALIDATE_OR_GOTO ("cli", rsp, out); switch (type) { case GF_SNAP_OPTION_TYPE_CREATE: if (!snap_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto out; } if (!volname) { gf_log ("cli", GF_LOG_ERROR, "Failed to get volume name"); goto out; } if (rsp->op_ret != 0) { gf_event (EVENT_SNAPSHOT_CREATE_FAILED, "snapshot_name=%s;volume_name=%s;error=%s", snap_name, volname, rsp->op_errstr ? rsp->op_errstr : "Please check log file for details"); ret = 0; break; } if (!snap_uuid) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); goto out; } gf_event (EVENT_SNAPSHOT_CREATED, "snapshot_name=%s;" "volume_name=%s;snapshot_uuid=%s", snap_name, volname, snap_uuid); ret = 0; break; case GF_SNAP_OPTION_TYPE_ACTIVATE: if (!snap_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto out; } if (rsp->op_ret != 0) { gf_event (EVENT_SNAPSHOT_ACTIVATE_FAILED, "snapshot_name=%s;error=%s", snap_name, rsp->op_errstr ? rsp->op_errstr : "Please check log file for details"); ret = 0; break; } if (!snap_uuid) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); goto out; } gf_event (EVENT_SNAPSHOT_ACTIVATED, "snapshot_name=%s;" "snapshot_uuid=%s", snap_name, snap_uuid); ret = 0; break; case GF_SNAP_OPTION_TYPE_DEACTIVATE: if (!snap_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto out; } if (rsp->op_ret != 0) { gf_event (EVENT_SNAPSHOT_DEACTIVATE_FAILED, "snapshot_name=%s;error=%s", snap_name, rsp->op_errstr ? rsp->op_errstr : "Please check log file for details"); ret = 0; break; } if (!snap_uuid) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); goto out; } gf_event (EVENT_SNAPSHOT_DEACTIVATED, "snapshot_name=%s;" "snapshot_uuid=%s", snap_name, snap_uuid); ret = 0; break; case GF_SNAP_OPTION_TYPE_RESTORE: if (!snap_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto out; } if (rsp->op_ret != 0) { gf_event (EVENT_SNAPSHOT_RESTORE_FAILED, "snapshot_name=%s;error=%s", snap_name, rsp->op_errstr ? rsp->op_errstr : "Please check log file for details"); ret = 0; break; } if (!snap_uuid) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); goto out; } if (!volname) { gf_log ("cli", GF_LOG_ERROR, "Failed to get volname"); goto out; } gf_event (EVENT_SNAPSHOT_RESTORED, "snapshot_name=%s;" "snapshot_uuid=%s;volume_name=%s", snap_name, snap_uuid, volname); ret = 0; break; case GF_SNAP_OPTION_TYPE_DELETE: ret = dict_get_int32 (dict, "sub-cmd", &delete_cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not get sub-cmd"); goto out; } /* * Need not generate any event (success or failure) for delete * * all, as it will trigger individual delete for all snapshots * */ if (delete_cmd == GF_SNAP_DELETE_TYPE_ALL) { ret = 0; break; } if (!snap_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto out; } if (rsp->op_ret != 0) { gf_event (EVENT_SNAPSHOT_DELETE_FAILED, "snapshot_name=%s;error=%s", snap_name, rsp->op_errstr ? rsp->op_errstr : "Please check log file for details"); ret = 0; break; } if (!snap_uuid) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); goto out; } gf_event (EVENT_SNAPSHOT_DELETED, "snapshot_name=%s;" "snapshot_uuid=%s", snap_name, snap_uuid); ret = 0; break; case GF_SNAP_OPTION_TYPE_CLONE: if (!clone_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get clone name"); goto out; } if (!snap_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snapname name"); goto out; } if (rsp->op_ret != 0) { gf_event (EVENT_SNAPSHOT_CLONE_FAILED, "snapshot_name=%s;clone_name=%s;" "error=%s", snap_name, clone_name, rsp->op_errstr ? rsp->op_errstr : "Please check log file for details"); ret = 0; break; } if (!snap_uuid) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); goto out; } gf_event (EVENT_SNAPSHOT_CLONED, "snapshot_name=%s;" "clone_name=%s;clone_uuid=%s", snap_name, clone_name, snap_uuid); ret = 0; break; case GF_SNAP_OPTION_TYPE_CONFIG: if (rsp->op_ret != 0) { gf_event (EVENT_SNAPSHOT_CONFIG_UPDATE_FAILED, "error=%s", rsp->op_errstr ? rsp->op_errstr : "Please check log file for details"); ret = 0; break; } ret = dict_get_int32 (dict, "config-command", &config_command); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch config type"); goto out; } if (config_command == GF_SNAP_CONFIG_DISPLAY) { ret = 0; break; } /* These are optional parameters therefore ignore the error */ ret = dict_get_uint64 (dict, "snap-max-hard-limit", &hard_limit); ret = dict_get_uint64 (dict, "snap-max-soft-limit", &soft_limit); ret = dict_get_str (dict, "auto-delete", &auto_delete); ret = dict_get_str (dict, "snap-activate-on-create", &snap_activate); if (!hard_limit && !soft_limit && !auto_delete && !snap_activate) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "At least one option from " "snap-max-hard-limit, snap-max-soft-limit, " "auto-delete and snap-activate-on-create " "should be set"); goto out; } volname = NULL; ret = dict_get_str (dict, "volname", &volname); if (hard_limit || soft_limit) { snprintf (option, sizeof(option), "%s=%"PRIu64, hard_limit ? "hard_limit" : "soft_limit", hard_limit ? hard_limit:soft_limit); } else if (auto_delete || snap_activate) { snprintf (option, sizeof(option), "%s=%s", auto_delete ? "auto-delete" : "snap-activate", auto_delete ? auto_delete:snap_activate); } snprintf (msg, sizeof(msg), "config_type=%s;%s", volname?"volume_config":"system_config", option); gf_event (EVENT_SNAPSHOT_CONFIG_UPDATED, "%s", msg); ret = 0; break; default: gf_log ("cli", GF_LOG_WARNING, "Cannot generate event for unknown type."); ret = 0; goto out; } out: return ret; } /* * Fetch necessary data from dict at one place instead of * * repeating the same code again and again. * */ int gf_cli_snapshot_get_data_from_dict (dict_t *dict, char **snap_name, char **volname, char **snap_uuid, int8_t *soft_limit_flag, char **clone_name) { int ret = -1; GF_VALIDATE_OR_GOTO ("cli", dict, out); if (snap_name) ret = dict_get_str (dict, "snapname", snap_name); if (volname) ret = dict_get_str (dict, "volname1", volname); if (snap_uuid) ret = dict_get_str (dict, "snapuuid", snap_uuid); if (soft_limit_flag) ret = dict_get_int8 (dict, "soft-limit-reach", soft_limit_flag); if (clone_name) ret = dict_get_str (dict, "clonename", clone_name); ret = 0; out: return ret; } int gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { int ret = -1; gf_cli_rsp rsp = {0, }; dict_t *dict = NULL; char *snap_name = NULL; char *clone_name = NULL; int32_t type = 0; call_frame_t *frame = NULL; gf_boolean_t snap_driven = _gf_false; int8_t soft_limit_flag = -1; char *volname = NULL; char *snap_uuid = NULL; GF_ASSERT (myframe); if (req->rpc_status == -1) { goto out; } frame = myframe; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (frame->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) goto out; ret = dict_get_int32 (dict, "type", &type); if (ret) { gf_log (frame->this->name, GF_LOG_ERROR, "failed to get type"); goto out; } ret = gf_cli_snapshot_get_data_from_dict (dict, &snap_name, &volname, &snap_uuid, &soft_limit_flag, &clone_name); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to fetch data from dict."); goto out; } #if (USE_EVENTS) ret = gf_cli_generate_snapshot_event (&rsp, dict, type, snap_name, volname, snap_uuid, clone_name); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to generate snapshot event"); goto out; } #endif /* Snapshot status and delete command is handled separately */ if (global_state->mode & GLUSTER_MODE_XML && GF_SNAP_OPTION_TYPE_STATUS != type && GF_SNAP_OPTION_TYPE_DELETE != type) { ret = cli_xml_output_snapshot (type, dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); } goto out; } switch (type) { case GF_SNAP_OPTION_TYPE_CREATE: if (rsp.op_ret) { cli_err("snapshot create: failed: %s", rsp.op_errstr ? rsp.op_errstr : "Please check log file for details"); ret = rsp.op_ret; goto out; } if (!snap_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto out; } if (!volname) { gf_log ("cli", GF_LOG_ERROR, "Failed to get volume name"); goto out; } cli_out ("snapshot create: success: Snap %s created " "successfully", snap_name); if (soft_limit_flag == 1) { cli_out ("Warning: Soft-limit of volume (%s) is " "reached. Snapshot creation is not possible " "once hard-limit is reached.", volname); } ret = 0; break; case GF_SNAP_OPTION_TYPE_CLONE: if (rsp.op_ret) { cli_err("snapshot clone: failed: %s", rsp.op_errstr ? rsp.op_errstr : "Please check log file for details"); ret = rsp.op_ret; goto out; } if (!clone_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get clone name"); goto out; } if (!snap_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snapname name"); goto out; } cli_out ("snapshot clone: success: Clone %s created " "successfully", clone_name); ret = 0; break; case GF_SNAP_OPTION_TYPE_RESTORE: if (rsp.op_ret) { cli_err("snapshot restore: failed: %s", rsp.op_errstr ? rsp.op_errstr : "Please check log file for details"); ret = rsp.op_ret; goto out; } if (!snap_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto out; } cli_out ("Snapshot restore: %s: Snap restored " "successfully", snap_name); ret = 0; break; case GF_SNAP_OPTION_TYPE_ACTIVATE: if (rsp.op_ret) { cli_err("snapshot activate: failed: %s", rsp.op_errstr ? rsp.op_errstr : "Please check log file for details"); ret = rsp.op_ret; goto out; } if (!snap_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto out; } cli_out ("Snapshot activate: %s: Snap activated " "successfully", snap_name); ret = 0; break; case GF_SNAP_OPTION_TYPE_DEACTIVATE: if (rsp.op_ret) { cli_err("snapshot deactivate: failed: %s", rsp.op_errstr ? rsp.op_errstr : "Please check log file for details"); ret = rsp.op_ret; goto out; } if (!snap_name) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto out; } cli_out ("Snapshot deactivate: %s: Snap deactivated " "successfully", snap_name); ret = 0; break; case GF_SNAP_OPTION_TYPE_INFO: if (rsp.op_ret) { cli_err ("Snapshot info : failed: %s", rsp.op_errstr ? rsp.op_errstr : "Please check log file for details"); ret = rsp.op_ret; goto out; } snap_driven = dict_get_str_boolean (dict, "snap-driven", _gf_false); if (snap_driven == _gf_true) { ret = cli_call_snapshot_info (dict, snap_driven); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Snapshot info failed"); goto out; } } else if (snap_driven == _gf_false) { ret = cli_get_snaps_in_volume (dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Snapshot info failed"); goto out; } } break; case GF_SNAP_OPTION_TYPE_CONFIG: ret = cli_snapshot_config_display (dict, &rsp); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to display " "snapshot config output."); goto out; } break; case GF_SNAP_OPTION_TYPE_LIST: if (rsp.op_ret) { cli_err ("Snapshot list : failed: %s", rsp.op_errstr ? rsp.op_errstr : "Please check log file for details"); ret = rsp.op_ret; goto out; } ret = cli_snapshot_list (dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to display " "snapshot list"); goto out; } break; case GF_SNAP_OPTION_TYPE_DELETE: ret = cli_snapshot_remove_reply (&rsp, dict, frame); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to delete snap"); goto out; } break; case GF_SNAP_OPTION_TYPE_STATUS: ret = cli_snapshot_status (dict, &rsp, frame); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to display " "snapshot status output."); goto out; } break; default: cli_err ("Unknown command executed"); ret = -1; goto out; } out: if (dict) dict_unref (dict); cli_cmd_broadcast_response (ret); free (rsp.dict.dict_val); free (rsp.op_errstr); return ret; } int32_t gf_cli_snapshot_for_delete (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int32_t ret = -1; int32_t cmd = -1; cli_local_t *local = NULL; dict_t *snap_dict = NULL; int32_t snapcount = 0; int i = 0; char question[PATH_MAX] = ""; char *volname = NULL; gf_answer_t answer = GF_ANSWER_NO; GF_VALIDATE_OR_GOTO ("cli", frame, out); GF_VALIDATE_OR_GOTO ("cli", frame->local, out); GF_VALIDATE_OR_GOTO ("cli", this, out); GF_VALIDATE_OR_GOTO ("cli", data, out); local = frame->local; ret = dict_get_int32 (local->dict, "sub-cmd", &cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get " "sub-cmd"); goto out; } /* No need multiple RPCs for individual snapshot delete*/ if (cmd == GF_SNAP_DELETE_TYPE_SNAP) { ret = 0; goto out; } ret = dict_get_int32 (local->dict, "snapcount", &snapcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not get " "snapcount"); goto out; } if (global_state->mode & GLUSTER_MODE_XML) { #ifdef HAVE_LIB_XML ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"snapCount", "%d", snapcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to write " "xml element \"snapCount\""); goto out; } #endif /* HAVE_LIB_XML */ } else if (snapcount == 0) { cli_out ("No snapshots present"); goto out; } if (cmd == GF_SNAP_DELETE_TYPE_ALL) { snprintf (question, sizeof (question), "System contains %d " "snapshot(s).\nDo you still " "want to continue and delete them? ", snapcount); } else { ret = dict_get_str (local->dict, "volname", &volname); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to fetch " "volname from local dictionary"); goto out; } snprintf (question, sizeof (question), "Volume (%s) contains " "%d snapshot(s).\nDo you still want to " "continue and delete them? ", volname, snapcount); } answer = cli_cmd_get_confirmation (global_state, question); if (GF_ANSWER_NO == answer) { ret = 0; gf_log ("cli", GF_LOG_DEBUG, "User cancelled " "snapshot delete operation for snap delete"); goto out; } for (i = 1 ; i <= snapcount ; i++) { ret = -1; snap_dict = dict_new(); if (!snap_dict) goto out; ret = cli_populate_req_dict_for_delete (snap_dict, local->dict, i); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not " "populate snap request dictionary"); goto out; } ret = cli_to_glusterd (&req, frame, gf_cli_snapshot_cbk, (xdrproc_t) xdr_gf_cli_req, snap_dict, GLUSTER_CLI_SNAP, this, cli_rpc_prog, NULL); if (ret) { /* Fail the operation if deleting one of the * snapshots is failed */ gf_log ("cli", GF_LOG_ERROR, "cli_to_glusterd " "for snapshot delete failed"); goto out; } dict_unref (snap_dict); snap_dict = NULL; } out: if (snap_dict) dict_unref (snap_dict); return ret; } int32_t gf_cli_snapshot_for_status (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = -1; int32_t cmd = -1; cli_local_t *local = NULL; dict_t *snap_dict = NULL; int snapcount = 0; int i = 0; GF_VALIDATE_OR_GOTO ("cli", frame, out); GF_VALIDATE_OR_GOTO ("cli", frame->local, out); GF_VALIDATE_OR_GOTO ("cli", this, out); GF_VALIDATE_OR_GOTO ("cli", data, out); local = frame->local; ret = dict_get_int32 (local->dict, "sub-cmd", &cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get sub-cmd"); goto out; } /* Snapshot status of single snap (i.e. GF_SNAP_STATUS_TYPE_SNAP) * is already handled. Therefore we can return from here. * If want to get status of all snaps in the system or volume then * we should get them one by one.*/ if ((cmd == GF_SNAP_STATUS_TYPE_SNAP) || (cmd == GF_SNAP_STATUS_TYPE_ITER)) { ret = 0; goto out; } ret = dict_get_int32 (local->dict, "status.snapcount", &snapcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not get snapcount"); goto out; } if (snapcount == 0 && !(global_state->mode & GLUSTER_MODE_XML)) { cli_out ("No snapshots present"); } for (i = 0 ; i < snapcount; i++) { ret = -1; snap_dict = dict_new(); if (!snap_dict) goto out; ret = cli_populate_req_dict_for_status (snap_dict, local->dict, i); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not " "populate snap request dictionary"); goto out; } ret = cli_to_glusterd (&req, frame, gf_cli_snapshot_cbk, (xdrproc_t) xdr_gf_cli_req, snap_dict, GLUSTER_CLI_SNAP, this, cli_rpc_prog, NULL); /* Ignore the return value and error for snapshot * status of type "ALL" or "VOL" * * Scenario : There might be case where status command * and delete command might be issued at the same time. * In that case when status tried to fetch detail of * snap which has been deleted by concurrent command, * then it will show snapshot not present. Which will * not be appropriate. */ dict_unref (snap_dict); snap_dict = NULL; } ret = 0; out: if (snap_dict) dict_unref (snap_dict); return ret; } int32_t gf_cli_snapshot (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; dict_t *options = NULL; int ret = -1; int tmp_ret = -1; cli_local_t *local = NULL; char *err_str = NULL; int type = -1; if (!frame || !this || !data) goto out; if (!frame->local) goto out; local = frame->local; options = data; ret = dict_get_int32 (local->dict, "type", &type); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_snapshot_begin_composite_op (local); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to begin " "snapshot xml composite op"); goto out; } } ret = cli_to_glusterd (&req, frame, gf_cli_snapshot_cbk, (xdrproc_t) xdr_gf_cli_req, options, GLUSTER_CLI_SNAP, this, cli_rpc_prog, NULL); if (ret) { gf_log ("cli", GF_LOG_ERROR, "cli_to_glusterd for " "snapshot failed"); goto xmlend; } if (GF_SNAP_OPTION_TYPE_STATUS == type) { ret = gf_cli_snapshot_for_status (frame, this, data); if (ret) { gf_log ("cli", GF_LOG_ERROR, "cli to glusterd " "for snapshot status command failed"); } goto xmlend; } if (GF_SNAP_OPTION_TYPE_DELETE == type) { ret = gf_cli_snapshot_for_delete (frame, this, data); if (ret) { gf_log ("cli", GF_LOG_ERROR, "cli to glusterd " "for snapshot delete command failed"); } goto xmlend; } ret = 0; xmlend: if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_snapshot_end_composite_op (local); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to end " "snapshot xml composite op"); goto out; } } out: if (ret && local && GF_SNAP_OPTION_TYPE_STATUS == type) { tmp_ret = dict_get_str (local->dict, "op_err_str", &err_str); if (tmp_ret || !err_str) { cli_err ("Snapshot Status : failed: %s", "Please " "check log file for details"); } else { cli_err ("Snapshot Status : failed: %s", err_str); dict_del (local->dict, "op_err_str"); } } gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); if (global_state->mode & GLUSTER_MODE_XML) { /* XML mode handles its own error */ ret = 0; } return ret; } int32_t gf_cli_barrier_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; GF_ASSERT (myframe); if (-1 == req->rpc_status) goto out; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received response to barrier"); if (rsp.op_ret) { if (rsp.op_errstr && (strlen (rsp.op_errstr) > 1)) { cli_err ("volume barrier: command unsuccessful : %s", rsp.op_errstr); } else { cli_err ("volume barrier: command unsuccessful"); } } else { cli_out ("volume barrier: command successful"); } ret = rsp.op_ret; out: if (dict) dict_unref (dict); free (rsp.op_errstr); free (rsp.dict.dict_val); cli_cmd_broadcast_response (ret); return ret; } int gf_cli_barrier_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; dict_t *options = NULL; int ret = -1; if (!frame || !this || !data) goto out; options = data; ret = cli_to_glusterd (&req, frame, gf_cli_barrier_volume_cbk, (xdrproc_t) xdr_gf_cli_req, options, GLUSTER_CLI_BARRIER_VOLUME, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli_get_vol_opt_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; char *key = NULL; char *value = NULL; char msg[1024] = {0,}; int i = 0; char dict_key[50] = {0,}; GF_ASSERT (myframe); if (-1 == req->rpc_status) goto out; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received response to get volume option"); if (rsp.op_ret) { if (strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "volume get option: " "failed: %s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "volume get option: " "failed"); if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volGetopts", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); } } else { cli_err ("%s", msg); } ret = rsp.op_ret; goto out_nolog; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed rsp_dict unserialization"); goto out; } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_getopts (dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) { gf_log ("cli", GF_LOG_ERROR, "xml output generation " "failed"); ret = 0; } goto out; } ret = dict_get_str (dict, "warning", &value); if (!ret) { cli_out ("%s", value); } ret = dict_get_int32 (dict, "count", &count); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to retrieve count " "from the dictionary"); goto out; } if (count <= 0) { gf_log ("cli", GF_LOG_ERROR, "Value of count :%d is " "invalid", count); ret = -1; goto out; } cli_out ("%-40s%-40s", "Option", "Value"); cli_out ("%-40s%-40s", "------", "-----"); for (i=1; i<=count; i++) { snprintf (dict_key, sizeof dict_key, "key%d", i); ret = dict_get_str (dict, dict_key, &key); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to" " retrieve %s from the " "dictionary", dict_key); goto out; } snprintf (dict_key, sizeof dict_key, "value%d", i); ret = dict_get_str (dict, dict_key, &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to " "retrieve key value for %s from" "the dictionary", dict_key); goto out; } cli_out ("%-40s%-40s", key, value); } out: if (ret) { cli_out ("volume get option failed. Check the cli/glusterd log " "file for more details"); } out_nolog: if (dict) dict_unref (dict); free (rsp.op_errstr); free (rsp.dict.dict_val); cli_cmd_broadcast_response (ret); return ret; } int gf_cli_get_vol_opt (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; dict_t *options = NULL; int ret = -1; if (!frame || !this || !data) goto out; options = data; ret = cli_to_glusterd (&req, frame, gf_cli_get_vol_opt_cbk, (xdrproc_t)xdr_gf_cli_req, options, GLUSTER_CLI_GET_VOL_OPT, this, cli_rpc_prog, NULL); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } int cli_to_glusterd (gf_cli_req *req, call_frame_t *frame, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc, dict_t *dict, int procnum, xlator_t *this, rpc_clnt_prog_t *prog, struct iobref *iobref) { int ret = 0; size_t len = 0; char *cmd = NULL; int i = 0; const char **words = NULL; cli_local_t *local = NULL; if (!this || !frame || !dict) { ret = -1; goto out; } if (!frame->local) { ret = -1; goto out; } local = frame->local; if (!local->words) { ret = -1; goto out; } words = local->words; while (words[i]) len += strlen (words[i++]) + 1; cmd = GF_CALLOC (1, len, gf_common_mt_char); if (!cmd) { ret = -1; goto out; } for (i = 0; words[i]; i++) { strncat (cmd, words[i], strlen (words[i])); if (words[i+1] != NULL) strncat (cmd, " ", strlen (" ")); } cmd [len - 1] = '\0'; ret = dict_set_dynstr (dict, "cmd-str", cmd); if (ret) goto out; ret = dict_allocate_and_serialize (dict, &(req->dict).dict_val, &(req->dict).dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_DEBUG, "failed to get serialized length of dict"); goto out; } ret = cli_cmd_submit (NULL, req, frame, prog, procnum, iobref, this, cbkfn, (xdrproc_t) xdrproc); out: return ret; } int gf_cli_print_bitrot_scrub_status (dict_t *dict) { int i = 1; int j = 0; int ret = -1; int count = 0; char key[256] = {0,}; char *volname = NULL; char *node_name = NULL; char *scrub_freq = NULL; char *state_scrub = NULL; char *scrub_impact = NULL; char *bad_file_str = NULL; char *scrub_log_file = NULL; char *bitrot_log_file = NULL; uint64_t scrub_files = 0; uint64_t unsigned_files = 0; uint64_t scrub_time = 0; uint64_t days = 0; uint64_t hours = 0; uint64_t minutes = 0; uint64_t seconds = 0; char *last_scrub = NULL; uint64_t error_count = 0; int8_t scrub_running = 0; char *scrub_state_op = NULL; ret = dict_get_str (dict, "volname", &volname); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get volume name"); ret = dict_get_str (dict, "features.scrub", &state_scrub); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get scrub state value"); ret = dict_get_str (dict, "features.scrub-throttle", &scrub_impact); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get scrub impact " "value"); ret = dict_get_str (dict, "features.scrub-freq", &scrub_freq); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get scrub -freq value"); ret = dict_get_str (dict, "bitrot_log_file", &bitrot_log_file); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get bitrot log file " "location"); ret = dict_get_str (dict, "scrub_log_file", &scrub_log_file); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get scrubber log file " "location"); ret = dict_get_int32 (dict, "count", &count); if (ret) { gf_log ("cli", GF_LOG_ERROR, "count not get count value from" " dictionary"); goto out; } for (i = 1; i <= count; i++) { memset (key, 0, 256); snprintf (key, 256, "scrub-running-%d", i); ret = dict_get_int8 (dict, key, &scrub_running); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get scrubbed " "files"); if (scrub_running) break; } if (scrub_running) gf_asprintf (&scrub_state_op, "%s (In Progress)", state_scrub); else gf_asprintf (&scrub_state_op, "%s (Idle)", state_scrub); cli_out ("\n%s: %s\n", "Volume name ", volname); cli_out ("%s: %s\n", "State of scrub", scrub_state_op); cli_out ("%s: %s\n", "Scrub impact", scrub_impact); cli_out ("%s: %s\n", "Scrub frequency", scrub_freq); cli_out ("%s: %s\n", "Bitrot error log location", bitrot_log_file); cli_out ("%s: %s\n", "Scrubber error log location", scrub_log_file); for (i = 1; i <= count; i++) { /* Reset the variables to prevent carryover of values */ node_name = NULL; last_scrub = NULL; scrub_time = 0; days = 0; hours = 0; minutes = 0; seconds = 0; error_count = 0; scrub_files = 0; unsigned_files = 0; memset (key, 0, 256); snprintf (key, 256, "node-name-%d", i); ret = dict_get_str (dict, key, &node_name); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get node-name"); memset (key, 0, 256); snprintf (key, 256, "scrubbed-files-%d", i); ret = dict_get_uint64 (dict, key, &scrub_files); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get scrubbed " "files"); memset (key, 0, 256); snprintf (key, 256, "unsigned-files-%d", i); ret = dict_get_uint64 (dict, key, &unsigned_files); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get unsigned " "files"); memset (key, 0, 256); snprintf (key, 256, "scrub-duration-%d", i); ret = dict_get_uint64 (dict, key, &scrub_time); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get last scrub " "duration"); memset (key, 0, 256); snprintf (key, 256, "last-scrub-time-%d", i); ret = dict_get_str (dict, key, &last_scrub); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get last scrub" " time"); memset (key, 0, 256); snprintf (key, 256, "error-count-%d", i); ret = dict_get_uint64 (dict, key, &error_count); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get error " "count"); cli_out ("\n%s\n", "==========================================" "==============="); cli_out ("%s: %s\n", "Node", node_name); cli_out ("%s: %"PRIu64 "\n", "Number of Scrubbed files", scrub_files); cli_out ("%s: %"PRIu64 "\n", "Number of Skipped files", unsigned_files); if ((!last_scrub) || !strcmp (last_scrub, "")) cli_out ("%s: %s\n", "Last completed scrub time", "Scrubber pending to complete."); else cli_out ("%s: %s\n", "Last completed scrub time", last_scrub); /* Printing last scrub duration time in human readable form*/ seconds = scrub_time%60; minutes = (scrub_time/60)%60; hours = (scrub_time/3600)%24; days = scrub_time/86400; cli_out ("%s: %"PRIu64 ":%"PRIu64 ":%"PRIu64 ":%"PRIu64 "\n", "Duration of last scrub (D:M:H:M:S)", days, hours, minutes, seconds); cli_out ("%s: %"PRIu64 "\n", "Error count", error_count); if (error_count) { cli_out ("%s:\n", "Corrupted object's [GFID]"); /* Printing list of bad file's (Corrupted object's)*/ for (j = 0; j < error_count; j++) { memset (key, 0, 256); snprintf (key, 256, "quarantine-%d-%d", j, i); ret = dict_get_str (dict, key, &bad_file_str); if (!ret) { cli_out ("%s\n", bad_file_str); } } } } cli_out ("%s\n", "==========================================" "==============="); out: GF_FREE (scrub_state_op); return 0; } int gf_cli_bitrot_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { int ret = -1; int type = 0; gf_cli_rsp rsp = {0, }; dict_t *dict = NULL; GF_ASSERT (myframe); if (req->rpc_status == -1) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, "Failed to decode xdr response"); goto out; } if (rsp.op_ret) { ret = -1; if (global_state->mode & GLUSTER_MODE_XML) goto xml_output; if (strcmp (rsp.op_errstr, "")) cli_err ("Bitrot command failed : %s", rsp.op_errstr); else cli_err ("Bitrot command : failed"); goto out; } if (rsp.dict.dict_len) { /* Unserialize the dictionary */ dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "failed to unserialize " "req-buffer to dictionary"); goto out; } } gf_log ("cli", GF_LOG_DEBUG, "Received resp to bit rot command"); ret = dict_get_int32 (dict, "type", &type); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get command type"); goto out; } if ((type == GF_BITROT_CMD_SCRUB_STATUS) && !(global_state->mode & GLUSTER_MODE_XML)) { ret = gf_cli_print_bitrot_scrub_status (dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to print bitrot " "scrub status"); } goto out; } xml_output: if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_profile (dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } if (!rsp.op_ret) cli_out ("volume bitrot: success"); ret = rsp.op_ret; out: if (dict) dict_unref (dict); free (rsp.dict.dict_val); free (rsp.op_errstr); cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli_bitrot (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = { {0,} }; dict_t *options = NULL; int ret = -1; if (!frame || !this || !data) goto out; options = data; ret = cli_to_glusterd (&req, frame, gf_cli_bitrot_cbk, (xdrproc_t) xdr_gf_cli_req, options, GLUSTER_CLI_BITROT, this, cli_rpc_prog, NULL); if (ret) { gf_log ("cli", GF_LOG_ERROR, "cli_to_glusterd for " "bitrot failed"); goto out; } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); GF_FREE (req.dict.dict_val); return ret; } struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = { [GLUSTER_CLI_NULL] = {"NULL", NULL }, [GLUSTER_CLI_PROBE] = {"PROBE_QUERY", gf_cli_probe}, [GLUSTER_CLI_DEPROBE] = {"DEPROBE_QUERY", gf_cli_deprobe}, [GLUSTER_CLI_LIST_FRIENDS] = {"LIST_FRIENDS", gf_cli_list_friends}, [GLUSTER_CLI_UUID_RESET] = {"UUID_RESET", gf_cli3_1_uuid_reset}, [GLUSTER_CLI_UUID_GET] = {"UUID_GET", gf_cli3_1_uuid_get}, [GLUSTER_CLI_CREATE_VOLUME] = {"CREATE_VOLUME", gf_cli_create_volume}, [GLUSTER_CLI_DELETE_VOLUME] = {"DELETE_VOLUME", gf_cli_delete_volume}, [GLUSTER_CLI_START_VOLUME] = {"START_VOLUME", gf_cli_start_volume}, [GLUSTER_CLI_STOP_VOLUME] = {"STOP_VOLUME", gf_cli_stop_volume}, [GLUSTER_CLI_RENAME_VOLUME] = {"RENAME_VOLUME", gf_cli_rename_volume}, [GLUSTER_CLI_DEFRAG_VOLUME] = {"DEFRAG_VOLUME", gf_cli_defrag_volume}, [GLUSTER_CLI_GET_VOLUME] = {"GET_VOLUME", gf_cli_get_volume}, [GLUSTER_CLI_GET_NEXT_VOLUME] = {"GET_NEXT_VOLUME", gf_cli_get_next_volume}, [GLUSTER_CLI_SET_VOLUME] = {"SET_VOLUME", gf_cli_set_volume}, [GLUSTER_CLI_ADD_BRICK] = {"ADD_BRICK", gf_cli_add_brick}, [GLUSTER_CLI_REMOVE_BRICK] = {"REMOVE_BRICK", gf_cli_remove_brick}, [GLUSTER_CLI_REPLACE_BRICK] = {"REPLACE_BRICK", gf_cli_replace_brick}, [GLUSTER_CLI_LOG_ROTATE] = {"LOG ROTATE", gf_cli_log_rotate}, [GLUSTER_CLI_GETSPEC] = {"GETSPEC", gf_cli_getspec}, [GLUSTER_CLI_PMAP_PORTBYBRICK] = {"PMAP PORTBYBRICK", gf_cli_pmap_b2p}, [GLUSTER_CLI_SYNC_VOLUME] = {"SYNC_VOLUME", gf_cli_sync_volume}, [GLUSTER_CLI_RESET_VOLUME] = {"RESET_VOLUME", gf_cli_reset_volume}, [GLUSTER_CLI_FSM_LOG] = {"FSM_LOG", gf_cli_fsm_log}, [GLUSTER_CLI_GSYNC_SET] = {"GSYNC_SET", gf_cli_gsync_set}, [GLUSTER_CLI_PROFILE_VOLUME] = {"PROFILE_VOLUME", gf_cli_profile_volume}, [GLUSTER_CLI_QUOTA] = {"QUOTA", gf_cli_quota}, [GLUSTER_CLI_TOP_VOLUME] = {"TOP_VOLUME", gf_cli_top_volume}, [GLUSTER_CLI_GETWD] = {"GETWD", gf_cli_getwd}, [GLUSTER_CLI_STATUS_VOLUME] = {"STATUS_VOLUME", gf_cli_status_volume}, [GLUSTER_CLI_STATUS_ALL] = {"STATUS_ALL", gf_cli_status_volume_all}, [GLUSTER_CLI_MOUNT] = {"MOUNT", gf_cli_mount}, [GLUSTER_CLI_UMOUNT] = {"UMOUNT", gf_cli_umount}, [GLUSTER_CLI_HEAL_VOLUME] = {"HEAL_VOLUME", gf_cli_heal_volume}, [GLUSTER_CLI_STATEDUMP_VOLUME] = {"STATEDUMP_VOLUME", gf_cli_statedump_volume}, [GLUSTER_CLI_LIST_VOLUME] = {"LIST_VOLUME", gf_cli_list_volume}, [GLUSTER_CLI_CLRLOCKS_VOLUME] = {"CLEARLOCKS_VOLUME", gf_cli_clearlocks_volume}, [GLUSTER_CLI_COPY_FILE] = {"COPY_FILE", gf_cli_copy_file}, [GLUSTER_CLI_SYS_EXEC] = {"SYS_EXEC", gf_cli_sys_exec}, [GLUSTER_CLI_SNAP] = {"SNAP", gf_cli_snapshot}, [GLUSTER_CLI_BARRIER_VOLUME] = {"BARRIER VOLUME", gf_cli_barrier_volume}, [GLUSTER_CLI_GET_VOL_OPT] = {"GET_VOL_OPT", gf_cli_get_vol_opt}, [GLUSTER_CLI_BITROT] = {"BITROT", gf_cli_bitrot}, [GLUSTER_CLI_ATTACH_TIER] = {"ATTACH_TIER", gf_cli_attach_tier}, [GLUSTER_CLI_TIER] = {"TIER", gf_cli_tier}, [GLUSTER_CLI_GET_STATE] = {"GET_STATE", gf_cli_get_state}, [GLUSTER_CLI_RESET_BRICK] = {"RESET_BRICK", gf_cli_reset_brick}, [GLUSTER_CLI_REMOVE_TIER_BRICK] = {"DETACH_TIER", gf_cli_remove_tier_brick}, [GLUSTER_CLI_ADD_TIER_BRICK] = {"ADD_TIER_BRICK", gf_cli_add_tier_brick} }; struct rpc_clnt_program cli_prog = { .progname = "Gluster CLI", .prognum = GLUSTER_CLI_PROGRAM, .progver = GLUSTER_CLI_VERSION, .numproc = GLUSTER_CLI_MAXVALUE, .proctable = gluster_cli_actors, }; struct rpc_clnt_procedure cli_quotad_procs[GF_AGGREGATOR_MAXVALUE] = { [GF_AGGREGATOR_NULL] = {"NULL", NULL}, [GF_AGGREGATOR_LOOKUP] = {"LOOKUP", NULL}, [GF_AGGREGATOR_GETLIMIT] = {"GETLIMIT", cli_quotad_getlimit}, }; struct rpc_clnt_program cli_quotad_clnt = { .progname = "CLI Quotad client", .prognum = GLUSTER_AGGREGATOR_PROGRAM, .progver = GLUSTER_AGGREGATOR_VERSION, .numproc = GF_AGGREGATOR_MAXVALUE, .proctable = cli_quotad_procs, }; glusterfs-3.13.2/cli/src/PaxHeaders.5796/input.c0000644000000000000000000000013113230626775017420 xustar000000000000000030 mtime=1516449277.183371926 30 atime=1516449277.183371926 29 ctime=1516449329.34649292 glusterfs-3.13.2/cli/src/input.c0000664000175100017510000000427713230626775017674 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2010-2012 Red Hat, Inc. This file is part of GlusterFS. 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 #include #include "cli.h" #include "cli-mem-types.h" #define CMDBUFSIZ 1024 void * cli_batch (void *d) { struct cli_state *state = NULL; int ret = 0; state = d; ret = cli_cmd_process (state, state->argc, state->argv); gf_log ("", GF_LOG_INFO, "Exiting with: %d", ret); exit (-ret); return NULL; } void * cli_input (void *d) { struct cli_state *state = NULL; int ret = 0; char cmdbuf[CMDBUFSIZ]; char *cmd = NULL; size_t len = 0; state = d; for (;;) { printf ("%s", state->prompt); cmd = fgets (cmdbuf, CMDBUFSIZ, stdin); if (!cmd) break; len = strlen(cmd); if (len > 0 && cmd[len - 1] == '\n') //strip trailing \n cmd[len - 1] = '\0'; ret = cli_cmd_process_line (state, cmd); if (ret != 0 && state->mode & GLUSTER_MODE_ERR_FATAL) break; } exit (-ret); return NULL; } int cli_input_init (struct cli_state *state) { int ret = 0; if (state->argc) { ret = pthread_create (&state->input, NULL, cli_batch, state); return ret; } if (isatty (STDIN_FILENO)) { state->prompt = "gluster> "; cli_rl_enable (state); } else { state->prompt = ""; state->mode |= GLUSTER_MODE_SCRIPT | GLUSTER_MODE_ERR_FATAL; } if (!state->rl_enabled) ret = pthread_create (&state->input, NULL, cli_input, state); return ret; } glusterfs-3.13.2/cli/src/PaxHeaders.5796/Makefile.am0000644000000000000000000000013113230626775020151 xustar000000000000000030 mtime=1516449277.173371903 30 atime=1516449284.116388012 29 ctime=1516449329.33349289 glusterfs-3.13.2/cli/src/Makefile.am0000664000175100017510000000217413230626775020417 0ustar00jenkinsjenkins00000000000000sbin_PROGRAMS = gluster gluster_SOURCES = cli.c registry.c input.c cli-cmd.c cli-rl.c cli-cmd-global.c \ cli-cmd-volume.c cli-cmd-peer.c cli-rpc-ops.c cli-cmd-parser.c\ cli-cmd-system.c cli-cmd-misc.c cli-xml-output.c cli-quotad-client.c cli-cmd-snapshot.c gluster_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la $(GF_LDADD) \ $(RLLIBS) $(top_builddir)/rpc/xdr/src/libgfxdr.la \ $(top_builddir)/rpc/rpc-lib/src/libgfrpc.la \ $(XML_LIBS) gluster_LDFLAGS = $(GF_LDFLAGS) noinst_HEADERS = cli.h cli-mem-types.h cli-cmd.h cli-quotad-client.h AM_CPPFLAGS = $(GF_CPPFLAGS) \ -I$(top_srcdir)/libglusterfs/src -I$(top_srcdir)/rpc/rpc-lib/src\ -I$(top_srcdir)/rpc/xdr/src\ -I$(top_builddir)/rpc/xdr/src\ -DDATADIR=\"$(localstatedir)\" \ -DCONFDIR=\"$(sysconfdir)/glusterfs\" \ -DGSYNCD_PREFIX=\"$(GLUSTERFS_LIBEXECDIR)\"\ -DSYNCDAEMON_COMPILE=$(SYNCDAEMON_COMPILE) -DSBIN_DIR=\"$(sbindir)\"\ $(XML_CPPFLAGS) AM_CFLAGS = -Wall $(GF_CFLAGS) CLEANFILES = $(top_builddir)/libglusterfs/src/libglusterfs.la: $(MAKE) -C $(top_builddir)/libglusterfs/src/ all install-data-hook: $(mkdir_p) $(DESTDIR)$(localstatedir)/run/gluster glusterfs-3.13.2/cli/src/PaxHeaders.5796/cli-cmd-parser.c0000644000000000000000000000013113230626775021063 xustar000000000000000030 mtime=1516449277.175371908 30 atime=1516449277.173371903 29 ctime=1516449329.35949295 glusterfs-3.13.2/cli/src/cli-cmd-parser.c0000664000175100017510000061127713230626775021343 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2010-2013 Red Hat, Inc. This file is part of GlusterFS. 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 #include #include #include #include "cli.h" #include "cli-cmd.h" #include "cli-mem-types.h" #include "dict.h" #include "protocol-common.h" #include "cli1-xdr.h" #define MAX_SNAP_DESCRIPTION_LEN 1024 struct snap_config_opt_vals_ snap_confopt_vals[] = { {.op_name = "snap-max-hard-limit", .question = "Changing snapshot-max-hard-limit " "will limit the creation of new snapshots " "if they exceed the new limit.\n" "Do you want to continue?" }, {.op_name = "snap-max-soft-limit", .question = "If Auto-delete is enabled, snap-max-soft-limit will" " trigger deletion of oldest snapshot, on the " "creation of new snapshot, when the " "snap-max-soft-limit is reached.\n" "Do you want to change the snap-max-soft-limit?" }, {.op_name = "both", .question = "Changing snapshot-max-hard-limit " "will limit the creation of new snapshots " "if they exceed the new snapshot-max-hard-limit.\n" "If Auto-delete is enabled, snap-max-soft-limit will" " trigger deletion of oldest snapshot, on the " "creation of new snapshot, when the " "snap-max-soft-limit is reached.\n" "Do you want to continue?" }, {.op_name = NULL, } }; enum cli_snap_config_set_types { GF_SNAP_CONFIG_SET_HARD = 0, GF_SNAP_CONFIG_SET_SOFT = 1, GF_SNAP_CONFIG_SET_BOTH = 2, }; typedef enum cli_snap_config_set_types cli_snap_config_set_types; int cli_cmd_validate_volume (char *volname); static const char * id_sel (void *wcon) { return (const char *)wcon; } static char * str_getunamb (const char *tok, char **opwords) { return (char *)cli_getunamb (tok, (void **)opwords, id_sel); } int32_t cli_cmd_bricks_parse (const char **words, int wordcount, int brick_index, char **bricks, int *brick_count) { int ret = 0; char *tmp_list = NULL; char brick_list[120000] = {0,}; char *space = " "; char *delimiter = NULL; char *host_name = NULL; char *free_list_ptr = NULL; char *tmpptr = NULL; int j = 0; int brick_list_len = 0; char *tmp_host = NULL; GF_ASSERT (words); GF_ASSERT (wordcount); GF_ASSERT (bricks); GF_ASSERT (brick_index > 0); GF_ASSERT (brick_index < wordcount); strncpy (brick_list, space, strlen (space)); brick_list_len++; while (brick_index < wordcount) { if (validate_brick_name ((char *)words[brick_index])) { cli_err ("Wrong brick type: %s, use :" "", words[brick_index]); ret = -1; goto out; } else { delimiter = strrchr (words[brick_index], ':'); ret = gf_canonicalize_path (delimiter + 1); if (ret) goto out; } if ((brick_list_len + strlen (words[brick_index]) + 1) > sizeof (brick_list)) { cli_err ("Total brick list is larger than a request. " "Can take (brick_count %d)", *brick_count); ret = -1; goto out; } tmp_host = gf_strdup ((char *)words[brick_index]); if (!tmp_host) { gf_log ("cli", GF_LOG_ERROR, "Out of memory"); ret = -1; goto out; } get_host_name (tmp_host, &host_name); if (!host_name) { ret = -1; gf_log("cli",GF_LOG_ERROR, "Unable to allocate " "memory"); goto out; } if (!(strcmp (host_name, "localhost") && strcmp (host_name, "127.0.0.1") && strncmp (host_name, "0.", 2))) { cli_err ("Please provide a valid hostname/ip other " "than localhost, 127.0.0.1 or loopback " "address (0.0.0.0 to 0.255.255.255)."); ret = -1; GF_FREE (tmp_host); goto out; } if (!valid_internet_address (host_name, _gf_false)) { cli_err ("internet address '%s' does not conform to " "standards", host_name); } GF_FREE (tmp_host); tmp_list = gf_strdup (brick_list + 1); if (free_list_ptr) { GF_FREE (free_list_ptr); free_list_ptr = NULL; } free_list_ptr = tmp_list; j = 0; while(j < *brick_count) { strtok_r (tmp_list, " ", &tmpptr); if (!(strcmp (tmp_list, words[brick_index]))) { ret = -1; cli_err ("Found duplicate" " exports %s",words[brick_index]); goto out; } tmp_list = tmpptr; j++; } strcat (brick_list, words[brick_index]); strcat (brick_list, " "); brick_list_len += (strlen (words[brick_index]) + 1); ++(*brick_count); ++brick_index; } *bricks = gf_strdup (brick_list); if (!*bricks) ret = -1; out: GF_FREE (free_list_ptr); return ret; } int32_t cli_cmd_create_disperse_check (struct cli_state *state, int *disperse, int *redundancy, int *data, int count) { int i = 0; int tmp = 0; gf_answer_t answer = GF_ANSWER_NO; char question[128]; const char *question1 = "There isn't an optimal redundancy value " "for this configuration. Do you want to " "create the volume with redundancy 1 ?"; const char *question2 = "The optimal redundancy for this " "configuration is %d. Do you want to create " "the volume with this value ?"; const char *question3 = "This configuration is not optimal on most " "workloads. Do you want to use it ?"; const char *question4 = "Redundancy for this configuration is %d. " "Do you want to create " "the volume with this value ?"; if (*data > 0) { if (*disperse > 0 && *redundancy > 0) { if (*disperse != (*data + *redundancy)) { cli_err ("Disperse count(%d) should be equal " "to sum of disperse-data count(%d) and " "redundancy count(%d)", *disperse, *data, *redundancy); return -1; } } else if (*redundancy > 0) { *disperse = *data + *redundancy; } else if (*disperse > 0) { *redundancy = *disperse - *data; } else { if ((count - *data) >= *data) { cli_err ("Please provide redundancy count " "along with disperse-data count"); return -1; } else { sprintf (question, question4, count - *data); answer = cli_cmd_get_confirmation (state, question); if (answer == GF_ANSWER_NO) return -1; *redundancy = count - *data; *disperse = count; } } } if (*disperse <= 0) { if (count < 3) { cli_err ("number of bricks must be greater " "than 2"); return -1; } *disperse = count; } if (*redundancy == -1) { tmp = *disperse - 1; for (i = tmp / 2; (i > 0) && ((tmp & -tmp) != tmp); i--, tmp--); if (i == 0) { answer = cli_cmd_get_confirmation(state, question1); if (answer == GF_ANSWER_NO) return -1; *redundancy = 1; } else { *redundancy = *disperse - tmp; if (*redundancy > 1) { sprintf(question, question2, *redundancy); answer = cli_cmd_get_confirmation(state, question); if (answer == GF_ANSWER_NO) return -1; } } tmp = 0; } else { tmp = *disperse - *redundancy; } if (*redundancy > (*disperse - 1) / 2) { cli_err ("redundancy must be less than %d for a " "disperse %d volume", (*disperse + 1) / 2, *disperse); return -1; } if ((tmp & -tmp) != tmp) { answer = cli_cmd_get_confirmation(state, question3); if (answer == GF_ANSWER_NO) return -1; } return 0; } static int32_t cli_validate_disperse_volume (char *word, gf1_cluster_type type, const char **words, int32_t wordcount, int32_t index, int32_t *disperse_count, int32_t *redundancy_count, int32_t *data_count) { int ret = -1; switch (type) { case GF_CLUSTER_TYPE_NONE: case GF_CLUSTER_TYPE_DISPERSE: if (strcmp (word, "disperse") == 0) { if (*disperse_count >= 0) { cli_err ("disperse option given twice"); goto out; } if (wordcount < (index+2)) { goto out; } ret = gf_string2int (words[index + 1], disperse_count); if (ret == -1 && errno == EINVAL) { *disperse_count = 0; ret = 1; } else if (ret == -1) { goto out; } else { if (*disperse_count < 3) { cli_err ("disperse count must " "be greater than 2"); goto out; } ret = 2; } } else if (strcmp (word, "disperse-data") == 0) { if (*data_count >= 0) { cli_err ("disperse-data option given twice"); goto out; } if (wordcount < (index+2)) { goto out; } ret = gf_string2int (words[index+1], data_count); if (ret == -1 || *data_count < 2) { cli_err ("disperse-data must be greater than 1"); goto out; } ret = 2; } else if (strcmp (word, "redundancy") == 0) { if (*redundancy_count >= 0) { cli_err ("redundancy option given twice"); goto out; } if (wordcount < (index+2)) { goto out; } ret = gf_string2int (words[index+1], redundancy_count); if (ret == -1 || *redundancy_count < 1) { cli_err ("redundancy must be greater than 0"); goto out; } ret = 2; } break; case GF_CLUSTER_TYPE_STRIPE_REPLICATE: cli_err ("striped-replicated-dispersed volume " "is not supported"); goto out; case GF_CLUSTER_TYPE_TIER: cli_err ("tier-dispersed volume is not " "supported"); goto out; case GF_CLUSTER_TYPE_STRIPE: cli_err ("striped-dispersed volume is not " "supported"); goto out; case GF_CLUSTER_TYPE_REPLICATE: cli_err ("replicated-dispersed volume is not " "supported"); goto out; default: cli_err ("Invalid type given"); break; } out: return ret; } int32_t cli_validate_volname (const char *volname) { int32_t ret = -1; int32_t i = -1; static const char * const invalid_volnames[] = { "volume", "type", "subvolumes", "option", "end-volume", "all", "volume_not_in_ring", "description", "force", "snap-max-hard-limit", "snap-max-soft-limit", "auto-delete", "activate-on-create", NULL}; if (volname[0] == '-') goto out; for (i = 0; invalid_volnames[i]; i++) { if (!strcmp (volname, invalid_volnames[i])) { cli_err ("\"%s\" cannot be the name of a volume.", volname); goto out; } } if (strchr (volname, '/')) goto out; if (strlen (volname) > GD_VOLUME_NAME_MAX) { cli_err("Volume name exceeds %d characters.", GD_VOLUME_NAME_MAX); goto out; } for (i = 0; i < strlen (volname); i++) { if (!isalnum (volname[i]) && (volname[i] != '_') && (volname[i] != '-')) { cli_err ("Volume name should not contain \"%c\"" " character.\nVolume names can only" "contain alphanumeric, '-' and '_' " "characters.", volname[i]); goto out; } } ret = 0; out: return ret; } int32_t cli_cmd_volume_create_parse (struct cli_state *state, const char **words, int wordcount, dict_t **options, char **brick_list) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; gf1_cluster_type type = GF_CLUSTER_TYPE_NONE; int sub_count = 1; int brick_index = 0; char *trans_type = NULL; int32_t index = 0; char *bricks = NULL; int32_t brick_count = 0; char *opwords[] = { "replica", "stripe", "transport", "disperse", "redundancy", "disperse-data", "arbiter", NULL }; char *w = NULL; int op_count = 0; int32_t replica_count = 1; int32_t arbiter_count = 0; int32_t stripe_count = 1; int32_t disperse_count = -1; int32_t redundancy_count = -1; int32_t disperse_data_count = -1; gf_boolean_t is_force = _gf_false; int wc = wordcount; gf_answer_t answer = GF_ANSWER_NO; const char *question = NULL; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; if (wordcount < 3) goto out; volname = (char *)words[2]; GF_ASSERT (volname); /* Validate the volume name here itself */ if (cli_validate_volname (volname) < 0) goto out; if (wordcount < 4) { ret = -1; goto out; } type = GF_CLUSTER_TYPE_NONE; index = 3; while (op_count < 3) { ret = -1; w = str_getunamb (words[index], opwords); if (!w) { break; } else if ((strcmp (w, "replica")) == 0) { switch (type) { case GF_CLUSTER_TYPE_STRIPE_REPLICATE: case GF_CLUSTER_TYPE_REPLICATE: cli_err ("replica option given twice"); goto out; case GF_CLUSTER_TYPE_NONE: type = GF_CLUSTER_TYPE_REPLICATE; break; case GF_CLUSTER_TYPE_STRIPE: type = GF_CLUSTER_TYPE_STRIPE_REPLICATE; break; case GF_CLUSTER_TYPE_TIER: cli_err ("replicated-tiered volume is not " "supported"); goto out; break; case GF_CLUSTER_TYPE_DISPERSE: cli_err ("replicated-dispersed volume is not " "supported"); goto out; default: cli_err ("Invalid type given"); goto out; } if (wordcount < (index+2)) { ret = -1; goto out; } replica_count = strtol (words[index+1], NULL, 0); if (replica_count < 2) { cli_err ("replica count should be greater" " than 1"); ret = -1; goto out; } if (replica_count == 2) { if (strcmp (words[wordcount - 1], "force")) { question = "Replica 2 volumes are prone" " to split-brain. Use " "Arbiter or Replica 3 to " "avoid this. See: " "http://docs.gluster.org/en/latest/Administrator%20Guide/Split%20brain%20and%20ways%20to%20deal%20with%20it/." "\nDo you still want to " "continue?\n"; answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { gf_log ("cli", GF_LOG_ERROR, "Volume create " "cancelled, exiting"); ret = -1; goto out; } } } ret = dict_set_int32 (dict, "replica-count", replica_count); if (ret) goto out; index += 2; if (words[index]) { if (!strcmp (words[index], "arbiter")) { ret = gf_string2int (words[index+1], &arbiter_count); if (ret == -1 || arbiter_count != 1 || replica_count != 3) { cli_err ("For arbiter " "configuration, " "replica count must be" " 3 and arbiter count " "must be 1. The 3rd " "brick of the replica " "will be the arbiter"); ret = -1; goto out; } ret = dict_set_int32 (dict, "arbiter-count", arbiter_count); if (ret) goto out; index += 2; } } } else if ((strcmp (w, "stripe")) == 0) { switch (type) { case GF_CLUSTER_TYPE_STRIPE_REPLICATE: case GF_CLUSTER_TYPE_STRIPE: cli_err ("stripe option given twice"); goto out; case GF_CLUSTER_TYPE_NONE: type = GF_CLUSTER_TYPE_STRIPE; break; case GF_CLUSTER_TYPE_REPLICATE: type = GF_CLUSTER_TYPE_STRIPE_REPLICATE; break; case GF_CLUSTER_TYPE_DISPERSE: cli_err ("striped-dispersed volume is not " "supported"); goto out; case GF_CLUSTER_TYPE_TIER: cli_err ("striped-tier volume is not " "supported"); goto out; default: cli_err ("Invalid type given"); goto out; } if (wordcount < (index + 2)) { ret = -1; goto out; } stripe_count = strtol (words[index+1], NULL, 0); if (stripe_count < 2) { cli_err ("stripe count should be greater" " than 1"); ret = -1; goto out; } ret = dict_set_int32 (dict, "stripe-count", stripe_count); if (ret) goto out; index += 2; } else if ((strcmp (w, "transport")) == 0) { if (trans_type) { cli_err ("'transport' option given more" " than one time"); goto out; } if ((strcasecmp (words[index+1], "tcp") == 0)) { trans_type = gf_strdup ("tcp"); } else if ((strcasecmp (words[index+1], "rdma") == 0)) { trans_type = gf_strdup ("rdma"); } else if ((strcasecmp (words[index+1], "tcp,rdma") == 0) || (strcasecmp (words[index+1], "rdma,tcp") == 0)) { trans_type = gf_strdup ("tcp,rdma"); } else { gf_log ("", GF_LOG_ERROR, "incorrect transport" " protocol specified"); ret = -1; goto out; } index += 2; } else if ((strcmp (w, "disperse") == 0) || (strcmp (w, "redundancy") == 0) || (strcmp (w, "disperse-data") == 0)) { ret = cli_validate_disperse_volume (w, type, words, wordcount, index, &disperse_count, &redundancy_count, &disperse_data_count); if (ret < 0) goto out; index += ret; type = GF_CLUSTER_TYPE_DISPERSE; } else if ((strcmp (w, "arbiter") == 0)) { cli_err ("arbiter option must be preceded by replica " "option."); ret = -1; goto out; } else { GF_ASSERT (!"opword mismatch"); ret = -1; goto out; } op_count++; } if (!trans_type) trans_type = gf_strdup ("tcp"); if (index >= wordcount) { ret = -1; goto out; } brick_index = index; if (strcmp (words[wordcount - 1], "force") == 0) { is_force = _gf_true; wc = wordcount - 1; } ret = cli_cmd_bricks_parse (words, wc, brick_index, &bricks, &brick_count); if (ret) goto out; /* If brick-count is not valid when replica or stripe is given, exit here */ if (!brick_count) { cli_err ("No bricks specified"); ret = -1; goto out; } if (type == GF_CLUSTER_TYPE_DISPERSE) { ret = cli_cmd_create_disperse_check (state, &disperse_count, &redundancy_count, &disperse_data_count, brick_count); if (!ret) ret = dict_set_int32 (dict, "disperse-count", disperse_count); if (!ret) ret = dict_set_int32 (dict, "redundancy-count", redundancy_count); if (ret) goto out; sub_count = disperse_count; } else sub_count = stripe_count * replica_count; if (brick_count % sub_count) { if (type == GF_CLUSTER_TYPE_STRIPE) cli_err ("number of bricks is not a multiple of " "stripe count"); else if (type == GF_CLUSTER_TYPE_REPLICATE) cli_err ("number of bricks is not a multiple of " "replica count"); else if (type == GF_CLUSTER_TYPE_DISPERSE) cli_err ("number of bricks is not a multiple of " "disperse count"); else cli_err ("number of bricks given doesn't match " "required count"); ret = -1; goto out; } /* Everything is parsed fine. start setting info in dict */ ret = dict_set_str (dict, "volname", volname); if (ret) goto out; ret = dict_set_int32 (dict, "type", type); if (ret) goto out; ret = dict_set_dynstr (dict, "transport", trans_type); if (ret) goto out; trans_type = NULL; ret = dict_set_dynstr (dict, "bricks", bricks); if (ret) goto out; ret = dict_set_int32 (dict, "count", brick_count); if (ret) goto out; ret = dict_set_int32 (dict, "force", is_force); if (ret) goto out; *options = dict; *brick_list = bricks; out: if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to parse create volume CLI"); if (dict) dict_unref (dict); } GF_FREE (trans_type); return ret; } int32_t cli_cmd_volume_reset_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; if (wordcount < 3) goto out; if (wordcount > 5) goto out; volname = (char *)words[2]; if (!volname) { ret = -1; goto out; } ret = dict_set_str (dict, "volname", volname); if (ret) goto out; if (wordcount == 3) { ret = dict_set_str (dict, "key", "all"); if (ret) goto out; } if (wordcount >= 4) { if (!strcmp ("force", (char*)words[3])) { ret = dict_set_int32 (dict, "force", 1); if (ret) goto out; ret = dict_set_str (dict, "key", "all"); if (ret) goto out; } else { ret = dict_set_str (dict, "key", (char *)words[3]); if (ret) goto out; } } if (wordcount == 5) { if (strcmp ("force", (char*)words[4])) { ret = -1; goto out; } else { ret = dict_set_int32 (dict, "force", 1); if (ret) goto out; } } *options = dict; out: if (ret && dict) { dict_unref (dict); } return ret; } int32_t cli_cmd_get_state_parse (struct cli_state *state, const char **words, int wordcount, dict_t **options, char **op_errstr) { dict_t *dict = NULL; int ret = -1; char *odir = NULL; char *filename = NULL; char *daemon_name = NULL; int count = 0; uint32_t cmd = 0; GF_VALIDATE_OR_GOTO ("cli", options, out); GF_VALIDATE_OR_GOTO ("cli", words, out); dict = dict_new (); if (!dict) goto out; if (wordcount < 1 || wordcount > 7) { *op_errstr = gf_strdup ("Problem parsing arguments." " Check usage."); goto out; } if (wordcount >= 1) { gf_asprintf (&daemon_name, "%s", "glusterd"); for (count = 1; count < wordcount; count++) { if (strcmp (words[count], "odir") == 0 || strcmp (words[count], "file") == 0) { if (strcmp (words[count], "odir") == 0) { if (++count < wordcount) { odir = (char *) words[count]; continue; } else { ret = -1; goto out; } } else if (strcmp (words[count], "file") == 0) { if (++count < wordcount) { filename = (char *) words[count]; continue; } else { ret = -1; goto out; } } } else { if (count > 1) { if (count == wordcount-1) { if (strcmp (words[count], "detail") == 0) { cmd = GF_CLI_GET_STATE_DETAIL; continue; } else if (strcmp (words[count], "volumeoptions") == 0) { cmd = GF_CLI_GET_STATE_VOLOPTS; continue; } } else { *op_errstr = gf_strdup ("Problem" " parsing arguments. " "Check usage."); ret = -1; goto out; } } if (strcmp (words[count], "glusterd") == 0) { continue; } else { if (count == wordcount-1) { if (strcmp (words[count], "detail") == 0) { cmd = GF_CLI_GET_STATE_DETAIL; continue; } else if (strcmp (words[count], "volumeoptions") == 0) { cmd = GF_CLI_GET_STATE_VOLOPTS; continue; } } *op_errstr = gf_strdup ("glusterd is " "the only supported daemon."); ret = -1; goto out; } } } ret = dict_set_str (dict, "daemon", daemon_name); if (ret) { *op_errstr = gf_strdup ("Command failed. Please check " " log file for more details."); gf_log (THIS->name, GF_LOG_ERROR, "Setting daemon name to dictionary failed"); goto out; } if (odir) { ret = dict_set_str (dict, "odir", odir); if (ret) { *op_errstr = gf_strdup ("Command failed. Please" " check log file for" " more details."); gf_log (THIS->name, GF_LOG_ERROR, "Setting output directory to" "dictionary failed"); goto out; } } if (filename) { ret = dict_set_str (dict, "filename", filename); if (ret) { *op_errstr = gf_strdup ("Command failed. Please" " check log file for" " more details."); gf_log (THIS->name, GF_LOG_ERROR, "Setting filename to dictionary failed"); goto out; } } if (cmd) { ret = dict_set_uint32 (dict, "getstate-cmd", cmd); if (ret) { *op_errstr = gf_strdup ("Command failed. Please" " check log file for" " more details."); gf_log (THIS->name, GF_LOG_ERROR, "Setting " "get-state command type to dictionary " "failed"); goto out; } } } out: if (dict) *options = dict; if (ret && dict) dict_unref (dict); return ret; } int32_t cli_cmd_inode_quota_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) { gf_log ("cli", GF_LOG_ERROR, "dict_new failed"); goto out; } if (wordcount != 4) goto out; volname = (char *)words[2]; if (!volname) { ret = -1; goto out; } /* Validate the volume name here itself */ if (cli_validate_volname (volname) < 0) goto out; ret = dict_set_str (dict, "volname", volname); if (ret < 0) goto out; if (strcmp (words[3], "enable") != 0) { cli_out ("Invalid quota option : %s", words[3]); ret = -1; goto out; } ret = dict_set_int32 (dict, "type", GF_QUOTA_OPTION_TYPE_ENABLE_OBJECTS); if (ret < 0) goto out; *options = dict; out: if (ret < 0) { if (dict) dict_unref (dict); } return ret; } int32_t cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; int i = -1; char key[20] = {0, }; int64_t value = 0; gf_quota_type type = GF_QUOTA_OPTION_TYPE_NONE; char *opwords[] = { "enable", "disable", "limit-usage", "remove", "list", "alert-time", "soft-timeout", "hard-timeout", "default-soft-limit", "limit-objects", "list-objects", "remove-objects", NULL}; char *w = NULL; uint32_t time = 0; double percent = 0; char *end_ptr = NULL; int64_t limit = 0; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) { gf_log ("cli", GF_LOG_ERROR, "dict_new failed"); goto out; } if (wordcount < 4) { if ((wordcount == 3) && !(strcmp (words[2], "help"))) { ret = 1; } goto out; } volname = (char *)words[2]; if (!volname) { ret = -1; goto out; } /* Validate the volume name here itself */ if (cli_validate_volname (volname) < 0) goto out; ret = dict_set_str (dict, "volname", volname); if (ret < 0) goto out; w = str_getunamb (words[3], opwords); if (!w) { cli_out ("Invalid quota option : %s", words[3]); ret = - 1; goto out; } if (strcmp (w, "enable") == 0) { if (wordcount == 4) { type = GF_QUOTA_OPTION_TYPE_ENABLE; ret = 0; goto set_type; } else { ret = -1; goto out; } } if (strcmp (w, "disable") == 0) { if (wordcount == 4) { type = GF_QUOTA_OPTION_TYPE_DISABLE; ret = 0; goto set_type; } else { ret = -1; goto out; } } if (strcmp (w, "limit-usage") == 0) { type = GF_QUOTA_OPTION_TYPE_LIMIT_USAGE; } else if (strcmp (w, "limit-objects") == 0) { type = GF_QUOTA_OPTION_TYPE_LIMIT_OBJECTS; } if (type == GF_QUOTA_OPTION_TYPE_LIMIT_USAGE || type == GF_QUOTA_OPTION_TYPE_LIMIT_OBJECTS) { if (wordcount < 6 || wordcount > 7) { ret = -1; goto out; } if (words[4][0] != '/') { cli_err ("Please enter absolute path"); ret = -1; goto out; } ret = dict_set_str (dict, "path", (char *) words[4]); if (ret) goto out; if (!words[5]) { cli_err ("Please enter the limit value to be set"); ret = -1; goto out; } if (type == GF_QUOTA_OPTION_TYPE_LIMIT_USAGE) { ret = gf_string2bytesize_int64 (words[5], &value); if (ret != 0 || value <= 0) { if (errno == ERANGE || value <= 0) { ret = -1; cli_err ("Please enter an integer " "value in the range of " "(1 - %"PRId64 ")", INT64_MAX); } else cli_err ("Please enter a correct " "value"); goto out; } } else { errno = 0; limit = strtol (words[5], &end_ptr, 10); if (errno == ERANGE || errno == EINVAL || limit <= 0 || strcmp (end_ptr, "") != 0) { ret = -1; cli_err ("Please enter an integer value in " "the range 1 - %"PRId64, INT64_MAX); goto out; } } ret = dict_set_str (dict, "hard-limit", (char *) words[5]); if (ret < 0) goto out; if (wordcount == 7) { ret = gf_string2percent (words[6], &percent); if (ret != 0 || percent > 100) { ret = -1; cli_err ("Please enter a correct value " "in the range of 0 to 100"); goto out; } ret = dict_set_str (dict, "soft-limit", (char *) words[6]); if (ret < 0) goto out; } goto set_type; } if (strcmp (w, "remove") == 0) { if (wordcount != 5) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_REMOVE; if (words[4][0] != '/') { cli_err ("Please enter absolute path"); ret = -1; goto out; } ret = dict_set_str (dict, "path", (char *) words[4]); if (ret < 0) goto out; goto set_type; } if (strcmp (w, "remove-objects") == 0) { if (wordcount != 5) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_REMOVE_OBJECTS; if (words[4][0] != '/') { cli_err ("Please enter absolute path"); ret = -1; goto out; } ret = dict_set_str (dict, "path", (char *) words[4]); if (ret < 0) goto out; goto set_type; } if (strcmp (w, "list") == 0) { type = GF_QUOTA_OPTION_TYPE_LIST; if (words[4] && words[4][0] != '/') { cli_err ("Please enter absolute path"); ret = -1; goto out; } i = 4; while (i < wordcount) { snprintf (key, 20, "path%d", i-4); ret = dict_set_str (dict, key, (char *) words [i++]); if (ret < 0) goto out; } ret = dict_set_int32 (dict, "count", i - 4); if (ret < 0) goto out; goto set_type; } if (strcmp (w, "list-objects") == 0) { if (wordcount < 4) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_LIST_OBJECTS; i = 4; while (i < wordcount) { snprintf (key, 20, "path%d", i-4); ret = dict_set_str (dict, key, (char *) words[i++]); if (ret < 0) { gf_log ("cli", GF_LOG_ERROR, "Failed to set " "quota patch in request dictionary"); goto out; } } ret = dict_set_int32 (dict, "count", i - 4); if (ret < 0) { gf_log ("cli", GF_LOG_ERROR, "Failed to set quota " "limit count in request dictionary"); goto out; } goto set_type; } if (strcmp (w, "alert-time") == 0) { if (wordcount != 5) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_ALERT_TIME; ret = gf_string2time (words[4], &time); if (ret) { cli_err ("Invalid argument %s. Please enter a valid " "string", words[4]); goto out; } ret = dict_set_str (dict, "value", (char *)words[4]); if (ret < 0) goto out; goto set_type; } if (strcmp (w, "soft-timeout") == 0) { if (wordcount != 5) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_SOFT_TIMEOUT; ret = gf_string2time (words[4], &time); if (ret) { cli_err ("Invalid argument %s. Please enter a valid " "string", words[4]); goto out; } ret = dict_set_str (dict, "value", (char *)words[4]); if (ret < 0) goto out; goto set_type; } if (strcmp (w, "hard-timeout") == 0) { if(wordcount != 5) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_HARD_TIMEOUT; ret = gf_string2time (words[4], &time); if (ret) { cli_err ("Invalid argument %s. Please enter a valid " "string", words[4]); goto out; } ret = dict_set_str (dict, "value", (char *)words[4]); if (ret < 0) goto out; goto set_type; } if (strcmp (w, "default-soft-limit") == 0) { if(wordcount != 5) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_DEFAULT_SOFT_LIMIT; ret = dict_set_str (dict, "value", (char *)words[4]); if (ret < 0) goto out; goto set_type; } else { GF_ASSERT (!"opword mismatch"); } set_type: ret = dict_set_int32 (dict, "type", type); if (ret < 0) goto out; *options = dict; out: if (ret < 0) { if (dict) dict_unref (dict); } return ret; } static gf_boolean_t cli_is_key_spl (char *key) { return (strcmp (key, "group") == 0); } static int cli_add_key_group (dict_t *dict, char *key, char *value, char **op_errstr) { int ret = -1; int opt_count = 0; char iter_key[1024] = {0,}; char iter_val[1024] = {0,}; char *saveptr = NULL; char *tok_key = NULL; char *tok_val = NULL; char *dkey = NULL; char *dval = NULL; char *tagpath = NULL; char *buf = NULL; char line[PATH_MAX + 256] = {0,}; char errstr[2048] = ""; FILE *fp = NULL; ret = gf_asprintf (&tagpath, "%s/groups/%s", GLUSTERD_DEFAULT_WORKDIR, value); if (ret == -1) { tagpath = NULL; goto out; } fp = fopen (tagpath, "r"); if (!fp) { ret = -1; snprintf(errstr, sizeof(errstr), "Unable to open file '%s'." " Error: %s", tagpath, strerror (errno)); if (op_errstr) *op_errstr = gf_strdup(errstr); goto out; } opt_count = 0; buf = line; while (fscanf (fp, "%s", buf) != EOF) { opt_count++; tok_key = strtok_r (line, "=", &saveptr); tok_val = strtok_r (NULL, "=", &saveptr); if (!tok_key || !tok_val) { ret = -1; snprintf(errstr, sizeof(errstr), "'%s' file format " "not valid.", tagpath); if (op_errstr) *op_errstr = gf_strdup(errstr); goto out; } snprintf (iter_key, sizeof (iter_key), "key%d", opt_count); dkey = gf_strdup (tok_key); ret = dict_set_dynstr (dict, iter_key, dkey); if (ret) goto out; dkey = NULL; snprintf (iter_val, sizeof (iter_val), "value%d", opt_count); dval = gf_strdup (tok_val); ret = dict_set_dynstr (dict, iter_val, dval); if (ret) goto out; dval = NULL; } if (!opt_count) { ret = -1; snprintf(errstr, sizeof(errstr), "'%s' file format " "not valid.", tagpath); if (op_errstr) *op_errstr = gf_strdup(errstr); goto out; } ret = dict_set_int32 (dict, "count", opt_count); out: GF_FREE (tagpath); if (ret) { GF_FREE (dkey); GF_FREE (dval); } if (fp) fclose (fp); return ret; } int32_t cli_cmd_volume_set_parse (struct cli_state *state, const char **words, int wordcount, dict_t **options, char **op_errstr) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; int count = 0; char *key = NULL; char *value = NULL; int i = 0; char str[50] = {0,}; const char *question = NULL; gf_answer_t answer = GF_ANSWER_NO; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; if (wordcount < 3) goto out; volname = (char *)words[2]; GF_ASSERT (volname); ret = dict_set_str (dict, "volname", volname); if (ret) goto out; if (!strcmp (volname, "all")) { ret = dict_set_str (dict, "globalname", "All"); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "dict set on global key failed."); goto out; } ret = dict_set_int32 (dict, "hold_global_locks", _gf_true); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "dict set on global key failed."); goto out; } } if ((!strcmp (volname, "help") || !strcmp (volname, "help-xml")) && wordcount == 3 ) { ret = dict_set_str (dict, volname, volname); if (ret) goto out; } else if (wordcount < 5) { ret = -1; goto out; } else if (wordcount == 5 && cli_is_key_spl ((char *)words[3])) { key = (char *) words[3]; value = (char *) words[4]; if ( !key || !value) { ret = -1; goto out; } ret = gf_strip_whitespace (value, strlen (value)); if (ret == -1) goto out; if (strlen (value) == 0) { ret = -1; goto out; } ret = cli_add_key_group (dict, key, value, op_errstr); if (ret == 0) *options = dict; goto out; } for (i = 3; i < wordcount; i+=2) { key = (char *) words[i]; value = (char *) words[i+1]; if ( !key || !value) { ret = -1; goto out; } count++; if (fnmatch ("user.*", key, FNM_NOESCAPE) != 0) { ret = gf_strip_whitespace (value, strlen (value)); if (ret == -1) goto out; } if (strlen (value) == 0) { ret = -1; goto out; } if (cli_is_key_spl (key)) { ret = -1; goto out; } sprintf (str, "key%d", count); ret = dict_set_str (dict, str, key); if (ret) goto out; sprintf (str, "value%d", count); ret = dict_set_str (dict, str, value); if (ret) goto out; if ((!strcmp (key, "cluster.enable-shared-storage")) && (!strcmp (value, "disable"))) { question = "Disabling cluster.enable-shared-storage " "will delete the shared storage volume" "(gluster_shared_storage), which is used " "by snapshot scheduler, geo-replication " "and NFS-Ganesha. Do you still want to " "continue?"; answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { gf_log ("cli", GF_LOG_ERROR, "Operation " "cancelled, exiting"); *op_errstr = gf_strdup ("Aborted by user."); ret = -1; goto out; } } if ((!strcmp (key, "nfs.disable")) && (!strcmp (value, "off"))) { question = "Gluster NFS is being deprecated in favor " "of NFS-Ganesha Enter \"yes\" to continue " "using Gluster NFS"; answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { gf_log ("cli", GF_LOG_ERROR, "Operation " "cancelled, exiting"); *op_errstr = gf_strdup ("Aborted by user."); ret = -1; goto out; } } } ret = dict_set_int32 (dict, "count", wordcount-3); if (ret) goto out; *options = dict; out: if (ret && dict) dict_unref (dict); return ret; } int32_t cli_cmd_volume_add_brick_parse (const char **words, int wordcount, dict_t **options, int *ret_type) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; int brick_count = 0, brick_index = 0; char *bricks = NULL; char *opwords_cl[] = { "replica", "stripe", NULL }; gf1_cluster_type type = GF_CLUSTER_TYPE_NONE; int count = 1; int arbiter_count = 0; char *w = NULL; int index; gf_boolean_t is_force = _gf_false; int wc = wordcount; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; if (wordcount < 3) goto out; volname = (char *)words[2]; GF_ASSERT (volname); ret = dict_set_str (dict, "volname", volname); if (ret) goto out; if (wordcount < 4) { ret = -1; goto out; } if (wordcount < 6) { /* seems no options are given, go directly to the parse_brick */ brick_index = 3; type = GF_CLUSTER_TYPE_NONE; goto parse_bricks; } w = str_getunamb (words[3], opwords_cl); if (!w) { type = GF_CLUSTER_TYPE_NONE; index = 3; } else if ((strcmp (w, "replica")) == 0) { type = GF_CLUSTER_TYPE_REPLICATE; count = strtol (words[4], NULL, 0); if (!count || (count < 2)) { cli_err ("replica count should be greater than 1"); ret = -1; goto out; } ret = dict_set_int32 (dict, "replica-count", count); if (ret) goto out; index = 5; if (words[index] && !strcmp (words[index], "arbiter")) { arbiter_count = strtol (words[6], NULL, 0); if (arbiter_count != 1 || count != 3) { cli_err ("For arbiter configuration, replica " "count must be 3 and arbiter count " "must be 1. The 3rd brick of the " "replica will be the arbiter"); ret = -1; goto out; } ret = dict_set_int32 (dict, "arbiter-count", arbiter_count); if (ret) goto out; index = 7; } } else if ((strcmp (w, "stripe")) == 0) { type = GF_CLUSTER_TYPE_STRIPE; count = strtol (words[4], NULL, 0); if (!count || (count < 2)) { cli_err ("stripe count should be greater than 1"); ret = -1; goto out; } ret = dict_set_int32 (dict, "stripe-count", count); if (ret) goto out; index = 5; } else { GF_ASSERT (!"opword mismatch"); ret = -1; goto out; } brick_index = index; parse_bricks: if (strcmp (words[wordcount - 1], "force") == 0) { is_force = _gf_true; wc = wordcount - 1; } ret = cli_cmd_bricks_parse (words, wc, brick_index, &bricks, &brick_count); if (ret) goto out; if (!brick_count) { cli_err ("No bricks specified"); ret = -1; goto out; } ret = dict_set_dynstr (dict, "bricks", bricks); if (ret) goto out; ret = dict_set_int32 (dict, "count", brick_count); if (ret) goto out; ret = dict_set_int32 (dict, "force", is_force); if (ret) goto out; *options = dict; out: if (ret_type) *ret_type = type; if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to parse add-brick CLI"); if (dict) dict_unref (dict); } return ret; } int32_t cli_cmd_volume_tier_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; int32_t command = GF_DEFRAG_CMD_NONE; int32_t is_force = 0; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; if (!(wordcount == 4 || wordcount == 5)) { gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); ret = -1; goto out; } volname = (char *)words[2]; GF_ASSERT (volname); ret = cli_cmd_validate_volume (volname); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to validate volume name"); goto out; } ret = dict_set_str (dict, "volname", volname); if (ret) goto out; volname = (char *)words[2]; if (wordcount == 4) { if (!strcmp(words[3], "status")) command = GF_DEFRAG_CMD_STATUS_TIER; else if (!strcmp(words[3], "start")) command = GF_DEFRAG_CMD_START_TIER; else if (!strcmp(words[3], "stop")) command = GF_DEFRAG_CMD_STOP_TIER; else { ret = -1; goto out; } } else if (wordcount == 5) { if ((!strcmp (words[3], "start")) && (!strcmp (words[4], "force"))) { command = GF_DEFRAG_CMD_START_TIER; is_force = 1; ret = dict_set_int32 (dict, "force", is_force); if (ret) goto out; } else { ret = -1; goto out; } } ret = dict_set_int32 (dict, "rebalance-command", command); if (ret) goto out; *options = dict; out: if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to parse tier CLI"); if (dict) dict_unref (dict); } return ret; } int32_t cli_cmd_volume_detach_tier_parse (const char **words, int wordcount, dict_t **options, int *question) { int ret = -1; char *word = NULL; dict_t *dict = NULL; int32_t command = GF_DEFRAG_CMD_NONE; dict = dict_new (); if (!dict) goto out; ret = dict_set_str (dict, "volname", (char *)words[2]); if (ret) goto out; if (wordcount == 3 && !strcmp ((char *)words[2], "help")) { return -1; } if (wordcount != 4) { ret = -1; goto out; } word = (char *)words[3]; ret = -1; if (!strcmp(word, "start")) { command = GF_DEFRAG_CMD_DETACH_START; } else if (!strcmp(word, "commit")) { *question = 1; command = GF_DEFRAG_CMD_DETACH_COMMIT; } else if (!strcmp(word, "force")) { *question = 1; command = GF_DEFRAG_CMD_DETACH_COMMIT_FORCE; } else if (!strcmp(word, "stop")) command = GF_DEFRAG_CMD_DETACH_STOP; else if (!strcmp(word, "status")) command = GF_DEFRAG_CMD_DETACH_STATUS; else goto out; ret = dict_set_int32 (dict, "command", command); if (ret) goto out; *options = dict; ret = 0; out: if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to parse detach tier CLI"); if (dict) dict_unref (dict); } return ret; } int32_t cli_cmd_volume_remove_brick_parse (const char **words, int wordcount, dict_t **options, int *question, int *brick_count) { dict_t *dict = NULL; char *volname = NULL; char *delimiter = NULL; int ret = -1; char key[50]; int brick_index = 0; int32_t tmp_index = 0; int32_t j = 0; char *tmp_brick = NULL; char *tmp_brick1 = NULL; char *type_opword[] = { "replica", NULL }; char *opwords[] = { "start", "commit", "stop", "status", "force", NULL }; char *w = NULL; int32_t command = GF_OP_CMD_NONE; long count = 0; GF_ASSERT (words); GF_ASSERT (options); if (wordcount < 5) goto out; dict = dict_new (); if (!dict) goto out; volname = (char *)words[2]; GF_ASSERT (volname); ret = dict_set_str (dict, "volname", volname); if (ret) goto out; brick_index = 3; w = str_getunamb (words[3], type_opword); if (w && !strcmp ("replica", w)) { if (wordcount < 6) { ret = -1; goto out; } count = strtol (words[4], NULL, 0); if (count < 1) { cli_err ("replica count should be greater than 0 in " "case of remove-brick"); ret = -1; goto out; } ret = dict_set_int32 (dict, "replica-count", count); if (ret) goto out; brick_index = 5; } else if (w) { GF_ASSERT (!"opword mismatch"); } w = str_getunamb (words[wordcount - 1], opwords); if (!w) { ret = -1; goto out; } else { /* handled this option */ wordcount--; if (!strcmp ("start", w)) { command = GF_OP_CMD_START; } else if (!strcmp ("commit", w)) { command = GF_OP_CMD_COMMIT; if (question) *question = 1; } else if (!strcmp ("stop", w)) { command = GF_OP_CMD_STOP; } else if (!strcmp ("status", w)) { command = GF_OP_CMD_STATUS; } else if (!strcmp ("force", w)) { command = GF_OP_CMD_COMMIT_FORCE; if (question) *question = 1; } else { GF_ASSERT (!"opword mismatch"); ret = -1; goto out; } } ret = dict_set_int32 (dict, "command", command); if (ret) gf_log ("cli", GF_LOG_INFO, "failed to set 'command' %d", command); tmp_index = brick_index; tmp_brick = GF_MALLOC(2048 * sizeof(*tmp_brick), gf_common_mt_char); if (!tmp_brick) { gf_log ("",GF_LOG_ERROR,"cli_cmd_volume_remove_brick_parse: " "Unable to get memory"); ret = -1; goto out; } tmp_brick1 = GF_MALLOC(2048 * sizeof(*tmp_brick1), gf_common_mt_char); if (!tmp_brick1) { gf_log ("",GF_LOG_ERROR,"cli_cmd_volume_remove_brick_parse: " "Unable to get memory"); ret = -1; goto out; } while (brick_index < wordcount) { if (validate_brick_name ((char *)words[brick_index])) { cli_err ("wrong brick type: %s, use :" "", words[brick_index]); ret = -1; goto out; } else { delimiter = strrchr(words[brick_index], ':'); ret = gf_canonicalize_path (delimiter + 1); if (ret) goto out; } j = tmp_index; strcpy(tmp_brick, words[brick_index]); while ( j < brick_index) { strcpy(tmp_brick1, words[j]); if (!(strcmp (tmp_brick, tmp_brick1))) { gf_log("",GF_LOG_ERROR, "Duplicate bricks" " found %s", words[brick_index]); cli_err("Duplicate bricks found %s", words[brick_index]); ret = -1; goto out; } j++; } snprintf (key, 50, "brick%d", ++(*brick_count)); ret = dict_set_str (dict, key, (char *)words[brick_index++]); if (ret) goto out; } if (command != GF_OP_CMD_STATUS && command != GF_OP_CMD_STOP) { ret = dict_set_int32 (dict, "count", *brick_count); if (ret) goto out; } *options = dict; out: if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to parse remove-brick CLI"); if (dict) dict_unref (dict); } GF_FREE (tmp_brick); GF_FREE (tmp_brick1); return ret; } int32_t cli_cmd_brick_op_validate_bricks (const char **words, dict_t *dict, int src, int dst) { int ret = -1; char *delimiter = NULL; if (validate_brick_name ((char *)words[src])) { cli_err ("wrong brick type: %s, use " ":", words[3]); ret = -1; goto out; } else { delimiter = strrchr ((char *)words[src], '/'); ret = gf_canonicalize_path (delimiter); if (ret) goto out; } ret = dict_set_str (dict, "src-brick", (char *)words[src]); if (ret) goto out; if (dst == -1) { ret = 0; goto out; } if (validate_brick_name ((char *)words[dst])) { cli_err ("wrong brick type: %s, use " ":", words[dst]); ret = -1; goto out; } else { delimiter = strrchr ((char *)words[dst], '/'); ret = gf_canonicalize_path (delimiter); if (ret) goto out; } ret = dict_set_str (dict, "dst-brick", (char *)words[dst]); if (ret) goto out; ret = 0; out: return ret; } int32_t cli_cmd_volume_reset_brick_parse (const char **words, int wordcount, dict_t **options) { int ret = -1; char *volname = NULL; dict_t *dict = NULL; if (wordcount < 5 || wordcount > 7) goto out; dict = dict_new (); if (!dict) goto out; volname = (char *)words[2]; ret = dict_set_str (dict, "volname", volname); if (ret) goto out; if (wordcount == 5) { if (strcmp (words[4], "start")) { cli_err ("Invalid option '%s' for reset-brick. Please " "enter valid reset-brick command", words[4]); ret = -1; goto out; } ret = cli_cmd_brick_op_validate_bricks (words, dict, 3, -1); if (ret) goto out; ret = dict_set_str (dict, "operation", "GF_RESET_OP_START"); if (ret) goto out; } else if (wordcount == 6) { if (strcmp (words[5], "commit")) { cli_err ("Invalid option '%s' for reset-brick. Please " "enter valid reset-brick command", words[5]); ret = -1; goto out; } ret = cli_cmd_brick_op_validate_bricks (words, dict, 3, 4); if (ret) goto out; ret = dict_set_str (dict, "operation", "GF_RESET_OP_COMMIT"); if (ret) goto out; } else if (wordcount == 7) { if (strcmp (words[5], "commit") || strcmp (words[6], "force")) { cli_err ("Invalid option '%s %s' for reset-brick. Please " "enter valid reset-brick command", words[5], words[6]); ret = -1; goto out; } ret = cli_cmd_brick_op_validate_bricks (words, dict, 3, 4); if (ret) goto out; ret = dict_set_str (dict, "operation", "GF_RESET_OP_COMMIT_FORCE"); if (ret) goto out; } *options = dict; out: if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to parse reset-brick CLI"); if (dict) dict_unref (dict); } return ret; } int32_t cli_cmd_volume_replace_brick_parse (const char **words, int wordcount, dict_t **options) { int ret = -1; char *volname = NULL; dict_t *dict = NULL; GF_ASSERT (words); GF_ASSERT (options); if (wordcount != 7) { ret = -1; goto out; } dict = dict_new (); if (!dict) { gf_log ("cli", GF_LOG_ERROR, "Failed to allocate dictionary"); goto out; } volname = (char *)words[2]; GF_ASSERT (volname); ret = dict_set_str (dict, "volname", volname); if (ret) goto out; ret = cli_cmd_brick_op_validate_bricks (words, dict, 3, 4); if (ret) goto out; /* commit force option */ if (strcmp ("commit", words[5]) || strcmp ("force", words[6])) { cli_err ("Invalid option '%s' '%s' for replace-brick. Please " "enter valid replace-brick command", words[5], words[6]); ret = -1; goto out; } ret = dict_set_str (dict, "operation", "GF_REPLACE_OP_COMMIT_FORCE"); if (ret) goto out; *options = dict; out: if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to parse reset-brick CLI"); if (dict) dict_unref (dict); } return ret; } int32_t cli_cmd_log_filename_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; char *volname = NULL; char *str = NULL; int ret = -1; char *delimiter = NULL; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; volname = (char *)words[3]; GF_ASSERT (volname); ret = dict_set_str (dict, "volname", volname); if (ret) goto out; str = (char *)words[4]; if (strchr (str, ':')) { delimiter = strchr (words[4], ':'); if (!delimiter || delimiter == words[4] || *(delimiter+1) != '/') { cli_err ("wrong brick type: %s, use :" "", words[4]); ret = -1; goto out; } else { ret = gf_canonicalize_path (delimiter + 1); if (ret) goto out; } ret = dict_set_str (dict, "brick", str); if (ret) goto out; /* Path */ str = (char *)words[5]; ret = dict_set_str (dict, "path", str); if (ret) goto out; } else { ret = dict_set_str (dict, "path", str); if (ret) goto out; } *options = dict; out: if (ret && dict) dict_unref (dict); return ret; } int32_t cli_cmd_log_level_parse (const char **words, int worcount, dict_t **options) { dict_t *dict = NULL; int ret = -1; GF_ASSERT (words); GF_ASSERT (options); /* * loglevel command format: * > volume log level * > volume log level colon-o posix WARNING * > volume log level colon-o replicate* DEBUG * > volume log level coon-o * TRACE */ GF_ASSERT ((strncmp(words[0], "volume", 6) == 0)); GF_ASSERT ((strncmp(words[1], "log", 3) == 0)); GF_ASSERT ((strncmp(words[2], "level", 5) == 0)); ret = glusterd_check_log_level(words[5]); if (ret == -1) { cli_err("Invalid log level [%s] specified", words[5]); cli_err("Valid values for loglevel: (DEBUG|WARNING|ERROR" "|CRITICAL|NONE|TRACE)"); goto out; } dict = dict_new (); if (!dict) goto out; GF_ASSERT(words[3]); GF_ASSERT(words[4]); ret = dict_set_str (dict, "volname", (char *)words[3]); if (ret) goto out; ret = dict_set_str (dict, "xlator", (char *)words[4]); if (ret) goto out; ret = dict_set_str (dict, "loglevel", (char *)words[5]); if (ret) goto out; *options = dict; out: if (ret && dict) dict_unref (dict); return ret; } int32_t cli_cmd_log_locate_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; char *volname = NULL; char *str = NULL; int ret = -1; char *delimiter = NULL; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; volname = (char *)words[3]; GF_ASSERT (volname); ret = dict_set_str (dict, "volname", volname); if (ret) goto out; if (words[4]) { delimiter = strchr (words[4], ':'); if (!delimiter || delimiter == words[4] || *(delimiter+1) != '/') { cli_err ("wrong brick type: %s, use :" "", words[4]); ret = -1; goto out; } else { ret = gf_canonicalize_path (delimiter + 1); if (ret) goto out; } str = (char *)words[4]; ret = dict_set_str (dict, "brick", str); if (ret) goto out; } *options = dict; out: if (ret && dict) dict_unref (dict); return ret; } int32_t cli_cmd_log_rotate_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; char *volname = NULL; char *str = NULL; int ret = -1; char *delimiter = NULL; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; if (strcmp ("rotate", words[3]) == 0) volname = (char *)words[2]; else if (strcmp ("rotate", words[2]) == 0) volname = (char *)words[3]; GF_ASSERT (volname); ret = dict_set_str (dict, "volname", volname); if (ret) goto out; if (words[4]) { delimiter = strchr (words[4], ':'); if (!delimiter || delimiter == words[4] || *(delimiter+1) != '/') { cli_err ("wrong brick type: %s, use :" "", words[4]); ret = -1; goto out; } else { ret = gf_canonicalize_path (delimiter + 1); if (ret) goto out; } str = (char *)words[4]; ret = dict_set_str (dict, "brick", str); if (ret) goto out; } *options = dict; out: if (ret && dict) dict_unref (dict); return ret; } static gf_boolean_t gsyncd_url_check (const char *w) { return !!strpbrk (w, ":/"); } static gf_boolean_t gsyncd_glob_check (const char *w) { return !!strpbrk (w, "*?["); } static int config_parse (const char **words, int wordcount, dict_t *dict, unsigned cmdi, unsigned glob) { int32_t ret = -1; int32_t i = -1; char *append_str = NULL; size_t append_len = 0; char *subop = NULL; char *ret_chkpt = NULL; struct tm checkpoint_time; char chkpt_buf[20] = ""; switch ((wordcount - 1) - cmdi) { case 0: subop = gf_strdup ("get-all"); break; case 1: if (words[cmdi + 1][0] == '!') { (words[cmdi + 1])++; if (gf_asprintf (&subop, "del%s", glob ? "-glob" : "") == -1) subop = NULL; } else subop = gf_strdup ("get"); ret = dict_set_str (dict, "op_name", ((char *)words[cmdi + 1])); if (ret < 0) goto out; break; default: if (gf_asprintf (&subop, "set%s", glob ? "-glob" : "") == -1) subop = NULL; ret = dict_set_str (dict, "op_name", ((char *)words[cmdi + 1])); if (ret < 0) goto out; /* join the varargs by spaces to get the op_value */ for (i = cmdi + 2; i < wordcount; i++) append_len += (strlen (words[i]) + 1); /* trailing strcat will add two bytes, make space for that */ append_len++; append_str = GF_CALLOC (1, append_len, cli_mt_append_str); if (!append_str) { ret = -1; goto out; } for (i = cmdi + 2; i < wordcount; i++) { strcat (append_str, words[i]); strcat (append_str, " "); } append_str[append_len - 2] = '\0'; /* "checkpoint now" is special: we resolve that "now" */ if ((strcmp (words[cmdi + 1], "checkpoint") == 0) && (strcmp (append_str, "now") == 0)) { struct timeval tv = {0,}; ret = gettimeofday (&tv, NULL); if (ret == -1) goto out; GF_FREE (append_str); append_str = GF_CALLOC (1, 300, cli_mt_append_str); if (!append_str) { ret = -1; goto out; } snprintf (append_str, 300, "%" GF_PRI_SECOND, tv.tv_sec); } else if ((strcmp (words[cmdi + 1], "checkpoint") == 0) && (strcmp (append_str, "now") != 0)) { memset(&checkpoint_time, 0, sizeof(struct tm)); ret_chkpt = strptime(append_str, "%Y-%m-%d %H:%M:%S", &checkpoint_time); if (ret_chkpt == NULL) { ret = -1; cli_err ("Invalid Checkpoint label. Use format " "\"Y-m-d H:M:S\", Example: 2016-10-25 15:30:45"); goto out; } GF_FREE (append_str); append_str = GF_CALLOC (1, 300, cli_mt_append_str); if (!append_str) { ret = -1; goto out; } strftime (chkpt_buf, sizeof(chkpt_buf), "%s", &checkpoint_time); snprintf (append_str, 300, "%s", chkpt_buf); } ret = dict_set_dynstr (dict, "op_value", append_str); } ret = -1; if (subop) { ret = dict_set_dynstr (dict, "subop", subop); if (!ret) subop = NULL; } out: if (ret && append_str) GF_FREE (append_str); GF_FREE (subop); gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } /* ssh_port_parse: Parses and validates when ssh_port is given. * ssh_index refers to index of ssh_port and * type refers to either push-pem or no-verify */ static int32_t parse_ssh_port (const char **words, int wordcount, dict_t *dict, unsigned *cmdi, int ssh_index, char *type) { int ret = 0; char *end_ptr = NULL; int64_t limit = 0; if (!strcmp ((char *)words[ssh_index], "ssh-port")) { if (strcmp ((char *)words[ssh_index-1], "create")) { ret = -1; goto out; } (*cmdi)++; limit = strtol (words[ssh_index+1], &end_ptr, 10); if (errno == ERANGE || errno == EINVAL || limit <= 0 || strcmp (end_ptr, "") != 0) { ret = -1; cli_err ("Please enter an integer value for ssh_port "); goto out; } ret = dict_set_int32 (dict, "ssh_port", limit); if (ret) goto out; (*cmdi)++; } else if (strcmp ((char *)words[ssh_index+1], "create")) { ret = -1; goto out; } ret = dict_set_int32 (dict, type, 1); if (ret) goto out; (*cmdi)++; out: return ret; } static int32_t force_push_pem_no_verify_parse (const char **words, int wordcount, dict_t *dict, unsigned *cmdi) { int32_t ret = 0; if (!strcmp ((char *)words[wordcount-1], "force")) { if ((strcmp ((char *)words[wordcount-2], "start")) && (strcmp ((char *)words[wordcount-2], "stop")) && (strcmp ((char *)words[wordcount-2], "create")) && (strcmp ((char *)words[wordcount-2], "no-verify")) && (strcmp ((char *)words[wordcount-2], "push-pem")) && (strcmp ((char *)words[wordcount-2], "pause")) && (strcmp ((char *)words[wordcount-2], "resume"))) { ret = -1; goto out; } ret = dict_set_uint32 (dict, "force", _gf_true); if (ret) goto out; (*cmdi)++; if (!strcmp ((char *)words[wordcount-2], "push-pem")) { ret = parse_ssh_port (words, wordcount, dict, cmdi, wordcount-4, "push_pem"); if (ret) goto out; } else if (!strcmp ((char *)words[wordcount-2], "no-verify")) { ret = parse_ssh_port (words, wordcount, dict, cmdi, wordcount-4, "no_verify"); if (ret) goto out; } } else if (!strcmp ((char *)words[wordcount-1], "push-pem")) { ret = parse_ssh_port (words, wordcount, dict, cmdi, wordcount-3, "push_pem"); if (ret) goto out; } else if (!strcmp ((char *)words[wordcount-1], "no-verify")) { ret = parse_ssh_port (words, wordcount, dict, cmdi, wordcount-3, "no_verify"); if (ret) goto out; } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) { int32_t ret = -1; dict_t *dict = NULL; gf1_cli_gsync_set type = GF_GSYNC_OPTION_TYPE_NONE; int i = 0; unsigned masteri = 0; unsigned slavei = 0; unsigned glob = 0; unsigned cmdi = 0; char *opwords[] = { "create", "status", "start", "stop", "config", "force", "delete", "ssh-port", "no-verify", "push-pem", "detail", "pause", "resume", NULL }; char *w = NULL; char *save_ptr = NULL; char *slave_temp = NULL; char *token = NULL; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; /* new syntax: * * volume geo-replication $m $s create [[ssh-port n] [[no-verify] | [push-pem]]] [force] * volume geo-replication [$m [$s]] status [detail] * volume geo-replication [$m] $s config [[!]$opt [$val]] * volume geo-replication $m $s start|stop [force] * volume geo-replication $m $s delete [reset-sync-time] * volume geo-replication $m $s pause [force] * volume geo-replication $m $s resume [force] */ if (wordcount < 3) goto out; for (i = 2; i <= 3 && i < wordcount - 1; i++) { if (gsyncd_glob_check (words[i])) glob = i; if (gsyncd_url_check (words[i])) { slavei = i; break; } } if (glob && !slavei) /* glob is allowed only for config, thus it implies there is a * slave argument; but that might have not been recognized on * the first scan as it's url characteristics has been covered * by the glob syntax. * * In this case, the slave is perforce the last glob-word -- the * upcoming one is neither glob, nor url, so it's definitely not * the slave. */ slavei = glob; if (slavei) { cmdi = slavei + 1; if (slavei == 3) masteri = 2; } else if (i <= 4) { if (strtail ("detail", (char *)words[wordcount-1])) { cmdi = wordcount - 2; if (i == 4) masteri = 2; } else { /* no $s, can only be status cmd * (with either a single $m before it or nothing) * -- these conditions imply that i <= 3 after * the iteration and that i is the successor of * the (0 or 1 length) sequence of $m-s. */ cmdi = i; if (i == 3) masteri = 2; } } else goto out; /* now check if input really complies syntax * (in a somewhat redundant way, in favor * transparent soundness) */ if (masteri && gsyncd_url_check (words[masteri])) goto out; if (slavei && !glob && !gsyncd_url_check (words[slavei])) goto out; w = str_getunamb (words[cmdi], opwords); if (!w) goto out; if (strcmp (w, "create") == 0) { type = GF_GSYNC_OPTION_TYPE_CREATE; if (!masteri || !slavei) goto out; } else if (strcmp (w, "status") == 0) { type = GF_GSYNC_OPTION_TYPE_STATUS; if (slavei && !masteri) goto out; } else if (strcmp (w, "config") == 0) { type = GF_GSYNC_OPTION_TYPE_CONFIG; if (!slavei) goto out; } else if (strcmp (w, "start") == 0) { type = GF_GSYNC_OPTION_TYPE_START; if (!masteri || !slavei) goto out; } else if (strcmp (w, "stop") == 0) { type = GF_GSYNC_OPTION_TYPE_STOP; if (!masteri || !slavei) goto out; } else if (strcmp (w, "delete") == 0) { type = GF_GSYNC_OPTION_TYPE_DELETE; if (!masteri || !slavei) goto out; } else if (strcmp (w, "pause") == 0) { type = GF_GSYNC_OPTION_TYPE_PAUSE; if (!masteri || !slavei) goto out; } else if (strcmp (w, "resume") == 0) { type = GF_GSYNC_OPTION_TYPE_RESUME; if (!masteri || !slavei) goto out; } else GF_ASSERT (!"opword mismatch"); ret = force_push_pem_no_verify_parse (words, wordcount, dict, &cmdi); if (ret) goto out; if (strtail ("detail", (char *)words[wordcount-1])) { if (!strtail ("status", (char *)words[wordcount-2])) { ret = -1; goto out; } ret = dict_set_uint32 (dict, "status-detail", _gf_true); if (ret) goto out; cmdi++; } if (type == GF_GSYNC_OPTION_TYPE_DELETE && !strcmp ((char *)words[wordcount-1], "reset-sync-time")) { if (strcmp ((char *)words[wordcount-2], "delete")) { ret = -1; goto out; } ret = dict_set_uint32 (dict, "reset-sync-time", _gf_true); if (ret) goto out; cmdi++; } if (type != GF_GSYNC_OPTION_TYPE_CONFIG && (cmdi < wordcount - 1 || glob)) goto out; /* If got so far, input is valid, assemble the message */ ret = 0; if (masteri) { ret = dict_set_str (dict, "master", (char *)words[masteri]); if (!ret) ret = dict_set_str (dict, "volname", (char *)words[masteri]); } if (!ret && slavei) { /* If geo-rep is created with root user using the syntax * gluster vol geo-rep root@ ... * pass down only else pass as it is. */ slave_temp = gf_strdup (words[slavei]); token = strtok_r (slave_temp, "@", &save_ptr); if (token && !strcmp (token, "root")) { ret = dict_set_str (dict, "slave", (char *)words[slavei]+5); } else { ret = dict_set_str (dict, "slave", (char *)words[slavei]); } } if (!ret) ret = dict_set_int32 (dict, "type", type); if (!ret && type == GF_GSYNC_OPTION_TYPE_CONFIG) ret = config_parse (words, wordcount, dict, cmdi, glob); out: if (slave_temp) GF_FREE (slave_temp); if (ret) { if (dict) dict_unref (dict); } else *options = dict; return ret; } int32_t cli_cmd_volume_profile_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; gf1_cli_stats_op op = GF_CLI_STATS_NONE; gf1_cli_info_op info_op = GF_CLI_INFO_NONE; gf_boolean_t is_peek = _gf_false; char *opwords[] = { "start", "stop", "info", NULL }; char *w = NULL; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; if (wordcount < 4) goto out; volname = (char *)words[2]; ret = dict_set_str (dict, "volname", volname); if (ret) goto out; w = str_getunamb (words[3], opwords); if (!w) { ret = -1; goto out; } if ((strcmp (w, "start") == 0 || strcmp (w, "stop") == 0) && wordcount > 5) goto out; if (strcmp (w, "info") == 0 && wordcount > 7) goto out; if (strcmp (w, "start") == 0) { op = GF_CLI_STATS_START; } else if (strcmp (w, "stop") == 0) { op = GF_CLI_STATS_STOP; } else if (strcmp (w, "info") == 0) { op = GF_CLI_STATS_INFO; info_op = GF_CLI_INFO_ALL; if (wordcount > 4) { if (strcmp (words[4], "incremental") == 0) { info_op = GF_CLI_INFO_INCREMENTAL; if (wordcount > 5 && strcmp (words[5], "peek") == 0) { is_peek = _gf_true; } } else if (strcmp (words[4], "cumulative") == 0) { info_op = GF_CLI_INFO_CUMULATIVE; } else if (strcmp (words[4], "clear") == 0) { info_op = GF_CLI_INFO_CLEAR; } else if (strcmp (words[4], "peek") == 0) { is_peek = _gf_true; } } } else GF_ASSERT (!"opword mismatch"); ret = dict_set_int32 (dict, "op", (int32_t)op); if (ret) goto out; ret = dict_set_int32 (dict, "info-op", (int32_t)info_op); if (ret) goto out; ret = dict_set_int32 (dict, "peek", is_peek); if (ret) goto out; if (!strcmp (words[wordcount - 1], "nfs")) { ret = dict_set_int32 (dict, "nfs", _gf_true); if (ret) goto out; } *options = dict; out: if (ret && dict) dict_unref (dict); return ret; } int32_t cli_cmd_volume_top_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; char *volname = NULL; char *value = NULL; char *key = NULL; int ret = -1; gf1_cli_stats_op op = GF_CLI_STATS_NONE; gf1_cli_top_op top_op = GF_CLI_TOP_NONE; int32_t list_cnt = -1; int index = 0; int perf = 0; int32_t blk_size = 0; int count = 0; gf_boolean_t nfs = _gf_false; char *delimiter = NULL; char *opwords[] = { "open", "read", "write", "opendir", "readdir", "read-perf", "write-perf", "clear", NULL }; char *w = NULL; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; if (wordcount < 4) goto out; volname = (char *)words[2]; ret = dict_set_str (dict, "volname", volname); if (ret) goto out; op = GF_CLI_STATS_TOP; ret = dict_set_int32 (dict, "op", (int32_t)op); if (ret) goto out; w = str_getunamb (words[3], opwords); if (!w) { ret = -1; goto out; } if (strcmp (w, "open") == 0) { top_op = GF_CLI_TOP_OPEN; } else if (strcmp (w, "read") == 0) { top_op = GF_CLI_TOP_READ; } else if (strcmp (w, "write") == 0) { top_op = GF_CLI_TOP_WRITE; } else if (strcmp (w, "opendir") == 0) { top_op = GF_CLI_TOP_OPENDIR; } else if (strcmp (w, "readdir") == 0) { top_op = GF_CLI_TOP_READDIR; } else if (strcmp (w, "read-perf") == 0) { top_op = GF_CLI_TOP_READ_PERF; perf = 1; } else if (strcmp (w, "write-perf") == 0) { top_op = GF_CLI_TOP_WRITE_PERF; perf = 1; } else if (strcmp (w, "clear") == 0) { ret = dict_set_int32 (dict, "clear-stats", 1); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not set clear-stats in dict"); goto out; } } else GF_ASSERT (!"opword mismatch"); ret = dict_set_int32 (dict, "top-op", (int32_t)top_op); if (ret) goto out; if ((wordcount > 4) && !strcmp (words[4], "nfs")) { nfs = _gf_true; ret = dict_set_int32 (dict, "nfs", nfs); if (ret) goto out; index = 5; } else { index = 4; } for (; index < wordcount; index+=2) { key = (char *) words[index]; value = (char *) words[index+1]; if ( key && !value ) { ret = -1; goto out; } if (!strcmp (key, "brick")) { delimiter = strchr (value, ':'); if (!delimiter || delimiter == value || *(delimiter+1) != '/') { cli_err ("wrong brick type: %s, use :" "", value); ret = -1; goto out; } else { ret = gf_canonicalize_path (delimiter + 1); if (ret) goto out; } ret = dict_set_str (dict, "brick", value); } else if (!strcmp (key, "list-cnt")) { ret = gf_is_str_int (value); if (!ret) list_cnt = atoi (value); if (ret || (list_cnt < 0) || (list_cnt > 100)) { cli_err ("list-cnt should be between 0 to 100"); ret = -1; goto out; } } else if (perf && !nfs && !strcmp (key, "bs")) { ret = gf_is_str_int (value); if (!ret) blk_size = atoi (value); if (ret || (blk_size <= 0)) { if (blk_size < 0) cli_err ("block size is an invalid" " number"); else cli_err ("block size should be an " "integer greater than zero"); ret = -1; goto out; } ret = dict_set_uint32 (dict, "blk-size", (uint32_t)blk_size); } else if (perf && !nfs && !strcmp (key, "count")) { ret = gf_is_str_int (value); if (!ret) count = atoi(value); if (ret || (count <= 0)) { if (count < 0) cli_err ("count is an invalid number"); else cli_err ("count should be an integer " "greater than zero"); ret = -1; goto out; } ret = dict_set_uint32 (dict, "blk-cnt", count); } else { ret = -1; goto out; } if (ret) { gf_log ("", GF_LOG_WARNING, "Dict set failed for " "key %s", key); goto out; } } if (list_cnt == -1) list_cnt = 100; ret = dict_set_int32 (dict, "list-cnt", list_cnt); if (ret) { gf_log ("", GF_LOG_WARNING, "Dict set failed for list_cnt"); goto out; } if ((blk_size > 0) ^ (count > 0)) { cli_err ("Need to give both 'bs' and 'count'"); ret = -1; goto out; } else if (((uint64_t)blk_size * count) > (10 * GF_UNIT_GB)) { cli_err ("'bs * count' value %"PRIu64" is greater than " "maximum allowed value of 10GB", ((uint64_t)blk_size * count)); ret = -1; goto out; } *options = dict; out: if (ret && dict) dict_unref (dict); return ret; } uint32_t cli_cmd_get_statusop (const char *arg) { int i = 0; uint32_t ret = GF_CLI_STATUS_NONE; char *w = NULL; char *opwords[] = {"detail", "mem", "clients", "fd", "inode", "callpool", "tasks", "client-list", NULL}; struct { char *opname; uint32_t opcode; } optable[] = { { "detail", GF_CLI_STATUS_DETAIL }, { "mem", GF_CLI_STATUS_MEM }, { "clients", GF_CLI_STATUS_CLIENTS }, { "fd", GF_CLI_STATUS_FD }, { "inode", GF_CLI_STATUS_INODE }, { "callpool", GF_CLI_STATUS_CALLPOOL }, { "tasks", GF_CLI_STATUS_TASKS }, { "client-list", GF_CLI_STATUS_CLIENT_LIST }, { NULL } }; w = str_getunamb (arg, opwords); if (!w) { gf_log ("cli", GF_LOG_DEBUG, "Not a status op %s", arg); goto out; } for (i = 0; optable[i].opname; i++) { if (!strcmp (w, optable[i].opname)) { ret = optable[i].opcode; break; } } out: return ret; } int cli_cmd_volume_status_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; int ret = -1; uint32_t cmd = 0; GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; switch (wordcount) { case 2: cmd = GF_CLI_STATUS_ALL; ret = 0; break; case 3: if (!strcmp (words[2], "all")) { cmd = GF_CLI_STATUS_ALL; ret = 0; } else { cmd = GF_CLI_STATUS_VOL; ret = dict_set_str (dict, "volname", (char *)words[2]); } break; case 4: cmd = cli_cmd_get_statusop (words[3]); if (!strcmp (words[2], "all")) { if (cmd == GF_CLI_STATUS_NONE) { cli_err ("%s is not a valid status option", words[3]); ret = -1; goto out; } cmd |= GF_CLI_STATUS_ALL; ret = 0; } else { ret = dict_set_str (dict, "volname", (char *)words[2]); if (ret) goto out; if (cmd == GF_CLI_STATUS_NONE) { if (!strcmp (words[3], "nfs")) { cmd |= GF_CLI_STATUS_NFS; } else if (!strcmp (words[3], "shd")) { cmd |= GF_CLI_STATUS_SHD; } else if (!strcmp (words[3], "quotad")) { cmd |= GF_CLI_STATUS_QUOTAD; } else if (!strcmp (words[3], "snapd")) { cmd |= GF_CLI_STATUS_SNAPD; } else if (!strcmp (words[3], "tierd")) { cmd |= GF_CLI_STATUS_TIERD; } else if (!strcmp (words[3], "bitd")) { cmd |= GF_CLI_STATUS_BITD; } else if (!strcmp (words[3], "scrub")) { cmd |= GF_CLI_STATUS_SCRUB; } else { cmd = GF_CLI_STATUS_BRICK; ret = dict_set_str (dict, "brick", (char *)words[3]); } } else { cmd |= GF_CLI_STATUS_VOL; ret = 0; } } break; case 5: if (!strcmp (words[2], "all")) { cli_err ("Cannot specify brick/nfs for \"all\""); ret = -1; goto out; } cmd = cli_cmd_get_statusop (words[4]); if (cmd == GF_CLI_STATUS_NONE) { cli_err ("%s is not a valid status option", words[4]); ret = -1; goto out; } ret = dict_set_str (dict, "volname", (char *)words[2]); if (ret) goto out; if (!strcmp (words[3], "nfs")) { if (cmd == GF_CLI_STATUS_FD || cmd == GF_CLI_STATUS_DETAIL || cmd == GF_CLI_STATUS_TASKS) { cli_err ("Detail/FD/Tasks status not available" " for NFS Servers"); ret = -1; goto out; } cmd |= GF_CLI_STATUS_NFS; } else if (!strcmp (words[3], "shd")){ if (cmd == GF_CLI_STATUS_FD || cmd == GF_CLI_STATUS_CLIENTS || cmd == GF_CLI_STATUS_DETAIL || cmd == GF_CLI_STATUS_TASKS) { cli_err ("Detail/FD/Clients/Tasks status not " "available for Self-heal Daemons"); ret = -1; goto out; } cmd |= GF_CLI_STATUS_SHD; } else if (!strcmp (words[3], "quotad")) { if (cmd == GF_CLI_STATUS_FD || cmd == GF_CLI_STATUS_CLIENTS || cmd == GF_CLI_STATUS_DETAIL || cmd == GF_CLI_STATUS_INODE) { cli_err ("Detail/FD/Clients/Inode status not " "available for Quota Daemon"); ret = -1; goto out; } cmd |= GF_CLI_STATUS_QUOTAD; } else if (!strcmp (words[3], "snapd")) { if (cmd == GF_CLI_STATUS_FD || cmd == GF_CLI_STATUS_CLIENTS || cmd == GF_CLI_STATUS_DETAIL || cmd == GF_CLI_STATUS_INODE) { cli_err ("Detail/FD/Clients/Inode status not " "available for snap daemon"); ret = -1; goto out; } cmd |= GF_CLI_STATUS_SNAPD; } else if (!strcmp (words[3], "tierd")) { if (cmd == GF_CLI_STATUS_FD || cmd == GF_CLI_STATUS_CLIENTS || cmd == GF_CLI_STATUS_DETAIL || cmd == GF_CLI_STATUS_INODE) { cli_err ("Detail/FD/Clients/Inode status not " "available for tier daemon"); ret = -1; goto out; } cmd |= GF_CLI_STATUS_TIERD; } else { if (cmd == GF_CLI_STATUS_TASKS) { cli_err ("Tasks status not available for " "bricks"); ret = -1; goto out; } cmd |= GF_CLI_STATUS_BRICK; ret = dict_set_str (dict, "brick", (char *)words[3]); } break; default: goto out; } if (ret) goto out; ret = dict_set_int32 (dict, "cmd", cmd); if (ret) goto out; *options = dict; out: if (ret && dict) dict_unref (dict); return ret; } gf_boolean_t cli_cmd_validate_dumpoption (const char *arg, char **option) { char *opwords[] = {"all", "nfs", "mem", "iobuf", "callpool", "priv", "fd", "inode", "history", "inodectx", "fdctx", "quotad", NULL}; char *w = NULL; w = str_getunamb (arg, opwords); if (!w) { gf_log ("cli", GF_LOG_DEBUG, "Unknown statedump option %s", arg); return _gf_false; } *option = w; return _gf_true; } int cli_cmd_volume_statedump_options_parse (const char **words, int wordcount, dict_t **options) { int ret = 0; int i = 0; dict_t *dict = NULL; int option_cnt = 0; char *option = NULL; char option_str[_POSIX_HOST_NAME_MAX + 100] = {0,}; char *tmp = NULL; char *ip_addr = NULL; char *pid = NULL; if ((wordcount >= 5) && ((strcmp (words[3], "client")) == 0)) { tmp = gf_strdup(words[4]); if (!tmp) { ret = -1; goto out; } ip_addr = strtok(tmp, ":"); pid = strtok(NULL, ":"); if (valid_internet_address (ip_addr, _gf_true) && pid && gf_valid_pid (pid, strlen(pid))) { strncat (option_str, words[3], strlen (words[3])); strncat (option_str, " ", 1); strncat (option_str, ip_addr, strlen (ip_addr)); strncat (option_str, " ", 1); strncat (option_str, pid, strlen (pid)); option_cnt = 3; } else { ret = -1; goto out; } } else { for (i = 3; i < wordcount; i++, option_cnt++) { if (!cli_cmd_validate_dumpoption (words[i], &option)) { ret = -1; goto out; } strncat (option_str, option, strlen (option)); strncat (option_str, " ", 1); } if ((strstr (option_str, "nfs")) && strstr (option_str, "quotad")) { ret = -1; goto out; } } dict = dict_new (); if (!dict) goto out; ret = dict_set_dynstr (dict, "options", gf_strdup (option_str)); if (ret) goto out; ret = dict_set_int32 (dict, "option_cnt", option_cnt); if (ret) goto out; *options = dict; out: GF_FREE (tmp); if (ret && dict) dict_unref (dict); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error parsing dumpoptions"); return ret; } int cli_cmd_volume_clrlks_opts_parse (const char **words, int wordcount, dict_t **options) { int ret = -1; int i = 0; dict_t *dict = NULL; char *kind_opts[4] = {"blocked", "granted", "all", NULL}; char *types[4] = {"inode", "entry", "posix", NULL}; char *free_ptr = NULL; dict = dict_new (); if (!dict) goto out; if (strcmp (words[4], "kind")) goto out; for (i = 0; kind_opts[i]; i++) { if (!strcmp (words[5], kind_opts[i])) { free_ptr = gf_strdup (words[5]); ret = dict_set_dynstr (dict, "kind", free_ptr); if (ret) goto out; free_ptr = NULL; break; } } if (i == 3) goto out; ret = -1; for (i = 0; types[i]; i++) { if (!strcmp (words[6], types[i])) { free_ptr = gf_strdup (words[6]); ret = dict_set_dynstr (dict, "type", free_ptr); if (ret) goto out; free_ptr = NULL; break; } } if (i == 3) goto out; if (wordcount == 8) { free_ptr = gf_strdup (words[7]); ret = dict_set_dynstr (dict, "opts", free_ptr); if (ret) goto out; free_ptr = NULL; } ret = 0; *options = dict; out: if (ret) { GF_FREE (free_ptr); dict_unref (dict); } return ret; } static int extract_hostname_path_from_token (const char *tmp_words, char **hostname, char **path) { int ret = 0; char *delimiter = NULL; char *tmp_host = NULL; char *host_name = NULL; char *words = NULL; *hostname = NULL; *path = NULL; words = GF_CALLOC (1, strlen (tmp_words) + 1, gf_common_mt_char); if (!words){ ret = -1; goto out; } strncpy (words, tmp_words, strlen (tmp_words) + 1); if (validate_brick_name (words)) { cli_err ("Wrong brick type: %s, use :" "", words); ret = -1; goto out; } else { delimiter = strrchr (words, ':'); ret = gf_canonicalize_path (delimiter + 1); if (ret) { goto out; } else { *path = GF_CALLOC (1, strlen (delimiter+1) +1, gf_common_mt_char); if (!*path) { ret = -1; goto out; } strncpy (*path, delimiter +1, strlen(delimiter + 1) + 1); } } tmp_host = gf_strdup (words); if (!tmp_host) { gf_log ("cli", GF_LOG_ERROR, "Out of memory"); ret = -1; goto out; } get_host_name (tmp_host, &host_name); if (!host_name) { ret = -1; gf_log("cli",GF_LOG_ERROR, "Unable to allocate " "memory"); goto out; } if (!(strcmp (host_name, "localhost") && strcmp (host_name, "127.0.0.1") && strncmp (host_name, "0.", 2))) { cli_err ("Please provide a valid hostname/ip other " "than localhost, 127.0.0.1 or loopback " "address (0.0.0.0 to 0.255.255.255)."); ret = -1; goto out; } if (!valid_internet_address (host_name, _gf_false)) { cli_err ("internet address '%s' does not conform to " "standards", host_name); ret = -1; goto out; } *hostname = GF_CALLOC (1, strlen (host_name) + 1, gf_common_mt_char); if (!*hostname) { ret = -1; goto out; } strncpy (*hostname, host_name, strlen (host_name) + 1); ret = 0; out: GF_FREE (words); GF_FREE (tmp_host); return ret; } static int set_hostname_path_in_dict (const char *token, dict_t *dict, int heal_op) { char *hostname = NULL; char *path = NULL; int ret = 0; ret = extract_hostname_path_from_token (token, &hostname, &path); if (ret) goto out; switch (heal_op) { case GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK: ret = dict_set_dynstr (dict, "heal-source-hostname", hostname); if (ret) goto out; ret = dict_set_dynstr (dict, "heal-source-brickpath", path); break; case GF_SHD_OP_STATISTICS_HEAL_COUNT_PER_REPLICA: ret = dict_set_dynstr (dict, "per-replica-cmd-hostname", hostname); if (ret) goto out; ret = dict_set_dynstr (dict, "per-replica-cmd-path", path); break; default: ret = -1; break; } out: return ret; } static int heal_command_type_get (const char *command) { int i = 0; /* subcommands are set as NULL */ char *heal_cmds[GF_SHD_OP_HEAL_DISABLE + 1] = { [GF_SHD_OP_INVALID] = NULL, [GF_SHD_OP_HEAL_INDEX] = NULL, [GF_SHD_OP_HEAL_FULL] = "full", [GF_SHD_OP_INDEX_SUMMARY] = "info", [GF_SHD_OP_HEALED_FILES] = NULL, [GF_SHD_OP_HEAL_FAILED_FILES] = NULL, [GF_SHD_OP_SPLIT_BRAIN_FILES] = NULL, [GF_SHD_OP_STATISTICS] = "statistics", [GF_SHD_OP_STATISTICS_HEAL_COUNT] = NULL, [GF_SHD_OP_STATISTICS_HEAL_COUNT_PER_REPLICA] = NULL, [GF_SHD_OP_SBRAIN_HEAL_FROM_BIGGER_FILE] = NULL, [GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK] = NULL, [GF_SHD_OP_HEAL_ENABLE] = "enable", [GF_SHD_OP_HEAL_DISABLE] = "disable", }; for (i = 0; i <= GF_SHD_OP_HEAL_DISABLE; i++) { if (heal_cmds[i] && (strcmp (heal_cmds[i], command) == 0)) return i; } return GF_SHD_OP_INVALID; } int cli_cmd_volume_heal_options_parse (const char **words, int wordcount, dict_t **options) { int ret = 0; dict_t *dict = NULL; gf_xl_afr_op_t op = GF_SHD_OP_INVALID; dict = dict_new (); if (!dict) goto out; ret = dict_set_str (dict, "volname", (char *) words[2]); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "failed to set volname"); goto out; } if (wordcount == 3) { ret = dict_set_int32 (dict, "heal-op", GF_SHD_OP_HEAL_INDEX); goto done; } if (wordcount == 4) { op = heal_command_type_get (words[3]); if (op == GF_SHD_OP_INVALID) { ret = -1; goto out; } ret = dict_set_int32 (dict, "heal-op", op); goto done; } if (wordcount == 5) { if (strcmp (words[3], "info") && strcmp (words[3], "statistics") && strcmp (words[3], "granular-entry-heal")) { ret = -1; goto out; } if (!strcmp (words[3], "info")) { if (!strcmp (words[4], "split-brain")) { ret = dict_set_int32 (dict, "heal-op", GF_SHD_OP_SPLIT_BRAIN_FILES); goto done; } if (!strcmp (words[4], "summary")) { ret = dict_set_int32 (dict, "heal-op", GF_SHD_OP_HEAL_SUMMARY); goto done; } } if (!strcmp (words[3], "statistics")) { if (!strcmp (words[4], "heal-count")) { ret = dict_set_int32 (dict, "heal-op", GF_SHD_OP_STATISTICS_HEAL_COUNT); goto done; } } if (!strcmp (words[3], "granular-entry-heal")) { if (!strcmp (words[4], "enable")) { ret = dict_set_int32 (dict, "heal-op", GF_SHD_OP_GRANULAR_ENTRY_HEAL_ENABLE); goto done; } else if (!strcmp (words[4], "disable")) { ret = dict_set_int32 (dict, "heal-op", GF_SHD_OP_GRANULAR_ENTRY_HEAL_DISABLE); goto done; } } ret = -1; goto out; } if (wordcount == 6) { if (strcmp (words[3], "split-brain")) { ret = -1; goto out; } if (!strcmp (words[4], "bigger-file")) { ret = dict_set_int32 (dict, "heal-op", GF_SHD_OP_SBRAIN_HEAL_FROM_BIGGER_FILE); if (ret) goto out; ret = dict_set_str (dict, "file", (char *)words[5]); if (ret) goto out; goto done; } if (!strcmp (words[4], "latest-mtime")) { ret = dict_set_int32 (dict, "heal-op", GF_SHD_OP_SBRAIN_HEAL_FROM_LATEST_MTIME); if (ret) goto out; ret = dict_set_str (dict, "file", (char *)words[5]); if (ret) goto out; goto done; } if (!strcmp (words[4], "source-brick")) { ret = dict_set_int32 (dict, "heal-op", GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK); if (ret) goto out; ret = set_hostname_path_in_dict (words[5], dict, GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK); if (ret) goto out; goto done; } ret = -1; goto out; } if (wordcount == 7) { if (!strcmp (words[3], "statistics") && !strcmp (words[4], "heal-count") && !strcmp (words[5], "replica")) { ret = dict_set_int32 (dict, "heal-op", GF_SHD_OP_STATISTICS_HEAL_COUNT_PER_REPLICA); if (ret) goto out; ret = set_hostname_path_in_dict (words[6], dict, GF_SHD_OP_STATISTICS_HEAL_COUNT_PER_REPLICA); if (ret) goto out; goto done; } if (!strcmp (words[3], "split-brain") && !strcmp (words[4], "source-brick")) { ret = dict_set_int32 (dict, "heal-op", GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK); ret = set_hostname_path_in_dict (words[5], dict, GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK); if (ret) goto out; ret = dict_set_str (dict, "file", (char *) words[6]); if (ret) goto out; goto done; } } ret = -1; goto out; done: *options = dict; out: if (ret && dict) { dict_unref (dict); *options = NULL; } return ret; } int cli_cmd_volume_old_tier_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; int ret = -1; char *volname = NULL; gf_cli_defrag_type cmd = 0; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; if (wordcount != 4) goto out; if ((strcmp (words[1], "tier") == 0) && (strcmp (words[3], "start") == 0)) { cmd = GF_DEFRAG_CMD_START_TIER; } else goto out; volname = (char *) words[2]; ret = dict_set_str (dict, "volname", volname); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "failed to set dict"); goto out; } ret = dict_set_int32 (dict, "rebalance-command", (int32_t) cmd); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "failed to set dict"); goto out; } *options = dict; out: if (ret && dict) dict_unref (dict); return ret; } int cli_cmd_volume_defrag_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; int ret = -1; char *option = NULL; char *volname = NULL; char *command = NULL; gf_cli_defrag_type cmd = 0; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; if (!((wordcount == 4) || (wordcount == 5))) goto out; if (wordcount == 4) { if (strcmp (words[3], "start") && strcmp (words[3], "stop") && strcmp (words[3], "status")) goto out; } else { if (strcmp (words[3], "fix-layout") && strcmp (words[3], "start")) goto out; } volname = (char *) words[2]; if (wordcount == 4) { command = (char *) words[3]; } if (wordcount == 5) { if ((strcmp (words[3], "fix-layout") || strcmp (words[4], "start")) && (strcmp (words[3], "start") || strcmp (words[4], "force"))) { ret = -1; goto out; } command = (char *) words[3]; option = (char *) words[4]; } if (strcmp (command, "start") == 0) { cmd = GF_DEFRAG_CMD_START; if (option && strcmp (option, "force") == 0) { cmd = GF_DEFRAG_CMD_START_FORCE; } goto done; } if (strcmp (command, "fix-layout") == 0) { cmd = GF_DEFRAG_CMD_START_LAYOUT_FIX; goto done; } if (strcmp (command, "stop") == 0) { cmd = GF_DEFRAG_CMD_STOP; goto done; } if (strcmp (command, "status") == 0) { cmd = GF_DEFRAG_CMD_STATUS; } done: ret = dict_set_str (dict, "volname", volname); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "failed to set dict"); goto out; } ret = dict_set_int32 (dict, "rebalance-command", (int32_t) cmd); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "failed to set dict"); goto out; } *options = dict; out: if (ret && dict) dict_unref (dict); return ret; } int32_t cli_snap_create_desc_parse (dict_t *dict, const char **words, size_t wordcount, int32_t desc_opt_loc) { int32_t ret = -1; char *desc = NULL; int32_t desc_len = 0; desc = GF_CALLOC (MAX_SNAP_DESCRIPTION_LEN + 1, sizeof(char), gf_common_mt_char); if (!desc) { ret = -1; goto out; } if (strlen (words[desc_opt_loc]) >= MAX_SNAP_DESCRIPTION_LEN) { cli_out ("snapshot create: description truncated: " "Description provided is longer than 1024 characters"); desc_len = MAX_SNAP_DESCRIPTION_LEN; } else { desc_len = strlen (words[desc_opt_loc]); } strncpy (desc, words[desc_opt_loc], desc_len); desc[desc_len] = '\0'; /* Calculating the size of the description as given by the user */ ret = dict_set_dynstr (dict, "description", desc); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to save snap " "description"); goto out; } ret = 0; out: if (ret && desc) GF_FREE (desc); return ret; } /* Function to check whether the Volume name is repeated */ int cli_check_if_volname_repeated (const char **words, unsigned int start_index, uint64_t cur_index) { uint64_t i = -1; int ret = 0; GF_ASSERT (words); for (i = start_index ; i < cur_index ; i++) { if (strcmp (words[i], words[cur_index]) == 0) { ret = -1; goto out; } } out: return ret; } /* snapshot clone * @arg-0, dict : Request Dictionary to be sent to server side. * @arg-1, words : Contains individual words of CLI command. * @arg-2, wordcount: Contains number of words present in the CLI command. * * return value : -1 on failure * 0 on success */ int cli_snap_clone_parse (dict_t *dict, const char **words, int wordcount) { uint64_t i = 0; int ret = -1; char *clonename = NULL; unsigned int cmdi = 2; /* cmdi is command index, here cmdi is "2" (gluster snapshot clone)*/ GF_ASSERT (words); GF_ASSERT (dict); if (wordcount == cmdi + 1) { cli_err ("Invalid Syntax."); gf_log ("cli", GF_LOG_ERROR, "Invalid number of words for snap clone command"); goto out; } if (strlen(words[cmdi]) >= GLUSTERD_MAX_SNAP_NAME) { cli_err ("snapshot clone: failed: clonename cannot exceed " "255 characters."); gf_log ("cli", GF_LOG_ERROR, "Clone name too long"); goto out; } clonename = (char *) words[cmdi]; for (i = 0 ; i < strlen (clonename); i++) { /* Following volume name convention */ if (!isalnum (clonename[i]) && (clonename[i] != '_' && (clonename[i] != '-'))) { /* TODO : Is this message enough?? */ cli_err ("Clonename can contain only alphanumeric, " "\"-\" and \"_\" characters"); goto out; } } ret = dict_set_int32 (dict, "volcount", 1); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save volcount"); goto out; } ret = dict_set_str (dict, "clonename", (char *)words[cmdi]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save clone " "name(%s)", (char *)words[cmdi]); goto out; } /* Filling snap name in the dictionary */ ret = dict_set_str (dict, "snapname", (char *)words[cmdi+1]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not " "save snap name(%s)", (char *)words[cmdi+1]); goto out; } ret = 0; out: return ret; } /* snapshot create [description ] * [force] * @arg-0, dict : Request Dictionary to be sent to server side. * @arg-1, words : Contains individual words of CLI command. * @arg-2, wordcount: Contains number of words present in the CLI command. * * return value : -1 on failure * 0 on success */ int cli_snap_create_parse (dict_t *dict, const char **words, int wordcount) { uint64_t i = 0; int ret = -1; uint64_t volcount = 0; char key[PATH_MAX] = ""; char *snapname = NULL; unsigned int cmdi = 2; int flags = 0; /* cmdi is command index, here cmdi is "2" (gluster snapshot create)*/ GF_ASSERT (words); GF_ASSERT (dict); if (wordcount <= cmdi + 1) { cli_err ("Invalid Syntax."); gf_log ("cli", GF_LOG_ERROR, "Too less words for snap create command"); goto out; } if (strlen(words[cmdi]) >= GLUSTERD_MAX_SNAP_NAME) { cli_err ("snapshot create: failed: snapname cannot exceed " "255 characters."); gf_log ("cli", GF_LOG_ERROR, "Snapname too long"); goto out; } snapname = (char *) words[cmdi]; for (i = 0 ; i < strlen (snapname); i++) { /* Following volume name convention */ if (!isalnum (snapname[i]) && (snapname[i] != '_' && (snapname[i] != '-'))) { /* TODO : Is this message enough?? */ cli_err ("Snapname can contain only alphanumeric, " "\"-\" and \"_\" characters"); goto out; } } ret = dict_set_str (dict, "snapname", (char *)words[cmdi]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save snap " "name(%s)", (char *)words[cmdi]); goto out; } /* Filling volume name in the dictionary */ for (i = cmdi + 1 ; i < wordcount && (strcmp (words[i], "description")) != 0 && (strcmp (words[i], "force") != 0) && (strcmp (words[i], "no-timestamp") != 0); i++) { volcount++; /* volume index starts from 1 */ ret = snprintf (key, sizeof (key), "volname%"PRIu64, volcount); if (ret < 0) { goto out; } ret = dict_set_str (dict, key, (char *)words[i]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not " "save volume name(%s)", (char *)words[i]); goto out; } if (i >= cmdi + 2) { ret = -1; cli_err("Creating multiple volume snapshot is not " "supported as of now"); goto out; } /* TODO : remove this above condition check once * multiple volume snapshot is supported */ } if (volcount == 0) { ret = -1; cli_err ("Please provide the volume name"); gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = dict_set_int32 (dict, "volcount", volcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save volcount"); goto out; } /* Verify how we got out of "for" loop, * if it is by reaching wordcount limit then goto "out", * because we need not parse for "description","force" and * "no-timestamp" after this. */ if (i == wordcount) { goto out; } if (strcmp (words[i], "no-timestamp") == 0) { ret = dict_set_str (dict, "no-timestamp", "true"); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save " "time-stamp option"); } if (i == (wordcount-1)) goto out; i++; } if ((strcmp (words[i], "description")) == 0) { ++i; if (i > (wordcount - 1)) { ret = -1; cli_err ("Please provide a description"); gf_log ("cli", GF_LOG_ERROR, "Description not provided"); goto out; } ret = cli_snap_create_desc_parse(dict, words, wordcount, i); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save snap " "description"); goto out; } if (i == (wordcount - 1)) goto out; i++; /* point the index to next word. * As description might be follwed by force option. * Before that, check if wordcount limit is reached */ } if (strcmp (words[i], "force") == 0) { flags = GF_CLI_FLAG_OP_FORCE; } else { ret = -1; cli_err ("Invalid Syntax."); gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } /* Check if the command has anything after "force" keyword */ if (++i < wordcount) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = 0; out: if(ret == 0) { /*Adding force flag in either of the case i.e force set * or unset*/ ret = dict_set_int32 (dict, "flags", flags); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save " "snap force option"); } } return ret; } /* snapshot list [volname] * @arg-0, dict : Request Dictionary to be sent to server side. * @arg-1, words : Contains individual words of CLI command. * @arg-2, wordcount: Contains number of words present in the CLI command. * * return value : -1 on failure * 0 on success */ int cli_snap_list_parse (dict_t *dict, const char **words, int wordcount) { int ret = -1; GF_ASSERT (words); GF_ASSERT (dict); if (wordcount < 2 || wordcount > 3) { gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } if (wordcount == 2) { ret = 0; goto out; } ret = dict_set_str (dict, "volname", (char *)words[2]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to save volname in dictionary"); goto out; } out: return ret; } /* snapshot info [(snapname | volume )] * @arg-0, dict : Request Dictionary to be sent to server side. * @arg-1, words : Contains individual words of CLI command. * @arg-2, wordcount: Contains number of words present in the CLI command. * * return value : -1 on failure * 0 on success */ int cli_snap_info_parse (dict_t *dict, const char **words, int wordcount) { int ret = -1; int32_t cmd = GF_SNAP_INFO_TYPE_ALL; unsigned int cmdi = 2; /* cmdi is command index, here cmdi is "2" (gluster snapshot info)*/ GF_ASSERT (words); GF_ASSERT (dict); if (wordcount > 4 || wordcount < cmdi) { gf_log ("cli", GF_LOG_ERROR, "Invalid syntax"); goto out; } if (wordcount == cmdi) { ret = 0; goto out; } /* If 3rd word is not "volume", then it must * be snapname. */ if (strcmp (words[cmdi], "volume") != 0) { ret = dict_set_str (dict, "snapname", (char *)words[cmdi]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to save " "snapname %s", words[cmdi]); goto out; } /* Once snap name is parsed, if we encounter any other * word then fail it. Invalid Syntax. * example : snapshot info word */ if ((cmdi + 1) != wordcount) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } cmd = GF_SNAP_INFO_TYPE_SNAP; ret = 0; goto out; /* No need to continue the parsing once we * get the snapname */ } /* If 3rd word is "volume", then check if next word * is present. As, "snapshot info volume" is an * invalid command. */ if ((cmdi + 1) == wordcount) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = dict_set_str (dict, "volname", (char *)words[wordcount - 1]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save " "volume name %s", words[wordcount - 1]); goto out; } cmd = GF_SNAP_INFO_TYPE_VOL; out: if (ret == 0) { ret = dict_set_int32 (dict, "sub-cmd", cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save " "type of snapshot info"); } } return ret; } /* snapshot restore * @arg-0, dict : Request Dictionary to be sent to server side. * @arg-1, words : Contains individual words of CLI command. * @arg-2, wordcount: Contains number of words present in the CLI command. * * return value : -1 on failure * 0 on success */ int cli_snap_restore_parse (dict_t *dict, const char **words, int wordcount, struct cli_state *state) { int ret = -1; const char *question = NULL; gf_answer_t answer = GF_ANSWER_NO; GF_ASSERT (words); GF_ASSERT (dict); if (wordcount != 3) { gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = dict_set_str (dict, "snapname", (char *)words[2]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to save snap-name %s", words[2]); goto out; } question = "Restore operation will replace the " "original volume with the snapshotted volume. " "Do you still want to continue?"; answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 1; gf_log ("cli", GF_LOG_ERROR, "User cancelled a snapshot " "restore operation for snap %s", (char *)words[2]); goto out; } out: return ret; } /* snapshot activate [force] * @arg-0, dict : Request Dictionary to be sent to server side. * @arg-1, words : Contains individual words of CLI command. * @arg-2, wordcount: Contains number of words present in the CLI command. * * return value : -1 on failure * 0 on success */ int cli_snap_activate_parse (dict_t *dict, const char **words, int wordcount) { int ret = -1; int flags = 0; GF_ASSERT (words); GF_ASSERT (dict); if ((wordcount < 3) || (wordcount > 4)) { gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = dict_set_str (dict, "snapname", (char *)words[2]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to save snap-name %s", words[2]); goto out; } if (wordcount == 4) { if (!strcmp("force", (char *)words[3])) { flags = GF_CLI_FLAG_OP_FORCE; } else { gf_log ("cli", GF_LOG_ERROR, "Invalid option"); ret = -1; goto out; } } ret = dict_set_int32 (dict, "flags", flags); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to save force option"); goto out; } out: return ret; } /* snapshot deactivate * @arg-0, dict : Request Dictionary to be sent to server side. * @arg-1, words : Contains individual words of CLI command. * @arg-2, wordcount: Contains number of words present in the CLI command. * * return value : -1 on failure * 0 on success * 1 if user cancelled the request */ int cli_snap_deactivate_parse (dict_t *dict, const char **words, int wordcount, struct cli_state *state) { int ret = -1; gf_answer_t answer = GF_ANSWER_NO; const char *question = "Deactivating snap will make its " "data inaccessible. Do you want to " "continue?"; GF_ASSERT (words); GF_ASSERT (dict); if ((wordcount != 3)) { gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = dict_set_str (dict, "snapname", (char *)words[2]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to save snap-name %s", words[2]); goto out; } answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 1; gf_log ("cli", GF_LOG_DEBUG, "User cancelled " "snapshot deactivate operation"); goto out; } out: return ret; } /* snapshot delete (all | snapname | volume ) * @arg-0, dict : Request Dictionary to be sent to server side. * @arg-1, words : Contains individual words of CLI command. * @arg-2, wordcount: Contains number of words present in the CLI command. * * return value : -1 on failure * 0 on success * 1 if user cancel the operation */ int cli_snap_delete_parse (dict_t *dict, const char **words, int wordcount, struct cli_state *state) { int ret = -1; const char *question = NULL; int32_t cmd = -1; unsigned int cmdi = 2; gf_answer_t answer = GF_ANSWER_NO; GF_ASSERT (words); GF_ASSERT (dict); if (wordcount > 4 || wordcount <= cmdi) { gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } question = "Deleting snap will erase all the information about " "the snap. Do you still want to continue?"; if (strcmp (words [cmdi], "all") == 0) { ret = 0; cmd = GF_SNAP_DELETE_TYPE_ALL; } else if (strcmp (words [cmdi], "volume") == 0) { if (++cmdi == wordcount) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = dict_set_str (dict, "volname", (char *)words[cmdi]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save " "volume name %s", words[wordcount - 1]); goto out; } cmd = GF_SNAP_DELETE_TYPE_VOL; } else { ret = dict_set_str (dict, "snapname", (char *)words[cmdi]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to save " "snapname %s", words[2]); goto out; } cmd = GF_SNAP_DELETE_TYPE_SNAP; } if ((cmdi + 1) != wordcount) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } if (cmd == GF_SNAP_DELETE_TYPE_SNAP) { answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 1; gf_log ("cli", GF_LOG_DEBUG, "User cancelled " "snapshot delete operation for snap %s", (char *)words[2]); goto out; } } ret = dict_set_int32 (dict, "sub-cmd", cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save " "type of snapshot delete"); } out: return ret; } /* snapshot status [(snapname | volume )] * @arg-0, dict : Request Dictionary to be sent to server side. * @arg-1, words : Contains individual words of CLI command. * @arg-2, wordcount: Contains number of words present in the CLI command. * * return value : -1 on failure * 0 on success */ int cli_snap_status_parse (dict_t *dict, const char **words, int wordcount) { int ret = -1; int32_t cmd = GF_SNAP_STATUS_TYPE_ALL; unsigned int cmdi = 2; /* cmdi is command index, here cmdi is "2" (gluster snapshot status)*/ GF_ASSERT (words); GF_ASSERT (dict); if (wordcount > 4 || wordcount < cmdi) { gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } if (wordcount == cmdi) { ret = 0; goto out; } /* if 3rd word is not "volume", then it must be "snapname" */ if (strcmp (words[cmdi], "volume") != 0) { ret = dict_set_str (dict, "snapname", (char *)words[cmdi]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Count not save " "snap name %s", words[cmdi]); goto out; } if ((cmdi + 1) != wordcount) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = 0; cmd = GF_SNAP_STATUS_TYPE_SNAP; goto out; } /* If 3rd word is "volume", then check if next word is present. * As, "snapshot info volume" is an invalid command */ if ((cmdi + 1) == wordcount) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = dict_set_str (dict, "volname", (char *)words [wordcount - 1]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Count not save " "volume name %s", words[wordcount - 1]); goto out; } cmd = GF_SNAP_STATUS_TYPE_VOL; out: if (ret == 0) { ret = dict_set_int32 (dict, "sub-cmd", cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not save cmd " "of snapshot status"); } } return ret; } /* return value: * -1 in case of failure. * 0 in case of success. */ int32_t cli_snap_config_limit_parse (const char **words, dict_t *dict, unsigned int wordcount, unsigned int index, char *key) { int ret = -1; int limit = 0; char *end_ptr = NULL; GF_ASSERT (words); GF_ASSERT (dict); GF_ASSERT (key); if (index >= wordcount) { ret = -1; cli_err ("Please provide a value for %s.", key); gf_log ("cli", GF_LOG_ERROR, "Value not provided for %s", key); goto out; } limit = strtol (words[index], &end_ptr, 10); if (limit <= 0 || strcmp (end_ptr, "") != 0) { ret = -1; cli_err("Please enter an integer value " "greater than zero for %s", key); goto out; } ret = dict_set_int32 (dict, key, limit); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not set " "%s in dictionary", key); goto out; } ret = dict_set_dynstr_with_alloc (dict, "globalname", "All"); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not set global key"); goto out; } ret = dict_set_int32 (dict, "hold_global_locks", _gf_true); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not set global locks"); goto out; } out: return ret; } /* function cli_snap_config_parse * Config Syntax : gluster snapshot config [volname] * [snap-max-hard-limit ] * [snap-max-soft-limit ] * return value: <0 on failure 1 if user cancels the operation, or limit value is out of range 0 on success NOTE : snap-max-soft-limit can only be set for system. */ int32_t cli_snap_config_parse (const char **words, int wordcount, dict_t *dict, struct cli_state *state) { int ret = -1; gf_answer_t answer = GF_ANSWER_NO; gf_boolean_t vol_presence = _gf_false; struct snap_config_opt_vals_ *conf_vals = NULL; int8_t hard_limit = 0; int8_t soft_limit = 0; int8_t config_type = -1; const char *question = NULL; unsigned int cmdi = 2; /* cmdi is command index, here cmdi is "2" (gluster snapshot config)*/ GF_ASSERT (words); GF_ASSERT (dict); GF_ASSERT (state); if ((wordcount < 2) || (wordcount > 7)) { gf_log ("cli", GF_LOG_ERROR, "Invalid wordcount(%d)", wordcount); goto out; } if (wordcount == 2) { config_type = GF_SNAP_CONFIG_DISPLAY; ret = 0; goto set; } /* auto-delete cannot be a volume name */ /* Check whether the 3rd word is volname */ if (strcmp (words[cmdi], "snap-max-hard-limit") != 0 && strcmp (words[cmdi], "snap-max-soft-limit") != 0 && strcmp (words[cmdi], "auto-delete") != 0 && strcmp (words[cmdi], "activate-on-create") != 0) { ret = dict_set_str (dict, "volname", (char *)words[cmdi]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set volname"); goto out; } cmdi++; vol_presence = _gf_true; if (cmdi == wordcount) { config_type = GF_SNAP_CONFIG_DISPLAY; ret = 0; goto set; } } config_type = GF_SNAP_CONFIG_TYPE_SET; if (strcmp (words[cmdi], "snap-max-hard-limit") == 0) { ret = cli_snap_config_limit_parse (words, dict, wordcount, ++cmdi, "snap-max-hard-limit"); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to parse snap " "config hard limit"); goto out; } hard_limit = 1; if (++cmdi == wordcount) { ret = 0; goto set; } } if (strcmp (words[cmdi], "snap-max-soft-limit") == 0) { if (vol_presence == 1) { ret = -1; cli_err ("Soft limit cannot be set to individual " "volumes."); gf_log ("cli", GF_LOG_ERROR, "Soft limit cannot be " "set to volumes"); goto out; } ret = cli_snap_config_limit_parse (words, dict, wordcount, ++cmdi, "snap-max-soft-limit"); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to parse snap " "config soft limit"); goto out; } if (++cmdi != wordcount) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } soft_limit = 1; } if (hard_limit || soft_limit) goto set; if (strcmp(words[cmdi], "auto-delete") == 0) { if (vol_presence == 1) { ret = -1; cli_err ("As of now, auto-delete option cannot be set " "to volumes"); gf_log ("cli", GF_LOG_ERROR, "auto-delete option " "cannot be set to volumes"); goto out; } if (++cmdi >= wordcount) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = dict_set_str (dict, "auto-delete", (char *)words[cmdi]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set " "value of auto-delete in request " "dictionary"); goto out; } if (++cmdi != wordcount) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } } else if (strcmp(words[cmdi], "activate-on-create") == 0) { if (vol_presence == 1) { ret = -1; cli_err ("As of now, activate-on-create option " "cannot be set to volumes"); gf_log ("cli", GF_LOG_ERROR, "activate-on-create " "option cannot be set to volumes"); goto out; } if (++cmdi >= wordcount) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = dict_set_str (dict, "snap-activate-on-create", (char *)words[cmdi]); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set value " "of activate-on-create in request dictionary"); goto out; } if (++cmdi != wordcount) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } } else { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = 0; /* Success */ set: ret = dict_set_int32 (dict, "config-command", config_type); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to set " "config-command"); goto out; } if (config_type == GF_SNAP_CONFIG_TYPE_SET && (hard_limit || soft_limit)) { conf_vals = snap_confopt_vals; if (hard_limit && soft_limit) { question = conf_vals[GF_SNAP_CONFIG_SET_BOTH].question; } else if (soft_limit) { question = conf_vals[GF_SNAP_CONFIG_SET_SOFT].question; } else if (hard_limit) { question = conf_vals[GF_SNAP_CONFIG_SET_HARD].question; } answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 1; gf_log ("cli", GF_LOG_DEBUG, "User cancelled " "snapshot config operation"); } } out: return ret; } int validate_op_name (const char *op, const char *opname, char **opwords) { int ret = -1; int i = 0; GF_ASSERT (opname); GF_ASSERT (opwords); for (i = 0 ; opwords[i] != NULL; i++) { if (strcmp (opwords[i], opname) == 0) { cli_out ("\"%s\" cannot be a %s", opname, op); goto out; } } ret = 0; out: return ret; } int32_t cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, struct cli_state *state) { int32_t ret = -1; dict_t *dict = NULL; gf1_cli_snapshot type = GF_SNAP_OPTION_TYPE_NONE; char *w = NULL; char *opwords[] = {"create", "delete", "restore", "activate", "deactivate", "list", "status", "config", "info", "clone", NULL}; char *invalid_snapnames[] = {"description", "force", "volume", "all", NULL}; char *invalid_volnames[] = {"volume", "type", "subvolumes", "option", "end-volume", "all", "volume_not_in_ring", "description", "force", "snap-max-hard-limit", "snap-max-soft-limit", "auto-delete", "activate-on-create", NULL}; GF_ASSERT (words); GF_ASSERT (options); GF_ASSERT (state); dict = dict_new (); if (!dict) goto out; /* Lowest wordcount possible */ if (wordcount < 2) { gf_log ("", GF_LOG_ERROR, "Invalid command: Not enough arguments"); goto out; } w = str_getunamb (words[1], opwords); if (!w) { /* Checks if the operation is a valid operation */ gf_log ("", GF_LOG_ERROR, "Opword Mismatch"); goto out; } if (!strcmp (w, "create")) { type = GF_SNAP_OPTION_TYPE_CREATE; } else if (!strcmp (w, "list")) { type = GF_SNAP_OPTION_TYPE_LIST; } else if (!strcmp (w, "info")) { type = GF_SNAP_OPTION_TYPE_INFO; } else if (!strcmp (w, "delete")) { type = GF_SNAP_OPTION_TYPE_DELETE; } else if (!strcmp (w, "config")) { type = GF_SNAP_OPTION_TYPE_CONFIG; } else if (!strcmp (w, "restore")) { type = GF_SNAP_OPTION_TYPE_RESTORE; } else if (!strcmp (w, "status")) { type = GF_SNAP_OPTION_TYPE_STATUS; } else if (!strcmp (w, "activate")) { type = GF_SNAP_OPTION_TYPE_ACTIVATE; } else if (!strcmp (w, "deactivate")) { type = GF_SNAP_OPTION_TYPE_DEACTIVATE; } else if (!strcmp(w, "clone")) { type = GF_SNAP_OPTION_TYPE_CLONE; } if (type != GF_SNAP_OPTION_TYPE_CONFIG && type != GF_SNAP_OPTION_TYPE_STATUS) { ret = dict_set_int32 (dict, "hold_snap_locks", _gf_true); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to set hold-snap-locks value " "as _gf_true"); goto out; } } /* Following commands does not require volume locks */ if (type == GF_SNAP_OPTION_TYPE_STATUS || type == GF_SNAP_OPTION_TYPE_ACTIVATE || type == GF_SNAP_OPTION_TYPE_DEACTIVATE) { ret = dict_set_int32 (dict, "hold_vol_locks", _gf_false); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Setting volume lock " "flag failed"); goto out; } } /* Check which op is intended */ switch (type) { case GF_SNAP_OPTION_TYPE_CREATE: /* Syntax : * gluster snapshot create * [no-timestamp] * [description ] * [force] */ /* In cases where the snapname is not given then * parsing fails & snapname cannot be "description", * "force" and "volume", that check is made here */ if (wordcount == 2){ ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = validate_op_name ("snapname", words[2], invalid_snapnames); if (ret) { goto out; } ret = cli_snap_create_parse (dict, words, wordcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "create command parsing failed."); goto out; } break; case GF_SNAP_OPTION_TYPE_CLONE: /* Syntax : * gluster snapshot clone */ /* In cases where the clonename is not given then * parsing fails & snapname cannot be "description", * "force" and "volume", that check is made here */ if (wordcount == 2) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } ret = validate_op_name ("clonename", words[2], invalid_volnames); if (ret) { goto out; } ret = cli_snap_clone_parse (dict, words, wordcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "clone command parsing failed."); goto out; } break; case GF_SNAP_OPTION_TYPE_INFO: /* Syntax : * gluster snapshot info [(snapname] | [vol )] */ ret = cli_snap_info_parse (dict, words, wordcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to parse " "snapshot info command"); goto out; } break; case GF_SNAP_OPTION_TYPE_LIST: /* Syntax : * gluster snaphsot list [volname] */ ret = cli_snap_list_parse (dict, words, wordcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to parse " "snapshot list command"); goto out; } break; case GF_SNAP_OPTION_TYPE_DELETE: /* Syntax : * snapshot delete (all | snapname | volume ) */ ret = cli_snap_delete_parse (dict, words, wordcount, state); if (ret) { /* A positive ret value means user cancelled * the command */ if (ret < 0) { gf_log ("cli", GF_LOG_ERROR, "Failed to parse " "snapshot delete command"); } goto out; } break; case GF_SNAP_OPTION_TYPE_CONFIG: /* snapshot config [volname] [snap-max-hard-limit ] * [snap-max-soft-limit ] */ ret = cli_snap_config_parse (words, wordcount, dict, state); if (ret) { if (ret < 0) gf_log ("cli", GF_LOG_ERROR, "config command parsing failed."); goto out; } ret = dict_set_int32 (dict, "type", GF_SNAP_OPTION_TYPE_CONFIG); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to set " "config type"); ret = -1; goto out; } break; case GF_SNAP_OPTION_TYPE_STATUS: { /* Syntax : * gluster snapshot status [(snapname | * volume )] */ ret = cli_snap_status_parse (dict, words, wordcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to parse " "snapshot status command"); goto out; } break; } case GF_SNAP_OPTION_TYPE_RESTORE: /* Syntax: * snapshot restore */ ret = cli_snap_restore_parse (dict, words, wordcount, state); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to parse " "restore command"); goto out; } break; case GF_SNAP_OPTION_TYPE_ACTIVATE: /* Syntax: * snapshot activate [force] */ ret = cli_snap_activate_parse (dict, words, wordcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to parse " "start command"); goto out; } break; case GF_SNAP_OPTION_TYPE_DEACTIVATE: /* Syntax: * snapshot deactivate */ ret = cli_snap_deactivate_parse (dict, words, wordcount, state); if (ret) { /* A positive ret value means user cancelled * the command */ if (ret < 0) { gf_log ("cli", GF_LOG_ERROR, "Failed to parse deactivate " "command"); } goto out; } break; default: gf_log ("", GF_LOG_ERROR, "Opword Mismatch"); goto out; } ret = dict_set_int32 (dict, "type", type); if (ret) { gf_log ("", GF_LOG_ERROR, "Failed to set type."); goto out; } /* If you got so far, input is valid */ ret = 0; out: if (ret) { if (dict) dict_unref (dict); } else *options = dict; return ret; } int cli_cmd_validate_volume (char *volname) { int i = 0; int ret = -1; if (volname[0] == '-') return ret; if (!strcmp (volname, "all")) { cli_err ("\"all\" cannot be the name of a volume."); return ret; } if (strchr (volname, '/')) { cli_err ("Volume name should not contain \"/\" character."); return ret; } if (strlen (volname) > GD_VOLUME_NAME_MAX) { cli_err ("Volname can not exceed %d characters.", GD_VOLUME_NAME_MAX); return ret; } for (i = 0; i < strlen (volname); i++) if (!isalnum (volname[i]) && (volname[i] != '_') && (volname[i] != '-')) { cli_err ("Volume name should not contain \"%c\"" " character.\nVolume names can only" "contain alphanumeric, '-' and '_' " "characters.", volname[i]); return ret; } ret = 0; return ret; } int32_t cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options) { int32_t ret = -1; char *w = NULL; char *volname = NULL; char *opwords[] = {"enable", "disable", "scrub-throttle", "scrub-frequency", "scrub", "signing-time", NULL}; char *scrub_throt_values[] = {"lazy", "normal", "aggressive", NULL}; char *scrub_freq_values[] = {"hourly", "daily", "weekly", "biweekly", "monthly", "minute", NULL}; char *scrub_values[] = {"pause", "resume", "status", "ondemand", NULL}; dict_t *dict = NULL; gf_bitrot_type type = GF_BITROT_OPTION_TYPE_NONE; int32_t expiry_time = 0; GF_ASSERT (words); GF_ASSERT (options); /* Hack to print out bitrot help properly */ if ((wordcount == 3) && !(strcmp (words[2], "help"))) { ret = 1; return ret; } if (wordcount < 4 || wordcount > 5) { gf_log ("cli", GF_LOG_ERROR, "Invalid syntax"); goto out; } dict = dict_new (); if (!dict) goto out; volname = (char *)words[2]; if (!volname) { ret = -1; goto out; } ret = cli_cmd_validate_volume (volname); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to validate volume name"); goto out; } ret = dict_set_str (dict, "volname", volname); if (ret) { cli_out ("Failed to set volume name in dictionary "); goto out; } w = str_getunamb (words[3], opwords); if (!w) { cli_out ("Invalid bit rot option : %s", words[3]); ret = -1; goto out; } if (strcmp (w, "enable") == 0) { if (wordcount == 4) { type = GF_BITROT_OPTION_TYPE_ENABLE; ret = 0; goto set_type; } else { ret = -1; goto out; } } if (strcmp (w, "disable") == 0) { if (wordcount == 4) { type = GF_BITROT_OPTION_TYPE_DISABLE; ret = 0; goto set_type; } else { ret = -1; goto out; } } if (!strcmp (w, "scrub-throttle")) { if (!words[4]) { cli_err ("Missing scrub-throttle value for bitrot " "option"); ret = -1; goto out; } else { w = str_getunamb (words[4], scrub_throt_values); if (!w) { cli_err ("Invalid scrub-throttle option for " "bitrot"); ret = -1; goto out; } else { type = GF_BITROT_OPTION_TYPE_SCRUB_THROTTLE; ret = dict_set_str (dict, "scrub-throttle-value", (char *) words[4]); if (ret) { cli_out ("Failed to set scrub-throttle " "value in the dict"); goto out; } goto set_type; } } } if (!strcmp (words[3], "scrub-frequency")) { if (!words[4]) { cli_err ("Missing scrub-frequency value"); ret = -1; goto out; } else { w = str_getunamb (words[4], scrub_freq_values); if (!w) { cli_err ("Invalid frequency option for bitrot"); ret = -1; goto out; } else { type = GF_BITROT_OPTION_TYPE_SCRUB_FREQ; ret = dict_set_str (dict, "scrub-frequency-value", (char *) words[4]); if (ret) { cli_out ("Failed to set dict for " "bitrot"); goto out; } goto set_type; } } } if (!strcmp (words[3], "scrub")) { if (!words[4]) { cli_err ("Missing scrub value for bitrot option"); ret = -1; goto out; } else { w = str_getunamb (words[4], scrub_values); if (!w) { cli_err ("Invalid scrub option for bitrot"); ret = -1; goto out; } else { if (strcmp (words[4], "status") == 0) { type = GF_BITROT_CMD_SCRUB_STATUS; } else if (strcmp (words[4], "ondemand") == 0) { type = GF_BITROT_CMD_SCRUB_ONDEMAND; } else { type = GF_BITROT_OPTION_TYPE_SCRUB; } ret = dict_set_str (dict, "scrub-value", (char *) words[4]); if (ret) { cli_out ("Failed to set dict for " "bitrot"); goto out; } goto set_type; } } } if (!strcmp (words[3], "signing-time")) { if (!words[4]) { cli_err ("Missing signing-time value for bitrot " "option"); ret = -1; goto out; } else { type = GF_BITROT_OPTION_TYPE_EXPIRY_TIME; expiry_time = strtol (words[4], NULL, 0); if (expiry_time < 1) { cli_err ("Expiry time value should not be less" " than 1"); ret = -1; goto out; } ret = dict_set_uint32 (dict, "expiry-time", (unsigned int) expiry_time); if (ret) { cli_out ("Failed to set dict for bitrot"); goto out; } goto set_type; } } else { cli_err ("Invalid option %s for bitrot. Please enter valid " "bitrot option", words[3]); ret = -1; goto out; } set_type: ret = dict_set_int32 (dict, "type", type); if (ret < 0) goto out; *options = dict; out: if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to parse bitrot command"); if (dict) dict_unref (dict); } return ret; } glusterfs-3.13.2/cli/src/PaxHeaders.5796/cli.h0000644000000000000000000000013213230626775017036 xustar000000000000000030 mtime=1516449277.183371926 30 atime=1516449277.183371926 30 ctime=1516449329.335492895 glusterfs-3.13.2/cli/src/cli.h0000664000175100017510000003543313230626775017307 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2006-2012 Red Hat, Inc. This file is part of GlusterFS. 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 __CLI_H__ #define __CLI_H__ #include "rpc-clnt.h" #include "glusterfs.h" #include "protocol-common.h" #include "logging.h" #include "quota-common-utils.h" #include "cli1-xdr.h" #if (HAVE_LIB_XML) #include #include #endif #define DEFAULT_EVENT_POOL_SIZE 16384 #define CLI_GLUSTERD_PORT 24007 #define DEFAULT_CLI_LOG_FILE_DIRECTORY DATADIR "/log/glusterfs" #define CLI_VOL_STATUS_BRICK_LEN 43 #define CLI_TAB_LENGTH 8 #define CLI_BRICK_STATUS_LINE_LEN 78 /* Geo-rep command positional arguments' index */ #define GEO_REP_CMD_INDEX 1 #define GEO_REP_CMD_CONFIG_INDEX 4 enum argp_option_keys { ARGP_DEBUG_KEY = 133, ARGP_PORT_KEY = 'p', }; int cli_default_conn_timeout; int cli_ten_minutes_timeout; typedef enum { COLD_BRICK_COUNT, COLD_TYPE, COLD_DIST_COUNT, COLD_REPLICA_COUNT, COLD_ARBITER_COUNT, COLD_DISPERSE_COUNT, COLD_REDUNDANCY_COUNT, HOT_BRICK_COUNT, HOT_TYPE, HOT_REPLICA_COUNT, MAX } values; #define GLUSTER_MODE_SCRIPT (1 << 0) #define GLUSTER_MODE_ERR_FATAL (1 << 1) #define GLUSTER_MODE_XML (1 << 2) #define GLUSTER_MODE_WIGNORE (1 << 3) #define GLUSTER_MODE_WIGNORE_PARTITION (1 << 4) #define GLUSTERD_GET_QUOTA_LIST_MOUNT_PATH(abspath, volname, path) do { \ snprintf (abspath, sizeof (abspath)-1, \ DEFAULT_VAR_RUN_DIRECTORY"/%s_quota_list%s", volname, path);\ } while (0) struct cli_state; struct cli_cmd_word; struct cli_cmd_tree; struct cli_cmd; extern char *cli_vol_status_str[]; extern char *cli_vol_task_status_str[]; typedef int (cli_cmd_cbk_t)(struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount); typedef void (cli_cmd_reg_cbk_t)( struct cli_cmd *this); typedef int (cli_cmd_match_t)(struct cli_cmd_word *word); typedef int (cli_cmd_filler_t)(struct cli_cmd_word *word); struct cli_cmd_word { struct cli_cmd_tree *tree; const char *word; cli_cmd_filler_t *filler; cli_cmd_match_t *match; cli_cmd_cbk_t *cbkfn; const char *desc; const char *pattern; int nextwords_cnt; struct cli_cmd_word **nextwords; }; struct cli_cmd_tree { struct cli_state *state; struct cli_cmd_word root; }; struct cli_state { int argc; char **argv; char debug; /* for events dispatching */ glusterfs_ctx_t *ctx; /* registry of known commands */ struct cli_cmd_tree tree; /* the thread which "executes" the command in non-interactive mode */ /* also the thread which reads from stdin in non-readline mode */ pthread_t input; /* terminal I/O */ const char *prompt; int rl_enabled; int rl_async; int rl_processing; /* autocompletion state */ char **matches; char **matchesp; char *remote_host; int remote_port; int mode; int await_connected; char *log_file; gf_loglevel_t log_level; char *glusterd_sock; }; struct cli_local { struct { char *volname; int flags; } get_vol; dict_t *dict; const char **words; /* Marker for volume status all */ gf_boolean_t all; #if (HAVE_LIB_XML) xmlTextWriterPtr writer; xmlDocPtr doc; int vol_count; #endif gf_lock_t lock; struct list_head dict_list; }; struct cli_volume_status { int port; int rdma_port; int online; uint64_t block_size; uint64_t total_inodes; uint64_t free_inodes; char *brick; char *pid_str; char *free; char *total; char *fs_name; char *mount_options; char *device; char *inode_size; }; struct snap_config_opt_vals_ { char *op_name; char *question; }; typedef struct cli_volume_status cli_volume_status_t; typedef struct cli_local cli_local_t; typedef ssize_t (*cli_serialize_t) (struct iovec outmsg, void *args); extern struct cli_state *global_state; /* use only in readline callback */ typedef const char *(*cli_selector_t) (void *wcon); char *get_struct_variable (int mem_num, gf_gsync_status_t *sts_val); void *cli_getunamb (const char *tok, void **choices, cli_selector_t sel); int cli_cmd_register (struct cli_cmd_tree *tree, struct cli_cmd *cmd); int cli_cmds_register (struct cli_state *state); int cli_input_init (struct cli_state *state); int cli_cmd_process (struct cli_state *state, int argc, char *argv[]); int cli_cmd_process_line (struct cli_state *state, const char *line); int cli_rl_enable (struct cli_state *state); int cli_rl_out (struct cli_state *state, const char *fmt, va_list ap); int cli_rl_err (struct cli_state *state, const char *fmt, va_list ap); int cli_usage_out (const char *usage); int _cli_out (const char *fmt, ...); int _cli_err (const char *fmt, ...); #define cli_out(fmt...) do { \ FMT_WARN (fmt); \ \ _cli_out(fmt); \ \ } while (0) #define cli_err(fmt...) do { \ FMT_WARN (fmt); \ \ _cli_err(fmt); \ \ } while (0) int cli_submit_request (struct rpc_clnt *rpc, void *req, call_frame_t *frame, rpc_clnt_prog_t *prog, int procnum, struct iobref *iobref, xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc); int32_t cli_cmd_volume_create_parse (struct cli_state *state, const char **words, int wordcount, dict_t **options, char **bricks); int32_t cli_cmd_volume_reset_parse (const char **words, int wordcount, dict_t **opt); int32_t cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **opt); int32_t cli_cmd_quota_parse (const char **words, int wordcount, dict_t **opt); int32_t cli_cmd_inode_quota_parse (const char **words, int wordcount, dict_t **opt); int32_t cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **opt); int32_t cli_cmd_volume_set_parse (struct cli_state *state, const char **words, int wordcount, dict_t **options, char **op_errstr); int32_t cli_cmd_get_state_parse (struct cli_state *state, const char **words, int wordcount, dict_t **options, char **op_errstr); int32_t cli_cmd_volume_add_brick_parse (const char **words, int wordcount, dict_t **options, int *type); int32_t cli_cmd_volume_detach_tier_parse (const char **words, int wordcount, dict_t **options, int *question); int32_t cli_cmd_volume_tier_parse (const char **words, int wordcount, dict_t **options); int32_t cli_cmd_volume_old_tier_parse (const char **words, int wordcount, dict_t **options); int32_t cli_cmd_volume_remove_brick_parse (const char **words, int wordcount, dict_t **options, int *question, int *brick_count); int32_t cli_cmd_volume_replace_brick_parse (const char **words, int wordcount, dict_t **options); int32_t cli_cmd_volume_reset_brick_parse (const char **words, int wordcount, dict_t **options); int32_t cli_cmd_log_rotate_parse (const char **words, int wordcount, dict_t **options); int32_t cli_cmd_log_locate_parse (const char **words, int wordcount, dict_t **options); int32_t cli_cmd_log_filename_parse (const char **words, int wordcount, dict_t **options); int32_t cli_cmd_volume_statedump_options_parse (const char **words, int wordcount, dict_t **options); int32_t cli_cmd_volume_clrlks_opts_parse (const char **words, int wordcount, dict_t **options); cli_local_t * cli_local_get (); void cli_local_wipe (cli_local_t *local); int32_t cli_cmd_await_connected (); int32_t cli_cmd_broadcast_connected (); int cli_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, void *data); int32_t cli_cmd_volume_profile_parse (const char **words, int wordcount, dict_t **options); int32_t cli_cmd_volume_top_parse (const char **words, int wordcount, dict_t **options); int32_t cli_cmd_log_level_parse (const char **words, int wordcount, dict_t **options); int32_t cli_cmd_volume_status_parse (const char **words, int wordcount, dict_t **options); int cli_cmd_volume_heal_options_parse (const char **words, int wordcount, dict_t **options); int cli_cmd_volume_defrag_parse (const char **words, int wordcount, dict_t **options); int cli_print_brick_status (cli_volume_status_t *status); void cli_print_detailed_status (cli_volume_status_t *status); int cli_get_detail_status (dict_t *dict, int i, cli_volume_status_t *status); void cli_print_line (int len); int cli_xml_output_str (char *op, char *str, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_dict (char *op, dict_t *dict, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_vol_top (dict_t *dict, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_vol_profile (dict_t *dict, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_vol_status_begin (cli_local_t *local, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_vol_status_end (cli_local_t *local); int cli_xml_output_vol_status (cli_local_t *local, dict_t *dict); int cli_xml_output_vol_list (dict_t *dict, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_vol_info_begin (cli_local_t *local, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_vol_info_end (cli_local_t *local); int cli_xml_output_vol_info (cli_local_t *local, dict_t *dict); int cli_xml_output_vol_quota_limit_list_begin (cli_local_t *local, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_vol_quota_limit_list_end (cli_local_t *local); int cli_quota_list_xml_error (cli_local_t *local, char *path, char *errstr); int cli_quota_xml_output (cli_local_t *local, char *path, int64_t hl_str, char *sl_final, int64_t sl_num, int64_t used, int64_t avail, char *sl, char *hl, gf_boolean_t limit_set); int cli_quota_object_xml_output (cli_local_t *local, char *path, char *sl_str, int64_t sl_val, quota_limits_t *limits, quota_meta_t *used_space, int64_t avail, char *sl, char *hl, gf_boolean_t limit_set); int cli_xml_output_peer_status (dict_t *dict, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_vol_rebalance (gf_cli_defrag_type op, dict_t *dict, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_vol_remove_brick_detach_tier (gf_boolean_t status_op, dict_t *dict, int op_ret, int op_errno, char *op_errstr, const char *op); int cli_xml_output_vol_replace_brick (dict_t *dict, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_vol_create (dict_t *dict, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_generic_volume (char *op, dict_t *dict, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_vol_gsync (dict_t *dict, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_vol_status_tasks_detail (cli_local_t *local, dict_t *dict); int cli_xml_snapshot_delete (cli_local_t *local, dict_t *dict, gf_cli_rsp *rsp); int cli_xml_snapshot_begin_composite_op (cli_local_t *local); int cli_xml_snapshot_end_composite_op (cli_local_t *local); int cli_xml_output_snap_delete_begin (cli_local_t *local, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_snap_delete_end (cli_local_t *local); int cli_xml_output_snap_status_begin (cli_local_t *local, int op_ret, int op_errno, char *op_errstr); int cli_xml_output_snap_status_end (cli_local_t *local); int cli_xml_output_snapshot (int cmd_type, dict_t *dict, int op_ret, int op_errno, char *op_errstr); int cli_xml_snapshot_status_single_snap (cli_local_t *local, dict_t *dict, char *key); char * is_server_debug_xlator (void *myframe); int32_t cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, struct cli_state *state); int cli_xml_output_vol_getopts (dict_t *dict, int op_ret, int op_errno, char *op_errstr); void print_quota_list_header (int type); void print_quota_list_empty (char *path, int type); int gf_gsync_status_t_comparator (const void *p, const void *q); #endif /* __CLI_H__ */ glusterfs-3.13.2/cli/src/PaxHeaders.5796/cli-rl.c0000644000000000000000000000013213230626775017444 xustar000000000000000030 mtime=1516449277.178371915 30 atime=1516449277.178371915 30 ctime=1516449329.349492927 glusterfs-3.13.2/cli/src/cli-rl.c0000664000175100017510000002226713230626775017716 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2010-2012 Red Hat, Inc. This file is part of GlusterFS. 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 #include #include "cli.h" #include "cli-cmd.h" #include "cli-mem-types.h" #include "event.h" #include #ifdef HAVE_READLINE #include #include #include int cli_rl_out (struct cli_state *state, const char *fmt, va_list ap) { int tmp_rl_point = rl_point; int n = rl_end; int ret = 0; if (rl_end >= 0 ) { rl_kill_text (0, rl_end); rl_redisplay (); } printf ("\r%*s\r", (int)strlen (state->prompt), ""); ret = vprintf (fmt, ap); printf ("\n"); fflush(stdout); if (n) { rl_do_undo (); rl_point = tmp_rl_point; rl_reset_line_state (); } return ret; } int cli_rl_err (struct cli_state *state, const char *fmt, va_list ap) { int tmp_rl_point = rl_point; int n = rl_end; int ret = 0; if (rl_end >= 0 ) { rl_kill_text (0, rl_end); rl_redisplay (); } fprintf (stderr, "\r%*s\r", (int)strlen (state->prompt), ""); ret = vfprintf (stderr, fmt, ap); fprintf (stderr, "\n"); fflush(stderr); if (n) { rl_do_undo (); rl_point = tmp_rl_point; rl_reset_line_state (); } return ret; } void cli_rl_process_line (char *line) { struct cli_state *state = NULL; int ret = 0; state = global_state; state->rl_processing = 1; { ret = cli_cmd_process_line (state, line); if (ret) gf_log (THIS->name, GF_LOG_WARNING, "failed to process line"); add_history (line); } state->rl_processing = 0; } int cli_rl_stdin (int fd, int idx, int gen, void *data, int poll_out, int poll_in, int poll_err) { struct cli_state *state = NULL; state = data; rl_callback_read_char (); event_handled (state->ctx->event_pool, fd, idx, gen); return 0; } char * cli_rl_autocomplete_entry (const char *text, int times) { struct cli_state *state = NULL; char *retp = NULL; state = global_state; if (!state->matchesp) return NULL; retp = *state->matchesp; state->matchesp++; return retp ? strdup (retp) : NULL; } int cli_rl_token_count (const char *text) { int count = 0; const char *trav = NULL; int is_spc = 1; for (trav = text; *trav; trav++) { if (*trav == ' ') { is_spc = 1; } else { if (is_spc) { count++; is_spc = 0; } } } if (is_spc) /* what needs to be autocompleted is a full new word, and not extend the last word */ count++; return count; } char ** cli_rl_tokenize (const char *text) { int count = 0; char **tokens = NULL; char **tokenp = NULL; char *token = NULL; char *copy = NULL; char *saveptr = NULL; int i = 0; count = cli_rl_token_count (text); tokens = calloc (count + 1, sizeof (*tokens)); if (!tokens) return NULL; copy = strdup (text); if (!copy) goto out; tokenp = tokens; for (token = strtok_r (copy, " \t\r\n", &saveptr); token; token = strtok_r (NULL, " \t\r\n", &saveptr)) { *tokenp = strdup (token); if (!*tokenp) goto out; tokenp++; i++; } if (i < count) { /* symbolize that what needs to be autocompleted is the full set of possible nextwords, and not extend the last word */ *tokenp = strdup (""); if (!*tokenp) goto out; tokenp++; i++; } out: free (copy); if (i < count) { cli_cmd_tokens_destroy (tokens); tokens = NULL; } return tokens; } char ** cli_rl_get_matches (struct cli_state *state, struct cli_cmd_word *word, const char *text) { char **matches = NULL; char **matchesp = NULL; struct cli_cmd_word **next = NULL; int count = 0; int len = 0; len = strlen (text); if (!word->nextwords) return NULL; for (next = word->nextwords; *next; next++) count++; matches = calloc (count + 1, sizeof (*matches)); matchesp = matches; for (next = word->nextwords; *next; next++) { if ((*next)->match) { continue; } if (strncmp ((*next)->word, text, len) == 0) { *matchesp = strdup ((*next)->word); matchesp++; } } return matches; } int cli_rl_autocomplete_prepare (struct cli_state *state, const char *text) { struct cli_cmd_word *word = NULL; struct cli_cmd_word *next = NULL; char **tokens = NULL; char **tokenp = NULL; char *token = NULL; char **matches = NULL; tokens = cli_rl_tokenize (text); if (!tokens) return 0; word = &state->tree.root; for (tokenp = tokens; (token = *tokenp); tokenp++) { if (!*(tokenp+1)) { /* last word */ break; } next = cli_cmd_nextword (word, token); word = next; if (!word) break; } if (!word) goto out; matches = cli_rl_get_matches (state, word, token); state->matches = matches; state->matchesp = matches; out: cli_cmd_tokens_destroy (tokens); return 0; } int cli_rl_autocomplete_cleanup (struct cli_state *state) { if (state->matches) cli_cmd_tokens_destroy (state->matches); state->matches = NULL; state->matchesp = NULL; return 0; } char ** cli_rl_autocomplete (const char *text, int start, int end) { struct cli_state *state = NULL; char **matches = NULL; char save = 0; state = global_state; /* hack to make the autocompletion code neater */ /* fake it as though the cursor is at the end of line */ save = rl_line_buffer[rl_point]; rl_line_buffer[rl_point] = 0; cli_rl_autocomplete_prepare (state, rl_line_buffer); matches = rl_completion_matches (text, cli_rl_autocomplete_entry); cli_rl_autocomplete_cleanup (state); rl_line_buffer[rl_point] = save; return matches; } static char * complete_none (const char *txt, int times) { return NULL; } void * cli_rl_input (void *_data) { struct cli_state *state = NULL; char *line = NULL; state = _data; for (;;) { line = readline (state->prompt); if (!line) exit(0); //break; if (*line) cli_rl_process_line (line); free (line); } return NULL; } int cli_rl_enable (struct cli_state *state) { int ret = 0; rl_pre_input_hook = NULL; rl_attempted_completion_function = cli_rl_autocomplete; rl_completion_entry_function = complete_none; if (!state->rl_async) { ret = pthread_create (&state->input, NULL, cli_rl_input, state); if (ret == 0) state->rl_enabled = 1; goto out; } ret = event_register (state->ctx->event_pool, 0, cli_rl_stdin, state, 1, 0); if (ret == -1) goto out; state->rl_enabled = 1; rl_callback_handler_install (state->prompt, cli_rl_process_line); out: return state->rl_enabled; } #else /* HAVE_READLINE */ int cli_rl_enable (struct cli_state *state) { return 0; } #endif /* HAVE_READLINE */ glusterfs-3.13.2/cli/src/PaxHeaders.5796/cli-mem-types.h0000644000000000000000000000013213230626775020754 xustar000000000000000030 mtime=1516449277.177371912 30 atime=1516449277.177371912 30 ctime=1516449329.337492899 glusterfs-3.13.2/cli/src/cli-mem-types.h0000664000175100017510000000150213230626775021213 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2010-2012 Red Hat, Inc. This file is part of GlusterFS. 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 __CLI_MEM_TYPES_H__ #define __CLI_MEM_TYPES_H__ #include "mem-types.h" #define CLI_MEM_TYPE_START (gf_common_mt_end + 1) enum cli_mem_types_ { cli_mt_xlator_list_t = CLI_MEM_TYPE_START, cli_mt_xlator_t, cli_mt_xlator_cmdline_option_t, cli_mt_char, cli_mt_call_pool_t, cli_mt_cli_local_t, cli_mt_cli_get_vol_ctx_t, cli_mt_append_str, cli_mt_cli_cmd, cli_mt_end }; #endif glusterfs-3.13.2/cli/src/PaxHeaders.5796/registry.c0000644000000000000000000000013213230626775020132 xustar000000000000000030 mtime=1516449277.183371926 30 atime=1516449277.183371926 30 ctime=1516449329.344492916 glusterfs-3.13.2/cli/src/registry.c0000664000175100017510000002144213230626775020376 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2010-2012 Red Hat, Inc. This file is part of GlusterFS. 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 "cli.h" #include "cli-cmd.h" static int __is_spc (int ch) { if (ch == ' ') return 1; return 0; } static int __is_div (int ch) { switch (ch) { case '(': case ')': case '<': case '>': case '[': case ']': case '{': case '}': case '|': return 1; } return 0; } static int __is_word (const char *word) { return (!__is_div (*word) && !__is_spc (*word)); } int counter_char (int ch) { switch (ch) { case '(': return ')'; case '<': return '>'; case '[': return ']'; case '{': return '}'; } return -1; } const char * __is_template_balanced (const char *template) { const char *trav = NULL; int ch = 0; trav = template; while (*trav) { ch = *trav; switch (ch) { case '<': case '(': case '[': trav = __is_template_balanced (trav+1); if (!trav) return NULL; if (*trav != counter_char (ch)) return NULL; break; case '>': case ')': case ']': return trav; } trav++; } return trav; } int is_template_balanced (const char *template) { const char *trav = NULL; trav = __is_template_balanced (template); if (!trav || *trav) return -1; return 0; } int cli_cmd_token_count (const char *template) { int count = 0; const char *trav = NULL; int is_alnum = 0; for (trav = template; *trav; trav++) { switch (*trav) { case '<': case '>': case '(': case ')': case '[': case ']': case '{': case '}': case '|': count++; /* fall through */ case ' ': is_alnum = 0; break; default: if (!is_alnum) { is_alnum = 1; count++; } } } return count + 1; } void cli_cmd_tokens_destroy (char **tokens) { char **tokenp = NULL; if (!tokens) return; tokenp = tokens; while (*tokenp) { free (*tokenp); tokenp++; } free (tokens); } int cli_cmd_tokens_fill (char **tokens, const char *template) { const char *trav = NULL; char **tokenp = NULL; char *token = NULL; int ret = 0; int ch = 0; tokenp = tokens; for (trav = template; *trav; trav++) { ch = *trav; if (__is_spc (ch)) continue; if (__is_div (ch)) { token = calloc (2, 1); if (!token) return -1; token[0] = ch; *tokenp = token; tokenp++; continue; } token = strdup (trav); *tokenp = token; tokenp++; for (token++; *token; token++) { if (__is_spc (*token) || __is_div (*token)) { *token = 0; break; } trav++; } } return ret; } char ** cli_cmd_tokenize (const char *template) { char **tokens = NULL; int ret = 0; int count = 0; ret = is_template_balanced (template); if (ret) return NULL; count = cli_cmd_token_count (template); if (count <= 0) return NULL; tokens = calloc (count + 1, sizeof (char *)); if (!tokens) return NULL; ret = cli_cmd_tokens_fill (tokens, template); if (ret) goto err; return tokens; err: cli_cmd_tokens_destroy (tokens); return NULL; } void * cli_getunamb (const char *tok, void **choices, cli_selector_t sel) { void **wcon = NULL; char *w = NULL; unsigned mn = 0; void *ret = NULL; if (!choices || !tok || !*tok) return NULL; for (wcon = choices; *wcon; wcon++) { w = strtail ((char *)sel (*wcon), tok); if (!w) /* no match */ continue; if (!*w) /* exact match */ return *wcon; ret = *wcon; mn++; } #ifdef FORCE_MATCH_EXACT return NULL; #else return (mn == 1) ? ret : NULL; #endif } static const char * sel_cmd_word (void *wcon) { return ((struct cli_cmd_word *)wcon)->word; } struct cli_cmd_word * cli_cmd_nextword (struct cli_cmd_word *word, const char *token) { return (struct cli_cmd_word *)cli_getunamb (token, (void **)word->nextwords, sel_cmd_word); } struct cli_cmd_word * cli_cmd_newword (struct cli_cmd_word *word, const char *token) { struct cli_cmd_word **nextwords = NULL; struct cli_cmd_word *nextword = NULL; nextwords = realloc (word->nextwords, (word->nextwords_cnt + 2) * sizeof (*nextwords)); if (!nextwords) return NULL; word->nextwords = nextwords; nextword = calloc (1, sizeof (*nextword)); if (!nextword) return NULL; nextword->word = strdup (token); if (!nextword->word) { free (nextword); return NULL; } nextword->tree = word->tree; nextwords[word->nextwords_cnt++] = nextword; nextwords[word->nextwords_cnt] = NULL; return nextword; } int cli_cmd_ingest (struct cli_cmd_tree *tree, char **tokens, cli_cmd_cbk_t *cbkfn, const char *desc, const char *pattern) { int ret = 0; char **tokenp = NULL; char *token = NULL; struct cli_cmd_word *word = NULL; struct cli_cmd_word *next = NULL; word = &tree->root; for (tokenp = tokens; (token = *tokenp); tokenp++) { if (!__is_word (token)) break; next = cli_cmd_nextword (word, token); if (!next) next = cli_cmd_newword (word, token); word = next; if (!word) break; } if (!word) return -1; if (word->cbkfn) { /* warning - command already registered */ } word->cbkfn = cbkfn; word->desc = desc; word->pattern = pattern; /* end of static strings in command template */ /* TODO: autocompletion beyond this point is just "nice to have" */ return ret; } int cli_cmd_register (struct cli_cmd_tree *tree, struct cli_cmd *cmd) { char **tokens = NULL; int ret = 0; GF_ASSERT (cmd); if (cmd->reg_cbk) cmd->reg_cbk (cmd); if (cmd->disable) { ret = 0; goto out; } tokens = cli_cmd_tokenize (cmd->pattern); if (!tokens) { ret = -1; goto out; } ret = cli_cmd_ingest (tree, tokens, cmd->cbk, cmd->desc, cmd->pattern); if (ret) { ret = -1; goto out; } ret = 0; out: if (tokens) cli_cmd_tokens_destroy (tokens); gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } glusterfs-3.13.2/cli/src/PaxHeaders.5796/Makefile.in0000644000000000000000000000013213230627004020145 xustar000000000000000030 mtime=1516449284.165388126 30 atime=1516449309.496446887 30 ctime=1516449329.331492885 glusterfs-3.13.2/cli/src/Makefile.in0000664000175100017510000006253013230627004020414 0ustar00jenkinsjenkins00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ sbin_PROGRAMS = gluster$(EXEEXT) subdir = cli/src DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(noinst_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/contrib/aclocal/mkdirp.m4 \ $(top_srcdir)/contrib/aclocal/python.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h $(top_builddir)/site.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) am_gluster_OBJECTS = cli.$(OBJEXT) registry.$(OBJEXT) input.$(OBJEXT) \ cli-cmd.$(OBJEXT) cli-rl.$(OBJEXT) cli-cmd-global.$(OBJEXT) \ cli-cmd-volume.$(OBJEXT) cli-cmd-peer.$(OBJEXT) \ cli-rpc-ops.$(OBJEXT) cli-cmd-parser.$(OBJEXT) \ cli-cmd-system.$(OBJEXT) cli-cmd-misc.$(OBJEXT) \ cli-xml-output.$(OBJEXT) cli-quotad-client.$(OBJEXT) \ cli-cmd-snapshot.$(OBJEXT) gluster_OBJECTS = $(am_gluster_OBJECTS) am__DEPENDENCIES_1 = gluster_DEPENDENCIES = \ $(top_builddir)/libglusterfs/src/libglusterfs.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(top_builddir)/rpc/xdr/src/libgfxdr.la \ $(top_builddir)/rpc/rpc-lib/src/libgfrpc.la \ $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = gluster_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(gluster_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(gluster_SOURCES) DIST_SOURCES = $(gluster_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACL_LIBS = @ACL_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LIBTOOLFLAGS = @AM_LIBTOOLFLAGS@ AM_MAKEFLAGS = @AM_MAKEFLAGS@ AR = @AR@ ARGP_STANDALONE_CPPFLAGS = @ARGP_STANDALONE_CPPFLAGS@ ARGP_STANDALONE_DIR = @ARGP_STANDALONE_DIR@ ARGP_STANDALONE_LDADD = @ARGP_STANDALONE_LDADD@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_PYTHON_INC = @BUILD_PYTHON_INC@ BUILD_PYTHON_LIB = @BUILD_PYTHON_LIB@ BUILD_PYTHON_SITE_PACKAGES = @BUILD_PYTHON_SITE_PACKAGES@ BUILD_PYTHON_SITE_PACKAGES_EXPANDED = @BUILD_PYTHON_SITE_PACKAGES_EXPANDED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONTRIBDIR = @CONTRIBDIR@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EVENTS_ENABLED = @EVENTS_ENABLED@ EVENTS_SUBDIR = @EVENTS_SUBDIR@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FUSERMOUNT_SUBDIR = @FUSERMOUNT_SUBDIR@ FUSE_CLIENT_SUBDIR = @FUSE_CLIENT_SUBDIR@ GEOREP_EXTRAS_SUBDIR = @GEOREP_EXTRAS_SUBDIR@ GFAPI_EXTRA_LDFLAGS = @GFAPI_EXTRA_LDFLAGS@ GFAPI_LIBS = @GFAPI_LIBS@ GFAPI_LT_VERSION = @GFAPI_LT_VERSION@ GFAPI_VERSION = @GFAPI_VERSION@ GF_CFLAGS = @GF_CFLAGS@ GF_CPPFLAGS = @GF_CPPFLAGS@ GF_DISTRIBUTION = @GF_DISTRIBUTION@ GF_FUSE_CFLAGS = @GF_FUSE_CFLAGS@ GF_FUSE_LDADD = @GF_FUSE_LDADD@ GF_HOST_OS = @GF_HOST_OS@ GF_LDADD = @GF_LDADD@ GF_LDFLAGS = @GF_LDFLAGS@ GF_XLATOR_DEFAULT_LDFLAGS = @GF_XLATOR_DEFAULT_LDFLAGS@ GLUPY_SUBDIR = @GLUPY_SUBDIR@ GLUPY_SUBDIR_MAKEFILE = @GLUPY_SUBDIR_MAKEFILE@ GLUPY_SUBDIR_SRC_MAKEFILE = @GLUPY_SUBDIR_SRC_MAKEFILE@ GLUSTERD_VOLFILE = @GLUSTERD_VOLFILE@ GLUSTERD_WORKDIR = @GLUSTERD_WORKDIR@ GLUSTERFSD_MISCDIR = @GLUSTERFSD_MISCDIR@ GLUSTERFS_LIBEXECDIR = @GLUSTERFS_LIBEXECDIR@ GREP = @GREP@ HAVE_ATOMIC_BUILTINS = @HAVE_ATOMIC_BUILTINS@ HAVE_BACKTRACE = @HAVE_BACKTRACE@ HAVE_LINKAT = @HAVE_LINKAT@ HAVE_MALLOC_STATS = @HAVE_MALLOC_STATS@ HAVE_SPINLOCK = @HAVE_SPINLOCK@ HAVE_STRNLEN = @HAVE_STRNLEN@ HAVE_SYNC_BUILTINS = @HAVE_SYNC_BUILTINS@ IBVERBS_SUBDIR = @IBVERBS_SUBDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBAIO = @LIBAIO@ LIBGFCHANGELOG_LT_VERSION = @LIBGFCHANGELOG_LT_VERSION@ LIBGFCHANGELOG_VERSION = @LIBGFCHANGELOG_VERSION@ LIBGFDB_VERSION = @LIBGFDB_VERSION@ LIBGFRPC_LT_VERSION = @LIBGFRPC_LT_VERSION@ LIBGFXDR_LT_VERSION = @LIBGFXDR_LT_VERSION@ LIBGLUSTERFS_LT_VERSION = @LIBGLUSTERFS_LT_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OCF_SUBDIR = @OCF_SUBDIR@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_RELEASE = @PACKAGE_RELEASE@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKGCONFIG_UUID = @PKGCONFIG_UUID@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHONDEV_CPPFLAGS = @PYTHONDEV_CPPFLAGS@ PYTHONDEV_LDFLAGS = @PYTHONDEV_LDFLAGS@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDMA_SUBDIR = @RDMA_SUBDIR@ RLLIBS = @RLLIBS@ RPCGEN = @RPCGEN@ SBIN_DIR = @SBIN_DIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SIZEOF_INT = @SIZEOF_INT@ SIZEOF_LONG = @SIZEOF_LONG@ SIZEOF_LONG_LONG = @SIZEOF_LONG_LONG@ SIZEOF_SHORT = @SIZEOF_SHORT@ SQLITE_CFLAGS = @SQLITE_CFLAGS@ SQLITE_LIBS = @SQLITE_LIBS@ STRIP = @STRIP@ SYNCDAEMON_COMPILE = @SYNCDAEMON_COMPILE@ SYNCDAEMON_SUBDIR = @SYNCDAEMON_SUBDIR@ SYSCONF_DIR = @SYSCONF_DIR@ UMOUNTD_SUBDIR = @UMOUNTD_SUBDIR@ UNITTEST_CFLAGS = @UNITTEST_CFLAGS@ UNITTEST_LDFLAGS = @UNITTEST_LDFLAGS@ UNITTEST_LIBS = @UNITTEST_LIBS@ URCU_CDS_CFLAGS = @URCU_CDS_CFLAGS@ URCU_CDS_LIBS = @URCU_CDS_LIBS@ URCU_CFLAGS = @URCU_CFLAGS@ URCU_LIBS = @URCU_LIBS@ USE_EC_DYNAMIC_AVX = @USE_EC_DYNAMIC_AVX@ USE_EC_DYNAMIC_NEON = @USE_EC_DYNAMIC_NEON@ USE_EC_DYNAMIC_SSE = @USE_EC_DYNAMIC_SSE@ USE_EC_DYNAMIC_X64 = @USE_EC_DYNAMIC_X64@ USE_POSIX_ACLS = @USE_POSIX_ACLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ initdir = @initdir@ install_sh = @install_sh@ launchddir = @launchddir@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ mountutildir = @mountutildir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ shrext_cmds = @shrext_cmds@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ systemddir = @systemddir@ target_alias = @target_alias@ tmpfilesdir = @tmpfilesdir@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ gluster_SOURCES = cli.c registry.c input.c cli-cmd.c cli-rl.c cli-cmd-global.c \ cli-cmd-volume.c cli-cmd-peer.c cli-rpc-ops.c cli-cmd-parser.c\ cli-cmd-system.c cli-cmd-misc.c cli-xml-output.c cli-quotad-client.c cli-cmd-snapshot.c gluster_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la $(GF_LDADD) \ $(RLLIBS) $(top_builddir)/rpc/xdr/src/libgfxdr.la \ $(top_builddir)/rpc/rpc-lib/src/libgfrpc.la \ $(XML_LIBS) gluster_LDFLAGS = $(GF_LDFLAGS) noinst_HEADERS = cli.h cli-mem-types.h cli-cmd.h cli-quotad-client.h AM_CPPFLAGS = $(GF_CPPFLAGS) \ -I$(top_srcdir)/libglusterfs/src -I$(top_srcdir)/rpc/rpc-lib/src\ -I$(top_srcdir)/rpc/xdr/src\ -I$(top_builddir)/rpc/xdr/src\ -DDATADIR=\"$(localstatedir)\" \ -DCONFDIR=\"$(sysconfdir)/glusterfs\" \ -DGSYNCD_PREFIX=\"$(GLUSTERFS_LIBEXECDIR)\"\ -DSYNCDAEMON_COMPILE=$(SYNCDAEMON_COMPILE) -DSBIN_DIR=\"$(sbindir)\"\ $(XML_CPPFLAGS) AM_CFLAGS = -Wall $(GF_CFLAGS) CLEANFILES = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign cli/src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign cli/src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gluster$(EXEEXT): $(gluster_OBJECTS) $(gluster_DEPENDENCIES) $(EXTRA_gluster_DEPENDENCIES) @rm -f gluster$(EXEEXT) $(AM_V_CCLD)$(gluster_LINK) $(gluster_OBJECTS) $(gluster_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli-cmd-global.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli-cmd-misc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli-cmd-parser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli-cmd-peer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli-cmd-snapshot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli-cmd-system.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli-cmd-volume.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli-cmd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli-quotad-client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli-rl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli-rpc-ops.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli-xml-output.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cli.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/input.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-data-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-sbinPROGRAMS cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-data-hook install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-sbinPROGRAMS $(top_builddir)/libglusterfs/src/libglusterfs.la: $(MAKE) -C $(top_builddir)/libglusterfs/src/ all install-data-hook: $(mkdir_p) $(DESTDIR)$(localstatedir)/run/gluster # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: glusterfs-3.13.2/cli/src/PaxHeaders.5796/cli-xml-output.c0000644000000000000000000000013213230626775021165 xustar000000000000000030 mtime=1516449277.182371924 30 atime=1516449277.181371921 30 ctime=1516449329.364492962 glusterfs-3.13.2/cli/src/cli-xml-output.c0000664000175100017510000074304113230626775021437 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2010-2012 Red Hat, Inc. This file is part of GlusterFS. 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 "cli.h" #include "cli1-xdr.h" #include "run.h" #include "compat.h" #include "syscall.h" #include "upcall-utils.h" enum gf_task_types { GF_TASK_TYPE_REBALANCE, GF_TASK_TYPE_REMOVE_BRICK }; /* * IMPORTANT NOTE: * All exported functions in this file which use libxml need use a * #if (HAVE_LIB_XML), #else, #endif * For eg, * int exported_func () { * #if (HAVE_LIB_XML) * * #else * return 0; * #endif * } * * All other functions, which are called internally within this file need to be * within #if (HAVE_LIB_XML), #endif statements * For eg, * #if (HAVE_LIB_XML) * int internal_func () * { * } * #endif * * Following the above formate ensures that all xml related code is compliled * only when libxml2 is present, and also keeps the rest of the codebase free * of #if (HAVE_LIB_XML) */ #if (HAVE_LIB_XML) #include #include #define XML_RET_CHECK_AND_GOTO(ret, label) do { \ if (ret < 0) { \ ret = -1; \ goto label; \ } \ else \ ret = 0; \ }while (0) \ int cli_begin_xml_output (xmlTextWriterPtr *writer, xmlDocPtr *doc) { int ret = -1; *writer = xmlNewTextWriterDoc (doc, 0); if (writer == NULL) { ret = -1; goto out; } ret = xmlTextWriterStartDocument (*writer, "1.0", "UTF-8", "yes"); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (*writer, (xmlChar *)"cliOutput"); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_end_xml_output (xmlTextWriterPtr writer, xmlDocPtr doc) { int ret = -1; /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterEndDocument (writer); XML_RET_CHECK_AND_GOTO (ret, out); /* Dump xml document to stdout and pretty format it */ xmlSaveFormatFileEnc ("-", doc, "UTF-8", 1); xmlFreeTextWriter (writer); xmlFreeDoc (doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_common (xmlTextWriterPtr writer, int op_ret, int op_errno, char *op_errstr) { int ret = -1; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"opRet", "%d", op_ret); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"opErrno", "%d", op_errno); XML_RET_CHECK_AND_GOTO (ret, out); if (op_errstr) ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"opErrstr", "%s", op_errstr); else ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"opErrstr", "%s", ""); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } #endif int cli_xml_output_str (char *op, char *str, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; if (op) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"cliOp", "%s", op); XML_RET_CHECK_AND_GOTO (ret, out); } if (str) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"output", "%s", str); XML_RET_CHECK_AND_GOTO (ret, out); } ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } #if (HAVE_LIB_XML) int cli_xml_output_data_pair (dict_t *this, char *key, data_t *value, void *data) { int ret = -1; xmlTextWriterPtr *writer = NULL; writer = (xmlTextWriterPtr *)data; ret = xmlTextWriterWriteFormatElement (*writer, (xmlChar *)key, "%s", value->data); XML_RET_CHECK_AND_GOTO (ret, out); out: return ret; } #endif int cli_xml_output_dict ( char *op, dict_t *dict, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; /* <"op"> */ ret = xmlTextWriterStartElement (writer, (xmlChar *)op); XML_RET_CHECK_AND_GOTO (ret, out); if (dict) dict_foreach (dict, cli_xml_output_data_pair, &writer); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } #if (HAVE_LIB_XML) int cli_xml_output_vol_status_common (xmlTextWriterPtr writer, dict_t *dict, int brick_index, int *online, gf_boolean_t *node_present) { int ret = -1; char *hostname = NULL; char *path = NULL; char *uuid = NULL; int port = 0; int rdma_port = 0; int status = 0; int pid = 0; char key[1024] = {0,}; snprintf (key, sizeof (key), "brick%d.hostname", brick_index); ret = dict_get_str (dict, key, &hostname); if (ret) { *node_present = _gf_false; goto out; } *node_present = _gf_true; /* * will be closed in the calling function cli_xml_output_vol_status()*/ ret = xmlTextWriterStartElement (writer, (xmlChar *)"node"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"hostname", "%s", hostname); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.path", brick_index); ret = dict_get_str (dict, key, &path); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"path", "%s", path); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.peerid", brick_index); ret = dict_get_str (dict, key, &uuid); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"peerid", "%s", uuid); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", brick_index); ret = dict_get_int32 (dict, key, &status); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"status", "%d", status); XML_RET_CHECK_AND_GOTO (ret, out); *online = status; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.port", brick_index); ret = dict_get_int32 (dict, key, &port); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.rdma_port", brick_index); ret = dict_get_int32 (dict, key, &rdma_port); /* If the process is either offline or doesn't provide a port (shd) * port = "N/A" * else print the port number of the process. */ /* * Tag 'port' can be removed once console management is started * to support new tag ports. */ if (*online == 1 && port != 0) ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"port", "%d", port); else ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"port", "%s", "N/A"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterStartElement (writer, (xmlChar *)"ports"); if (*online == 1 && (port != 0 || rdma_port != 0)) { if (port) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"tcp", "%d", port); } else { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"tcp", "%s", "N/A"); } XML_RET_CHECK_AND_GOTO (ret, out); if (rdma_port) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"rdma", "%d", rdma_port); } else { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"rdma", "%s", "N/A"); } XML_RET_CHECK_AND_GOTO (ret, out); } else { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"tcp", "%s", "N/A"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"rdma", "%s", "N/A"); XML_RET_CHECK_AND_GOTO (ret, out); } ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.pid", brick_index); ret = dict_get_int32 (dict, key, &pid); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"pid", "%d", pid); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_detail (xmlTextWriterPtr writer, dict_t *dict, int brick_index) { int ret = -1; uint64_t size_total = 0; uint64_t size_free = 0; char *device = NULL; uint64_t block_size = 0; char *mnt_options = NULL; char *fs_name = NULL; char *inode_size = NULL; uint64_t inodes_total = 0; uint64_t inodes_free = 0; char key[1024] = {0,}; snprintf (key, sizeof (key), "brick%d.total", brick_index); ret = dict_get_uint64 (dict, key, &size_total); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"sizeTotal", "%"PRIu64, size_total); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.free", brick_index); ret = dict_get_uint64 (dict, key, &size_free); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"sizeFree", "%"PRIu64, size_free); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.device", brick_index); ret = dict_get_str (dict, key, &device); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"device", "%s", device); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.block_size", brick_index); ret = dict_get_uint64 (dict, key, &block_size); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"blockSize", "%"PRIu64, block_size); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mnt_options", brick_index); ret = dict_get_str (dict, key, &mnt_options); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"mntOptions", "%s", mnt_options); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.fs_name", brick_index); ret = dict_get_str (dict, key, &fs_name); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"fsName", "%s", fs_name); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.inode_size", brick_index); ret = dict_get_str (dict, key, &inode_size); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"inodeSize", "%s", fs_name); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.total_inodes", brick_index); ret = dict_get_uint64 (dict, key, &inodes_total); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"inodesTotal", "%"PRIu64, inodes_total); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.free_inodes", brick_index); ret = dict_get_uint64 (dict, key, &inodes_free); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"inodesFree", "%"PRIu64, inodes_free); XML_RET_CHECK_AND_GOTO (ret, out); } else { ret = 0; } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_mempool (xmlTextWriterPtr writer, dict_t *dict, char *prefix) { int ret = -1; int mempool_count = 0; char *name = NULL; int hotcount = 0; int coldcount = 0; uint64_t paddedsizeof = 0; uint64_t alloccount = 0; int maxalloc = 0; char key[1024] = {0,}; int i = 0; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"mempool"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.mempool-count", prefix); ret = dict_get_int32 (dict, key, &mempool_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", "%d", mempool_count); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < mempool_count; i++) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"pool"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.name", prefix, i); ret = dict_get_str (dict, key, &name); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"name", "%s", name); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.hotcount", prefix, i); ret = dict_get_int32 (dict, key, &hotcount); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"hotCount", "%d", hotcount); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.coldcount", prefix, i); ret = dict_get_int32 (dict, key, &coldcount); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"coldCount", "%d", coldcount); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.paddedsizeof", prefix, i); ret = dict_get_uint64 (dict, key, &paddedsizeof); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"padddedSizeOf", "%"PRIu64, paddedsizeof); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.alloccount", prefix, i); ret = dict_get_uint64 (dict, key, &alloccount); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"allocCount", "%"PRIu64, alloccount); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.max_alloc", prefix, i); ret = dict_get_int32 (dict, key, &maxalloc); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"maxAlloc", "%d", maxalloc); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.pool-misses", prefix, i); ret = dict_get_uint64 (dict, key, &alloccount); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"poolMisses", "%"PRIu64, alloccount); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.max-stdalloc", prefix, i); ret = dict_get_int32 (dict, key, &maxalloc); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"maxStdAlloc", "%d", maxalloc); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_mem (xmlTextWriterPtr writer, dict_t *dict, int brick_index) { int ret = -1; int arena = 0; int ordblks = 0; int smblks = 0; int hblks = 0; int hblkhd = 0; int usmblks = 0; int fsmblks = 0; int uordblks = 0; int fordblks = 0; int keepcost = 0; char key[1024] = {0,}; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"memStatus"); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"mallinfo"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "brick%d.mallinfo.arena", brick_index); ret = dict_get_int32 (dict, key, &arena); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"arena", "%d", arena); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.ordblks", brick_index); ret = dict_get_int32 (dict, key, &ordblks); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"ordblks", "%d", ordblks); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.smblks", brick_index); ret = dict_get_int32 (dict, key, &smblks); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"smblks", "%d", smblks); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.hblks", brick_index); ret = dict_get_int32 (dict, key, &hblks); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"hblks", "%d", hblks); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.hblkhd", brick_index); ret = dict_get_int32 (dict, key, &hblkhd); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"hblkhd", "%d", hblkhd); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.usmblks", brick_index); ret = dict_get_int32 (dict, key, &usmblks); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"usmblks", "%d", usmblks); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.fsmblks", brick_index); ret = dict_get_int32 (dict, key, &fsmblks); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"fsmblks", "%d", fsmblks); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.uordblks", brick_index); ret = dict_get_int32 (dict, key, &uordblks); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"uordblks", "%d", uordblks); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.fordblks", brick_index); ret = dict_get_int32 (dict, key, &fordblks); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"fordblks", "%d", fordblks); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mallinfo.keepcost", brick_index); ret = dict_get_int32 (dict, key, &keepcost); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"keepcost", "%d", keepcost); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d", brick_index); ret = cli_xml_output_vol_status_mempool (writer, dict, key); if (ret) goto out; /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_clients (xmlTextWriterPtr writer, dict_t *dict, int brick_index) { int ret = -1; int client_count = 0; char *hostname = NULL; uint64_t bytes_read = 0; uint64_t bytes_write = 0; uint32_t opversion = 0; char key[1024] = {0,}; int i = 0; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"clientsStatus"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "brick%d.clientcount", brick_index); ret = dict_get_int32 (dict, key, &client_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"clientCount", "%d", client_count); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < client_count; i++) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"client"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.client%d.hostname", brick_index, i); ret = dict_get_str (dict, key, &hostname); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"hostname", "%s", hostname); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.client%d.bytesread", brick_index, i); ret = dict_get_uint64 (dict, key, &bytes_read); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"bytesRead", "%"PRIu64, bytes_read); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.client%d.byteswrite", brick_index, i); ret = dict_get_uint64 (dict, key, &bytes_write); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"bytesWrite", "%"PRIu64, bytes_write); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.client%d.opversion", brick_index, i); ret = dict_get_uint32 (dict, key, &opversion); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"opVersion", "%"PRIu32, opversion); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_inode_entry (xmlTextWriterPtr writer, dict_t *dict, char *prefix) { int ret = -1; char *gfid = NULL; uint64_t nlookup = 0; uint32_t ref = 0; int ia_type = 0; char key[1024] = {0,}; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"inode"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.gfid", prefix); ret = dict_get_str (dict, key, &gfid); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"gfid", "%s", gfid); XML_RET_CHECK_AND_GOTO (ret, out); memset (key,0, sizeof (key)); snprintf (key, sizeof (key), "%s.nlookup", prefix); ret = dict_get_uint64 (dict, key, &nlookup); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"nLookup", "%"PRIu64, nlookup); XML_RET_CHECK_AND_GOTO (ret, out); memset (key,0, sizeof (key)); snprintf (key, sizeof (key), "%s.ref", prefix); ret = dict_get_uint32 (dict, key, &ref); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"ref", "%"PRIu32, ref); XML_RET_CHECK_AND_GOTO (ret, out); memset (key,0, sizeof (key)); snprintf (key, sizeof (key), "%s.ia_type", prefix); ret = dict_get_int32 (dict, key, &ia_type); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"iaType", "%d", ia_type); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_itable (xmlTextWriterPtr writer, dict_t *dict, char *prefix) { int ret = -1; uint32_t active_size = 0; uint32_t lru_size = 0; uint32_t purge_size = 0; char key[1024] = {0,}; int i = 0; snprintf (key, sizeof (key), "%s.active_size", prefix); ret = dict_get_uint32 (dict, key, &active_size); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"activeSize", "%"PRIu32, active_size); XML_RET_CHECK_AND_GOTO (ret, out); if (active_size != 0) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"active"); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < active_size; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.active%d", prefix, i); ret = cli_xml_output_vol_status_inode_entry (writer, dict, key); if (ret) goto out; } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.lru_size", prefix); ret = dict_get_uint32 (dict, key, &lru_size); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"lruSize", "%"PRIu32, lru_size); XML_RET_CHECK_AND_GOTO (ret, out); if (lru_size != 0) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"lru"); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < lru_size; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.lru%d", prefix, i); ret = cli_xml_output_vol_status_inode_entry (writer, dict, key); if (ret) goto out; } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.purge_size", prefix); ret = dict_get_uint32 (dict, key, &purge_size); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"purgeSize", "%"PRIu32, purge_size); XML_RET_CHECK_AND_GOTO (ret, out); if (purge_size != 0) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"purge"); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < purge_size; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.purge%d", prefix, i); ret = cli_xml_output_vol_status_inode_entry (writer, dict, key); if (ret) goto out; } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_inode (xmlTextWriterPtr writer, dict_t *dict, int brick_index) { int ret = -1; int conn_count = 0; char key[1024] = {0,}; int i = 0; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"inodeStatus"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "brick%d.conncount", brick_index); ret = dict_get_int32 (dict, key, &conn_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"connections", "%d", conn_count); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < conn_count; i++) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"connection"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.conn%d.itable", brick_index, i); ret = cli_xml_output_vol_status_itable (writer, dict, key); if (ret) goto out; /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret= xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_fdtable (xmlTextWriterPtr writer, dict_t *dict, char *prefix) { int ret = -1; int refcount = 0; uint32_t maxfds = 0; int firstfree = 0; int openfds = 0; int fd_pid = 0; int fd_refcount = 0; int fd_flags = 0; char key[1024] = {0,}; int i = 0; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"fdTable"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.refcount", prefix); ret = dict_get_int32 (dict, key, &refcount); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"refCount", "%d", refcount); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.maxfds", prefix); ret = dict_get_uint32 (dict, key, &maxfds); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"maxFds", "%"PRIu32, maxfds); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.firstfree", prefix); ret = dict_get_int32 (dict, key, &firstfree); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"firstFree", "%d", firstfree); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.openfds", prefix); ret = dict_get_int32 (dict, key, &openfds); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"openFds", "%d", openfds); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < maxfds; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.fdentry%d.pid", prefix, i); ret = dict_get_int32 (dict, key, &fd_pid); if (ret) continue; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.fdentry%d.refcount", prefix, i); ret = dict_get_int32 (dict, key, &fd_refcount); if (ret) continue; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.fdentry%d.flags", prefix, i); ret = dict_get_int32 (dict, key, &fd_flags); if (ret) continue; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"fd"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"entry", "%d", i+1); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"pid", "%d", fd_pid); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"refCount", "%d", fd_refcount); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"flags", "%d", fd_flags); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_fd (xmlTextWriterPtr writer, dict_t *dict, int brick_index) { int ret = -1; int conn_count = 0; char key[1024] = {0,}; int i = 0; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"fdStatus"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "brick%d.conncount", brick_index); ret = dict_get_int32 (dict, key, &conn_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"connections", "%d", conn_count); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < conn_count; i++) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"connection"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.conn%d.fdtable", brick_index, i); ret = cli_xml_output_vol_status_fdtable (writer, dict, key); if (ret) goto out; /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_callframe (xmlTextWriterPtr writer, dict_t *dict, char *prefix) { int ret = -1; int ref_count = 0; char *translator = NULL; int complete = 0; char *parent = NULL; char *wind_from = NULL; char *wind_to = NULL; char *unwind_from = NULL; char *unwind_to = NULL; char key[1024] = {0,}; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"callFrame"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.refcount", prefix); ret = dict_get_int32 (dict, key, &ref_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"refCount", "%d", ref_count); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.translator", prefix); ret = dict_get_str (dict, key, &translator); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"translator", "%s", translator); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.complete", prefix); ret = dict_get_int32 (dict, key, &complete); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"complete", "%d", complete); XML_RET_CHECK_AND_GOTO (ret ,out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.parent", prefix); ret = dict_get_str (dict, key, &parent); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"parent", "%s", parent); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.windfrom", prefix); ret = dict_get_str (dict, key, &wind_from); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"windFrom", "%s", wind_from); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.windto", prefix); ret = dict_get_str (dict, key, &wind_to); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"windTo", "%s", wind_to); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.unwindfrom", prefix); ret = dict_get_str (dict, key, &unwind_from); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"unwindFrom", "%s", unwind_from); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.unwindto", prefix); ret = dict_get_str (dict, key, &unwind_to); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"unwindTo", "%s", unwind_to); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_callstack (xmlTextWriterPtr writer, dict_t *dict, char *prefix) { int ret = -1; int uid = 0; int gid = 0; int pid = 0; uint64_t unique = 0; int frame_count = 0; char key[1024] = {0,}; int i = 0; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"callStack"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.uid", prefix); ret = dict_get_int32 (dict, key, &uid); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"uid", "%d", uid); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.gid", prefix); ret = dict_get_int32 (dict, key, &gid); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"gid", "%d", gid); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pid", prefix); ret = dict_get_int32 (dict, key, &pid); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"pid", "%d", pid); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.unique", prefix); ret = dict_get_uint64 (dict, key, &unique); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"unique", "%"PRIu64, unique); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.count", prefix); ret = dict_get_int32 (dict, key, &frame_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"frameCount", "%d", frame_count); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < frame_count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.frame%d", prefix, i); ret = cli_xml_output_vol_status_callframe (writer, dict, key); if (ret) goto out; } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_callpool (xmlTextWriterPtr writer, dict_t *dict, int brick_index) { int ret = -1; int call_count = 0; char key[1024] = {0,}; int i = 0; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"callpoolStatus"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "brick%d.callpool.count", brick_index); ret = dict_get_int32 (dict, key, &call_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", "%d", call_count); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < call_count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.callpool.stack%d", brick_index, i); ret = cli_xml_output_vol_status_callstack (writer, dict, key); if (ret) goto out; } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } #endif int cli_xml_output_vol_status_begin (cli_local_t *local, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; ret = cli_begin_xml_output (&(local->writer), &(local->doc)); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_xml_output_common (local->writer, op_ret, op_errno, op_errstr); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *) "volStatus"); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"volumes"); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } int cli_xml_output_vol_status_end (cli_local_t *local) { #if (HAVE_LIB_XML) int ret = -1; /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO(ret, out); ret = cli_end_xml_output (local->writer, local->doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } #if (HAVE_LIB_XML) int cli_xml_output_remove_brick_task_params (xmlTextWriterPtr writer, dict_t *dict, char *prefix) { int ret = -1; char key[1024] = {0,}; int count = 0; int i = 0; char *brick = NULL; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"params"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.count", prefix); ret = dict_get_int32 (dict, key, &count); if (ret) goto out; for (i = 1; i <= count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.brick%d", prefix, i); ret = dict_get_str (dict, key, &brick); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"brick", "%s", brick); XML_RET_CHECK_AND_GOTO (ret, out); brick = NULL; } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_status_tasks (cli_local_t *local, dict_t *dict) { int ret = -1; char *task_type = NULL; char *task_id_str = NULL; int status = 0; int tasks = 0; char key[1024] = {0,}; int i = 0; /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"tasks"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "tasks", &tasks); if (ret) goto out; for (i = 0; i < tasks; i++) { /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"task"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "task%d.type", i); ret = dict_get_str (dict, key, &task_type); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"type", "%s", task_type); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "task%d.id", i); ret = dict_get_str (dict, key, &task_id_str); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"id", "%s", task_id_str); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "task%d.status", i); ret = dict_get_int32 (dict, key, &status); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"status", "%d", status); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"statusStr", "%s", cli_vol_task_status_str[status]); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "task%d", i); if (!strcmp (task_type, "Remove brick")) { ret = cli_xml_output_remove_brick_task_params (local->writer, dict, key); if (ret) goto out; } /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } #endif int cli_xml_output_vol_status_tasks_detail (cli_local_t *local, dict_t *dict) { #if (HAVE_LIB_XML) int ret = -1; char *volname = NULL; /**/ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"volume"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"volName", "%s", volname); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_xml_output_vol_status_tasks (local, dict); if (ret) goto out; /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); out: return ret; #else return 0; #endif } int cli_xml_output_vol_status (cli_local_t *local, dict_t *dict) { #if (HAVE_LIB_XML) int ret = -1; char *volname = NULL; int brick_count = 0; int brick_index_max = -1; int other_count = 0; int index_max = 0; uint32_t cmd = GF_CLI_STATUS_NONE; int online = 0; gf_boolean_t node_present = _gf_true; int i; int type = -1; int hot_brick_count = -1; /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"volume"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"volName", "%s", volname); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "count", &brick_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"nodeCount", "%d", brick_count); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_uint32 (dict, "cmd", &cmd); if (ret) goto out; ret = dict_get_int32 (dict, "brick-index-max", &brick_index_max); if (ret) goto out; ret = dict_get_int32 (dict, "other-count", &other_count); if (ret) goto out; index_max = brick_index_max + other_count; ret = dict_get_int32 (dict, "type", &type); if (ret) goto out; if (type == GF_CLUSTER_TYPE_TIER) { ret = dict_get_int32 (dict, "hot_brick_count", &hot_brick_count); if (ret) goto out; ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"hotBricks"); XML_RET_CHECK_AND_GOTO (ret, out); } for (i = 0; i <= index_max; i++) { if (type == GF_CLUSTER_TYPE_TIER && i == hot_brick_count) { /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"coldBricks"); XML_RET_CHECK_AND_GOTO (ret, out); } ret = cli_xml_output_vol_status_common (local->writer, dict, i, &online, &node_present); if (ret) { if (node_present) goto out; else continue; } switch (cmd & GF_CLI_STATUS_MASK) { case GF_CLI_STATUS_DETAIL: ret = cli_xml_output_vol_status_detail (local->writer, dict, i); if (ret) goto out; break; case GF_CLI_STATUS_MEM: if (online) { ret = cli_xml_output_vol_status_mem (local->writer, dict, i); if (ret) goto out; } break; case GF_CLI_STATUS_CLIENTS: if (online) { ret = cli_xml_output_vol_status_clients (local->writer, dict, i); if (ret) goto out; } break; case GF_CLI_STATUS_INODE: if (online) { ret = cli_xml_output_vol_status_inode (local->writer, dict, i); if (ret) goto out; } break; case GF_CLI_STATUS_FD: if (online) { ret = cli_xml_output_vol_status_fd (local->writer, dict, i); if (ret) goto out; } break; case GF_CLI_STATUS_CALLPOOL: if (online) { ret = cli_xml_output_vol_status_callpool (local->writer, dict, i); if (ret) goto out; } break; default: break; } /* was opened in cli_xml_output_vol_status_common()*/ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ if (type == GF_CLUSTER_TYPE_TIER && i == brick_index_max) { ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); } } /* Tasks are only present when a normal volume status call is done on a * single volume or on all volumes */ if (((cmd & GF_CLI_STATUS_MASK) == GF_CLI_STATUS_NONE) && (cmd & (GF_CLI_STATUS_VOL|GF_CLI_STATUS_ALL))) { ret = cli_xml_output_vol_status_tasks (local, dict); if (ret) goto out; } /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } #if (HAVE_LIB_XML) int cli_xml_output_vol_top_rw_perf (xmlTextWriterPtr writer, dict_t *dict, int brick_index, int member_index) { int ret = -1; char *filename = NULL; uint64_t throughput = 0; long int time_sec = 0; long int time_usec = 0; char timestr[256] = {0,}; char key[1024] = {0,}; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"file"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%d-filename-%d", brick_index, member_index); ret = dict_get_str (dict, key, &filename); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"filename", "%s", filename); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-value-%d", brick_index, member_index); ret = dict_get_uint64 (dict, key, &throughput); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", "%"PRIu64, throughput); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-time-sec-%d", brick_index, member_index); ret = dict_get_int32 (dict, key, (int32_t *)&time_sec); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-time-usec-%d", brick_index, member_index); ret = dict_get_int32 (dict, key, (int32_t *)&time_usec); if (ret) goto out; gf_time_fmt (timestr, sizeof timestr, time_sec, gf_timefmt_FT); snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr), ".%"GF_PRI_SUSECONDS, time_usec); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"time", "%s", timestr); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_top_other (xmlTextWriterPtr writer, dict_t *dict, int brick_index, int member_index) { int ret = -1; char *filename = NULL; uint64_t count = 0; char key[1024] = {0,}; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"file"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%d-filename-%d", brick_index, member_index); ret = dict_get_str (dict, key, &filename); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"filename", "%s", filename); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-value-%d", brick_index, member_index); ret = dict_get_uint64 (dict, key, &count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", "%"PRIu64, count); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } #endif int cli_xml_output_vol_top (dict_t *dict, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; int brick_count = 0; int top_op = GF_CLI_TOP_NONE; char *brick_name = NULL; int members = 0; uint64_t current_open = 0; uint64_t max_open = 0; char *max_open_time = NULL; double throughput = 0.0; double time_taken = 0.0; char key[1024] = {0,}; int i = 0; int j = 0; ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volTop"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "count", &brick_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"brickCount", "%d", brick_count); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "1-top-op", &top_op); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"topOp", "%d", top_op); XML_RET_CHECK_AND_GOTO (ret, out); while (i < brick_count) { i++; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"brick"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-brick", i); ret = dict_get_str (dict, key, &brick_name); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"name", "%s", brick_name); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key , sizeof (key), "%d-members", i); ret = dict_get_int32 (dict, key, &members); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"members", "%d", members); XML_RET_CHECK_AND_GOTO (ret, out); switch (top_op) { case GF_CLI_TOP_OPEN: memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-current-open", i); ret = dict_get_uint64 (dict, key, ¤t_open); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"currentOpen", "%"PRIu64, current_open); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-max-open", i); ret = dict_get_uint64 (dict, key, &max_open); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"maxOpen", "%"PRIu64, max_open); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-max-openfd-time", i); ret = dict_get_str (dict, key, &max_open_time); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"maxOpenTime", "%s", max_open_time); XML_RET_CHECK_AND_GOTO (ret, out); case GF_CLI_TOP_READ: case GF_CLI_TOP_WRITE: case GF_CLI_TOP_OPENDIR: case GF_CLI_TOP_READDIR: break; case GF_CLI_TOP_READ_PERF: case GF_CLI_TOP_WRITE_PERF: memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-throughput", i); ret = dict_get_double (dict, key, &throughput); if (!ret) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-time", i); ret = dict_get_double (dict, key, &time_taken); } if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"throughput", "%f", throughput); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"timeTaken", "%f", time_taken); XML_RET_CHECK_AND_GOTO (ret, out); } break; default: ret = -1; goto out; } for (j = 1; j <= members; j++) { if (top_op == GF_CLI_TOP_READ_PERF || top_op == GF_CLI_TOP_WRITE_PERF) { ret = cli_xml_output_vol_top_rw_perf (writer, dict, i, j); } else { ret = cli_xml_output_vol_top_other (writer, dict, i, j); } if (ret) goto out; } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } #if (HAVE_LIB_XML) int cli_xml_output_vol_profile_stats (xmlTextWriterPtr writer, dict_t *dict, int brick_index, int interval) { int ret = -1; uint64_t read_count = 0; uint64_t write_count = 0; uint64_t hits = 0; double avg_latency = 0.0; double max_latency = 0.0; double min_latency = 0.0; uint64_t duration = 0; uint64_t total_read = 0; uint64_t total_write = 0; char key[1024] = {0}; int i = 0; /* || */ if (interval == -1) ret = xmlTextWriterStartElement (writer, (xmlChar *)"cumulativeStats"); else ret = xmlTextWriterStartElement (writer, (xmlChar *)"intervalStats"); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"blockStats"); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < 32; i++) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"block"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"size", "%"PRIu32, (1 << i)); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-read-%d", brick_index, interval, (1 << i)); ret = dict_get_uint64 (dict, key, &read_count); if (ret) read_count = 0; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"reads", "%"PRIu64, read_count); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-write-%d", brick_index, interval, (1 << i)); ret = dict_get_uint64 (dict, key, &write_count); if (ret) write_count = 0; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"writes", "%"PRIu64, write_count); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"fopStats"); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < GF_FOP_MAXVALUE; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-%d-hits", brick_index, interval, i); ret = dict_get_uint64 (dict, key, &hits); if (ret) goto cont; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-%d-avglatency", brick_index, interval, i); ret = dict_get_double (dict, key, &avg_latency); if (ret) goto cont; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-%d-minlatency", brick_index, interval, i); ret = dict_get_double (dict, key, &min_latency); if (ret) goto cont; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-%d-maxlatency", brick_index, interval, i); ret = dict_get_double (dict, key, &max_latency); if (ret) goto cont; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"fop"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"name","%s", gf_fop_list[i]); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"hits", "%"PRIu64, hits); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"avgLatency", "%f", avg_latency); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"minLatency", "%f", min_latency); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"maxLatency", "%f", max_latency); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); cont: hits = 0; avg_latency = 0.0; min_latency = 0.0; max_latency = 0.0; } for (i = 0; i < GF_UPCALL_FLAGS_MAXVALUE; i++) { hits = 0; avg_latency = 0.0; min_latency = 0.0; max_latency = 0.0; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-%d-upcall-hits", brick_index, interval, i); ret = dict_get_uint64 (dict, key, &hits); if (ret) continue; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"fop"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"name", "%s", gf_fop_list[i]); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"hits", "%"PRIu64, hits); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"avgLatency", "%f", avg_latency); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"minLatency", "%f", min_latency); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"maxLatency", "%f", max_latency); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-duration", brick_index, interval); ret = dict_get_uint64 (dict, key, &duration); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"duration", "%"PRIu64, duration); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-total-read", brick_index, interval); ret = dict_get_uint64 (dict, key, &total_read); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"totalRead", "%"PRIu64, total_read); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-total-write", brick_index, interval); ret = dict_get_uint64 (dict, key, &total_write); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"totalWrite", "%"PRIu64, total_write); XML_RET_CHECK_AND_GOTO (ret, out); /* || */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } #endif int cli_xml_output_vol_profile (dict_t *dict, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; char *volname = NULL; int op = GF_CLI_STATS_NONE; int info_op = GF_CLI_INFO_NONE; int brick_count = 0; char *brick_name = NULL; int interval = 0; char key[1024] = {0,}; int i = 0; int stats_cleared = 0; ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volProfile"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"volname", "%s", volname); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "op", &op); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"profileOp", "%d", op); XML_RET_CHECK_AND_GOTO (ret, out); if (GF_CLI_STATS_INFO != op) goto cont; ret = dict_get_int32 (dict, "count", &brick_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"brickCount", "%d", brick_count); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "info-op", &info_op); if (ret) goto out; while (i < brick_count) { i++; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"brick"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%d-brick", i); ret = dict_get_str (dict, key, &brick_name); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"brickName", "%s", brick_name); XML_RET_CHECK_AND_GOTO (ret, out); if (GF_CLI_INFO_CLEAR == info_op) { snprintf (key, sizeof (key), "%d-stats-cleared", i); ret = dict_get_int32 (dict, key, &stats_cleared); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"clearStats", "%s", stats_cleared ? "Cleared stats." : "Failed to clear stats."); XML_RET_CHECK_AND_GOTO (ret, out); } else { snprintf (key, sizeof (key), "%d-cumulative", i); ret = dict_get_int32 (dict, key, &interval); if (ret == 0) { ret = cli_xml_output_vol_profile_stats (writer, dict, i, interval); if (ret) goto out; } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-interval", i); ret = dict_get_int32 (dict, key, &interval); if (ret == 0) { ret = cli_xml_output_vol_profile_stats (writer, dict, i, interval); if (ret) goto out; } } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } cont: /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } int cli_xml_output_vol_list (dict_t *dict, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; int count = 0; char *volname = NULL; char key[1024] = {0,}; int i = 0; ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volList"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "count", &count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", "%d", count); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d", i); ret = dict_get_str (dict, key, &volname); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"volume", "%s", volname); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } #if (HAVE_LIB_XML) int cli_xml_output_vol_info_option (xmlTextWriterPtr writer, char *substr, char *optstr, char *valstr) { int ret = -1; char *ptr1 = NULL; char *ptr2 = NULL; ptr1 = substr; ptr2 = optstr; while (ptr1) { if (*ptr1 != *ptr2) break; ptr1++; ptr2++; if (!ptr1) goto out; if (!ptr2) goto out; } if (*ptr2 == '\0') goto out; /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } struct tmp_xml_option_logger { char *key; xmlTextWriterPtr writer; }; static int _output_vol_info_option (dict_t *d, char *k, data_t *v, void *data) { int ret = 0; char *ptr = NULL; struct tmp_xml_option_logger *tmp = NULL; tmp = data; ptr = strstr (k, "option."); if (!ptr) goto out; if (!v) { ret = -1; goto out; } ret = cli_xml_output_vol_info_option (tmp->writer, tmp->key, k, v->data); out: return ret; } int cli_xml_output_vol_info_options (xmlTextWriterPtr writer, dict_t *dict, char *prefix) { int ret = -1; int opt_count = 0; char key[1024] = {0,}; struct tmp_xml_option_logger tmp = {0,}; snprintf (key, sizeof (key), "%s.opt_count", prefix); ret = dict_get_int32 (dict, key, &opt_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"optCount", "%d", opt_count); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"options"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.option.", prefix); tmp.key = key; tmp.writer = writer; ret = dict_foreach (dict, _output_vol_info_option, &tmp); if (ret) goto out; /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } #endif int cli_xml_output_vol_info (cli_local_t *local, dict_t *dict) { #if (HAVE_LIB_XML) int ret = 0; int count = 0; char *volname = NULL; char *volume_id = NULL; char *uuid = NULL; int type = 0; int status = 0; int brick_count = 0; int dist_count = 0; int stripe_count = 0; int replica_count = 0; int arbiter_count = 0; int snap_count = 0; int isArbiter = 0; int disperse_count = 0; int redundancy_count = 0; int transport = 0; char *brick = NULL; char key[1024] = {0,}; int i = 0; int j = 1; char *caps __attribute__((unused)) = NULL; int k __attribute__((unused)) = 0; int index = 1; int tier_vol_type = 0; /* hot dist count is always zero so need for it to be * included in the array.*/ int hot_dist_count = 0; values c = 0; char *keys[MAX] = { [COLD_BRICK_COUNT] = "volume%d.cold_brick_count", [COLD_TYPE] = "volume%d.cold_type", [COLD_DIST_COUNT] = "volume%d.cold_dist_count", [COLD_REPLICA_COUNT] = "volume%d.cold_replica_count", [COLD_ARBITER_COUNT] = "volume%d.cold_arbiter_count", [COLD_DISPERSE_COUNT] = "volume%d.cold_disperse_count", [COLD_REDUNDANCY_COUNT] = "volume%d.cold_redundancy_count", [HOT_BRICK_COUNT] = "volume%d.hot_brick_count", [HOT_TYPE] = "volume%d.hot_type", [HOT_REPLICA_COUNT] = "volume%d.hot_replica_count"}; int value[MAX] = {}; ret = dict_get_int32 (dict, "count", &count); if (ret) goto out; for (i = 0; i < count; i++) { /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"volume"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.name", i); ret = dict_get_str (dict, key, &volname); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"name", "%s", volname); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.volume_id", i); ret = dict_get_str (dict, key, &volume_id); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"id", "%s", volume_id); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.status", i); ret = dict_get_int32 (dict, key, &status); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"status", "%d", status); XML_RET_CHECK_AND_GOTO (ret, out); ret =xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"statusStr", "%s", cli_vol_status_str[status]); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.snap_count", i); ret = dict_get_int32 (dict, key, &snap_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"snapshotCount", "%d", snap_count); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.brick_count", i); ret = dict_get_int32 (dict, key, &brick_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"brickCount", "%d", brick_count); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.dist_count", i); ret = dict_get_int32 (dict, key, &dist_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"distCount", "%d", dist_count); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.stripe_count", i); ret = dict_get_int32 (dict, key, &stripe_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"stripeCount", "%d", stripe_count); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.replica_count", i); ret = dict_get_int32 (dict, key, &replica_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"replicaCount", "%d", replica_count); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.arbiter_count", i); ret = dict_get_int32 (dict, key, &arbiter_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"arbiterCount", "%d", arbiter_count); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.disperse_count", i); ret = dict_get_int32 (dict, key, &disperse_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"disperseCount", "%d", disperse_count); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.redundancy_count", i); ret = dict_get_int32 (dict, key, &redundancy_count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"redundancyCount", "%d", redundancy_count); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.type", i); ret = dict_get_int32 (dict, key, &type); if (ret) goto out; /* For Distributed-(stripe,replicate,stipe-replicate,disperse) types */ type = get_vol_type (type, dist_count, brick_count); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"type", "%d", type); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"typeStr", "%s", vol_type_str[type]); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.transport", i); ret = dict_get_int32 (dict, key, &transport); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"transport", "%d", transport); XML_RET_CHECK_AND_GOTO (ret, out); #ifdef HAVE_BD_XLATOR /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"xlators"); XML_RET_CHECK_AND_GOTO (ret, out); for (k = 0; ; k++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key),"volume%d.xlator%d", i, k); ret = dict_get_str (dict, key, &caps); if (ret) break; /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"xlator"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"name", "%s", caps); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *) "capabilities"); XML_RET_CHECK_AND_GOTO (ret, out); j = 0; for (j = 0; ;j++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.xlator%d.caps%d", i, k, j); ret = dict_get_str (dict, key, &caps); if (ret) break; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"capability", "%s", caps); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); } ret = xmlTextWriterFullEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ #endif j = 1; /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"bricks"); XML_RET_CHECK_AND_GOTO (ret, out); if (type == GF_CLUSTER_TYPE_TIER) { /*the values for hot stripe, disperse and redundancy * should not be looped in here as they are zero * always */ for (c = COLD_BRICK_COUNT; c < MAX; c++) { memset (key, 0, sizeof (key)); snprintf (key, 256, keys[c], i); ret = dict_get_int32 (dict, key, &value[c]); if (ret) goto out; } hot_dist_count = (value[HOT_REPLICA_COUNT] ? value[HOT_REPLICA_COUNT] : 1); tier_vol_type = get_vol_type (value[HOT_TYPE], hot_dist_count, value[HOT_BRICK_COUNT]); if ((value[HOT_TYPE] != GF_CLUSTER_TYPE_TIER) && (value[HOT_TYPE] > 0) && (hot_dist_count < value[HOT_BRICK_COUNT])) tier_vol_type = value[HOT_TYPE] + GF_CLUSTER_TYPE_MAX - 1; ret = xmlTextWriterStartElement (local->writer, (xmlChar *) "hotBricks"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"hotBrickType", "%s", vol_type_str[tier_vol_type]); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"hotreplicaCount", "%d", value[HOT_REPLICA_COUNT]); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"hotbrickCount", "%d", value[HOT_BRICK_COUNT]); XML_RET_CHECK_AND_GOTO (ret, out); if (value[HOT_TYPE] == GF_CLUSTER_TYPE_NONE || value[HOT_TYPE] == GF_CLUSTER_TYPE_TIER) { ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"numberOfBricks", "%d", value[HOT_BRICK_COUNT]); } else { ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"numberOfBricks", "%d x %d = %d", (value[HOT_BRICK_COUNT] / hot_dist_count), hot_dist_count, value[HOT_BRICK_COUNT]); } XML_RET_CHECK_AND_GOTO (ret, out); while (index <= value[HOT_BRICK_COUNT]) { snprintf (key, 1024, "volume%d.brick%d", i, index); ret = dict_get_str (dict, key, &brick); if (ret) goto out; ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"brick"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.brick%d.uuid", i, j); ret = dict_get_str (dict, key, &uuid); if (ret) goto out; ret = xmlTextWriterWriteFormatAttribute (local->writer, (xmlChar *)"uuid", "%s", uuid); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatString (local->writer, "%s", brick); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"name", "%s", brick); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"hostUuid", "%s", uuid); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); index++; } ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); tier_vol_type = get_vol_type (value[COLD_TYPE], value[COLD_DIST_COUNT], value[COLD_BRICK_COUNT]); ret = xmlTextWriterStartElement (local->writer, (xmlChar *) "coldBricks"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"coldBrickType", "%s", vol_type_str[tier_vol_type]); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"coldreplicaCount", "%d", value[COLD_REPLICA_COUNT]); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"coldarbiterCount", "%d", value[COLD_ARBITER_COUNT]); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"coldbrickCount", "%d", value[COLD_BRICK_COUNT]); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"colddisperseCount", "%d", value[COLD_DISPERSE_COUNT]); XML_RET_CHECK_AND_GOTO (ret, out); if (value[COLD_TYPE] == GF_CLUSTER_TYPE_NONE || value[COLD_TYPE] == GF_CLUSTER_TYPE_TIER) { ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"numberOfBricks", "%d", value[COLD_BRICK_COUNT]); } else if (value[COLD_TYPE] == GF_CLUSTER_TYPE_DISPERSE) { ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"numberOfBricks", " %d x (%d + %d) = %d", (value[COLD_BRICK_COUNT] / value[COLD_DIST_COUNT]), value[COLD_DISPERSE_COUNT] - value[COLD_REDUNDANCY_COUNT], value[COLD_REDUNDANCY_COUNT], value[COLD_BRICK_COUNT]); } else { ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"numberOfBricks", "%d x %d = %d", (value[COLD_BRICK_COUNT] / value[COLD_DIST_COUNT]), value[COLD_DIST_COUNT], value[COLD_BRICK_COUNT]); } XML_RET_CHECK_AND_GOTO (ret, out); index = value[HOT_BRICK_COUNT] + 1; while (index <= brick_count) { snprintf (key, 1024, "volume%d.brick%d", i, index); ret = dict_get_str (dict, key, &brick); if (ret) goto out; ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"brick"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.brick%d.uuid", i, j); ret = dict_get_str (dict, key, &uuid); if (ret) goto out; ret = xmlTextWriterWriteFormatAttribute (local->writer, (xmlChar *)"uuid", "%s", uuid); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatString (local->writer, "%s", brick); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"name", "%s", brick); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"hostUuid", "%s", uuid); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.brick%d.isArbiter", i, index); if (dict_get (dict, key)) isArbiter = 1; else isArbiter = 0; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"isArbiter", "%d", isArbiter); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); index++; } ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); } else { while (j <= brick_count) { ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"brick"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.brick%d.uuid", i, j); ret = dict_get_str (dict, key, &uuid); if (ret) goto out; ret = xmlTextWriterWriteFormatAttribute (local->writer, (xmlChar *)"uuid", "%s", uuid); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.brick%d", i, j); ret = dict_get_str (dict, key, &brick); if (ret) goto out; ret = xmlTextWriterWriteFormatString (local->writer, "%s", brick); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"name", "%s", brick); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"hostUuid", "%s", uuid); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.brick%d.isArbiter", i, j); if (dict_get (dict, key)) isArbiter = 1; else isArbiter = 0; ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"isArbiter", "%d", isArbiter); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); j++; } } /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d", i); ret = cli_xml_output_vol_info_options (local->writer, dict, key); if (ret) goto out; /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); } if (volname) { GF_FREE (local->get_vol.volname); local->get_vol.volname = gf_strdup (volname); local->vol_count += count; } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } int cli_xml_output_vol_info_begin (cli_local_t *local, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; GF_ASSERT (local); ret = cli_begin_xml_output (&(local->writer), &(local->doc)); if (ret) goto out; ret = cli_xml_output_common (local->writer, op_ret, op_errno, op_errstr); if (ret) goto out; /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"volInfo"); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"volumes"); XML_RET_CHECK_AND_GOTO (ret, out); /* Init vol count */ local->vol_count = 0; out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } int cli_xml_output_vol_info_end (cli_local_t *local) { #if (HAVE_LIB_XML) int ret = -1; GF_ASSERT (local); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"count", "%d", local->vol_count); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_end_xml_output (local->writer, local->doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } int cli_xml_output_vol_quota_limit_list_end (cli_local_t *local) { #if (HAVE_LIB_XML) int ret = -1; ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_end_xml_output (local->writer, local->doc); out: return ret; #else return 0; #endif } int cli_xml_output_vol_quota_limit_list_begin (cli_local_t *local, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; ret = cli_begin_xml_output (&(local->writer), &(local->doc)); if (ret) goto out; ret = cli_xml_output_common (local->writer, op_ret, op_errno, op_errstr); if (ret) goto out; /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"volQuota"); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } #if (HAVE_LIB_XML) static int cli_xml_output_peer_hostnames (xmlTextWriterPtr writer, dict_t *dict, const char *prefix, int count) { int ret = -1; int i = 0; char *hostname = NULL; char key[1024] = {0,}; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"hostnames"); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 0; i < count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.hostname%d", prefix, i); ret = dict_get_str (dict, key, &hostname); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"hostname", "%s", hostname); XML_RET_CHECK_AND_GOTO (ret, out); hostname = NULL; } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } #endif int cli_xml_output_peer_status (dict_t *dict, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; int count = 0; char *uuid = NULL; char *hostname = NULL; int connected = 0; int state_id = 0; char *state_str = NULL; int hostname_count = 0; int i = 1; char key[1024] = {0,}; ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"peerStatus"); XML_RET_CHECK_AND_GOTO (ret, out); if (!dict) goto cont; ret = dict_get_int32 (dict, "count", &count); if (ret) goto out; while (i <= count) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"peer"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "friend%d.uuid", i); ret = dict_get_str (dict, key, &uuid); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"uuid", "%s", uuid); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "friend%d.hostname", i); ret = dict_get_str (dict, key, &hostname); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"hostname", "%s", hostname); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "friend%d.hostname_count", i); ret = dict_get_int32 (dict, key, &hostname_count); if ((ret == 0) && (hostname_count > 0)) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "friend%d", i); ret = cli_xml_output_peer_hostnames (writer, dict, key, hostname_count); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "friend%d.connected", i); ret = dict_get_int32 (dict, key, &connected); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"connected", "%d", connected); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "friend%d.stateId", i); ret = dict_get_int32 (dict, key, &state_id); if (!ret) { /* ignore */ ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"state", "%d", state_id); XML_RET_CHECK_AND_GOTO (ret, out); } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "friend%d.state", i); ret = dict_get_str (dict, key, &state_str); if (!ret) { /* ignore */ ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"stateStr", "%s", state_str); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); i++; } cont: /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } #if (HAVE_LIB_XML) /* Used for rebalance stop/status, remove-brick status */ int cli_xml_output_vol_rebalance_status (xmlTextWriterPtr writer, dict_t *dict, enum gf_task_types task_type) { int ret = -1; int count = 0; char *node_name = NULL; char *node_uuid = NULL; uint64_t files = 0; uint64_t size = 0; uint64_t lookups = 0; int status_rcd = 0; uint64_t failures = 0; uint64_t skipped = 0; uint64_t total_files = 0; uint64_t total_size = 0; uint64_t total_lookups = 0; uint64_t total_failures = 0; uint64_t total_skipped = 0; char key[1024] = {0,}; int i = 0; int overall_status = -1; double elapsed = 0; double overall_elapsed = 0; if (!dict) { ret = 0; goto out; } ret = dict_get_int32 (dict, "count", &count); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"nodeCount", "%d", count); XML_RET_CHECK_AND_GOTO (ret, out); while (i < count) { i++; /* Getting status early, to skip nodes that don't have the * rebalance process started */ memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "status-%d", i); ret = dict_get_int32 (dict, key, &status_rcd); /* If glusterd is down it fails to get the status, try getting status from other nodes */ if (ret) continue; if (GF_DEFRAG_STATUS_NOT_STARTED == status_rcd) continue; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"node"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "node-name-%d", i); ret = dict_get_str (dict, key, &node_name); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"nodeName", "%s", node_name); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "node-uuid-%d", i); ret = dict_get_str (dict, key, &node_uuid); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"id", "%s", node_uuid); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "files-%d", i); ret = dict_get_uint64 (dict, key, &files); if (ret) goto out; total_files += files; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"files", "%"PRIu64, files); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "size-%d", i); ret = dict_get_uint64 (dict, key, &size); if (ret) goto out; total_size += size; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"size", "%"PRIu64,size); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "lookups-%d", i); ret = dict_get_uint64 (dict, key, &lookups); if (ret) goto out; total_lookups += lookups; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"lookups", "%"PRIu64, lookups); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "failures-%d", i); ret = dict_get_uint64 (dict, key, &failures); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "skipped-%d", i); ret = dict_get_uint64 (dict, key, &skipped); if (ret) goto out; if (task_type == GF_TASK_TYPE_REMOVE_BRICK) { failures += skipped; skipped = 0; } total_failures += failures; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"failures", "%"PRIu64, failures); XML_RET_CHECK_AND_GOTO (ret, out); total_skipped += skipped; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"skipped", "%"PRIu64, skipped); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"status", "%d", status_rcd); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"statusStr", "%s", cli_vol_task_status_str[status_rcd]); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, 256); snprintf (key, 256, "run-time-%d", i); ret = dict_get_double (dict, key, &elapsed); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"runtime", "%.2f", elapsed); XML_RET_CHECK_AND_GOTO (ret, out); if (elapsed > overall_elapsed) { overall_elapsed = elapsed; } /* Rebalance has 5 states, * NOT_STARTED, STARTED, STOPPED, COMPLETE, FAILED * The precedence used to determine the aggregate status is as * below, * STARTED > FAILED > STOPPED > COMPLETE > NOT_STARTED */ /* TODO: Move this to a common place utilities that both CLI and * glusterd need. * Till then if the below algorithm is changed, change it in * glusterd_volume_status_aggregate_tasks_status in * glusterd-utils.c */ if (-1 == overall_status) overall_status = status_rcd; int rank[] = { [GF_DEFRAG_STATUS_STARTED] = 1, [GF_DEFRAG_STATUS_FAILED] = 2, [GF_DEFRAG_STATUS_STOPPED] = 3, [GF_DEFRAG_STATUS_COMPLETE] = 4, [GF_DEFRAG_STATUS_NOT_STARTED] = 5 }; if (rank[status_rcd] <= rank[overall_status]) overall_status = status_rcd; /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } /* Aggregate status */ /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"aggregate"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"files", "%"PRIu64, total_files); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"size", "%"PRIu64, total_size); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"lookups", "%"PRIu64, total_lookups); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"failures", "%"PRIu64, total_failures); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"skipped", "%"PRIu64, total_skipped); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"status", "%d", overall_status); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"statusStr", "%s", cli_vol_task_status_str[overall_status]); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer,(xmlChar *)"runtime", "%.2f", overall_elapsed); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int cli_xml_output_vol_tier_status (xmlTextWriterPtr writer, dict_t *dict, enum gf_task_types task_type) { int ret = -1; int count = 0; char *node_name = NULL; char *status_str = NULL; uint64_t promoted = 0; uint64_t demoted = 0; int i = 1; char key[1024] = {0,}; gf_defrag_status_t status_rcd = GF_DEFRAG_STATUS_NOT_STARTED; GF_VALIDATE_OR_GOTO ("cli", dict, out); ret = dict_get_int32 (dict, "count", &count); if (ret) { gf_log ("cli", GF_LOG_ERROR, "count not set"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"nodeCount", "%d", count); XML_RET_CHECK_AND_GOTO (ret, out); while (i <= count) { promoted = 0; node_name = NULL; demoted = 0; ret = xmlTextWriterStartElement (writer, (xmlChar *)"node"); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "node-name-%d", i); ret = dict_get_str (dict, key, &node_name); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"nodeName", "%s", node_name); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "promoted-%d", i); ret = dict_get_uint64 (dict, key, &promoted); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"promoted" "Files", "%"PRIu64, promoted); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "demoted-%d", i); ret = dict_get_uint64 (dict, key, &demoted); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"demoted" "Files", "%"PRIu64, demoted); XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, 256); snprintf (key, 256, "status-%d", i); ret = dict_get_int32 (dict, key, (int32_t *)&status_rcd); status_str = cli_vol_task_status_str[status_rcd]; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"statusStr", "%s", status_str); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); i++; } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } #endif int cli_xml_output_vol_rebalance (gf_cli_defrag_type op, dict_t *dict, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; char *task_id_str = NULL; ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volRebalance"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, GF_REBALANCE_TID_KEY, &task_id_str); if (ret == 0) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"task-id", "%s", task_id_str); XML_RET_CHECK_AND_GOTO (ret, out); } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"op", "%d", op); XML_RET_CHECK_AND_GOTO (ret, out); if (GF_DEFRAG_CMD_STATUS_TIER == op) { ret = cli_xml_output_vol_tier_status (writer, dict, GF_TASK_TYPE_REBALANCE); if (ret) goto out; } if ((GF_DEFRAG_CMD_STOP == op) || (GF_DEFRAG_CMD_STATUS == op)) { ret = cli_xml_output_vol_rebalance_status (writer, dict, GF_TASK_TYPE_REBALANCE); if (ret) goto out; } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } int cli_xml_output_vol_remove_brick_detach_tier (gf_boolean_t status_op, dict_t *dict, int op_ret, int op_errno, char *op_errstr, const char *op) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; char *task_id_str = NULL; ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; ret = xmlTextWriterStartElement (writer, (xmlChar *) op); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, GF_REMOVE_BRICK_TID_KEY, &task_id_str); if (ret == 0) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"task-id", "%s", task_id_str); XML_RET_CHECK_AND_GOTO (ret, out); } if (status_op) { ret = cli_xml_output_vol_rebalance_status (writer, dict, GF_TASK_TYPE_REMOVE_BRICK); if (ret) goto out; } ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } int cli_xml_output_vol_replace_brick (dict_t *dict, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } int cli_xml_output_vol_create (dict_t *dict, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; char *volname = NULL; char *volid = NULL; ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; if (dict) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volCreate"); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volume"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", volname); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "volume-id", &volid); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"id", "%s", volid); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } int cli_xml_output_generic_volume (char *op, dict_t *dict, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; char *volname = NULL; char *volid = NULL; GF_ASSERT (op); ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; if (dict) { /* <"op"> */ ret = xmlTextWriterStartElement (writer, (xmlChar *)op); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volume"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", volname); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "vol-id", &volid); if (ret) goto out; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"id", "%s", volid); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } #if (HAVE_LIB_XML) int _output_gsync_config (FILE *fp, xmlTextWriterPtr writer, char *op_name) { char resbuf[256 + PATH_MAX] = {0,}; char *ptr = NULL; char *v = NULL; int blen = sizeof(resbuf); int ret = 0; for (;;) { ptr = fgets (resbuf, blen, fp); if (!ptr) break; v = resbuf + strlen (resbuf) - 1; while (isspace (*v)) { /* strip trailing space */ *v-- = '\0'; } if (v == resbuf) { /* skip empty line */ continue; } if (op_name!= NULL){ ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)op_name, "%s", resbuf); XML_RET_CHECK_AND_GOTO (ret, out); goto out; } v = strchr (resbuf, ':'); if (!v) { ret = -1; goto out; } *v++ = '\0'; while (isspace (*v)) v++; v = gf_strdup (v); if (!v) { ret = -1; goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)resbuf, "%s", v); XML_RET_CHECK_AND_GOTO (ret, out); } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } #endif #if (HAVE_LIB_XML) int get_gsync_config (runner_t *runner, int (*op_conf)(FILE *fp, xmlTextWriterPtr writer, char *op_name), xmlTextWriterPtr writer, char *op_name) { int ret = 0; runner_redir (runner, STDOUT_FILENO, RUN_PIPE); if (runner_start (runner) != 0) { gf_log ("cli", GF_LOG_ERROR, "spawning child failed"); return -1; } ret = op_conf (runner_chio (runner, STDOUT_FILENO), writer, op_name); ret |= runner_end (runner); if (ret) gf_log ("cli", GF_LOG_ERROR, "reading data from child failed"); return ret ? -1 : 0; } #endif #if (HAVE_LIB_XML) int cli_xml_generate_gsync_config (dict_t *dict, xmlTextWriterPtr writer) { runner_t runner = {0,}; char *subop = NULL; char *gwd = NULL; char *slave = NULL; char *confpath = NULL; char *master = NULL; char *op_name = NULL; int ret = -1; char conf_path[PATH_MAX] = ""; if (dict_get_str (dict, "subop", &subop) != 0) { ret = -1; goto out; } if (strcmp (subop, "get") != 0 && strcmp (subop, "get-all") != 0) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"message", "%s",GEOREP" config updated successfully" ); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; goto out; } if (dict_get_str (dict, "glusterd_workdir", &gwd) != 0 || dict_get_str (dict, "slave", &slave) != 0) { ret = -1; goto out; } if (dict_get_str (dict, "master", &master) != 0) master = NULL; if (dict_get_str (dict, "op_name", &op_name) != 0) op_name = NULL; ret = dict_get_str (dict, "conf_path", &confpath); if (!confpath) { ret = snprintf (conf_path, sizeof (conf_path) - 1, "%s/"GEOREP"/gsyncd_template.conf", gwd); conf_path[ret] = '\0'; confpath = conf_path; } runinit (&runner); runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); runner_argprintf (&runner, "%s", confpath); runner_argprintf (&runner, "--iprefix=%s", DATADIR); if (master) runner_argprintf (&runner, ":%s", master); runner_add_arg (&runner, slave); runner_argprintf (&runner, "--config-%s", subop); if (op_name) runner_add_arg (&runner, op_name); ret = get_gsync_config (&runner, _output_gsync_config, writer, op_name); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } #endif #if (HAVE_LIB_XML) int cli_xml_output_vol_gsync_status (dict_t *dict, xmlTextWriterPtr writer) { int ret = -1; int i = 1; int j = 0; int count = 0; const int number_of_fields = 20; int closed = 1; int session_closed = 1; gf_gsync_status_t **status_values = NULL; char status_value_name[PATH_MAX] = ""; char *tmp = NULL; char *volume = NULL; char *volume_next = NULL; char *slave = NULL; char *slave_next = NULL; char *title_values[] = {"master_node", "", "master_brick", "slave_user", "slave", "slave_node", "status", "crawl_status", /* last_synced */ "", "entry", "data", "meta", "failures", /* checkpoint_time */ "", "checkpoint_completed", /* checkpoint_completion_time */ "", "master_node_uuid", /* last_synced_utc */ "last_synced", /* checkpoint_time_utc */ "checkpoint_time", /* checkpoint_completion_time_utc */ "checkpoint_completion_time"}; GF_ASSERT (dict); ret = dict_get_int32 (dict, "gsync-count", &count); if (ret) goto out; status_values = GF_CALLOC (count, sizeof (gf_gsync_status_t *), gf_common_mt_char); if (!status_values) { ret = -1; goto out; } for (i = 0; i < count; i++) { status_values[i] = GF_CALLOC (1, sizeof (gf_gsync_status_t), gf_common_mt_char); if (!status_values[i]) { ret = -1; goto out; } snprintf (status_value_name, sizeof (status_value_name), "status_value%d", i); ret = dict_get_bin (dict, status_value_name, (void **)&(status_values[i])); if (ret) { gf_log ("cli", GF_LOG_ERROR, "struct member empty."); goto out; } } qsort(status_values, count, sizeof (gf_gsync_status_t *), gf_gsync_status_t_comparator); for (i = 0; i < count; i++) { if (closed) { ret = xmlTextWriterStartElement (writer, (xmlChar *)"volume"); XML_RET_CHECK_AND_GOTO (ret, out); tmp = get_struct_variable (1, status_values[i]); if (!tmp) { gf_log ("cli", GF_LOG_ERROR, "struct member empty."); ret = -1; goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"name", "%s",tmp); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterStartElement (writer, (xmlChar *)"sessions"); XML_RET_CHECK_AND_GOTO (ret, out); closed = 0; } if (session_closed) { ret = xmlTextWriterStartElement (writer, (xmlChar *)"session"); XML_RET_CHECK_AND_GOTO (ret, out); session_closed = 0; tmp = get_struct_variable (21, status_values[i]); if (!tmp) { gf_log ("cli", GF_LOG_ERROR, "struct member empty."); ret = -1; goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"session_slave", "%s", tmp); XML_RET_CHECK_AND_GOTO (ret, out); } ret = xmlTextWriterStartElement (writer, (xmlChar *)"pair"); XML_RET_CHECK_AND_GOTO (ret, out); for (j = 0; j < number_of_fields; j++) { /* XML ignore fields */ if (strcmp(title_values[j], "") == 0) continue; tmp = get_struct_variable (j, status_values[i]); if (!tmp) { gf_log ("cli", GF_LOG_ERROR, "struct member empty."); ret = -1; goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)title_values[j], "%s", tmp); XML_RET_CHECK_AND_GOTO (ret, out); } ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); if (i+1 < count) { slave = get_struct_variable (20, status_values[i]); slave_next = get_struct_variable (20, status_values[i+1]); volume = get_struct_variable (1, status_values[i]); volume_next = get_struct_variable (1, status_values[i+1]); if (!slave || !slave_next || !volume || !volume_next) { gf_log ("cli", GF_LOG_ERROR, "struct member empty."); ret = -1; goto out; } if (strcmp (volume, volume_next)!=0) { closed = 1; session_closed = 1; ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } else if (strcmp (slave, slave_next)!=0) { session_closed = 1; ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } } else { ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } } out: gf_log ("cli",GF_LOG_DEBUG, "Returning %d", ret); return ret; } #endif int cli_xml_output_vol_gsync (dict_t *dict, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; char *master = NULL; char *slave = NULL; int type = 0; GF_ASSERT (dict); ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"geoRep"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "type", &type); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get type"); goto out; } switch (type) { case GF_GSYNC_OPTION_TYPE_START: case GF_GSYNC_OPTION_TYPE_STOP: case GF_GSYNC_OPTION_TYPE_PAUSE: case GF_GSYNC_OPTION_TYPE_RESUME: case GF_GSYNC_OPTION_TYPE_CREATE: case GF_GSYNC_OPTION_TYPE_DELETE: if (dict_get_str (dict, "master", &master) != 0) master = "???"; if (dict_get_str (dict, "slave", &slave) != 0) slave = "???"; ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"master", "%s", master); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"slave", "%s", slave); XML_RET_CHECK_AND_GOTO (ret, out); break; case GF_GSYNC_OPTION_TYPE_CONFIG: if (op_ret == 0) { ret = xmlTextWriterStartElement (writer, (xmlChar *)"config"); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_xml_generate_gsync_config (dict, writer); if (ret) goto out; ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } break; case GF_GSYNC_OPTION_TYPE_STATUS: ret = cli_xml_output_vol_gsync_status (dict, writer); break; default: ret = 0; break; } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_end_xml_output (writer, doc); out: gf_log ("cli",GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif } #if (HAVE_LIB_XML) /* This function will generate snapshot create output in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing create output * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_create (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) { int ret = -1; char *str_value = NULL; GF_ASSERT (writer); GF_ASSERT (doc); GF_ASSERT (dict); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapCreate"); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "snapname", &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "snapuuid", &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } /* This function will generate snapshot clone output in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing create output * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_clone (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) { int ret = -1; char *str_value = NULL; GF_VALIDATE_OR_GOTO ("cli", writer, out); GF_VALIDATE_OR_GOTO ("cli", doc, out); GF_VALIDATE_OR_GOTO ("cli", dict, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"CloneCreate"); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volume"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "clonename", &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get clone name"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "snapuuid", &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get clone uuid"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } /* This function will generate snapshot restore output in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing restore output * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_restore (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) { int ret = -1; char *str_value = NULL; GF_ASSERT (writer); GF_ASSERT (doc); GF_ASSERT (dict); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapRestore"); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volume"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "volname", &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get vol name"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "volid", &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get volume id"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "snapname", &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "snapuuid", &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } /* This function will generate snapshot list output in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing list output * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_list (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) { int ret = -1; int i = 0; int snapcount = 0; char *str_value = NULL; char key[PATH_MAX] = ""; GF_ASSERT (writer); GF_ASSERT (doc); GF_ASSERT (dict); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapList"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "snapcount", &snapcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snapcount"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "count", "%d", snapcount); XML_RET_CHECK_AND_GOTO (ret, out); for (i = 1; i <= snapcount; ++i) { ret = snprintf (key, sizeof (key), "snapname%d", i); if (ret < 0) { goto out; } ret = dict_get_str (dict, key, &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not get %s ", key); goto out; } else { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"snapshot", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); } } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } /* This function will generate xml output for origin volume * of the given snapshot. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing info output * @param keyprefix prefix for dictionary key * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_info_orig_vol (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict, char *keyprefix) { int ret = -1; int value = 0; char *buffer = NULL; char key [PATH_MAX] = ""; GF_ASSERT (dict); GF_ASSERT (keyprefix); GF_ASSERT (writer); GF_ASSERT (doc); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"originVolume"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%sorigin-volname", keyprefix); ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_WARNING, "Failed to get %s", key); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%ssnapcount", keyprefix); ret = dict_get_int32 (dict, key, &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "snapCount", "%d", value); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%ssnaps-available", keyprefix); ret = dict_get_int32 (dict, key, &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "snapRemaining", "%d", value); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } /* This function will generate xml output of snapshot volume info. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing info output * @param keyprefix key prefix for dictionary * @param snap_driven boolean to check if output is based of volume * or snapshot * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_info_snap_vol (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict, char *keyprefix, gf_boolean_t snap_driven) { char key [PATH_MAX] = ""; char *buffer = NULL; int ret = -1; GF_ASSERT (dict); GF_ASSERT (keyprefix); GF_ASSERT (writer); GF_ASSERT (doc); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapVolume"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.volname", keyprefix); ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.vol-status", keyprefix); ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get %s", key); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "status", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); /* If the command is snap_driven then we need to show origin volume * info. Else this is shown in the start of info display.*/ if (snap_driven) { snprintf (key, sizeof (key), "%s.", keyprefix); ret = cli_xml_snapshot_info_orig_vol (writer, doc, dict, key); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create " "xml output for snapshot's origin volume"); goto out; } } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } /* This function will generate snapshot info of individual snapshot * in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing info output * @param keyprefix key prefix for dictionary * @param snap_driven boolean to check if output is based of volume * or snapshot * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_info_per_snap (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict, char *keyprefix, gf_boolean_t snap_driven) { char key_buffer[PATH_MAX] = ""; char *buffer = NULL; int volcount = 0; int ret = -1; int i = 0; GF_ASSERT (dict); GF_ASSERT (keyprefix); GF_ASSERT (writer); GF_ASSERT (doc); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key_buffer, sizeof (key_buffer), "%s.snapname", keyprefix); ret = dict_get_str (dict, key_buffer, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to fetch snapname %s ", key_buffer); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key_buffer, sizeof (key_buffer), "%s.snap-id", keyprefix); ret = dict_get_str (dict, key_buffer, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to fetch snap-id %s ", key_buffer); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key_buffer, sizeof (key_buffer), "%s.snap-desc", keyprefix); ret = dict_get_str (dict, key_buffer, &buffer); if (!ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "description", "%s", buffer); } else { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "description", "%s", ""); } XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key_buffer, sizeof (key_buffer), "%s.snap-time", keyprefix); ret = dict_get_str (dict, key_buffer, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to fetch snap-time %s ", keyprefix); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "createTime", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key_buffer, sizeof (key_buffer), "%s.vol-count", keyprefix); ret = dict_get_int32 (dict, key_buffer, &volcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Fail to get snap vol count"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "volCount", "%d", volcount); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, key_buffer, &volcount); /* Display info of each snapshot volume */ for (i = 1 ; i <= volcount ; i++) { snprintf (key_buffer, sizeof (key_buffer), "%s.vol%d", keyprefix, i); ret = cli_xml_snapshot_info_snap_vol (writer, doc, dict, key_buffer, snap_driven); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not list " "details of volume in a snap"); goto out; } } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); out: return ret; } /* This function will generate snapshot info output in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing info output * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_info (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) { int ret = -1; int i = 0; int snapcount = 0; char key [PATH_MAX] = ""; gf_boolean_t snap_driven = _gf_false; GF_ASSERT (writer); GF_ASSERT (doc); GF_ASSERT (dict); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapInfo"); XML_RET_CHECK_AND_GOTO (ret, out); snap_driven = dict_get_str_boolean (dict, "snap-driven", _gf_false); /* If the approach is volume based then we should display orgin volume * information first followed by per snap info*/ if (!snap_driven) { ret = cli_xml_snapshot_info_orig_vol (writer, doc, dict, ""); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create " "xml output for snapshot's origin volume"); goto out; } } ret = dict_get_int32 (dict, "snapcount", &snapcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snapcount"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "count", "%d", snapcount); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshots"); XML_RET_CHECK_AND_GOTO (ret, out); /* Get snapshot info of individual snapshots */ for (i = 1; i <= snapcount; ++i) { snprintf (key, sizeof (key), "snap%d", i); ret = cli_xml_snapshot_info_per_snap (writer, doc, dict, key, snap_driven); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not get %s ", key); goto out; } } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } /* This function will generate snapshot status of individual * snapshot volume in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing status output * @param keyprefix key prefix for dictionary * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_volume_status (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict, const char *keyprefix) { int ret = -1; int brickcount = 0; int i = 0; int pid = 0; char *buffer = NULL; char key[PATH_MAX] = ""; GF_ASSERT (writer); GF_ASSERT (doc); GF_ASSERT (dict); GF_ASSERT (keyprefix); snprintf (key, sizeof (key), "%s.brickcount", keyprefix); ret = dict_get_int32 (dict, key, &brickcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to fetch brickcount"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "brickCount", "%d", brickcount); XML_RET_CHECK_AND_GOTO (ret, out); /* Get status of every brick belonging to the snapshot volume */ for (i = 0 ; i < brickcount ; i++) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"brick"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.brick%d.path", keyprefix, i); ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get Brick Path"); /* * If path itself is not present, then end * * this brick's status and continue to the * * brick * */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); continue; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "path", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.brick%d.vgname", keyprefix, i); ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get Volume Group"); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "volumeGroup", "N/A"); } else ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "volumeGroup", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.brick%d.status", keyprefix, i); ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_INFO, "Unable to get Brick Running"); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "brick_running", "N/A"); } else ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "brick_running", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.brick%d.pid", keyprefix, i); ret = dict_get_int32 (dict, key, &pid); if (ret) { gf_log ("cli", GF_LOG_INFO, "Unable to get pid"); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "pid", "N/A"); } else ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "pid", "%d", pid); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.brick%d.data", keyprefix, i); ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get Data Percent"); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "data_percentage", "N/A"); } else ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "data_percentage", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.brick%d.lvsize", keyprefix, i); ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get LV Size"); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "lvSize", "N/A"); } else { /* Truncate any newline character */ buffer = strtok (buffer, "\n"); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "lvSize", "%s", buffer); } XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } out: return ret; } /* This function will generate snapshot status of individual * snapshot in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing status output * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_status_per_snap (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict, const char *keyprefix) { int ret = -1; int volcount = 0; int i = 0; char *buffer = NULL; char key [PATH_MAX] = ""; GF_ASSERT (writer); GF_ASSERT (doc); GF_ASSERT (dict); GF_ASSERT (keyprefix); ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.snapname", keyprefix); ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get snapname"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.uuid", keyprefix); ret = dict_get_str (dict, key, &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get snap UUID"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.volcount", keyprefix); ret = dict_get_int32 (dict, key, &volcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to get volume count"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "volCount", "%d", volcount); XML_RET_CHECK_AND_GOTO (ret, out); /* Get snapshot status of individual snapshot volume */ for (i = 0 ; i < volcount ; i++) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volume"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (key, sizeof (key), "%s.vol%d", keyprefix, i); ret = cli_xml_snapshot_volume_status (writer, doc, dict, key); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not get snap volume status"); goto out; } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } /* This function will generate snapshot status output in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing status output * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_status (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) { int ret = -1; int snapcount = 0; int i = 0; int status_cmd = 0; char key [PATH_MAX] = ""; GF_ASSERT (writer); GF_ASSERT (doc); GF_ASSERT (dict); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapStatus"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "sub-cmd", &status_cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch status type"); goto out; } if ((GF_SNAP_STATUS_TYPE_SNAP == status_cmd) || (GF_SNAP_STATUS_TYPE_ITER == status_cmd)) { snapcount = 1; } else { ret = dict_get_int32 (dict, "status.snapcount", &snapcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not get snapcount"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "count", "%d", snapcount); XML_RET_CHECK_AND_GOTO (ret, out); } for (i = 0 ; i < snapcount; i++) { snprintf (key, sizeof (key), "status.snap%d", i); ret = cli_xml_snapshot_status_per_snap (writer, doc, dict, key); if (ret < 0) { gf_log ("cli", GF_LOG_ERROR, "failed to create xml " "output for snapshot status"); goto out; } } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } /* This function will generate snapshot config show output in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing status output * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_config_show (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) { int ret = -1; uint64_t i = 0; uint64_t value = 0; uint64_t volcount = 0; char buf[PATH_MAX] = ""; char *str_value = NULL; GF_ASSERT (writer); GF_ASSERT (doc); GF_ASSERT (dict); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"systemConfig"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_uint64 (dict, "snap-max-hard-limit", &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get " "snap-max-hard-limit"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "hardLimit", "%"PRIu64, value); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_uint64 (dict, "snap-max-soft-limit", &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get " "snap-max-soft-limit"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "softLimit", "%"PRIu64"%%", value); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "auto-delete", &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch auto-delete"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "autoDelete", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "snap-activate-on-create", &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch snap-activate-on-create-delete"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "activateOnCreate", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volumeConfig"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_uint64 (dict, "voldisplaycount", &volcount); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch volcount"); goto out; } /* Get config of all the volumes */ for (i = 0; i < volcount; i++) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volume"); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (buf, sizeof(buf), "volume%"PRIu64"-volname", i); ret = dict_get_str (dict, buf, &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch %s", buf); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (buf, sizeof(buf), "volume%"PRIu64"-snap-max-hard-limit", i); ret = dict_get_uint64 (dict, buf, &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch %s", buf); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "hardLimit", "%"PRIu64, value); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (buf, sizeof(buf), "volume%"PRIu64"-active-hard-limit", i); ret = dict_get_uint64 (dict, buf, &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch" " effective snap_max_hard_limit for " "%s", str_value); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "effectiveHardLimit", "%"PRIu64, value); XML_RET_CHECK_AND_GOTO (ret, out); snprintf (buf, sizeof(buf), "volume%"PRIu64"-snap-max-soft-limit", i); ret = dict_get_uint64 (dict, buf, &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch %s", buf); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "softLimit", "%"PRIu64, value); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } /* This function will generate snapshot config set output in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing status output * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_config_set (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) { int ret = -1; uint64_t hard_limit = 0; uint64_t soft_limit = 0; char *volname = NULL; char *auto_delete = NULL; char *snap_activate = NULL; GF_ASSERT (writer); GF_ASSERT (doc); GF_ASSERT (dict); /* This is optional parameter therefore ignore the error */ ret = dict_get_uint64 (dict, "snap-max-hard-limit", &hard_limit); /* This is optional parameter therefore ignore the error */ ret = dict_get_uint64 (dict, "snap-max-soft-limit", &soft_limit); ret = dict_get_str (dict, "auto-delete", &auto_delete); ret = dict_get_str (dict, "snap-activate-on-create", &snap_activate); if (!hard_limit && !soft_limit && !auto_delete && !snap_activate) { ret = -1; gf_log ("cli", GF_LOG_ERROR, "At least one option from " "snap-max-hard-limit, snap-max-soft-limit, auto-delete" " and snap-activate-on-create should be set"); goto out; } /* Ignore the error, as volname is optional */ ret = dict_get_str (dict, "volname", &volname); if (NULL == volname) { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"systemConfig"); } else { /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"volumeConfig"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", volname); } XML_RET_CHECK_AND_GOTO (ret, out); if (hard_limit) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "newHardLimit", "%"PRIu64, hard_limit); XML_RET_CHECK_AND_GOTO (ret, out); } if (soft_limit) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "newSoftLimit", "%"PRIu64, soft_limit); XML_RET_CHECK_AND_GOTO (ret, out); } if (auto_delete) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "autoDelete", "%s", auto_delete); XML_RET_CHECK_AND_GOTO (ret, out); } if (snap_activate) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "activateOnCreate", "%s", snap_activate); XML_RET_CHECK_AND_GOTO (ret, out); } /* or */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } /* This function will generate snapshot config output in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing config output * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_config (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict) { int ret = -1; int config_command = 0; GF_ASSERT (writer); GF_ASSERT (doc); GF_ASSERT (dict); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapConfig"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "config-command", &config_command); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch config type"); goto out; } switch (config_command) { case GF_SNAP_CONFIG_TYPE_SET: ret = cli_xml_snapshot_config_set (writer, doc, dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create xml " "output for snapshot config set command"); goto out; } break; case GF_SNAP_CONFIG_DISPLAY: ret = cli_xml_snapshot_config_show (writer, doc, dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create xml " "output for snapshot config show command"); goto out; } break; default: gf_log ("cli", GF_LOG_ERROR, "Unknown config command :%d", config_command); ret = -1; goto out; } /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } /* This function will generate snapshot activate or * deactivate output in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing activate or deactivate output * * @return 0 on success and -1 on failure */ static int cli_xml_snapshot_activate_deactivate (xmlTextWriterPtr writer, xmlDocPtr doc, dict_t *dict, int cmd) { int ret = -1; char *buffer = NULL; char *tag = NULL; GF_ASSERT (writer); GF_ASSERT (doc); GF_ASSERT (dict); if (GF_SNAP_OPTION_TYPE_ACTIVATE == cmd) { tag = "snapActivate"; } else if (GF_SNAP_OPTION_TYPE_DEACTIVATE == cmd) { tag = "snapDeactivate"; } else { gf_log ("cli", GF_LOG_ERROR, "invalid command %d", cmd); goto out; } /* or */ ret = xmlTextWriterStartElement (writer, (xmlChar *)tag); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "snapname", &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "snapuuid", &buffer); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", "%s", buffer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); /* or */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); ret = 0; out: return ret; } #endif /* HAVE_LIB_XML */ /* This function will generate snapshot delete output in xml format. * * @param writer xmlTextWriterPtr * @param doc xmlDocPtr * @param dict dict containing delete output * @param rsp cli response * * @return 0 on success and -1 on failure */ int cli_xml_snapshot_delete (cli_local_t *local, dict_t *dict, gf_cli_rsp *rsp) { int ret = -1; #ifdef HAVE_LIB_XML char *str_value = NULL; xmlTextWriterPtr writer = local->writer; xmlDocPtr doc = local->doc; GF_ASSERT (writer); GF_ASSERT (doc); GF_ASSERT (dict); /* */ ret = xmlTextWriterStartElement (writer, (xmlChar *)"snapshot"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_str (dict, "snapname", &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap name"); goto xmlend; } if (!rsp->op_ret) { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "status", "Success"); } else { ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "status", "Failure"); XML_RET_CHECK_AND_GOTO (ret, xmlend); ret = cli_xml_output_common (writer, rsp->op_ret, rsp->op_errno, rsp->op_errstr); } XML_RET_CHECK_AND_GOTO (ret, xmlend); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "name", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, xmlend); ret = dict_get_str (dict, "snapuuid", &str_value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snap uuid"); goto xmlend; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *) "uuid", "%s", str_value); XML_RET_CHECK_AND_GOTO (ret, out); xmlend: /* */ ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); #endif /* HAVE_LIB_XML */ ret = 0; out: return ret; } int cli_xml_output_snap_status_begin (cli_local_t *local, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; GF_ASSERT (local); ret = cli_begin_xml_output (&(local->writer), &(local->doc)); XML_RET_CHECK_AND_GOTO (ret, out); ret = cli_xml_output_common (local->writer, op_ret, op_errno, op_errstr); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *) "snapStatus"); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"snapshots"); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_TRACE, "Returning %d", ret); return ret; #else return 0; #endif } int cli_xml_output_snap_status_end (cli_local_t *local) { #if (HAVE_LIB_XML) int ret = -1; GF_ASSERT (local); /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO(ret, out); ret = cli_end_xml_output (local->writer, local->doc); out: gf_log ("cli", GF_LOG_TRACE, "Returning %d", ret); return ret; #else return 0; #endif } int cli_xml_output_snap_delete_begin (cli_local_t *local, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; int delete_cmd = -1; GF_ASSERT (local); ret = cli_begin_xml_output (&(local->writer), &(local->doc)); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (local->dict, "sub-cmd", &delete_cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get sub-cmd"); goto out; } ret = cli_xml_output_common (local->writer, op_ret, op_errno, op_errstr); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *) "snapDelete"); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"snapshots"); XML_RET_CHECK_AND_GOTO (ret, out); out: gf_log ("cli", GF_LOG_TRACE, "Returning %d", ret); return ret; #else return 0; #endif } int cli_xml_output_snap_delete_end (cli_local_t *local) { #if (HAVE_LIB_XML) int ret = -1; GF_ASSERT (local); /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); /* */ ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO(ret, out); ret = cli_end_xml_output (local->writer, local->doc); out: gf_log ("cli", GF_LOG_TRACE, "Returning %d", ret); return ret; #else return 0; #endif } /* This function will generate xml output for all the snapshot commands * * @param cmd_type command type * @param dict dict containing snapshot command output * @param op_ret return value of the snapshot command * @param op_errno errno for the snapshot command * @param op_errstr error string for the snapshot command * * @return 0 on success and -1 on failure */ int cli_xml_output_snapshot (int cmd_type, dict_t *dict, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int ret = -1; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; GF_ASSERT (dict); ret = cli_begin_xml_output (&writer, &doc); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to output " "xml begin block"); goto out; } ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to output " "xml common block"); goto out; } /* In case of command failure just printing the error message is good * enough */ if (0 != op_ret) { goto end; } switch (cmd_type) { case GF_SNAP_OPTION_TYPE_CREATE: ret = cli_xml_snapshot_create (writer, doc, dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create " "xml output for snapshot create command"); goto out; } break; case GF_SNAP_OPTION_TYPE_CLONE: ret = cli_xml_snapshot_clone (writer, doc, dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create " "xml output for snapshot clone command"); goto out; } break; case GF_SNAP_OPTION_TYPE_RESTORE: ret = cli_xml_snapshot_restore (writer, doc, dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create " "xml output for snapshot restore command"); goto out; } break; case GF_SNAP_OPTION_TYPE_LIST: ret = cli_xml_snapshot_list (writer, doc, dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create " "xml output for snapshot list command"); goto out; } break; case GF_SNAP_OPTION_TYPE_STATUS: ret = cli_xml_snapshot_status (writer, doc, dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create" "xml output for snapshot status command"); goto out; } break; case GF_SNAP_OPTION_TYPE_INFO: ret = cli_xml_snapshot_info (writer, doc, dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create " "xml output for snapshot info command"); goto out; } break; case GF_SNAP_OPTION_TYPE_ACTIVATE: case GF_SNAP_OPTION_TYPE_DEACTIVATE: ret = cli_xml_snapshot_activate_deactivate (writer, doc, dict, cmd_type); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create " "xml output for snapshot config command"); } break; case GF_SNAP_OPTION_TYPE_CONFIG: ret = cli_xml_snapshot_config (writer, doc, dict); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to create " "xml output for snapshot config command"); } break; default: gf_log ("cli", GF_LOG_ERROR, "Unexpected snapshot command: %d", cmd_type); goto out; } end: ret = cli_end_xml_output (writer, doc); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to output " "xml end block"); goto out; } ret = 0; out: return ret; #else return 0; #endif /* HAVE_LIB_XML */ } int cli_xml_snapshot_begin_composite_op (cli_local_t *local) { int ret = -1; #ifdef HAVE_LIB_XML int cmd = -1; int type = -1; ret = dict_get_int32 (local->dict, "sub-cmd", &cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get " "sub-cmd"); ret = 0; goto out; } if (cmd == GF_SNAP_STATUS_TYPE_ITER || cmd == GF_SNAP_DELETE_TYPE_SNAP){ ret = 0; goto out; } ret = dict_get_int32 (local->dict, "type", &type); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snapshot " "command type from dictionary"); goto out; } if (GF_SNAP_OPTION_TYPE_STATUS == type) ret = cli_xml_output_snap_status_begin (local, 0, 0, NULL); else if (GF_SNAP_OPTION_TYPE_DELETE == type) ret = cli_xml_output_snap_delete_begin (local, 0, 0, NULL); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error creating xml output"); goto out; } #endif /* HAVE_LIB_XML */ ret = 0; out: return ret; } int cli_xml_snapshot_end_composite_op (cli_local_t *local) { int ret = -1; #ifdef HAVE_LIB_XML int cmd = -1; int type = -1; ret = dict_get_int32 (local->dict, "sub-cmd", &cmd); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get " "sub-cmd"); ret = 0; goto out; } if (cmd == GF_SNAP_STATUS_TYPE_ITER || cmd == GF_SNAP_DELETE_TYPE_SNAP){ ret = 0; goto out; } ret = dict_get_int32 (local->dict, "type", &type); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snapshot " "command type from dictionary"); goto out; } if (GF_SNAP_OPTION_TYPE_STATUS == type) ret = cli_xml_output_snap_status_end (local); else if (GF_SNAP_OPTION_TYPE_DELETE == type) ret = cli_xml_output_snap_delete_end (local); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error creating xml " "output"); goto out; } #endif /* HAVE_LIB_XML */ ret = 0; out: return ret; } int cli_xml_snapshot_status_single_snap (cli_local_t *local, dict_t *dict, char *key) { #if (HAVE_LIB_XML) int ret = -1; GF_VALIDATE_OR_GOTO ("cli", (local != NULL), out); GF_VALIDATE_OR_GOTO ("cli", (dict != NULL), out); GF_VALIDATE_OR_GOTO ("cli", (key != NULL), out); ret = cli_xml_snapshot_status_per_snap (local->writer, local->doc, dict, key); out: return ret; #else return 0; #endif /* HAVE_LIB_XML */ } int cli_xml_output_vol_getopts (dict_t *dict, int op_ret, int op_errno, char *op_errstr) { #if (HAVE_LIB_XML) int i = 0; int ret = -1; int count = 0; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; char *key = NULL; char *value = NULL; char dict_key[50] = {0,}; ret = cli_begin_xml_output (&writer, &doc); if (ret) goto out; ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); if (ret) goto out; ret = xmlTextWriterStartElement (writer, (xmlChar *)"volGetopts"); XML_RET_CHECK_AND_GOTO (ret, out); ret = dict_get_int32 (dict, "count", &count); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to retrieve count " "from the dictionary"); goto out; } if (count <= 0) { gf_log ("cli", GF_LOG_ERROR, "Value of count :%d is " "invalid", count); ret = -1; goto out; } ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", "%d", count); XML_RET_CHECK_AND_GOTO (ret, out); for (i=1; i<=count; i++) { sprintf (dict_key, "key%d", i); ret = dict_get_str (dict, dict_key, &key); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to" " retrieve %s from the " "dictionary", dict_key); goto out; } sprintf (dict_key, "value%d", i); ret = dict_get_str (dict, dict_key, &value); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to " "retrieve key value for %s from" "the dictionary", dict_key); goto out; } ret = xmlTextWriterStartElement (writer, (xmlChar *)"Opt"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"Option", "%s", key); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"Value", "%s", value); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterEndElement (writer); XML_RET_CHECK_AND_GOTO (ret, out); } ret = cli_end_xml_output (writer, doc); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; #else return 0; #endif /* HAVE_LIB_XML */ } int cli_quota_list_xml_error (cli_local_t *local, char *path, char *errstr) { #if (HAVE_LIB_XML) int ret = -1; ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"limit"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"path", "%s", path); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"errstr", "%s", errstr); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); out: return ret; #else return 0; #endif } int cli_quota_xml_output (cli_local_t *local, char *path, int64_t hl_str, char *sl_final, int64_t sl_num, int64_t used, int64_t avail, char *sl, char *hl, gf_boolean_t limit_set) { #if (HAVE_LIB_XML) int ret = -1; ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"limit"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"path", "%s", path); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"hard_limit", !limit_set ? "N/A" : "%"PRId64, hl_str); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"soft_limit_percent", !limit_set ? "N/A" : "%s", sl_final); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"soft_limit_value", !limit_set ? "N/A" : "%"PRId64, sl_num); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"used_space", "%"PRId64, used); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"avail_space", !limit_set ? "N/A" : "%"PRId64, avail); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"sl_exceeded", !limit_set ? "N/A" : "%s", sl); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"hl_exceeded", !limit_set ? "N/A" : "%s", hl); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); out: return ret; #else return 0; #endif /* HAVE_LIB_XML */ } int cli_quota_object_xml_output (cli_local_t *local, char *path, char *sl_str, int64_t sl_val, quota_limits_t *limits, quota_meta_t *used_space, int64_t avail, char *sl, char *hl, gf_boolean_t limit_set) { #if (HAVE_LIB_XML) int ret = -1; ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"limit"); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"path", "%s", path); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"hard_limit", !limit_set ? "N/A" : "%"PRId64, limits->hl); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"soft_limit_percent", !limit_set ? "N/A" : "%s", sl_str); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"soft_limit_value", !limit_set ? "N/A" : "%"PRIu64, sl_val); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"file_count", "%"PRId64, used_space->file_count); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"dir_count", "%"PRIu64, used_space->dir_count); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"available", !limit_set ? "N/A" : "%"PRId64, avail); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"sl_exceeded", !limit_set ? "N/A" : "%s", sl); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterWriteFormatElement (local->writer, (xmlChar *)"hl_exceeded", !limit_set ? "N/A" : "%s", hl); XML_RET_CHECK_AND_GOTO (ret, out); ret = xmlTextWriterEndElement (local->writer); XML_RET_CHECK_AND_GOTO (ret, out); out: return ret; #else return 0; #endif /* HAVE_LIB_XML */ } glusterfs-3.13.2/cli/src/PaxHeaders.5796/cli-quotad-client.c0000644000000000000000000000013213230626775021600 xustar000000000000000030 mtime=1516449277.177371912 30 atime=1516449277.177371912 30 ctime=1516449329.366492967 glusterfs-3.13.2/cli/src/cli-quotad-client.c0000664000175100017510000001005213230626775022037 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2010-2013 Red Hat, Inc. This file is part of GlusterFS. 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 "cli-quotad-client.h" extern struct rpc_clnt global_quotad_rpc; extern struct rpc_clnt_program cli_quotad_clnt; int cli_quotad_submit_request (void *req, call_frame_t *frame, rpc_clnt_prog_t *prog, int procnum, struct iobref *iobref, xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc) { int ret = -1; int count = 0; struct iovec iov = {0, }; struct iobuf *iobuf = NULL; char new_iobref = 0; ssize_t xdr_size = 0; GF_ASSERT (this); if (req) { xdr_size = xdr_sizeof (xdrproc, req); iobuf = iobuf_get2 (this->ctx->iobuf_pool, xdr_size); if (!iobuf) { goto out; }; if (!iobref) { iobref = iobref_new (); if (!iobref) { goto out; } new_iobref = 1; } iobref_add (iobref, iobuf); iov.iov_base = iobuf->ptr; iov.iov_len = iobuf_size (iobuf); /* Create the xdr payload */ ret = xdr_serialize_generic (iov, req, xdrproc); if (ret == -1) { goto out; } iov.iov_len = ret; count = 1; } /* Send the msg */ ret = rpc_clnt_submit (&global_quotad_rpc, prog, procnum, cbkfn, &iov, count, NULL, 0, iobref, frame, NULL, 0, NULL, 0, NULL); ret = 0; out: if (new_iobref) iobref_unref (iobref); if (iobuf) iobuf_unref (iobuf); return ret; } int cli_quotad_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, void *data) { xlator_t *this = NULL; int ret = 0; this = mydata; switch (event) { case RPC_CLNT_CONNECT: { gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_CONNECT"); break; } case RPC_CLNT_DISCONNECT: { gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_DISCONNECT"); break; } default: gf_log (this->name, GF_LOG_TRACE, "got some other RPC event %d", event); ret = 0; break; } return ret; } struct rpc_clnt * cli_quotad_clnt_init (xlator_t *this, dict_t *options) { struct rpc_clnt *rpc = NULL; int ret = -1; ret = dict_set_str (options, "transport.address-family", "unix"); if (ret) goto out; ret = dict_set_str (options, "transport-type", "socket"); if (ret) goto out; ret = dict_set_str (options, "transport.socket.connect-path", "/var/run/gluster/quotad.socket"); if (ret) goto out; rpc = rpc_clnt_new (options, this, this->name, 16); if (!rpc) goto out; ret = rpc_clnt_register_notify (rpc, cli_quotad_notify, this); if (ret) { gf_log ("cli", GF_LOG_ERROR, "failed to register notify"); goto out; } rpc_clnt_start (rpc); out: if (ret) { if (rpc) rpc_clnt_unref (rpc); rpc = NULL; } return rpc; } glusterfs-3.13.2/cli/src/PaxHeaders.5796/cli-cmd-volume.c0000644000000000000000000000013113230626775021076 xustar000000000000000029 mtime=1516449277.17637191 30 atime=1516449277.175371908 30 ctime=1516449329.353492936 glusterfs-3.13.2/cli/src/cli-cmd-volume.c0000664000175100017510000035445513230626775021360 0ustar00jenkinsjenkins00000000000000/* Copyright (c) 2010-2012 Red Hat, Inc. This file is part of GlusterFS. 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 #include #include #include #include #include #include #include "cli.h" #include "cli-cmd.h" #include "cli-mem-types.h" #include "cli1-xdr.h" #include "run.h" #include "syscall.h" #include "common-utils.h" #include "events.h" extern struct rpc_clnt *global_rpc; extern struct rpc_clnt *global_quotad_rpc; extern rpc_clnt_prog_t *cli_rpc_prog; extern rpc_clnt_prog_t cli_quotad_clnt; int cli_cmd_volume_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word, const char **words, int wordcount); int cli_cmd_bitrot_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word, const char **words, int wordcount); int cli_cmd_quota_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word, const char **words, int wordcount); int cli_cmd_tier_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word, const char **words, int wordcount); int cli_cmd_volume_info_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; cli_cmd_volume_get_ctx_t ctx = {0,}; cli_local_t *local = NULL; int sent = 0; int parse_error = 0; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; if ((wordcount == 2) || (wordcount == 3 && !strcmp (words[2], "all"))) { ctx.flags = GF_CLI_GET_NEXT_VOLUME; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_NEXT_VOLUME]; } else if (wordcount == 3) { ctx.flags = GF_CLI_GET_VOLUME; ctx.volname = (char *)words[2]; if (strlen (ctx.volname) > GD_VOLUME_NAME_MAX) { cli_out ("Invalid volume name"); goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_VOLUME]; } else { cli_usage_out (word->pattern); parse_error = 1; return -1; } local = cli_local_get (); if (!local) goto out; local->get_vol.flags = ctx.flags; if (ctx.volname) local->get_vol.volname = gf_strdup (ctx.volname); frame->local = local; if (proc->fn) { ret = proc->fn (frame, THIS, &ctx); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Getting Volume information failed!"); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_sync_volume_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; int sent = 0; int parse_error = 0; dict_t *dict = NULL; cli_local_t *local = NULL; gf_answer_t answer = GF_ANSWER_NO; const char *question = "Sync volume may make data " "inaccessible while the sync " "is in progress. Do you want " "to continue?"; if ((wordcount < 3) || (wordcount > 4)) { cli_usage_out (word->pattern); parse_error = 1; goto out; } dict = dict_new (); if (!dict) goto out; if ((wordcount == 3) || !strcmp(words[3], "all")) { ret = dict_set_int32 (dict, "flags", (int32_t) GF_CLI_SYNC_ALL); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "failed to set" "flag"); goto out; } } else { ret = dict_set_str (dict, "volname", (char *) words[3]); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "failed to set " "volume"); goto out; } } ret = dict_set_str (dict, "hostname", (char *) words[2]); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "failed to set hostname"); goto out; } if (!(state->mode & GLUSTER_MODE_SCRIPT)) { answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_SYNC_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; CLI_LOCAL_INIT (local, words, frame, dict); if (proc->fn) { ret = proc->fn (frame, THIS, dict); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume sync failed"); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_create_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; char *trans_type = NULL; char *bricks = NULL; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_CREATE_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_create_parse (state, words, wordcount, &options, &bricks); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } ret = dict_get_str (options, "transport", &trans_type); if (ret) { gf_log("cli", GF_LOG_ERROR, "Unable to get transport type"); goto out; } if (state->mode & GLUSTER_MODE_WIGNORE) { ret = dict_set_int32 (options, "force", _gf_true); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set force " "option"); goto out; } } CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume create failed"); } if (ret == 0) { gf_event (EVENT_VOLUME_CREATE, "name=%s;bricks=%s", (char *)words[2], bricks); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_delete_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; char *volname = NULL; gf_answer_t answer = GF_ANSWER_NO; const char *question = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; dict_t *dict = NULL; question = "Deleting volume will erase all information about the volume. " "Do you want to continue?"; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_DELETE_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; dict = dict_new (); if (!dict) goto out; if (wordcount != 3) { cli_usage_out (word->pattern); parse_error = 1; goto out; } volname = (char *)words[2]; ret = dict_set_str (dict, "volname", volname); if (ret) { gf_log (THIS->name, GF_LOG_WARNING, "dict set failed"); goto out; } if (!strcmp (volname, GLUSTER_SHARED_STORAGE)) { question = "Deleting the shared storage volume" "(gluster_shared_storage), will affect features " "like snapshot scheduler, geo-replication " "and NFS-Ganesha. Do you still want to " "continue?"; } answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } CLI_LOCAL_INIT (local, words, frame, dict); if (proc->fn) { ret = proc->fn (frame, THIS, dict); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume delete failed"); } CLI_STACK_DESTROY (frame); if (ret == 0 && GF_ANSWER_YES == answer) { gf_event (EVENT_VOLUME_DELETE, "name=%s", (char *)words[2]); } return ret; } int cli_cmd_volume_start_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; int sent = 0; int parse_error = 0; dict_t *dict = NULL; int flags = 0; cli_local_t *local = NULL; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; if (wordcount < 3 || wordcount > 4) { cli_usage_out (word->pattern); parse_error = 1; goto out; } dict = dict_new (); if (!dict) { goto out; } if (!words[2]) goto out; ret = dict_set_str (dict, "volname", (char *)words[2]); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "dict set failed"); goto out; } if (wordcount == 4) { if (!strcmp("force", words[3])) { flags |= GF_CLI_FLAG_OP_FORCE; } else { ret = -1; cli_usage_out (word->pattern); parse_error = 1; goto out; } } ret = dict_set_int32 (dict, "flags", flags); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "dict set failed"); goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_START_VOLUME]; CLI_LOCAL_INIT (local, words, frame, dict); if (proc->fn) { ret = proc->fn (frame, THIS, dict); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume start failed"); } CLI_STACK_DESTROY (frame); if (ret == 0) { gf_event (EVENT_VOLUME_START, "name=%s;force=%d", (char *)words[2], (flags & GF_CLI_FLAG_OP_FORCE)); } return ret; } gf_answer_t cli_cmd_get_confirmation (struct cli_state *state, const char *question) { char answer[5] = {'\0', }; int flush = '\0'; size_t len; if (state->mode & GLUSTER_MODE_SCRIPT) return GF_ANSWER_YES; printf ("%s (y/n) ", question); if (fgets (answer, 4, stdin) == NULL) { cli_out("gluster cli read error"); goto out; } len = strlen (answer); if (len && answer [len - 1] == '\n'){ answer [--len] = '\0'; } else { do{ flush = getchar (); }while (flush != '\n'); } if (len > 3) goto out; if (!strcasecmp (answer, "y") || !strcasecmp (answer, "yes")) return GF_ANSWER_YES; else if (!strcasecmp (answer, "n") || !strcasecmp (answer, "no")) return GF_ANSWER_NO; out: cli_out ("Invalid input, please enter y/n"); return GF_ANSWER_NO; } int cli_cmd_volume_stop_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; int flags = 0; gf_answer_t answer = GF_ANSWER_NO; int sent = 0; int parse_error = 0; dict_t *dict = NULL; char *volname = NULL; cli_local_t *local = NULL; const char *question = "Stopping volume will make its data inaccessible. " "Do you want to continue?"; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; if (wordcount < 3 || wordcount > 4) { cli_usage_out (word->pattern); parse_error = 1; goto out; } volname = (char*) words[2]; dict = dict_new (); ret = dict_set_str (dict, "volname", volname); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "dict set failed"); goto out; } if (!strcmp (volname, GLUSTER_SHARED_STORAGE)) { question = "Stopping the shared storage volume" "(gluster_shared_storage), will affect features " "like snapshot scheduler, geo-replication " "and NFS-Ganesha. Do you still want to " "continue?"; } if (wordcount == 4) { if (!strcmp("force", words[3])) { flags |= GF_CLI_FLAG_OP_FORCE; } else { ret = -1; cli_usage_out (word->pattern); parse_error = 1; goto out; } } ret = dict_set_int32 (dict, "flags", flags); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "dict set failed"); goto out; } answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STOP_VOLUME]; CLI_LOCAL_INIT (local, words, frame, dict); if (proc->fn) { ret = proc->fn (frame, THIS, dict); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume stop on '%s' failed", volname); } CLI_STACK_DESTROY (frame); if (ret == 0 && GF_ANSWER_YES == answer) { gf_event (EVENT_VOLUME_STOP, "name=%s;force=%d", (char *)words[2], (flags & GF_CLI_FLAG_OP_FORCE)); } return ret; } int cli_cmd_volume_rename_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *dict = NULL; int sent = 0; int parse_error = 0; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; dict = dict_new (); if (!dict) goto out; if (wordcount != 4) { cli_usage_out (word->pattern); parse_error = 1; goto out; } ret = dict_set_str (dict, "old-volname", (char *)words[2]); if (ret) goto out; ret = dict_set_str (dict, "new-volname", (char *)words[3]); if (ret) goto out; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_RENAME_VOLUME]; if (proc->fn) { ret = proc->fn (frame, THIS, dict); } out: if (dict) dict_unref (dict); if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume rename on '%s' failed", (char *)words[2]); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_defrag_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *dict = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; #if (USE_EVENTS) eventtypes_t event = EVENT_LAST; #endif #ifdef GF_SOLARIS_HOST_OS cli_out ("Command not supported on Solaris"); goto out; #endif frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_defrag_parse (words, wordcount, &dict); if (ret) { cli_usage_out (word->pattern); parse_error = 1; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_DEFRAG_VOLUME]; CLI_LOCAL_INIT (local, words, frame, dict); if (proc->fn) { ret = proc->fn (frame, THIS, dict); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume rebalance failed"); } else { #if (USE_EVENTS) if (!(strcmp (words[wordcount-1], "start")) || !(strcmp (words[wordcount-1], "force"))) { event = EVENT_VOLUME_REBALANCE_START; } else if (!strcmp (words[wordcount-1], "stop")) { event = EVENT_VOLUME_REBALANCE_STOP; } if (event != EVENT_LAST) gf_event (event, "volume=%s", (char *)words[2]); #endif } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_reset_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int sent = 0; int parse_error = 0; int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; cli_local_t *local = NULL; #if (USE_EVENTS) int ret1 = -1; char *tmp_opt = NULL; #endif proc = &cli_rpc_prog->proctable[GLUSTER_CLI_RESET_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_reset_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume reset failed"); } #if (USE_EVENTS) if (ret == 0) { ret1 = dict_get_str (options, "key", &tmp_opt); if (ret1) tmp_opt = ""; gf_event (EVENT_VOLUME_RESET, "name=%s;option=%s", (char *)words[2], tmp_opt); } #endif CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_profile_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int sent = 0; int parse_error = 0; int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; cli_local_t *local = NULL; ret = cli_cmd_volume_profile_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_PROFILE_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume profile failed"); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_set_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int sent = 0; int parse_error = 0; int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; cli_local_t *local = NULL; char *op_errstr = NULL; #if (USE_EVENTS) int ret1 = -1; int i = 1; char dict_key[50] = {0,}; char *tmp_opt = NULL; char *opts_str = NULL; int num_options = 0; #endif proc = &cli_rpc_prog->proctable[GLUSTER_CLI_SET_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_set_parse (state, words, wordcount, &options, &op_errstr); if (ret) { if (op_errstr) { cli_err ("%s", op_errstr); GF_FREE (op_errstr); } else cli_usage_out (word->pattern); parse_error = 1; goto out; } CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume set failed"); } #if (USE_EVENTS) if (ret == 0 && strcmp(words[2], "help") != 0) { ret1 = dict_get_int32 (options, "count", &num_options); if (ret1) num_options = 0; else num_options = num_options/2; /* Initialize opts_str */ opts_str = gf_strdup (""); /* Prepare String in format options=KEY1,VALUE1,KEY2,VALUE2 */ for (i = 1; i <= num_options; i++) { sprintf (dict_key, "key%d", i); ret1 = dict_get_str (options, dict_key, &tmp_opt); if (ret1) tmp_opt = ""; gf_asprintf (&opts_str, "%s,%s", opts_str, tmp_opt); sprintf (dict_key, "value%d", i); ret1 = dict_get_str (options, dict_key, &tmp_opt); if (ret1) tmp_opt = ""; gf_asprintf (&opts_str, "%s,%s", opts_str, tmp_opt); } gf_event (EVENT_VOLUME_SET, "name=%s;options=%s", (char *)words[2], opts_str); /* Allocated by gf_strdup and gf_asprintf */ GF_FREE (opts_str); } #endif CLI_STACK_DESTROY (frame); return ret; } static int cli_event_remove_brick_str (dict_t *options, char **event_str, eventtypes_t *event) { int ret = -1; char *bricklist = NULL; char *brick = NULL; char *volname = NULL; char key[256] = {0,}; const char *eventstrformat = "volume=%s;bricks=%s"; int32_t command = 0; int32_t i = 1; int32_t count = 0; int32_t eventstrlen = 1; char *tmp_ptr = NULL; if (!options || !event_str || !event) goto out; ret = dict_get_str (options, "volname", &volname); if (ret || !volname) { gf_log ("cli", GF_LOG_ERROR, "Failed to fetch volname"); ret = -1; goto out; } /* Get the list of bricks for the event */ ret = dict_get_int32 (options, "command", &command); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to fetch command"); ret = -1; goto out; } switch (command) { case GF_OP_CMD_START: *event = EVENT_VOLUME_REMOVE_BRICK_START; break; case GF_OP_CMD_COMMIT: *event = EVENT_VOLUME_REMOVE_BRICK_COMMIT; break; case GF_OP_CMD_COMMIT_FORCE: *event = EVENT_VOLUME_REMOVE_BRICK_FORCE; break; case GF_OP_CMD_STOP: *event = EVENT_VOLUME_REMOVE_BRICK_STOP; break; default: *event = EVENT_LAST; break; } ret = -1; if (*event == EVENT_LAST) { goto out; } /* I could just get this from words[] but this is cleaner in case the * format changes */ while (i) { snprintf (key, sizeof (key), "brick%d", i); ret = dict_get_str (options, key, &brick); if (ret) { break; } eventstrlen += strlen (brick) + 1; i++; } count = --i; eventstrlen += 1; bricklist = GF_CALLOC (eventstrlen, sizeof (char), gf_common_mt_char); if (!bricklist) { goto out; } tmp_ptr = bricklist; i = 1; while (i <= count) { snprintf (key, sizeof (key), "brick%d", i); ret = dict_get_str (options, key, &brick); if (ret) { break; } snprintf (tmp_ptr, eventstrlen, "%s ", brick); eventstrlen -= (strlen (brick) + 1); tmp_ptr += (strlen (brick) + 1); i++; } if (!ret) { gf_asprintf (event_str, eventstrformat, volname, bricklist); } else { gf_asprintf (event_str, eventstrformat, volname, ""); } ret = 0; out: GF_FREE (bricklist); return ret; } int cli_cmd_volume_add_brick_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; gf_answer_t answer = GF_ANSWER_NO; cli_local_t *local = NULL; #if (USE_EVENTS) char *event_str = NULL; char *bricks = NULL; const char *eventstrformat = "volume=%s;bricks=%s"; #endif const char *question = "Changing the 'stripe count' of the volume is " "not a supported feature. In some cases it may result in data " "loss on the volume. Also there may be issues with regular " "filesystem operations on the volume after the change. Do you " "really want to continue with 'stripe' count option ? "; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_add_brick_parse (words, wordcount, &options, 0); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } /* TODO: there are challenges in supporting changing of stripe-count, until it is properly supported give warning to user */ if (dict_get (options, "stripe-count")) { answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } } #if (USE_EVENTS) /* Get the list of bricks for the event */ ret = dict_get_str (options, "bricks", &bricks); if (!ret) { gf_asprintf (&event_str, eventstrformat, (char *)words[2], &bricks[1] /*Skip leading space*/); } else { gf_asprintf (&event_str, eventstrformat, (char *)words[2], ""); } #endif if (state->mode & GLUSTER_MODE_WIGNORE) { ret = dict_set_int32 (options, "force", _gf_true); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set force " "option"); goto out; } } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_ADD_BRICK]; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume add-brick failed"); } else { #if (USE_EVENTS) gf_event (EVENT_VOLUME_ADD_BRICK, "%s", event_str); GF_FREE (event_str); #endif } CLI_STACK_DESTROY (frame); return ret; } int cli_tier_validate_replica_type (dict_t *dict, int type) { int brick_count = -1; int replica_count = 1; int ret = -1; ret = dict_get_int32 (dict, "count", &brick_count); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get brick count"); goto out; } ret = dict_get_int32 (dict, "replica-count", &replica_count); if (ret) { gf_log ("cli", GF_LOG_DEBUG, "Failed to get replica count. " "Defaulting to one"); replica_count = 1; } /* * Change the calculation of sub_count once attach-tier support * disperse volume. * sub_count = disperse_count for disperse volume * */ if (brick_count % replica_count) { if (type == GF_CLUSTER_TYPE_REPLICATE) cli_err ("number of bricks is not a multiple of " "replica count"); else if (type == GF_CLUSTER_TYPE_DISPERSE) cli_err ("number of bricks is not a multiple of " "disperse count"); else cli_err ("number of bricks given doesn't match " "required count"); ret = -1; goto out; } ret = 0; out: return ret; } int do_cli_cmd_volume_attach_tier (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; int type = 0; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_add_brick_parse (words, wordcount, &options, &type); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } /* * Merge this check when attach-tier has it's own cli parse function. */ ret = cli_tier_validate_replica_type (options, type); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } if (state->mode & GLUSTER_MODE_WIGNORE) { ret = dict_set_int32 (options, "force", _gf_true); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set force " "option"); goto out; } } ret = dict_set_int32 (options, "attach-tier", 1); if (ret) goto out; ret = dict_set_int32 (options, "hot-type", type); if (ret) goto out; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_ADD_TIER_BRICK]; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("attach-tier failed"); } CLI_STACK_DESTROY (frame); return ret; } int do_cli_cmd_volume_detach_tier (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount, gf_boolean_t *aborted) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; gf_answer_t answer = GF_ANSWER_NO; cli_local_t *local = NULL; int need_question = 0; const char *question = "Removing tier can result in data loss. " "Do you want to Continue?"; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_detach_tier_parse(words, wordcount, &options, &need_question); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } ret = dict_set_int32 (options, "force", 1); if (ret) goto out; ret = dict_set_int32 (options, "count", 0); if (ret) goto out; *aborted = _gf_false; if (!(state->mode & GLUSTER_MODE_SCRIPT) && need_question) { /* we need to ask question only in case of 'commit or force' */ answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 0; *aborted = _gf_true; goto out; } } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_REMOVE_TIER_BRICK]; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume detach tier failed"); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_tier_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; call_frame_t *frame = NULL; dict_t *options = NULL; rpc_clnt_procedure_t *proc = NULL; cli_local_t *local = NULL; int i = 0; eventtypes_t event = EVENT_LAST; gf_boolean_t aborted = _gf_false; gf_answer_t answer = GF_ANSWER_NO; const char *detach_question = "gluster volume detach-tier " " is " "deprecated. Use the new command \'" "gluster volume tier detach \'\n" "Do you want to Continue?"; const char *attach_question = "gluster volume attach-tier " "[] ... is " "deprecated. Use the new command \'" "gluster volume tier attach [] ... [force]\'\n" "Do you want to Continue?"; if (wordcount < 4) { if (wordcount == 3 && !strcmp(words[2], "help")) { cli_cmd_tier_help_cbk (state, word, words, wordcount); ret = 0; } else { cli_usage_out (word->pattern); } goto out; } if (!strcmp(words[1], "detach-tier")) { /* we need to ask question when older command is used */ answer = cli_cmd_get_confirmation (state, detach_question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } ret = do_cli_cmd_volume_detach_tier (state, word, words, wordcount, &aborted); goto out; } else if (!strcmp(words[3], "detach")) { for (i = 3; i < wordcount; i++) words[i] = words[i+1]; ret = do_cli_cmd_volume_detach_tier (state, word, words, wordcount-1, &aborted); if (!aborted) { if (!strcmp (words[wordcount-2], "commit")) { event = EVENT_TIER_DETACH_COMMIT; } else if (!strcmp (words[wordcount-2], "start")) { event = EVENT_TIER_DETACH_START; } else if (!strcmp (words[wordcount-2], "stop")) { event = EVENT_TIER_DETACH_STOP; } else if (!strcmp (words[wordcount-2], "force")) { event = EVENT_TIER_DETACH_FORCE; } } goto out; } else if (!strcmp(words[1], "attach-tier")) { /* we need to ask question when the older command is used */ answer = cli_cmd_get_confirmation (state, attach_question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } ret = do_cli_cmd_volume_attach_tier (state, word, words, wordcount); goto out; } else if (!strcmp(words[3], "attach")) { for (i = 3; i < wordcount; i++) words[i] = words[i+1]; ret = do_cli_cmd_volume_attach_tier (state, word, words, wordcount-1); if (!strcmp (words[wordcount-2], "force")) { event = EVENT_TIER_ATTACH_FORCE; } else { event = EVENT_TIER_ATTACH; } goto out; } ret = cli_cmd_volume_tier_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); goto out; } if (!strcmp (words[wordcount-1], "start")) { event = EVENT_TIER_START; } else { if (!strcmp (words[wordcount-2], "start") && !strcmp (words[wordcount-1], "force")) { event = EVENT_TIER_START_FORCE; } } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_TIER]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_out ("Tier command failed"); } else { if (event != EVENT_LAST) { gf_event (event, "vol=%s", words[2]); } } if (options) dict_unref (options); return ret; } int cli_get_soft_limit (dict_t *options, const char **words, dict_t *xdata) { call_frame_t *frame = NULL; cli_local_t *local = NULL; rpc_clnt_procedure_t *proc = NULL; char *default_sl = NULL; char *default_sl_dup = NULL; int ret = -1; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) { ret = -1; goto out; } //We need a ref on @options to prevent CLI_STACK_DESTROY //from destroying it prematurely. dict_ref (options); CLI_LOCAL_INIT (local, words, frame, options); proc = &cli_rpc_prog->proctable[GLUSTER_CLI_QUOTA]; ret = proc->fn (frame, THIS, options); ret = dict_get_str (options, "default-soft-limit", &default_sl); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get default soft limit"); goto out; } default_sl_dup = gf_strdup (default_sl); if (!default_sl_dup) { ret = -1; goto out; } ret = dict_set_dynstr (xdata, "default-soft-limit", default_sl_dup); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set default soft limit"); GF_FREE (default_sl_dup); goto out; } out: CLI_STACK_DESTROY (frame); return ret; } /* Checks if at least one limit has been set on the volume * * Returns true if at least one limit is set. Returns false otherwise. */ gf_boolean_t _limits_set_on_volume (char *volname, int type) { gf_boolean_t limits_set = _gf_false; int ret = -1; char quota_conf_file[PATH_MAX] = {0,}; int fd = -1; char buf[16] = {0,}; float version = 0.0f; char gfid_type_stored = 0; char gfid_type = 0; /* TODO: fix hardcoding; Need to perform an RPC call to glusterd * to fetch working directory */ snprintf (quota_conf_file, sizeof quota_conf_file, "%s/vols/%s/quota.conf", GLUSTERD_DEFAULT_WORKDIR, volname); fd = open (quota_conf_file, O_RDONLY); if (fd == -1) goto out; ret = quota_conf_read_version (fd, &version); if (ret) goto out; if (type == GF_QUOTA_OPTION_TYPE_LIST) gfid_type = GF_QUOTA_CONF_TYPE_USAGE; else gfid_type = GF_QUOTA_CONF_TYPE_OBJECTS; /* Try to read atleast one gfid of type 'gfid_type' */ while (1) { ret = quota_conf_read_gfid (fd, buf, &gfid_type_stored, version); if (ret <= 0) break; if (gfid_type_stored == gfid_type) { limits_set = _gf_true; break; } } out: if (fd != -1) sys_close (fd); return limits_set; } int cli_cmd_quota_handle_list_all (const char **words, dict_t *options) { int all_failed = 1; int count = 0; int ret = -1; rpc_clnt_procedure_t *proc = NULL; cli_local_t *local = NULL; call_frame_t *frame = NULL; dict_t *xdata = NULL; char *gfid_str = NULL; char *volname = NULL; char *volname_dup = NULL; unsigned char buf[16] = {0}; int fd = -1; char quota_conf_file[PATH_MAX] = {0}; gf_boolean_t xml_err_flag = _gf_false; char err_str[NAME_MAX] = {0,}; int32_t type = 0; char gfid_type = 0; float version = 0.0f; int32_t max_count = 0; xdata = dict_new (); if (!xdata) { ret = -1; goto out; } ret = dict_get_str (options, "volname", &volname); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get volume name"); goto out; } ret = dict_get_int32 (options, "type", &type); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get quota option type"); goto out; } ret = dict_set_int32 (xdata, "type", type); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set type in xdata"); goto out; } ret = cli_get_soft_limit (options, words, xdata); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to fetch default " "soft-limit"); goto out; } /* Check if at least one limit is set on volume. No need to check for * quota enabled as cli_get_soft_limit() handles that */ if (!_limits_set_on_volume (volname, type)) { snprintf (err_str, sizeof (err_str), "No%s quota configured on" " volume %s", (type == GF_QUOTA_OPTION_TYPE_LIST) ? "" : " inode", volname); if (global_state->mode & GLUSTER_MODE_XML) { xml_err_flag = _gf_true; } else { cli_out ("quota: %s", err_str); } ret = 0; goto out; } frame = create_frame (THIS, THIS->ctx->pool); if (!frame) { ret = -1; goto out; } volname_dup = gf_strdup (volname); if (!volname_dup) { ret = -1; goto out; } ret = dict_set_dynstr (xdata, "volume-uuid", volname_dup); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set volume-uuid"); GF_FREE (volname_dup); goto out; } //TODO: fix hardcoding; Need to perform an RPC call to glusterd //to fetch working directory snprintf (quota_conf_file, sizeof quota_conf_file, "%s/vols/%s/quota.conf", GLUSTERD_DEFAULT_WORKDIR, volname); fd = open (quota_conf_file, O_RDONLY); if (fd == -1) { //This may because no limits were yet set on the volume gf_log ("cli", GF_LOG_TRACE, "Unable to open " "quota.conf"); ret = 0; goto out; } ret = quota_conf_read_version (fd, &version); if (ret) goto out; CLI_LOCAL_INIT (local, words, frame, xdata); proc = &cli_quotad_clnt.proctable[GF_AGGREGATOR_GETLIMIT]; gfid_str = GF_CALLOC (1, gf_common_mt_char, 64); if (!gfid_str) { ret = -1; goto out; } for (count = 0;; count++) { ret = quota_conf_read_gfid (fd, buf, &gfid_type, version); if (ret == 0) { break; } else if (ret < 0) { gf_log (THIS->name, GF_LOG_CRITICAL, "Quota " "configuration store may be corrupt."); goto out; } if ((type == GF_QUOTA_OPTION_TYPE_LIST && gfid_type == GF_QUOTA_CONF_TYPE_OBJECTS) || (type == GF_QUOTA_OPTION_TYPE_LIST_OBJECTS && gfid_type == GF_QUOTA_CONF_TYPE_USAGE)) continue; max_count++; } ret = dict_set_int32 (xdata, "max_count", max_count); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set max_count"); goto out; } ret = sys_lseek (fd, 0L, SEEK_SET); if (ret < 0) { gf_log (THIS->name, GF_LOG_ERROR, "failed to move offset to " "the beginning: %s", strerror (errno)); goto out; } ret = quota_conf_read_version (fd, &version); if (ret) goto out; for (count = 0;; count++) { ret = quota_conf_read_gfid (fd, buf, &gfid_type, version); if (ret == 0) { break; } else if (ret < 0) { gf_log (THIS->name, GF_LOG_CRITICAL, "Quota " "configuration store may be corrupt."); goto out; } if ((type == GF_QUOTA_OPTION_TYPE_LIST && gfid_type == GF_QUOTA_CONF_TYPE_OBJECTS) || (type == GF_QUOTA_OPTION_TYPE_LIST_OBJECTS && gfid_type == GF_QUOTA_CONF_TYPE_USAGE)) continue; uuid_utoa_r (buf, gfid_str); ret = dict_set_str (xdata, "gfid", gfid_str); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set gfid"); goto out; } ret = proc->fn (frame, THIS, xdata); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get quota " "limits for %s", uuid_utoa ((unsigned char*)buf)); } dict_del (xdata, "gfid"); all_failed = all_failed && ret; } if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_quota_limit_list_end (local); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error in printing " "xml output"); goto out; } } if (count > 0) { ret = all_failed? -1: 0; } else { ret = 0; } out: if (xml_err_flag) { ret = cli_xml_output_str ("volQuota", NULL, -1, 0, err_str); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting in " "xml format"); } } if (fd != -1) { sys_close (fd); } GF_FREE (gfid_str); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Could not fetch and display quota" " limits"); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_bitrot_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; int parse_err = 0; call_frame_t *frame = NULL; dict_t *options = NULL; cli_local_t *local = NULL; rpc_clnt_procedure_t *proc = NULL; int sent = 0; #if (USE_EVENTS) int cmd_type = -1; int ret1 = -1; int event_type = -1; char *tmp = NULL; char *events_str = NULL; #endif ret = cli_cmd_bitrot_parse (words, wordcount, &options); if (ret < 0) { cli_usage_out (word->pattern); parse_err = 1; goto out; } if (ret == 1) { /* this is 'volume bitrot help' */ cli_cmd_bitrot_help_cbk (state, word, words, wordcount); ret = 0; goto out2; } frame = create_frame (THIS, THIS->ctx->pool); if (!frame) { ret = -1; goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_BITROT]; if (proc == NULL) { ret = -1; goto out; } CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_err == 0)) cli_err ("Bit rot command failed. Please check the cli " "logs for more details"); } #if (USE_EVENTS) if (ret == 0) { ret1 = dict_get_int32 (options, "type", &cmd_type); if (ret1) cmd_type = -1; else { ret1 = dict_get_str (options, "volname", &tmp); if (ret1) tmp = ""; gf_asprintf (&events_str, "name=%s", tmp); } switch (cmd_type) { case GF_BITROT_OPTION_TYPE_ENABLE: event_type = EVENT_BITROT_ENABLE; break; case GF_BITROT_OPTION_TYPE_DISABLE: event_type = EVENT_BITROT_DISABLE; break; case GF_BITROT_CMD_SCRUB_ONDEMAND: event_type = EVENT_BITROT_SCRUB_ONDEMAND; break; case GF_BITROT_OPTION_TYPE_SCRUB_THROTTLE: event_type = EVENT_BITROT_SCRUB_THROTTLE; ret1 = dict_get_str (options, "scrub-throttle-value", &tmp); if (ret1) tmp = ""; gf_asprintf (&events_str, "%s;value=%s", events_str, tmp); break; case GF_BITROT_OPTION_TYPE_SCRUB_FREQ: event_type = EVENT_BITROT_SCRUB_FREQ; ret1 = dict_get_str (options, "scrub-frequency-value", &tmp); if (ret1) tmp = ""; gf_asprintf (&events_str, "%s;value=%s", events_str, tmp); break; case GF_BITROT_OPTION_TYPE_SCRUB: event_type = EVENT_BITROT_SCRUB_OPTION; ret1 = dict_get_str (options, "scrub-value", &tmp); if (ret1) tmp = ""; gf_asprintf (&events_str, "%s;value=%s", events_str, tmp); break; default: break; } if (event_type > -1) gf_event (event_type, "%s", events_str); if (events_str) GF_FREE (events_str); } #endif CLI_STACK_DESTROY (frame); out2: return ret; } int cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = 0; int parse_err = 0; int32_t type = 0; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; gf_answer_t answer = GF_ANSWER_NO; cli_local_t *local = NULL; int sent = 0; char *volname = NULL; const char *question = "Disabling quota will delete all the quota " "configuration. Do you want to continue?"; //parse **words into options dictionary if (strcmp (words[1], "inode-quota") == 0) { ret = cli_cmd_inode_quota_parse (words, wordcount, &options); if (ret < 0) { cli_usage_out (word->pattern); parse_err = 1; goto out; } } else { ret = cli_cmd_quota_parse (words, wordcount, &options); if (ret == 1) { cli_cmd_quota_help_cbk (state, word, words, wordcount); ret = 0; goto out; } if (ret < 0) { cli_usage_out (word->pattern); parse_err = 1; goto out; } } ret = dict_get_int32 (options, "type", &type); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get opcode"); goto out; } //handle quota-disable and quota-list-all different from others switch (type) { case GF_QUOTA_OPTION_TYPE_DISABLE: answer = cli_cmd_get_confirmation (state, question); if (answer == GF_ANSWER_NO) goto out; break; case GF_QUOTA_OPTION_TYPE_LIST: case GF_QUOTA_OPTION_TYPE_LIST_OBJECTS: if (wordcount != 4) break; ret = cli_cmd_quota_handle_list_all (words, options); goto out; default: break; } ret = dict_get_str (options, "volname", &volname); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get volume name"); goto out; } frame = create_frame (THIS, THIS->ctx->pool); if (!frame) { ret = -1; goto out; } CLI_LOCAL_INIT (local, words, frame, options); proc = &cli_rpc_prog->proctable[GLUSTER_CLI_QUOTA]; if (proc->fn) ret = proc->fn (frame, THIS, options); out: if (ret) { cli_cmd_sent_status_get (&sent); if (sent == 0 && parse_err == 0) cli_out ("Quota command failed. Please check the cli " "logs for more details"); } /* Events for Quota */ if (ret == 0) { switch (type) { case GF_QUOTA_OPTION_TYPE_ENABLE: gf_event (EVENT_QUOTA_ENABLE, "volume=%s", volname); break; case GF_QUOTA_OPTION_TYPE_DISABLE: gf_event (EVENT_QUOTA_DISABLE, "volume=%s", volname); break; case GF_QUOTA_OPTION_TYPE_LIMIT_USAGE: gf_event (EVENT_QUOTA_SET_USAGE_LIMIT, "volume=%s;" "path=%s;limit=%s", volname, words[4], words[5]); break; case GF_QUOTA_OPTION_TYPE_LIMIT_OBJECTS: gf_event (EVENT_QUOTA_SET_OBJECTS_LIMIT, "volume=%s;" "path=%s;limit=%s", volname, words[4], words[5]); break; case GF_QUOTA_OPTION_TYPE_REMOVE: gf_event (EVENT_QUOTA_REMOVE_USAGE_LIMIT, "volume=%s;" "path=%s", volname, words[4]); break; case GF_QUOTA_OPTION_TYPE_REMOVE_OBJECTS: gf_event (EVENT_QUOTA_REMOVE_OBJECTS_LIMIT, "volume=%s;" "path=%s", volname, words[4]); break; case GF_QUOTA_OPTION_TYPE_ALERT_TIME: gf_event (EVENT_QUOTA_ALERT_TIME, "volume=%s;time=%s", volname, words[4]); break; case GF_QUOTA_OPTION_TYPE_SOFT_TIMEOUT: gf_event (EVENT_QUOTA_SOFT_TIMEOUT, "volume=%s;" "soft-timeout=%s", volname, words[4]); break; case GF_QUOTA_OPTION_TYPE_HARD_TIMEOUT: gf_event (EVENT_QUOTA_HARD_TIMEOUT, "volume=%s;" "hard-timeout=%s", volname, words[4]); break; case GF_QUOTA_OPTION_TYPE_DEFAULT_SOFT_LIMIT: gf_event (EVENT_QUOTA_DEFAULT_SOFT_LIMIT, "volume=%s;" "default-soft-limit=%s", volname, words[4]); break; } } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_remove_brick_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; gf_answer_t answer = GF_ANSWER_NO; int brick_count = 0; int sent = 0; int parse_error = 0; int need_question = 0; cli_local_t *local = NULL; char *volname = NULL; #if (USE_EVENTS) eventtypes_t event = EVENT_LAST; char *event_str = NULL; int event_ret = -1; #endif const char *question = "Removing brick(s) can result in data loss. " "Do you want to Continue?"; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_remove_brick_parse (words, wordcount, &options, &need_question, &brick_count); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } if (!brick_count) { cli_err ("No bricks specified"); cli_usage_out (word->pattern); parse_error = 1; ret = -1; goto out; } ret = dict_get_str (options, "volname", &volname); if (ret || !volname) { gf_log ("cli", GF_LOG_ERROR, "Failed to fetch volname"); ret = -1; goto out; } #if (USE_EVENTS) event_ret = cli_event_remove_brick_str (options, &event_str, &event); #endif if (!strcmp (volname, GLUSTER_SHARED_STORAGE)) { question = "Removing brick from the shared storage volume" "(gluster_shared_storage), will affect features " "like snapshot scheduler, geo-replication " "and NFS-Ganesha. Do you still want to " "continue?"; need_question = _gf_true; } if (!(state->mode & GLUSTER_MODE_SCRIPT) && need_question) { /* we need to ask question only in case of 'commit or force' */ answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_REMOVE_BRICK]; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume remove-brick failed"); } else { #if (USE_EVENTS) if (!event_ret) { gf_event (event, "%s", event_str); GF_FREE (event_str); } #endif } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_reset_brick_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; #ifdef GF_SOLARIS_HOST_OS cli_out ("Command not supported on Solaris"); goto out; #endif proc = &cli_rpc_prog->proctable[GLUSTER_CLI_RESET_BRICK]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_reset_brick_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } if (state->mode & GLUSTER_MODE_WIGNORE_PARTITION) { ret = dict_set_int32 (options, "ignore-partition", _gf_true); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to set ignore-" "partition option"); goto out; } } CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume reset-brick failed"); } else { if (wordcount > 5) { gf_event (EVENT_BRICK_RESET_COMMIT, "Volume=%s;source-brick=%s;" "destination-brick=%s", (char *)words[2], (char *)words[3], (char *)words[4]); } else { gf_event (EVENT_BRICK_RESET_START, "Volume=%s;source-brick=%s", (char *)words[2], (char *)words[3]); } } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_replace_brick_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; #ifdef GF_SOLARIS_HOST_OS cli_out ("Command not supported on Solaris"); goto out; #endif proc = &cli_rpc_prog->proctable[GLUSTER_CLI_REPLACE_BRICK]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_replace_brick_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume replace-brick failed"); } else { gf_event (EVENT_BRICK_REPLACE, "Volume=%s;source-brick=%s;destination-brick=%s", (char *)words[2], (char *)words[3], (char *)words[4]); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_set_transport_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { cli_cmd_broadcast_response (0); return 0; } int cli_cmd_volume_top_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; ret = cli_cmd_volume_top_parse (words, wordcount, &options); if (ret) { parse_error = 1; cli_usage_out (word->pattern); goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_TOP_VOLUME]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume top failed"); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_log_rotate_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; if (!((wordcount == 4) || (wordcount == 5))) { cli_usage_out (word->pattern); parse_error = 1; goto out; } if (!((strcmp ("rotate", words[2]) == 0) || (strcmp ("rotate", words[3]) == 0))) { cli_usage_out (word->pattern); parse_error = 1; goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LOG_ROTATE]; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_log_rotate_parse (words, wordcount, &options); if (ret) goto out; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume log rotate failed"); } CLI_STACK_DESTROY (frame); return ret; } #if (SYNCDAEMON_COMPILE) static int cli_check_gsync_present () { char buff[PATH_MAX] = {0, }; runner_t runner = {0,}; char *ptr = NULL; int ret = 0; ret = setenv ("_GLUSTERD_CALLED_", "1", 1); if (-1 == ret) { gf_log ("", GF_LOG_WARNING, "setenv syscall failed, hence could" "not assert if geo-replication is installed"); goto out; } runinit (&runner); runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "--version", NULL); runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); ret = runner_start (&runner); if (ret == -1) { gf_log ("", GF_LOG_INFO, "geo-replication not installed"); goto out; } ptr = fgets(buff, sizeof(buff), runner_chio (&runner, STDOUT_FILENO)); if (ptr) { if (!strstr (buff, "gsyncd")) { ret = -1; goto out; } } else { ret = -1; goto out; } ret = runner_end (&runner); if (ret) gf_log ("", GF_LOG_ERROR, "geo-replication not installed"); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret ? -1 : 0; } void cli_cmd_check_gsync_exists_cbk (struct cli_cmd *this) { int ret = 0; ret = cli_check_gsync_present (); if (ret) this->disable = _gf_true; } #endif int cli_cmd_volume_gsync_set_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = 0; int parse_err = 0; dict_t *options = NULL; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; cli_local_t *local = NULL; #if (USE_EVENTS) int ret1 = -1; int cmd_type = -1; int tmpi = 0; char *tmp = NULL; char *events_str = NULL; int event_type = -1; #endif proc = &cli_rpc_prog->proctable [GLUSTER_CLI_GSYNC_SET]; frame = create_frame (THIS, THIS->ctx->pool); if (frame == NULL) { ret = -1; goto out; } ret = cli_cmd_gsync_set_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_err = 1; goto out; } CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) ret = proc->fn (frame, THIS, options); out: if (ret && parse_err == 0) cli_out (GEOREP" command failed"); #if (USE_EVENTS) if (ret == 0) { events_str = gf_strdup (""); /* Type of Geo-rep Action - Create, Start etc */ ret1 = dict_get_int32 (options, "type", &cmd_type); if (ret1) cmd_type = -1; /* Only capture Events for modification commands */ switch (cmd_type) { case GF_GSYNC_OPTION_TYPE_CREATE: event_type = EVENT_GEOREP_CREATE; break; case GF_GSYNC_OPTION_TYPE_START: event_type = EVENT_GEOREP_START; break; case GF_GSYNC_OPTION_TYPE_STOP: event_type = EVENT_GEOREP_STOP; break; case GF_GSYNC_OPTION_TYPE_PAUSE: event_type = EVENT_GEOREP_PAUSE; break; case GF_GSYNC_OPTION_TYPE_RESUME: event_type = EVENT_GEOREP_RESUME; break; case GF_GSYNC_OPTION_TYPE_DELETE: event_type = EVENT_GEOREP_DELETE; break; case GF_GSYNC_OPTION_TYPE_CONFIG: ret1 = dict_get_str (options, "subop", &tmp); if (ret1) tmp = ""; /* For Config Set additionally capture key and value */ /* For Config Reset capture key */ if (strcmp (tmp, "set") == 0) { event_type = EVENT_GEOREP_CONFIG_SET; ret1 = dict_get_str (options, "op_name", &tmp); if (ret1) tmp = ""; gf_asprintf (&events_str, "%soption=%s;", events_str, tmp); ret1 = dict_get_str (options, "op_value", &tmp); if (ret1) tmp = ""; gf_asprintf (&events_str, "%svalue=%s;", events_str, tmp); } else if (strcmp (tmp, "del") == 0) { event_type = EVENT_GEOREP_CONFIG_RESET; ret1 = dict_get_str (options, "op_name", &tmp); if (ret1) tmp = ""; gf_asprintf (&events_str, "%soption=%s;", events_str, tmp); } break; default: break; } if (event_type > -1) { /* Capture all optional arguments used */ ret1 = dict_get_int32 (options, "force", &tmpi); if (ret1 == 0) gf_asprintf (&events_str, "%sforce=%d;", events_str, tmpi); ret1 = dict_get_int32 (options, "push_pem", &tmpi); if (ret1 == 0) gf_asprintf (&events_str, "%spush_pem=%d;", events_str, tmpi); ret1 = dict_get_int32 (options, "no_verify", &tmpi); if (ret1 == 0) gf_asprintf (&events_str, "%sno_verify=%d;", events_str, tmpi); ret1 = dict_get_int32 (options, "ssh_port", &tmpi); if (ret1 == 0) gf_asprintf (&events_str, "%sssh_port=%d;", events_str, tmpi); ret1 = dict_get_int32 (options, "reset-sync-time", &tmpi); if (ret1 == 0) gf_asprintf (&events_str, "%sreset_sync_time=%d;", events_str, tmpi); /* Capture Master and Slave Info */ ret1 = dict_get_str (options, "master", &tmp); if (ret1) tmp = ""; gf_asprintf (&events_str, "%smaster=%s;", events_str, tmp); ret1 = dict_get_str (options, "slave", &tmp); if (ret1) tmp = ""; gf_asprintf (&events_str, "%sslave=%s", events_str, tmp); gf_event (event_type, "%s", events_str); } /* Allocated by gf_strdup and gf_asprintf */ GF_FREE (events_str); } #endif CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_status_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *dict = NULL; uint32_t cmd = 0; cli_local_t *local = NULL; ret = cli_cmd_volume_status_parse (words, wordcount, &dict); if (ret) { cli_usage_out (word->pattern); goto out; } ret = dict_get_uint32 (dict, "cmd", &cmd); if (ret) goto out; if (!(cmd & GF_CLI_STATUS_ALL)) { /* for one volume or brick */ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATUS_VOLUME]; } else { /* volume status all or all detail */ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATUS_ALL]; } if (!proc->fn) goto out; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; CLI_LOCAL_INIT (local, words, frame, dict); ret = proc->fn (frame, THIS, dict); out: CLI_STACK_DESTROY (frame); return ret; } int cli_get_detail_status (dict_t *dict, int i, cli_volume_status_t *status) { uint64_t free = 0; uint64_t total = 0; char key[1024] = {0}; int ret = 0; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.free", i); ret = dict_get_uint64 (dict, key, &free); status->free = gf_uint64_2human_readable (free); if (!status->free) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.total", i); ret = dict_get_uint64 (dict, key, &total); status->total = gf_uint64_2human_readable (total); if (!status->total) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.device", i); ret = dict_get_str (dict, key, &(status->device)); if (ret) status->device = NULL; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.block_size", i); ret = dict_get_uint64 (dict, key, &(status->block_size)); if (ret) { ret = 0; status->block_size = 0; } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.mnt_options", i); ret = dict_get_str (dict, key, &(status->mount_options)); if (ret) status->mount_options = NULL; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.fs_name", i); ret = dict_get_str (dict, key, &(status->fs_name)); if (ret) { ret = 0; status->fs_name = NULL; } memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.inode_size", i); ret = dict_get_str (dict, key, &(status->inode_size)); if (ret) status->inode_size = NULL; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.total_inodes", i); ret = dict_get_uint64 (dict, key, &(status->total_inodes)); if (ret) status->total_inodes = 0; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.free_inodes", i); ret = dict_get_uint64 (dict, key, &(status->free_inodes)); if (ret) { ret = 0; status->free_inodes = 0; } out: return ret; } void cli_print_detailed_status (cli_volume_status_t *status) { cli_out ("%-20s : %-20s", "Brick", status->brick); if (status->online) { cli_out ("%-20s : %-20d", "TCP Port", status->port); cli_out ("%-20s : %-20d", "RDMA Port", status->rdma_port); } else { cli_out ("%-20s : %-20s", "TCP Port", "N/A"); cli_out ("%-20s : %-20s", "RDMA Port", "N/A"); } cli_out ("%-20s : %-20c", "Online", (status->online) ? 'Y' : 'N'); cli_out ("%-20s : %-20s", "Pid", status->pid_str); if (status->fs_name) cli_out ("%-20s : %-20s", "File System", status->fs_name); else cli_out ("%-20s : %-20s", "File System", "N/A"); if (status->device) cli_out ("%-20s : %-20s", "Device", status->device); else cli_out ("%-20s : %-20s", "Device", "N/A"); if (status->mount_options) { cli_out ("%-20s : %-20s", "Mount Options", status->mount_options); } else { cli_out ("%-20s : %-20s", "Mount Options", "N/A"); } if (status->inode_size) { cli_out ("%-20s : %-20s", "Inode Size", status->inode_size); } else { cli_out ("%-20s : %-20s", "Inode Size", "N/A"); } if (status->free) cli_out ("%-20s : %-20s", "Disk Space Free", status->free); else cli_out ("%-20s : %-20s", "Disk Space Free", "N/A"); if (status->total) cli_out ("%-20s : %-20s", "Total Disk Space", status->total); else cli_out ("%-20s : %-20s", "Total Disk Space", "N/A"); if (status->total_inodes) { cli_out ("%-20s : %-20"GF_PRI_INODE, "Inode Count", status->total_inodes); } else { cli_out ("%-20s : %-20s", "Inode Count", "N/A"); } if (status->free_inodes) { cli_out ("%-20s : %-20"GF_PRI_INODE, "Free Inodes", status->free_inodes); } else { cli_out ("%-20s : %-20s", "Free Inodes", "N/A"); } } int cli_print_brick_status (cli_volume_status_t *status) { int fieldlen = CLI_VOL_STATUS_BRICK_LEN; int bricklen = 0; char *p = NULL; int num_spaces = 0; p = status->brick; bricklen = strlen (p); while (bricklen > 0) { if (bricklen > fieldlen) { cli_out ("%.*s", fieldlen, p); p += fieldlen; bricklen -= fieldlen; } else { num_spaces = (fieldlen - bricklen) + 1; printf ("%s", p); while (num_spaces-- != 0) printf (" "); if (status->port || status->rdma_port) { if (status->online) cli_out ("%-10d%-11d%-8c%-5s", status->port, status->rdma_port, status->online?'Y':'N', status->pid_str); else cli_out ("%-10s%-11s%-8c%-5s", "N/A", "N/A", status->online?'Y':'N', status->pid_str); } else cli_out ("%-10s%-11s%-8c%-5s", "N/A", "N/A", status->online?'Y':'N', status->pid_str); bricklen = 0; } } return 0; } #define NEEDS_GLFS_HEAL(op) ((op == GF_SHD_OP_SBRAIN_HEAL_FROM_BIGGER_FILE) || \ (op == GF_SHD_OP_SBRAIN_HEAL_FROM_LATEST_MTIME) ||\ (op == GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK) || \ (op == GF_SHD_OP_INDEX_SUMMARY) || \ (op == GF_SHD_OP_SPLIT_BRAIN_FILES) || \ (op == GF_SHD_OP_GRANULAR_ENTRY_HEAL_ENABLE) || \ (op == GF_SHD_OP_HEAL_SUMMARY)) int cli_launch_glfs_heal (int heal_op, dict_t *options) { char buff[PATH_MAX] = {0}; runner_t runner = {0}; char *filename = NULL; char *hostname = NULL; char *path = NULL; char *volname = NULL; char *out = NULL; int ret = 0; runinit (&runner); ret = dict_get_str (options, "volname", &volname); runner_add_args (&runner, SBIN_DIR"/glfsheal", volname, NULL); runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); switch (heal_op) { case GF_SHD_OP_INDEX_SUMMARY: if (global_state->mode & GLUSTER_MODE_XML) { runner_add_args (&runner, "xml", NULL); } break; case GF_SHD_OP_SBRAIN_HEAL_FROM_BIGGER_FILE: ret = dict_get_str (options, "file", &filename); runner_add_args (&runner, "bigger-file", filename, NULL); break; case GF_SHD_OP_SBRAIN_HEAL_FROM_LATEST_MTIME: ret = dict_get_str (options, "file", &filename); runner_add_args (&runner, "latest-mtime", filename, NULL); break; case GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK: ret = dict_get_str (options, "heal-source-hostname", &hostname); ret = dict_get_str (options, "heal-source-brickpath", &path); runner_add_args (&runner, "source-brick", NULL); runner_argprintf (&runner, "%s:%s", hostname, path); if (dict_get_str (options, "file", &filename) == 0) runner_argprintf (&runner, filename); break; case GF_SHD_OP_SPLIT_BRAIN_FILES: runner_add_args (&runner, "split-brain-info", NULL); if (global_state->mode & GLUSTER_MODE_XML) { runner_add_args (&runner, "xml", NULL); } break; case GF_SHD_OP_GRANULAR_ENTRY_HEAL_ENABLE: case GF_SHD_OP_GRANULAR_ENTRY_HEAL_DISABLE: runner_add_args (&runner, "granular-entry-heal-op", NULL); break; case GF_SHD_OP_HEAL_SUMMARY: runner_add_args (&runner, "info-summary", NULL); if (global_state->mode & GLUSTER_MODE_XML) { runner_add_args (&runner, "xml", NULL); } break; default: ret = -1; } ret = runner_start (&runner); if (ret == -1) goto out; while ((out = fgets (buff, sizeof(buff), runner_chio (&runner, STDOUT_FILENO)))) { printf ("%s", out); } ret = runner_end (&runner); out: return ret; } int cli_cmd_volume_heal_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; int sent = 0; int parse_error = 0; dict_t *options = NULL; xlator_t *this = NULL; cli_local_t *local = NULL; int heal_op = 0; this = THIS; frame = create_frame (this, this->ctx->pool); if (!frame) goto out; if (wordcount < 3) { cli_usage_out (word->pattern); parse_error = 1; goto out; } ret = cli_cmd_volume_heal_options_parse (words, wordcount, &options); if (ret) { cli_usage_out (word->pattern); parse_error = 1; goto out; } ret = dict_get_int32 (options, "heal-op", &heal_op); if (ret < 0) goto out; if (NEEDS_GLFS_HEAL (heal_op)) { ret = cli_launch_glfs_heal (heal_op, options); if (ret < 0) goto out; if (heal_op != GF_SHD_OP_GRANULAR_ENTRY_HEAL_ENABLE) goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_HEAL_VOLUME]; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0) && !(global_state->mode & GLUSTER_MODE_XML)) { cli_out ("Volume heal failed."); } } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_statedump_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; if (wordcount < 3) { cli_usage_out (word->pattern); parse_error = 1; goto out; } if (wordcount >= 3) { ret = cli_cmd_volume_statedump_options_parse (words, wordcount, &options); if (ret) { parse_error = 1; gf_log ("cli", GF_LOG_ERROR, "Error parsing " "statedump options"); cli_out ("Error parsing options"); cli_usage_out (word->pattern); } } ret = dict_set_str (options, "volname", (char *)words[2]); if (ret) goto out; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATEDUMP_VOLUME]; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume statedump failed"); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_list_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; call_frame_t *frame = NULL; rpc_clnt_procedure_t *proc = NULL; int sent = 0; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LIST_VOLUME]; if (proc->fn) { ret = proc->fn (frame, THIS, NULL); } out: if (ret) { cli_cmd_sent_status_get (&sent); if (sent == 0) cli_out ("Volume list failed"); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_clearlocks_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; if (wordcount < 7 || wordcount > 8) { cli_usage_out (word->pattern); parse_error = 1; goto out; } ret = cli_cmd_volume_clrlks_opts_parse (words, wordcount, &options); if (ret) { parse_error = 1; gf_log ("cli", GF_LOG_ERROR, "Error parsing " "clear-locks options"); cli_out ("Error parsing options"); cli_usage_out (word->pattern); } ret = dict_set_str (options, "volname", (char *)words[2]); if (ret) goto out; ret = dict_set_str (options, "path", (char *)words[3]); if (ret) goto out; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_CLRLOCKS_VOLUME]; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) { ret = proc->fn (frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_out ("Volume clear-locks failed"); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_barrier_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; if (wordcount != 4) { cli_usage_out (word->pattern); parse_error = 1; goto out; } options = dict_new(); if (!options) { ret = -1; goto out; } ret = dict_set_str(options, "volname", (char *)words[2]); if (ret) goto out; ret = dict_set_str (options, "barrier", (char *)words[3]); if (ret) goto out; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_BARRIER_VOLUME]; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) ret = proc->fn (frame, THIS, options); out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_error == 0)) cli_err ("Volume barrier failed"); } CLI_STACK_DESTROY (frame); return ret; } int cli_cmd_volume_getopt_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_err = 0; cli_local_t *local = NULL; if (wordcount != 4) { cli_usage_out (word->pattern); parse_err = 1; goto out; } frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; options = dict_new (); if (!options) goto out; ret = dict_set_str (options, "volname", (char *)words[2]); if (ret) goto out; ret = dict_set_str (options, "key", (char *)words[3]); if (ret) goto out; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_VOL_OPT]; CLI_LOCAL_INIT (local, words, frame, options); if (proc->fn) ret = proc->fn (frame, THIS, options); out: if (ret) { cli_cmd_sent_status_get (&sent); if ((sent == 0) && (parse_err == 0)) cli_err ("Volume get option failed"); } CLI_STACK_DESTROY (frame); return ret; } /* This is a bit of a hack to display the help. The current bitrot cmd * format does not work well when registering the cmds. * Ideally the should have been of the form * gluster volume bitrot ... */ struct cli_cmd bitrot_cmds[] = { {"volume bitrot help", cli_cmd_bitrot_help_cbk, "display help for volume bitrot commands" }, {"volume bitrot {enable|disable}", NULL, /*cli_cmd_bitrot_cbk,*/ "Enable/disable bitrot for volume " }, {"volume bitrot scrub-throttle {lazy|normal|aggressive}", NULL, /*cli_cmd_bitrot_cbk,*/ "Set the speed of the scrubber for volume " }, {"volume bitrot scrub-frequency {hourly|daily|weekly|biweekly" "|monthly}", NULL, /*cli_cmd_bitrot_cbk,*/ "Set the frequency of the scrubber for volume " }, {"volume bitrot scrub {pause|resume|status|ondemand}", NULL, /*cli_cmd_bitrot_cbk,*/ "Pause/resume the scrubber for . Status displays the status of " "the scrubber. ondemand starts the scrubber immediately." }, {"volume bitrot {enable|disable}\n" "volume bitrot scrub-throttle {lazy|normal|aggressive}\n" "volume bitrot scrub-frequency {hourly|daily|weekly|biweekly" "|monthly}\n" "volume bitrot scrub {pause|resume|status|ondemand}", cli_cmd_bitrot_cbk, NULL }, { NULL, NULL, NULL } }; struct cli_cmd quota_cmds[] = { /* Quota commands */ {"volume quota help", cli_cmd_quota_help_cbk, "display help for volume quota commands" }, {"volume quota {enable|disable|list [ ...]| " "list-objects [ ...] | remove | remove-objects | " "default-soft-limit }", cli_cmd_quota_cbk, "Enable/disable and configure quota for " }, {"volume quota {limit-usage []}", cli_cmd_quota_cbk, "Set maximum size for for " }, {"volume quota {limit-objects []}", cli_cmd_quota_cbk, "Set the maximum number of entries allowed in for " }, {"volume quota {alert-time|soft-timeout|hard-timeout} {