Whamcloud - gitweb
EX-3198 lipe: add lipe_find2 script
authorJian Yu <yujian@whamcloud.com>
Thu, 26 Aug 2021 07:13:32 +0000 (00:13 -0700)
committerJohn L. Hammond <jhammond@whamcloud.com>
Fri, 15 Oct 2021 22:26:46 +0000 (22:26 +0000)
Add a simplified lipe_find2 script to wrap lipe_convert_expr
and lipe_scan2.

Usage: lipe_find2 [OPTION]... -- DEVICE [EXPRESSION]
  --client-mount=MOUNT  use the Lustre client at MOUNT for FID to path
  --print-fid           print FID of each file matching expression
  --print-json[=ATTRS]  print a JSON object with atributes specified by ATTRS
                        describing each file matching expression. ATTRS must be
                        a comma separated list of attribute names.
                        use 'lipe_find2 --list-attrs' to see available attributes names
  --print-path[=WHICH]  print path(s) of each file matching expression
                        WHICH must be 'one' (default) or 'all'
  --absolute-paths      prefix paths with MOUNT/ (for --print-path)
                        prefix FIDs with MOUNT/.lustre/fid/ (for --print-fid)
  --delimiter=DELIM     use DELIM intead of newline to delimit matches
  --null                use a NUL byte intead of newline to delimit matches
  --threads=COUNT       use COUNT scanning threads
  -h,--help             display this help text and exit
  --debug               display debug information
  --list-attrs          list available attribute names
  --no-convert          do not convert the EXPRESSION
  --version             output version information and exit

If --absolute-paths or --print-path is used then --client-mount is
required. It is also required if --print-json is used and ATTRS
includes paths.

For expression details see lipe_find(1).

Test-Parameters: trivial testlist=sanity-lipe
Test-Parameters: trivial env=LIPE_FIND=lipe_find2 testlist=sanity-lipe
Change-Id: Iacca61f9f5d28d17a45596b9d96f958dc50ca57f
Signed-off-by: Jian Yu <yujian@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/44963
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: John L. Hammond <jhammond@whamcloud.com>
lipe/Makefile.am
lipe/lipe-func.sh [new file with mode: 0755]
lipe/lipe.spec.in
lipe/lipe_find2 [new file with mode: 0755]
lustre/tests/sanity-lipe.sh

index e5bfddf..82cdcb5 100644 (file)
@@ -70,6 +70,8 @@ EXTRA_DIST= \
        lipe.spec \
        lipe.spec.in \
        lipe_c_check.pl \
