-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 \
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
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"
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])
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
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 \
/Makefile.in
-/acceptor
/routerstat
/wirecheck
/lst
# Lustre is a trademark of Sun Microsystems, Inc.
#
-## $(srcdir)/../ for <portals/*.h>, ../../ for generated <config.h>
-#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
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
%bcond_without ldiskfs
%bcond_with zfs
%bcond_without lustre_tests
+%bcond_without lustre_utils
%bcond_without lustre_iokit
%bcond_without lustre_modules
# 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
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
# 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
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
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
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
%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
%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
/lustre.spec
/Makefile.in
/version_tag.pl
-/lustre_createcsv.sh
-/lustre_config.sh
/lc_net.sh
/lc_modprobe.sh
/lc_hb.sh
/lc_md
/lc_modprobe
/lc_net
-/lustre_config
-/lustre_createcsv
/lustre
/lustre_start
/tree_status.pl
# 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)
+++ /dev/null
-#!/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 <<EOF
-
-Usage: $(basename $0) [options] <-a|-w|-x> <csv file>
-
- 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 <<EOF
-
-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.
-
-It can also optionally:
- * upgrade Lustre targets from 1.4 to 1.6
- * verify the network connectivity and hostnames in the cluster
- * configure Linux MD/LVM devices
- * modify /etc/modprobe.conf to add Lustre networking info
- * add the Lustre server info to /etc/fstab
- * produce configurations for Heartbeat or CluManager.
-
-There are 5 kinds of line formats in the csv file. They represent the following
-targets:
-1) Linux MD device
-The format is:
-hostname,MD,md name,operation mode,options,raid level,component devices
-
-hostname hostname of the node in the cluster
-MD marker of MD device line
-md name MD device name, e.g. /dev/md0
-operation mode create or remove, default is create
-options a "catchall" for other mdadm options, e.g. "-c 128"
-raid level raid level: 0,1,4,5,6,10,linear and multipath
-component devices block devices to be combined into the MD device
- Multiple devices are separated by space or by using
- shell expansions, e.g. "/dev/sd{a,b,c}"
-
-2) Linux LVM PV (Physical Volume)
-The format is:
-hostname,PV,pv names,operation mode,options
-
-hostname hostname of the node in the cluster
-PV marker of PV line
-pv names devices or loopback files to be initialized for later
- use by LVM or to be wiped the label, e.g. /dev/sda
- Multiple devices or files are separated by space or by
- using shell expansions, e.g. "/dev/sd{a,b,c}"
-operation mode create or remove, default is create
-options a "catchall" for other pvcreate/pvremove options
- e.g. "-vv"
-
-3) Linux LVM VG (Volume Group)
-The format is:
-hostname,VG,vg name,operation mode,options,pv paths
-
-hostname hostname of the node in the cluster
-VG marker of VG line
-vg name name of the volume group, e.g. ost_vg
-operation mode create or remove, default is create
-options a "catchall" for other vgcreate/vgremove options
- e.g. "-s 32M"
-pv paths physical volumes to construct this VG, required by
- create mode
- Multiple PVs are separated by space or by using
- shell expansions, e.g. "/dev/sd[k-m]1"
-
-4) Linux LVM LV (Logical Volume)
-The format is:
-hostname,LV,lv name,operation mode,options,lv size,vg name
-
-hostname hostname of the node in the cluster
-LV marker of LV line
-lv name name of the logical volume to be created (optional)
- or path of the logical volume to be removed (required
- by remove mode)
-operation mode create or remove, default is create
-options a "catchall" for other lvcreate/lvremove options
- e.g. "-i 2 -I 128"
-lv size size [kKmMgGtT] to be allocated for the new LV
- Default unit is megabytes.
-vg name name of the VG in which the new LV will be created
-
-5) Lustre target
-The format is:
-hostname,module_opts,device name,mount point,device type,fsname,mgs nids,index,
-format options,mkfs options,mount options,failover nids
-
-hostname hostname of the node in the cluster, must match "uname -n"
-module_opts Lustre networking module options
-device name Lustre target (block device or loopback file)
-mount point Lustre target mount point
-device type Lustre target type (mgs, mdt, ost, mgs|mdt, mdt|mgs)
-fsname Lustre filesystem name, should be limited to 8 characters
- Default is "lustre".
-mgs nids NID(s) of remote mgs node, required for mdt and ost targets
- If this item is not given for an mdt, it is assumed that
- the mdt will also be an mgs, according to mkfs.lustre.
-index Lustre target index
-format options a "catchall" contains options to be passed to mkfs.lustre
- "--device-size", "--param", etc. all goes into this item.
-mkfs options format options to be wrapped with --mkfsoptions="" and
- passed to mkfs.lustre
-mount options If this script is invoked with "-m" option, then the value of
- this item will be wrapped with --mountfsoptions="" and passed
- to mkfs.lustre, else the value will be added into /etc/fstab.
-failover nids NID(s) of failover partner node
-
-All the NIDs in one node are delimited by commas (','). When multiple nodes are
-specified, they are delimited by a colon (':').
-
-Items left blank will be set to defaults.
-
-Example 1 - Simple, with combo MGS/MDT:
--------------------------------------------------------------------------------
-# combo mdt/mgs
-lustre-mgs,options lnet networks=tcp,/tmp/mgs,/mnt/mgs,mgs|mdt,,,,--device-size=10240
-
-# ost0
-lustre-ost,options lnet networks=tcp,/tmp/ost0,/mnt/ost0,ost,,lustre-mgs@tcp0,,--device-size=10240
-
-# ost1
-lustre-ost,options lnet networks=tcp,/tmp/ost1,/mnt/ost1,ost,,lustre-mgs@tcp0,,--device-size=10240
--------------------------------------------------------------------------------
-
-Example 2 - Separate MGS/MDT, two networks interfaces:
--------------------------------------------------------------------------------
-# mgs
-lustre-mgs1,options lnet 'networks="tcp,elan"',/dev/sda,/mnt/mgs,mgs,,,,--quiet --param="sys.timeout=50",,"defaults,noauto","lustre-mgs2,2@elan"
-
-# mdt
-lustre-mdt1,options lnet 'networks="tcp,elan"',/dev/sdb,/mnt/mdt,mdt,lustre2,"lustre-mgs1,1@elan:lustre-mgs2,2@elan",,--quiet --param="lov.stripesize=4194304",-J size=16,"defaults,noauto",lustre-mdt2
-
-# ost
-lustre-ost1,options lnet 'networks="tcp,elan"',/dev/sdc,/mnt/ost,ost,lustre2,"lustre-mgs1,1@elan:lustre-mgs2,2@elan",,--quiet,-I 512,"defaults,noauto",lustre-ost2
--------------------------------------------------------------------------------
-
-Example 3 - with combo MGS/MDT failover pair and OST failover pair:
--------------------------------------------------------------------------------
-# combo mgs/mdt
-lustre-mgs1,options lnet networks=tcp,/tmp/mgs,/mnt/mgs,mgs|mdt,,,,--quiet --device-size=10240,,,lustre-mgs2@tcp0
-
-# combo mgs/mdt backup (--noformat)
-lustre-mgs2,options lnet networks=tcp,/tmp/mgs,/mnt/mgs,mgs|mdt,,,,--quiet --device-size=10240 --noformat,,,lustre-mgs1@tcp0
-
-# ost
-lustre-ost1,options lnet networks=tcp,/tmp/ost1,/mnt/ost1,ost,,"lustre-mgs1@tcp0:lustre-mgs2@tcp0",,--quiet --device-size=10240,,,lustre-ost2@tcp0
-
-# ost backup (--noformat) (note different device name)
-lustre-ost2,options lnet networks=tcp,/tmp/ost2,/mnt/ost2,ost,,"lustre-mgs1@tcp0:lustre-mgs2@tcp0",,--quiet --device-size=10240 --noformat,,,lustre-ost1@tcp0
--------------------------------------------------------------------------------
-
-Example 4 - Configure Linux MD/LVM devices before formatting Lustre targets:
--------------------------------------------------------------------------------
-# MD device on mgsnode
-mgsnode,MD,/dev/md0,,-q,1,/dev/sda1 /dev/sdb1
-
-# MD/LVM devices on ostnode
-ostnode,MD,/dev/md0,,-q -c 128,5,"/dev/sd{a,b,c}"
-ostnode,MD,/dev/md1,,-q -c 128,5,"/dev/sd{d,e,f}"
-ostnode,PV,/dev/md0 /dev/md1
-ostnode,VG,ost_vg,,-s 32M,/dev/md0 /dev/md1
-ostnode,LV,ost0,,-i 2 -I 128,300G,ost_vg
-ostnode,LV,ost1,,-i 2 -I 128,300G,ost_vg
-
-# combo mgs/mdt
-mgsnode,options lnet networks=tcp,/dev/md0,/mnt/mgs,mgs|mdt,,,,--quiet
-
-# ost0
-ostnode,options lnet networks=tcp,/dev/ost_vg/ost0,/mnt/ost0,ost,,mgsnode,,--quiet
-
-# ost1
-ostnode,options lnet networks=tcp,/dev/ost_vg/ost1,/mnt/ost1,ost,,mgsnode,,--quiet
--------------------------------------------------------------------------------
-
-EOF
- exit 0
-}
-
-# Get the library of functions
-. @scriptlibdir@/lc_common
-
-#***************************** Global variables *****************************#
-declare -a NODE_NAMES # node names in the failover group
-declare -a TARGET_OPTS # target services in one failover group
-
-CONFIG_MD_LVM=false
-MODIFY_FSTAB=true
-UPGRADE_TARGET=false
-# Get and check the positional parameters
-while getopts "aw:x:t:ndfmuhv" OPTION; do
- case $OPTION in
- a)
- [ -z "${SPECIFIED_NODELIST}" ] && [ -z "${EXCLUDED_NODELIST}" ] \
- && USE_ALLNODES=true
- NODELIST_OPT="${NODELIST_OPT} -a"
- ;;
- w)
- USE_ALLNODES=false
- SPECIFIED_NODELIST=$OPTARG
- NODELIST_OPT="${NODELIST_OPT} -w ${SPECIFIED_NODELIST}"
- ;;
- x)
- USE_ALLNODES=false
- EXCLUDED_NODELIST=$OPTARG
- NODELIST_OPT="${NODELIST_OPT} -x ${EXCLUDED_NODELIST}"
- ;;
- t)
- HATYPE_OPT=$OPTARG
- if [ "${HATYPE_OPT}" != "${HBVER_HBV1}" ] \
- && [ "${HATYPE_OPT}" != "${HBVER_HBV2}" ] \
- && [ "${HATYPE_OPT}" != "${HATYPE_CLUMGR}" ]; then
- error_output "Invalid HA software type" \
- "- ${HATYPE_OPT}!"
- usage 1>&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
+++ /dev/null
-#!/bin/bash
-#
-# Reads old MDS config logs for transferring to a MGS
-#
-###############################################################################
-
-TMP=${TMP:-/tmp/logs}
-
-# Usage
-usage() {
- cat >&2 <<EOF
-
-Usage: `basename $0` <mdsdev> <newfsname>
-
- <mdsdev> the MDS disk device (e.g. /dev/sda1)
- <newfsname> 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
-
$(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
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
$(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$f; \
else :; fi; \
done
+endif
if LDISKFS_ENABLED
libiam_a_SOURCES = libiam.c
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
+++ /dev/null
-#!/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 <adilger@sun.com>
-#
-
-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