From: Dmitry Eremin Date: Fri, 30 May 2014 14:38:24 +0000 (+0400) Subject: LU-5104 build: utilities cleanup X-Git-Tag: 2.6.53~42 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=adf2e9d9ab987b46fa0269038f348cf2a17fd0e0 LU-5104 build: utilities cleanup - remove unused utilities: lustre_createcsv, lustre_config, lustre_up14 - move req_layout, loadgen, wirecheck and wiretest to tests RPM - add dependency tests from utils (multiop from liblustreapi) - make corrent mapping for configure parameters "--enable-*/--disable-*" to "--with/--without *" - fix find command for empty results - fix utils building (add ifdef UTILS and fix .spec file) - don't install few server scripts and utils for client build Signed-off-by: Dmitry Eremin Change-Id: I947ea4739526f74a18427dd853c4198871dd0e21 Reviewed-on: http://review.whamcloud.com/10654 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: Bob Glossman Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin --- diff --git a/autoMakefile.am b/autoMakefile.am index c78cbb3..27640fb 100644 --- a/autoMakefile.am +++ b/autoMakefile.am @@ -89,10 +89,10 @@ dist-hook: -name CVS -o \ -name .svn -o \ -name .git -o \ - -name .#* | xargs rm -rf + -name .#* -exec rm -rf {} \; $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$(top_distdir)" distdir="$(distdir)" \ - module-dist-hook + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + module-dist-hook EXTRA_DIST = @PACKAGE_TARNAME@.spec \ build/Makefile \ diff --git a/config/lustre-build.m4 b/config/lustre-build.m4 index 32b3861..496303b 100644 --- a/config/lustre-build.m4 +++ b/config/lustre-build.m4 @@ -531,11 +531,16 @@ CONFIGURE_ARGS= eval set -- $ac_configure_args for arg; do case $arg in + --enable-dist ) ;; --with-release=* ) ;; --with-kmp-moddir=* ) ;; --with-linux=* | --with-linux-obj=* ) ;; - --enable-tests | --disable-tests ) ;; + --enable-ldiskfs | --disable-ldiskfs ) ;; --enable-modules | --disable-modules ) ;; + --enable-server | --disable-server ) ;; + --enable-tests | --disable-tests ) ;; + --enable-utils | --disable-utils ) ;; + --enable-iokit | --disable-iokit ) ;; * ) CONFIGURE_ARGS="$CONFIGURE_ARGS '$arg'" ;; esac done @@ -574,7 +579,9 @@ if test x$enable_modules != xyes ; then fi if test x$enable_tests != xyes ; then RPMBINARGS="$RPMBINARGS --without lustre_tests" - RPMSRCARGS="$RPMSRCARGS --without lustre_tests" +fi +if test x$enable_utils != xyes ; then + RPMBINARGS="$RPMBINARGS --without lustre_utils" fi if test x$enable_server != xyes ; then RPMBINARGS="$RPMBINARGS --without servers" @@ -633,6 +640,9 @@ LC_CONFIG_CLIENT LB_CONFIG_MPITESTS LB_CONFIG_SERVERS +# Tests depends from utils (multiop from liblustreapi) +AS_IF([test "x$enable_utils" = xno], [enable_tests="no"]) + # two macros for cmd3 m4_ifdef([LC_CONFIG_SPLIT], [LC_CONFIG_SPLIT]) m4_ifdef([LC_NODEMAP_PROC_DEBUG], [LC_NODEMAP_PROC_DEBUG]) diff --git a/libcfs/libcfs/autoMakefile.am b/libcfs/libcfs/autoMakefile.am index 252a199..604ed12 100644 --- a/libcfs/libcfs/autoMakefile.am +++ b/libcfs/libcfs/autoMakefile.am @@ -55,11 +55,13 @@ endif libcfs_a_CPPFLAGS = $(LLCPPFLAGS) libcfs_a_CFLAGS = $(LLCFLAGS) +if UTILS lib_LIBRARIES = libcfsutil.a libcfsutil_a_SOURCES = nidstrings.c libcfs_string.c util/parser.c \ util/l_ioctl.c util/util.c libcfsutil_a_CPPFLAGS = $(LLCPPFLAGS) libcfsutil_a_CFLAGS = $(LLCFLAGS) -DLUSTRE_UTILS=1 +endif if MODULES @@ -67,7 +69,7 @@ if LINUX modulenet_DATA := libcfs$(KMODEXT) endif -endif +endif # MODULES MOSTLYCLEANFILES := @MOSTLYCLEANFILES@ linux-*.c linux/*.o libcfs EXTRA_DIST := $(libcfs-all-objs:%.o=%.c) tracefile.h prng.c \ diff --git a/lnet/utils/.gitignore b/lnet/utils/.gitignore index 138369d..c24c5d2 100644 --- a/lnet/utils/.gitignore +++ b/lnet/utils/.gitignore @@ -1,5 +1,4 @@ /Makefile.in -/acceptor /routerstat /wirecheck /lst diff --git a/lnet/utils/Makefile.am b/lnet/utils/Makefile.am index 8ff8cca..d45dcf2 100644 --- a/lnet/utils/Makefile.am +++ b/lnet/utils/Makefile.am @@ -34,26 +34,13 @@ # Lustre is a trademark of Sun Microsystems, Inc. # -## $(srcdir)/../ for , ../../ for generated -#COMPILE = $(CC) -Wall -g -I$(srcdir)/../include -I../../include -#LINK = $(CC) -o $@ - AM_CFLAGS = $(LLCFLAGS) LIBCFS= $(top_builddir)/libcfs/libcfs/libcfs.a LIBCFSUTIL= $(top_builddir)/libcfs/libcfs/libcfsutil.a -lib_LIBRARIES = libptlctl.a - -libptlctl_a_SOURCES = portals.c debug.c - -sbin_PROGRAMS = - if UTILS -sbin_PROGRAMS += routerstat wirecheck lst -endif - -wirecheck_SOURCES = wirecheck.c +sbin_PROGRAMS = routerstat lst routerstat_SOURCES = routerstat.c @@ -61,9 +48,20 @@ lst_SOURCES = lst.c lst_LDADD = -L. -lptlctl $(LIBCFSUTIL) $(LIBCFS) $(LIBREADLINE) $(LIBEFENCE) lst_DEPENDENCIES = libptlctl.a +if TESTS +sbin_PROGRAMS += wirecheck + +wirecheck_SOURCES = wirecheck.c +endif + +lib_LIBRARIES = libptlctl.a + +libptlctl_a_SOURCES = portals.c debug.c +endif # UTILS + LND_LIBS = if BUILD_USOCKLND -LND_LIBS += $(top_builddir)/lnet/ulnds/socklnd/libsocklnd.a +LND_LIBS += $(top_builddir)/lnet/ulnds/socklnd/libsocklnd.a endif EXTRA_DIST = genlib.sh diff --git a/lustre.spec.in b/lustre.spec.in index 95e3830..23dea92 100644 --- a/lustre.spec.in +++ b/lustre.spec.in @@ -5,6 +5,7 @@ %bcond_without ldiskfs %bcond_with zfs %bcond_without lustre_tests +%bcond_without lustre_utils %bcond_without lustre_iokit %bcond_without lustre_modules @@ -279,11 +280,19 @@ cd $RPM_BUILD_DIR/lustre-%{version} # build failures %define optflags -g -O2 -Werror CONFIGURE_ARGS="%{?configure_args} --with-release=%release" + %if %{with lustre_tests} CONFIGURE_ARGS="$CONFIGURE_ARGS --enable-tests" %else CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-tests" %endif + +%if %{with lustre_utils} +CONFIGURE_ARGS="$CONFIGURE_ARGS --enable-utils" +%else +CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-utils" +%endif + %if %{without lustre_iokit} CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-iokit" %endif @@ -294,6 +303,14 @@ CONFIGURE_ARGS="$CONFIGURE_ARGS --enable-modules" CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-modules" %endif +%if %{without servers} +CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-server" +%endif + +%if %{without ldiskfs} +CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-ldiskfs" +%endif + %if %{without zfs} CONFIGURE_ARGS="$CONFIGURE_ARGS --without-zfs" %endif @@ -330,9 +347,11 @@ make install DESTDIR=$RPM_BUILD_ROOT # The .ha_v2 extension identifies the heartbeat resource agent as using # legacy syntax. Install a compatibility symlink to avoid conflicts when # newer-style agents are added. +%if %{with lustre_utils} ln -s Lustre.ha_v2 $RPM_BUILD_ROOT%{_sysconfdir}/ha.d/resource.d/Lustre echo '%{_sysconfdir}/ha.d/resource.d/Lustre.ha_v2' >>lustre.files echo '%{_sysconfdir}/ha.d/resource.d/Lustre' >>lustre.files +%endif if [ -f $RPM_BUILD_ROOT%{_sysconfdir}/init.d/lustre ]; then echo '%{_sysconfdir}/sysconfig/lustre' >>lustre.files @@ -352,7 +371,7 @@ ln -s $RPM_BUILD_ROOT%{_prefix}/src lustre-source make distdir distdir=lustre-source/lustre-%{version} chmod -R go-w lustre-source/lustre-%{version} # fc18 needs 'x' permission for library files -find $RPM_BUILD_ROOT -name '*.so' | xargs chmod +x +find $RPM_BUILD_ROOT -name \*.so -type f -exec chmod +x {} \; if [ -f $RPM_BUILD_ROOT%{_libdir}/libiam.a ] ; then echo '%{_libdir}/libiam.a' >>lustre.files @@ -363,12 +382,16 @@ if [ -d $RPM_BUILD_ROOT%{_libdir}/lustre/snmp ] ; then echo '%{_datadir}/lustre/snmp/mibs' >>lustre.files fi -find $RPM_BUILD_ROOT%{_libdir}/@PACKAGE@/ -name \*.la -delete +find $RPM_BUILD_ROOT%{_libdir}/@PACKAGE@/ -name \*.la -type f -delete %if %{with lustre_tests} echo '%{_libdir}/lustre/tests/*' >>lustre-tests.files echo '%{_bindir}/mcreate' >>lustre-tests.files echo '%{_bindir}/munlink' >>lustre-tests.files +echo '%{_bindir}/req_layout' >>lustre-tests.files +echo '%{_sbindir}/wirecheck' >>lustre-tests.files +echo '%{_sbindir}/wiretest' >>lustre-tests.files +echo '%{_sbindir}/loadgen' >>lustre-tests.files %if %{with lustre_modules} echo '%{?rootdir}/lib/modules/%{kversion}/%{kmoddir}/kernel/fs/@PACKAGE@/llog_test.ko' >>lustre-tests.files %endif @@ -394,34 +417,40 @@ if [ -f $POST_SCRIPT ]; then fi %endif %else +%if %{with lustre_modules} # mark modules executable for find-debuginfo.sh -find $RPM_BUILD_ROOT%{?rootdir}/lib/modules/%{kversion}/%{kmoddir} -name "*.ko" -type f | \ - xargs --no-run-if-empty chmod u+x +find $RPM_BUILD_ROOT%{?rootdir}/lib/modules/%{kversion}/%{kmoddir} \ + -name \*.ko -type f -exec chmod u+x {} \; +%endif %endif %files -f lustre.files %defattr(-,root,root) -%{?rootdir}/sbin/mount.lustre %{_sbindir}/* -%{_bindir}/lfs -%{_bindir}/lfs_migrate -%{_bindir}/llbackup +%if %{with lustre_utils} +%if %{with servers} +%{_libexecdir}/lustre/lc_common +%{_libexecdir}/lustre/haconfig +%{_bindir}/lustre_req_history +%endif + %{_bindir}/llobdstat %{_bindir}/llstat -%{_bindir}/lustre_req_history %{_bindir}/plot-llstat -%{_bindir}/req_layout + +%{_bindir}/lfs +%{_bindir}/lfs_migrate +%{?rootdir}/sbin/mount.lustre %{_libdir}/libptlctl.a %{_libdir}/libcfsutil.a %{_libdir}/liblustreapi.a %{_libdir}/liblustreapi.so %{_mandir}/man?/* -%{_datadir}/lustre %{_includedir}/lustre %{_includedir}/libcfs %{_includedir}/linux/lustre_user.h -%{_libexecdir}/lustre/lc_common -%{_libexecdir}/lustre/haconfig +%endif +%{_datadir}/lustre %{_sysconfdir}/udev/rules.d/99-lustre.rules %config(noreplace) %{_sysconfdir}/ldev.conf @@ -451,7 +480,9 @@ find $RPM_BUILD_ROOT%{?rootdir}/lib/modules/%{kversion}/%{kmoddir} -name "*.ko" %defattr(-,root,root) %{?rootdir}/lib/modules/%{kversion}/%{kmoddir}/kernel/fs/@PACKAGE@/ldiskfs.ko %{?rootdir}/lib/modules/%{kversion}/%{kmoddir}/kernel/fs/@PACKAGE@/osd_ldiskfs.ko +%if %{with lustre_utils} %{_libdir}/@PACKAGE@/mount_osd_ldiskfs.so +%endif %if %{defined rpm_post_base} %attr(0555, root, root) %{rpm_post_base}-osd-ldiskfs.sh %endif @@ -461,7 +492,9 @@ find $RPM_BUILD_ROOT%{?rootdir}/lib/modules/%{kversion}/%{kmoddir} -name "*.ko" %files osd-zfs %defattr(-,root,root) %{?rootdir}/lib/modules/%{kversion}/%{kmoddir}/kernel/fs/@PACKAGE@/osd_zfs.ko +%if %{with lustre_utils} %{_libdir}/@PACKAGE@/mount_osd_zfs.so +%endif %if %{defined rpm_post_base} %attr(0555, root, root) %{rpm_post_base}-osd-zfs.sh %endif diff --git a/lustre/scripts/.gitignore b/lustre/scripts/.gitignore index a45dd923..65eadf0 100644 --- a/lustre/scripts/.gitignore +++ b/lustre/scripts/.gitignore @@ -1,8 +1,6 @@ /lustre.spec /Makefile.in /version_tag.pl -/lustre_createcsv.sh -/lustre_config.sh /lc_net.sh /lc_modprobe.sh /lc_hb.sh @@ -15,8 +13,6 @@ /lc_md /lc_modprobe /lc_net -/lustre_config -/lustre_createcsv /lustre /lustre_start /tree_status.pl diff --git a/lustre/scripts/Makefile.am b/lustre/scripts/Makefile.am index f2b60a8a7..395bcf2 100644 --- a/lustre/scripts/Makefile.am +++ b/lustre/scripts/Makefile.am @@ -34,38 +34,41 @@ # Lustre is a trademark of Sun Microsystems, Inc. # -sbinscripts = lc_servip lustre_up14 lustre_rmmod lhbadm ldev -sbinscripts += lustre_routes_config lustre_routes_conversion - # These are scripts that are generated from .in files -genscripts = lustre_config lc_modprobe lc_net lc_hb lc_cluman \ - lc_md lc_lvm lustre_start +genscripts = lc_modprobe lc_net lc_hb lc_cluman lc_md lc_lvm lustre_start + +sbin_SCRIPTS = lustre_rmmod if INIT_SCRIPTS initdir = $(sysconfdir)/init.d -init_SCRIPTS = lnet +init_SCRIPTS = lnet if SERVER init_SCRIPTS += lustre endif endif +if UTILS +sbin_SCRIPTS += ldev lustre_routes_config lustre_routes_conversion +bin_SCRIPTS = lfs_migrate + if SERVER +sbin_SCRIPTS += $(genscripts) lc_mon lhbadm lc_servip +bin_SCRIPTS += lustre_req_history + hadir = $(sysconfdir)/ha.d/resource.d ha_SCRIPTS = Lustre.ha_v2 -endif - -sbin_SCRIPTS = $(genscripts) $(sbinscripts) -bin_SCRIPTS = lustre_req_history lfs_migrate - -EXTRA_DIST = license-status version_tag.pl version_tag-git.pl \ - version_tag-none.pl lc_common \ - $(addsuffix .in,$(genscripts)) lc_mon $(sbinscripts) \ - $(bin_SCRIPTS) lustre lnet lhbadm \ - haconfig ldev Lustre.ha_v2 dkms.mkconf scriptlibdir = @libexecdir@/@PACKAGE@ scriptlib_SCRIPTS = haconfig scriptlib_DATA = lc_common +endif # SERVER +endif # UTILS + +EXTRA_DIST = license-status version_tag.pl version_tag-git.pl \ + version_tag-none.pl lustre_rmmod ldev lc_mon lhbadm \ + lc_servip lustre_routes_config lustre_routes_conversion \ + $(addsuffix .in,$(genscripts)) lfs_migrate lustre_req_history \ + lustre lnet lc_common haconfig Lustre.ha_v2 dkms.mkconf CLEANFILES = $(genscripts) diff --git a/lustre/scripts/lustre_config.in b/lustre/scripts/lustre_config.in deleted file mode 100644 index fcdf45f..0000000 --- a/lustre/scripts/lustre_config.in +++ /dev/null @@ -1,768 +0,0 @@ -#!/bin/bash - -# vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4: - -# -# lustre_config - format and set up multiple lustre servers from a csv file -# -# This script is used to parse each line of a spreadsheet (csv file) and -# execute remote commands to format (mkfs.lustre) every Lustre target -# that will be part of the Lustre cluster. -# -# In addition, it can also verify the network connectivity and hostnames in -# the cluster, configure Linux MD/LVM devices and produce High-Availability -# software configurations for Heartbeat or CluManager. -# -################################################################################ - -# Usage -usage() { - cat < - - This script is used to format and set up multiple lustre servers from a - csv file. - - Options: - -h help and examples - -a select all the nodes from the csv file to operate on - -w hostname,hostname,... - select the specified list of nodes (separated by commas) to - operate on rather than all the nodes in the csv file - -x hostname,hostname,... - exclude the specified list of nodes (separated by commas) - -t HAtype produce High-Availability software configurations - The argument following -t is used to indicate the High- - Availability software type. The HA software types which - are currently supported are: hbv1 (Heartbeat version 1) - and hbv2 (Heartbeat version 2). - -n no net - don't verify network connectivity and hostnames - in the cluster - -d configure Linux MD/LVM devices before formatting the - Lustre targets - -f force-format the Lustre targets using --reformat option - -m no fstab change - don't modify /etc/fstab to add the new - Lustre targets - If using this option, then the value of "mount options" - item in the csv file will be passed to mkfs.lustre, else - the value will be added into the /etc/fstab. - -u upgrade Lustre targets from 1.4 to 1.6 - -v verbose mode - csv file a spreadsheet that contains configuration parameters - (separated by commas) for each target in a Lustre cluster - -EOF -} - -# Samples -sample() { - cat <&2 - exit 1 - fi - ;; - n) - VERIFY_CONNECT=false - ;; - d) - CONFIG_MD_LVM=true - ;; - f) - REFORMAT_OPTION=$"--reformat " - ;; - m) - MODIFY_FSTAB=false - ;; - u) - UPGRADE_TARGET=true - ;; - h) - usage - sample - ;; - v) - VERBOSE_OPT=$" -v" - VERBOSE_OUTPUT=true - ;; - ?) - usage 1>&2 - exit 1 - ;; - esac -done - -# Toss out the parameters we've already processed -shift `expr $OPTIND - 1` - -# Here we expect the csv file -if [ $# -eq 0 ]; then - error_output "Missing csv file!" - usage 1>&2 - exit 1 -fi - -CSV_FILE=$1 - -# Construct the command line of mkfs.lustre -construct_mkfs_cmdline() { - # Check argument - if [ $# -eq 0 ]; then - error_output "construct_mkfs_cmdline():"\ - "Missing argument for function construct_mkfs_cmdline()!" - return 1 - fi - - declare -i i=$1 - local mgsnids mgsnids_str - local failnids failnids_str - - if $UPGRADE_TARGET; then - MKFS_CMD="$TUNEFS --writeconf" - else - MKFS_CMD="$MKFS $REFORMAT_OPTION" - fi - - case "${DEVICE_TYPE[i]}" in - "ost") - MKFS_CMD="$MKFS_CMD --ost" - ;; - "mdt") - MKFS_CMD="$MKFS_CMD --mdt" - ;; - "mgs") - MKFS_CMD="$MKFS_CMD --mgs" - ;; - "mdt|mgs" | "mgs|mdt") - MKFS_CMD="$MKFS_CMD --mgs --mdt" - ;; - *) - error_output "construct_mkfs_cmdline():"\ - "Invalid device type - \"${DEVICE_TYPE[i]}\"!" - return 1 - ;; - esac - - if [ -n "${FS_NAME[i]}" ]; then - MKFS_CMD="$MKFS_CMD --fsname=${FS_NAME[i]}" - fi - - if [ -n "${MGS_NIDS[i]}" ]; then - mgsnids_str=${MGS_NIDS[i]} - for mgsnids in ${mgsnids_str//:/ }; do - MKFS_CMD="$MKFS_CMD --mgsnode=$mgsnids" - done - fi - - if [ -n "${INDEX[i]}" ]; then - MKFS_CMD="$MKFS_CMD --index=${INDEX[i]}" - fi - - if [ -n "${FORMAT_OPTIONS[i]}" ]; then - MKFS_CMD="$MKFS_CMD ${FORMAT_OPTIONS[i]}" - fi - - if ! $UPGRADE_TARGET && [ -n "${MKFS_OPTIONS[i]}" ]; then - MKFS_CMD="$MKFS_CMD --mkfsoptions=\"${MKFS_OPTIONS[i]}\"" - fi - - if [ -n "${MOUNT_OPTIONS[i]}" ] && ! $MODIFY_FSTAB; then - MKFS_CMD="$MKFS_CMD --mountfsoptions=\"${MOUNT_OPTIONS[i]}\"" - fi - - if [ -n "${FAILOVERS[i]}" ]; then - failnids_str=${FAILOVERS[i]} - for failnids in ${failnids_str//:/ }; do - MKFS_CMD="$MKFS_CMD --failnode=$failnids" - done - fi - - MKFS_CMD="$MKFS_CMD ${DEVICE_NAME[i]}" - return 0 -} - -# Get all the node names in this failover group -get_nodenames() { - # Check argument - if [ $# -eq 0 ]; then - error_output "get_nodenames(): Missing"\ - "argument for function get_nodenames()!" - return 1 - fi - - declare -i i=$1 - declare -i idx - local nids - - # Initialize the NODE_NAMES array - unset NODE_NAMES - - NODE_NAMES[0]=${HOST_NAME[i]} - - idx=1 - for nids in ${FAILOVERS_NAMES[i]//:/ } - do - NODE_NAMES[idx]=$(nids2hostname ${nids}) - if [ ${PIPESTATUS[0]} -ne 0 ]; then - error_output "${NODE_NAMES[idx]}" - return 1 - fi - - idx=$idx+1 - done - - return 0 -} - -# Verify whether the format line has HA items -is_ha_line() { - declare -i i=$1 - - [ -n "${FAILOVERS[i]}" ] && return 0 - - return 1 -} - -# Produce HA software's configuration files -gen_ha_config() { - declare -i i=$1 - declare -i idx - local cmd_line - - # Prepare parameters - # Hostnames option - HOSTNAME_OPT=${HOST_NAME[i]} - - if ! get_nodenames $i; then - error_output "gen_ha_config(): Can not get the"\ - "failover nodenames from failover nids - \"${FAILOVERS[i]}\" in"\ - "the \"${HOST_NAME[i]}\" failover group!" - return 1 - fi - - for ((idx = 1; idx < ${#NODE_NAMES[@]}; idx++)); do - HOSTNAME_OPT=${HOSTNAME_OPT}$":"${NODE_NAMES[idx]} - done - - # Target devices option - DEVICE_OPT=" -d "${TARGET_OPTS[0]} - for ((idx = 1; idx < ${#TARGET_OPTS[@]}; idx++)); do - DEVICE_OPT=${DEVICE_OPT}" -d "${TARGET_OPTS[idx]} - done - - # Construct the generation script command line - case "${HATYPE_OPT}" in - "${HBVER_HBV1}"|"${HBVER_HBV2}") # Heartbeat - cmd_line=${GEN_HB_CONFIG}$" -r ${HATYPE_OPT} -n ${HOSTNAME_OPT}" - cmd_line=${cmd_line}${DEVICE_OPT}${VERBOSE_OPT} - ;; - "${HATYPE_CLUMGR}") # CluManager - cmd_line=${GEN_CLUMGR_CONFIG}$" -n ${HOSTNAME_OPT}" - cmd_line=${cmd_line}${DEVICE_OPT}${VERBOSE_OPT} - ;; - esac - - # Execute script to generate HA software's configuration files - verbose_output "Generating HA software's configurations in"\ - "${HOST_NAME[i]} failover group..." - verbose_output "${cmd_line}" - eval $(echo "${cmd_line}") - if [ ${PIPESTATUS[0]} -ne 0 ]; then - return 1 - fi - verbose_output "Generate HA software's configurations in"\ - "${HOST_NAME[i]} failover group OK" - - return 0 -} - -# Configure HA software -config_ha() { - if $UPGRADE_TARGET || [ -z "${HATYPE_OPT}" ]; then - return 0 - fi - - declare -i i j k - declare -i prim_idx # Index for PRIM_HOSTNAMES array - declare -i target_idx # Index for TARGET_OPTS and HOST_INDEX arrays - - declare -a PRIM_HOSTNAMES # Primary hostnames in all the failover - # groups in the lustre cluster - declare -a HOST_INDEX # Indices for the same node in all the - # format lines in the csv file - local prim_host - - # Initialize the PRIM_HOSTNAMES array - prim_idx=0 - unset PRIM_HOSTNAMES - - # Get failover groups and generate HA configuration files - for ((i = 0; i < ${#HOST_NAME[@]}; i++)); do - prim_host=${HOST_NAME[i]} - - for ((j = 0; j < ${#PRIM_HOSTNAMES[@]}; j++)); do - [ "${prim_host}" = "${PRIM_HOSTNAMES[j]}" ] && continue 2 - done - - target_idx=0 - unset HOST_INDEX - unset TARGET_OPTS - for ((k = 0; k < ${#HOST_NAME[@]}; k++)); do - if [ "${prim_host}" = "${HOST_NAME[k]}" ] && is_ha_line "${k}" - then - HOST_INDEX[target_idx]=$k - TARGET_OPTS[target_idx]=${DEVICE_NAME[k]}:${MOUNT_POINT[k]} - target_idx=$(( target_idx + 1 )) - fi - done - - if [ ${#TARGET_OPTS[@]} -ne 0 ]; then - PRIM_HOSTNAMES[prim_idx]=${prim_host} - prim_idx=$(( prim_idx + 1 )) - - if ! gen_ha_config ${HOST_INDEX[0]}; then - return 1 - fi - fi - done - - if [ ${#PRIM_HOSTNAMES[@]} -eq 0 ]; then - verbose_output "There are no \"failover nids\" items in the"\ - "csv file. No HA configuration files are generated!" - fi - - rm -rf ${TMP_DIRS} - return 0 -} - -# Execute remote command to add lnet options lines to remote nodes' -# modprobe.conf/modules.conf and format(mkfs.lustre) Lustre targets -mass_config() { - local COMMAND - declare -a REMOTE_PID - declare -a REMOTE_CMD - declare -i pid_num=0 - declare -i i=0 - local checked_hosts="" - - if [ ${#HOST_NAME[@]} -eq 0 ]; then - verbose_output "There are no Lustre targets specified." - return 0 - fi - - if ! $UPGRADE_TARGET; then - # Start lnet network in the MGS node - start_mgs_lnet || return 1 - fi - - for ((i = 0; i < ${#HOST_NAME[@]}; i++)); do - # Construct the command line of mkfs.lustre - if ! construct_mkfs_cmdline $i; then - return 1 - fi - - # create the mount point on the node - COMMAND="mkdir -p ${MOUNT_POINT[i]}" - verbose_output "Creating the mount point ${MOUNT_POINT[i]} on" \ - "${HOST_NAME[i]}" - ${REMOTE} ${HOST_NAME[i]} "${COMMAND}" >&2 - if [ ${PIPESTATUS[0]} -ne 0 ]; then - error_output "mass_config():"\ - "Failed to execute remote command to"\ - "create the mountpoint on ${HOST_NAME[i]}!" - return 1 - fi - - if ! $UPGRADE_TARGET && ! is_mgs_node ${HOST_NAME[i]} && \ - ! host_in_hostlist ${HOST_NAME[i]} $checked_hosts; then - # Execute remote command to add lnet options lines to - # modprobe.conf/modules.conf - add_module_options $i ${HOST_NAME[i]} || return ${PIPESTATUS[0]} - - # Check lnet networks - check_lnet $i || return ${PIPESTATUS[0]} - - checked_hosts="$checked_hosts,${HOST_NAME[i]}" - fi - - # Execute remote command to format or upgrade Lustre target - local OP - $UPGRADE_TARGET && OP="Upgrading" || OP="Formatting" - verbose_output "$OP Lustre target ${DEVICE_NAME[i]} on ${HOST_NAME[i]}..." - - COMMAND="export PATH=\$PATH:/sbin:/usr/sbin; $MKFS_CMD" - REMOTE_CMD[$pid_num]="$REMOTE ${HOST_NAME[i]} \"$COMMAND\"" - verbose_output "$OP command line is: ${REMOTE_CMD[$pid_num]}" - - $REMOTE ${HOST_NAME[i]} "$COMMAND" & - REMOTE_PID[$pid_num]=$! - let pid_num=$pid_num+1 - sleep 1 - done - - # Wait for the exit status of the background remote command - verbose_output "Waiting for the return of the remote command..." - fail_exit_status=false - for ((pid_num = 0; pid_num < ${#REMOTE_PID[@]}; pid_num++)); do - wait ${REMOTE_PID[${pid_num}]} - if [ ${PIPESTATUS[0]} -ne 0 ]; then - error_output "mass_config(): Failed"\ - "to execute \"${REMOTE_CMD[${pid_num}]}\"!" - fail_exit_status=true - fi - done - - if ${fail_exit_status}; then - return 1 - fi - - verbose_output "Success on all Lustre targets!" - return 0 -} - -# get_mntopts hostname device_name failovers -# Construct the mount options of Lustre target @device_name in host @hostname -get_mntopts() { - local host_name=$1 - local device_name=$2 - local failovers=$3 - local mnt_opts= - local ret_str - - [ -n "${failovers}" ] && mnt_opts=defaults,noauto || mnt_opts=defaults - - # Execute remote command to check whether the device - # is a block device or not - ret_str=$(${REMOTE} ${host_name} \ - "[ -b ${device_name} ] && echo block || echo loop" 2>&1) - if [ ${PIPESTATUS[0]} -ne 0 -a -n "${ret_str}" ]; then - echo "`basename $0`: get_mntopts() error:" \ - "remote command to ${host_name} error: ${ret_str}" - return 1 - fi - - if [ -z "${ret_str}" ]; then - echo "`basename $0`: get_mntopts() error: remote error:" \ - "No results from remote!" \ - "Check network connectivity between the local host and ${host_name}!" - return 1 - fi - - [ "${ret_str}" != "${ret_str#*loop}" ] && mnt_opts=${mnt_opts},loop - - echo ${mnt_opts} - return 0 -} - -# Execute remote command to modify /etc/fstab to add the new Lustre targets -modify_fstab() { - declare -i i - local mntent mntopts device_name - local COMMAND - - if ! ${MODIFY_FSTAB}; then - return 0 - fi - - for ((i = 0; i < ${#HOST_NAME[@]}; i++)); do - verbose_output "Modify /etc/fstab of host ${HOST_NAME[i]}"\ - "to add Lustre target ${DEVICE_NAME[i]}" - mntent=${DEVICE_NAME[i]}"\t\t"${MOUNT_POINT[i]}"\t\t"${FS_TYPE} - - # Get mount options - if [ -n "${MOUNT_OPTIONS[i]}" ]; then - # The mount options already specified in the csv file. - mntopts="${MOUNT_OPTIONS[i]}" - else - mntopts=$(get_mntopts ${HOST_NAME[i]} ${DEVICE_NAME[i]}\ - ${FAILOVERS[i]}) - if [ ${PIPESTATUS[0]} -ne 0 ]; then - error_output "${mntopts}" - return 1 - fi - fi - - mntent=${mntent}"\t"${mntopts}"\t"0" "0 - verbose_output "`echo -e ${mntent}`" - - # Execute remote command to modify /etc/fstab - device_name=${DEVICE_NAME[i]//\//\\/} - COMMAND=". @scriptlibdir@/lc_common; \ - sed -i \"/^${device_name}\t/d\" \$(fcanon /etc/fstab); \ - echo -e \"${mntent}\" >> \$(fcanon /etc/fstab)" - ${REMOTE} ${HOST_NAME[i]} "${COMMAND}" >&2 - if [ ${PIPESTATUS[0]} -ne 0 ]; then - error_output "modify_fstab():"\ - "Failed to modify /etc/fstab of host ${HOST_NAME[i]}"\ - "to add Lustre target ${DEVICE_NAME[i]}!" - return 1 - fi - done - - return 0 -} - -#********************************* Main Flow **********************************# - -# Check the csv file -check_file $CSV_FILE || exit ${PIPESTATUS[0]} - -# Get the list of nodes to be operated on -NODES_TO_USE=$(get_nodelist) || error_exit ${PIPESTATUS[0]} "$NODES_TO_USE" - -# Check the node list -check_nodelist $NODES_TO_USE || exit ${PIPESTATUS[0]} - -if ${VERIFY_CONNECT}; then -# Check the network connectivity and hostnames - echo "`basename $0`: Checking the cluster network connectivity"\ - "and hostnames..." - if ! ${VERIFY_CLUSTER_NET} ${NODELIST_OPT} ${VERBOSE_OPT} ${CSV_FILE}; then - exit 1 - fi - echo "`basename $0`: Check the cluster network connectivity"\ - "and hostnames OK!" - echo -fi - -if $CONFIG_MD_LVM && ! $UPGRADE_TARGET; then -# Configure Linux MD/LVM devices - echo "`basename $0`: Configuring Linux MD/LVM devices..." - if ! ${SCRIPT_CONFIG_MD} ${NODELIST_OPT} ${VERBOSE_OPT} ${CSV_FILE}; then - exit 1 - fi - - if ! ${SCRIPT_CONFIG_LVM} ${NODELIST_OPT} ${VERBOSE_OPT} ${CSV_FILE}; then - exit 1 - fi - echo "`basename $0`: Configure Linux MD/LVM devices OK!" - echo -fi - -# Configure the Lustre cluster -echo "`basename $0`: ******** Lustre cluster configuration BEGIN ********" - -get_lustre_items $CSV_FILE || exit ${PIPESTATUS[0]} - -check_mgs || exit ${PIPESTATUS[0]} - -# Format or upgrade Lustre server targets -mass_config || exit ${PIPESTATUS[0]} - -# Modify /etc/fstab to add the new Lustre server targets -modify_fstab || exit ${PIPESTATUS[0]} - -# Produce HA software's configuration files -if ! config_ha; then - rm -rf ${TMP_DIRS} - exit 1 -fi - -echo "`basename $0`: ******** Lustre cluster configuration END **********" - -exit 0 diff --git a/lustre/scripts/lustre_up14 b/lustre/scripts/lustre_up14 deleted file mode 100644 index 9027237..0000000 --- a/lustre/scripts/lustre_up14 +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash -# -# Reads old MDS config logs for transferring to a MGS -# -############################################################################### - -TMP=${TMP:-/tmp/logs} - -# Usage -usage() { - cat >&2 < - - the MDS disk device (e.g. /dev/sda1) - the name of the new filesystem (e.g. testfs) - - This script will extract old config logs from an MDS device to a - temporary location ($TMP). During the upgrade procedure, mount the - MGS disk as type ldiskfs (e.g. mount -t ldiskfs /dev/sda - /mnt/temp), then copy these logs into the CONFIGS directory on the - MGS (e.g. /mnt/temp/CONFIGS). Logs from many MDS's can be added - in this way. When done, unmount the MGS, and then re-mount it as - type lustre to start the service. - -EOF - exit 1 -} - -if [ $# -lt 2 ]; then - usage -fi - -DEV=$1 -FSNAME=$2 -DEBUGFS="debugfs -c -R" -mkdir -p $TMP - -FILES=`$DEBUGFS "ls -l LOGS" $DEV | awk '{print $9}' | awk '/[a-z]/ {print $1}'` - -for FILE in ${FILES}; do - $DEBUGFS "dump LOGS/$FILE $TMP/temp" $DEV 2> /dev/null - MDC=`strings $TMP/temp | grep MDC` - LOV=`strings $TMP/temp | grep lov` - if [ -n "$MDC" ]; then - TYPE=client - else - if [ -n "$LOV" ]; then - TYPE=MDT0000 - else - echo "Can't determine type for log '$FILE', skipping" - continue - fi - fi - echo -n "Copying log '$FILE' to '${FSNAME}-${TYPE}'. Okay [y/n]?" - read OK - if [ "$OK" = "y" ]; then - mv $TMP/temp $TMP/${FSNAME}-${TYPE} - else - rm $TMP/temp - fi -done - -echo ls -l $TMP -ls -l $TMP - diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index 5aefe21..d012030 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -15,25 +15,32 @@ LIBPTLCTL := $(top_builddir)/lnet/utils/libptlctl.a \ $(top_builddir)/libcfs/libcfs/libcfsutil.a \ $(top_builddir)/libcfs/libcfs/libcfs.a -bin_scripts = llstat llobdstat plot-llstat llbackup - +if TESTS EXTRA_PROGRAMS = wirecheck +endif if UTILS # mount only finds helpers in /sbin rootsbin_PROGRAMS = mount.lustre -sbin_PROGRAMS = lctl wiretest l_getidentity llverfs llverdev \ - llog_reader lr_reader lustre_rsync \ - ll_recover_lost_found_objs ltrack_stats ll_decode_filter_fid +bin_SCRIPTS = llstat llobdstat plot-llstat +bin_PROGRAMS = lfs +sbin_PROGRAMS = lctl l_getidentity llverfs lustre_rsync ltrack_stats + +if TESTS +bin_PROGRAMS += req_layout +sbin_PROGRAMS += wiretest +if LIBPTHREAD +sbin_PROGRAMS += loadgen +endif +endif # TESTS + if SERVER -sbin_PROGRAMS += mkfs.lustre tunefs.lustre +sbin_PROGRAMS += mkfs.lustre tunefs.lustre llverdev lr_reader \ + ll_recover_lost_found_objs ll_decode_filter_fid llog_reader endif if LIBPTHREAD -sbin_PROGRAMS += loadgen lhsmtool_posix +sbin_PROGRAMS += lhsmtool_posix endif -bin_PROGRAMS = lfs req_layout -bin_SCRIPTS = $(bin_scripts) -sbin_SCRIPTS = $(sbin_scripts) pkglib_LTLIBRARIES = lib_LIBRARIES = liblustreapi.a @@ -90,6 +97,7 @@ liblustreapitmp_a_SOURCES = liblustreapi.c liblustreapi_hsm.c \ liblustreapi_lease.c \ $(L_IOCTL) $(L_KERNELCOMM) $(L_STRING) +if UTILS # build static and shared lib lustreapi liblustreapi.a : liblustreapitmp.a rm -f liblustreapi.a liblustreapi.so @@ -106,6 +114,7 @@ install-exec-hook: liblustreapi.so $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$f; \ else :; fi; \ done +endif if LDISKFS_ENABLED libiam_a_SOURCES = libiam.c @@ -171,9 +180,9 @@ wirecheck_CPPFLAGS = -DCC="\"$(CC)\"" wiretest_SOURCES = wiretest.c -endif +endif # UTILS -EXTRA_DIST = $(sbin_scripts) $(bin_scripts) +EXTRA_DIST = llstat llobdstat plot-llstat # NOTE: this should only be run on i386. newwiretest: wirehdr.c wirecheck diff --git a/lustre/utils/llbackup b/lustre/utils/llbackup deleted file mode 100755 index 0cabc1e..0000000 --- a/lustre/utils/llbackup +++ /dev/null @@ -1,537 +0,0 @@ -#!/bin/bash -# do a parallel backup and restore of specified files -# -# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. -# -# This file is part of Lustre, http://www.lustre.org. -# -# Lustre is free software; you can redistribute it and/or -# modify it under the terms of version 2 of the GNU General Public -# License as published by the Free Software Foundation. -# -# Lustre is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Lustre; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# Author: Andreas Dilger -# - -VERSION=1.1.0 - -export LC_ALL=C - -RSH=${RSH:-"ssh"} # use "bash -c" for local testing -SPLITMB=${SPLITMB:-8192} # target chunk size (uncompressed) -SPLITCOUNT=${SPLITCOUNT:-200} # number of files to give each client -TAR=${TAR:-"tar"} # also htar in theory works (untested) - -#PROGPATH=$(which $0 2> /dev/null) || PROGPATH=$PWD/$0 -case $0 in - .*) PROGPATH=$PWD/$0 ;; - *) PROGPATH=$0 ;; -esac - -PROGNAME="$(basename $PROGPATH)" -LOGPREFIX="$PROGNAME" -log() { - echo "$LOGPREFIX: $*" 1>&2 -} - -fatal() { - log "ERROR: $*" - exit 1 -} - -usage() { - log "$*" - echo "usage: $PROGNAME [-chjvxz] [-C directory] [-e rsh] [-i inputlist]" - echo -e "\t\t[-l logdir] [-n nodes] [-s splitmb] [-T tar] -f ${FTYPE}base" - echo -e "\t-c create archive" - echo -e "\t-C directory: relative directory for filenames (default PWD)" - echo -e "\t-e rsh: specify the passwordless remote shell (default $RSH)" - if [ "$OP" = "backup" ]; then - echo -e "\t-f outputfile: specify base output filename for backup" - else - echo -e "\t-f ${OP}filelist: specify list of files to $OP" - fi - echo -e "\t-h: print help message and exit (use -x -h for restore help)" - if [ "$OP" = "backup" ]; then - echo -e "\t-i inputfile: list of files to backup (default stdin)" - fi - echo -e "\t-j: use bzip2 compression on $FTYPE file(s)" - echo -e "\t-l logdir: directory for output logs" - echo -e "\t-n nodes: comma-separated list of client nodes to run ${OP}s" - if [ "$OP" = "backup" ]; then - echo -e "\t-s splitmb: target size for backup chunks " \ - "(default ${SPLITMB}MiB)" - echo -e "\t-S splitcount: number of files sent to each client "\ - "(default ${SPLITCOUNT})" - fi - echo -e "\t-t: list table of contents of tarfile" - echo -e "\t-T tar: specify the backup command (default $TAR)" - echo -e "\t-v: be verbose - list all files being processed" - echo -e "\t-V: print version number and exit" - echo -e "\t-x: extract files instead of backing them up" - echo -e "\t-z: use gzip compression on $FTYPE file(s)" - exit 1 -} - -usage_inactive() { - usage "inactive argument '$1 $2' in '$3' mode" -} - -set_op_type() { - case $1 in - *backup*) OP=backup; FTYPE=output; TAROP="-c" ;; - *list*) OP=list; FTYPE=input; TAROP="-t"; SPLITCOUNT=1 ;; - *restore*) OP=restore; FTYPE=input; TAROP="-x"; SPLITCOUNT=1 ;; - *) FTYPE="output"; usage "unknown archive operation '$1'";; - esac -} - -#echo ARGV: "$@" - -# --fileonly, --remote are internal-use-only options -TEMPARGS=$(getopt -n $LOGPREFIX -o cC:e:f:hi:jl:n:ps:S:tT:vVxz --long create,extract,list,restore,directory:,rsh:,outputbase:,help,inputfile:,bzip2,logdir:,nodes:,permissions:splitmb,splitcount,tar:,verbose,version,gzip,fileonly,remote: -- "$@") - -eval set -- "$TEMPARGS" - -set_op_type $PROGNAME - -# parse input arguments, and accumulate the client-specific args -while true; do - case "$1" in - -c|--create) [ "$OP" != "backup" ] && - usage "can't use $1 $TAROP at the same time" - OP="backup"; ARGS="$ARGS $1"; shift ;; - -C|--directory) GOTODIR="$2"; cd "$2" || usage "error cd to -C $2"; - ARGS="$ARGS $1 \"$2\""; shift 2 ;; - -e|--rsh) RSH="$2"; shift 2;; - -f|--outputbase)OUTPUTBASE="$2";ARGS="$ARGS $1 \"$2\""; shift 2 ;; - -h|--help) ARGS=""; break;; - -i|--inputfile) INPUT="$2"; shift 2;; - -j|--bzip2) TARCOMP="-j"; ARGS="$ARGS $1"; shift ;; - -l|--logdir) LOGDIR="$2"; ARGS="$ARGS $1 \"$2\""; shift 2 ;; - -n|--nodes) NODELIST="$NODELIST,$2"; - ARGS="$ARGS $1 \"$2\""; shift 2 ;; - -p|--permissions) PERM="-p"; ARGS="$ARGS $1"; shift ;; - -s|--splitmb) [ "$OP" != "backup" ] && usage_inactive $1 $2 $OP - SPLITMB=$2; ARGS="$ARGS $1 \"$2\""; shift 2 ;; - -S|--splitcount)[ "$OP" != "backup" ] && usage_inactive $1 $2 $OP - SPLITCOUNT=$2; ARGS="$ARGS $1 \"$2\""; shift 2 ;; - -t|--list) [ "$OP" != "backup" -a "$OP" != "list" ] && - usage "can't use $1 $TAROP at the same time" - OP="list"; ARGS="$ARGS $1"; shift ;; - -T|--tar) TAR="$2"; ARGS="$ARGS $1 \"$2\""; shift 2 ;; - -v|--vebose) [ "$VERBOSE" = "-v" ] && set -vx # be extra verbose - VERBOSE="-v"; ARGS="$ARGS $1"; shift ;; - -V|--version) echo "$LOGPREFIX: version $VERSION"; exit 0;; - -x|--extract|--restore) - [ "$OP" != "backup" -a "$OP" != "restore" ] && - usage "can't use $1 $TAROP at the same time" - OP="restore"; ARGS="$ARGS $1"; shift ;; - -z|--gzip) TARCOMP="-z"; ARGS="$ARGS $1"; shift ;; - # these commands are for internal use only - --remote) NODENUM="$2"; LOGPREFIX="$(hostname).$2"; shift 2;; - --fileonly) FILEONLY="yes"; shift;; - --) shift; break;; - *) usage "unknown argument '$1'" 1>&2 ;; - esac -done - -set_op_type $OP - -#log "ARGS: $ARGS" - -[ -z "$ARGS" ] && usage "$OP a list of files, running on multiple nodes" - -# we should be able to use any backup tool that can accept filenames -# from an input file instead of just pathnames on the command-line. -# Unset TARCOMP for htar, as it doesn't support on-the-fly compression. -TAREXT= -case "$(basename $TAR)" in - htar*) TARARG="-L"; TAROUT="-f"; TARCOMP=""; MINKB=0 ;; - tar*|gnutar*|gtar*) TARARG="-T"; TAROUT="-b 2048 -f"; TAREXT=.tar ;; - *) fatal "unknown archiver '$TAR'" ;; -esac - -if [ "$OP" = "backup" ]; then - [ -z "$OUTPUTBASE" ] && usage "'-f ${FTYPE}base' must be given for $OP" - # Make sure we leave some margin free in the output filesystem for the - # chunks. If we are dumping to a network filesystem (denoted by having - # a ':' in the name, not sure how else to check) then we assume this - # filesystem is shared among all clients and expect the other nodes - # to also consume space there. - OUTPUTFS=$(dirname $OUTPUTBASE) - NETFS=$(df -P $OUTPUTFS | awk '/^[[:alnum:]]*:/ { print $1 }') - MINKB=${MINKB:-$((SPLITMB * 2 * 1024))} - [ "$NETFS" ] && MINKB=$(($(echo $NODELIST | tr ',' ' ' | wc -w) * $MINKB)) - - # Compress the output files as we go. - case "$TARCOMP" in - -z) TAREXT="$TAREXT.gz";; - -j) TAREXT="$TAREXT.bz2";; - esac -else - [ -z "$OUTPUTBASE" ] && - usage "-f ${OP}filelist must be specified for $OP" - # we want to be able to use this for a list of files to restore - # but it is convenient to use $INPUT for reading the pathnames - # of the tar files during restore/list operations to handle stdin - [ "$INPUT" ] && usage "-i inputbase unsupported for $OP" - INPUT=$OUTPUTBASE - TARARG="" -fi - -[ -z "$NODELIST" ] && NODELIST="localhost" - -# If we are writing to a char or block device (e.g. tape) don't add any suffix -# We can't currently specify a different target device per client... -if [ -b "$OUTPUTBASE" -o -c "$OUTPUTBASE" ]; then - MINKB=0 - [ -z "$LOGDIR" ] && LOGDIR="/var/log" - LOGBASE="$LOGDIR/$PROGNAME" -elif [ -d "$OUTPUTBASE" ]; then - usage "-f $OUTPUTBASE must be a pathname, not a directory" -else - [ -z "$LOGDIR" ] && LOGBASE="$OUTPUTBASE" || LOGBASE="$LOGDIR/$PROGNAME" -fi -LOGBASE="$LOGBASE.$(date +%Y%m%d%H%M)" - -# tar up a sinle list of files into a chunk. We don't exit if there is an -# error returned, since that might happen frequently with e.g. files moving -# and no longer being available for backup. -# usage: run_one_tar {file_list} {chunk_nr} {chunkbytes} -DONE_MSG="FINISH_THIS_PROGRAM_NOW_I_TELL_YOU" -KILL_MSG="EXIT_THIS_PROGRAM_NOW_I_TELL_YOU" -run_one_backup() { -#set -vx - TMPLIST="$1" - CHUNK="$2" - CHUNKMB="$(($3 / 1048576))" - if [ -b "$OUTPUTBASE" -o -c "$OUTPUTBASE" ]; then - OUTFILE="$OUTPUTBASE" - else - OUTFILE="$OUTPUTBASE.$NODENUM.$CHUNK$TAREXT" - fi - CHUNKBASE="$LOGBASE.$NODENUM.$CHUNK" - LISTFILE="$CHUNKBASE.list" - LOG="$CHUNKBASE.log" - - cp "$TMPLIST" "$LISTFILE" - - SLEPT=0 - FREEKB=$(df -P $OUTPUTFS 2> /dev/null | tail -n 1 | awk '{print $4}') - while [ $FREEKB -lt $MINKB ]; do - sleep 5 - SLEPT=$((SLEPT + 5)) - if [ $((SLEPT % 60)) -eq 10 ]; then - log "waiting ${SLEPT}s for ${MINKB}kB free in $OUTPUTFS" - fi - FREEKB=$(df -P $OUTPUTFS | tail -n 1 | awk '{print $4}') - done - [ $SLEPT -gt 0 ] && log "waited ${SLEPT}s for space in ${OUTPUTFS}" - log "$LISTFILE started - est. ${CHUNKMB}MB" - START=$(date +%s) - eval $TAR $TAROP $PERM $TARARG "$TMPLIST" -v $TARCOMP $TAROUT "$OUTFILE" \ - 2>&1 >>"$LOG" | tee -a $LOG | grep -v "Removing leading" - RC=${PIPESTATUS[0]} - ELAPSE=$(($(date +%s) - START)) - if [ $RC -eq 0 ]; then - if [ -f "$OUTFILE" ]; then - BYTES=$(stat -c '%s' "$OUTFILE") - CHUNKMB=$((BYTES / 1048576)) - log "$LISTFILE finished - act. ${CHUNKMB}MB/${ELAPSE}s" - else - log "$LISTFILE finished OK - ${ELAPSE}s" - fi - echo "OK" > $CHUNKBASE.done - else - echo "ERROR=$RC" > $CHUNKBASE.done - log "ERROR: $LISTFILE exited with rc=$RC" - fi - rm $TMPLIST - return $RC -} - -run_one_restore_or_list() { -#set -vx - INPUTFILE="$1" - LOG="$LOGBASE.$(basename $INPUTFILE).restore.log" - - SLEPT=0 - while [ $MINKB != 0 -a ! -r "$INPUTFILE" ]; do - SLEPT=$((SLEPT + 5)) - if [ $((SLEPT % 60)) -eq 10 ]; then - log "waiting ${SLEPT}s for $INPUTFILE staging" - fi - sleep 5 - done - [ $SLEPT -gt 0 ] && log "waited ${SLEPT}s for $INPUTFILE staging" - log "$OP of $INPUTFILE started" - START=$(date +%s) - eval $TAR $TAROP -v $TARCOMP $TAROUT "$INPUTFILE" 2>&1 >>"$LOG" | - tee -a "$LOG" | grep -v "Removing leading" - RC=${PIPESTATUS[0]} - ELAPSE=$(($(date +%s) - START)) - [ "$OP" = "list" ] && cat $LOG - if [ $RC -eq 0 ]; then - log "$INPUTFILE finished OK - ${ELAPSE}s" - echo "OK" > $INPUTFILE.restore.done - else - echo "ERROR=$RC" > $INPUTFILE.restore.done - log "ERROR: $OP of $INPUTFILE exited with rc=$RC" - fi - return $RC -} - -# Run as a remote command and read input filenames from stdin and create tar -# output files of the requested size. The input filenames can either be: -# "bytes filename" or "filename" depending on whether FILEONLY is set. -# -# Read filenames until we have either a large enough list of small files, -# or we get a very large single file that is backed up by itself. -run_remotely() { -#set -vx - log "started thread" - RCMAX=0 - - [ "$FILEONLY" ] && PARAMS="FILENAME" || PARAMS="BYTES FILENAME" - - if [ "$OP" = "backup" ]; then - TMPBASE=$PROGNAME.$LOGPREFIX.temp - TMPFILE="$(mktemp -t $TMPBASE.$(date +%s).XXXXXXX)" - OUTPUTFILENUM=0 - SUMBYTES=0 - fi - BYTES="" - - while read $PARAMS; do - [ "$FILENAME" = "$DONE_MSG" -o "$BYTES" = "$DONE_MSG" ] && break - if [ "$FILENAME" = "$KILL_MSG" -o "$BYTES" = "$KILL_MSG" ]; then - log "exiting $OP on request" - [ "$TARPID" ] && kill -9 $TARPID 2> /dev/null - exit 9 - fi - - case "$OP" in - list|restore) - run_one_restore_or_list $FILENAME; RC=$? - ;; - backup) STAT=($(stat -c '%s %F' "$FILENAME")) - [ "$FILEONLY" ] && BYTES=${STAT[0]} - # if this is a directory that has files in it, it will - # be backed up as part of this (or some other) backup. - # Only include it in the backup if empty, otherwise - # the files therein will be backed up multiple times - if [ "${STAT[1]}" = "directory" ]; then - NUM=`find "$FILENAME" -maxdepth 1|head -2|wc -l` - [ "$NUM" -gt 1 ] && continue - fi - [ "$VERBOSE" ] && log "$FILENAME" - - # if a file is > 3/4 of chunk size, archive by itself - # avoid shell math: 1024 * 1024 / (3/4) = 1398101 - if [ $((BYTES / 1398101)) -gt $SPLITMB ]; then - # create a very temp list for just this file - TARLIST=$(mktemp -t $TMPBASE.$(date +%s).XXXXXX) - echo "$FILENAME" > "$TARLIST" - TARBYTES=$BYTES - else - SUMBYTES=$((SUMBYTES + BYTES)) - echo "$FILENAME" >> $TMPFILE - - # not large enough input list, keep collecting - [ $((SUMBYTES >> 20)) -lt $SPLITMB ] && continue - - TARBYTES=$SUMBYTES - SUMBYTES=0 - TARLIST="$TMPFILE" - TMPFILE=$(mktemp -t $TMPBASE.$(date +%s).XXXXXXX) - fi - - wait $TARPID - RC=$? - run_one_backup "$TARLIST" "$OUTPUTFILENUM" $TARBYTES & - TARPID=$! - OUTPUTFILENUM=$((OUTPUTFILENUM + 1)) - ;; - esac - - [ $RC -gt $RCMAX ] && RCMAX=$RC - done - - if [ "$TARPID" ]; then - wait $TARPID - RC=$? - [ $RC -gt $RCMAX ] && RCMAX=$RC - fi - - if [ -s "$TMPFILE" ]; then - run_one_backup "$TMPFILE" "$OUTPUTFILENUM" $SUMBYTES - RC=$? - [ $RC -gt $RCMAX ] && RCMAX=$RC - fi - exit $RCMAX -} - -# If we are a client then just run that subroutine and exit -[ "$NODENUM" ] && run_remotely && exit 0 - -# Tell the clients to exit. Their input pipes might be busy so it may -# take a while for them to consume the files and finish. -CLEANING=no -cleanup() { - log "cleaning up remote processes" - for FD in $(seq $BASEFD $((BASEFD + NUMCLI - 1))); do - echo "$DONE_MSG" >&$FD - done - CLEANING=yes - - SLEPT=0 - RUN=$(ps auxww | egrep -v "grep|bash" | grep -c "$PROGNAME.*remote") - while [ $RUN -gt 0 ]; do - set +vx - #ps auxww | grep "$PROGNAME.*remote" | egrep -v "grep|bash" - sleep 1 - SLEPT=$((SLEPT + 1)) - [ $((SLEPT % 30)) -eq 0 ] && - log "wait for $RUN processes to finish" - [ $((SLEPT % 300)) -eq 0 ] && - ps auxww |grep "$PROGNAME.*remote" |egrep -v "grep|bash" - RUN=$(ps auxww|egrep -v "grep|bash"|grep -c "$PROGNAME.*remote") - done - trap 0 -} - -do_cleanup() { - if [ "$CLEANING" = "yes" ]; then - log "killing all remote processes - may not stop immediately" - for FD in $(seq $BASEFD $((BASEFD + NUMCLI - 1))); do - echo "$KILL_MSG" >&$FD - done - sleep 1 - PROCS=$(ps auxww|awk '/$PROGNAME.*remote/ { print $2 }') - [ "$PROCS" ] && kill -9 $PROCS - trap 0 - fi - - cleanup -} - -# values that only need to be determined on the master -# always read from stdin, even if it is a file, to be more consistent -case "$INPUT" in - -|"") INPUT="standard input";; - *) if [ ! -r "$INPUT" ]; then - [ "$VERBOSE" ] && ls -l "$INPUT" - usage "can't read input file '$INPUT'" - fi - exec <$INPUT ;; -esac - -# if unspecified, run remote clients in the current PWD to get correct paths -[ -z "$GOTODIR" ] && ARGS="$ARGS -C \"$PWD\"" - -# main() -BASEFD=100 -NUMCLI=0 - -# Check if the input list has the file size specified or not. Input -# lines should be of the form "{bytes} {filename}" or "{filename}". -# If no size is given then the file sizes are determined by the clients -# to do the chunking (useful for making a full backup, but not as good -# at evenly distributing the data among clients). In rare cases the first -# file specified may have a blank line and no size - check that as well. -if [ "$OP" = "backup" ]; then - read BYTES FILENAME - if [ -z "$FILENAME" -a -e "$BYTES" ]; then - FILENAME="$BYTES" - BYTES="" - FILEONLY="yes" && ARGS="$ARGS --fileonly" - elif [ -e "$BYTES $FILENAME" ]; then - FILENAME="$BYTES $FILENAME" - BYTES="" - FILEONLY="yes" && ARGS="$ARGS --fileonly" - elif [ ! -e "$FILENAME" ]; then - log "input was '$BYTES $FILENAME'" - fatal "first line of '$INPUT' is not a file" - fi -else - FILEONLY="yes" && ARGS="$ARGS --fileonly" -fi - -# kill the $RSH processes if we get a signal -trap do_cleanup INT EXIT - -# start up the remote processes, each one with its stdin attached to a -# different output file descriptor, so that we can communicate with them -# individually when sending files to back up. We generate a remote log -# file and also return output to this process. -for CLIENT in $(echo $NODELIST | tr ',' ' '); do - FD=$((BASEFD+NUMCLI)) - LOG=$OUTPUTBASE.$CLIENT.$FD.log - eval "exec $FD> >($RSH $CLIENT '$PROGPATH --remote=$NUMCLI $ARGS')" - RC=$? - if [ $RC -eq 0 ]; then - log "starting $0.$NUMCLI on $CLIENT" - NUMCLI=$((NUMCLI + 1)) - else - log "ERROR: failed '$RSH $CLIENT $PROGPATH': RC=$?" - fi -done - -if [ $NUMCLI -eq 0 ]; then - fatal "unable to start any threads" -fi - -CURRCLI=0 -# We don't want to use "BYTES FILENAME" if the input doesn't include the -# size, as this might cause problems with files with whitespace in them. -# Instead we just have two different loops depending on whether the size -# is in the input file or not. We dish out the files either by size -# (to fill a chunk), or just round-robin and hope for the best. -if [ "$FILEONLY" ]; then - if [ "$FILENAME" ]; then - [ "$VERBOSE" ] && log "$FILENAME" - echo "$FILENAME" 1>&$BASEFD # rewrite initial line - fi - # if we don't know the size, just round-robin among the clients - while read FILENAME; do - FD=$((BASEFD+CURRCLI)) - [ -n "$VERBOSE" -a "$OP" != "backup" ] && log "$OP $FILENAME" - echo "$FILENAME" 1>&$FD - - COUNT=$((COUNT + 1)) - if [ $COUNT -ge $SPLITCOUNT ]; then - CURRCLI=$(((CURRCLI + 1) % NUMCLI)) - COUNT=0 - fi - done -else - [ "$VERBOSE" ] && log "$FILENAME" - echo $BYTES "$FILENAME" 1>&$BASEFD # rewrite initial line - # if we know the size, then give each client enough to start a chunk - while read BYTES FILENAME; do - FD=$((BASEFD+CURRCLI)) - [ "$VERBOSE" ] && log "$FILENAME" - echo $BYTES "$FILENAME" >&$FD - - # take tar blocking factor into account - [ $BYTES -lt 10240 ] && BYTES=10240 - SUMBYTES=$((SUMBYTES + BYTES)) - if [ $((SUMBYTES / 1048576)) -ge $SPLITMB ]; then - CURRCLI=$(((CURRCLI + 1) % NUMCLI)) - SUMBYTES=0 - fi - done -fi - -# Once all of the files have been given out, wait for the remote processes -# to complete. That might take a while depending on the size of the backup. -cleanup