+       lipe_find2 \
+       lipe-func.sh \
        lpcc.conf \
        laudit.conf.example \
        pybuild/*.py \
diff --git a/lipe/lipe-func.sh b/lipe/lipe-func.sh
new file mode 100755 (executable)
index 0000000..94cbda7
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/bash
+# Common functions for LiPE utilities
+
+LL_SUPER_MAGIC=0x0BD00BD0
+
+debug() {
+       if $DEBUG; then
+               echo "$PROGRAM_NAME: $@" >&2
+       fi
+}
+
+error() {
+       echo "$PROGRAM_NAME: $@" >&2
+}
+
+fatal() {
+       error "fatal:" "$@"
+       exit 1
+}
+
+# Check Lustre client mount point and device.
+check_client_mount() {
+       local mount_point="$1"
+       local device="$2"
+       local fstype
+       local label
+
+       [[ $mount_point ]] || fatal "client mount point must be specified"
+       [[ $device ]] || fatal "device must be specified"
+       [[ -b $device ]] || fatal "'$device' is not a block device"
+
+       # Check that $mount_point is a Lustre client mount.
+       fstype=$(stat --file-system --format='%t' $mount_point)
+       debug "fstype = '$fstype'"
+
+       mountpoint --quiet $mount_point &&
+       ((16#$fstype == LL_SUPER_MAGIC)) ||
+               fatal "'$mount_point' is not a Lustre client mount point"
+
+       # Check that $mount_point/.lustre/fid exists.
+       [[ -d $mount_point/.lustre/fid ]] ||
+               fatal "'$mount_point/.lustre/fid' does not exist"
+
+       # Check that $mount_point is the right Lustre client mount for $device.
+       label=$(e2label $device)
+       lfs df $mount_point | grep -q "^${label}_UUID" ||
+               fatal "'$device' is not a server device for '$mount_point'"
+
+       return 0
+}
index 3ddf591..1701413 100644 (file)
@@ -224,6 +224,8 @@ cp -a \
 cp \
        ldsync \
        lipe_find \
+       lipe_find2 \
+       lipe-func.sh \
        lipe_convert_expr \
        lipe_run_action \
        lipe_install \
@@ -406,6 +408,9 @@ rm -rf $RPM_BUILD_ROOT
 %{_bindir}/lipe_scan
 %{_bindir}/lipe_scan2
 %{_bindir}/lipe_find
+%{_bindir}/lipe_find2
+%{_bindir}/lipe-func.sh
+%{_bindir}/lipe_convert_expr
 %{python2_sitelib}/pylipe
 %config(noreplace) %{_sysconfdir}/lipe_install.conf
 %config(noreplace) %{_sysconfdir}/lipe_launch.json
diff --git a/lipe/lipe_find2 b/lipe/lipe_find2
new file mode 100755 (executable)
index 0000000..d682d2f
--- /dev/null
@@ -0,0 +1,169 @@
+#!/bin/bash
+
+set -e
+
+LIPE_PATH=${LIPE_PATH:-$(dirname $(type -p $0))}
+. $LIPE_PATH/lipe-func.sh
+
+PROGRAM_NAME=$(basename $0)
+LIPE_SCAN=${LIPE_SCAN:-"lipe_scan2"}
+LIPE_CONVERT_EXPR=${LIPE_CONVERT_EXPR:-"lipe_convert_expr"}
+LIPE_CONVERT=true
+DEBUG=false
+
+usage() {
+       echo "Usage: $PROGRAM_NAME [OPTION]... -- DEVICE [EXPRESSION]" >&2
+       echo "Try '$PROGRAM_NAME --help' for more information" >&2
+       exit 1
+}
+
+help() {
+cat <<EOF
+Usage: $PROGRAM_NAME [OPTION]... -- DEVICE [EXPRESSION]
+Scan DEVICE for files matching EXPRESSION (or all files if expression
+is omitted). Print FIDs (default), JSON object descriptions, or paths,
+of matching files to stdout.
+
+Mandatory arguments to long options are mandatory for short options too.
+  --client-mount=MOUNT        use the Lustre client at MOUNT for FID to path
+  --print-fid                 print FID of each file matching expression
+  --print-json[=ATTRS]        print a JSON object with atributes specified by ATTRS
+                              describing each file matching expression. ATTRS must be
+                              a comma separated list of attribute names.
+                              use '$PROGRAM_NAME --list-attrs' to see available attributes names
+  --print-path[=WHICH]        print path(s) of each file matching expression
+                              WHICH must be 'one' (default) or 'all'
+  --absolute-paths            prefix paths with MOUNT/ (for --print-path)
+                              prefix FIDs with MOUNT/.lustre/fid/ (for --print-fid)
+  --delimiter=DELIM           use DELIM intead of newline to delimit matches
+  --null                      use a NUL byte intead of newline to delimit matches
+  --threads=COUNT             use COUNT scanning threads
+  -h,--help                   display this help text and exit
+  --debug                     display debug information
+  --list-attrs                list available attribute names
+  --no-convert                do not convert the EXPRESSION
+  --version                   output version information and exit
+
+If --absolute-paths or --print-path is used then --client-mount is
+required. It is also required if --print-json is used and ATTRS
+includes paths.
+
+For expression details see lipe_find(1).
+EOF
+       exit 0
+}
+
+main() {
+       local client_mount
+       local device
+       local expression
+       local threads=0 # 0 means default.
+       local -a lipe_scan2_options=()
+       local options
+       local opt
+
+       local short_options="h"
+       local long_options="client-mount:,print-fid,print-json::,print-path::"
+       long_options+="${long_options:+,}absolute-paths,delimiter:,null"
+       long_options+="${long_options:+,}threads:,help,debug,list-attrs"
+       long_options+="${long_options:+,}no-convert,version"
+       options=$(getopt --name="$PROGRAM_NAME" \
+                        --options="$short_options" \
+                        --longoptions="$long_options" -- "$@") ||
+               fatal "invalid options"
+
+       eval set -- "$options"
+       while true; do
+               case "$1" in
+               --client-mount)
+                       shift
+                       client_mount="$1"
+                       lipe_scan2_options+=(--client-mount="$1")
+                       ;;
+               --print-fid)
+                       lipe_scan2_options+=(--print-fid)
+                       ;;
+               --print-json)
+                       shift
+                       opt="--print-json"
+                       [[ -z "$1" ]] || opt+="=$1"
+                       lipe_scan2_options+=("$opt")
+                       ;;
+               --print-path)
+                       shift
+                       opt="--print-path"
+                       [[ -z "$1" ]] || opt+="=$1"
+                       lipe_scan2_options+=("$opt")
+                       ;;
+               --absolute-paths)
+                       lipe_scan2_options+=(--absolute-paths)
+                       ;;
+               --delimiter)
+                       shift
+                       lipe_scan2_options+=(--delimiter="$1")
+                       ;;
+               --null)
+                       lipe_scan2_options+=(--null)
+                       ;;
+               --threads)
+                       shift
+                       threads="$1"
+                       lipe_scan2_options+=(--threads="$1")
+                       ;;
+               -h|--help)
+                       help
+                       ;;
+               --debug)
+                       DEBUG=true
+                       lipe_scan2_options+=(--debug)
+                       ;;
+               --list-attrs)
+                       $LIPE_SCAN --list-attrs
+                       exit 0
+                       ;;
+               --no-convert)
+                       LIPE_CONVERT=false
+                       ;;
+               --version)
+                       $LIPE_SCAN --version |
+                               sed -e "s/$LIPE_SCAN/$PROGRAM_NAME/"
+                       exit 0
+                       ;;
+               --)
+                       shift
+                       break
+                       ;;
+               esac
+               shift
+       done
+
+       if [[ $# < 1 ]]; then
+               # Missing device.
+               usage
+       fi
+
+       device="$1"
+       shift
+       # Now $@ is just the expression.
+       debug "client_mount = '$client_mount'"
+       debug "device = '$device'"
+       debug "threads = '$threads'"
+       debug "argc = $#"
+       debug "argv = '$@'"
+
+       [[ -z "$client_mount" ]] ||
+               check_client_mount $client_mount $device
+
+       if [[ -n "$@" ]]; then
+               expression="$@"
+               ! $LIPE_CONVERT || expression=$($LIPE_CONVERT_EXPR "$@")
+       fi
+       debug "expression = '$expression'"
+
+       local start=$SECONDS
+       $LIPE_SCAN "${lipe_scan2_options[@]}" "$device" \
+               ${expression:+"$expression"}
+       echo "$PROGRAM_NAME finished in $((SECONDS - start)) seconds" >&2
+}
+
+main "$@"
index 8ff932f..20f706f 100644 (file)
@@ -36,17 +36,29 @@ done
 which jq || skip_env "jq is not installed"
 
 # lipe_find configuration
-LIPE_FIND="lipe_find"
+LIPE_FIND=${LIPE_FIND:-"lipe_find"}
 LIPE_FIND_LOG_DIR=${LIPE_FIND_LOG_DIR:-"/var/log/lipe_find"}
 LIPE_FIND_VERBOSE=${LIPE_FIND_VERBOSE:-false}
 LIPE_FIND_USE_MOUNT=${LIPE_FIND_USE_MOUNT:-false}
 
+[[ $LIPE_FIND = *lipe_find ]] && PRINT_FID_OPT="-print-fid" ||
+       PRINT_FID_OPT="--print-fid"
+
 LIPE_POOL1=${LIPE_POOL1:-"fast"}
 LIPE_POOL2=${LIPE_POOL2:-"slow"}
 
 build_test_filter
 check_and_setup_lustre
 
+# mount Lustre clients on MDS node(s)
+LIPE_MDS_NODE=$(exclude_items_from_list $(comma_list $(all_mdts_nodes)) \
+               $HOSTNAME)
+if [[ -n $LIPE_MDS_NODE ]]; then
+       zconf_mount_clients $LIPE_MDS_NODE $MOUNT ||
+               error "failed to mount Lustre client on MDS node $LIPE_MDS_NODE"
+       stack_trap "zconf_umount_clients $LIPE_MDS_NODE $MOUNT"
+fi
+
 # create OST pools
 create_ost_pools() {
        pool_add $LIPE_POOL1 || error "failed to create OST pool '$LIPE_POOL1'"
@@ -192,26 +204,31 @@ do_lipe_find_facet() {
        local facet="$1"
        local action="$2"
        local device="$(facet_device $facet)"
+       local device_opt
        local quiet
 
        $LIPE_FIND_VERBOSE || quiet=yes
        ! $LIPE_FIND_USE_MOUNT || device=$MOUNT
 
+       [[ $LIPE_FIND = *lipe_find ]] && device_opt="$device" ||
+               device_opt="-- $device"
+
        # lipe_find fails if run twice in the same wall clock second.
        VERBOSE=false do_facet $facet "sync; [[ ! -e $LIPE_FIND_LOG_DIR ]] ||" \
                "find $LIPE_FIND_LOG_DIR -mindepth 1 -delete"
-       do_facet $facet "$LIPE_FIND $action $device ${@:3}" \
+       do_facet $facet "$LIPE_FIND $action $device_opt ${@:3}" \
                        "${quiet:+2>/dev/null}"
 }
 
 expect_fid() {
        local fid="$1"
        local which="${2:-true}"
+       local fid_str="$(tr -d '[]' <<<$fid)"
 
        if $which; then
-               grep --fixed-strings "$fid" || error "expected FID '$fid'"
+               grep --fixed-strings "$fid_str" || error "expected FID '$fid'"
        else
-               ! grep --fixed-strings "$fid" || error "unexpected FID '$fid'"
+               ! grep --fixed-strings "$fid_str" || error "unexpected FID '$fid'"
        fi
 }
 
@@ -230,14 +247,16 @@ lipe_find_expect_file() {
        local file="$1"
        local which="$2"
 
-       do_lipe_find_facet mds1 -print-fid "${@:3}" | expect_file "$file" "$which"
+       do_lipe_find_facet mds1 $PRINT_FID_OPT "${@:3}" |
+               expect_file "$file" "$which"
 }
 
 lipe_find_expect_fid() {
        local fid="$1"
        local which="$2"
 
-       do_lipe_find_facet mds1 -print-fid "${@:3}" | expect_fid "$fid" "$which"
+       do_lipe_find_facet mds1 $PRINT_FID_OPT "${@:3}" |
+               expect_fid "$fid" "$which"
 }
 
 lipe_find_max_stripe_size() {
@@ -264,7 +283,7 @@ lipe_find_max_stripe_size() {
 
 # lipe_find test cases
 test_1() {
-       do_lipe_find_facet mds1 -print-fid || error "cannot run lipe_find"
+       do_lipe_find_facet mds1 $PRINT_FID_OPT || error "cannot run lipe_find"
 }
 run_test 1 "lipe_find works"
 
@@ -380,12 +399,6 @@ test_5() {
        mkdir $td || error "mkdir $td failed"
        create_lipe_find_files $tf
 
-       # mount Lustre clients on MDS nodes
-       zconf_mount_clients $(comma_list $(all_mdts_nodes)) $MOUNT ||
-               error "failed to mount Lustre clients on MDS nodes"
-       stack_trap "zconf_umount_clients $(comma_list $(all_mdts_nodes)) \
-                  $MOUNT"
-
        local saved_LIPE_FIND_USE_MOUNT=$LIPE_FIND_USE_MOUNT
        LIPE_FIND_USE_MOUNT=true
        stack_trap "LIPE_FIND_USE_MOUNT=$saved_LIPE_FIND_USE_MOUNT"
@@ -1018,12 +1031,6 @@ test_17() {
        mkdir $td-1 || error "mkdir $td-1 failed"
        create_lipe_find_files $tf
 
-       # mount Lustre clients on MDS nodes
-       zconf_mount_clients $(comma_list $(all_mdts_nodes)) $MOUNT ||
-               error "failed to mount Lustre clients on MDS nodes"
-       stack_trap "zconf_umount_clients $(comma_list $(all_mdts_nodes)) \
-                  $MOUNT"
-
        local saved_LIPE_FIND_USE_MOUNT=$LIPE_FIND_USE_MOUNT
        LIPE_FIND_USE_MOUNT=true
        stack_trap "LIPE_FIND_USE_MOUNT=$saved_LIPE_FIND_USE_MOUNT"
@@ -1240,12 +1247,6 @@ test_22() {
        mkdir $td || error "mkdir $td failed"
        create_lipe_find_files $tf
 
-       # mount Lustre clients on MDS nodes
-       zconf_mount_clients $(comma_list $(all_mdts_nodes)) $MOUNT ||
-               error "failed to mount Lustre clients on MDS nodes"
-       stack_trap "zconf_umount_clients $(comma_list $(all_mdts_nodes)) \
-                  $MOUNT"
-
        local saved_LIPE_FIND_USE_MOUNT=$LIPE_FIND_USE_MOUNT
        LIPE_FIND_USE_MOUNT=true
        stack_trap "LIPE_FIND_USE_MOUNT=$saved_LIPE_FIND_USE_MOUNT"
@@ -1319,12 +1320,6 @@ test_23() {
        mkdir $td || error "mkdir $td failed"
        create_lipe_find_files $tf
 
-       # mount Lustre clients on MDS nodes
-       zconf_mount_clients $(comma_list $(all_mdts_nodes)) $MOUNT ||
-               error "failed to mount Lustre clients on MDS nodes"
-       stack_trap "zconf_umount_clients $(comma_list $(all_mdts_nodes)) \
-                  $MOUNT"
-
        local saved_LIPE_FIND_USE_MOUNT=$LIPE_FIND_USE_MOUNT
        LIPE_FIND_USE_MOUNT=true
        stack_trap "LIPE_FIND_USE_MOUNT=$saved_LIPE_FIND_USE_MOUNT"
@@ -1347,20 +1342,6 @@ do_lipe_scan2_facet() {
        do_facet "$facet" lipe_scan2 "$device" "$@"
 }
 
-lipe_scan2_mount_client() {
-       local nodes
-
-       # All MDT nodes except the current node.
-       nodes=$(all_mdts_nodes | grep --fixed-strings --line-regexp --invert-match "$HOSTNAME")
-       if [[ -z "$nodes" ]]; then
-               return
-       fi
-
-       zconf_mount_clients "$(comma_list $nodes)" "$MOUNT" ||
-               error "failed to mount Lustre clients on MDS nodes"
-       stack_trap "zconf_umount_clients $(comma_list $nodes) $MOUNT"
-}
-
 test_200() {
        local file=$DIR/$tdir/$tfile
        local fid
@@ -1417,8 +1398,6 @@ test_201() {
        sync
        cancel_lru_locks mdc
 
-       lipe_scan2_mount_client
-
        attrs=$(do_lipe_scan2_facet mds1 --client-mount="$MOUNT" --print-json=fid,paths |
                jq --arg FID "$fid" 'select(.fid == $FID)')
        echo "attrs = '$attrs'" >&2