summaryrefslogtreecommitdiffstats
path: root/src/ceph/qa/standalone
diff options
context:
space:
mode:
Diffstat (limited to 'src/ceph/qa/standalone')
-rw-r--r--src/ceph/qa/standalone/README23
-rwxr-xr-xsrc/ceph/qa/standalone/ceph-helpers.sh1993
-rwxr-xr-xsrc/ceph/qa/standalone/crush/crush-choose-args.sh161
-rwxr-xr-xsrc/ceph/qa/standalone/crush/crush-classes.sh223
-rwxr-xr-xsrc/ceph/qa/standalone/erasure-code/test-erasure-code-plugins.sh117
-rwxr-xr-xsrc/ceph/qa/standalone/erasure-code/test-erasure-code.sh339
-rwxr-xr-xsrc/ceph/qa/standalone/erasure-code/test-erasure-eio.sh323
-rwxr-xr-xsrc/ceph/qa/standalone/misc/rados-striper.sh101
-rwxr-xr-xsrc/ceph/qa/standalone/misc/test-ceph-helpers.sh21
-rwxr-xr-xsrc/ceph/qa/standalone/mon/misc.sh238
-rwxr-xr-xsrc/ceph/qa/standalone/mon/mkfs.sh198
-rwxr-xr-xsrc/ceph/qa/standalone/mon/mon-bind.sh147
-rwxr-xr-xsrc/ceph/qa/standalone/mon/mon-created-time.sh54
-rwxr-xr-xsrc/ceph/qa/standalone/mon/mon-handle-forward.sh64
-rwxr-xr-xsrc/ceph/qa/standalone/mon/mon-ping.sh46
-rwxr-xr-xsrc/ceph/qa/standalone/mon/mon-scrub.sh49
-rwxr-xr-xsrc/ceph/qa/standalone/mon/osd-crush.sh229
-rwxr-xr-xsrc/ceph/qa/standalone/mon/osd-erasure-code-profile.sh229
-rwxr-xr-xsrc/ceph/qa/standalone/mon/osd-pool-create.sh215
-rwxr-xr-xsrc/ceph/qa/standalone/mon/osd-pool-df.sh75
-rwxr-xr-xsrc/ceph/qa/standalone/mon/test_pool_quota.sh63
-rwxr-xr-xsrc/ceph/qa/standalone/osd/osd-bench.sh96
-rwxr-xr-xsrc/ceph/qa/standalone/osd/osd-config.sh118
-rwxr-xr-xsrc/ceph/qa/standalone/osd/osd-copy-from.sh68
-rwxr-xr-xsrc/ceph/qa/standalone/osd/osd-dup.sh83
-rwxr-xr-xsrc/ceph/qa/standalone/osd/osd-fast-mark-down.sh116
-rwxr-xr-xsrc/ceph/qa/standalone/osd/osd-markdown.sh122
-rwxr-xr-xsrc/ceph/qa/standalone/osd/osd-reactivate.sh56
-rwxr-xr-xsrc/ceph/qa/standalone/osd/osd-reuse-id.sh52
-rwxr-xr-xsrc/ceph/qa/standalone/scrub/osd-recovery-scrub.sh129
-rwxr-xr-xsrc/ceph/qa/standalone/scrub/osd-scrub-repair.sh2826
-rwxr-xr-xsrc/ceph/qa/standalone/scrub/osd-scrub-snaps.sh481
-rwxr-xr-xsrc/ceph/qa/standalone/special/ceph_objectstore_tool.py2024
-rwxr-xr-xsrc/ceph/qa/standalone/special/test-failure.sh48
34 files changed, 0 insertions, 11127 deletions
diff --git a/src/ceph/qa/standalone/README b/src/ceph/qa/standalone/README
deleted file mode 100644
index 3082442..0000000
--- a/src/ceph/qa/standalone/README
+++ /dev/null
@@ -1,23 +0,0 @@
-qa/standalone
-=============
-
-These scripts run standalone clusters, but not in a normal way. They make
-use of functions ceph-helpers.sh to quickly start/stop daemons against
-toy clusters in a single directory.
-
-They are normally run via teuthology based on qa/suites/rados/standalone/*.yaml.
-
-You can run them in a git checkout + build directory as well:
-
- * The qa/run-standalone.sh will run all of them in sequence. This is slow
- since there is no parallelism.
-
- * You can run individual script(s) by specifying the basename or path below
- qa/standalone as arguments to qa/run-standalone.sh.
-
-../qa/run-standalone.sh misc.sh osd/osd-dup.sh
-
- * Add support for specifying arguments to selected tests by simply adding
- list of tests to each argument.
-
-../qa/run-standalone.sh "test-ceph-helpers.sh test_get_last_scrub_stamp"
diff --git a/src/ceph/qa/standalone/ceph-helpers.sh b/src/ceph/qa/standalone/ceph-helpers.sh
deleted file mode 100755
index 2581930..0000000
--- a/src/ceph/qa/standalone/ceph-helpers.sh
+++ /dev/null
@@ -1,1993 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2013,2014 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014,2015 Red Hat <contact@redhat.com>
-# Copyright (C) 2014 Federico Gimenez <fgimenez@coit.es>
-#
-# Author: Loic Dachary <loic@dachary.org>
-# Author: Federico Gimenez <fgimenez@coit.es>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-TIMEOUT=300
-PG_NUM=4
-: ${CEPH_BUILD_VIRTUALENV:=/tmp}
-
-if type xmlstarlet > /dev/null 2>&1; then
- XMLSTARLET=xmlstarlet
-elif type xml > /dev/null 2>&1; then
- XMLSTARLET=xml
-else
- echo "Missing xmlstarlet binary!"
- exit 1
-fi
-
-if [ `uname` = FreeBSD ]; then
- SED=gsed
- DIFFCOLOPTS=""
- KERNCORE="kern.corefile"
-else
- SED=sed
- termwidth=$(stty -a | head -1 | sed -e 's/.*columns \([0-9]*\).*/\1/')
- if [ -n "$termwidth" -a "$termwidth" != "0" ]; then
- termwidth="-W ${termwidth}"
- fi
- DIFFCOLOPTS="-y $termwidth"
- KERNCORE="kernel.core_pattern"
-fi
-
-EXTRA_OPTS=""
-if [ -n "$CEPH_LIB" ]; then
- EXTRA_OPTS+=" --erasure-code-dir $CEPH_LIB"
- EXTRA_OPTS+=" --plugin-dir $CEPH_LIB"
- EXTRA_OPTS+=" --osd-class-dir $CEPH_LIB"
-fi
-
-#! @file ceph-helpers.sh
-# @brief Toolbox to manage Ceph cluster dedicated to testing
-#
-# Example use case:
-#
-# ~~~~~~~~~~~~~~~~{.sh}
-# source ceph-helpers.sh
-#
-# function mytest() {
-# # cleanup leftovers and reset mydir
-# setup mydir
-# # create a cluster with one monitor and three osds
-# run_mon mydir a
-# run_osd mydir 0
-# run_osd mydir 2
-# run_osd mydir 3
-# # put and get an object
-# rados --pool rbd put GROUP /etc/group
-# rados --pool rbd get GROUP /tmp/GROUP
-# # stop the cluster and cleanup the directory
-# teardown mydir
-# }
-# ~~~~~~~~~~~~~~~~
-#
-# The focus is on simplicity and efficiency, in the context of
-# functional tests. The output is intentionally very verbose
-# and functions return as soon as an error is found. The caller
-# is also expected to abort on the first error so that debugging
-# can be done by looking at the end of the output.
-#
-# Each function is documented, implemented and tested independently.
-# When modifying a helper, the test and the documentation are
-# expected to be updated and it is easier of they are collocated. A
-# test for a given function can be run with
-#
-# ~~~~~~~~~~~~~~~~{.sh}
-# ceph-helpers.sh TESTS test_get_osds
-# ~~~~~~~~~~~~~~~~
-#
-# and all the tests (i.e. all functions matching test_*) are run
-# with:
-#
-# ~~~~~~~~~~~~~~~~{.sh}
-# ceph-helpers.sh TESTS
-# ~~~~~~~~~~~~~~~~
-#
-# A test function takes a single argument : the directory dedicated
-# to the tests. It is expected to not create any file outside of this
-# directory and remove it entirely when it completes successfully.
-#
-
-
-function get_asok_dir() {
- if [ -n "$CEPH_ASOK_DIR" ]; then
- echo "$CEPH_ASOK_DIR"
- else
- echo ${TMPDIR:-/tmp}/ceph-asok.$$
- fi
-}
-
-function get_asok_path() {
- local name=$1
- if [ -n "$name" ]; then
- echo $(get_asok_dir)/ceph-$name.asok
- else
- echo $(get_asok_dir)/\$cluster-\$name.asok
- fi
-}
-##
-# Cleanup any leftovers found in **dir** via **teardown**
-# and reset **dir** as an empty environment.
-#
-# @param dir path name of the environment
-# @return 0 on success, 1 on error
-#
-function setup() {
- local dir=$1
- teardown $dir || return 1
- mkdir -p $dir
- mkdir -p $(get_asok_dir)
-}
-
-function test_setup() {
- local dir=$dir
- setup $dir || return 1
- test -d $dir || return 1
- setup $dir || return 1
- test -d $dir || return 1
- teardown $dir
-}
-
-#######################################################################
-
-##
-# Kill all daemons for which a .pid file exists in **dir** and remove
-# **dir**. If the file system in which **dir** is btrfs, delete all
-# subvolumes that relate to it.
-#
-# @param dir path name of the environment
-# @return 0 on success, 1 on error
-#
-function teardown() {
- local dir=$1
- local dumplogs=$2
- kill_daemons $dir KILL
- if [ `uname` != FreeBSD ] \
- && [ $(stat -f -c '%T' .) == "btrfs" ]; then
- __teardown_btrfs $dir
- fi
- local cores="no"
- local pattern="$(sysctl -n $KERNCORE)"
- # See if we have apport core handling
- if [ "${pattern:0:1}" = "|" ]; then
- # TODO: Where can we get the dumps?
- # Not sure where the dumps really are so this will look in the CWD
- pattern=""
- fi
- # Local we start with core and teuthology ends with core
- if ls $(dirname $pattern) | grep -q '^core\|core$' ; then
- cores="yes"
- if [ -n "$LOCALRUN" ]; then
- mkdir /tmp/cores.$$ 2> /dev/null || true
- for i in $(ls $(dirname $(sysctl -n $KERNCORE)) | grep '^core\|core$'); do
- mv $i /tmp/cores.$$
- done
- fi
- fi
- if [ "$cores" = "yes" -o "$dumplogs" = "1" ]; then
- display_logs $dir
- fi
- rm -fr $dir
- rm -rf $(get_asok_dir)
- if [ "$cores" = "yes" ]; then
- echo "ERROR: Failure due to cores found"
- if [ -n "$LOCALRUN" ]; then
- echo "Find saved core files in /tmp/cores.$$"
- fi
- return 1
- fi
- return 0
-}
-
-function __teardown_btrfs() {
- local btrfs_base_dir=$1
- local btrfs_root=$(df -P . | tail -1 | awk '{print $NF}')
- local btrfs_dirs=$(cd $btrfs_base_dir; sudo btrfs subvolume list . -t | awk '/^[0-9]/ {print $4}' | grep "$btrfs_base_dir/$btrfs_dir")
- for subvolume in $btrfs_dirs; do
- sudo btrfs subvolume delete $btrfs_root/$subvolume
- done
-}
-
-function test_teardown() {
- local dir=$dir
- setup $dir || return 1
- teardown $dir || return 1
- ! test -d $dir || return 1
-}
-
-#######################################################################
-
-##
-# Sends a signal to a single daemon.
-# This is a helper function for kill_daemons
-#
-# After the daemon is sent **signal**, its actual termination
-# will be verified by sending it signal 0. If the daemon is
-# still alive, kill_daemon will pause for a few seconds and
-# try again. This will repeat for a fixed number of times
-# before kill_daemon returns on failure. The list of
-# sleep intervals can be specified as **delays** and defaults
-# to:
-#
-# 0.1 0.2 1 1 1 2 3 5 5 5 10 10 20 60 60 60 120
-#
-# This sequence is designed to run first a very short sleep time (0.1)
-# if the machine is fast enough and the daemon terminates in a fraction of a
-# second. The increasing sleep numbers should give plenty of time for
-# the daemon to die even on the slowest running machine. If a daemon
-# takes more than a few minutes to stop (the sum of all sleep times),
-# there probably is no point in waiting more and a number of things
-# are likely to go wrong anyway: better give up and return on error.
-#
-# @param pid the process id to send a signal
-# @param send_signal the signal to send
-# @param delays sequence of sleep times before failure
-#
-function kill_daemon() {
- local pid=$(cat $1)
- local send_signal=$2
- local delays=${3:-0.1 0.2 1 1 1 2 3 5 5 5 10 10 20 60 60 60 120}
- local exit_code=1
- for try in $delays ; do
- if kill -$send_signal $pid 2> /dev/null ; then
- exit_code=1
- else
- exit_code=0
- break
- fi
- send_signal=0
- sleep $try
- done;
- return $exit_code
-}
-
-function test_kill_daemon() {
- local dir=$1
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
-
- name_prefix=osd
- for pidfile in $(find $dir 2>/dev/null | grep $name_prefix'[^/]*\.pid') ; do
- #
- # sending signal 0 won't kill the daemon
- # waiting just for one second instead of the default schedule
- # allows us to quickly verify what happens when kill fails
- # to stop the daemon (i.e. it must return false)
- #
- ! kill_daemon $pidfile 0 1 || return 1
- #
- # killing just the osd and verify the mon still is responsive
- #
- kill_daemon $pidfile TERM || return 1
- done
-
- ceph osd dump | grep "osd.0 down" || return 1
-
- name_prefix=mgr
- for pidfile in $(find $dir 2>/dev/null | grep $name_prefix'[^/]*\.pid') ; do
- #
- # kill the mgr
- #
- kill_daemon $pidfile TERM || return 1
- done
-
- name_prefix=mon
- for pidfile in $(find $dir 2>/dev/null | grep $name_prefix'[^/]*\.pid') ; do
- #
- # kill the mon and verify it cannot be reached
- #
- kill_daemon $pidfile TERM || return 1
- ! timeout 5 ceph status || return 1
- done
-
- teardown $dir || return 1
-}
-
-##
-# Kill all daemons for which a .pid file exists in **dir**. Each
-# daemon is sent a **signal** and kill_daemons waits for it to exit
-# during a few minutes. By default all daemons are killed. If a
-# **name_prefix** is provided, only the daemons for which a pid
-# file is found matching the prefix are killed. See run_osd and
-# run_mon for more information about the name conventions for
-# the pid files.
-#
-# Send TERM to all daemons : kill_daemons $dir
-# Send KILL to all daemons : kill_daemons $dir KILL
-# Send KILL to all osds : kill_daemons $dir KILL osd
-# Send KILL to osd 1 : kill_daemons $dir KILL osd.1
-#
-# If a daemon is sent the TERM signal and does not terminate
-# within a few minutes, it will still be running even after
-# kill_daemons returns.
-#
-# If all daemons are kill successfully the function returns 0
-# if at least one daemon remains, this is treated as an
-# error and the function return 1.
-#
-# @param dir path name of the environment
-# @param signal name of the first signal (defaults to TERM)
-# @param name_prefix only kill match daemons (defaults to all)
-# @param delays sequence of sleep times before failure
-# @return 0 on success, 1 on error
-#
-function kill_daemons() {
- local trace=$(shopt -q -o xtrace && echo true || echo false)
- $trace && shopt -u -o xtrace
- local dir=$1
- local signal=${2:-TERM}
- local name_prefix=$3 # optional, osd, mon, osd.1
- local delays=$4 #optional timing
- local status=0
- local pids=""
-
- for pidfile in $(find $dir 2>/dev/null | grep $name_prefix'[^/]*\.pid') ; do
- run_in_background pids kill_daemon $pidfile $signal $delays
- done
-
- wait_background pids
- status=$?
-
- $trace && shopt -s -o xtrace
- return $status
-}
-
-function test_kill_daemons() {
- local dir=$1
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- #
- # sending signal 0 won't kill the daemon
- # waiting just for one second instead of the default schedule
- # allows us to quickly verify what happens when kill fails
- # to stop the daemon (i.e. it must return false)
- #
- ! kill_daemons $dir 0 osd 1 || return 1
- #
- # killing just the osd and verify the mon still is responsive
- #
- kill_daemons $dir TERM osd || return 1
- ceph osd dump | grep "osd.0 down" || return 1
- #
- # kill the mgr
- #
- kill_daemons $dir TERM mgr || return 1
- #
- # kill the mon and verify it cannot be reached
- #
- kill_daemons $dir TERM || return 1
- ! timeout 5 ceph status || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Run a monitor by the name mon.**id** with data in **dir**/**id**.
-# The logs can be found in **dir**/mon.**id**.log and the pid file
-# is **dir**/mon.**id**.pid and the admin socket is
-# **dir**/**id**/ceph-mon.**id**.asok.
-#
-# The remaining arguments are passed verbatim to ceph-mon --mkfs
-# and the ceph-mon daemon.
-#
-# Two mandatory arguments must be provided: --fsid and --mon-host
-# Instead of adding them to every call to run_mon, they can be
-# set in the CEPH_ARGS environment variable to be read implicitly
-# by every ceph command.
-#
-# The CEPH_CONF variable is expected to be set to /dev/null to
-# only rely on arguments for configuration.
-#
-# Examples:
-#
-# CEPH_ARGS="--fsid=$(uuidgen) "
-# CEPH_ARGS+="--mon-host=127.0.0.1:7018 "
-# run_mon $dir a # spawn a mon and bind port 7018
-# run_mon $dir a --debug-filestore=20 # spawn with filestore debugging
-#
-# If mon_initial_members is not set, the default rbd pool is deleted
-# and replaced with a replicated pool with less placement groups to
-# speed up initialization. If mon_initial_members is set, no attempt
-# is made to recreate the rbd pool because it would hang forever,
-# waiting for other mons to join.
-#
-# A **dir**/ceph.conf file is created but not meant to be used by any
-# function. It is convenient for debugging a failure with:
-#
-# ceph --conf **dir**/ceph.conf -s
-#
-# @param dir path name of the environment
-# @param id mon identifier
-# @param ... can be any option valid for ceph-mon
-# @return 0 on success, 1 on error
-#
-function run_mon() {
- local dir=$1
- shift
- local id=$1
- shift
- local data=$dir/$id
-
- ceph-mon \
- --id $id \
- --mkfs \
- --mon-data=$data \
- --run-dir=$dir \
- "$@" || return 1
-
- ceph-mon \
- --id $id \
- --mon-osd-full-ratio=.99 \
- --mon-data-avail-crit=1 \
- --mon-data-avail-warn=5 \
- --paxos-propose-interval=0.1 \
- --osd-crush-chooseleaf-type=0 \
- $EXTRA_OPTS \
- --debug-mon 20 \
- --debug-ms 20 \
- --debug-paxos 20 \
- --chdir= \
- --mon-data=$data \
- --log-file=$dir/\$name.log \
- --admin-socket=$(get_asok_path) \
- --mon-cluster-log-file=$dir/log \
- --run-dir=$dir \
- --pid-file=$dir/\$name.pid \
- --mon-allow-pool-delete \
- --mon-osd-backfillfull-ratio .99 \
- "$@" || return 1
-
- cat > $dir/ceph.conf <<EOF
-[global]
-fsid = $(get_config mon $id fsid)
-mon host = $(get_config mon $id mon_host)
-EOF
-}
-
-function test_run_mon() {
- local dir=$1
-
- setup $dir || return 1
-
- run_mon $dir a --mon-initial-members=a || return 1
- create_rbd_pool || return 1
- # rbd has not been deleted / created, hence it has pool id 0
- ceph osd dump | grep "pool 1 'rbd'" || return 1
- kill_daemons $dir || return 1
-
- run_mon $dir a || return 1
- create_rbd_pool || return 1
- # rbd has been deleted / created, hence it does not have pool id 0
- ! ceph osd dump | grep "pool 1 'rbd'" || return 1
- local size=$(CEPH_ARGS='' ceph --format=json daemon $(get_asok_path mon.a) \
- config get osd_pool_default_size)
- test "$size" = '{"osd_pool_default_size":"3"}' || return 1
-
- ! CEPH_ARGS='' ceph status || return 1
- CEPH_ARGS='' ceph --conf $dir/ceph.conf status || return 1
-
- kill_daemons $dir || return 1
-
- run_mon $dir a --osd_pool_default_size=1 || return 1
- local size=$(CEPH_ARGS='' ceph --format=json daemon $(get_asok_path mon.a) \
- config get osd_pool_default_size)
- test "$size" = '{"osd_pool_default_size":"1"}' || return 1
- kill_daemons $dir || return 1
-
- CEPH_ARGS="$CEPH_ARGS --osd_pool_default_size=2" \
- run_mon $dir a || return 1
- local size=$(CEPH_ARGS='' ceph --format=json daemon $(get_asok_path mon.a) \
- config get osd_pool_default_size)
- test "$size" = '{"osd_pool_default_size":"2"}' || return 1
- kill_daemons $dir || return 1
-
- teardown $dir || return 1
-}
-
-function create_rbd_pool() {
- ceph osd pool delete rbd rbd --yes-i-really-really-mean-it || return 1
- create_pool rbd $PG_NUM || return 1
- rbd pool init rbd
-}
-
-function create_pool() {
- ceph osd pool create "$@"
- sleep 1
-}
-
-#######################################################################
-
-function run_mgr() {
- local dir=$1
- shift
- local id=$1
- shift
- local data=$dir/$id
-
- ceph-mgr \
- --id $id \
- $EXTRA_OPTS \
- --debug-mgr 20 \
- --debug-objecter 20 \
- --debug-ms 20 \
- --debug-paxos 20 \
- --chdir= \
- --mgr-data=$data \
- --log-file=$dir/\$name.log \
- --admin-socket=$(get_asok_path) \
- --run-dir=$dir \
- --pid-file=$dir/\$name.pid \
- "$@" || return 1
-}
-
-#######################################################################
-
-##
-# Create (prepare) and run (activate) an osd by the name osd.**id**
-# with data in **dir**/**id**. The logs can be found in
-# **dir**/osd.**id**.log, the pid file is **dir**/osd.**id**.pid and
-# the admin socket is **dir**/**id**/ceph-osd.**id**.asok.
-#
-# The remaining arguments are passed verbatim to ceph-osd.
-#
-# Two mandatory arguments must be provided: --fsid and --mon-host
-# Instead of adding them to every call to run_osd, they can be
-# set in the CEPH_ARGS environment variable to be read implicitly
-# by every ceph command.
-#
-# The CEPH_CONF variable is expected to be set to /dev/null to
-# only rely on arguments for configuration.
-#
-# The run_osd function creates the OSD data directory with ceph-disk
-# prepare on the **dir**/**id** directory and relies on the
-# activate_osd function to run the daemon.
-#
-# Examples:
-#
-# CEPH_ARGS="--fsid=$(uuidgen) "
-# CEPH_ARGS+="--mon-host=127.0.0.1:7018 "
-# run_osd $dir 0 # prepare and activate an osd using the monitor listening on 7018
-#
-# @param dir path name of the environment
-# @param id osd identifier
-# @param ... can be any option valid for ceph-osd
-# @return 0 on success, 1 on error
-#
-function run_osd() {
- local dir=$1
- shift
- local id=$1
- shift
- local osd_data=$dir/$id
-
- local ceph_disk_args
- ceph_disk_args+=" --statedir=$dir"
- ceph_disk_args+=" --sysconfdir=$dir"
- ceph_disk_args+=" --prepend-to-path="
-
- mkdir -p $osd_data
- ceph-disk $ceph_disk_args \
- prepare --filestore $osd_data || return 1
-
- activate_osd $dir $id "$@"
-}
-
-function run_osd_bluestore() {
- local dir=$1
- shift
- local id=$1
- shift
- local osd_data=$dir/$id
-
- local ceph_disk_args
- ceph_disk_args+=" --statedir=$dir"
- ceph_disk_args+=" --sysconfdir=$dir"
- ceph_disk_args+=" --prepend-to-path="
-
- mkdir -p $osd_data
- ceph-disk $ceph_disk_args \
- prepare --bluestore $osd_data || return 1
-
- activate_osd $dir $id "$@"
-}
-
-function test_run_osd() {
- local dir=$1
-
- setup $dir || return 1
-
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
-
- run_osd $dir 0 || return 1
- local backfills=$(CEPH_ARGS='' ceph --format=json daemon $(get_asok_path osd.0) \
- config get osd_max_backfills)
- echo "$backfills" | grep --quiet 'osd_max_backfills' || return 1
-
- run_osd $dir 1 --osd-max-backfills 20 || return 1
- local backfills=$(CEPH_ARGS='' ceph --format=json daemon $(get_asok_path osd.1) \
- config get osd_max_backfills)
- test "$backfills" = '{"osd_max_backfills":"20"}' || return 1
-
- CEPH_ARGS="$CEPH_ARGS --osd-max-backfills 30" run_osd $dir 2 || return 1
- local backfills=$(CEPH_ARGS='' ceph --format=json daemon $(get_asok_path osd.2) \
- config get osd_max_backfills)
- test "$backfills" = '{"osd_max_backfills":"30"}' || return 1
-
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Shutdown and remove all traces of the osd by the name osd.**id**.
-#
-# The OSD is shutdown with the TERM signal. It is then removed from
-# the auth list, crush map, osd map etc and the files associated with
-# it are also removed.
-#
-# @param dir path name of the environment
-# @param id osd identifier
-# @return 0 on success, 1 on error
-#
-function destroy_osd() {
- local dir=$1
- local id=$2
-
- ceph osd out osd.$id || return 1
- kill_daemons $dir TERM osd.$id || return 1
- ceph osd purge osd.$id --yes-i-really-mean-it || return 1
- teardown $dir/$id || return 1
- rm -fr $dir/$id
-}
-
-function test_destroy_osd() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- destroy_osd $dir 0 || return 1
- ! ceph osd dump | grep "osd.$id " || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Run (activate) an osd by the name osd.**id** with data in
-# **dir**/**id**. The logs can be found in **dir**/osd.**id**.log,
-# the pid file is **dir**/osd.**id**.pid and the admin socket is
-# **dir**/**id**/ceph-osd.**id**.asok.
-#
-# The remaining arguments are passed verbatim to ceph-osd.
-#
-# Two mandatory arguments must be provided: --fsid and --mon-host
-# Instead of adding them to every call to activate_osd, they can be
-# set in the CEPH_ARGS environment variable to be read implicitly
-# by every ceph command.
-#
-# The CEPH_CONF variable is expected to be set to /dev/null to
-# only rely on arguments for configuration.
-#
-# The activate_osd function expects a valid OSD data directory
-# in **dir**/**id**, either just created via run_osd or re-using
-# one left by a previous run of ceph-osd. The ceph-osd daemon is
-# run indirectly via ceph-disk activate.
-#
-# The activate_osd function blocks until the monitor reports the osd
-# up. If it fails to do so within $TIMEOUT seconds, activate_osd
-# fails.
-#
-# Examples:
-#
-# CEPH_ARGS="--fsid=$(uuidgen) "
-# CEPH_ARGS+="--mon-host=127.0.0.1:7018 "
-# activate_osd $dir 0 # activate an osd using the monitor listening on 7018
-#
-# @param dir path name of the environment
-# @param id osd identifier
-# @param ... can be any option valid for ceph-osd
-# @return 0 on success, 1 on error
-#
-function activate_osd() {
- local dir=$1
- shift
- local id=$1
- shift
- local osd_data=$dir/$id
-
- local ceph_disk_args
- ceph_disk_args+=" --statedir=$dir"
- ceph_disk_args+=" --sysconfdir=$dir"
- ceph_disk_args+=" --prepend-to-path="
-
- local ceph_args="$CEPH_ARGS"
- ceph_args+=" --osd-failsafe-full-ratio=.99"
- ceph_args+=" --osd-journal-size=100"
- ceph_args+=" --osd-scrub-load-threshold=2000"
- ceph_args+=" --osd-data=$osd_data"
- ceph_args+=" --chdir="
- ceph_args+=$EXTRA_OPTS
- ceph_args+=" --run-dir=$dir"
- ceph_args+=" --admin-socket=$(get_asok_path)"
- ceph_args+=" --debug-osd=20"
- ceph_args+=" --log-file=$dir/\$name.log"
- ceph_args+=" --pid-file=$dir/\$name.pid"
- ceph_args+=" --osd-max-object-name-len 460"
- ceph_args+=" --osd-max-object-namespace-len 64"
- ceph_args+=" --enable-experimental-unrecoverable-data-corrupting-features *"
- ceph_args+=" "
- ceph_args+="$@"
- mkdir -p $osd_data
- CEPH_ARGS="$ceph_args " ceph-disk $ceph_disk_args \
- activate \
- --mark-init=none \
- $osd_data || return 1
-
- [ "$id" = "$(cat $osd_data/whoami)" ] || return 1
-
- wait_for_osd up $id || return 1
-}
-
-function test_activate_osd() {
- local dir=$1
-
- setup $dir || return 1
-
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
-
- run_osd $dir 0 || return 1
- local backfills=$(CEPH_ARGS='' ceph --format=json daemon $(get_asok_path osd.0) \
- config get osd_max_backfills)
- echo "$backfills" | grep --quiet 'osd_max_backfills' || return 1
-
- kill_daemons $dir TERM osd || return 1
-
- activate_osd $dir 0 --osd-max-backfills 20 || return 1
- local backfills=$(CEPH_ARGS='' ceph --format=json daemon $(get_asok_path osd.0) \
- config get osd_max_backfills)
- test "$backfills" = '{"osd_max_backfills":"20"}' || return 1
-
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Wait until the OSD **id** is either up or down, as specified by
-# **state**. It fails after $TIMEOUT seconds.
-#
-# @param state either up or down
-# @param id osd identifier
-# @return 0 on success, 1 on error
-#
-function wait_for_osd() {
- local state=$1
- local id=$2
-
- status=1
- for ((i=0; i < $TIMEOUT; i++)); do
- echo $i
- if ! ceph osd dump | grep "osd.$id $state"; then
- sleep 1
- else
- status=0
- break
- fi
- done
- return $status
-}
-
-function test_wait_for_osd() {
- local dir=$1
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- wait_for_osd up 0 || return 1
- kill_daemons $dir TERM osd || return 1
- wait_for_osd down 0 || return 1
- ( TIMEOUT=1 ; ! wait_for_osd up 0 ) || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Display the list of OSD ids supporting the **objectname** stored in
-# **poolname**, as reported by ceph osd map.
-#
-# @param poolname an existing pool
-# @param objectname an objectname (may or may not exist)
-# @param STDOUT white space separated list of OSD ids
-# @return 0 on success, 1 on error
-#
-function get_osds() {
- local poolname=$1
- local objectname=$2
-
- local osds=$(ceph --format json osd map $poolname $objectname 2>/dev/null | \
- jq '.acting | .[]')
- # get rid of the trailing space
- echo $osds
-}
-
-function test_get_osds() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=2 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- create_rbd_pool || return 1
- get_osds rbd GROUP | grep --quiet '^[0-1] [0-1]$' || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Wait for the monitor to form quorum (optionally, of size N)
-#
-# @param timeout duration (lower-bound) to wait for quorum to be formed
-# @param quorumsize size of quorum to wait for
-# @return 0 on success, 1 on error
-#
-function wait_for_quorum() {
- local timeout=$1
- local quorumsize=$2
-
- if [[ -z "$timeout" ]]; then
- timeout=300
- fi
-
- if [[ -z "$quorumsize" ]]; then
- timeout $timeout ceph mon_status --format=json >&/dev/null || return 1
- return 0
- fi
-
- no_quorum=1
- wait_until=$((`date +%s` + $timeout))
- while [[ $(date +%s) -lt $wait_until ]]; do
- jqfilter='.quorum | length == '$quorumsize
- jqinput="$(timeout $timeout ceph mon_status --format=json 2>/dev/null)"
- res=$(echo $jqinput | jq "$jqfilter")
- if [[ "$res" == "true" ]]; then
- no_quorum=0
- break
- fi
- done
- return $no_quorum
-}
-
-#######################################################################
-
-##
-# Return the PG of supporting the **objectname** stored in
-# **poolname**, as reported by ceph osd map.
-#
-# @param poolname an existing pool
-# @param objectname an objectname (may or may not exist)
-# @param STDOUT a PG
-# @return 0 on success, 1 on error
-#
-function get_pg() {
- local poolname=$1
- local objectname=$2
-
- ceph --format json osd map $poolname $objectname 2>/dev/null | jq -r '.pgid'
-}
-
-function test_get_pg() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- get_pg rbd GROUP | grep --quiet '^[0-9]\.[0-9a-f][0-9a-f]*$' || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Return the value of the **config**, obtained via the config get command
-# of the admin socket of **daemon**.**id**.
-#
-# @param daemon mon or osd
-# @param id mon or osd ID
-# @param config the configuration variable name as found in config_opts.h
-# @param STDOUT the config value
-# @return 0 on success, 1 on error
-#
-function get_config() {
- local daemon=$1
- local id=$2
- local config=$3
-
- CEPH_ARGS='' \
- ceph --format json daemon $(get_asok_path $daemon.$id) \
- config get $config 2> /dev/null | \
- jq -r ".$config"
-}
-
-function test_get_config() {
- local dir=$1
-
- # override the default config using command line arg and check it
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- test $(get_config mon a osd_pool_default_size) = 1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 --osd_max_scrubs=3 || return 1
- test $(get_config osd 0 osd_max_scrubs) = 3 || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Set the **config** to specified **value**, via the config set command
-# of the admin socket of **daemon**.**id**
-#
-# @param daemon mon or osd
-# @param id mon or osd ID
-# @param config the configuration variable name as found in config_opts.h
-# @param value the config value
-# @return 0 on success, 1 on error
-#
-function set_config() {
- local daemon=$1
- local id=$2
- local config=$3
- local value=$4
-
- test $(env CEPH_ARGS='' ceph --format json daemon $(get_asok_path $daemon.$id) \
- config set $config $value 2> /dev/null | \
- jq 'has("success")') == true
-}
-
-function test_set_config() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- test $(get_config mon a ms_crc_header) = true || return 1
- set_config mon a ms_crc_header false || return 1
- test $(get_config mon a ms_crc_header) = false || return 1
- set_config mon a ms_crc_header true || return 1
- test $(get_config mon a ms_crc_header) = true || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Return the OSD id of the primary OSD supporting the **objectname**
-# stored in **poolname**, as reported by ceph osd map.
-#
-# @param poolname an existing pool
-# @param objectname an objectname (may or may not exist)
-# @param STDOUT the primary OSD id
-# @return 0 on success, 1 on error
-#
-function get_primary() {
- local poolname=$1
- local objectname=$2
-
- ceph --format json osd map $poolname $objectname 2>/dev/null | \
- jq '.acting_primary'
-}
-
-function test_get_primary() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- local osd=0
- run_mgr $dir x || return 1
- run_osd $dir $osd || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- test $(get_primary rbd GROUP) = $osd || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Return the id of any OSD supporting the **objectname** stored in
-# **poolname**, as reported by ceph osd map, except the primary.
-#
-# @param poolname an existing pool
-# @param objectname an objectname (may or may not exist)
-# @param STDOUT the OSD id
-# @return 0 on success, 1 on error
-#
-function get_not_primary() {
- local poolname=$1
- local objectname=$2
-
- local primary=$(get_primary $poolname $objectname)
- ceph --format json osd map $poolname $objectname 2>/dev/null | \
- jq ".acting | map(select (. != $primary)) | .[0]"
-}
-
-function test_get_not_primary() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=2 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- local primary=$(get_primary rbd GROUP)
- local not_primary=$(get_not_primary rbd GROUP)
- test $not_primary != $primary || return 1
- test $not_primary = 0 -o $not_primary = 1 || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Run ceph-objectstore-tool against the OSD **id** using the data path
-# **dir**. The OSD is killed with TERM prior to running
-# ceph-objectstore-tool because access to the data path is
-# exclusive. The OSD is restarted after the command completes. The
-# objectstore_tool returns after all PG are active+clean again.
-#
-# @param dir the data path of the OSD
-# @param id the OSD id
-# @param ... arguments to ceph-objectstore-tool
-# @param STDIN the input of ceph-objectstore-tool
-# @param STDOUT the output of ceph-objectstore-tool
-# @return 0 on success, 1 on error
-#
-# The value of $ceph_osd_args will be passed to restarted osds
-#
-function objectstore_tool() {
- local dir=$1
- shift
- local id=$1
- shift
- local osd_data=$dir/$id
-
- local osd_type=$(cat $osd_data/type)
-
- kill_daemons $dir TERM osd.$id >&2 < /dev/null || return 1
-
- local journal_args
- if [ "$objectstore_type" == "filestore" ]; then
- journal_args=" --journal-path $osd_data/journal"
- fi
- ceph-objectstore-tool \
- --data-path $osd_data \
- $journal_args \
- "$@" || return 1
- activate_osd $dir $id $ceph_osd_args >&2 || return 1
- wait_for_clean >&2
-}
-
-function test_objectstore_tool() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- local osd=0
- run_mgr $dir x || return 1
- run_osd $dir $osd || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- rados --pool rbd put GROUP /etc/group || return 1
- objectstore_tool $dir $osd GROUP get-bytes | \
- diff - /etc/group
- ! objectstore_tool $dir $osd NOTEXISTS get-bytes || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Predicate checking if there is an ongoing recovery in the
-# cluster. If any of the recovering_{keys,bytes,objects}_per_sec
-# counters are reported by ceph status, it means recovery is in
-# progress.
-#
-# @return 0 if recovery in progress, 1 otherwise
-#
-function get_is_making_recovery_progress() {
- local recovery_progress
- recovery_progress+=".recovering_keys_per_sec + "
- recovery_progress+=".recovering_bytes_per_sec + "
- recovery_progress+=".recovering_objects_per_sec"
- local progress=$(ceph --format json status 2>/dev/null | \
- jq -r ".pgmap | $recovery_progress")
- test "$progress" != null
-}
-
-function test_get_is_making_recovery_progress() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- ! get_is_making_recovery_progress || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Return the number of active PGs in the cluster. A PG is active if
-# ceph pg dump pgs reports it both **active** and **clean** and that
-# not **stale**.
-#
-# @param STDOUT the number of active PGs
-# @return 0 on success, 1 on error
-#
-function get_num_active_clean() {
- local expression
- expression+="select(contains(\"active\") and contains(\"clean\")) | "
- expression+="select(contains(\"stale\") | not)"
- ceph --format json pg dump pgs 2>/dev/null | \
- jq "[.[] | .state | $expression] | length"
-}
-
-function test_get_num_active_clean() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- local num_active_clean=$(get_num_active_clean)
- test "$num_active_clean" = $PG_NUM || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Return the number of PGs in the cluster, according to
-# ceph pg dump pgs.
-#
-# @param STDOUT the number of PGs
-# @return 0 on success, 1 on error
-#
-function get_num_pgs() {
- ceph --format json status 2>/dev/null | jq '.pgmap.num_pgs'
-}
-
-function test_get_num_pgs() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- local num_pgs=$(get_num_pgs)
- test "$num_pgs" -gt 0 || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Return the OSD ids in use by at least one PG in the cluster (either
-# in the up or the acting set), according to ceph pg dump pgs. Every
-# OSD id shows as many times as they are used in up and acting sets.
-# If an OSD id is in both the up and acting set of a given PG, it will
-# show twice.
-#
-# @param STDOUT a sorted list of OSD ids
-# @return 0 on success, 1 on error
-#
-function get_osd_id_used_by_pgs() {
- ceph --format json pg dump pgs 2>/dev/null | jq '.[] | .up[], .acting[]' | sort
-}
-
-function test_get_osd_id_used_by_pgs() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- local osd_ids=$(get_osd_id_used_by_pgs | uniq)
- test "$osd_ids" = "0" || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Wait until the OSD **id** shows **count** times in the
-# PGs (see get_osd_id_used_by_pgs for more information about
-# how OSD ids are counted).
-#
-# @param id the OSD id
-# @param count the number of time it must show in the PGs
-# @return 0 on success, 1 on error
-#
-function wait_osd_id_used_by_pgs() {
- local id=$1
- local count=$2
-
- status=1
- for ((i=0; i < $TIMEOUT / 5; i++)); do
- echo $i
- if ! test $(get_osd_id_used_by_pgs | grep -c $id) = $count ; then
- sleep 5
- else
- status=0
- break
- fi
- done
- return $status
-}
-
-function test_wait_osd_id_used_by_pgs() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- wait_osd_id_used_by_pgs 0 8 || return 1
- ! TIMEOUT=1 wait_osd_id_used_by_pgs 123 5 || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Return the date and time of the last completed scrub for **pgid**,
-# as reported by ceph pg dump pgs. Note that a repair also sets this
-# date.
-#
-# @param pgid the id of the PG
-# @param STDOUT the date and time of the last scrub
-# @return 0 on success, 1 on error
-#
-function get_last_scrub_stamp() {
- local pgid=$1
- local sname=${2:-last_scrub_stamp}
- ceph --format json pg dump pgs 2>/dev/null | \
- jq -r ".[] | select(.pgid==\"$pgid\") | .$sname"
-}
-
-function test_get_last_scrub_stamp() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- stamp=$(get_last_scrub_stamp 1.0)
- test -n "$stamp" || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Predicate checking if the cluster is clean, i.e. all of its PGs are
-# in a clean state (see get_num_active_clean for a definition).
-#
-# @return 0 if the cluster is clean, 1 otherwise
-#
-function is_clean() {
- num_pgs=$(get_num_pgs)
- test $num_pgs != 0 || return 1
- test $(get_num_active_clean) = $num_pgs || return 1
-}
-
-function test_is_clean() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- is_clean || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Return a list of numbers that are increasingly larger and whose
-# total is **timeout** seconds. It can be used to have short sleep
-# delay while waiting for an event on a fast machine. But if running
-# very slowly the larger delays avoid stressing the machine even
-# further or spamming the logs.
-#
-# @param timeout sum of all delays, in seconds
-# @return a list of sleep delays
-#
-function get_timeout_delays() {
- local trace=$(shopt -q -o xtrace && echo true || echo false)
- $trace && shopt -u -o xtrace
- local timeout=$1
- local first_step=${2:-1}
-
- local i
- local total="0"
- i=$first_step
- while test "$(echo $total + $i \<= $timeout | bc -l)" = "1"; do
- echo -n "$i "
- total=$(echo $total + $i | bc -l)
- i=$(echo $i \* 2 | bc -l)
- done
- if test "$(echo $total \< $timeout | bc -l)" = "1"; then
- echo -n $(echo $timeout - $total | bc -l)
- fi
- $trace && shopt -s -o xtrace
-}
-
-function test_get_timeout_delays() {
- test "$(get_timeout_delays 1)" = "1 " || return 1
- test "$(get_timeout_delays 5)" = "1 2 2" || return 1
- test "$(get_timeout_delays 6)" = "1 2 3" || return 1
- test "$(get_timeout_delays 7)" = "1 2 4 " || return 1
- test "$(get_timeout_delays 8)" = "1 2 4 1" || return 1
- test "$(get_timeout_delays 1 .1)" = ".1 .2 .4 .3" || return 1
- test "$(get_timeout_delays 1.5 .1)" = ".1 .2 .4 .8 " || return 1
- test "$(get_timeout_delays 5 .1)" = ".1 .2 .4 .8 1.6 1.9" || return 1
- test "$(get_timeout_delays 6 .1)" = ".1 .2 .4 .8 1.6 2.9" || return 1
- test "$(get_timeout_delays 6.3 .1)" = ".1 .2 .4 .8 1.6 3.2 " || return 1
- test "$(get_timeout_delays 20 .1)" = ".1 .2 .4 .8 1.6 3.2 6.4 7.3" || return 1
-}
-
-#######################################################################
-
-##
-# Wait until the cluster becomes clean or if it does not make progress
-# for $TIMEOUT seconds.
-# Progress is measured either via the **get_is_making_recovery_progress**
-# predicate or if the number of clean PGs changes (as returned by get_num_active_clean)
-#
-# @return 0 if the cluster is clean, 1 otherwise
-#
-function wait_for_clean() {
- local num_active_clean=-1
- local cur_active_clean
- local -a delays=($(get_timeout_delays $TIMEOUT .1))
- local -i loop=0
-
- while test $(get_num_pgs) == 0 ; do
- sleep 1
- done
-
- while true ; do
- # Comparing get_num_active_clean & get_num_pgs is used to determine
- # if the cluster is clean. That's almost an inline of is_clean() to
- # get more performance by avoiding multiple calls of get_num_active_clean.
- cur_active_clean=$(get_num_active_clean)
- test $cur_active_clean = $(get_num_pgs) && break
- if test $cur_active_clean != $num_active_clean ; then
- loop=0
- num_active_clean=$cur_active_clean
- elif get_is_making_recovery_progress ; then
- loop=0
- elif (( $loop >= ${#delays[*]} )) ; then
- ceph report
- return 1
- fi
- sleep ${delays[$loop]}
- loop+=1
- done
- return 0
-}
-
-function test_wait_for_clean() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- create_rbd_pool || return 1
- ! TIMEOUT=1 wait_for_clean || return 1
- run_osd $dir 0 || return 1
- wait_for_clean || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Wait until the cluster becomes HEALTH_OK again or if it does not make progress
-# for $TIMEOUT seconds.
-#
-# @return 0 if the cluster is HEALTHY, 1 otherwise
-#
-function wait_for_health() {
- local grepstr=$1
- local -a delays=($(get_timeout_delays $TIMEOUT .1))
- local -i loop=0
-
- while ! ceph health detail | grep "$grepstr" ; do
- if (( $loop >= ${#delays[*]} )) ; then
- ceph health detail
- return 1
- fi
- sleep ${delays[$loop]}
- loop+=1
- done
-}
-
-function wait_for_health_ok() {
- wait_for_health "HEALTH_OK" || return 1
-}
-
-function test_wait_for_health_ok() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 --osd_failsafe_full_ratio=.99 --mon_pg_warn_min_per_osd=0 || return 1
- run_mgr $dir x --mon_pg_warn_min_per_osd=0 || return 1
- run_osd $dir 0 || return 1
- kill_daemons $dir TERM osd || return 1
- ! TIMEOUT=1 wait_for_health_ok || return 1
- activate_osd $dir 0 || return 1
- wait_for_health_ok || return 1
- teardown $dir || return 1
-}
-
-
-#######################################################################
-
-##
-# Run repair on **pgid** and wait until it completes. The repair
-# function will fail if repair does not complete within $TIMEOUT
-# seconds.
-#
-# @param pgid the id of the PG
-# @return 0 on success, 1 on error
-#
-function repair() {
- local pgid=$1
- local last_scrub=$(get_last_scrub_stamp $pgid)
- ceph pg repair $pgid
- wait_for_scrub $pgid "$last_scrub"
-}
-
-function test_repair() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- repair 1.0 || return 1
- kill_daemons $dir KILL osd || return 1
- ! TIMEOUT=1 repair 1.0 || return 1
- teardown $dir || return 1
-}
-#######################################################################
-
-##
-# Run scrub on **pgid** and wait until it completes. The pg_scrub
-# function will fail if repair does not complete within $TIMEOUT
-# seconds. The pg_scrub is complete whenever the
-# **get_last_scrub_stamp** function reports a timestamp different from
-# the one stored before starting the scrub.
-#
-# @param pgid the id of the PG
-# @return 0 on success, 1 on error
-#
-function pg_scrub() {
- local pgid=$1
- local last_scrub=$(get_last_scrub_stamp $pgid)
- ceph pg scrub $pgid
- wait_for_scrub $pgid "$last_scrub"
-}
-
-function pg_deep_scrub() {
- local pgid=$1
- local last_scrub=$(get_last_scrub_stamp $pgid last_deep_scrub_stamp)
- ceph pg deep-scrub $pgid
- wait_for_scrub $pgid "$last_scrub" last_deep_scrub_stamp
-}
-
-function test_pg_scrub() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- pg_scrub 1.0 || return 1
- kill_daemons $dir KILL osd || return 1
- ! TIMEOUT=1 pg_scrub 1.0 || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Run the *command* and expect it to fail (i.e. return a non zero status).
-# The output (stderr and stdout) is stored in a temporary file in *dir*
-# and is expected to contain the string *expected*.
-#
-# Return 0 if the command failed and the string was found. Otherwise
-# return 1 and cat the full output of the command on stderr for debug.
-#
-# @param dir temporary directory to store the output
-# @param expected string to look for in the output
-# @param command ... the command and its arguments
-# @return 0 on success, 1 on error
-#
-
-function expect_failure() {
- local dir=$1
- shift
- local expected="$1"
- shift
- local success
-
- if "$@" > $dir/out 2>&1 ; then
- success=true
- else
- success=false
- fi
-
- if $success || ! grep --quiet "$expected" $dir/out ; then
- cat $dir/out >&2
- return 1
- else
- return 0
- fi
-}
-
-function test_expect_failure() {
- local dir=$1
-
- setup $dir || return 1
- expect_failure $dir FAIL bash -c 'echo FAIL ; exit 1' || return 1
- # the command did not fail
- ! expect_failure $dir FAIL bash -c 'echo FAIL ; exit 0' > $dir/out || return 1
- grep --quiet FAIL $dir/out || return 1
- # the command failed but the output does not contain the expected string
- ! expect_failure $dir FAIL bash -c 'echo UNEXPECTED ; exit 1' > $dir/out || return 1
- ! grep --quiet FAIL $dir/out || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Given the *last_scrub*, wait for scrub to happen on **pgid**. It
-# will fail if scrub does not complete within $TIMEOUT seconds. The
-# repair is complete whenever the **get_last_scrub_stamp** function
-# reports a timestamp different from the one given in argument.
-#
-# @param pgid the id of the PG
-# @param last_scrub timestamp of the last scrub for *pgid*
-# @return 0 on success, 1 on error
-#
-function wait_for_scrub() {
- local pgid=$1
- local last_scrub="$2"
- local sname=${3:-last_scrub_stamp}
-
- for ((i=0; i < $TIMEOUT; i++)); do
- if test "$(get_last_scrub_stamp $pgid $sname)" '>' "$last_scrub" ; then
- return 0
- fi
- sleep 1
- done
- return 1
-}
-
-function test_wait_for_scrub() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- local pgid=1.0
- ceph pg repair $pgid
- local last_scrub=$(get_last_scrub_stamp $pgid)
- wait_for_scrub $pgid "$last_scrub" || return 1
- kill_daemons $dir KILL osd || return 1
- last_scrub=$(get_last_scrub_stamp $pgid)
- ! TIMEOUT=1 wait_for_scrub $pgid "$last_scrub" || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Return 0 if the erasure code *plugin* is available, 1 otherwise.
-#
-# @param plugin erasure code plugin
-# @return 0 on success, 1 on error
-#
-
-function erasure_code_plugin_exists() {
- local plugin=$1
- local status
- local grepstr
- local s
- case `uname` in
- FreeBSD) grepstr="Cannot open.*$plugin" ;;
- *) grepstr="$plugin.*No such file" ;;
- esac
-
- s=$(ceph osd erasure-code-profile set TESTPROFILE plugin=$plugin 2>&1)
- local status=$?
- if [ $status -eq 0 ]; then
- ceph osd erasure-code-profile rm TESTPROFILE
- elif ! echo $s | grep --quiet "$grepstr" ; then
- status=1
- # display why the string was rejected.
- echo $s
- fi
- return $status
-}
-
-function test_erasure_code_plugin_exists() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- erasure_code_plugin_exists jerasure || return 1
- ! erasure_code_plugin_exists FAKE || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-
-##
-# Display all log files from **dir** on stdout.
-#
-# @param dir directory in which all data is stored
-#
-
-function display_logs() {
- local dir=$1
-
- find $dir -maxdepth 1 -name '*.log' | \
- while read file ; do
- echo "======================= $file"
- cat $file
- done
-}
-
-function test_display_logs() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a || return 1
- kill_daemons $dir || return 1
- display_logs $dir > $dir/log.out
- grep --quiet mon.a.log $dir/log.out || return 1
- teardown $dir || return 1
-}
-
-#######################################################################
-##
-# Spawn a command in background and save the pid in the variable name
-# passed in argument. To make the output reading easier, the output is
-# prepend with the process id.
-#
-# Example:
-# pids1=""
-# run_in_background pids1 bash -c 'sleep 1; exit 1'
-#
-# @param pid_variable the variable name (not value) where the pids will be stored
-# @param ... the command to execute
-# @return only the pid_variable output should be considered and used with **wait_background**
-#
-function run_in_background() {
- local pid_variable=$1
- shift;
- # Execute the command and prepend the output with its pid
- # We enforce to return the exit status of the command and not the awk one.
- ("$@" |& awk '{ a[i++] = $0 }END{for (i = 0; i in a; ++i) { print "'$$': " a[i]} }'; return ${PIPESTATUS[0]}) >&2 &
- eval "$pid_variable+=\" $!\""
-}
-
-function test_run_in_background() {
- local pids
- run_in_background pids sleep 1
- run_in_background pids sleep 1
- test $(echo $pids | wc -w) = 2 || return 1
- wait $pids || return 1
-}
-
-#######################################################################
-##
-# Wait for pids running in background to complete.
-# This function is usually used after a **run_in_background** call
-# Example:
-# pids1=""
-# run_in_background pids1 bash -c 'sleep 1; exit 1'
-# wait_background pids1
-#
-# @param pids The variable name that contains the active PIDS. Set as empty at then end of the function.
-# @return returns 1 if at least one process exits in error unless returns 0
-#
-function wait_background() {
- # We extract the PIDS from the variable name
- pids=${!1}
-
- return_code=0
- for pid in $pids; do
- if ! wait $pid; then
- # If one process failed then return 1
- return_code=1
- fi
- done
-
- # We empty the variable reporting that all process ended
- eval "$1=''"
-
- return $return_code
-}
-
-
-function test_wait_background() {
- local pids=""
- run_in_background pids bash -c "sleep 1; exit 1"
- run_in_background pids bash -c "sleep 2; exit 0"
- wait_background pids
- if [ $? -ne 1 ]; then return 1; fi
-
- run_in_background pids bash -c "sleep 1; exit 0"
- run_in_background pids bash -c "sleep 2; exit 0"
- wait_background pids
- if [ $? -ne 0 ]; then return 1; fi
-
- if [ ! -z "$pids" ]; then return 1; fi
-}
-
-function flush_pg_stats()
-{
- local timeout=${1:-$TIMEOUT}
-
- ids=`ceph osd ls`
- seqs=''
- for osd in $ids; do
- seq=`ceph tell osd.$osd flush_pg_stats`
- seqs="$seqs $osd-$seq"
- done
-
- for s in $seqs; do
- osd=`echo $s | cut -d - -f 1`
- seq=`echo $s | cut -d - -f 2`
- echo "waiting osd.$osd seq $seq"
- while test $(ceph osd last-stat-seq $osd) -lt $seq; do
- sleep 1
- if [ $((timeout--)) -eq 0 ]; then
- return 1
- fi
- done
- done
-}
-
-function test_flush_pg_stats()
-{
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
- rados -p rbd put obj /etc/group
- flush_pg_stats
- local jq_filter='.pools | .[] | select(.name == "rbd") | .stats'
- raw_bytes_used=`ceph df detail --format=json | jq "$jq_filter.raw_bytes_used"`
- bytes_used=`ceph df detail --format=json | jq "$jq_filter.bytes_used"`
- test $raw_bytes_used > 0 || return 1
- test $raw_bytes_used == $bytes_used || return 1
- teardown $dir
-}
-
-#######################################################################
-
-##
-# Call the **run** function (which must be defined by the caller) with
-# the **dir** argument followed by the caller argument list.
-#
-# If the **run** function returns on error, all logs found in **dir**
-# are displayed for diagnostic purposes.
-#
-# **teardown** function is called when the **run** function returns
-# (on success or on error), to cleanup leftovers. The CEPH_CONF is set
-# to /dev/null and CEPH_ARGS is unset so that the tests are protected from
-# external interferences.
-#
-# It is the responsibility of the **run** function to call the
-# **setup** function to prepare the test environment (create a temporary
-# directory etc.).
-#
-# The shell is required (via PS4) to display the function and line
-# number whenever a statement is executed to help debugging.
-#
-# @param dir directory in which all data is stored
-# @param ... arguments passed transparently to **run**
-# @return 0 on success, 1 on error
-#
-function main() {
- local dir=td/$1
- shift
-
- shopt -s -o xtrace
- PS4='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: '
-
- export PATH=${CEPH_BUILD_VIRTUALENV}/ceph-disk-virtualenv/bin:${CEPH_BUILD_VIRTUALENV}/ceph-detect-init-virtualenv/bin:.:$PATH # make sure program from sources are preferred
- #export PATH=$CEPH_ROOT/src/ceph-disk/virtualenv/bin:$CEPH_ROOT/src/ceph-detect-init/virtualenv/bin:.:$PATH # make sure program from sources are preferred
-
- export CEPH_CONF=/dev/null
- unset CEPH_ARGS
-
- local code
- if run $dir "$@" ; then
- code=0
- else
- code=1
- fi
- teardown $dir $code || return 1
- return $code
-}
-
-#######################################################################
-
-function run_tests() {
- shopt -s -o xtrace
- PS4='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: '
-
- export PATH=${CEPH_BUILD_VIRTUALENV}/ceph-disk-virtualenv/bin:${CEPH_BUILD_VIRTUALENV}/ceph-detect-init-virtualenv/bin:.:$PATH # make sure program from sources are preferred
- #export PATH=$CEPH_ROOT/src/ceph-disk/virtualenv/bin:$CEPH_ROOT/src/ceph-detect-init/virtualenv/bin:.:$PATH # make sure program from sources are preferred
-
- export CEPH_MON="127.0.0.1:7109" # git grep '\<7109\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+=" --fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
- export CEPH_CONF=/dev/null
-
- local funcs=${@:-$(set | sed -n -e 's/^\(test_[0-9a-z_]*\) .*/\1/p')}
- local dir=td/ceph-helpers
-
- for func in $funcs ; do
- if ! $func $dir; then
- teardown $dir 1
- return 1
- fi
- done
-}
-
-if test "$1" = TESTS ; then
- shift
- run_tests "$@"
- exit $?
-fi
-
-# NOTE:
-# jq only support --exit-status|-e from version 1.4 forwards, which makes
-# returning on error waaaay prettier and straightforward.
-# However, the current automated upstream build is running with v1.3,
-# which has no idea what -e is. Hence the convoluted error checking we
-# need. Sad.
-# The next time someone changes this code, please check if v1.4 is now
-# a thing, and, if so, please change these to use -e. Thanks.
-
-# jq '.all.supported | select([.[] == "foo"] | any)'
-function jq_success() {
- input="$1"
- filter="$2"
- expects="\"$3\""
-
- in_escaped=$(printf %s "$input" | sed "s/'/'\\\\''/g")
- filter_escaped=$(printf %s "$filter" | sed "s/'/'\\\\''/g")
-
- ret=$(echo "$in_escaped" | jq "$filter_escaped")
- if [[ "$ret" == "true" ]]; then
- return 0
- elif [[ -n "$expects" ]]; then
- if [[ "$ret" == "$expects" ]]; then
- return 0
- fi
- fi
- return 1
- input=$1
- filter=$2
- expects="$3"
-
- ret="$(echo $input | jq \"$filter\")"
- if [[ "$ret" == "true" ]]; then
- return 0
- elif [[ -n "$expects" && "$ret" == "$expects" ]]; then
- return 0
- fi
- return 1
-}
-
-function inject_eio() {
- local pooltype=$1
- shift
- local which=$1
- shift
- local poolname=$1
- shift
- local objname=$1
- shift
- local dir=$1
- shift
- local shard_id=$1
- shift
-
- local -a initial_osds=($(get_osds $poolname $objname))
- local osd_id=${initial_osds[$shard_id]}
- if [ "$pooltype" != "ec" ]; then
- shard_id=""
- fi
- set_config osd $osd_id filestore_debug_inject_read_err true || return 1
- local loop=0
- while ( CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.$osd_id) \
- inject${which}err $poolname $objname $shard_id | grep -q Invalid ); do
- loop=$(expr $loop + 1)
- if [ $loop = "10" ]; then
- return 1
- fi
- sleep 1
- done
-}
-
-# Local Variables:
-# compile-command: "cd ../../src ; make -j4 && ../qa/standalone/ceph-helpers.sh TESTS # test_get_config"
-# End:
diff --git a/src/ceph/qa/standalone/crush/crush-choose-args.sh b/src/ceph/qa/standalone/crush/crush-choose-args.sh
deleted file mode 100755
index 6e03a99..0000000
--- a/src/ceph/qa/standalone/crush/crush-choose-args.sh
+++ /dev/null
@@ -1,161 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2017 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7131" # git grep '\<7131\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
- CEPH_ARGS+="--crush-location=root=default,host=HOST "
- CEPH_ARGS+="--osd-crush-initial-weight=3 "
- #
- # Disable device auto class feature for now.
- # The device class is non-deterministic and will
- # crash the crushmap comparison below.
- #
- CEPH_ARGS+="--osd-class-update-on-start=false "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_choose_args_update() {
- #
- # adding a weighted OSD updates the weight up to the top
- #
- local dir=$1
-
- run_mon $dir a || return 1
- run_osd $dir 0 || return 1
-
- ceph osd set-require-min-compat-client luminous
- ceph osd getcrushmap > $dir/map || return 1
- crushtool -d $dir/map -o $dir/map.txt || return 1
- sed -i -e '/end crush map/d' $dir/map.txt
- cat >> $dir/map.txt <<EOF
-# choose_args
-choose_args 0 {
- {
- bucket_id -1
- weight_set [
- [ 3.000 ]
- [ 3.000 ]
- ]
- ids [ -10 ]
- }
- {
- bucket_id -2
- weight_set [
- [ 2.000 ]
- [ 2.000 ]
- ]
- ids [ -20 ]
- }
-}
-
-# end crush map
-EOF
- crushtool -c $dir/map.txt -o $dir/map-new || return 1
- ceph osd setcrushmap -i $dir/map-new || return 1
-
- run_osd $dir 1 || return 1
- ceph osd getcrushmap > $dir/map-one-more || return 1
- crushtool -d $dir/map-one-more -o $dir/map-one-more.txt || return 1
- cat $dir/map-one-more.txt
- diff -u $dir/map-one-more.txt $CEPH_ROOT/src/test/crush/crush-choose-args-expected-one-more-3.txt || return 1
-
- destroy_osd $dir 1 || return 1
- ceph osd getcrushmap > $dir/map-one-less || return 1
- crushtool -d $dir/map-one-less -o $dir/map-one-less.txt || return 1
- diff -u $dir/map-one-less.txt $dir/map.txt || return 1
-}
-
-function TEST_no_update_weight_set() {
- #
- # adding a zero weight OSD does not update the weight set at all
- #
- local dir=$1
-
- ORIG_CEPH_ARGS="$CEPH_ARGS"
- CEPH_ARGS+="--osd-crush-update-weight-set=false "
-
- run_mon $dir a || return 1
- run_osd $dir 0 || return 1
-
- ceph osd set-require-min-compat-client luminous
- ceph osd crush tree
- ceph osd getcrushmap > $dir/map || return 1
- crushtool -d $dir/map -o $dir/map.txt || return 1
- sed -i -e '/end crush map/d' $dir/map.txt
- cat >> $dir/map.txt <<EOF
-# choose_args
-choose_args 0 {
- {
- bucket_id -1
- weight_set [
- [ 2.000 ]
- [ 1.000 ]
- ]
- ids [ -10 ]
- }
- {
- bucket_id -2
- weight_set [
- [ 2.000 ]
- [ 1.000 ]
- ]
- ids [ -20 ]
- }
-}
-
-# end crush map
-EOF
- crushtool -c $dir/map.txt -o $dir/map-new || return 1
- ceph osd setcrushmap -i $dir/map-new || return 1
- ceph osd crush tree
-
-
- run_osd $dir 1 || return 1
- ceph osd crush tree
- ceph osd getcrushmap > $dir/map-one-more || return 1
- crushtool -d $dir/map-one-more -o $dir/map-one-more.txt || return 1
- cat $dir/map-one-more.txt
- diff -u $dir/map-one-more.txt $CEPH_ROOT/src/test/crush/crush-choose-args-expected-one-more-0.txt || return 1
-
- destroy_osd $dir 1 || return 1
- ceph osd crush tree
- ceph osd getcrushmap > $dir/map-one-less || return 1
- crushtool -d $dir/map-one-less -o $dir/map-one-less.txt || return 1
- diff -u $dir/map-one-less.txt $dir/map.txt || return 1
-
- CEPH_ARGS="$ORIG_CEPH_ARGS"
-}
-
-main crush-choose-args "$@"
-
-# Local Variables:
-# compile-command: "cd ../../../build ; ln -sf ../src/ceph-disk/ceph_disk/main.py bin/ceph-disk && make -j4 && ../src/test/crush/crush-choose-args.sh"
-# End:
diff --git a/src/ceph/qa/standalone/crush/crush-classes.sh b/src/ceph/qa/standalone/crush/crush-classes.sh
deleted file mode 100755
index bcaab3f..0000000
--- a/src/ceph/qa/standalone/crush/crush-classes.sh
+++ /dev/null
@@ -1,223 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2017 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7130" # git grep '\<7130\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
- #
- # Disable auto-class, so we can inject device class manually below
- #
- CEPH_ARGS+="--osd-class-update-on-start=false "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function add_something() {
- local dir=$1
- local obj=${2:-SOMETHING}
-
- local payload=ABCDEF
- echo $payload > $dir/ORIGINAL
- rados --pool rbd put $obj $dir/ORIGINAL || return 1
-}
-
-function get_osds_up() {
- local poolname=$1
- local objectname=$2
-
- local osds=$(ceph --format xml osd map $poolname $objectname 2>/dev/null | \
- $XMLSTARLET sel -t -m "//up/osd" -v . -o ' ')
- # get rid of the trailing space
- echo $osds
-}
-
-function TEST_classes() {
- local dir=$1
-
- run_mon $dir a || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- run_osd $dir 2 || return 1
- create_rbd_pool || return 1
-
- test "$(get_osds_up rbd SOMETHING)" == "1 2 0" || return 1
- add_something $dir SOMETHING || return 1
-
- #
- # osd.0 has class ssd and the rule is modified
- # to only take ssd devices.
- #
- ceph osd getcrushmap > $dir/map || return 1
- crushtool -d $dir/map -o $dir/map.txt || return 1
- ${SED} -i \
- -e '/device 0 osd.0/s/$/ class ssd/' \
- -e '/step take default/s/$/ class ssd/' \
- $dir/map.txt || return 1
- crushtool -c $dir/map.txt -o $dir/map-new || return 1
- ceph osd setcrushmap -i $dir/map-new || return 1
-
- #
- # There can only be one mapping since there only is
- # one device with ssd class.
- #
- ok=false
- for delay in 2 4 8 16 32 64 128 256 ; do
- if test "$(get_osds_up rbd SOMETHING_ELSE)" == "0" ; then
- ok=true
- break
- fi
- sleep $delay
- ceph osd dump # for debugging purposes
- ceph pg dump # for debugging purposes
- done
- $ok || return 1
- #
- # Writing keeps working because the pool is min_size 1 by
- # default.
- #
- add_something $dir SOMETHING_ELSE || return 1
-
- #
- # Sanity check that the rule indeed has ssd
- # generated bucket with a name including ~ssd.
- #
- ceph osd crush dump | grep -q '~ssd' || return 1
-}
-
-function TEST_set_device_class() {
- local dir=$1
-
- TEST_classes $dir || return 1
-
- ceph osd crush set-device-class ssd osd.0 || return 1
- ceph osd crush class ls-osd ssd | grep 0 || return 1
- ceph osd crush set-device-class ssd osd.1 || return 1
- ceph osd crush class ls-osd ssd | grep 1 || return 1
- ceph osd crush set-device-class ssd 0 1 || return 1 # should be idempotent
-
- ok=false
- for delay in 2 4 8 16 32 64 128 256 ; do
- if test "$(get_osds_up rbd SOMETHING_ELSE)" == "0 1" ; then
- ok=true
- break
- fi
- sleep $delay
- ceph osd crush dump
- ceph osd dump # for debugging purposes
- ceph pg dump # for debugging purposes
- done
- $ok || return 1
-}
-
-function TEST_mon_classes() {
- local dir=$1
-
- run_mon $dir a || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- run_osd $dir 2 || return 1
- create_rbd_pool || return 1
-
- test "$(get_osds_up rbd SOMETHING)" == "1 2 0" || return 1
- add_something $dir SOMETHING || return 1
-
- # test rm-device-class
- ceph osd crush set-device-class aaa osd.0 || return 1
- ceph osd tree | grep -q 'aaa' || return 1
- ceph osd crush dump | grep -q '~aaa' || return 1
- ceph osd crush tree --show-shadow | grep -q '~aaa' || return 1
- ceph osd crush set-device-class bbb osd.1 || return 1
- ceph osd tree | grep -q 'bbb' || return 1
- ceph osd crush dump | grep -q '~bbb' || return 1
- ceph osd crush tree --show-shadow | grep -q '~bbb' || return 1
- ceph osd crush set-device-class ccc osd.2 || return 1
- ceph osd tree | grep -q 'ccc' || return 1
- ceph osd crush dump | grep -q '~ccc' || return 1
- ceph osd crush tree --show-shadow | grep -q '~ccc' || return 1
- ceph osd crush rm-device-class 0 || return 1
- ceph osd tree | grep -q 'aaa' && return 1
- ceph osd crush class ls | grep -q 'aaa' && return 1 # class 'aaa' should gone
- ceph osd crush rm-device-class 1 || return 1
- ceph osd tree | grep -q 'bbb' && return 1
- ceph osd crush class ls | grep -q 'bbb' && return 1 # class 'bbb' should gone
- ceph osd crush rm-device-class 2 || return 1
- ceph osd tree | grep -q 'ccc' && return 1
- ceph osd crush class ls | grep -q 'ccc' && return 1 # class 'ccc' should gone
- ceph osd crush set-device-class asdf all || return 1
- ceph osd tree | grep -q 'asdf' || return 1
- ceph osd crush dump | grep -q '~asdf' || return 1
- ceph osd crush tree --show-shadow | grep -q '~asdf' || return 1
- ceph osd crush rule create-replicated asdf-rule default host asdf || return 1
- ceph osd crush rm-device-class all || return 1
- ceph osd tree | grep -q 'asdf' && return 1
- ceph osd crush class ls | grep -q 'asdf' || return 1 # still referenced by asdf-rule
-
- ceph osd crush set-device-class abc osd.2 || return 1
- ceph osd crush move osd.2 root=foo rack=foo-rack host=foo-host || return 1
- out=`ceph osd tree |awk '$1 == 2 && $2 == "abc" {print $0}'`
- if [ "$out" == "" ]; then
- return 1
- fi
-
- # verify 'crush move' too
- ceph osd crush dump | grep -q 'foo~abc' || return 1
- ceph osd crush tree --show-shadow | grep -q 'foo~abc' || return 1
- ceph osd crush dump | grep -q 'foo-rack~abc' || return 1
- ceph osd crush tree --show-shadow | grep -q 'foo-rack~abc' || return 1
- ceph osd crush dump | grep -q 'foo-host~abc' || return 1
- ceph osd crush tree --show-shadow | grep -q 'foo-host~abc' || return 1
- ceph osd crush rm-device-class osd.2 || return 1
- # restore class, so we can continue to test create-replicated
- ceph osd crush set-device-class abc osd.2 || return 1
-
- ceph osd crush rule create-replicated foo-rule foo host abc || return 1
-
- # test set-device-class implicitly change class
- ceph osd crush set-device-class hdd osd.0 || return 1
- expect_failure $dir EBUSY ceph osd crush set-device-class nvme osd.0 || return 1
-
- # test class rename
- ceph osd crush rm-device-class all || return 1
- ceph osd crush set-device-class class_1 all || return 1
- ceph osd crush class ls | grep 'class_1' || return 1
- ceph osd crush tree --show-shadow | grep 'class_1' || return 1
- ceph osd crush rule create-replicated class_1_rule default host class_1 || return 1
- ceph osd crush class rename class_1 class_2
- ceph osd crush class rename class_1 class_2 # idempotent
- ceph osd crush class ls | grep 'class_1' && return 1
- ceph osd crush tree --show-shadow | grep 'class_1' && return 1
- ceph osd crush class ls | grep 'class_2' || return 1
- ceph osd crush tree --show-shadow | grep 'class_2' || return 1
-}
-
-main crush-classes "$@"
-
-# Local Variables:
-# compile-command: "cd ../../../build ; ln -sf ../src/ceph-disk/ceph_disk/main.py bin/ceph-disk && make -j4 && ../src/test/crush/crush-classes.sh"
-# End:
diff --git a/src/ceph/qa/standalone/erasure-code/test-erasure-code-plugins.sh b/src/ceph/qa/standalone/erasure-code/test-erasure-code-plugins.sh
deleted file mode 100755
index 26aff64..0000000
--- a/src/ceph/qa/standalone/erasure-code/test-erasure-code-plugins.sh
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/bin/bash -x
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-arch=$(uname -m)
-
-case $arch in
- i[[3456]]86*|x86_64*|amd64*)
- legacy_jerasure_plugins=(jerasure_generic jerasure_sse3 jerasure_sse4)
- legacy_shec_plugins=(shec_generic shec_sse3 shec_sse4)
- plugins=(jerasure shec lrc isa)
- ;;
- aarch64*|arm*)
- legacy_jerasure_plugins=(jerasure_generic jerasure_neon)
- legacy_shec_plugins=(shec_generic shec_neon)
- plugins=(jerasure shec lrc)
- ;;
- *)
- echo "unsupported platform ${arch}."
- return 1
- ;;
-esac
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:17110" # git grep '\<17110\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- $func $dir || return 1
- done
-}
-
-function TEST_preload_warning() {
- local dir=$1
-
- for plugin in ${legacy_jerasure_plugins[*]} ${legacy_shec_plugins[*]}; do
- setup $dir || return 1
- run_mon $dir a --osd_erasure_code_plugins="${plugin}" || return 1
- run_mgr $dir x || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path mon.a) log flush || return 1
- run_osd $dir 0 --osd_erasure_code_plugins="${plugin}" || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log flush || return 1
- grep "WARNING: osd_erasure_code_plugins contains plugin ${plugin}" $dir/mon.a.log || return 1
- grep "WARNING: osd_erasure_code_plugins contains plugin ${plugin}" $dir/osd.0.log || return 1
- teardown $dir || return 1
- done
- return 0
-}
-
-function TEST_preload_no_warning() {
- local dir=$1
-
- for plugin in ${plugins[*]}; do
- setup $dir || return 1
- run_mon $dir a --osd_erasure_code_plugins="${plugin}" || return 1
- run_mgr $dir x || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path mon.a) log flush || return 1
- run_osd $dir 0 --osd_erasure_code_plugins="${plugin}" || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log flush || return 1
- ! grep "WARNING: osd_erasure_code_plugins contains plugin" $dir/mon.a.log || return 1
- ! grep "WARNING: osd_erasure_code_plugins contains plugin" $dir/osd.0.log || return 1
- teardown $dir || return 1
- done
-
- return 0
-}
-
-function TEST_preload_no_warning_default() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path mon.a) log flush || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log flush || return 1
- ! grep "WARNING: osd_erasure_code_plugins" $dir/mon.a.log || return 1
- ! grep "WARNING: osd_erasure_code_plugins" $dir/osd.0.log || return 1
- teardown $dir || return 1
-
- return 0
-}
-
-function TEST_ec_profile_warning() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- for id in $(seq 0 2) ; do
- run_osd $dir $id || return 1
- done
- create_rbd_pool || return 1
- wait_for_clean || return 1
-
- for plugin in ${legacy_jerasure_plugins[*]}; do
- ceph osd erasure-code-profile set prof-${plugin} crush-failure-domain=osd technique=reed_sol_van plugin=${plugin} || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path mon.a) log flush || return 1
- grep "WARNING: erasure coding profile prof-${plugin} uses plugin ${plugin}" $dir/mon.a.log || return 1
- done
-
- for plugin in ${legacy_shec_plugins[*]}; do
- ceph osd erasure-code-profile set prof-${plugin} crush-failure-domain=osd plugin=${plugin} || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path mon.a) log flush || return 1
- grep "WARNING: erasure coding profile prof-${plugin} uses plugin ${plugin}" $dir/mon.a.log || return 1
- done
-
- teardown $dir || return 1
-}
-
-main test-erasure-code-plugins "$@"
diff --git a/src/ceph/qa/standalone/erasure-code/test-erasure-code.sh b/src/ceph/qa/standalone/erasure-code/test-erasure-code.sh
deleted file mode 100755
index 6dd5833..0000000
--- a/src/ceph/qa/standalone/erasure-code/test-erasure-code.sh
+++ /dev/null
@@ -1,339 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7101" # git grep '\<7101\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON --mon-osd-prime-pg-temp=false"
-
- setup $dir || return 1
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- # check that erasure code plugins are preloaded
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path mon.a) log flush || return 1
- grep 'load: jerasure.*lrc' $dir/mon.a.log || return 1
- for id in $(seq 0 10) ; do
- run_osd $dir $id || return 1
- done
- create_rbd_pool || return 1
- wait_for_clean || return 1
- # check that erasure code plugins are preloaded
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log flush || return 1
- grep 'load: jerasure.*lrc' $dir/osd.0.log || return 1
- create_erasure_coded_pool ecpool || return 1
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- $func $dir || return 1
- done
-
- delete_pool ecpool || return 1
- teardown $dir || return 1
-}
-
-function create_erasure_coded_pool() {
- local poolname=$1
-
- ceph osd erasure-code-profile set myprofile \
- crush-failure-domain=osd || return 1
- create_pool $poolname 12 12 erasure myprofile \
- || return 1
- wait_for_clean || return 1
-}
-
-function delete_pool() {
- local poolname=$1
-
- ceph osd pool delete $poolname $poolname --yes-i-really-really-mean-it
-}
-
-function rados_put_get() {
- local dir=$1
- local poolname=$2
- local objname=${3:-SOMETHING}
-
-
- for marker in AAA BBB CCCC DDDD ; do
- printf "%*s" 1024 $marker
- done > $dir/ORIGINAL
-
- #
- # get and put an object, compare they are equal
- #
- rados --pool $poolname put $objname $dir/ORIGINAL || return 1
- rados --pool $poolname get $objname $dir/COPY || return 1
- diff $dir/ORIGINAL $dir/COPY || return 1
- rm $dir/COPY
-
- #
- # take out an OSD used to store the object and
- # check the object can still be retrieved, which implies
- # recovery
- #
- local -a initial_osds=($(get_osds $poolname $objname))
- local last=$((${#initial_osds[@]} - 1))
- ceph osd out ${initial_osds[$last]} || return 1
- ! get_osds $poolname $objname | grep '\<'${initial_osds[$last]}'\>' || return 1
- rados --pool $poolname get $objname $dir/COPY || return 1
- diff $dir/ORIGINAL $dir/COPY || return 1
- ceph osd in ${initial_osds[$last]} || return 1
-
- rm $dir/ORIGINAL
-}
-
-function rados_osds_out_in() {
- local dir=$1
- local poolname=$2
- local objname=${3:-SOMETHING}
-
-
- for marker in FFFF GGGG HHHH IIII ; do
- printf "%*s" 1024 $marker
- done > $dir/ORIGINAL
-
- #
- # get and put an object, compare they are equal
- #
- rados --pool $poolname put $objname $dir/ORIGINAL || return 1
- rados --pool $poolname get $objname $dir/COPY || return 1
- diff $dir/ORIGINAL $dir/COPY || return 1
- rm $dir/COPY
-
- #
- # take out two OSDs used to store the object, wait for the cluster
- # to be clean (i.e. all PG are clean and active) again which
- # implies the PG have been moved to use the remaining OSDs. Check
- # the object can still be retrieved.
- #
- wait_for_clean || return 1
- local osds_list=$(get_osds $poolname $objname)
- local -a osds=($osds_list)
- for osd in 0 1 ; do
- ceph osd out ${osds[$osd]} || return 1
- done
- wait_for_clean || return 1
- #
- # verify the object is no longer mapped to the osds that are out
- #
- for osd in 0 1 ; do
- ! get_osds $poolname $objname | grep '\<'${osds[$osd]}'\>' || return 1
- done
- rados --pool $poolname get $objname $dir/COPY || return 1
- diff $dir/ORIGINAL $dir/COPY || return 1
- #
- # bring the osds back in, , wait for the cluster
- # to be clean (i.e. all PG are clean and active) again which
- # implies the PG go back to using the same osds as before
- #
- for osd in 0 1 ; do
- ceph osd in ${osds[$osd]} || return 1
- done
- wait_for_clean || return 1
- test "$osds_list" = "$(get_osds $poolname $objname)" || return 1
- rm $dir/ORIGINAL
-}
-
-function TEST_rados_put_get_lrc_advanced() {
- local dir=$1
- local poolname=pool-lrc-a
- local profile=profile-lrc-a
-
- ceph osd erasure-code-profile set $profile \
- plugin=lrc \
- mapping=DD_ \
- crush-steps='[ [ "chooseleaf", "osd", 0 ] ]' \
- layers='[ [ "DDc", "" ] ]' || return 1
- create_pool $poolname 12 12 erasure $profile \
- || return 1
-
- rados_put_get $dir $poolname || return 1
-
- delete_pool $poolname
- ceph osd erasure-code-profile rm $profile
-}
-
-function TEST_rados_put_get_lrc_kml() {
- local dir=$1
- local poolname=pool-lrc
- local profile=profile-lrc
-
- ceph osd erasure-code-profile set $profile \
- plugin=lrc \
- k=4 m=2 l=3 \
- crush-failure-domain=osd || return 1
- create_pool $poolname 12 12 erasure $profile \
- || return 1
-
- rados_put_get $dir $poolname || return 1
-
- delete_pool $poolname
- ceph osd erasure-code-profile rm $profile
-}
-
-function TEST_rados_put_get_isa() {
- if ! erasure_code_plugin_exists isa ; then
- echo "SKIP because plugin isa has not been built"
- return 0
- fi
- local dir=$1
- local poolname=pool-isa
-
- ceph osd erasure-code-profile set profile-isa \
- plugin=isa \
- crush-failure-domain=osd || return 1
- create_pool $poolname 1 1 erasure profile-isa \
- || return 1
-
- rados_put_get $dir $poolname || return 1
-
- delete_pool $poolname
-}
-
-function TEST_rados_put_get_jerasure() {
- local dir=$1
-
- rados_put_get $dir ecpool || return 1
-
- local poolname=pool-jerasure
- local profile=profile-jerasure
-
- ceph osd erasure-code-profile set $profile \
- plugin=jerasure \
- k=4 m=2 \
- crush-failure-domain=osd || return 1
- create_pool $poolname 12 12 erasure $profile \
- || return 1
-
- rados_put_get $dir $poolname || return 1
- rados_osds_out_in $dir $poolname || return 1
-
- delete_pool $poolname
- ceph osd erasure-code-profile rm $profile
-}
-
-function TEST_rados_put_get_shec() {
- local dir=$1
-
- local poolname=pool-shec
- local profile=profile-shec
-
- ceph osd erasure-code-profile set $profile \
- plugin=shec \
- k=2 m=1 c=1 \
- crush-failure-domain=osd || return 1
- create_pool $poolname 12 12 erasure $profile \
- || return 1
-
- rados_put_get $dir $poolname || return 1
-
- delete_pool $poolname
- ceph osd erasure-code-profile rm $profile
-}
-
-function TEST_alignment_constraints() {
- local payload=ABC
- echo "$payload" > $dir/ORIGINAL
- #
- # Verify that the rados command enforces alignment constraints
- # imposed by the stripe width
- # See http://tracker.ceph.com/issues/8622
- #
- local stripe_unit=$(ceph-conf --show-config-value osd_pool_erasure_code_stripe_unit)
- eval local $(ceph osd erasure-code-profile get myprofile | grep k=)
- local block_size=$((stripe_unit * k - 1))
- dd if=/dev/zero of=$dir/ORIGINAL bs=$block_size count=2
- rados --block-size=$block_size \
- --pool ecpool put UNALIGNED $dir/ORIGINAL || return 1
- rm $dir/ORIGINAL
-}
-
-function chunk_size() {
- echo $(ceph-conf --show-config-value osd_pool_erasure_code_stripe_unit)
-}
-
-#
-# By default an object will be split in two (k=2) with the first part
-# of the object in the first OSD of the up set and the second part in
-# the next OSD in the up set. This layout is defined by the mapping
-# parameter and this function helps verify that the first and second
-# part of the object are located in the OSD where they should be.
-#
-function verify_chunk_mapping() {
- local dir=$1
- local poolname=$2
- local first=$3
- local second=$4
-
- local payload=$(printf '%*s' $(chunk_size) FIRST$poolname ; printf '%*s' $(chunk_size) SECOND$poolname)
- echo -n "$payload" > $dir/ORIGINAL
-
- rados --pool $poolname put SOMETHING$poolname $dir/ORIGINAL || return 1
- rados --pool $poolname get SOMETHING$poolname $dir/COPY || return 1
- local -a osds=($(get_osds $poolname SOMETHING$poolname))
- for (( i = 0; i < ${#osds[@]}; i++ )) ; do
- ceph daemon osd.${osds[$i]} flush_journal
- done
- diff $dir/ORIGINAL $dir/COPY || return 1
- rm $dir/COPY
-
- local -a osds=($(get_osds $poolname SOMETHING$poolname))
- grep --quiet --recursive --text FIRST$poolname $dir/${osds[$first]} || return 1
- grep --quiet --recursive --text SECOND$poolname $dir/${osds[$second]} || return 1
-}
-
-function TEST_chunk_mapping() {
- local dir=$1
-
- #
- # mapping=DD_ is the default:
- # first OSD (i.e. 0) in the up set has the first part of the object
- # second OSD (i.e. 1) in the up set has the second part of the object
- #
- verify_chunk_mapping $dir ecpool 0 1 || return 1
-
- ceph osd erasure-code-profile set remap-profile \
- plugin=lrc \
- layers='[ [ "_DD", "" ] ]' \
- mapping='_DD' \
- crush-steps='[ [ "choose", "osd", 0 ] ]' || return 1
- ceph osd erasure-code-profile get remap-profile
- create_pool remap-pool 12 12 erasure remap-profile \
- || return 1
-
- #
- # mapping=_DD
- # second OSD (i.e. 1) in the up set has the first part of the object
- # third OSD (i.e. 2) in the up set has the second part of the object
- #
- verify_chunk_mapping $dir remap-pool 1 2 || return 1
-
- delete_pool remap-pool
- ceph osd erasure-code-profile rm remap-profile
-}
-
-main test-erasure-code "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/erasure-code/test-erasure-code.sh"
-# End:
diff --git a/src/ceph/qa/standalone/erasure-code/test-erasure-eio.sh b/src/ceph/qa/standalone/erasure-code/test-erasure-eio.sh
deleted file mode 100755
index b788016..0000000
--- a/src/ceph/qa/standalone/erasure-code/test-erasure-eio.sh
+++ /dev/null
@@ -1,323 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2015 Red Hat <contact@redhat.com>
-#
-#
-# Author: Kefu Chai <kchai@redhat.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7112" # git grep '\<7112\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- create_rbd_pool || return 1
-
- # check that erasure code plugins are preloaded
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path mon.a) log flush || return 1
- grep 'load: jerasure.*lrc' $dir/mon.a.log || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function setup_osds() {
- for id in $(seq 0 3) ; do
- run_osd $dir $id || return 1
- done
- wait_for_clean || return 1
-
- # check that erasure code plugins are preloaded
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log flush || return 1
- grep 'load: jerasure.*lrc' $dir/osd.0.log || return 1
-}
-
-function create_erasure_coded_pool() {
- local poolname=$1
-
- ceph osd erasure-code-profile set myprofile \
- plugin=jerasure \
- k=2 m=1 \
- crush-failure-domain=osd || return 1
- create_pool $poolname 1 1 erasure myprofile \
- || return 1
- wait_for_clean || return 1
-}
-
-function delete_pool() {
- local poolname=$1
-
- ceph osd pool delete $poolname $poolname --yes-i-really-really-mean-it
- ceph osd erasure-code-profile rm myprofile
-}
-
-function rados_put() {
- local dir=$1
- local poolname=$2
- local objname=${3:-SOMETHING}
-
- for marker in AAA BBB CCCC DDDD ; do
- printf "%*s" 1024 $marker
- done > $dir/ORIGINAL
- #
- # get and put an object, compare they are equal
- #
- rados --pool $poolname put $objname $dir/ORIGINAL || return 1
-}
-
-function rados_get() {
- local dir=$1
- local poolname=$2
- local objname=${3:-SOMETHING}
- local expect=${4:-ok}
-
- #
- # Expect a failure to get object
- #
- if [ $expect = "fail" ];
- then
- ! rados --pool $poolname get $objname $dir/COPY
- return
- fi
- #
- # get an object, compare with $dir/ORIGINAL
- #
- rados --pool $poolname get $objname $dir/COPY || return 1
- diff $dir/ORIGINAL $dir/COPY || return 1
- rm $dir/COPY
-}
-
-function rados_put_get() {
- local dir=$1
- local poolname=$2
- local objname=${3:-SOMETHING}
- local recovery=$4
-
- #
- # get and put an object, compare they are equal
- #
- rados_put $dir $poolname $objname || return 1
- # We can read even though caller injected read error on one of the shards
- rados_get $dir $poolname $objname || return 1
-
- if [ -n "$recovery" ];
- then
- #
- # take out the last OSD used to store the object,
- # bring it back, and check for clean PGs which means
- # recovery didn't crash the primary.
- #
- local -a initial_osds=($(get_osds $poolname $objname))
- local last=$((${#initial_osds[@]} - 1))
- # Kill OSD
- kill_daemons $dir TERM osd.${initial_osds[$last]} >&2 < /dev/null || return 1
- ceph osd out ${initial_osds[$last]} || return 1
- ! get_osds $poolname $objname | grep '\<'${initial_osds[$last]}'\>' || return 1
- ceph osd in ${initial_osds[$last]} || return 1
- run_osd $dir ${initial_osds[$last]} || return 1
- wait_for_clean || return 1
- fi
-
- rm $dir/ORIGINAL
-}
-
-function rados_get_data_eio() {
- local dir=$1
- shift
- local shard_id=$1
- shift
- local recovery=$1
- shift
-
- # inject eio to speificied shard
- #
- local poolname=pool-jerasure
- local objname=obj-eio-$$-$shard_id
- inject_eio ec data $poolname $objname $dir $shard_id || return 1
- rados_put_get $dir $poolname $objname $recovery || return 1
-
- shard_id=$(expr $shard_id + 1)
- inject_eio ec data $poolname $objname $dir $shard_id || return 1
- # Now 2 out of 3 shards get EIO, so should fail
- rados_get $dir $poolname $objname fail || return 1
-}
-
-# Change the size of speificied shard
-#
-function set_size() {
- local objname=$1
- shift
- local dir=$1
- shift
- local shard_id=$1
- shift
- local bytes=$1
- shift
- local mode=${1}
-
- local poolname=pool-jerasure
- local -a initial_osds=($(get_osds $poolname $objname))
- local osd_id=${initial_osds[$shard_id]}
- ceph osd set noout
- if [ "$mode" = "add" ];
- then
- objectstore_tool $dir $osd_id $objname get-bytes $dir/CORRUPT || return 1
- dd if=/dev/urandom bs=$bytes count=1 >> $dir/CORRUPT
- elif [ "$bytes" = "0" ];
- then
- touch $dir/CORRUPT
- else
- dd if=/dev/urandom bs=$bytes count=1 of=$dir/CORRUPT
- fi
- objectstore_tool $dir $osd_id $objname set-bytes $dir/CORRUPT || return 1
- rm -f $dir/CORRUPT
- ceph osd unset noout
-}
-
-function rados_get_data_bad_size() {
- local dir=$1
- shift
- local shard_id=$1
- shift
- local bytes=$1
- shift
- local mode=${1:-set}
-
- local poolname=pool-jerasure
- local objname=obj-size-$$-$shard_id-$bytes
- rados_put $dir $poolname $objname || return 1
-
- # Change the size of speificied shard
- #
- set_size $objname $dir $shard_id $bytes $mode || return 1
-
- rados_get $dir $poolname $objname || return 1
-
- # Leave objname and modify another shard
- shard_id=$(expr $shard_id + 1)
- set_size $objname $dir $shard_id $bytes $mode || return 1
- rados_get $dir $poolname $objname fail || return 1
-}
-
-#
-# These two test cases try to validate the following behavior:
-# For object on EC pool, if there is one shard having read error (
-# either primary or replica), client can still read object.
-#
-# If 2 shards have read errors the client will get an error.
-#
-function TEST_rados_get_subread_eio_shard_0() {
- local dir=$1
- setup_osds || return 1
-
- local poolname=pool-jerasure
- create_erasure_coded_pool $poolname || return 1
- # inject eio on primary OSD (0) and replica OSD (1)
- local shard_id=0
- rados_get_data_eio $dir $shard_id || return 1
- delete_pool $poolname
-}
-
-function TEST_rados_get_subread_eio_shard_1() {
- local dir=$1
- setup_osds || return 1
-
- local poolname=pool-jerasure
- create_erasure_coded_pool $poolname || return 1
- # inject eio into replicas OSD (1) and OSD (2)
- local shard_id=1
- rados_get_data_eio $dir $shard_id || return 1
- delete_pool $poolname
-}
-
-#
-# These two test cases try to validate that following behavior:
-# For object on EC pool, if there is one shard which an incorrect
-# size this will cause an internal read error, client can still read object.
-#
-# If 2 shards have incorrect size the client will get an error.
-#
-function TEST_rados_get_bad_size_shard_0() {
- local dir=$1
- setup_osds || return 1
-
- local poolname=pool-jerasure
- create_erasure_coded_pool $poolname || return 1
- # Set incorrect size into primary OSD (0) and replica OSD (1)
- local shard_id=0
- rados_get_data_bad_size $dir $shard_id 10 || return 1
- rados_get_data_bad_size $dir $shard_id 0 || return 1
- rados_get_data_bad_size $dir $shard_id 256 add || return 1
- delete_pool $poolname
-}
-
-function TEST_rados_get_bad_size_shard_1() {
- local dir=$1
- setup_osds || return 1
-
- local poolname=pool-jerasure
- create_erasure_coded_pool $poolname || return 1
- # Set incorrect size into replicas OSD (1) and OSD (2)
- local shard_id=1
- rados_get_data_bad_size $dir $shard_id 10 || return 1
- rados_get_data_bad_size $dir $shard_id 0 || return 1
- rados_get_data_bad_size $dir $shard_id 256 add || return 1
- delete_pool $poolname
-}
-
-function TEST_rados_get_with_subreadall_eio_shard_0() {
- local dir=$1
- local shard_id=0
-
- setup_osds || return 1
-
- local poolname=pool-jerasure
- create_erasure_coded_pool $poolname || return 1
- # inject eio on primary OSD (0)
- local shard_id=0
- rados_get_data_eio $dir $shard_id recovery || return 1
-
- delete_pool $poolname
-}
-
-function TEST_rados_get_with_subreadall_eio_shard_1() {
- local dir=$1
- local shard_id=0
-
- setup_osds || return 1
-
- local poolname=pool-jerasure
- create_erasure_coded_pool $poolname || return 1
- # inject eio on replica OSD (1)
- local shard_id=1
- rados_get_data_eio $dir $shard_id recovery || return 1
-
- delete_pool $poolname
-}
-
-main test-erasure-eio "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/erasure-code/test-erasure-eio.sh"
-# End:
diff --git a/src/ceph/qa/standalone/misc/rados-striper.sh b/src/ceph/qa/standalone/misc/rados-striper.sh
deleted file mode 100755
index 0315153..0000000
--- a/src/ceph/qa/standalone/misc/rados-striper.sh
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2014 Red Hat <contact@redhat.com>
-#
-# Author: Sebastien Ponce <sebastien.ponce@cern.ch>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7116" # git grep '\<7116\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- # setup
- setup $dir || return 1
-
- # create a cluster with one monitor and three osds
- run_mon $dir a || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- run_osd $dir 2 || return 1
- create_rbd_pool || return 1
-
- # create toyfile
- dd if=/dev/urandom of=$dir/toyfile bs=1234 count=1
-
- # put a striped object
- rados --pool rbd --striper put toyfile $dir/toyfile || return 1
-
- # stat it, with and without striping
- rados --pool rbd --striper stat toyfile | cut -d ',' -f 2 > $dir/stripedStat || return 1
- rados --pool rbd stat toyfile.0000000000000000 | cut -d ',' -f 2 > $dir/stat || return 1
- echo ' size 1234' > $dir/refstat
- diff -w $dir/stripedStat $dir/refstat || return 1
- diff -w $dir/stat $dir/refstat || return 1
- rados --pool rbd stat toyfile >& $dir/staterror
- grep -q 'No such file or directory' $dir/staterror || return 1
-
- # get the file back with and without striping
- rados --pool rbd --striper get toyfile $dir/stripedGroup || return 1
- diff -w $dir/toyfile $dir/stripedGroup || return 1
- rados --pool rbd get toyfile.0000000000000000 $dir/nonSTripedGroup || return 1
- diff -w $dir/toyfile $dir/nonSTripedGroup || return 1
-
- # test truncate
- rados --pool rbd --striper truncate toyfile 12
- rados --pool rbd --striper stat toyfile | cut -d ',' -f 2 > $dir/stripedStat || return 1
- rados --pool rbd stat toyfile.0000000000000000 | cut -d ',' -f 2 > $dir/stat || return 1
- echo ' size 12' > $dir/reftrunc
- diff -w $dir/stripedStat $dir/reftrunc || return 1
- diff -w $dir/stat $dir/reftrunc || return 1
-
- # test xattrs
-
- rados --pool rbd --striper setxattr toyfile somexattr somevalue || return 1
- rados --pool rbd --striper getxattr toyfile somexattr > $dir/xattrvalue || return 1
- rados --pool rbd getxattr toyfile.0000000000000000 somexattr > $dir/xattrvalue2 || return 1
- echo 'somevalue' > $dir/refvalue
- diff -w $dir/xattrvalue $dir/refvalue || return 1
- diff -w $dir/xattrvalue2 $dir/refvalue || return 1
- rados --pool rbd --striper listxattr toyfile > $dir/xattrlist || return 1
- echo 'somexattr' > $dir/reflist
- diff -w $dir/xattrlist $dir/reflist || return 1
- rados --pool rbd listxattr toyfile.0000000000000000 | grep -v striper > $dir/xattrlist2 || return 1
- diff -w $dir/xattrlist2 $dir/reflist || return 1
- rados --pool rbd --striper rmxattr toyfile somexattr || return 1
-
- local attr_not_found_str="No data available"
- [ `uname` = FreeBSD ] && \
- attr_not_found_str="Attribute not found"
- expect_failure $dir "$attr_not_found_str" \
- rados --pool rbd --striper getxattr toyfile somexattr || return 1
- expect_failure $dir "$attr_not_found_str" \
- rados --pool rbd getxattr toyfile.0000000000000000 somexattr || return 1
-
- # test rm
- rados --pool rbd --striper rm toyfile || return 1
- expect_failure $dir 'No such file or directory' \
- rados --pool rbd --striper stat toyfile || return 1
- expect_failure $dir 'No such file or directory' \
- rados --pool rbd stat toyfile.0000000000000000 || return 1
-
- # cleanup
- teardown $dir || return 1
-}
-
-main rados-striper "$@"
diff --git a/src/ceph/qa/standalone/misc/test-ceph-helpers.sh b/src/ceph/qa/standalone/misc/test-ceph-helpers.sh
deleted file mode 100755
index 932fcf3..0000000
--- a/src/ceph/qa/standalone/misc/test-ceph-helpers.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2013,2014 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014 Red Hat <contact@redhat.com>
-# Copyright (C) 2014 Federico Gimenez <fgimenez@coit.es>
-#
-# Author: Loic Dachary <loic@dachary.org>
-# Author: Federico Gimenez <fgimenez@coit.es>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-
-$CEPH_ROOT/qa/standalone/ceph-helpers.sh TESTS "$@"
diff --git a/src/ceph/qa/standalone/mon/misc.sh b/src/ceph/qa/standalone/mon/misc.sh
deleted file mode 100755
index e025e07..0000000
--- a/src/ceph/qa/standalone/mon/misc.sh
+++ /dev/null
@@ -1,238 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7102" # git grep '\<7102\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- $func $dir || return 1
- done
-}
-
-TEST_POOL=rbd
-
-function TEST_osd_pool_get_set() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a || return 1
- create_rbd_pool || return 1
- create_pool $TEST_POOL 8
-
- local flag
- for flag in nodelete nopgchange nosizechange write_fadvise_dontneed noscrub nodeep-scrub; do
- ceph osd pool set $TEST_POOL $flag 0 || return 1
- ! ceph osd dump | grep 'pool ' | grep $flag || return 1
- ceph osd pool set $TEST_POOL $flag 1 || return 1
- ceph osd dump | grep 'pool ' | grep $flag || return 1
- ceph osd pool set $TEST_POOL $flag false || return 1
- ! ceph osd dump | grep 'pool ' | grep $flag || return 1
- ceph osd pool set $TEST_POOL $flag false || return 1
- # check that setting false twice does not toggle to true (bug)
- ! ceph osd dump | grep 'pool ' | grep $flag || return 1
- ceph osd pool set $TEST_POOL $flag true || return 1
- ceph osd dump | grep 'pool ' | grep $flag || return 1
- # cleanup
- ceph osd pool set $TEST_POOL $flag 0 || return 1
- done
-
- local size=$(ceph osd pool get $TEST_POOL size|awk '{print $2}')
- local min_size=$(ceph osd pool get $TEST_POOL min_size|awk '{print $2}')
-
- ceph osd pool set $TEST_POOL scrub_min_interval 123456 || return 1
- ceph osd dump | grep 'pool ' | grep 'scrub_min_interval 123456' || return 1
- ceph osd pool set $TEST_POOL scrub_min_interval 0 || return 1
- ceph osd dump | grep 'pool ' | grep 'scrub_min_interval' && return 1
- ceph osd pool set $TEST_POOL scrub_max_interval 123456 || return 1
- ceph osd dump | grep 'pool ' | grep 'scrub_max_interval 123456' || return 1
- ceph osd pool set $TEST_POOL scrub_max_interval 0 || return 1
- ceph osd dump | grep 'pool ' | grep 'scrub_max_interval' && return 1
- ceph osd pool set $TEST_POOL deep_scrub_interval 123456 || return 1
- ceph osd dump | grep 'pool ' | grep 'deep_scrub_interval 123456' || return 1
- ceph osd pool set $TEST_POOL deep_scrub_interval 0 || return 1
- ceph osd dump | grep 'pool ' | grep 'deep_scrub_interval' && return 1
-
- #replicated pool size restrict in 1 and 10
- ! ceph osd pool set $TEST_POOL 11 || return 1
- #replicated pool min_size must be between in 1 and size
- ! ceph osd pool set $TEST_POOL min_size $(expr $size + 1) || return 1
- ! ceph osd pool set $TEST_POOL min_size 0 || return 1
-
- local ecpool=erasepool
- create_pool $ecpool 12 12 erasure default || return 1
- #erasue pool size=k+m, min_size=k
- local size=$(ceph osd pool get $ecpool size|awk '{print $2}')
- local min_size=$(ceph osd pool get $ecpool min_size|awk '{print $2}')
- local k=$(expr $min_size - 1) # default min_size=k+1
- #erasure pool size can't change
- ! ceph osd pool set $ecpool size $(expr $size + 1) || return 1
- #erasure pool min_size must be between in k and size
- ceph osd pool set $ecpool min_size $(expr $k + 1) || return 1
- ! ceph osd pool set $ecpool min_size $(expr $k - 1) || return 1
- ! ceph osd pool set $ecpool min_size $(expr $size + 1) || return 1
-
- teardown $dir || return 1
-}
-
-function TEST_mon_add_to_single_mon() {
- local dir=$1
-
- fsid=$(uuidgen)
- MONA=127.0.0.1:7117 # git grep '\<7117\>' : there must be only one
- MONB=127.0.0.1:7118 # git grep '\<7118\>' : there must be only one
- CEPH_ARGS_orig=$CEPH_ARGS
- CEPH_ARGS="--fsid=$fsid --auth-supported=none "
- CEPH_ARGS+="--mon-initial-members=a "
- CEPH_ARGS+="--mon-host=$MONA "
-
- setup $dir || return 1
- run_mon $dir a --public-addr $MONA || return 1
- # wait for the quorum
- timeout 120 ceph -s > /dev/null || return 1
- run_mon $dir b --public-addr $MONB || return 1
- teardown $dir || return 1
-
- setup $dir || return 1
- run_mon $dir a --public-addr $MONA || return 1
- # without the fix of #5454, mon.a will assert failure at seeing the MMonJoin
- # from mon.b
- run_mon $dir b --public-addr $MONB || return 1
- # wait for the quorum
- timeout 120 ceph -s > /dev/null || return 1
- local num_mons
- num_mons=$(ceph mon dump --format=json 2>/dev/null | jq ".mons | length") || return 1
- [ $num_mons == 2 ] || return 1
- # no reason to take more than 120 secs to get this submitted
- timeout 120 ceph mon add b $MONB || return 1
- teardown $dir || return 1
-}
-
-function TEST_no_segfault_for_bad_keyring() {
- local dir=$1
- setup $dir || return 1
- # create a client.admin key and add it to ceph.mon.keyring
- ceph-authtool --create-keyring $dir/ceph.mon.keyring --gen-key -n mon. --cap mon 'allow *'
- ceph-authtool --create-keyring $dir/ceph.client.admin.keyring --gen-key -n client.admin --cap mon 'allow *'
- ceph-authtool $dir/ceph.mon.keyring --import-keyring $dir/ceph.client.admin.keyring
- CEPH_ARGS_TMP="--fsid=$(uuidgen) --mon-host=127.0.0.1:7102 --auth-supported=cephx "
- CEPH_ARGS_orig=$CEPH_ARGS
- CEPH_ARGS="$CEPH_ARGS_TMP --keyring=$dir/ceph.mon.keyring "
- run_mon $dir a
- # create a bad keyring and make sure no segfault occurs when using the bad keyring
- echo -e "[client.admin]\nkey = BQAUlgtWoFePIxAAQ9YLzJSVgJX5V1lh5gyctg==" > $dir/bad.keyring
- CEPH_ARGS="$CEPH_ARGS_TMP --keyring=$dir/bad.keyring"
- ceph osd dump 2> /dev/null
- # 139(11|128) means segfault and core dumped
- [ $? -eq 139 ] && return 1
- CEPH_ARGS=$CEPH_ARGS_orig
- teardown $dir || return 1
-}
-
-function TEST_mon_features() {
- local dir=$1
- setup $dir || return 1
-
- fsid=$(uuidgen)
- MONA=127.0.0.1:7127 # git grep '\<7127\>' ; there must be only one
- MONB=127.0.0.1:7128 # git grep '\<7128\>' ; there must be only one
- MONC=127.0.0.1:7129 # git grep '\<7129\>' ; there must be only one
- CEPH_ARGS_orig=$CEPH_ARGS
- CEPH_ARGS="--fsid=$fsid --auth-supported=none "
- CEPH_ARGS+="--mon-initial-members=a,b,c "
- CEPH_ARGS+="--mon-host=$MONA,$MONB,$MONC "
- CEPH_ARGS+="--mon-debug-no-initial-persistent-features "
- CEPH_ARGS+="--mon-debug-no-require-luminous "
-
- run_mon $dir a --public-addr $MONA || return 1
- run_mon $dir b --public-addr $MONB || return 1
- timeout 120 ceph -s > /dev/null || return 1
-
- # expect monmap to contain 3 monitors (a, b, and c)
- jqinput="$(ceph mon_status --format=json 2>/dev/null)"
- jq_success "$jqinput" '.monmap.mons | length == 3' || return 1
- # quorum contains two monitors
- jq_success "$jqinput" '.quorum | length == 2' || return 1
- # quorum's monitor features contain kraken and luminous
- jqfilter='.features.quorum_mon[]|select(. == "kraken")'
- jq_success "$jqinput" "$jqfilter" "kraken" || return 1
- jqfilter='.features.quorum_mon[]|select(. == "luminous")'
- jq_success "$jqinput" "$jqfilter" "luminous" || return 1
-
- # monmap must have no persistent features set, because we
- # don't currently have a quorum made out of all the monitors
- # in the monmap.
- jqfilter='.monmap.features.persistent | length == 0'
- jq_success "$jqinput" "$jqfilter" || return 1
-
- # nor do we have any optional features, for that matter.
- jqfilter='.monmap.features.optional | length == 0'
- jq_success "$jqinput" "$jqfilter" || return 1
-
- # validate 'mon feature ls'
-
- jqinput="$(ceph mon feature ls --format=json 2>/dev/null)"
- # 'kraken' and 'luminous' are supported
- jqfilter='.all.supported[] | select(. == "kraken")'
- jq_success "$jqinput" "$jqfilter" "kraken" || return 1
- jqfilter='.all.supported[] | select(. == "luminous")'
- jq_success "$jqinput" "$jqfilter" "luminous" || return 1
-
- # start third monitor
- run_mon $dir c --public-addr $MONC || return 1
-
- wait_for_quorum 300 3 || return 1
-
- timeout 300 ceph -s > /dev/null || return 1
-
- jqinput="$(ceph mon_status --format=json 2>/dev/null)"
- # expect quorum to have all three monitors
- jqfilter='.quorum | length == 3'
- jq_success "$jqinput" "$jqfilter" || return 1
- # quorum's monitor features contain kraken and luminous
- jqfilter='.features.quorum_mon[]|select(. == "kraken")'
- jq_success "$jqinput" "$jqfilter" "kraken" || return 1
- jqfilter='.features.quorum_mon[]|select(. == "luminous")'
- jq_success "$jqinput" "$jqfilter" "luminous" || return 1
-
- # monmap must have no both 'kraken' and 'luminous' persistent
- # features set.
- jqfilter='.monmap.features.persistent | length == 2'
- jq_success "$jqinput" "$jqfilter" || return 1
- jqfilter='.monmap.features.persistent[]|select(. == "kraken")'
- jq_success "$jqinput" "$jqfilter" "kraken" || return 1
- jqfilter='.monmap.features.persistent[]|select(. == "luminous")'
- jq_success "$jqinput" "$jqfilter" "luminous" || return 1
-
- CEPH_ARGS=$CEPH_ARGS_orig
- # that's all folks. thank you for tuning in.
- teardown $dir || return 1
-}
-
-main misc "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/mon/misc.sh"
-# End:
diff --git a/src/ceph/qa/standalone/mon/mkfs.sh b/src/ceph/qa/standalone/mon/mkfs.sh
deleted file mode 100755
index 6b8e58d..0000000
--- a/src/ceph/qa/standalone/mon/mkfs.sh
+++ /dev/null
@@ -1,198 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-set -xe
-PS4='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: '
-
-
-DIR=mkfs
-export CEPH_CONF=/dev/null
-unset CEPH_ARGS
-MON_ID=a
-MON_DIR=$DIR/$MON_ID
-CEPH_MON=127.0.0.1:7110 # git grep '\<7110\>' : there must be only one
-TIMEOUT=360
-
-EXTRAOPTS=""
-if [ -n "$CEPH_LIB" ]; then
- EXTRAOPTS+=" --erasure-code-dir $CEPH_LIB"
- EXTRAOPTS+=" --plugin-dir $CEPH_LIB"
- EXTRAOPTS+=" --osd-class-dir $CEPH_LIB"
-fi
-
-function setup() {
- teardown
- mkdir $DIR
-}
-
-function teardown() {
- kill_daemons
- rm -fr $DIR
-}
-
-function mon_mkfs() {
- local fsid=$(uuidgen)
-
- ceph-mon \
- --id $MON_ID \
- --fsid $fsid \
- $EXTRAOPTS \
- --mkfs \
- --mon-data=$MON_DIR \
- --mon-initial-members=$MON_ID \
- --mon-host=$CEPH_MON \
- "$@"
-}
-
-function mon_run() {
- ceph-mon \
- --id $MON_ID \
- --chdir= \
- --mon-osd-full-ratio=.99 \
- --mon-data-avail-crit=1 \
- $EXTRAOPTS \
- --mon-data=$MON_DIR \
- --log-file=$MON_DIR/log \
- --mon-cluster-log-file=$MON_DIR/log \
- --run-dir=$MON_DIR \
- --pid-file=$MON_DIR/pidfile \
- --public-addr $CEPH_MON \
- "$@"
-}
-
-function kill_daemons() {
- for pidfile in $(find $DIR -name pidfile) ; do
- pid=$(cat $pidfile)
- for try in 0 1 1 1 2 3 ; do
- kill $pid || break
- sleep $try
- done
- done
-}
-
-function auth_none() {
- mon_mkfs --auth-supported=none
-
- ceph-mon \
- --id $MON_ID \
- --mon-osd-full-ratio=.99 \
- --mon-data-avail-crit=1 \
- $EXTRAOPTS \
- --mon-data=$MON_DIR \
- --extract-monmap $MON_DIR/monmap
-
- [ -f $MON_DIR/monmap ] || return 1
-
- [ ! -f $MON_DIR/keyring ] || return 1
-
- mon_run --auth-supported=none
-
- timeout $TIMEOUT ceph --mon-host $CEPH_MON mon stat || return 1
-}
-
-function auth_cephx_keyring() {
- cat > $DIR/keyring <<EOF
-[mon.]
- key = AQDUS79S0AF9FRAA2cgRLFscVce0gROn/s9WMg==
- caps mon = "allow *"
-EOF
-
- mon_mkfs --keyring=$DIR/keyring
-
- [ -f $MON_DIR/keyring ] || return 1
-
- mon_run
-
- timeout $TIMEOUT ceph \
- --name mon. \
- --keyring $MON_DIR/keyring \
- --mon-host $CEPH_MON mon stat || return 1
-}
-
-function auth_cephx_key() {
- if [ -f /etc/ceph/keyring ] ; then
- echo "Please move /etc/ceph/keyring away for testing!"
- return 1
- fi
-
- local key=$(ceph-authtool --gen-print-key)
-
- if mon_mkfs --key='corrupted key' ; then
- return 1
- else
- rm -fr $MON_DIR/store.db
- rm -fr $MON_DIR/kv_backend
- fi
-
- mon_mkfs --key=$key
-
- [ -f $MON_DIR/keyring ] || return 1
- grep $key $MON_DIR/keyring
-
- mon_run
-
- timeout $TIMEOUT ceph \
- --name mon. \
- --keyring $MON_DIR/keyring \
- --mon-host $CEPH_MON mon stat || return 1
-}
-
-function makedir() {
- local toodeep=$MON_DIR/toodeep
-
- # fail if recursive directory creation is needed
- ceph-mon \
- --id $MON_ID \
- --mon-osd-full-ratio=.99 \
- --mon-data-avail-crit=1 \
- $EXTRAOPTS \
- --mkfs \
- --mon-data=$toodeep 2>&1 | tee $DIR/makedir.log
- grep 'toodeep.*No such file' $DIR/makedir.log > /dev/null
- rm $DIR/makedir.log
-
- # an empty directory does not mean the mon exists
- mkdir $MON_DIR
- mon_mkfs --auth-supported=none 2>&1 | tee $DIR/makedir.log
- ! grep "$MON_DIR already exists" $DIR/makedir.log || return 1
-}
-
-function idempotent() {
- mon_mkfs --auth-supported=none
- mon_mkfs --auth-supported=none 2>&1 | tee $DIR/makedir.log
- grep "'$MON_DIR' already exists" $DIR/makedir.log > /dev/null || return 1
-}
-
-function run() {
- local actions
- actions+="makedir "
- actions+="idempotent "
- actions+="auth_cephx_key "
- actions+="auth_cephx_keyring "
- actions+="auth_none "
- for action in $actions ; do
- setup
- $action || return 1
- teardown
- done
-}
-
-run
-
-# Local Variables:
-# compile-command: "cd ../.. ; make TESTS=test/mon/mkfs.sh check"
-# End:
diff --git a/src/ceph/qa/standalone/mon/mon-bind.sh b/src/ceph/qa/standalone/mon/mon-bind.sh
deleted file mode 100755
index a4d774d..0000000
--- a/src/ceph/qa/standalone/mon/mon-bind.sh
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2017 Quantum Corp.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-SOCAT_PIDS=()
-
-function port_forward() {
- local source_port=$1
- local target_port=$2
-
- socat TCP-LISTEN:${source_port},fork,reuseaddr TCP:localhost:${target_port} &
- SOCAT_PIDS+=( $! )
-}
-
-function cleanup() {
- for p in "${SOCAT_PIDS[@]}"; do
- kill $p
- done
- SOCAT_PIDS=()
-}
-
-trap cleanup SIGTERM SIGKILL SIGQUIT SIGINT
-
-function run() {
- local dir=$1
- shift
-
- export MON_IP=127.0.0.1
- export MONA_PUBLIC=7132 # git grep '\<7132\>' ; there must be only one
- export MONB_PUBLIC=7133 # git grep '\<7133\>' ; there must be only one
- export MONC_PUBLIC=7134 # git grep '\<7134\>' ; there must be only one
- export MONA_BIND=7135 # git grep '\<7135\>' ; there must be only one
- export MONB_BIND=7136 # git grep '\<7136\>' ; there must be only one
- export MONC_BIND=7137 # git grep '\<7137\>' ; there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir && cleanup || { cleanup; return 1; }
- teardown $dir
- done
-}
-
-function TEST_mon_client_connect_fails() {
- local dir=$1
-
- # start the mon with a public-bind-addr that is different
- # from the public-addr.
- CEPH_ARGS+="--mon-initial-members=a "
- CEPH_ARGS+="--mon-host=${MON_IP}:${MONA_PUBLIC} "
- run_mon $dir a --mon-host=${MON_IP}:${MONA_PUBLIC} --public-bind-addr=${MON_IP}:${MONA_BIND} || return 1
-
- # now attempt to ping it that should fail.
- timeout 3 ceph ping mon.a || return 0
- return 1
-}
-
-function TEST_mon_client_connect() {
- local dir=$1
-
- # start the mon with a public-bind-addr that is different
- # from the public-addr.
- CEPH_ARGS+="--mon-initial-members=a "
- CEPH_ARGS+="--mon-host=${MON_IP}:${MONA_PUBLIC} "
- run_mon $dir a --mon-host=${MON_IP}:${MONA_PUBLIC} --public-bind-addr=${MON_IP}:${MONA_BIND} || return 1
-
- # now forward the public port to the bind port.
- port_forward ${MONA_PUBLIC} ${MONA_BIND}
-
- # attempt to connect. we expect that to work
- ceph ping mon.a || return 1
-}
-
-function TEST_mon_quorum() {
- local dir=$1
-
- # start the mon with a public-bind-addr that is different
- # from the public-addr.
- CEPH_ARGS+="--mon-initial-members=a,b,c "
- CEPH_ARGS+="--mon-host=${MON_IP}:${MONA_PUBLIC},${MON_IP}:${MONB_PUBLIC},${MON_IP}:${MONC_PUBLIC} "
- run_mon $dir a --public-addr=${MON_IP}:${MONA_PUBLIC} --public-bind-addr=${MON_IP}:${MONA_BIND} || return 1
- run_mon $dir b --public-addr=${MON_IP}:${MONB_PUBLIC} --public-bind-addr=${MON_IP}:${MONB_BIND} || return 1
- run_mon $dir c --public-addr=${MON_IP}:${MONC_PUBLIC} --public-bind-addr=${MON_IP}:${MONC_BIND} || return 1
-
- # now forward the public port to the bind port.
- port_forward ${MONA_PUBLIC} ${MONA_BIND}
- port_forward ${MONB_PUBLIC} ${MONB_BIND}
- port_forward ${MONC_PUBLIC} ${MONC_BIND}
-
- # expect monmap to contain 3 monitors (a, b, and c)
- jqinput="$(ceph mon_status --format=json 2>/dev/null)"
- jq_success "$jqinput" '.monmap.mons | length == 3' || return 1
-
- # quorum should form
- wait_for_quorum 300 3 || return 1
- # expect quorum to have all three monitors
- jqfilter='.quorum | length == 3'
- jq_success "$jqinput" "$jqfilter" || return 1
-}
-
-function TEST_put_get() {
- local dir=$1
-
- # start the mon with a public-bind-addr that is different
- # from the public-addr.
- CEPH_ARGS+="--mon-initial-members=a,b,c "
- CEPH_ARGS+="--mon-host=${MON_IP}:${MONA_PUBLIC},${MON_IP}:${MONB_PUBLIC},${MON_IP}:${MONC_PUBLIC} "
- run_mon $dir a --public-addr=${MON_IP}:${MONA_PUBLIC} --public-bind-addr=${MON_IP}:${MONA_BIND} || return 1
- run_mon $dir b --public-addr=${MON_IP}:${MONB_PUBLIC} --public-bind-addr=${MON_IP}:${MONB_BIND} || return 1
- run_mon $dir c --public-addr=${MON_IP}:${MONC_PUBLIC} --public-bind-addr=${MON_IP}:${MONC_BIND} || return 1
-
- # now forward the public port to the bind port.
- port_forward ${MONA_PUBLIC} ${MONA_BIND}
- port_forward ${MONB_PUBLIC} ${MONB_BIND}
- port_forward ${MONC_PUBLIC} ${MONC_BIND}
-
- # quorum should form
- wait_for_quorum 300 3 || return 1
-
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- run_osd $dir 2 || return 1
-
- create_pool hello 8 || return 1
-
- echo "hello world" > $dir/hello
- rados --pool hello put foo $dir/hello || return 1
- rados --pool hello get foo $dir/hello2 || return 1
- diff $dir/hello $dir/hello2 || return 1
-}
-
-main mon-bind "$@"
diff --git a/src/ceph/qa/standalone/mon/mon-created-time.sh b/src/ceph/qa/standalone/mon/mon-created-time.sh
deleted file mode 100755
index 0955803..0000000
--- a/src/ceph/qa/standalone/mon/mon-created-time.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2015 SUSE LINUX GmbH
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7125" # git grep '\<7125\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_mon_created_time() {
- local dir=$1
-
- run_mon $dir a || return 1
-
- ceph mon dump || return 1
-
- if test "$(ceph mon dump 2>/dev/null | sed -n '/created/p' | awk '{print $NF}')"x = ""x ; then
- return 1
- fi
-
- if test "$(ceph mon dump 2>/dev/null | sed -n '/created/p' | awk '{print $NF}')"x = "0.000000"x ; then
- return 1
- fi
-}
-
-main mon-created-time "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/mon/mon-created-time.sh"
-# End:
diff --git a/src/ceph/qa/standalone/mon/mon-handle-forward.sh b/src/ceph/qa/standalone/mon/mon-handle-forward.sh
deleted file mode 100755
index e3b539b..0000000
--- a/src/ceph/qa/standalone/mon/mon-handle-forward.sh
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014,2015 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
-
- setup $dir || return 1
-
- MONA=127.0.0.1:7300
- MONB=127.0.0.1:7301
- (
- FSID=$(uuidgen)
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$FSID --auth-supported=none "
- CEPH_ARGS+="--mon-initial-members=a,b --mon-host=$MONA,$MONB "
- run_mon $dir a --public-addr $MONA || return 1
- run_mon $dir b --public-addr $MONB || return 1
- )
-
- timeout 360 ceph --mon-host $MONA mon stat || return 1
- # check that MONB is indeed a peon
- ceph --admin-daemon $(get_asok_path mon.b) mon_status |
- grep '"peon"' || return 1
- # when the leader ( MONA ) is used, there is no message forwarding
- ceph --mon-host $MONA osd pool create POOL1 12
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path mon.a) log flush || return 1
- grep 'mon_command(.*"POOL1"' $dir/a/mon.a.log
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path mon.b) log flush || return 1
- grep 'mon_command(.*"POOL1"' $dir/mon.b.log && return 1
- # when the peon ( MONB ) is used, the message is forwarded to the leader
- ceph --mon-host $MONB osd pool create POOL2 12
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path mon.b) log flush || return 1
- grep 'forward_request.*mon_command(.*"POOL2"' $dir/mon.b.log
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path mon.a) log flush || return 1
- grep ' forward(mon_command(.*"POOL2"' $dir/mon.a.log
- # forwarded messages must retain features from the original connection
- features=$(sed -n -e 's|.*127.0.0.1:0.*accept features \([0-9][0-9]*\)|\1|p' < \
- $dir/mon.b.log)
- grep ' forward(mon_command(.*"POOL2".*con_features '$features $dir/mon.a.log
-
- teardown $dir || return 1
-}
-
-main mon-handle-forward "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 TESTS=test/mon/mon-handle-forward.sh check"
-# End:
diff --git a/src/ceph/qa/standalone/mon/mon-ping.sh b/src/ceph/qa/standalone/mon/mon-ping.sh
deleted file mode 100755
index 9574f5f..0000000
--- a/src/ceph/qa/standalone/mon/mon-ping.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2015 SUSE LINUX GmbH
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7119" # git grep '\<7119\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_mon_ping() {
- local dir=$1
-
- run_mon $dir a || return 1
-
- ceph ping mon.a || return 1
-}
-
-main mon-ping "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/mon/mon-ping.sh"
-# End:
diff --git a/src/ceph/qa/standalone/mon/mon-scrub.sh b/src/ceph/qa/standalone/mon/mon-scrub.sh
deleted file mode 100755
index b40a6bc..0000000
--- a/src/ceph/qa/standalone/mon/mon-scrub.sh
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7120" # git grep '\<7120\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_mon_scrub() {
- local dir=$1
-
- run_mon $dir a || return 1
-
- ceph mon scrub || return 1
-}
-
-main mon-scrub "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/mon/mon-scrub.sh"
-# End:
diff --git a/src/ceph/qa/standalone/mon/osd-crush.sh b/src/ceph/qa/standalone/mon/osd-crush.sh
deleted file mode 100755
index 747e30d..0000000
--- a/src/ceph/qa/standalone/mon/osd-crush.sh
+++ /dev/null
@@ -1,229 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7104" # git grep '\<7104\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | ${SED} -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_crush_rule_create_simple() {
- local dir=$1
-
- run_mon $dir a || return 1
-
- ceph --format xml osd crush rule dump replicated_rule | \
- egrep '<op>take</op><item>[^<]+</item><item_name>default</item_name>' | \
- grep '<op>choose_firstn</op><num>0</num><type>osd</type>' || return 1
- local ruleset=ruleset0
- local root=host1
- ceph osd crush add-bucket $root host
- local failure_domain=osd
- ceph osd crush rule create-simple $ruleset $root $failure_domain || return 1
- ceph osd crush rule create-simple $ruleset $root $failure_domain 2>&1 | \
- grep "$ruleset already exists" || return 1
- ceph --format xml osd crush rule dump $ruleset | \
- egrep '<op>take</op><item>[^<]+</item><item_name>'$root'</item_name>' | \
- grep '<op>choose_firstn</op><num>0</num><type>'$failure_domain'</type>' || return 1
- ceph osd crush rule rm $ruleset || return 1
-}
-
-function TEST_crush_rule_dump() {
- local dir=$1
-
- run_mon $dir a || return 1
-
- local ruleset=ruleset1
- ceph osd crush rule create-erasure $ruleset || return 1
- test $(ceph --format json osd crush rule dump $ruleset | \
- jq ".rule_name == \"$ruleset\"") == true || return 1
- test $(ceph --format json osd crush rule dump | \
- jq "map(select(.rule_name == \"$ruleset\")) | length == 1") == true || return 1
- ! ceph osd crush rule dump non_existent_ruleset || return 1
- ceph osd crush rule rm $ruleset || return 1
-}
-
-function TEST_crush_rule_rm() {
- local ruleset=erasure2
-
- run_mon $dir a || return 1
-
- ceph osd crush rule create-erasure $ruleset default || return 1
- ceph osd crush rule ls | grep $ruleset || return 1
- ceph osd crush rule rm $ruleset || return 1
- ! ceph osd crush rule ls | grep $ruleset || return 1
-}
-
-function TEST_crush_rule_create_erasure() {
- local dir=$1
-
- run_mon $dir a || return 1
- # should have at least one OSD
- run_osd $dir 0 || return 1
-
- local ruleset=ruleset3
- #
- # create a new ruleset with the default profile, implicitly
- #
- ceph osd crush rule create-erasure $ruleset || return 1
- ceph osd crush rule create-erasure $ruleset 2>&1 | \
- grep "$ruleset already exists" || return 1
- ceph --format xml osd crush rule dump $ruleset | \
- egrep '<op>take</op><item>[^<]+</item><item_name>default</item_name>' | \
- grep '<op>chooseleaf_indep</op><num>0</num><type>host</type>' || return 1
- ceph osd crush rule rm $ruleset || return 1
- ! ceph osd crush rule ls | grep $ruleset || return 1
- #
- # create a new ruleset with the default profile, explicitly
- #
- ceph osd crush rule create-erasure $ruleset default || return 1
- ceph osd crush rule ls | grep $ruleset || return 1
- ceph osd crush rule rm $ruleset || return 1
- ! ceph osd crush rule ls | grep $ruleset || return 1
- #
- # create a new ruleset and the default profile, implicitly
- #
- ceph osd erasure-code-profile rm default || return 1
- ! ceph osd erasure-code-profile ls | grep default || return 1
- ceph osd crush rule create-erasure $ruleset || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path mon.a) log flush || return 1
- grep 'profile set default' $dir/mon.a.log || return 1
- ceph osd erasure-code-profile ls | grep default || return 1
- ceph osd crush rule rm $ruleset || return 1
- ! ceph osd crush rule ls | grep $ruleset || return 1
-}
-
-function check_ruleset_id_match_rule_id() {
- local rule_name=$1
- rule_id=`ceph osd crush rule dump $rule_name | grep "\"rule_id\":" | awk -F ":|," '{print int($2)}'`
- ruleset_id=`ceph osd crush rule dump $rule_name | grep "\"ruleset\":"| awk -F ":|," '{print int($2)}'`
- test $ruleset_id = $rule_id || return 1
-}
-
-function generate_manipulated_rules() {
- local dir=$1
- ceph osd crush add-bucket $root host
- ceph osd crush rule create-simple test_rule1 $root osd firstn || return 1
- ceph osd crush rule create-simple test_rule2 $root osd firstn || return 1
- ceph osd getcrushmap -o $dir/original_map
- crushtool -d $dir/original_map -o $dir/decoded_original_map
- #manipulate the rulesets , to make the rule_id != ruleset_id
- ${SED} -i 's/ruleset 0/ruleset 3/' $dir/decoded_original_map
- ${SED} -i 's/ruleset 2/ruleset 0/' $dir/decoded_original_map
- ${SED} -i 's/ruleset 1/ruleset 2/' $dir/decoded_original_map
-
- crushtool -c $dir/decoded_original_map -o $dir/new_map
- ceph osd setcrushmap -i $dir/new_map
-
- ceph osd crush rule dump
-}
-
-function TEST_crush_ruleset_match_rule_when_creating() {
- local dir=$1
-
- run_mon $dir a || return 1
-
- local root=host1
-
- generate_manipulated_rules $dir
-
- ceph osd crush rule create-simple special_rule_simple $root osd firstn || return 1
-
- ceph osd crush rule dump
- #show special_rule_simple has same rule_id and ruleset_id
- check_ruleset_id_match_rule_id special_rule_simple || return 1
-}
-
-function TEST_add_ruleset_failed() {
- local dir=$1
-
- run_mon $dir a || return 1
-
- local root=host1
-
- ceph osd crush add-bucket $root host
- ceph osd crush rule create-simple test_rule1 $root osd firstn || return 1
- ceph osd crush rule create-simple test_rule2 $root osd firstn || return 1
- ceph osd getcrushmap > $dir/crushmap || return 1
- crushtool --decompile $dir/crushmap > $dir/crushmap.txt || return 1
- for i in $(seq 3 255)
- do
- cat <<EOF
-rule test_rule$i {
- ruleset $i
- type replicated
- min_size 1
- max_size 10
- step take $root
- step choose firstn 0 type osd
- step emit
-}
-EOF
- done >> $dir/crushmap.txt
- crushtool --compile $dir/crushmap.txt -o $dir/crushmap || return 1
- ceph osd setcrushmap -i $dir/crushmap || return 1
- ceph osd crush rule create-simple test_rule_nospace $root osd firstn 2>&1 | grep "Error ENOSPC" || return 1
-
-}
-
-function TEST_crush_rename_bucket() {
- local dir=$1
-
- run_mon $dir a || return 1
-
- ceph osd crush add-bucket host1 host
- ceph osd tree
- ! ceph osd tree | grep host2 || return 1
- ceph osd crush rename-bucket host1 host2 || return 1
- ceph osd tree
- ceph osd tree | grep host2 || return 1
- ceph osd crush rename-bucket host1 host2 || return 1 # idempotency
- ceph osd crush rename-bucket nonexistent something 2>&1 | grep "Error ENOENT" || return 1
-}
-
-function TEST_crush_reject_empty() {
- local dir=$1
- run_mon $dir a || return 1
- # should have at least one OSD
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
-
- local empty_map=$dir/empty_map
- :> $empty_map.txt
- crushtool -c $empty_map.txt -o $empty_map.map || return 1
- expect_failure $dir "Error EINVAL" \
- ceph osd setcrushmap -i $empty_map.map || return 1
-}
-
-main osd-crush "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/mon/osd-crush.sh"
-# End:
diff --git a/src/ceph/qa/standalone/mon/osd-erasure-code-profile.sh b/src/ceph/qa/standalone/mon/osd-erasure-code-profile.sh
deleted file mode 100755
index 5480612..0000000
--- a/src/ceph/qa/standalone/mon/osd-erasure-code-profile.sh
+++ /dev/null
@@ -1,229 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7220" # git grep '\<7220\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_set() {
- local dir=$1
- local id=$2
-
- run_mon $dir a || return 1
-
- local profile=myprofile
- #
- # no key=value pairs : use the default configuration
- #
- ceph osd erasure-code-profile set $profile 2>&1 || return 1
- ceph osd erasure-code-profile get $profile | \
- grep plugin=jerasure || return 1
- ceph osd erasure-code-profile rm $profile
- #
- # key=value pairs override the default
- #
- ceph osd erasure-code-profile set $profile \
- key=value plugin=isa || return 1
- ceph osd erasure-code-profile get $profile | \
- grep -e key=value -e plugin=isa || return 1
- #
- # --force is required to override an existing profile
- #
- ! ceph osd erasure-code-profile set $profile > $dir/out 2>&1 || return 1
- grep 'will not override' $dir/out || return 1
- ceph osd erasure-code-profile set $profile key=other --force || return 1
- ceph osd erasure-code-profile get $profile | \
- grep key=other || return 1
-
- ceph osd erasure-code-profile rm $profile # cleanup
-}
-
-function TEST_ls() {
- local dir=$1
- local id=$2
-
- run_mon $dir a || return 1
-
- local profile=myprofile
- ! ceph osd erasure-code-profile ls | grep $profile || return 1
- ceph osd erasure-code-profile set $profile 2>&1 || return 1
- ceph osd erasure-code-profile ls | grep $profile || return 1
- ceph --format xml osd erasure-code-profile ls | \
- grep "<profile>$profile</profile>" || return 1
-
- ceph osd erasure-code-profile rm $profile # cleanup
-}
-
-function TEST_rm() {
- local dir=$1
- local id=$2
-
- run_mon $dir a || return 1
-
- local profile=myprofile
- ceph osd erasure-code-profile set $profile 2>&1 || return 1
- ceph osd erasure-code-profile ls | grep $profile || return 1
- ceph osd erasure-code-profile rm $profile || return 1
- ! ceph osd erasure-code-profile ls | grep $profile || return 1
- ceph osd erasure-code-profile rm WRONG 2>&1 | \
- grep "WRONG does not exist" || return 1
-
- ceph osd erasure-code-profile set $profile || return 1
- create_pool poolname 12 12 erasure $profile || return 1
- ! ceph osd erasure-code-profile rm $profile > $dir/out 2>&1 || return 1
- grep "poolname.*using.*$profile" $dir/out || return 1
- ceph osd pool delete poolname poolname --yes-i-really-really-mean-it || return 1
- ceph osd erasure-code-profile rm $profile || return 1
-
- ceph osd erasure-code-profile rm $profile # cleanup
-}
-
-function TEST_get() {
- local dir=$1
- local id=$2
-
- run_mon $dir a || return 1
-
- local default_profile=default
- ceph osd erasure-code-profile get $default_profile | \
- grep plugin=jerasure || return 1
- ceph --format xml osd erasure-code-profile get $default_profile | \
- grep '<plugin>jerasure</plugin>' || return 1
- ! ceph osd erasure-code-profile get WRONG > $dir/out 2>&1 || return 1
- grep -q "unknown erasure code profile 'WRONG'" $dir/out || return 1
-}
-
-function TEST_set_idempotent() {
- local dir=$1
- local id=$2
-
- run_mon $dir a || return 1
- #
- # The default profile is set using a code path different from
- # ceph osd erasure-code-profile set: verify that it is idempotent,
- # as if it was using the same code path.
- #
- ceph osd erasure-code-profile set default k=2 m=1 2>&1 || return 1
- local profile
- #
- # Because plugin=jerasure is the default, it uses a slightly
- # different code path where defaults (m=1 for instance) are added
- # implicitly.
- #
- profile=profileidempotent1
- ! ceph osd erasure-code-profile ls | grep $profile || return 1
- ceph osd erasure-code-profile set $profile k=2 crush-failure-domain=osd 2>&1 || return 1
- ceph osd erasure-code-profile ls | grep $profile || return 1
- ceph osd erasure-code-profile set $profile k=2 crush-failure-domain=osd 2>&1 || return 1
- ceph osd erasure-code-profile rm $profile # cleanup
-
- #
- # In the general case the profile is exactly what is on
- #
- profile=profileidempotent2
- ! ceph osd erasure-code-profile ls | grep $profile || return 1
- ceph osd erasure-code-profile set $profile plugin=lrc k=4 m=2 l=3 crush-failure-domain=osd 2>&1 || return 1
- ceph osd erasure-code-profile ls | grep $profile || return 1
- ceph osd erasure-code-profile set $profile plugin=lrc k=4 m=2 l=3 crush-failure-domain=osd 2>&1 || return 1
- ceph osd erasure-code-profile rm $profile # cleanup
-}
-
-function TEST_format_invalid() {
- local dir=$1
-
- local profile=profile
- # osd_pool_default_erasure-code-profile is
- # valid JSON but not of the expected type
- run_mon $dir a \
- --osd_pool_default_erasure-code-profile 1 || return 1
- ! ceph osd erasure-code-profile set $profile > $dir/out 2>&1 || return 1
- cat $dir/out
- grep 'must be a JSON object' $dir/out || return 1
-}
-
-function TEST_format_json() {
- local dir=$1
-
- # osd_pool_default_erasure-code-profile is JSON
- expected='"plugin":"isa"'
- run_mon $dir a \
- --osd_pool_default_erasure-code-profile "{$expected}" || return 1
- ceph --format json osd erasure-code-profile get default | \
- grep "$expected" || return 1
-}
-
-function TEST_format_plain() {
- local dir=$1
-
- # osd_pool_default_erasure-code-profile is plain text
- expected='"plugin":"isa"'
- run_mon $dir a \
- --osd_pool_default_erasure-code-profile "plugin=isa" || return 1
- ceph --format json osd erasure-code-profile get default | \
- grep "$expected" || return 1
-}
-
-function TEST_profile_k_sanity() {
- local dir=$1
- local profile=profile-sanity
-
- run_mon $dir a || return 1
-
- expect_failure $dir 'k must be a multiple of (k + m) / l' \
- ceph osd erasure-code-profile set $profile \
- plugin=lrc \
- l=1 \
- k=1 \
- m=1 || return 1
-
- if erasure_code_plugin_exists isa ; then
- expect_failure $dir 'k=1 must be >= 2' \
- ceph osd erasure-code-profile set $profile \
- plugin=isa \
- k=1 \
- m=1 || return 1
- else
- echo "SKIP because plugin isa has not been built"
- fi
-
- expect_failure $dir 'k=1 must be >= 2' \
- ceph osd erasure-code-profile set $profile \
- plugin=jerasure \
- k=1 \
- m=1 || return 1
-}
-
-main osd-erasure-code-profile "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/mon/osd-erasure-code-profile.sh"
-# End:
diff --git a/src/ceph/qa/standalone/mon/osd-pool-create.sh b/src/ceph/qa/standalone/mon/osd-pool-create.sh
deleted file mode 100755
index 693165d..0000000
--- a/src/ceph/qa/standalone/mon/osd-pool-create.sh
+++ /dev/null
@@ -1,215 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2013, 2014 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7105" # git grep '\<7105\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-# Before http://tracker.ceph.com/issues/8307 the invalid profile was created
-function TEST_erasure_invalid_profile() {
- local dir=$1
- run_mon $dir a || return 1
- local poolname=pool_erasure
- local notaprofile=not-a-valid-erasure-code-profile
- ! ceph osd pool create $poolname 12 12 erasure $notaprofile || return 1
- ! ceph osd erasure-code-profile ls | grep $notaprofile || return 1
-}
-
-function TEST_erasure_crush_rule() {
- local dir=$1
- run_mon $dir a || return 1
- #
- # choose the crush ruleset used with an erasure coded pool
- #
- local crush_ruleset=myruleset
- ! ceph osd crush rule ls | grep $crush_ruleset || return 1
- ceph osd crush rule create-erasure $crush_ruleset
- ceph osd crush rule ls | grep $crush_ruleset
- local poolname
- poolname=pool_erasure1
- ! ceph --format json osd dump | grep '"crush_rule":1' || return 1
- ceph osd pool create $poolname 12 12 erasure default $crush_ruleset
- ceph --format json osd dump | grep '"crush_rule":1' || return 1
- #
- # a crush ruleset by the name of the pool is implicitly created
- #
- poolname=pool_erasure2
- ceph osd erasure-code-profile set myprofile
- ceph osd pool create $poolname 12 12 erasure myprofile
- ceph osd crush rule ls | grep $poolname || return 1
- #
- # a non existent crush ruleset given in argument is an error
- # http://tracker.ceph.com/issues/9304
- #
- poolname=pool_erasure3
- ! ceph osd pool create $poolname 12 12 erasure myprofile INVALIDRULESET || return 1
-}
-
-function TEST_erasure_code_profile_default() {
- local dir=$1
- run_mon $dir a || return 1
- ceph osd erasure-code-profile rm default || return 1
- ! ceph osd erasure-code-profile ls | grep default || return 1
- ceph osd pool create $poolname 12 12 erasure default
- ceph osd erasure-code-profile ls | grep default || return 1
-}
-
-function TEST_erasure_crush_stripe_unit() {
- local dir=$1
- # the default stripe unit is used to initialize the pool
- run_mon $dir a --public-addr $CEPH_MON
- stripe_unit=$(ceph-conf --show-config-value osd_pool_erasure_code_stripe_unit)
- eval local $(ceph osd erasure-code-profile get myprofile | grep k=)
- stripe_width = $((stripe_unit * k))
- ceph osd pool create pool_erasure 12 12 erasure
- ceph --format json osd dump | tee $dir/osd.json
- grep '"stripe_width":'$stripe_width $dir/osd.json > /dev/null || return 1
-}
-
-function TEST_erasure_crush_stripe_unit_padded() {
- local dir=$1
- # setting osd_pool_erasure_code_stripe_unit modifies the stripe_width
- # and it is padded as required by the default plugin
- profile+=" plugin=jerasure"
- profile+=" technique=reed_sol_van"
- k=4
- profile+=" k=$k"
- profile+=" m=2"
- actual_stripe_unit=2048
- desired_stripe_unit=$((actual_stripe_unit - 1))
- actual_stripe_width=$((actual_stripe_unit * k))
- run_mon $dir a \
- --osd_pool_erasure_code_stripe_unit $desired_stripe_unit \
- --osd_pool_default_erasure_code_profile "$profile" || return 1
- ceph osd pool create pool_erasure 12 12 erasure
- ceph osd dump | tee $dir/osd.json
- grep "stripe_width $actual_stripe_width" $dir/osd.json > /dev/null || return 1
-}
-
-function TEST_erasure_code_pool() {
- local dir=$1
- run_mon $dir a || return 1
- ceph --format json osd dump > $dir/osd.json
- local expected='"erasure_code_profile":"default"'
- ! grep "$expected" $dir/osd.json || return 1
- ceph osd pool create erasurecodes 12 12 erasure
- ceph --format json osd dump | tee $dir/osd.json
- grep "$expected" $dir/osd.json > /dev/null || return 1
-
- ceph osd pool create erasurecodes 12 12 erasure 2>&1 | \
- grep 'already exists' || return 1
- ceph osd pool create erasurecodes 12 12 2>&1 | \
- grep 'cannot change to type replicated' || return 1
-}
-
-function TEST_replicated_pool_with_ruleset() {
- local dir=$1
- run_mon $dir a
- local ruleset=ruleset0
- local root=host1
- ceph osd crush add-bucket $root host
- local failure_domain=osd
- local poolname=mypool
- ceph osd crush rule create-simple $ruleset $root $failure_domain || return 1
- ceph osd crush rule ls | grep $ruleset
- ceph osd pool create $poolname 12 12 replicated $ruleset || return 1
- rule_id=`ceph osd crush rule dump $ruleset | grep "rule_id" | awk -F[' ':,] '{print $4}'`
- ceph osd pool get $poolname crush_rule 2>&1 | \
- grep "crush_rule: $rule_id" || return 1
- #non-existent crush ruleset
- ceph osd pool create newpool 12 12 replicated non-existent 2>&1 | \
- grep "doesn't exist" || return 1
-}
-
-function TEST_erasure_code_pool_lrc() {
- local dir=$1
- run_mon $dir a || return 1
-
- ceph osd erasure-code-profile set LRCprofile \
- plugin=lrc \
- mapping=DD_ \
- layers='[ [ "DDc", "" ] ]' || return 1
-
- ceph --format json osd dump > $dir/osd.json
- local expected='"erasure_code_profile":"LRCprofile"'
- local poolname=erasurecodes
- ! grep "$expected" $dir/osd.json || return 1
- ceph osd pool create $poolname 12 12 erasure LRCprofile
- ceph --format json osd dump | tee $dir/osd.json
- grep "$expected" $dir/osd.json > /dev/null || return 1
- ceph osd crush rule ls | grep $poolname || return 1
-}
-
-function TEST_replicated_pool() {
- local dir=$1
- run_mon $dir a || return 1
- ceph osd pool create replicated 12 12 replicated replicated_rule || return 1
- ceph osd pool create replicated 12 12 replicated replicated_rule 2>&1 | \
- grep 'already exists' || return 1
- # default is replicated
- ceph osd pool create replicated1 12 12 || return 1
- # default is replicated, pgp_num = pg_num
- ceph osd pool create replicated2 12 || return 1
- ceph osd pool create replicated 12 12 erasure 2>&1 | \
- grep 'cannot change to type erasure' || return 1
-}
-
-function TEST_no_pool_delete() {
- local dir=$1
- run_mon $dir a || return 1
- ceph osd pool create foo 1 || return 1
- ceph tell mon.a injectargs -- --no-mon-allow-pool-delete || return 1
- ! ceph osd pool delete foo foo --yes-i-really-really-mean-it || return 1
- ceph tell mon.a injectargs -- --mon-allow-pool-delete || return 1
- ceph osd pool delete foo foo --yes-i-really-really-mean-it || return 1
-}
-
-function TEST_utf8_cli() {
- local dir=$1
- run_mon $dir a || return 1
- # Hopefully it's safe to include literal UTF-8 characters to test
- # the fix for http://tracker.ceph.com/issues/7387. If it turns out
- # to not be OK (when is the default encoding *not* UTF-8?), maybe
- # the character '黄' can be replaced with the escape $'\xe9\xbb\x84'
- ceph osd pool create 黄 16 || return 1
- ceph osd lspools 2>&1 | \
- grep "黄" || return 1
- ceph -f json-pretty osd dump | \
- python -c "import json; import sys; json.load(sys.stdin)" || return 1
- ceph osd pool delete 黄 黄 --yes-i-really-really-mean-it
-}
-
-main osd-pool-create "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/mon/osd-pool-create.sh"
-# End:
diff --git a/src/ceph/qa/standalone/mon/osd-pool-df.sh b/src/ceph/qa/standalone/mon/osd-pool-df.sh
deleted file mode 100755
index 3ed169d..0000000
--- a/src/ceph/qa/standalone/mon/osd-pool-df.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright (C) 2017 Tencent <contact@tencent.com>
-#
-# Author: Chang Liu <liuchang0812@gmail.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7113" # git grep '\<7113\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_ceph_df() {
- local dir=$1
- setup $dir || return 1
-
- run_mon $dir a || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- run_osd $dir 2 || return 1
- run_osd $dir 3 || return 1
- run_osd $dir 4 || return 1
- run_osd $dir 5 || return 1
- run_mgr $dir x || return 1
-
- profile+=" plugin=jerasure"
- profile+=" technique=reed_sol_van"
- profile+=" k=4"
- profile+=" m=2"
- profile+=" crush-failure-domain=osd"
-
- ceph osd erasure-code-profile set ec42profile ${profile}
-
- local rep_poolname=testcephdf_replicate
- local ec_poolname=testcephdf_erasurecode
- create_pool $rep_poolname 6 6 replicated
- create_pool $ec_poolname 6 6 erasure ec42profile
-
- local global_avail=`ceph df -f json | jq '.stats.total_avail_bytes'`
- local rep_avail=`ceph df -f json | jq '.pools | map(select(.name == "$rep_poolname"))[0].stats.max_avail'`
- local ec_avail=`ceph df -f json | jq '.pools | map(select(.name == "$ec_poolname"))[0].stats.max_avail'`
-
- echo "${global_avail} >= ${rep_avail}*3" | bc || return 1
- echo "${global_avail} >= ${ec_avail}*1.5" | bc || return 1
-
- ceph osd pool delete $rep_poolname $rep_poolname --yes-i-really-really-mean-it
- ceph osd pool delete $ec_poolname $ec_poolname --yes-i-really-really-mean-it
- ceph osd erasure-code-profile rm ec42profile
- teardown $dir || return 1
-}
-
-main osd-pool-df "$@"
diff --git a/src/ceph/qa/standalone/mon/test_pool_quota.sh b/src/ceph/qa/standalone/mon/test_pool_quota.sh
deleted file mode 100755
index 7ea6ae0..0000000
--- a/src/ceph/qa/standalone/mon/test_pool_quota.sh
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/bin/bash
-
-#
-# Generic pool quota test
-#
-
-# Includes
-
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:17108" # git grep '\<17108\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- $func $dir || return 1
- done
-}
-
-function TEST_pool_quota() {
- local dir=$1
- setup $dir || return 1
-
- run_mon $dir a || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- run_osd $dir 2 || return 1
-
- local poolname=testquota
- create_pool $poolname 20
- local objects=`ceph df detail | grep -w $poolname|awk '{print $3}'`
- local bytes=`ceph df detail | grep -w $poolname|awk '{print $4}'`
-
- echo $objects
- echo $bytes
- if [ $objects != 'N/A' ] || [ $bytes != 'N/A' ] ;
- then
- return 1
- fi
-
- ceph osd pool set-quota $poolname max_objects 1000
- ceph osd pool set-quota $poolname max_bytes 1024
-
- objects=`ceph df detail | grep -w $poolname|awk '{print $3}'`
- bytes=`ceph df detail | grep -w $poolname|awk '{print $4}'`
-
- if [ $objects != '1000' ] || [ $bytes != '1024' ] ;
- then
- return 1
- fi
-
- ceph osd pool delete $poolname $poolname --yes-i-really-really-mean-it
- teardown $dir || return 1
-}
-
-main testpoolquota
diff --git a/src/ceph/qa/standalone/osd/osd-bench.sh b/src/ceph/qa/standalone/osd/osd-bench.sh
deleted file mode 100755
index 59a6f8d..0000000
--- a/src/ceph/qa/standalone/osd/osd-bench.sh
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7106" # git grep '\<7106\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_bench() {
- local dir=$1
-
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
-
- local osd_bench_small_size_max_iops=$(CEPH_ARGS='' ceph-conf \
- --show-config-value osd_bench_small_size_max_iops)
- local osd_bench_large_size_max_throughput=$(CEPH_ARGS='' ceph-conf \
- --show-config-value osd_bench_large_size_max_throughput)
- local osd_bench_max_block_size=$(CEPH_ARGS='' ceph-conf \
- --show-config-value osd_bench_max_block_size)
- local osd_bench_duration=$(CEPH_ARGS='' ceph-conf \
- --show-config-value osd_bench_duration)
-
- #
- # block size too high
- #
- expect_failure $dir osd_bench_max_block_size \
- ceph tell osd.0 bench 1024 $((osd_bench_max_block_size + 1)) || return 1
-
- #
- # count too high for small (< 1MB) block sizes
- #
- local bsize=1024
- local max_count=$(($bsize * $osd_bench_duration * $osd_bench_small_size_max_iops))
- expect_failure $dir bench_small_size_max_iops \
- ceph tell osd.0 bench $(($max_count + 1)) $bsize || return 1
-
- #
- # count too high for large (>= 1MB) block sizes
- #
- local bsize=$((1024 * 1024 + 1))
- local max_count=$(($osd_bench_large_size_max_throughput * $osd_bench_duration))
- expect_failure $dir osd_bench_large_size_max_throughput \
- ceph tell osd.0 bench $(($max_count + 1)) $bsize || return 1
-
- #
- # default values should work
- #
- ceph tell osd.0 bench || return 1
-
- #
- # test object_size < block_size
- ceph tell osd.0 bench 10 14456 4444 3
- #
-
- #
- # test object_size < block_size & object_size = 0(default value)
- #
- ceph tell osd.0 bench 1 14456
-}
-
-main osd-bench "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/osd/osd-bench.sh"
-# End:
diff --git a/src/ceph/qa/standalone/osd/osd-config.sh b/src/ceph/qa/standalone/osd/osd-config.sh
deleted file mode 100755
index d2dfe99..0000000
--- a/src/ceph/qa/standalone/osd/osd-config.sh
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7100" # git grep '\<7100\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_config_init() {
- local dir=$1
-
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- local advance=1000
- local stale=1000
- local cache=500
- run_osd $dir 0 \
- --osd-map-max-advance $advance \
- --osd-map-cache-size $cache \
- --osd-pg-epoch-persisted-max-stale $stale \
- || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log flush || return 1
- grep 'is not > osd_map_max_advance' $dir/osd.0.log || return 1
- grep 'is not > osd_pg_epoch_persisted_max_stale' $dir/osd.0.log || return 1
-}
-
-function TEST_config_track() {
- local dir=$1
-
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
-
- local osd_map_cache_size=$(CEPH_ARGS='' ceph-conf \
- --show-config-value osd_map_cache_size)
- local osd_map_max_advance=$(CEPH_ARGS='' ceph-conf \
- --show-config-value osd_map_max_advance)
- local osd_pg_epoch_persisted_max_stale=$(CEPH_ARGS='' ceph-conf \
- --show-config-value osd_pg_epoch_persisted_max_stale)
- #
- # lower cache_size under max_advance to trigger the warning
- #
- ! grep 'is not > osd_map_max_advance' $dir/osd.0.log || return 1
- local cache=$(($osd_map_max_advance / 2))
- ceph tell osd.0 injectargs "--osd-map-cache-size $cache" || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log flush || return 1
- grep 'is not > osd_map_max_advance' $dir/osd.0.log || return 1
- rm $dir/osd.0.log
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log reopen || return 1
-
- #
- # reset cache_size to the default and assert that it does not trigger the warning
- #
- ! grep 'is not > osd_map_max_advance' $dir/osd.0.log || return 1
- local cache=$osd_map_cache_size
- ceph tell osd.0 injectargs "--osd-map-cache-size $cache" || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log flush || return 1
- ! grep 'is not > osd_map_max_advance' $dir/osd.0.log || return 1
- rm $dir/osd.0.log
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log reopen || return 1
-
- #
- # increase the osd_map_max_advance above the default cache_size
- #
- ! grep 'is not > osd_map_max_advance' $dir/osd.0.log || return 1
- local advance=$(($osd_map_cache_size * 2))
- ceph tell osd.0 injectargs "--osd-map-max-advance $advance" || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log flush || return 1
- grep 'is not > osd_map_max_advance' $dir/osd.0.log || return 1
- rm $dir/osd.0.log
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log reopen || return 1
-
- #
- # increase the osd_pg_epoch_persisted_max_stale above the default cache_size
- #
- ! grep 'is not > osd_pg_epoch_persisted_max_stale' $dir/osd.0.log || return 1
- local stale=$(($osd_map_cache_size * 2))
- ceph tell osd.0 injectargs "--osd-pg-epoch-persisted-max-stale $stale" || return 1
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log flush || return 1
- grep 'is not > osd_pg_epoch_persisted_max_stale' $dir/osd.0.log || return 1
- rm $dir/osd.0.log
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.0) log reopen || return 1
-}
-
-main osd-config "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/osd/osd-config.sh"
-# End:
diff --git a/src/ceph/qa/standalone/osd/osd-copy-from.sh b/src/ceph/qa/standalone/osd/osd-copy-from.sh
deleted file mode 100755
index 3dcb0a8..0000000
--- a/src/ceph/qa/standalone/osd/osd-copy-from.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>
-# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-# Author: Sage Weil <sage@redhat.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7111" # git grep '\<7111\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_copy_from() {
- local dir=$1
-
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- create_rbd_pool || return 1
-
- # success
- rados -p rbd put foo $(which rados)
- rados -p rbd cp foo foo2
- rados -p rbd stat foo2
-
- # failure
- ceph tell osd.\* injectargs -- --osd-debug-inject-copyfrom-error
- ! rados -p rbd cp foo foo3
- ! rados -p rbd stat foo3
-
- # success again
- ceph tell osd.\* injectargs -- --no-osd-debug-inject-copyfrom-error
- ! rados -p rbd cp foo foo3
- rados -p rbd stat foo3
-}
-
-main osd-copy-from "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/osd/osd-bench.sh"
-# End:
diff --git a/src/ceph/qa/standalone/osd/osd-dup.sh b/src/ceph/qa/standalone/osd/osd-dup.sh
deleted file mode 100755
index bcb0fdc..0000000
--- a/src/ceph/qa/standalone/osd/osd-dup.sh
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/bin/bash
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-[ `uname` = FreeBSD ] && exit 0
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7146" # git grep '\<7146\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
- # avoid running out of fds in rados bench
- CEPH_ARGS+="--filestore_wbthrottle_xfs_ios_hard_limit=900 "
- CEPH_ARGS+="--filestore_wbthrottle_btrfs_ios_hard_limit=900 "
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_filestore_to_bluestore() {
- local dir=$1
-
- local flimit=$(ulimit -n)
- if [ $flimit -lt 1536 ]; then
- echo "Low open file limit ($flimit), test may fail. Increase to 1536 or higher and retry if that happens."
- fi
-
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- osd_pid=$(cat $dir/osd.0.pid)
- run_osd $dir 1 || return 1
- run_osd $dir 2 || return 1
-
- sleep 5
-
- create_pool foo 16
-
- # write some objects
- rados bench -p foo 10 write -b 4096 --no-cleanup || return 1
-
- # kill
- while kill $osd_pid; do sleep 1 ; done
- ceph osd down 0
-
- mv $dir/0 $dir/0.old || return 1
- mkdir $dir/0 || return 1
- ofsid=$(cat $dir/0.old/fsid)
- echo "osd fsid $ofsid"
- O=$CEPH_ARGS
- CEPH_ARGS+="--log-file $dir/cot.log --log-max-recent 0 "
- ceph-objectstore-tool --type bluestore --data-path $dir/0 --fsid $ofsid \
- --op mkfs || return 1
- ceph-objectstore-tool --data-path $dir/0.old --target-data-path $dir/0 \
- --op dup || return 1
- CEPH_ARGS=$O
-
- run_osd_bluestore $dir 0 || return 1
-
- while ! ceph osd stat | grep '3 up' ; do sleep 1 ; done
- ceph osd metadata 0 | grep bluestore || return 1
-
- ceph osd scrub 0
-
- # give it some time
- sleep 15
- # and make sure mon is sync'ed
- flush_pg_stats
-
- wait_for_clean || return 1
-}
-
-main osd-dup "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/osd/osd-dup.sh"
-# End:
diff --git a/src/ceph/qa/standalone/osd/osd-fast-mark-down.sh b/src/ceph/qa/standalone/osd/osd-fast-mark-down.sh
deleted file mode 100755
index 9f413d0..0000000
--- a/src/ceph/qa/standalone/osd/osd-fast-mark-down.sh
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2016 Piotr Dałek <git@predictor.org.pl>
-# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
-#
-# Author: Piotr Dałek <git@predictor.org.pl>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-MAX_PROPAGATION_TIME=30
-
-function run() {
- local dir=$1
- shift
- rm -f $dir/*.pid
- export CEPH_MON="127.0.0.1:7126" # git grep '\<7126\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- OLD_ARGS=$CEPH_ARGS
- CEPH_ARGS+="--osd-fast-fail-on-connection-refused=false "
- echo "Ensuring old behavior is there..."
- test_fast_kill $dir && (echo "OSDs died too early! Old behavior doesn't work." ; return 1)
-
- CEPH_ARGS=$OLD_ARGS"--osd-fast-fail-on-connection-refused=true "
- OLD_ARGS=$CEPH_ARGS
-
- CEPH_ARGS+="--ms_type=simple"
- echo "Testing simple msgr..."
- test_fast_kill $dir || return 1
-
- CEPH_ARGS=$OLD_ARGS"--ms_type=async"
- echo "Testing async msgr..."
- test_fast_kill $dir || return 1
-
- return 0
-
-}
-
-function test_fast_kill() {
- # create cluster with 3 osds
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=3 || return 1
- run_mgr $dir x || return 1
- for oi in {0..2}; do
- run_osd $dir $oi || return 1
- pids[$oi]=$(cat $dir/osd.$oi.pid)
- done
-
- create_rbd_pool || return 1
-
- # make some objects so osds to ensure connectivity between osds
- rados -p rbd bench 10 write -b 4096 --max-objects 128 --no-cleanup
- sleep 1
-
- killid=0
- previd=0
-
- # kill random osd and see if after max MAX_PROPAGATION_TIME, the osd count decreased.
- for i in {1..2}; do
- while [ $killid -eq $previd ]; do
- killid=${pids[$RANDOM%${#pids[@]}]}
- done
- previd=$killid
-
- kill -9 $killid
- time_left=$MAX_PROPAGATION_TIME
- down_osds=0
-
- while [ $time_left -gt 0 ]; do
- sleep 1
- time_left=$[$time_left - 1];
-
- grep -m 1 -c -F "ms_handle_refused" $dir/osd.*.log > /dev/null
- if [ $? -ne 0 ]; then
- continue
- fi
-
- down_osds=$(ceph osd tree | grep -c down)
- if [ $down_osds -lt $i ]; then
- # osds not marked down yet, try again in a second
- continue
- elif [ $down_osds -gt $i ]; then
- echo Too many \($down_osds\) osds died!
- return 1
- else
- break
- fi
- done
-
- if [ $down_osds -lt $i ]; then
- echo Killed the OSD, yet it is not marked down
- ceph osd tree
- return 1
- fi
- done
- pkill -SIGTERM rados
- teardown $dir || return 1
-}
-
-main osd-fast-mark-down "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/osd/osd-fast-mark-down.sh"
-# End:
diff --git a/src/ceph/qa/standalone/osd/osd-markdown.sh b/src/ceph/qa/standalone/osd/osd-markdown.sh
deleted file mode 100755
index b3c800c..0000000
--- a/src/ceph/qa/standalone/osd/osd-markdown.sh
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2015 Intel <contact@intel.com.com>
-# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
-#
-# Author: Xiaoxi Chen <xiaoxi.chen@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7108" # git grep '\<7108\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function markdown_N_impl() {
- markdown_times=$1
- total_time=$2
- sleeptime=$3
- for i in `seq 1 $markdown_times`
- do
- # check the OSD is UP
- ceph osd tree
- ceph osd tree | grep osd.0 |grep up || return 1
- # mark the OSD down.
- ceph osd down 0
- sleep $sleeptime
- done
-}
-
-
-function TEST_markdown_exceed_maxdown_count() {
- local dir=$1
-
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- run_osd $dir 2 || return 1
- # 3+1 times within 300s, osd should stay dead on the 4th time
- local count=3
- local sleeptime=10
- local period=300
- ceph tell osd.0 injectargs '--osd_max_markdown_count '$count'' || return 1
- ceph tell osd.0 injectargs '--osd_max_markdown_period '$period'' || return 1
-
- markdown_N_impl $(($count+1)) $period $sleeptime
- # down N+1 times ,the osd.0 shoud die
- ceph osd tree | grep down | grep osd.0 || return 1
-}
-
-function TEST_markdown_boot() {
- local dir=$1
-
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- run_osd $dir 2 || return 1
-
- # 3 times within 120s, should stay up
- local count=3
- local sleeptime=10
- local period=120
- ceph tell osd.0 injectargs '--osd_max_markdown_count '$count'' || return 1
- ceph tell osd.0 injectargs '--osd_max_markdown_period '$period'' || return 1
-
- markdown_N_impl $count $period $sleeptime
- #down N times, osd.0 should be up
- sleep 15 # give osd plenty of time to notice and come back up
- ceph osd tree | grep up | grep osd.0 || return 1
-}
-
-function TEST_markdown_boot_exceed_time() {
- local dir=$1
-
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- run_osd $dir 2 || return 1
-
-
- # 3+1 times, but over 40s, > 20s, so should stay up
- local count=3
- local period=20
- local sleeptime=10
- ceph tell osd.0 injectargs '--osd_max_markdown_count '$count'' || return 1
- ceph tell osd.0 injectargs '--osd_max_markdown_period '$period'' || return 1
-
- markdown_N_impl $(($count+1)) $period $sleeptime
- sleep 15 # give osd plenty of time to notice and come back up
- ceph osd tree | grep up | grep osd.0 || return 1
-}
-
-main osd-markdown "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/osd/osd-bench.sh"
-# End:
diff --git a/src/ceph/qa/standalone/osd/osd-reactivate.sh b/src/ceph/qa/standalone/osd/osd-reactivate.sh
deleted file mode 100755
index ddeee95..0000000
--- a/src/ceph/qa/standalone/osd/osd-reactivate.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/bash
-#
-# Author: Vicente Cheng <freeze.bilsted@gmail.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7122" # git grep '\<7122\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_reactivate() {
- local dir=$1
-
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
-
- kill_daemons $dir TERM osd || return 1
-
- ready_path=$dir"/0/ready"
- activate_path=$dir"/0/active"
- # trigger mkfs again
- rm -rf $ready_path $activate_path
- activate_osd $dir 0 || return 1
-
-}
-
-main osd-reactivate "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/osd/osd-reactivate.sh"
-# End:
diff --git a/src/ceph/qa/standalone/osd/osd-reuse-id.sh b/src/ceph/qa/standalone/osd/osd-reuse-id.sh
deleted file mode 100755
index 807c0ab..0000000
--- a/src/ceph/qa/standalone/osd/osd-reuse-id.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#! /bin/bash
-#
-# Copyright (C) 2015 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7123" # git grep '\<7123\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- $func $dir || return 1
- done
-}
-
-function TEST_reuse_id() {
- local dir=$1
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
- destroy_osd $dir 1 || return 1
- run_osd $dir 1 || return 1
-}
-
-main osd-reuse-id "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && test/osd/osd-reuse-id.sh"
-# End:
diff --git a/src/ceph/qa/standalone/scrub/osd-recovery-scrub.sh b/src/ceph/qa/standalone/scrub/osd-recovery-scrub.sh
deleted file mode 100755
index ef9a331..0000000
--- a/src/ceph/qa/standalone/scrub/osd-recovery-scrub.sh
+++ /dev/null
@@ -1,129 +0,0 @@
-#! /bin/bash
-#
-# Copyright (C) 2017 Red Hat <contact@redhat.com>
-#
-# Author: David Zafman <dzafman@redhat.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7124" # git grep '\<7124\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- $func $dir || return 1
- done
-}
-
-function TEST_recovery_scrub() {
- local dir=$1
- local poolname=test
-
- TESTDATA="testdata.$$"
- OSDS=8
- PGS=32
- OBJECTS=4
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- for osd in $(seq 0 $(expr $OSDS - 1))
- do
- run_osd $dir $osd || return 1
- done
-
- # Create a pool with $PGS pgs
- create_pool $poolname $PGS $PGS
- wait_for_clean || return 1
- poolid=$(ceph osd dump | grep "^pool.*[']test[']" | awk '{ print $2 }')
-
- dd if=/dev/urandom of=$TESTDATA bs=1M count=50
- for i in $(seq 1 $OBJECTS)
- do
- rados -p $poolname put obj${i} $TESTDATA
- done
- rm -f $TESTDATA
-
- ceph osd pool set $poolname size 4
-
- pids=""
- for pg in $(seq 0 $(expr $PGS - 1))
- do
- run_in_background pids pg_scrub $poolid.$(echo "{ obase=16; $pg }" | bc | tr '[:upper:]' '[:lower:]')
- done
- ceph pg dump pgs
- wait_background pids
- return_code=$?
- if [ $return_code -ne 0 ]; then return $return_code; fi
-
- ERRORS=0
- pidfile=$(find $dir 2>/dev/null | grep $name_prefix'[^/]*\.pid')
- pid=$(cat $pidfile)
- if ! kill -0 $pid
- then
- echo "OSD crash occurred"
- tail -100 $dir/osd.0.log
- ERRORS=$(expr $ERRORS + 1)
- fi
-
- kill_daemons $dir || return 1
-
- declare -a err_strings
- err_strings[0]="not scheduling scrubs due to active recovery"
- # Test with these two strings after disabled check in OSD::sched_scrub()
- #err_strings[0]="handle_scrub_reserve_request: failed to reserve remotely"
- #err_strings[1]="sched_scrub: failed to reserve locally"
-
- for osd in $(seq 0 $(expr $OSDS - 1))
- do
- grep "failed to reserve\|not scheduling scrubs" $dir/osd.${osd}.log
- done
- for err_string in "${err_strings[@]}"
- do
- found=false
- for osd in $(seq 0 $(expr $OSDS - 1))
- do
- if grep "$err_string" $dir/osd.${osd}.log > /dev/null;
- then
- found=true
- fi
- done
- if [ "$found" = "false" ]; then
- echo "Missing log message '$err_string'"
- ERRORS=$(expr $ERRORS + 1)
- fi
- done
-
- teardown $dir || return 1
-
- if [ $ERRORS != "0" ];
- then
- echo "TEST FAILED WITH $ERRORS ERRORS"
- return 1
- fi
-
- echo "TEST PASSED"
- return 0
-}
-
-main osd-recovery-scrub "$@"
-
-# Local Variables:
-# compile-command: "cd build ; make -j4 && \
-# ../qa/run-standalone.sh osd-recovery-scrub.sh"
diff --git a/src/ceph/qa/standalone/scrub/osd-scrub-repair.sh b/src/ceph/qa/standalone/scrub/osd-scrub-repair.sh
deleted file mode 100755
index 2aaaebd..0000000
--- a/src/ceph/qa/standalone/scrub/osd-scrub-repair.sh
+++ /dev/null
@@ -1,2826 +0,0 @@
-#!/bin/bash -x
-#
-# Copyright (C) 2014 Red Hat <contact@redhat.com>
-#
-# Author: Loic Dachary <loic@dachary.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-if [ `uname` = FreeBSD ]; then
- # erasure coding overwrites are only tested on Bluestore
- # erasure coding on filestore is unsafe
- # http://docs.ceph.com/docs/master/rados/operations/erasure-code/#erasure-coding-with-overwrites
- use_ec_overwrite=false
-else
- use_ec_overwrite=true
-fi
-
-# Test development and debugging
-# Set to "yes" in order to ignore diff errors and save results to update test
-getjson="no"
-
-# Ignore the epoch and filter out the attr '_' value because it has date information and won't match
-if [ "$(jq --version 2>&1 | awk '{ print $3}')" = "1.3" ]; then # Not sure all versions that apply here
- jqfilter='.inconsistents | (.[].shards[].attrs[] | select(.name == "_") | .value) |= "----Stripped-by-test----"'
-else
- jqfilter='.inconsistents | (.[].shards[].attrs[]? | select(.name == "_") | .value) |= "----Stripped-by-test----"'
-fi
-sortkeys='import json; import sys ; JSON=sys.stdin.read() ; ud = json.loads(JSON) ; print json.dumps(ud, sort_keys=True, indent=2)'
-
-# Remove items are not consistent across runs, the pg interval and client
-sedfilter='s/\([ ]*\"\(selected_\)*object_info\":.*head[(]\)[^[:space:]]* [^[:space:]]* \(.*\)/\1\3/'
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7107" # git grep '\<7107\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- $func $dir || return 1
- done
-}
-
-function add_something() {
- local dir=$1
- local poolname=$2
- local obj=${3:-SOMETHING}
- local scrub=${4:-noscrub}
-
- if [ "$scrub" = "noscrub" ];
- then
- ceph osd set noscrub || return 1
- ceph osd set nodeep-scrub || return 1
- else
- ceph osd unset noscrub || return 1
- ceph osd unset nodeep-scrub || return 1
- fi
-
- local payload=ABCDEF
- echo $payload > $dir/ORIGINAL
- rados --pool $poolname put $obj $dir/ORIGINAL || return 1
-}
-
-#
-# Corrupt one copy of a replicated pool
-#
-function TEST_corrupt_and_repair_replicated() {
- local dir=$1
- local poolname=rbd
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=2 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
-
- add_something $dir $poolname || return 1
- corrupt_and_repair_one $dir $poolname $(get_not_primary $poolname SOMETHING) || return 1
- # Reproduces http://tracker.ceph.com/issues/8914
- corrupt_and_repair_one $dir $poolname $(get_primary $poolname SOMETHING) || return 1
-
- teardown $dir || return 1
-}
-
-function corrupt_and_repair_two() {
- local dir=$1
- local poolname=$2
- local first=$3
- local second=$4
-
- #
- # 1) remove the corresponding file from the OSDs
- #
- pids=""
- run_in_background pids objectstore_tool $dir $first SOMETHING remove
- run_in_background pids objectstore_tool $dir $second SOMETHING remove
- wait_background pids
- return_code=$?
- if [ $return_code -ne 0 ]; then return $return_code; fi
-
- #
- # 2) repair the PG
- #
- local pg=$(get_pg $poolname SOMETHING)
- repair $pg
- #
- # 3) The files must be back
- #
- pids=""
- run_in_background pids objectstore_tool $dir $first SOMETHING list-attrs
- run_in_background pids objectstore_tool $dir $second SOMETHING list-attrs
- wait_background pids
- return_code=$?
- if [ $return_code -ne 0 ]; then return $return_code; fi
-
- rados --pool $poolname get SOMETHING $dir/COPY || return 1
- diff $dir/ORIGINAL $dir/COPY || return 1
-}
-
-#
-# 1) add an object
-# 2) remove the corresponding file from a designated OSD
-# 3) repair the PG
-# 4) check that the file has been restored in the designated OSD
-#
-function corrupt_and_repair_one() {
- local dir=$1
- local poolname=$2
- local osd=$3
-
- #
- # 1) remove the corresponding file from the OSD
- #
- objectstore_tool $dir $osd SOMETHING remove || return 1
- #
- # 2) repair the PG
- #
- local pg=$(get_pg $poolname SOMETHING)
- repair $pg
- #
- # 3) The file must be back
- #
- objectstore_tool $dir $osd SOMETHING list-attrs || return 1
- rados --pool $poolname get SOMETHING $dir/COPY || return 1
- diff $dir/ORIGINAL $dir/COPY || return 1
-}
-
-function corrupt_and_repair_erasure_coded() {
- local dir=$1
- local poolname=$2
-
- add_something $dir $poolname || return 1
-
- local primary=$(get_primary $poolname SOMETHING)
- local -a osds=($(get_osds $poolname SOMETHING | sed -e "s/$primary//"))
- local not_primary_first=${osds[0]}
- local not_primary_second=${osds[1]}
-
- # Reproduces http://tracker.ceph.com/issues/10017
- corrupt_and_repair_one $dir $poolname $primary || return 1
- # Reproduces http://tracker.ceph.com/issues/10409
- corrupt_and_repair_one $dir $poolname $not_primary_first || return 1
- corrupt_and_repair_two $dir $poolname $not_primary_first $not_primary_second || return 1
- corrupt_and_repair_two $dir $poolname $primary $not_primary_first || return 1
-
-}
-
-function create_ec_pool() {
- local pool_name=$1
- local allow_overwrites=$2
-
- ceph osd erasure-code-profile set myprofile crush-failure-domain=osd $3 $4 $5 $6 $7 || return 1
-
- create_pool "$poolname" 1 1 erasure myprofile || return 1
-
- if [ "$allow_overwrites" = "true" ]; then
- ceph osd pool set "$poolname" allow_ec_overwrites true || return 1
- fi
-
- wait_for_clean || return 1
- return 0
-}
-
-function auto_repair_erasure_coded() {
- local dir=$1
- local allow_overwrites=$2
- local poolname=ecpool
-
- # Launch a cluster with 5 seconds scrub interval
- setup $dir || return 1
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- local ceph_osd_args="--osd-scrub-auto-repair=true \
- --osd-deep-scrub-interval=5 \
- --osd-scrub-max-interval=5 \
- --osd-scrub-min-interval=5 \
- --osd-scrub-interval-randomize-ratio=0"
- for id in $(seq 0 2) ; do
- if [ "$allow_overwrites" = "true" ]; then
- run_osd_bluestore $dir $id $ceph_osd_args || return 1
- else
- run_osd $dir $id $ceph_osd_args || return 1
- fi
- done
- create_rbd_pool || return 1
- wait_for_clean || return 1
-
- # Create an EC pool
- create_ec_pool $poolname $allow_overwrites k=2 m=1 || return 1
-
- # Put an object
- local payload=ABCDEF
- echo $payload > $dir/ORIGINAL
- rados --pool $poolname put SOMETHING $dir/ORIGINAL || return 1
-
- # Remove the object from one shard physically
- # Restarted osd get $ceph_osd_args passed
- objectstore_tool $dir $(get_not_primary $poolname SOMETHING) SOMETHING remove || return 1
- # Wait for auto repair
- local pgid=$(get_pg $poolname SOMETHING)
- wait_for_scrub $pgid "$(get_last_scrub_stamp $pgid)"
- wait_for_clean || return 1
- # Verify - the file should be back
- # Restarted osd get $ceph_osd_args passed
- objectstore_tool $dir $(get_not_primary $poolname SOMETHING) SOMETHING list-attrs || return 1
- rados --pool $poolname get SOMETHING $dir/COPY || return 1
- diff $dir/ORIGINAL $dir/COPY || return 1
-
- # Tear down
- teardown $dir || return 1
-}
-
-function TEST_auto_repair_erasure_coded_appends() {
- auto_repair_erasure_coded $1 false
-}
-
-function TEST_auto_repair_erasure_coded_overwrites() {
- if [ "$use_ec_overwrite" = "true" ]; then
- auto_repair_erasure_coded $1 true
- fi
-}
-
-function corrupt_and_repair_jerasure() {
- local dir=$1
- local allow_overwrites=$2
- local poolname=ecpool
-
- setup $dir || return 1
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- for id in $(seq 0 3) ; do
- if [ "$allow_overwrites" = "true" ]; then
- run_osd_bluestore $dir $id || return 1
- else
- run_osd $dir $id || return 1
- fi
- done
- create_rbd_pool || return 1
- wait_for_clean || return 1
-
- create_ec_pool $poolname $allow_overwrites k=2 m=2 || return 1
- corrupt_and_repair_erasure_coded $dir $poolname || return 1
-
- teardown $dir || return 1
-}
-
-function TEST_corrupt_and_repair_jerasure_appends() {
- corrupt_and_repair_jerasure $1
-}
-
-function TEST_corrupt_and_repair_jerasure_overwrites() {
- if [ "$use_ec_overwrite" = "true" ]; then
- corrupt_and_repair_jerasure $1 true
- fi
-}
-
-function corrupt_and_repair_lrc() {
- local dir=$1
- local allow_overwrites=$2
- local poolname=ecpool
-
- setup $dir || return 1
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- for id in $(seq 0 9) ; do
- if [ "$allow_overwrites" = "true" ]; then
- run_osd_bluestore $dir $id || return 1
- else
- run_osd $dir $id || return 1
- fi
- done
- create_rbd_pool || return 1
- wait_for_clean || return 1
-
- create_ec_pool $poolname $allow_overwrites k=4 m=2 l=3 plugin=lrc || return 1
- corrupt_and_repair_erasure_coded $dir $poolname || return 1
-
- teardown $dir || return 1
-}
-
-function TEST_corrupt_and_repair_lrc_appends() {
- corrupt_and_repair_jerasure $1
-}
-
-function TEST_corrupt_and_repair_lrc_overwrites() {
- if [ "$use_ec_overwrite" = "true" ]; then
- corrupt_and_repair_jerasure $1 true
- fi
-}
-
-function unfound_erasure_coded() {
- local dir=$1
- local allow_overwrites=$2
- local poolname=ecpool
- local payload=ABCDEF
-
- setup $dir || return 1
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- for id in $(seq 0 3) ; do
- if [ "$allow_overwrites" = "true" ]; then
- run_osd_bluestore $dir $id || return 1
- else
- run_osd $dir $id || return 1
- fi
- done
- create_rbd_pool || return 1
- wait_for_clean || return 1
-
- create_ec_pool $poolname $allow_overwrites k=2 m=2 || return 1
-
- add_something $dir $poolname || return 1
-
- local primary=$(get_primary $poolname SOMETHING)
- local -a osds=($(get_osds $poolname SOMETHING | sed -e "s/$primary//"))
- local not_primary_first=${osds[0]}
- local not_primary_second=${osds[1]}
- local not_primary_third=${osds[2]}
-
- #
- # 1) remove the corresponding file from the OSDs
- #
- pids=""
- run_in_background pids objectstore_tool $dir $not_primary_first SOMETHING remove
- run_in_background pids objectstore_tool $dir $not_primary_second SOMETHING remove
- run_in_background pids objectstore_tool $dir $not_primary_third SOMETHING remove
- wait_background pids
- return_code=$?
- if [ $return_code -ne 0 ]; then return $return_code; fi
-
- #
- # 2) repair the PG
- #
- local pg=$(get_pg $poolname SOMETHING)
- repair $pg
- #
- # 3) check pg state
- #
- # it may take a bit to appear due to mon/mgr asynchrony
- for f in `seq 1 60`; do
- ceph -s | grep "1/1 objects unfound" && break
- sleep 1
- done
- ceph -s|grep "4 osds: 4 up, 4 in" || return 1
- ceph -s|grep "1/1 objects unfound" || return 1
-
- teardown $dir || return 1
-}
-
-function TEST_unfound_erasure_coded_appends() {
- unfound_erasure_coded $1
-}
-
-function TEST_unfound_erasure_coded_overwrites() {
- if [ "$use_ec_overwrite" = "true" ]; then
- unfound_erasure_coded $1 true
- fi
-}
-
-#
-# list_missing for EC pool
-#
-function list_missing_erasure_coded() {
- local dir=$1
- local allow_overwrites=$2
- local poolname=ecpool
-
- setup $dir || return 1
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- for id in $(seq 0 2) ; do
- if [ "$allow_overwrites" = "true" ]; then
- run_osd_bluestore $dir $id || return 1
- else
- run_osd $dir $id || return 1
- fi
- done
- create_rbd_pool || return 1
- wait_for_clean || return 1
-
- create_ec_pool $poolname $allow_overwrites k=2 m=1 || return 1
-
- # Put an object and remove the two shards (including primary)
- add_something $dir $poolname MOBJ0 || return 1
- local -a osds0=($(get_osds $poolname MOBJ0))
-
- # Put another object and remove two shards (excluding primary)
- add_something $dir $poolname MOBJ1 || return 1
- local -a osds1=($(get_osds $poolname MOBJ1))
-
- # Stop all osd daemons
- for id in $(seq 0 2) ; do
- kill_daemons $dir TERM osd.$id >&2 < /dev/null || return 1
- done
-
- id=${osds0[0]}
- ceph-objectstore-tool --data-path $dir/$id \
- MOBJ0 remove || return 1
- id=${osds0[1]}
- ceph-objectstore-tool --data-path $dir/$id \
- MOBJ0 remove || return 1
-
- id=${osds1[1]}
- ceph-objectstore-tool --data-path $dir/$id \
- MOBJ1 remove || return 1
- id=${osds1[2]}
- ceph-objectstore-tool --data-path $dir/$id \
- MOBJ1 remove || return 1
-
- for id in $(seq 0 2) ; do
- activate_osd $dir $id >&2 || return 1
- done
- create_rbd_pool || return 1
- wait_for_clean || return 1
-
- # Get get - both objects should in the same PG
- local pg=$(get_pg $poolname MOBJ0)
-
- # Repair the PG, which triggers the recovering,
- # and should mark the object as unfound
- repair $pg
-
- for i in $(seq 0 120) ; do
- [ $i -lt 60 ] || return 1
- matches=$(ceph pg $pg list_missing | egrep "MOBJ0|MOBJ1" | wc -l)
- [ $matches -eq 2 ] && break
- done
-
- teardown $dir || return 1
-}
-
-function TEST_list_missing_erasure_coded_appends() {
- list_missing_erasure_coded $1 false
-}
-
-function TEST_list_missing_erasure_coded_overwrites() {
- if [ "$use_ec_overwrite" = "true" ]; then
- list_missing_erasure_coded $1 true
- fi
-}
-
-#
-# Corrupt one copy of a replicated pool
-#
-function TEST_corrupt_scrub_replicated() {
- local dir=$1
- local poolname=csr_pool
- local total_objs=16
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=2 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
- run_osd $dir 1 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
-
- create_pool foo 1 || return 1
- create_pool $poolname 1 1 || return 1
- wait_for_clean || return 1
-
- for i in $(seq 1 $total_objs) ; do
- objname=ROBJ${i}
- add_something $dir $poolname $objname || return 1
-
- rados --pool $poolname setomapheader $objname hdr-$objname || return 1
- rados --pool $poolname setomapval $objname key-$objname val-$objname || return 1
- done
-
- local pg=$(get_pg $poolname ROBJ0)
-
- # Compute an old omap digest and save oi
- CEPH_ARGS='' ceph daemon $(get_asok_path osd.0) \
- config set osd_deep_scrub_update_digest_min_age 0
- CEPH_ARGS='' ceph daemon $(get_asok_path osd.1) \
- config set osd_deep_scrub_update_digest_min_age 0
- pg_deep_scrub $pg
-
- for i in $(seq 1 $total_objs) ; do
- objname=ROBJ${i}
-
- # Alternate corruption between osd.0 and osd.1
- local osd=$(expr $i % 2)
-
- case $i in
- 1)
- # Size (deep scrub data_digest too)
- local payload=UVWXYZZZ
- echo $payload > $dir/CORRUPT
- objectstore_tool $dir $osd $objname set-bytes $dir/CORRUPT || return 1
- ;;
-
- 2)
- # digest (deep scrub only)
- local payload=UVWXYZ
- echo $payload > $dir/CORRUPT
- objectstore_tool $dir $osd $objname set-bytes $dir/CORRUPT || return 1
- ;;
-
- 3)
- # missing
- objectstore_tool $dir $osd $objname remove || return 1
- ;;
-
- 4)
- # Modify omap value (deep scrub only)
- objectstore_tool $dir $osd $objname set-omap key-$objname $dir/CORRUPT || return 1
- ;;
-
- 5)
- # Delete omap key (deep scrub only)
- objectstore_tool $dir $osd $objname rm-omap key-$objname || return 1
- ;;
-
- 6)
- # Add extra omap key (deep scrub only)
- echo extra > $dir/extra-val
- objectstore_tool $dir $osd $objname set-omap key2-$objname $dir/extra-val || return 1
- rm $dir/extra-val
- ;;
-
- 7)
- # Modify omap header (deep scrub only)
- echo -n newheader > $dir/hdr
- objectstore_tool $dir $osd $objname set-omaphdr $dir/hdr || return 1
- rm $dir/hdr
- ;;
-
- 8)
- rados --pool $poolname setxattr $objname key1-$objname val1-$objname || return 1
- rados --pool $poolname setxattr $objname key2-$objname val2-$objname || return 1
-
- # Break xattrs
- echo -n bad-val > $dir/bad-val
- objectstore_tool $dir $osd $objname set-attr _key1-$objname $dir/bad-val || return 1
- objectstore_tool $dir $osd $objname rm-attr _key2-$objname || return 1
- echo -n val3-$objname > $dir/newval
- objectstore_tool $dir $osd $objname set-attr _key3-$objname $dir/newval || return 1
- rm $dir/bad-val $dir/newval
- ;;
-
- 9)
- objectstore_tool $dir $osd $objname get-attr _ > $dir/robj9-oi
- echo -n D > $dir/change
- rados --pool $poolname put $objname $dir/change
- objectstore_tool $dir $osd $objname set-attr _ $dir/robj9-oi
- rm $dir/oi $dir/change
- ;;
-
- # ROBJ10 must be handled after digests are re-computed by a deep scrub below
- # ROBJ11 must be handled with config change before deep scrub
- # ROBJ12 must be handled with config change before scrubs
- # ROBJ13 must be handled before scrubs
-
- 14)
- echo -n bad-val > $dir/bad-val
- objectstore_tool $dir 0 $objname set-attr _ $dir/bad-val || return 1
- objectstore_tool $dir 1 $objname rm-attr _ || return 1
- rm $dir/bad-val
- ;;
-
- 15)
- objectstore_tool $dir $osd $objname rm-attr _ || return 1
- ;;
-
- 16)
- objectstore_tool $dir 0 $objname rm-attr snapset || return 1
- echo -n bad-val > $dir/bad-val
- objectstore_tool $dir 1 $objname set-attr snapset $dir/bad-val || return 1
-
- esac
- done
-
- local pg=$(get_pg $poolname ROBJ0)
-
- inject_eio rep data $poolname ROBJ11 $dir 0 || return 1 # shard 0 of [1, 0], osd.1
- inject_eio rep mdata $poolname ROBJ12 $dir 1 || return 1 # shard 1 of [1, 0], osd.0
- inject_eio rep mdata $poolname ROBJ13 $dir 1 || return 1 # shard 1 of [1, 0], osd.0
- inject_eio rep data $poolname ROBJ13 $dir 0 || return 1 # shard 0 of [1, 0], osd.1
-
- pg_scrub $pg
-
- rados list-inconsistent-pg $poolname > $dir/json || return 1
- # Check pg count
- test $(jq '. | length' $dir/json) = "1" || return 1
- # Check pgid
- test $(jq -r '.[0]' $dir/json) = $pg || return 1
-
- rados list-inconsistent-obj $pg > $dir/json || return 1
- # Get epoch for repair-get requests
- epoch=$(jq .epoch $dir/json)
-
- jq "$jqfilter" << EOF | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/checkcsjson
-{
- "inconsistents": [
- {
- "shards": [
- {
- "size": 7,
- "errors": [],
- "osd": 0,
- "primary": false
- },
- {
- "size": 9,
- "errors": [
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:ce3f1d6a:::ROBJ1:head(47'54 osd.0.0:53 dirty|omap|data_digest|omap_digest s 7 uv 3 dd 2ddbf8f5 od f5fba2c6 alloc_hint [0 0 0])",
- "union_shard_errors": [
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "errors": [
- "size_mismatch"
- ],
- "object": {
- "version": 3,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ1"
- }
- },
- {
- "shards": [
- {
- "errors": [
- "stat_error"
- ],
- "osd": 0,
- "primary": false
- },
- {
- "size": 7,
- "errors": [],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:bc819597:::ROBJ12:head(47'52 osd.0.0:51 dirty|omap|data_digest|omap_digest s 7 uv 36 dd 2ddbf8f5 od 67f306a alloc_hint [0 0 0])",
- "union_shard_errors": [
- "stat_error"
- ],
- "errors": [],
- "object": {
- "version": 36,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ12"
- }
- },
- {
- "shards": [
- {
- "errors": [
- "stat_error"
- ],
- "osd": 0,
- "primary": false
- },
- {
- "size": 7,
- "errors": [],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:d60617f9:::ROBJ13:head(47'55 osd.0.0:54 dirty|omap|data_digest|omap_digest s 7 uv 39 dd 2ddbf8f5 od 6441854d alloc_hint [0 0 0])",
- "union_shard_errors": [
- "stat_error"
- ],
- "errors": [],
- "object": {
- "version": 39,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ13"
- }
- },
- {
- "shards": [
- {
- "size": 7,
- "attrs": [
- {
- "Base64": false,
- "value": "",
- "name": "_"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "errors": [
- "oi_attr_corrupted"
- ],
- "osd": 0,
- "primary": false
- },
- {
- "size": 7,
- "attrs": [
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "errors": [
- "oi_attr_missing"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "union_shard_errors": [
- "oi_attr_missing",
- "oi_attr_corrupted"
- ],
- "errors": [],
- "object": {
- "version": 0,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ14"
- }
- },
- {
- "shards": [
- {
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "size": 7,
- "errors": [],
- "osd": 0,
- "primary": false
- },
- {
- "attrs": [
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "size": 7,
- "errors": [
- "oi_attr_missing"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:30259878:::ROBJ15:head(47'46 osd.0.0:45 dirty|omap|data_digest|omap_digest s 7 uv 45 dd 2ddbf8f5 od 2d2a4d6e alloc_hint [0 0 0])",
- "union_shard_errors": [
- "oi_attr_missing"
- ],
- "errors": [],
- "object": {
- "version": 45,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ15"
- }
- },
- {
- "errors": [],
- "object": {
- "locator": "",
- "name": "ROBJ16",
- "nspace": "",
- "snap": "head",
- "version": 0
- },
- "shards": [
- {
- "attrs": [
- {
- "Base64": true,
- "name": "_",
- "value": ""
- }
- ],
- "errors": [
- "ss_attr_missing"
- ],
- "osd": 0,
- "primary": false,
- "size": 7
- },
- {
- "attrs": [
- {
- "Base64": true,
- "name": "_",
- "value": ""
- },
- {
- "Base64": false,
- "name": "snapset",
- "value": "bad-val"
- }
- ],
- "errors": [
- "ss_attr_corrupted"
- ],
- "osd": 1,
- "primary": true,
- "size": 7
- }
- ],
- "union_shard_errors": [
- "ss_attr_missing",
- "ss_attr_corrupted"
- ]
- },
- {
- "shards": [
- {
- "size": 7,
- "errors": [],
- "osd": 0,
- "primary": false
- },
- {
- "errors": [
- "missing"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:f2a5b2a4:::ROBJ3:head(47'57 osd.0.0:56 dirty|omap|data_digest|omap_digest s 7 uv 9 dd 2ddbf8f5 od b35dfd alloc_hint [0 0 0])",
- "union_shard_errors": [
- "missing"
- ],
- "errors": [],
- "object": {
- "version": 9,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ3"
- }
- },
- {
- "shards": [
- {
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "bad-val",
- "name": "_key1-ROBJ8"
- },
- {
- "Base64": false,
- "value": "val3-ROBJ8",
- "name": "_key3-ROBJ8"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "size": 7,
- "errors": [],
- "osd": 0,
- "primary": false
- },
- {
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "val1-ROBJ8",
- "name": "_key1-ROBJ8"
- },
- {
- "Base64": false,
- "value": "val2-ROBJ8",
- "name": "_key2-ROBJ8"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "size": 7,
- "errors": [],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:86586531:::ROBJ8:head(82'62 client.4351.0:1 dirty|omap|data_digest|omap_digest s 7 uv 66 dd 2ddbf8f5 od d6be81dc alloc_hint [0 0 0])",
- "union_shard_errors": [],
- "errors": [
- "attr_value_mismatch",
- "attr_name_mismatch"
- ],
- "object": {
- "version": 66,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ8"
- }
- },
- {
- "shards": [
- {
- "object_info": "3:ffdb2004:::ROBJ9:head(102'63 client.4433.0:1 dirty|omap|data_digest|omap_digest s 1 uv 67 dd 2b63260d od 2eecc539 alloc_hint [0 0 0])",
- "size": 1,
- "errors": [],
- "osd": 0,
- "primary": false
- },
- {
- "object_info": "3:ffdb2004:::ROBJ9:head(47'60 osd.0.0:59 dirty|omap|data_digest|omap_digest s 7 uv 27 dd 2ddbf8f5 od 2eecc539 alloc_hint [0 0 0])",
- "size": 1,
- "errors": [
- "obj_size_oi_mismatch"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:ffdb2004:::ROBJ9:head(102'63 client.4433.0:1 dirty|omap|data_digest|omap_digest s 1 uv 67 dd 2b63260d od 2eecc539 alloc_hint [0 0 0])",
- "union_shard_errors": [
- "obj_size_oi_mismatch"
- ],
- "errors": [
- "object_info_inconsistency"
- ],
- "object": {
- "version": 67,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ9"
- }
- }
- ],
- "epoch": 0
-}
-EOF
-
- jq "$jqfilter" $dir/json | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/csjson
- diff ${DIFFCOLOPTS} $dir/checkcsjson $dir/csjson || test $getjson = "yes" || return 1
- if test $getjson = "yes"
- then
- jq '.' $dir/json > save1.json
- fi
-
- if which jsonschema > /dev/null;
- then
- jsonschema -i $dir/json $CEPH_ROOT/doc/rados/command/list-inconsistent-obj.json || return 1
- fi
-
- objname=ROBJ9
- # Change data and size again because digest was recomputed
- echo -n ZZZ > $dir/change
- rados --pool $poolname put $objname $dir/change
- # Set one to an even older value
- objectstore_tool $dir 0 $objname set-attr _ $dir/robj9-oi
- rm $dir/oi $dir/change
-
- objname=ROBJ10
- objectstore_tool $dir 1 $objname get-attr _ > $dir/oi
- rados --pool $poolname setomapval $objname key2-$objname val2-$objname
- objectstore_tool $dir 0 $objname set-attr _ $dir/oi
- objectstore_tool $dir 1 $objname set-attr _ $dir/oi
- rm $dir/oi
-
- inject_eio rep data $poolname ROBJ11 $dir 0 || return 1 # shard 0 of [1, 0], osd.1
- inject_eio rep mdata $poolname ROBJ12 $dir 1 || return 1 # shard 1 of [1, 0], osd.0
- inject_eio rep mdata $poolname ROBJ13 $dir 1 || return 1 # shard 1 of [1, 0], osd.0
- inject_eio rep data $poolname ROBJ13 $dir 0 || return 1 # shard 0 of [1, 0], osd.1
- pg_deep_scrub $pg
-
- rados list-inconsistent-pg $poolname > $dir/json || return 1
- # Check pg count
- test $(jq '. | length' $dir/json) = "1" || return 1
- # Check pgid
- test $(jq -r '.[0]' $dir/json) = $pg || return 1
-
- rados list-inconsistent-obj $pg > $dir/json || return 1
- # Get epoch for repair-get requests
- epoch=$(jq .epoch $dir/json)
-
- jq "$jqfilter" << EOF | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/checkcsjson
-{
- "inconsistents": [
- {
- "shards": [
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0xf5fba2c6",
- "size": 7,
- "errors": [],
- "osd": 0,
- "primary": false
- },
- {
- "data_digest": "0x2d4a11c2",
- "omap_digest": "0xf5fba2c6",
- "size": 9,
- "errors": [
- "data_digest_mismatch_oi",
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:ce3f1d6a:::ROBJ1:head(47'54 osd.0.0:53 dirty|omap|data_digest|omap_digest s 7 uv 3 dd 2ddbf8f5 od f5fba2c6 alloc_hint [0 0 0])",
- "union_shard_errors": [
- "data_digest_mismatch_oi",
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "errors": [
- "data_digest_mismatch",
- "size_mismatch"
- ],
- "object": {
- "version": 3,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ1"
- }
- },
- {
- "shards": [
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0xa8dd5adc",
- "size": 7,
- "errors": [
- "omap_digest_mismatch_oi"
- ],
- "osd": 0,
- "primary": false
- },
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0xa8dd5adc",
- "size": 7,
- "errors": [
- "omap_digest_mismatch_oi"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:b1f19cbd:::ROBJ10:head(47'51 osd.0.0:50 dirty|omap|data_digest|omap_digest s 7 uv 30 dd 2ddbf8f5 od c2025a24 alloc_hint [0 0 0])",
- "union_shard_errors": [
- "omap_digest_mismatch_oi"
- ],
- "errors": [],
- "object": {
- "version": 30,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ10"
- }
- },
- {
- "shards": [
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0xa03cef03",
- "size": 7,
- "errors": [],
- "osd": 0,
- "primary": false
- },
- {
- "size": 7,
- "errors": [
- "read_error"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:87abbf36:::ROBJ11:head(47'48 osd.0.0:47 dirty|omap|data_digest|omap_digest s 7 uv 33 dd 2ddbf8f5 od a03cef03 alloc_hint [0 0 0])",
- "union_shard_errors": [
- "read_error"
- ],
- "errors": [],
- "object": {
- "version": 33,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ11"
- }
- },
- {
- "shards": [
- {
- "errors": [
- "stat_error"
- ],
- "osd": 0,
- "primary": false
- },
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0x067f306a",
- "size": 7,
- "errors": [],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:bc819597:::ROBJ12:head(47'52 osd.0.0:51 dirty|omap|data_digest|omap_digest s 7 uv 36 dd 2ddbf8f5 od 67f306a alloc_hint [0 0 0])",
- "union_shard_errors": [
- "stat_error"
- ],
- "errors": [],
- "object": {
- "version": 36,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ12"
- }
- },
- {
- "shards": [
- {
- "errors": [
- "stat_error"
- ],
- "osd": 0,
- "primary": false
- },
- {
- "size": 7,
- "errors": [
- "read_error"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "union_shard_errors": [
- "stat_error",
- "read_error"
- ],
- "errors": [],
- "object": {
- "version": 0,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ13"
- }
- },
- {
- "shards": [
- {
- "attrs": [
- {
- "Base64": false,
- "value": "",
- "name": "_"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0x4f14f849",
- "size": 7,
- "errors": [
- "oi_attr_corrupted"
- ],
- "osd": 0,
- "primary": false
- },
- {
- "attrs": [
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0x4f14f849",
- "size": 7,
- "errors": [
- "oi_attr_missing"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "union_shard_errors": [
- "oi_attr_missing",
- "oi_attr_corrupted"
- ],
- "errors": [],
- "object": {
- "version": 0,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ14"
- }
- },
- {
- "shards": [
- {
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0x2d2a4d6e",
- "size": 7,
- "errors": [],
- "osd": 0,
- "primary": false
- },
- {
- "attrs": [
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0x2d2a4d6e",
- "size": 7,
- "errors": [
- "oi_attr_missing"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:30259878:::ROBJ15:head(47'46 osd.0.0:45 dirty|omap|data_digest|omap_digest s 7 uv 45 dd 2ddbf8f5 od 2d2a4d6e alloc_hint [0 0 0])",
- "union_shard_errors": [
- "oi_attr_missing"
- ],
- "errors": [],
- "object": {
- "version": 45,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ15"
- }
- },
- {
- "errors": [],
- "object": {
- "locator": "",
- "name": "ROBJ16",
- "nspace": "",
- "snap": "head",
- "version": 0
- },
- "shards": [
- {
- "attrs": [
- {
- "Base64": true,
- "name": "_",
- "value": ""
- }
- ],
- "data_digest": "0x2ddbf8f5",
- "errors": [
- "ss_attr_missing"
- ],
- "omap_digest": "0x8b699207",
- "osd": 0,
- "primary": false,
- "size": 7
- },
- {
- "attrs": [
- {
- "Base64": true,
- "name": "_",
- "value": ""
- },
- {
- "Base64": false,
- "name": "snapset",
- "value": "bad-val"
- }
- ],
- "data_digest": "0x2ddbf8f5",
- "errors": [
- "ss_attr_corrupted"
- ],
- "omap_digest": "0x8b699207",
- "osd": 1,
- "primary": true,
- "size": 7
- }
- ],
- "union_shard_errors": [
- "ss_attr_missing",
- "ss_attr_corrupted"
- ]
- },
- {
- "shards": [
- {
- "data_digest": "0x578a4830",
- "omap_digest": "0xf8e11918",
- "size": 7,
- "errors": [
- "data_digest_mismatch_oi"
- ],
- "osd": 0,
- "primary": false
- },
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0xf8e11918",
- "size": 7,
- "errors": [],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:e97ce31e:::ROBJ2:head(47'56 osd.0.0:55 dirty|omap|data_digest|omap_digest s 7 uv 6 dd 2ddbf8f5 od f8e11918 alloc_hint [0 0 0])",
- "union_shard_errors": [
- "data_digest_mismatch_oi"
- ],
- "errors": [
- "data_digest_mismatch"
- ],
- "object": {
- "version": 6,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ2"
- }
- },
- {
- "shards": [
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0x00b35dfd",
- "size": 7,
- "errors": [],
- "osd": 0,
- "primary": false
- },
- {
- "errors": [
- "missing"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:f2a5b2a4:::ROBJ3:head(47'57 osd.0.0:56 dirty|omap|data_digest|omap_digest s 7 uv 9 dd 2ddbf8f5 od b35dfd alloc_hint [0 0 0])",
- "union_shard_errors": [
- "missing"
- ],
- "errors": [],
- "object": {
- "version": 9,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ3"
- }
- },
- {
- "shards": [
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0xd7178dfe",
- "size": 7,
- "errors": [
- "omap_digest_mismatch_oi"
- ],
- "osd": 0,
- "primary": false
- },
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0xe2d46ea4",
- "size": 7,
- "errors": [],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:f4981d31:::ROBJ4:head(47'58 osd.0.0:57 dirty|omap|data_digest|omap_digest s 7 uv 12 dd 2ddbf8f5 od e2d46ea4 alloc_hint [0 0 0])",
- "union_shard_errors": [
- "omap_digest_mismatch_oi"
- ],
- "errors": [
- "omap_digest_mismatch"
- ],
- "object": {
- "version": 12,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ4"
- }
- },
- {
- "shards": [
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0x1a862a41",
- "size": 7,
- "errors": [],
- "osd": 0,
- "primary": false
- },
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0x06cac8f6",
- "size": 7,
- "errors": [
- "omap_digest_mismatch_oi"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:f4bfd4d1:::ROBJ5:head(47'59 osd.0.0:58 dirty|omap|data_digest|omap_digest s 7 uv 15 dd 2ddbf8f5 od 1a862a41 alloc_hint [0 0 0])",
- "union_shard_errors": [
- "omap_digest_mismatch_oi"
- ],
- "errors": [
- "omap_digest_mismatch"
- ],
- "object": {
- "version": 15,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ5"
- }
- },
- {
- "shards": [
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0x689ee887",
- "size": 7,
- "errors": [
- "omap_digest_mismatch_oi"
- ],
- "osd": 0,
- "primary": false
- },
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0x179c919f",
- "size": 7,
- "errors": [],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:a53c12e8:::ROBJ6:head(47'50 osd.0.0:49 dirty|omap|data_digest|omap_digest s 7 uv 18 dd 2ddbf8f5 od 179c919f alloc_hint [0 0 0])",
- "union_shard_errors": [
- "omap_digest_mismatch_oi"
- ],
- "errors": [
- "omap_digest_mismatch"
- ],
- "object": {
- "version": 18,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ6"
- }
- },
- {
- "shards": [
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0xefced57a",
- "size": 7,
- "errors": [],
- "osd": 0,
- "primary": false
- },
- {
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0x6a73cc07",
- "size": 7,
- "errors": [
- "omap_digest_mismatch_oi"
- ],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:8b55fa4b:::ROBJ7:head(47'49 osd.0.0:48 dirty|omap|data_digest|omap_digest s 7 uv 21 dd 2ddbf8f5 od efced57a alloc_hint [0 0 0])",
- "union_shard_errors": [
- "omap_digest_mismatch_oi"
- ],
- "errors": [
- "omap_digest_mismatch"
- ],
- "object": {
- "version": 21,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ7"
- }
- },
- {
- "shards": [
- {
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "bad-val",
- "name": "_key1-ROBJ8"
- },
- {
- "Base64": false,
- "value": "val3-ROBJ8",
- "name": "_key3-ROBJ8"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0xd6be81dc",
- "size": 7,
- "errors": [],
- "osd": 0,
- "primary": false
- },
- {
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "val1-ROBJ8",
- "name": "_key1-ROBJ8"
- },
- {
- "Base64": false,
- "value": "val2-ROBJ8",
- "name": "_key2-ROBJ8"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "data_digest": "0x2ddbf8f5",
- "omap_digest": "0xd6be81dc",
- "size": 7,
- "errors": [],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:86586531:::ROBJ8:head(82'62 client.4351.0:1 dirty|omap|data_digest|omap_digest s 7 uv 66 dd 2ddbf8f5 od d6be81dc alloc_hint [0 0 0])",
- "union_shard_errors": [],
- "errors": [
- "attr_value_mismatch",
- "attr_name_mismatch"
- ],
- "object": {
- "version": 66,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ8"
- }
- },
- {
- "shards": [
- {
- "object_info": "3:ffdb2004:::ROBJ9:head(47'60 osd.0.0:59 dirty|omap|data_digest|omap_digest s 7 uv 27 dd 2ddbf8f5 od 2eecc539 alloc_hint [0 0 0])",
- "data_digest": "0x1f26fb26",
- "omap_digest": "0x2eecc539",
- "size": 3,
- "errors": [
- "obj_size_oi_mismatch"
- ],
- "osd": 0,
- "primary": false
- },
- {
- "object_info": "3:ffdb2004:::ROBJ9:head(122'64 client.4532.0:1 dirty|omap|data_digest|omap_digest s 3 uv 68 dd 1f26fb26 od 2eecc539 alloc_hint [0 0 0])",
- "data_digest": "0x1f26fb26",
- "omap_digest": "0x2eecc539",
- "size": 3,
- "errors": [],
- "osd": 1,
- "primary": true
- }
- ],
- "selected_object_info": "3:ffdb2004:::ROBJ9:head(122'64 client.4532.0:1 dirty|omap|data_digest|omap_digest s 3 uv 68 dd 1f26fb26 od 2eecc539 alloc_hint [0 0 0])",
- "union_shard_errors": [
- "obj_size_oi_mismatch"
- ],
- "errors": [
- "object_info_inconsistency"
- ],
- "object": {
- "version": 68,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "ROBJ9"
- }
- }
- ],
- "epoch": 0
-}
-EOF
-
- jq "$jqfilter" $dir/json | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/csjson
- diff ${DIFFCOLOPTS} $dir/checkcsjson $dir/csjson || test $getjson = "yes" || return 1
- if test $getjson = "yes"
- then
- jq '.' $dir/json > save2.json
- fi
-
- if which jsonschema > /dev/null;
- then
- jsonschema -i $dir/json $CEPH_ROOT/doc/rados/command/list-inconsistent-obj.json || return 1
- fi
-
- rados rmpool $poolname $poolname --yes-i-really-really-mean-it
- teardown $dir || return 1
-}
-
-
-#
-# Test scrub errors for an erasure coded pool
-#
-function corrupt_scrub_erasure() {
- local dir=$1
- local allow_overwrites=$2
- local poolname=ecpool
- local total_objs=5
-
- setup $dir || return 1
- run_mon $dir a || return 1
- run_mgr $dir x || return 1
- for id in $(seq 0 2) ; do
- if [ "$allow_overwrites" = "true" ]; then
- run_osd_bluestore $dir $id || return 1
- else
- run_osd $dir $id || return 1
- fi
- done
- create_rbd_pool || return 1
- create_pool foo 1
-
- create_ec_pool $poolname $allow_overwrites k=2 m=1 stripe_unit=2K --force || return 1
- wait_for_clean || return 1
-
- for i in $(seq 1 $total_objs) ; do
- objname=EOBJ${i}
- add_something $dir $poolname $objname || return 1
-
- local osd=$(expr $i % 2)
-
- case $i in
- 1)
- # Size (deep scrub data_digest too)
- local payload=UVWXYZZZ
- echo $payload > $dir/CORRUPT
- objectstore_tool $dir $osd $objname set-bytes $dir/CORRUPT || return 1
- ;;
-
- 2)
- # Corrupt EC shard
- dd if=/dev/urandom of=$dir/CORRUPT bs=2048 count=1
- objectstore_tool $dir $osd $objname set-bytes $dir/CORRUPT || return 1
- ;;
-
- 3)
- # missing
- objectstore_tool $dir $osd $objname remove || return 1
- ;;
-
- 4)
- rados --pool $poolname setxattr $objname key1-$objname val1-$objname || return 1
- rados --pool $poolname setxattr $objname key2-$objname val2-$objname || return 1
-
- # Break xattrs
- echo -n bad-val > $dir/bad-val
- objectstore_tool $dir $osd $objname set-attr _key1-$objname $dir/bad-val || return 1
- objectstore_tool $dir $osd $objname rm-attr _key2-$objname || return 1
- echo -n val3-$objname > $dir/newval
- objectstore_tool $dir $osd $objname set-attr _key3-$objname $dir/newval || return 1
- rm $dir/bad-val $dir/newval
- ;;
-
- 5)
- # Corrupt EC shard
- dd if=/dev/urandom of=$dir/CORRUPT bs=2048 count=2
- objectstore_tool $dir $osd $objname set-bytes $dir/CORRUPT || return 1
- ;;
-
- esac
- done
-
- local pg=$(get_pg $poolname EOBJ0)
-
- pg_scrub $pg
-
- rados list-inconsistent-pg $poolname > $dir/json || return 1
- # Check pg count
- test $(jq '. | length' $dir/json) = "1" || return 1
- # Check pgid
- test $(jq -r '.[0]' $dir/json) = $pg || return 1
-
- rados list-inconsistent-obj $pg > $dir/json || return 1
- # Get epoch for repair-get requests
- epoch=$(jq .epoch $dir/json)
-
- jq "$jqfilter" << EOF | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/checkcsjson
-{
- "inconsistents": [
- {
- "shards": [
- {
- "size": 2048,
- "errors": [],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "size": 9,
- "shard": 0,
- "errors": [
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "osd": 1,
- "primary": true
- },
- {
- "size": 2048,
- "shard": 1,
- "errors": [],
- "osd": 2,
- "primary": false
- }
- ],
- "selected_object_info": "3:9175b684:::EOBJ1:head(21'1 client.4179.0:1 dirty|data_digest|omap_digest s 7 uv 1 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "errors": [
- "size_mismatch"
- ],
- "object": {
- "version": 1,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ1"
- }
- },
- {
- "shards": [
- {
- "size": 2048,
- "errors": [],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "shard": 0,
- "errors": [
- "missing"
- ],
- "osd": 1,
- "primary": true
- },
- {
- "size": 2048,
- "shard": 1,
- "errors": [],
- "osd": 2,
- "primary": false
- }
- ],
- "selected_object_info": "3:b197b25d:::EOBJ3:head(37'3 client.4251.0:1 dirty|data_digest|omap_digest s 7 uv 3 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [
- "missing"
- ],
- "errors": [],
- "object": {
- "version": 3,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ3"
- }
- },
- {
- "shards": [
- {
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "bad-val",
- "name": "_key1-EOBJ4"
- },
- {
- "Base64": false,
- "value": "val3-EOBJ4",
- "name": "_key3-EOBJ4"
- },
- {
- "Base64": true,
- "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
- "name": "hinfo_key"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "size": 2048,
- "errors": [],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "osd": 1,
- "primary": true,
- "shard": 0,
- "errors": [],
- "size": 2048,
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "val1-EOBJ4",
- "name": "_key1-EOBJ4"
- },
- {
- "Base64": false,
- "value": "val2-EOBJ4",
- "name": "_key2-EOBJ4"
- },
- {
- "Base64": true,
- "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
- "name": "hinfo_key"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ]
- },
- {
- "osd": 2,
- "primary": false,
- "shard": 1,
- "errors": [],
- "size": 2048,
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "val1-EOBJ4",
- "name": "_key1-EOBJ4"
- },
- {
- "Base64": false,
- "value": "val2-EOBJ4",
- "name": "_key2-EOBJ4"
- },
- {
- "Base64": true,
- "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
- "name": "hinfo_key"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ]
- }
- ],
- "selected_object_info": "3:5e723e06:::EOBJ4:head(45'6 client.4289.0:1 dirty|data_digest|omap_digest s 7 uv 6 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [],
- "errors": [
- "attr_value_mismatch",
- "attr_name_mismatch"
- ],
- "object": {
- "version": 6,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ4"
- }
- },
- {
- "shards": [
- {
- "size": 2048,
- "errors": [],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "size": 4096,
- "shard": 0,
- "errors": [
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "osd": 1,
- "primary": true
- },
- {
- "size": 2048,
- "shard": 1,
- "errors": [],
- "osd": 2,
- "primary": false
- }
- ],
- "selected_object_info": "3:8549dfb5:::EOBJ5:head(65'7 client.4441.0:1 dirty|data_digest|omap_digest s 7 uv 7 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "errors": [
- "size_mismatch"
- ],
- "object": {
- "version": 7,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ5"
- }
- }
- ],
- "epoch": 0
-}
-EOF
-
- jq "$jqfilter" $dir/json | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/csjson
- diff ${DIFFCOLOPTS} $dir/checkcsjson $dir/csjson || test $getjson = "yes" || return 1
- if test $getjson = "yes"
- then
- jq '.' $dir/json > save3.json
- fi
-
- if which jsonschema > /dev/null;
- then
- jsonschema -i $dir/json $CEPH_ROOT/doc/rados/command/list-inconsistent-obj.json || return 1
- fi
-
- pg_deep_scrub $pg
-
- rados list-inconsistent-pg $poolname > $dir/json || return 1
- # Check pg count
- test $(jq '. | length' $dir/json) = "1" || return 1
- # Check pgid
- test $(jq -r '.[0]' $dir/json) = $pg || return 1
-
- rados list-inconsistent-obj $pg > $dir/json || return 1
- # Get epoch for repair-get requests
- epoch=$(jq .epoch $dir/json)
-
- if [ "$allow_overwrites" = "true" ]
- then
- jq "$jqfilter" << EOF | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/checkcsjson
-{
- "inconsistents": [
- {
- "shards": [
- {
- "data_digest": "0x00000000",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "size": 9,
- "shard": 0,
- "errors": [
- "read_error",
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "osd": 1,
- "primary": true
- },
- {
- "data_digest": "0x00000000",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "shard": 1,
- "errors": [],
- "osd": 2,
- "primary": false
- }
- ],
- "selected_object_info": "3:9175b684:::EOBJ1:head(27'1 client.4155.0:1 dirty|data_digest|omap_digest s 7 uv 1 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [
- "read_error",
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "errors": [
- "size_mismatch"
- ],
- "object": {
- "version": 1,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ1"
- }
- },
- {
- "shards": [
- {
- "data_digest": "0x00000000",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "shard": 0,
- "errors": [
- "missing"
- ],
- "osd": 1,
- "primary": true
- },
- {
- "data_digest": "0x00000000",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "shard": 1,
- "errors": [],
- "osd": 2,
- "primary": false
- }
- ],
- "selected_object_info": "3:b197b25d:::EOBJ3:head(41'3 client.4199.0:1 dirty|data_digest|omap_digest s 7 uv 3 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [
- "missing"
- ],
- "errors": [],
- "object": {
- "version": 3,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ3"
- }
- },
- {
- "shards": [
- {
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "bad-val",
- "name": "_key1-EOBJ4"
- },
- {
- "Base64": false,
- "value": "val3-EOBJ4",
- "name": "_key3-EOBJ4"
- },
- {
- "Base64": true,
- "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
- "name": "hinfo_key"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "data_digest": "0x00000000",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "val1-EOBJ4",
- "name": "_key1-EOBJ4"
- },
- {
- "Base64": false,
- "value": "val2-EOBJ4",
- "name": "_key2-EOBJ4"
- },
- {
- "Base64": true,
- "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
- "name": "hinfo_key"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "data_digest": "0x00000000",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 0,
- "osd": 1,
- "primary": true
- },
- {
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "val1-EOBJ4",
- "name": "_key1-EOBJ4"
- },
- {
- "Base64": false,
- "value": "val2-EOBJ4",
- "name": "_key2-EOBJ4"
- },
- {
- "Base64": true,
- "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
- "name": "hinfo_key"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "data_digest": "0x00000000",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 1,
- "osd": 2,
- "primary": false
- }
- ],
- "selected_object_info": "3:5e723e06:::EOBJ4:head(48'6 client.4223.0:1 dirty|data_digest|omap_digest s 7 uv 6 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [],
- "errors": [
- "attr_value_mismatch",
- "attr_name_mismatch"
- ],
- "object": {
- "version": 6,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ4"
- }
- },
- {
- "shards": [
- {
- "data_digest": "0x00000000",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "data_digest": "0x00000000",
- "omap_digest": "0xffffffff",
- "size": 4096,
- "errors": [
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "shard": 0,
- "osd": 1,
- "primary": true
- },
- {
- "data_digest": "0x00000000",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 1,
- "osd": 2,
- "primary": false
- }
- ],
- "selected_object_info": "3:8549dfb5:::EOBJ5:head(65'7 client.4288.0:1 dirty|data_digest|omap_digest s 7 uv 7 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "errors": [
- "size_mismatch"
- ],
- "object": {
- "version": 7,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ5"
- }
- }
- ],
- "epoch": 0
-}
-EOF
-
- else
-
- jq "$jqfilter" << EOF | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/checkcsjson
-{
- "inconsistents": [
- {
- "shards": [
- {
- "data_digest": "0x04cfa72f",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "size": 9,
- "shard": 0,
- "errors": [
- "read_error",
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "osd": 1,
- "primary": true
- },
- {
- "data_digest": "0x04cfa72f",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "shard": 1,
- "errors": [],
- "osd": 2,
- "primary": false
- }
- ],
- "selected_object_info": "3:9175b684:::EOBJ1:head(21'1 client.4179.0:1 dirty|data_digest|omap_digest s 7 uv 1 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [
- "read_error",
- "size_mismatch_oi",
- "obj_size_oi_mismatch"
- ],
- "errors": [
- "size_mismatch"
- ],
- "object": {
- "version": 1,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ1"
- }
- },
- {
- "shards": [
- {
- "size": 2048,
- "errors": [
- "ec_hash_error"
- ],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "data_digest": "0x04cfa72f",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 0,
- "osd": 1,
- "primary": true
- },
- {
- "data_digest": "0x04cfa72f",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 1,
- "osd": 2,
- "primary": false
- }
- ],
- "selected_object_info": "3:9babd184:::EOBJ2:head(29'2 client.4217.0:1 dirty|data_digest|omap_digest s 7 uv 2 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [
- "ec_hash_error"
- ],
- "errors": [],
- "object": {
- "version": 2,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ2"
- }
- },
- {
- "shards": [
- {
- "data_digest": "0x04cfa72f",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "osd": 1,
- "primary": true,
- "shard": 0,
- "errors": [
- "missing"
- ]
- },
- {
- "data_digest": "0x04cfa72f",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "shard": 1,
- "errors": [],
- "osd": 2,
- "primary": false
- }
- ],
- "selected_object_info": "3:b197b25d:::EOBJ3:head(37'3 client.4251.0:1 dirty|data_digest|omap_digest s 7 uv 3 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [
- "missing"
- ],
- "errors": [],
- "object": {
- "version": 3,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ3"
- }
- },
- {
- "shards": [
- {
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "bad-val",
- "name": "_key1-EOBJ4"
- },
- {
- "Base64": false,
- "value": "val3-EOBJ4",
- "name": "_key3-EOBJ4"
- },
- {
- "Base64": true,
- "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
- "name": "hinfo_key"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ],
- "data_digest": "0x04cfa72f",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "osd": 1,
- "primary": true,
- "shard": 0,
- "errors": [],
- "size": 2048,
- "omap_digest": "0xffffffff",
- "data_digest": "0x04cfa72f",
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "val1-EOBJ4",
- "name": "_key1-EOBJ4"
- },
- {
- "Base64": false,
- "value": "val2-EOBJ4",
- "name": "_key2-EOBJ4"
- },
- {
- "Base64": true,
- "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
- "name": "hinfo_key"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ]
- },
- {
- "osd": 2,
- "primary": false,
- "shard": 1,
- "errors": [],
- "size": 2048,
- "omap_digest": "0xffffffff",
- "data_digest": "0x04cfa72f",
- "attrs": [
- {
- "Base64": true,
- "value": "",
- "name": "_"
- },
- {
- "Base64": false,
- "value": "val1-EOBJ4",
- "name": "_key1-EOBJ4"
- },
- {
- "Base64": false,
- "value": "val2-EOBJ4",
- "name": "_key2-EOBJ4"
- },
- {
- "Base64": true,
- "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
- "name": "hinfo_key"
- },
- {
- "Base64": true,
- "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
- "name": "snapset"
- }
- ]
- }
- ],
- "selected_object_info": "3:5e723e06:::EOBJ4:head(45'6 client.4289.0:1 dirty|data_digest|omap_digest s 7 uv 6 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [],
- "errors": [
- "attr_value_mismatch",
- "attr_name_mismatch"
- ],
- "object": {
- "version": 6,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ4"
- }
- },
- {
- "shards": [
- {
- "data_digest": "0x04cfa72f",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "errors": [],
- "shard": 2,
- "osd": 0,
- "primary": false
- },
- {
- "size": 4096,
- "shard": 0,
- "errors": [
- "size_mismatch_oi",
- "ec_size_error",
- "obj_size_oi_mismatch"
- ],
- "osd": 1,
- "primary": true
- },
- {
- "data_digest": "0x04cfa72f",
- "omap_digest": "0xffffffff",
- "size": 2048,
- "shard": 1,
- "errors": [],
- "osd": 2,
- "primary": false
- }
- ],
- "selected_object_info": "3:8549dfb5:::EOBJ5:head(65'7 client.4441.0:1 dirty|data_digest|omap_digest s 7 uv 7 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
- "union_shard_errors": [
- "size_mismatch_oi",
- "ec_size_error",
- "obj_size_oi_mismatch"
- ],
- "errors": [
- "size_mismatch"
- ],
- "object": {
- "version": 7,
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "EOBJ5"
- }
- }
- ],
- "epoch": 0
-}
-EOF
-
- fi
-
- jq "$jqfilter" $dir/json | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/csjson
- diff ${DIFFCOLOPTS} $dir/checkcsjson $dir/csjson || test $getjson = "yes" || return 1
- if test $getjson = "yes"
- then
- if [ "$allow_overwrites" = "true" ]
- then
- num=4
- else
- num=5
- fi
- jq '.' $dir/json > save${num}.json
- fi
-
- if which jsonschema > /dev/null;
- then
- jsonschema -i $dir/json $CEPH_ROOT/doc/rados/command/list-inconsistent-obj.json || return 1
- fi
-
- rados rmpool $poolname $poolname --yes-i-really-really-mean-it
- teardown $dir || return 1
-}
-
-function TEST_corrupt_scrub_erasure_appends() {
- corrupt_scrub_erasure $1 false
-}
-
-function TEST_corrupt_scrub_erasure_overwrites() {
- if [ "$use_ec_overwrite" = "true" ]; then
- corrupt_scrub_erasure $1 true
- fi
-}
-
-#
-# Test to make sure that a periodic scrub won't cause deep-scrub info to be lost
-#
-function TEST_periodic_scrub_replicated() {
- local dir=$1
- local poolname=psr_pool
- local objname=POBJ
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=2 || return 1
- run_mgr $dir x || return 1
- local ceph_osd_args="--osd-scrub-interval-randomize-ratio=0 --osd-deep-scrub-randomize-ratio=0 "
- ceph_osd_args+="--osd_scrub_backoff_ratio=0"
- run_osd $dir 0 $ceph_osd_args || return 1
- run_osd $dir 1 $ceph_osd_args || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
-
- create_pool $poolname 1 1 || return 1
- wait_for_clean || return 1
-
- local osd=0
- add_something $dir $poolname $objname scrub || return 1
- local primary=$(get_primary $poolname $objname)
- local pg=$(get_pg $poolname $objname)
-
- # Add deep-scrub only error
- local payload=UVWXYZ
- echo $payload > $dir/CORRUPT
- # Uses $ceph_osd_args for osd restart
- objectstore_tool $dir $osd $objname set-bytes $dir/CORRUPT || return 1
-
- # No scrub information available, so expect failure
- set -o pipefail
- ! rados list-inconsistent-obj $pg | jq '.' || return 1
- set +o pipefail
-
- pg_deep_scrub $pg || return 1
-
- # Make sure bad object found
- rados list-inconsistent-obj $pg | jq '.' | grep -q $objname || return 1
-
- flush_pg_stats
- local last_scrub=$(get_last_scrub_stamp $pg)
- # Fake a schedule scrub
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.${primary}) \
- trigger_scrub $pg || return 1
- # Wait for schedule regular scrub
- wait_for_scrub $pg "$last_scrub"
-
- # It needed to be upgraded
- grep -q "Deep scrub errors, upgrading scrub to deep-scrub" $dir/osd.${primary}.log || return 1
-
- # Bad object still known
- rados list-inconsistent-obj $pg | jq '.' | grep -q $objname || return 1
-
- # Can't upgrade with this set
- ceph osd set nodeep-scrub
- # Let map change propagate to OSDs
- flush pg_stats
- sleep 5
-
- # Fake a schedule scrub
- CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.${primary}) \
- trigger_scrub $pg || return 1
- # Wait for schedule regular scrub
- # to notice scrub and skip it
- local found=false
- for i in $(seq 14 -1 0)
- do
- sleep 1
- ! grep -q "Regular scrub skipped due to deep-scrub errors and nodeep-scrub set" $dir/osd.${primary}.log || { found=true ; break; }
- echo Time left: $i seconds
- done
- test $found = "true" || return 1
-
- # Bad object still known
- rados list-inconsistent-obj $pg | jq '.' | grep -q $objname || return 1
-
- flush_pg_stats
- # Request a regular scrub and it will be done
- pg_scrub $pg
- grep -q "Regular scrub request, deep-scrub details will be lost" $dir/osd.${primary}.log || return 1
-
- # deep-scrub error is no longer present
- rados list-inconsistent-obj $pg | jq '.' | grep -qv $objname || return 1
-}
-
-
-main osd-scrub-repair "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && \
-# test/osd/osd-scrub-repair.sh # TEST_corrupt_and_repair_replicated"
-# End:
diff --git a/src/ceph/qa/standalone/scrub/osd-scrub-snaps.sh b/src/ceph/qa/standalone/scrub/osd-scrub-snaps.sh
deleted file mode 100755
index 4c03bdb..0000000
--- a/src/ceph/qa/standalone/scrub/osd-scrub-snaps.sh
+++ /dev/null
@@ -1,481 +0,0 @@
-#! /bin/bash
-#
-# Copyright (C) 2015 Red Hat <contact@redhat.com>
-#
-# Author: David Zafman <dzafman@redhat.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Library Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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 Library Public License for more details.
-#
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7121" # git grep '\<7121\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- $func $dir || return 1
- done
-}
-
-function TEST_scrub_snaps() {
- local dir=$1
- local poolname=test
-
- TESTDATA="testdata.$$"
-
- setup $dir || return 1
- run_mon $dir a --osd_pool_default_size=1 || return 1
- run_mgr $dir x || return 1
- run_osd $dir 0 || return 1
-
- create_rbd_pool || return 1
- wait_for_clean || return 1
-
- # Create a pool with a single pg
- create_pool $poolname 1 1
- wait_for_clean || return 1
- poolid=$(ceph osd dump | grep "^pool.*[']test[']" | awk '{ print $2 }')
-
- dd if=/dev/urandom of=$TESTDATA bs=1032 count=1
- for i in `seq 1 15`
- do
- rados -p $poolname put obj${i} $TESTDATA
- done
-
- SNAP=1
- rados -p $poolname mksnap snap${SNAP}
- dd if=/dev/urandom of=$TESTDATA bs=256 count=${SNAP}
- rados -p $poolname put obj1 $TESTDATA
- rados -p $poolname put obj5 $TESTDATA
- rados -p $poolname put obj3 $TESTDATA
- for i in `seq 6 14`
- do rados -p $poolname put obj${i} $TESTDATA
- done
-
- SNAP=2
- rados -p $poolname mksnap snap${SNAP}
- dd if=/dev/urandom of=$TESTDATA bs=256 count=${SNAP}
- rados -p $poolname put obj5 $TESTDATA
-
- SNAP=3
- rados -p $poolname mksnap snap${SNAP}
- dd if=/dev/urandom of=$TESTDATA bs=256 count=${SNAP}
- rados -p $poolname put obj3 $TESTDATA
-
- SNAP=4
- rados -p $poolname mksnap snap${SNAP}
- dd if=/dev/urandom of=$TESTDATA bs=256 count=${SNAP}
- rados -p $poolname put obj5 $TESTDATA
- rados -p $poolname put obj2 $TESTDATA
-
- SNAP=5
- rados -p $poolname mksnap snap${SNAP}
- SNAP=6
- rados -p $poolname mksnap snap${SNAP}
- dd if=/dev/urandom of=$TESTDATA bs=256 count=${SNAP}
- rados -p $poolname put obj5 $TESTDATA
-
- SNAP=7
- rados -p $poolname mksnap snap${SNAP}
-
- rados -p $poolname rm obj4
- rados -p $poolname rm obj2
-
- kill_daemons $dir TERM osd || return 1
-
- # Don't need to ceph_objectstore_tool function because osd stopped
-
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj1)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" --force remove
-
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --op list obj5 | grep \"snapid\":2)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" remove
-
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --op list obj5 | grep \"snapid\":1)"
- OBJ5SAVE="$JSON"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" remove
-
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --op list obj5 | grep \"snapid\":4)"
- dd if=/dev/urandom of=$TESTDATA bs=256 count=18
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" set-bytes $TESTDATA
-
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj3)"
- dd if=/dev/urandom of=$TESTDATA bs=256 count=15
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" set-bytes $TESTDATA
-
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --op list obj4 | grep \"snapid\":7)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" remove
-
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj2)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" rm-attr snapset
-
- # Create a clone which isn't in snapset and doesn't have object info
- JSON="$(echo "$OBJ5SAVE" | sed s/snapid\":1/snapid\":7/)"
- dd if=/dev/urandom of=$TESTDATA bs=256 count=7
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" set-bytes $TESTDATA
-
- rm -f $TESTDATA
-
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj6)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj7)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset corrupt
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj8)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset seq
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj9)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset clone_size
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj10)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset clone_overlap
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj11)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset clones
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj12)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset head
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj13)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset snaps
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj14)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset size
-
- echo "garbage" > $dir/bad
- JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj15)"
- ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" set-attr snapset $dir/bad
- rm -f $dir/bad
-
- run_osd $dir 0 || return 1
- create_rbd_pool || return 1
- wait_for_clean || return 1
-
- local pgid="${poolid}.0"
- if ! pg_scrub "$pgid" ; then
- cat $dir/osd.0.log
- return 1
- fi
- grep 'log_channel' $dir/osd.0.log
-
- rados list-inconsistent-pg $poolname > $dir/json || return 1
- # Check pg count
- test $(jq '. | length' $dir/json) = "1" || return 1
- # Check pgid
- test $(jq -r '.[0]' $dir/json) = $pgid || return 1
-
- rados list-inconsistent-snapset $pgid > $dir/json || return 1
- test $(jq '.inconsistents | length' $dir/json) = "21" || return 1
-
- local jqfilter='.inconsistents'
- local sortkeys='import json; import sys ; JSON=sys.stdin.read() ; ud = json.loads(JSON) ; print json.dumps(ud, sort_keys=True, indent=2)'
-
- jq "$jqfilter" << EOF | python -c "$sortkeys" > $dir/checkcsjson
-{
- "inconsistents": [
- {
- "errors": [
- "headless"
- ],
- "snap": 1,
- "locator": "",
- "nspace": "",
- "name": "obj1"
- },
- {
- "errors": [
- "size_mismatch"
- ],
- "snap": 1,
- "locator": "",
- "nspace": "",
- "name": "obj10"
- },
- {
- "errors": [
- "headless"
- ],
- "snap": 1,
- "locator": "",
- "nspace": "",
- "name": "obj11"
- },
- {
- "errors": [
- "size_mismatch"
- ],
- "snap": 1,
- "locator": "",
- "nspace": "",
- "name": "obj14"
- },
- {
- "errors": [
- "headless"
- ],
- "snap": 1,
- "locator": "",
- "nspace": "",
- "name": "obj6"
- },
- {
- "errors": [
- "headless"
- ],
- "snap": 1,
- "locator": "",
- "nspace": "",
- "name": "obj7"
- },
- {
- "errors": [
- "size_mismatch"
- ],
- "snap": 1,
- "locator": "",
- "nspace": "",
- "name": "obj9"
- },
- {
- "errors": [
- "headless"
- ],
- "snap": 4,
- "locator": "",
- "nspace": "",
- "name": "obj2"
- },
- {
- "errors": [
- "size_mismatch"
- ],
- "snap": 4,
- "locator": "",
- "nspace": "",
- "name": "obj5"
- },
- {
- "errors": [
- "headless"
- ],
- "snap": 7,
- "locator": "",
- "nspace": "",
- "name": "obj2"
- },
- {
- "errors": [
- "oi_attr_missing",
- "headless"
- ],
- "snap": 7,
- "locator": "",
- "nspace": "",
- "name": "obj5"
- },
- {
- "extra clones": [
- 1
- ],
- "errors": [
- "extra_clones"
- ],
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "obj11"
- },
- {
- "errors": [
- "head_mismatch"
- ],
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "obj12"
- },
- {
- "errors": [
- "ss_attr_corrupted"
- ],
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "obj15"
- },
- {
- "extra clones": [
- 7,
- 4
- ],
- "errors": [
- "ss_attr_missing",
- "extra_clones"
- ],
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "obj2"
- },
- {
- "errors": [
- "size_mismatch"
- ],
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "obj3"
- },
- {
- "missing": [
- 7
- ],
- "errors": [
- "clone_missing"
- ],
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "obj4"
- },
- {
- "missing": [
- 2,
- 1
- ],
- "extra clones": [
- 7
- ],
- "errors": [
- "extra_clones",
- "clone_missing"
- ],
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "obj5"
- },
- {
- "extra clones": [
- 1
- ],
- "errors": [
- "extra_clones"
- ],
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "obj6"
- },
- {
- "extra clones": [
- 1
- ],
- "errors": [
- "head_mismatch",
- "extra_clones"
- ],
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "obj7"
- },
- {
- "errors": [
- "snapset_mismatch"
- ],
- "snap": "head",
- "locator": "",
- "nspace": "",
- "name": "obj8"
- }
- ],
- "epoch": 20
-}
-EOF
-
- jq "$jqfilter" $dir/json | python -c "$sortkeys" > $dir/csjson
- diff ${DIFFCOLOPTS} $dir/checkcsjson $dir/csjson || return 1
-
- if which jsonschema > /dev/null;
- then
- jsonschema -i $dir/json $CEPH_ROOT/doc/rados/command/list-inconsistent-snap.json || return 1
- fi
-
- for i in `seq 1 7`
- do
- rados -p $poolname rmsnap snap$i
- done
-
- ERRORS=0
-
- pidfile=$(find $dir 2>/dev/null | grep $name_prefix'[^/]*\.pid')
- pid=$(cat $pidfile)
- if ! kill -0 $pid
- then
- echo "OSD crash occurred"
- tail -100 $dir/osd.0.log
- ERRORS=$(expr $ERRORS + 1)
- fi
-
- kill_daemons $dir || return 1
-
- declare -a err_strings
- err_strings[0]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*::obj10:.* is missing in clone_overlap"
- err_strings[1]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*::obj5:7 no '_' attr"
- err_strings[2]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*::obj5:7 is an unexpected clone"
- err_strings[3]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*::obj5:4 on disk size [(]4608[)] does not match object info size [(]512[)] adjusted for ondisk to [(]512[)]"
- err_strings[4]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj5:head expected clone .*:::obj5:2"
- err_strings[5]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj5:head expected clone .*:::obj5:1"
- err_strings[6]="log_channel[(]cluster[)] log [[]INF[]] : scrub [0-9]*[.]0 .*:::obj5:head 2 missing clone[(]s[)]"
- err_strings[7]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj12:head snapset.head_exists=false, but head exists"
- err_strings[8]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj8:head snaps.seq not set"
- err_strings[9]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj7:head snapset.head_exists=false, but head exists"
- err_strings[10]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj7:1 is an unexpected clone"
- err_strings[11]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj3:head on disk size [(]3840[)] does not match object info size [(]768[)] adjusted for ondisk to [(]768[)]"
- err_strings[12]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj6:1 is an unexpected clone"
- err_strings[13]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj2:head no 'snapset' attr"
- err_strings[14]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj2:7 clone ignored due to missing snapset"
- err_strings[15]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj2:4 clone ignored due to missing snapset"
- err_strings[16]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj4:head expected clone .*:::obj4:7"
- err_strings[17]="log_channel[(]cluster[)] log [[]INF[]] : scrub [0-9]*[.]0 .*:::obj4:head 1 missing clone[(]s[)]"
- err_strings[18]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj1:1 is an unexpected clone"
- err_strings[19]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj9:1 is missing in clone_size"
- err_strings[20]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj11:1 is an unexpected clone"
- err_strings[21]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj14:1 size 1032 != clone_size 1033"
- err_strings[22]="log_channel[(]cluster[)] log [[]ERR[]] : [0-9]*[.]0 scrub 22 errors"
- err_strings[23]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj15:head can't decode 'snapset' attr buffer"
-
- for err_string in "${err_strings[@]}"
- do
- if ! grep "$err_string" $dir/osd.0.log > /dev/null;
- then
- echo "Missing log message '$err_string'"
- ERRORS=$(expr $ERRORS + 1)
- fi
- done
-
- teardown $dir || return 1
-
- if [ $ERRORS != "0" ];
- then
- echo "TEST FAILED WITH $ERRORS ERRORS"
- return 1
- fi
-
- echo "TEST PASSED"
- return 0
-}
-
-main osd-scrub-snaps "$@"
-
-# Local Variables:
-# compile-command: "cd ../.. ; make -j4 && \
-# test/osd/osd-scrub-snaps.sh"
diff --git a/src/ceph/qa/standalone/special/ceph_objectstore_tool.py b/src/ceph/qa/standalone/special/ceph_objectstore_tool.py
deleted file mode 100755
index 7c52101..0000000
--- a/src/ceph/qa/standalone/special/ceph_objectstore_tool.py
+++ /dev/null
@@ -1,2024 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import print_function
-from subprocess import call
-try:
- from subprocess import check_output
-except ImportError:
- def check_output(*popenargs, **kwargs):
- import subprocess
- # backported from python 2.7 stdlib
- process = subprocess.Popen(
- stdout=subprocess.PIPE, *popenargs, **kwargs)
- output, unused_err = process.communicate()
- retcode = process.poll()
- if retcode:
- cmd = kwargs.get("args")
- if cmd is None:
- cmd = popenargs[0]
- error = subprocess.CalledProcessError(retcode, cmd)
- error.output = output
- raise error
- return output
-
-import filecmp
-import os
-import subprocess
-import math
-import time
-import sys
-import re
-import logging
-import json
-import tempfile
-import platform
-
-try:
- from subprocess import DEVNULL
-except ImportError:
- DEVNULL = open(os.devnull, "wb")
-
-logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.WARNING)
-
-
-if sys.version_info[0] >= 3:
- def decode(s):
- return s.decode('utf-8')
-
- def check_output(*args, **kwargs):
- return decode(subprocess.check_output(*args, **kwargs))
-else:
- def decode(s):
- return s
-
-
-
-def wait_for_health():
- print("Wait for health_ok...", end="")
- tries = 0
- while call("{path}/ceph health 2> /dev/null | grep -v 'HEALTH_OK\|HEALTH_WARN' > /dev/null".format(path=CEPH_BIN), shell=True) == 0:
- tries += 1
- if tries == 150:
- raise Exception("Time exceeded to go to health")
- time.sleep(1)
- print("DONE")
-
-
-def get_pool_id(name, nullfd):
- cmd = "{path}/ceph osd pool stats {pool}".format(pool=name, path=CEPH_BIN).split()
- # pool {pool} id # .... grab the 4 field
- return check_output(cmd, stderr=nullfd).split()[3]
-
-
-# return a list of unique PGS given an osd subdirectory
-def get_osd_pgs(SUBDIR, ID):
- PGS = []
- if ID:
- endhead = re.compile("{id}.*_head$".format(id=ID))
- DIR = os.path.join(SUBDIR, "current")
- PGS += [f for f in os.listdir(DIR) if os.path.isdir(os.path.join(DIR, f)) and (ID is None or endhead.match(f))]
- PGS = [re.sub("_head", "", p) for p in PGS if "_head" in p]
- return PGS
-
-
-# return a sorted list of unique PGs given a directory
-def get_pgs(DIR, ID):
- OSDS = [f for f in os.listdir(DIR) if os.path.isdir(os.path.join(DIR, f)) and f.find("osd") == 0]
- PGS = []
- for d in OSDS:
- SUBDIR = os.path.join(DIR, d)
- PGS += get_osd_pgs(SUBDIR, ID)
- return sorted(set(PGS))
-
-
-# return a sorted list of PGS a subset of ALLPGS that contain objects with prefix specified
-def get_objs(ALLPGS, prefix, DIR, ID):
- OSDS = [f for f in os.listdir(DIR) if os.path.isdir(os.path.join(DIR, f)) and f.find("osd") == 0]
- PGS = []
- for d in OSDS:
- DIRL2 = os.path.join(DIR, d)
- SUBDIR = os.path.join(DIRL2, "current")
- for p in ALLPGS:
- PGDIR = p + "_head"
- if not os.path.isdir(os.path.join(SUBDIR, PGDIR)):
- continue
- FINALDIR = os.path.join(SUBDIR, PGDIR)
- # See if there are any objects there
- if any(f for f in [val for _, _, fl in os.walk(FINALDIR) for val in fl] if f.startswith(prefix)):
- PGS += [p]
- return sorted(set(PGS))
-
-
-# return a sorted list of OSDS which have data from a given PG
-def get_osds(PG, DIR):
- ALLOSDS = [f for f in os.listdir(DIR) if os.path.isdir(os.path.join(DIR, f)) and f.find("osd") == 0]
- OSDS = []
- for d in ALLOSDS:
- DIRL2 = os.path.join(DIR, d)
- SUBDIR = os.path.join(DIRL2, "current")
- PGDIR = PG + "_head"
- if not os.path.isdir(os.path.join(SUBDIR, PGDIR)):
- continue
- OSDS += [d]
- return sorted(OSDS)
-
-
-def get_lines(filename):
- tmpfd = open(filename, "r")
- line = True
- lines = []
- while line:
- line = tmpfd.readline().rstrip('\n')
- if line:
- lines += [line]
- tmpfd.close()
- os.unlink(filename)
- return lines
-
-
-def cat_file(level, filename):
- if level < logging.getLogger().getEffectiveLevel():
- return
- print("File: " + filename)
- with open(filename, "r") as f:
- while True:
- line = f.readline().rstrip('\n')
- if not line:
- break
- print(line)
- print("<EOF>")
-
-
-def vstart(new, opt=""):
- print("vstarting....", end="")
- NEW = new and "-n" or "-N"
- call("MON=1 OSD=4 MDS=0 MGR=1 CEPH_PORT=7400 {path}/src/vstart.sh --filestore --short -l {new} -d {opt} > /dev/null 2>&1".format(new=NEW, opt=opt, path=CEPH_ROOT), shell=True)
- print("DONE")
-
-
-def test_failure(cmd, errmsg, tty=False):
- if tty:
- try:
- ttyfd = open("/dev/tty", "rwb")
- except Exception as e:
- logging.info(str(e))
- logging.info("SKIP " + cmd)
- return 0
- TMPFILE = r"/tmp/tmp.{pid}".format(pid=os.getpid())
- tmpfd = open(TMPFILE, "wb")
-
- logging.debug(cmd)
- if tty:
- ret = call(cmd, shell=True, stdin=ttyfd, stdout=ttyfd, stderr=tmpfd)
- ttyfd.close()
- else:
- ret = call(cmd, shell=True, stderr=tmpfd)
- tmpfd.close()
- if ret == 0:
- logging.error(cmd)
- logging.error("Should have failed, but got exit 0")
- return 1
- lines = get_lines(TMPFILE)
- matched = [ l for l in lines if errmsg in l ]
- if any(matched):
- logging.info("Correctly failed with message \"" + matched[0] + "\"")
- return 0
- else:
- logging.error("Command: " + cmd )
- logging.error("Bad messages to stderr \"" + str(lines) + "\"")
- logging.error("Expected \"" + errmsg + "\"")
- return 1
-
-
-def get_nspace(num):
- if num == 0:
- return ""
- return "ns{num}".format(num=num)
-
-
-def verify(DATADIR, POOL, NAME_PREFIX, db):
- TMPFILE = r"/tmp/tmp.{pid}".format(pid=os.getpid())
- ERRORS = 0
- for rawnsfile in [f for f in os.listdir(DATADIR) if f.split('-')[1].find(NAME_PREFIX) == 0]:
- nsfile = rawnsfile.split("__")[0]
- clone = rawnsfile.split("__")[1]
- nspace = nsfile.split("-")[0]
- file = nsfile.split("-")[1]
- # Skip clones
- if clone != "head":
- continue
- path = os.path.join(DATADIR, rawnsfile)
- try:
- os.unlink(TMPFILE)
- except:
- pass
- cmd = "{path}/rados -p {pool} -N '{nspace}' get {file} {out}".format(pool=POOL, file=file, out=TMPFILE, nspace=nspace, path=CEPH_BIN)
- logging.debug(cmd)
- call(cmd, shell=True, stdout=DEVNULL, stderr=DEVNULL)
- cmd = "diff -q {src} {result}".format(src=path, result=TMPFILE)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("{file} data not imported properly".format(file=file))
- ERRORS += 1
- try:
- os.unlink(TMPFILE)
- except:
- pass
- for key, val in db[nspace][file]["xattr"].items():
- cmd = "{path}/rados -p {pool} -N '{nspace}' getxattr {name} {key}".format(pool=POOL, name=file, key=key, nspace=nspace, path=CEPH_BIN)
- logging.debug(cmd)
- getval = check_output(cmd, shell=True, stderr=DEVNULL)
- logging.debug("getxattr {key} {val}".format(key=key, val=getval))
- if getval != val:
- logging.error("getxattr of key {key} returned wrong val: {get} instead of {orig}".format(key=key, get=getval, orig=val))
- ERRORS += 1
- continue
- hdr = db[nspace][file].get("omapheader", "")
- cmd = "{path}/rados -p {pool} -N '{nspace}' getomapheader {name} {file}".format(pool=POOL, name=file, nspace=nspace, file=TMPFILE, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stderr=DEVNULL)
- if ret != 0:
- logging.error("rados getomapheader returned {ret}".format(ret=ret))
- ERRORS += 1
- else:
- getlines = get_lines(TMPFILE)
- assert(len(getlines) == 0 or len(getlines) == 1)
- if len(getlines) == 0:
- gethdr = ""
- else:
- gethdr = getlines[0]
- logging.debug("header: {hdr}".format(hdr=gethdr))
- if gethdr != hdr:
- logging.error("getomapheader returned wrong val: {get} instead of {orig}".format(get=gethdr, orig=hdr))
- ERRORS += 1
- for key, val in db[nspace][file]["omap"].items():
- cmd = "{path}/rados -p {pool} -N '{nspace}' getomapval {name} {key} {file}".format(pool=POOL, name=file, key=key, nspace=nspace, file=TMPFILE, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stderr=DEVNULL)
- if ret != 0:
- logging.error("getomapval returned {ret}".format(ret=ret))
- ERRORS += 1
- continue
- getlines = get_lines(TMPFILE)
- if len(getlines) != 1:
- logging.error("Bad data from getomapval {lines}".format(lines=getlines))
- ERRORS += 1
- continue
- getval = getlines[0]
- logging.debug("getomapval {key} {val}".format(key=key, val=getval))
- if getval != val:
- logging.error("getomapval returned wrong val: {get} instead of {orig}".format(get=getval, orig=val))
- ERRORS += 1
- try:
- os.unlink(TMPFILE)
- except:
- pass
- return ERRORS
-
-
-def check_journal(jsondict):
- errors = 0
- if 'header' not in jsondict:
- logging.error("Key 'header' not in dump-journal")
- errors += 1
- elif 'max_size' not in jsondict['header']:
- logging.error("Key 'max_size' not in dump-journal header")
- errors += 1
- else:
- print("\tJournal max_size = {size}".format(size=jsondict['header']['max_size']))
- if 'entries' not in jsondict:
- logging.error("Key 'entries' not in dump-journal output")
- errors += 1
- elif len(jsondict['entries']) == 0:
- logging.info("No entries in journal found")
- else:
- errors += check_journal_entries(jsondict['entries'])
- return errors
-
-
-def check_journal_entries(entries):
- errors = 0
- for enum in range(len(entries)):
- if 'offset' not in entries[enum]:
- logging.error("No 'offset' key in entry {e}".format(e=enum))
- errors += 1
- if 'seq' not in entries[enum]:
- logging.error("No 'seq' key in entry {e}".format(e=enum))
- errors += 1
- if 'transactions' not in entries[enum]:
- logging.error("No 'transactions' key in entry {e}".format(e=enum))
- errors += 1
- elif len(entries[enum]['transactions']) == 0:
- logging.error("No transactions found in entry {e}".format(e=enum))
- errors += 1
- else:
- errors += check_entry_transactions(entries[enum], enum)
- return errors
-
-
-def check_entry_transactions(entry, enum):
- errors = 0
- for tnum in range(len(entry['transactions'])):
- if 'trans_num' not in entry['transactions'][tnum]:
- logging.error("Key 'trans_num' missing from entry {e} trans {t}".format(e=enum, t=tnum))
- errors += 1
- elif entry['transactions'][tnum]['trans_num'] != tnum:
- ft = entry['transactions'][tnum]['trans_num']
- logging.error("Bad trans_num ({ft}) entry {e} trans {t}".format(ft=ft, e=enum, t=tnum))
- errors += 1
- if 'ops' not in entry['transactions'][tnum]:
- logging.error("Key 'ops' missing from entry {e} trans {t}".format(e=enum, t=tnum))
- errors += 1
- else:
- errors += check_transaction_ops(entry['transactions'][tnum]['ops'], enum, tnum)
- return errors
-
-
-def check_transaction_ops(ops, enum, tnum):
- if len(ops) is 0:
- logging.warning("No ops found in entry {e} trans {t}".format(e=enum, t=tnum))
- errors = 0
- for onum in range(len(ops)):
- if 'op_num' not in ops[onum]:
- logging.error("Key 'op_num' missing from entry {e} trans {t} op {o}".format(e=enum, t=tnum, o=onum))
- errors += 1
- elif ops[onum]['op_num'] != onum:
- fo = ops[onum]['op_num']
- logging.error("Bad op_num ({fo}) from entry {e} trans {t} op {o}".format(fo=fo, e=enum, t=tnum, o=onum))
- errors += 1
- if 'op_name' not in ops[onum]:
- logging.error("Key 'op_name' missing from entry {e} trans {t} op {o}".format(e=enum, t=tnum, o=onum))
- errors += 1
- return errors
-
-
-def test_dump_journal(CFSD_PREFIX, osds):
- ERRORS = 0
- pid = os.getpid()
- TMPFILE = r"/tmp/tmp.{pid}".format(pid=pid)
-
- for osd in osds:
- # Test --op dump-journal by loading json
- cmd = (CFSD_PREFIX + "--op dump-journal --format json").format(osd=osd)
- logging.debug(cmd)
- tmpfd = open(TMPFILE, "wb")
- ret = call(cmd, shell=True, stdout=tmpfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from {cmd}".format(ret=ret, cmd=cmd))
- ERRORS += 1
- continue
- tmpfd.close()
- tmpfd = open(TMPFILE, "r")
- jsondict = json.load(tmpfd)
- tmpfd.close()
- os.unlink(TMPFILE)
-
- journal_errors = check_journal(jsondict)
- if journal_errors is not 0:
- logging.error(jsondict)
- ERRORS += journal_errors
-
- return ERRORS
-
-CEPH_BUILD_DIR = os.environ.get('CEPH_BUILD_DIR')
-CEPH_BIN = os.environ.get('CEPH_BIN')
-CEPH_ROOT = os.environ.get('CEPH_ROOT')
-
-if not CEPH_BUILD_DIR:
- CEPH_BUILD_DIR=os.getcwd()
- os.putenv('CEPH_BUILD_DIR', CEPH_BUILD_DIR)
- CEPH_BIN=os.path.join(CEPH_BUILD_DIR, 'bin')
- os.putenv('CEPH_BIN', CEPH_BIN)
- CEPH_ROOT=os.path.dirname(CEPH_BUILD_DIR)
- os.putenv('CEPH_ROOT', CEPH_ROOT)
- CEPH_LIB=os.path.join(CEPH_BUILD_DIR, 'lib')
- os.putenv('CEPH_LIB', CEPH_LIB)
-
-try:
- os.mkdir("td")
-except:
- pass # ok if this is already there
-CEPH_DIR = os.path.join(CEPH_BUILD_DIR, os.path.join("td", "cot_dir"))
-CEPH_CONF = os.path.join(CEPH_DIR, 'ceph.conf')
-
-def kill_daemons():
- call("{path}/init-ceph -c {conf} stop > /dev/null 2>&1".format(conf=CEPH_CONF, path=CEPH_BIN), shell=True)
-
-
-def check_data(DATADIR, TMPFILE, OSDDIR, SPLIT_NAME):
- repcount = 0
- ERRORS = 0
- for rawnsfile in [f for f in os.listdir(DATADIR) if f.split('-')[1].find(SPLIT_NAME) == 0]:
- nsfile = rawnsfile.split("__")[0]
- clone = rawnsfile.split("__")[1]
- nspace = nsfile.split("-")[0]
- file = nsfile.split("-")[1] + "__" + clone
- # Skip clones
- if clone != "head":
- continue
- path = os.path.join(DATADIR, rawnsfile)
- tmpfd = open(TMPFILE, "wb")
- cmd = "find {dir} -name '{file}_*_{nspace}_*'".format(dir=OSDDIR, file=file, nspace=nspace)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=tmpfd)
- if ret:
- logging.critical("INTERNAL ERROR")
- return 1
- tmpfd.close()
- obj_locs = get_lines(TMPFILE)
- if len(obj_locs) == 0:
- logging.error("Can't find imported object {name}".format(name=file))
- ERRORS += 1
- for obj_loc in obj_locs:
- # For btrfs skip snap_* dirs
- if re.search("/snap_[0-9]*/", obj_loc) is not None:
- continue
- repcount += 1
- cmd = "diff -q {src} {obj_loc}".format(src=path, obj_loc=obj_loc)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("{file} data not imported properly into {obj}".format(file=file, obj=obj_loc))
- ERRORS += 1
- return ERRORS, repcount
-
-
-def set_osd_weight(CFSD_PREFIX, osd_ids, osd_path, weight):
- # change the weight of osd.0 to math.pi in the newest osdmap of given osd
- osdmap_file = tempfile.NamedTemporaryFile(delete=True)
- cmd = (CFSD_PREFIX + "--op get-osdmap --file {osdmap_file}").format(osd=osd_path,
- osdmap_file=osdmap_file.name)
- output = check_output(cmd, shell=True)
- epoch = int(re.findall('#(\d+)', output)[0])
-
- new_crush_file = tempfile.NamedTemporaryFile(delete=True)
- old_crush_file = tempfile.NamedTemporaryFile(delete=True)
- ret = call("{path}/osdmaptool --export-crush {crush_file} {osdmap_file}".format(osdmap_file=osdmap_file.name,
- crush_file=old_crush_file.name, path=CEPH_BIN),
- stdout=DEVNULL,
- stderr=DEVNULL,
- shell=True)
- assert(ret == 0)
-
- for osd_id in osd_ids:
- cmd = "{path}/crushtool -i {crush_file} --reweight-item osd.{osd} {weight} -o {new_crush_file}".format(osd=osd_id,
- crush_file=old_crush_file.name,
- weight=weight,
- new_crush_file=new_crush_file.name, path=CEPH_BIN)
- ret = call(cmd, stdout=DEVNULL, shell=True)
- assert(ret == 0)
- old_crush_file, new_crush_file = new_crush_file, old_crush_file
-
- # change them back, since we don't need to preapre for another round
- old_crush_file, new_crush_file = new_crush_file, old_crush_file
- old_crush_file.close()
-
- ret = call("{path}/osdmaptool --import-crush {crush_file} {osdmap_file}".format(osdmap_file=osdmap_file.name,
- crush_file=new_crush_file.name, path=CEPH_BIN),
- stdout=DEVNULL,
- stderr=DEVNULL,
- shell=True)
- assert(ret == 0)
-
- # Minimum test of --dry-run by using it, but not checking anything
- cmd = CFSD_PREFIX + "--op set-osdmap --file {osdmap_file} --epoch {epoch} --force --dry-run"
- cmd = cmd.format(osd=osd_path, osdmap_file=osdmap_file.name, epoch=epoch)
- ret = call(cmd, stdout=DEVNULL, shell=True)
- assert(ret == 0)
-
- # osdmaptool increases the epoch of the changed osdmap, so we need to force the tool
- # to use use a different epoch than the one in osdmap
- cmd = CFSD_PREFIX + "--op set-osdmap --file {osdmap_file} --epoch {epoch} --force"
- cmd = cmd.format(osd=osd_path, osdmap_file=osdmap_file.name, epoch=epoch)
- ret = call(cmd, stdout=DEVNULL, shell=True)
-
- return ret == 0
-
-def get_osd_weights(CFSD_PREFIX, osd_ids, osd_path):
- osdmap_file = tempfile.NamedTemporaryFile(delete=True)
- cmd = (CFSD_PREFIX + "--op get-osdmap --file {osdmap_file}").format(osd=osd_path,
- osdmap_file=osdmap_file.name)
- ret = call(cmd, stdout=DEVNULL, shell=True)
- if ret != 0:
- return None
- # we have to read the weights from the crush map, even we can query the weights using
- # osdmaptool, but please keep in mind, they are different:
- # item weights in crush map versus weight associated with each osd in osdmap
- crush_file = tempfile.NamedTemporaryFile(delete=True)
- ret = call("{path}/osdmaptool --export-crush {crush_file} {osdmap_file}".format(osdmap_file=osdmap_file.name,
- crush_file=crush_file.name, path=CEPH_BIN),
- stdout=DEVNULL,
- shell=True)
- assert(ret == 0)
- output = check_output("{path}/crushtool --tree -i {crush_file} | tail -n {num_osd}".format(crush_file=crush_file.name,
- num_osd=len(osd_ids), path=CEPH_BIN),
- stderr=DEVNULL,
- shell=True)
- weights = []
- for line in output.strip().split('\n'):
- print(line)
- linev = re.split('\s+', line)
- if linev[0] is '':
- linev.pop(0)
- print('linev %s' % linev)
- weights.append(float(linev[2]))
-
- return weights
-
-
-def test_get_set_osdmap(CFSD_PREFIX, osd_ids, osd_paths):
- print("Testing get-osdmap and set-osdmap")
- errors = 0
- kill_daemons()
- weight = 1 / math.e # just some magic number in [0, 1]
- changed = []
- for osd_path in osd_paths:
- if set_osd_weight(CFSD_PREFIX, osd_ids, osd_path, weight):
- changed.append(osd_path)
- else:
- logging.warning("Failed to change the weights: {0}".format(osd_path))
- # i am pissed off if none of the store gets changed
- if not changed:
- errors += 1
-
- for osd_path in changed:
- weights = get_osd_weights(CFSD_PREFIX, osd_ids, osd_path)
- if not weights:
- errors += 1
- continue
- if any(abs(w - weight) > 1e-5 for w in weights):
- logging.warning("Weight is not changed: {0} != {1}".format(weights, weight))
- errors += 1
- return errors
-
-def test_get_set_inc_osdmap(CFSD_PREFIX, osd_path):
- # incrementals are not used unless we need to build an MOSDMap to update
- # OSD's peers, so an obvious way to test it is simply overwrite an epoch
- # with a different copy, and read it back to see if it matches.
- kill_daemons()
- file_e2 = tempfile.NamedTemporaryFile(delete=True)
- cmd = (CFSD_PREFIX + "--op get-inc-osdmap --file {file}").format(osd=osd_path,
- file=file_e2.name)
- output = check_output(cmd, shell=True)
- epoch = int(re.findall('#(\d+)', output)[0])
- # backup e1 incremental before overwriting it
- epoch -= 1
- file_e1_backup = tempfile.NamedTemporaryFile(delete=True)
- cmd = CFSD_PREFIX + "--op get-inc-osdmap --epoch {epoch} --file {file}"
- ret = call(cmd.format(osd=osd_path, epoch=epoch, file=file_e1_backup.name), shell=True)
- if ret: return 1
- # overwrite e1 with e2
- cmd = CFSD_PREFIX + "--op set-inc-osdmap --force --epoch {epoch} --file {file}"
- ret = call(cmd.format(osd=osd_path, epoch=epoch, file=file_e2.name), shell=True)
- if ret: return 1
- # Use dry-run to set back to e1 which shouldn't happen
- cmd = CFSD_PREFIX + "--op set-inc-osdmap --dry-run --epoch {epoch} --file {file}"
- ret = call(cmd.format(osd=osd_path, epoch=epoch, file=file_e1_backup.name), shell=True)
- if ret: return 1
- # read from e1
- file_e1_read = tempfile.NamedTemporaryFile(delete=True)
- cmd = CFSD_PREFIX + "--op get-inc-osdmap --epoch {epoch} --file {file}"
- ret = call(cmd.format(osd=osd_path, epoch=epoch, file=file_e1_read.name), shell=True)
- if ret: return 1
- errors = 0
- try:
- if not filecmp.cmp(file_e2.name, file_e1_read.name, shallow=False):
- logging.error("{{get,set}}-inc-osdmap mismatch {0} != {1}".format(file_e2.name, file_e1_read.name))
- errors += 1
- finally:
- # revert the change with file_e1_backup
- cmd = CFSD_PREFIX + "--op set-inc-osdmap --epoch {epoch} --file {file}"
- ret = call(cmd.format(osd=osd_path, epoch=epoch, file=file_e1_backup.name), shell=True)
- if ret:
- logging.error("Failed to revert the changed inc-osdmap")
- errors += 1
-
- return errors
-
-
-def test_removeall(CFSD_PREFIX, db, OBJREPPGS, REP_POOL, CEPH_BIN, OSDDIR, REP_NAME, NUM_CLONED_REP_OBJECTS):
- # Test removeall
- TMPFILE = r"/tmp/tmp.{pid}".format(pid=os.getpid())
- nullfd = open(os.devnull, "w")
- errors=0
- print("Test removeall")
- kill_daemons()
- for nspace in db.keys():
- for basename in db[nspace].keys():
- JSON = db[nspace][basename]['json']
- for pg in OBJREPPGS:
- OSDS = get_osds(pg, OSDDIR)
- for osd in OSDS:
- DIR = os.path.join(OSDDIR, os.path.join(osd, os.path.join("current", "{pg}_head".format(pg=pg))))
- fnames = [f for f in os.listdir(DIR) if os.path.isfile(os.path.join(DIR, f))
- and f.split("_")[0] == basename and f.split("_")[4] == nspace]
- if not fnames:
- continue
-
- if int(basename.split(REP_NAME)[1]) <= int(NUM_CLONED_REP_OBJECTS):
- cmd = (CFSD_PREFIX + "'{json}' remove").format(osd=osd, json=JSON)
- errors += test_failure(cmd, "Snapshots are present, use removeall to delete everything")
-
- cmd = (CFSD_PREFIX + " --force --dry-run '{json}' remove").format(osd=osd, json=JSON)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- if ret != 0:
- logging.error("remove with --force failed for {json}".format(json=JSON))
- errors += 1
-
- cmd = (CFSD_PREFIX + " --dry-run '{json}' removeall").format(osd=osd, json=JSON)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- if ret != 0:
- logging.error("removeall failed for {json}".format(json=JSON))
- errors += 1
-
- cmd = (CFSD_PREFIX + " '{json}' removeall").format(osd=osd, json=JSON)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- if ret != 0:
- logging.error("removeall failed for {json}".format(json=JSON))
- errors += 1
-
- tmpfd = open(TMPFILE, "w")
- cmd = (CFSD_PREFIX + "--op list --pgid {pg} --namespace {ns} {name}").format(osd=osd, pg=pg, ns=nspace, name=basename)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=tmpfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from {cmd}".format(ret=ret, cmd=cmd))
- errors += 1
- tmpfd.close()
- lines = get_lines(TMPFILE)
- if len(lines) != 0:
- logging.error("Removeall didn't remove all objects {ns}/{name} : {lines}".format(ns=nspace, name=basename, lines=lines))
- errors += 1
- vstart(new=False)
- wait_for_health()
- cmd = "{path}/rados -p {pool} rmsnap snap1".format(pool=REP_POOL, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- if ret != 0:
- logging.error("rados rmsnap failed")
- errors += 1
- time.sleep(2)
- wait_for_health()
- return errors
-
-
-def main(argv):
- if sys.version_info[0] < 3:
- sys.stdout = stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
- else:
- stdout = sys.stdout.buffer
- if len(argv) > 1 and argv[1] == "debug":
- nullfd = stdout
- else:
- nullfd = DEVNULL
-
- call("rm -fr {dir}; mkdir -p {dir}".format(dir=CEPH_DIR), shell=True)
- os.chdir(CEPH_DIR)
- os.environ["CEPH_DIR"] = CEPH_DIR
- OSDDIR = "dev"
- REP_POOL = "rep_pool"
- REP_NAME = "REPobject"
- EC_POOL = "ec_pool"
- EC_NAME = "ECobject"
- if len(argv) > 0 and argv[0] == 'large':
- PG_COUNT = 12
- NUM_REP_OBJECTS = 800
- NUM_CLONED_REP_OBJECTS = 100
- NUM_EC_OBJECTS = 12
- NUM_NSPACES = 4
- # Larger data sets for first object per namespace
- DATALINECOUNT = 50000
- # Number of objects to do xattr/omap testing on
- ATTR_OBJS = 10
- else:
- PG_COUNT = 4
- NUM_REP_OBJECTS = 2
- NUM_CLONED_REP_OBJECTS = 2
- NUM_EC_OBJECTS = 2
- NUM_NSPACES = 2
- # Larger data sets for first object per namespace
- DATALINECOUNT = 10
- # Number of objects to do xattr/omap testing on
- ATTR_OBJS = 2
- ERRORS = 0
- pid = os.getpid()
- TESTDIR = "/tmp/test.{pid}".format(pid=pid)
- DATADIR = "/tmp/data.{pid}".format(pid=pid)
- CFSD_PREFIX = CEPH_BIN + "/ceph-objectstore-tool --data-path " + OSDDIR + "/{osd} "
- PROFNAME = "testecprofile"
-
- os.environ['CEPH_CONF'] = CEPH_CONF
- vstart(new=True)
- wait_for_health()
-
- cmd = "{path}/ceph osd pool create {pool} {pg} {pg} replicated".format(pool=REP_POOL, pg=PG_COUNT, path=CEPH_BIN)
- logging.debug(cmd)
- call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- time.sleep(2)
- REPID = get_pool_id(REP_POOL, nullfd)
-
- print("Created Replicated pool #{repid}".format(repid=REPID))
-
- cmd = "{path}/ceph osd erasure-code-profile set {prof} crush-failure-domain=osd".format(prof=PROFNAME, path=CEPH_BIN)
- logging.debug(cmd)
- call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- cmd = "{path}/ceph osd erasure-code-profile get {prof}".format(prof=PROFNAME, path=CEPH_BIN)
- logging.debug(cmd)
- call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- cmd = "{path}/ceph osd pool create {pool} {pg} {pg} erasure {prof}".format(pool=EC_POOL, prof=PROFNAME, pg=PG_COUNT, path=CEPH_BIN)
- logging.debug(cmd)
- call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- ECID = get_pool_id(EC_POOL, nullfd)
-
- print("Created Erasure coded pool #{ecid}".format(ecid=ECID))
-
- print("Creating {objs} objects in replicated pool".format(objs=(NUM_REP_OBJECTS*NUM_NSPACES)))
- cmd = "mkdir -p {datadir}".format(datadir=DATADIR)
- logging.debug(cmd)
- call(cmd, shell=True)
-
- db = {}
-
- objects = range(1, NUM_REP_OBJECTS + 1)
- nspaces = range(NUM_NSPACES)
- for n in nspaces:
- nspace = get_nspace(n)
-
- db[nspace] = {}
-
- for i in objects:
- NAME = REP_NAME + "{num}".format(num=i)
- LNAME = nspace + "-" + NAME
- DDNAME = os.path.join(DATADIR, LNAME)
- DDNAME += "__head"
-
- cmd = "rm -f " + DDNAME
- logging.debug(cmd)
- call(cmd, shell=True)
-
- if i == 1:
- dataline = range(DATALINECOUNT)
- else:
- dataline = range(1)
- fd = open(DDNAME, "w")
- data = "This is the replicated data for " + LNAME + "\n"
- for _ in dataline:
- fd.write(data)
- fd.close()
-
- cmd = "{path}/rados -p {pool} -N '{nspace}' put {name} {ddname}".format(pool=REP_POOL, name=NAME, ddname=DDNAME, nspace=nspace, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stderr=nullfd)
- if ret != 0:
- logging.critical("Rados put command failed with {ret}".format(ret=ret))
- return 1
-
- db[nspace][NAME] = {}
-
- if i < ATTR_OBJS + 1:
- keys = range(i)
- else:
- keys = range(0)
- db[nspace][NAME]["xattr"] = {}
- for k in keys:
- if k == 0:
- continue
- mykey = "key{i}-{k}".format(i=i, k=k)
- myval = "val{i}-{k}".format(i=i, k=k)
- cmd = "{path}/rados -p {pool} -N '{nspace}' setxattr {name} {key} {val}".format(pool=REP_POOL, name=NAME, key=mykey, val=myval, nspace=nspace, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("setxattr failed with {ret}".format(ret=ret))
- ERRORS += 1
- db[nspace][NAME]["xattr"][mykey] = myval
-
- # Create omap header in all objects but REPobject1
- if i < ATTR_OBJS + 1 and i != 1:
- myhdr = "hdr{i}".format(i=i)
- cmd = "{path}/rados -p {pool} -N '{nspace}' setomapheader {name} {hdr}".format(pool=REP_POOL, name=NAME, hdr=myhdr, nspace=nspace, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.critical("setomapheader failed with {ret}".format(ret=ret))
- ERRORS += 1
- db[nspace][NAME]["omapheader"] = myhdr
-
- db[nspace][NAME]["omap"] = {}
- for k in keys:
- if k == 0:
- continue
- mykey = "okey{i}-{k}".format(i=i, k=k)
- myval = "oval{i}-{k}".format(i=i, k=k)
- cmd = "{path}/rados -p {pool} -N '{nspace}' setomapval {name} {key} {val}".format(pool=REP_POOL, name=NAME, key=mykey, val=myval, nspace=nspace, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.critical("setomapval failed with {ret}".format(ret=ret))
- db[nspace][NAME]["omap"][mykey] = myval
-
- # Create some clones
- cmd = "{path}/rados -p {pool} mksnap snap1".format(pool=REP_POOL, path=CEPH_BIN)
- logging.debug(cmd)
- call(cmd, shell=True)
-
- objects = range(1, NUM_CLONED_REP_OBJECTS + 1)
- nspaces = range(NUM_NSPACES)
- for n in nspaces:
- nspace = get_nspace(n)
-
- for i in objects:
- NAME = REP_NAME + "{num}".format(num=i)
- LNAME = nspace + "-" + NAME
- DDNAME = os.path.join(DATADIR, LNAME)
- # First clone
- CLONENAME = DDNAME + "__1"
- DDNAME += "__head"
-
- cmd = "mv -f " + DDNAME + " " + CLONENAME
- logging.debug(cmd)
- call(cmd, shell=True)
-
- if i == 1:
- dataline = range(DATALINECOUNT)
- else:
- dataline = range(1)
- fd = open(DDNAME, "w")
- data = "This is the replicated data after a snapshot for " + LNAME + "\n"
- for _ in dataline:
- fd.write(data)
- fd.close()
-
- cmd = "{path}/rados -p {pool} -N '{nspace}' put {name} {ddname}".format(pool=REP_POOL, name=NAME, ddname=DDNAME, nspace=nspace, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stderr=nullfd)
- if ret != 0:
- logging.critical("Rados put command failed with {ret}".format(ret=ret))
- return 1
-
- print("Creating {objs} objects in erasure coded pool".format(objs=(NUM_EC_OBJECTS*NUM_NSPACES)))
-
- objects = range(1, NUM_EC_OBJECTS + 1)
- nspaces = range(NUM_NSPACES)
- for n in nspaces:
- nspace = get_nspace(n)
-
- for i in objects:
- NAME = EC_NAME + "{num}".format(num=i)
- LNAME = nspace + "-" + NAME
- DDNAME = os.path.join(DATADIR, LNAME)
- DDNAME += "__head"
-
- cmd = "rm -f " + DDNAME
- logging.debug(cmd)
- call(cmd, shell=True)
-
- if i == 1:
- dataline = range(DATALINECOUNT)
- else:
- dataline = range(1)
- fd = open(DDNAME, "w")
- data = "This is the erasure coded data for " + LNAME + "\n"
- for j in dataline:
- fd.write(data)
- fd.close()
-
- cmd = "{path}/rados -p {pool} -N '{nspace}' put {name} {ddname}".format(pool=EC_POOL, name=NAME, ddname=DDNAME, nspace=nspace, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stderr=nullfd)
- if ret != 0:
- logging.critical("Erasure coded pool creation failed with {ret}".format(ret=ret))
- return 1
-
- db[nspace][NAME] = {}
-
- db[nspace][NAME]["xattr"] = {}
- if i < ATTR_OBJS + 1:
- keys = range(i)
- else:
- keys = range(0)
- for k in keys:
- if k == 0:
- continue
- mykey = "key{i}-{k}".format(i=i, k=k)
- myval = "val{i}-{k}".format(i=i, k=k)
- cmd = "{path}/rados -p {pool} -N '{nspace}' setxattr {name} {key} {val}".format(pool=EC_POOL, name=NAME, key=mykey, val=myval, nspace=nspace, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("setxattr failed with {ret}".format(ret=ret))
- ERRORS += 1
- db[nspace][NAME]["xattr"][mykey] = myval
-
- # Omap isn't supported in EC pools
- db[nspace][NAME]["omap"] = {}
-
- logging.debug(db)
-
- kill_daemons()
-
- if ERRORS:
- logging.critical("Unable to set up test")
- return 1
-
- ALLREPPGS = get_pgs(OSDDIR, REPID)
- logging.debug(ALLREPPGS)
- ALLECPGS = get_pgs(OSDDIR, ECID)
- logging.debug(ALLECPGS)
-
- OBJREPPGS = get_objs(ALLREPPGS, REP_NAME, OSDDIR, REPID)
- logging.debug(OBJREPPGS)
- OBJECPGS = get_objs(ALLECPGS, EC_NAME, OSDDIR, ECID)
- logging.debug(OBJECPGS)
-
- ONEPG = ALLREPPGS[0]
- logging.debug(ONEPG)
- osds = get_osds(ONEPG, OSDDIR)
- ONEOSD = osds[0]
- logging.debug(ONEOSD)
-
- print("Test invalid parameters")
- # On export can't use stdout to a terminal
- cmd = (CFSD_PREFIX + "--op export --pgid {pg}").format(osd=ONEOSD, pg=ONEPG)
- ERRORS += test_failure(cmd, "stdout is a tty and no --file filename specified", tty=True)
-
- # On export can't use stdout to a terminal
- cmd = (CFSD_PREFIX + "--op export --pgid {pg} --file -").format(osd=ONEOSD, pg=ONEPG)
- ERRORS += test_failure(cmd, "stdout is a tty and no --file filename specified", tty=True)
-
- # Prep a valid ec export file for import failure tests
- ONEECPG = ALLECPGS[0]
- osds = get_osds(ONEECPG, OSDDIR)
- ONEECOSD = osds[0]
- OTHERFILE = "/tmp/foo.{pid}".format(pid=pid)
- cmd = (CFSD_PREFIX + "--op export --pgid {pg} --file {file}").format(osd=ONEECOSD, pg=ONEECPG, file=OTHERFILE)
- logging.debug(cmd)
- call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
-
- # On import can't specify a different shard
- BADPG = ONEECPG.split('s')[0] + "s10"
- cmd = (CFSD_PREFIX + "--op import --pgid {pg} --file {file}").format(osd=ONEECOSD, pg=BADPG, file=OTHERFILE)
- ERRORS += test_failure(cmd, "Can't specify a different shard, must be")
-
- os.unlink(OTHERFILE)
-
- # Prep a valid export file for import failure tests
- OTHERFILE = "/tmp/foo.{pid}".format(pid=pid)
- cmd = (CFSD_PREFIX + "--op export --pgid {pg} --file {file}").format(osd=ONEOSD, pg=ONEPG, file=OTHERFILE)
- logging.debug(cmd)
- call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
-
- # On import can't specify a PG with a non-existent pool
- cmd = (CFSD_PREFIX + "--op import --pgid {pg} --file {file}").format(osd=ONEOSD, pg="10.0", file=OTHERFILE)
- ERRORS += test_failure(cmd, "Can't specify a different pgid pool, must be")
-
- # On import can't specify shard for a replicated export
- cmd = (CFSD_PREFIX + "--op import --pgid {pg}s0 --file {file}").format(osd=ONEOSD, pg=ONEPG, file=OTHERFILE)
- ERRORS += test_failure(cmd, "Can't specify a sharded pgid with a non-sharded export")
-
- # On import can't specify a PG with a bad seed
- TMPPG="{pool}.80".format(pool=REPID)
- cmd = (CFSD_PREFIX + "--op import --pgid {pg} --file {file}").format(osd=ONEOSD, pg=TMPPG, file=OTHERFILE)
- ERRORS += test_failure(cmd, "Illegal pgid, the seed is larger than current pg_num")
-
- os.unlink(OTHERFILE)
- cmd = (CFSD_PREFIX + "--op import --file {FOO}").format(osd=ONEOSD, FOO=OTHERFILE)
- ERRORS += test_failure(cmd, "file: {FOO}: No such file or directory".format(FOO=OTHERFILE))
-
- cmd = "{path}/ceph-objectstore-tool --data-path BAD_DATA_PATH --op list".format(osd=ONEOSD, path=CEPH_BIN)
- ERRORS += test_failure(cmd, "data-path: BAD_DATA_PATH: No such file or directory")
-
- cmd = "{path}/ceph-objectstore-tool --journal-path BAD_JOURNAL_PATH --op dump-journal".format(path=CEPH_BIN)
- ERRORS += test_failure(cmd, "journal-path: BAD_JOURNAL_PATH: (2) No such file or directory")
-
- cmd = (CFSD_PREFIX + "--journal-path BAD_JOURNAL_PATH --op list").format(osd=ONEOSD)
- ERRORS += test_failure(cmd, "journal-path: BAD_JOURNAL_PATH: No such file or directory")
-
- cmd = (CFSD_PREFIX + "--journal-path /bin --op list").format(osd=ONEOSD)
- ERRORS += test_failure(cmd, "journal-path: /bin: (21) Is a directory")
-
- # On import can't use stdin from a terminal
- cmd = (CFSD_PREFIX + "--op import --pgid {pg}").format(osd=ONEOSD, pg=ONEPG)
- ERRORS += test_failure(cmd, "stdin is a tty and no --file filename specified", tty=True)
-
- # On import can't use stdin from a terminal
- cmd = (CFSD_PREFIX + "--op import --pgid {pg} --file -").format(osd=ONEOSD, pg=ONEPG)
- ERRORS += test_failure(cmd, "stdin is a tty and no --file filename specified", tty=True)
-
- # Specify a bad --type
- os.mkdir(OSDDIR + "/fakeosd")
- cmd = ("{path}/ceph-objectstore-tool --data-path " + OSDDIR + "/{osd} --type foobar --op list --pgid {pg}").format(osd="fakeosd", pg=ONEPG, path=CEPH_BIN)
- ERRORS += test_failure(cmd, "Unable to create store of type foobar")
-
- # Don't specify a data-path
- cmd = "{path}/ceph-objectstore-tool --type memstore --op list --pgid {pg}".format(dir=OSDDIR, osd=ONEOSD, pg=ONEPG, path=CEPH_BIN)
- ERRORS += test_failure(cmd, "Must provide --data-path")
-
- cmd = (CFSD_PREFIX + "--op remove --pgid 2.0").format(osd=ONEOSD)
- ERRORS += test_failure(cmd, "Please use export-remove or you must use --force option")
-
- cmd = (CFSD_PREFIX + "--force --op remove").format(osd=ONEOSD)
- ERRORS += test_failure(cmd, "Must provide pgid")
-
- # Don't secify a --op nor object command
- cmd = CFSD_PREFIX.format(osd=ONEOSD)
- ERRORS += test_failure(cmd, "Must provide --op or object command...")
-
- # Specify a bad --op command
- cmd = (CFSD_PREFIX + "--op oops").format(osd=ONEOSD)
- ERRORS += test_failure(cmd, "Must provide --op (info, log, remove, mkfs, fsck, export, export-remove, import, list, fix-lost, list-pgs, rm-past-intervals, dump-journal, dump-super, meta-list, get-osdmap, set-osdmap, get-inc-osdmap, set-inc-osdmap, mark-complete)")
-
- # Provide just the object param not a command
- cmd = (CFSD_PREFIX + "object").format(osd=ONEOSD)
- ERRORS += test_failure(cmd, "Invalid syntax, missing command")
-
- # Provide an object name that doesn't exist
- cmd = (CFSD_PREFIX + "NON_OBJECT get-bytes").format(osd=ONEOSD)
- ERRORS += test_failure(cmd, "No object id 'NON_OBJECT' found")
-
- # Provide an invalid object command
- cmd = (CFSD_PREFIX + "--pgid {pg} '' notacommand").format(osd=ONEOSD, pg=ONEPG)
- ERRORS += test_failure(cmd, "Unknown object command 'notacommand'")
-
- cmd = (CFSD_PREFIX + "foo list-omap").format(osd=ONEOSD, pg=ONEPG)
- ERRORS += test_failure(cmd, "No object id 'foo' found or invalid JSON specified")
-
- cmd = (CFSD_PREFIX + "'{{\"oid\":\"obj4\",\"key\":\"\",\"snapid\":-1,\"hash\":2826278768,\"max\":0,\"pool\":1,\"namespace\":\"\"}}' list-omap").format(osd=ONEOSD, pg=ONEPG)
- ERRORS += test_failure(cmd, "Without --pgid the object '{\"oid\":\"obj4\",\"key\":\"\",\"snapid\":-1,\"hash\":2826278768,\"max\":0,\"pool\":1,\"namespace\":\"\"}' must be a JSON array")
-
- cmd = (CFSD_PREFIX + "'[]' list-omap").format(osd=ONEOSD, pg=ONEPG)
- ERRORS += test_failure(cmd, "Object '[]' must be a JSON array with 2 elements")
-
- cmd = (CFSD_PREFIX + "'[\"1.0\"]' list-omap").format(osd=ONEOSD, pg=ONEPG)
- ERRORS += test_failure(cmd, "Object '[\"1.0\"]' must be a JSON array with 2 elements")
-
- cmd = (CFSD_PREFIX + "'[\"1.0\", 5, 8, 9]' list-omap").format(osd=ONEOSD, pg=ONEPG)
- ERRORS += test_failure(cmd, "Object '[\"1.0\", 5, 8, 9]' must be a JSON array with 2 elements")
-
- cmd = (CFSD_PREFIX + "'[1, 2]' list-omap").format(osd=ONEOSD, pg=ONEPG)
- ERRORS += test_failure(cmd, "Object '[1, 2]' must be a JSON array with the first element a string")
-
- cmd = (CFSD_PREFIX + "'[\"1.3\",{{\"snapid\":\"not an int\"}}]' list-omap").format(osd=ONEOSD, pg=ONEPG)
- ERRORS += test_failure(cmd, "Decode object JSON error: value type is 2 not 4")
-
- TMPFILE = r"/tmp/tmp.{pid}".format(pid=pid)
- ALLPGS = OBJREPPGS + OBJECPGS
- OSDS = get_osds(ALLPGS[0], OSDDIR)
- osd = OSDS[0]
-
- print("Test all --op dump-journal")
- ALLOSDS = [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]
- ERRORS += test_dump_journal(CFSD_PREFIX, ALLOSDS)
-
- # Test --op list and generate json for all objects
- print("Test --op list variants")
-
- # retrieve all objects from all PGs
- tmpfd = open(TMPFILE, "wb")
- cmd = (CFSD_PREFIX + "--op list --format json").format(osd=osd)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=tmpfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from {cmd}".format(ret=ret, cmd=cmd))
- ERRORS += 1
- tmpfd.close()
- lines = get_lines(TMPFILE)
- JSONOBJ = sorted(set(lines))
- (pgid, coll, jsondict) = json.loads(JSONOBJ[0])[0]
-
- # retrieve all objects in a given PG
- tmpfd = open(OTHERFILE, "ab")
- cmd = (CFSD_PREFIX + "--op list --pgid {pg} --format json").format(osd=osd, pg=pgid)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=tmpfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from {cmd}".format(ret=ret, cmd=cmd))
- ERRORS += 1
- tmpfd.close()
- lines = get_lines(OTHERFILE)
- JSONOBJ = sorted(set(lines))
- (other_pgid, other_coll, other_jsondict) = json.loads(JSONOBJ[0])[0]
-
- if pgid != other_pgid or jsondict != other_jsondict or coll != other_coll:
- logging.error("the first line of --op list is different "
- "from the first line of --op list --pgid {pg}".format(pg=pgid))
- ERRORS += 1
-
- # retrieve all objects with a given name in a given PG
- tmpfd = open(OTHERFILE, "wb")
- cmd = (CFSD_PREFIX + "--op list --pgid {pg} {object} --format json").format(osd=osd, pg=pgid, object=jsondict['oid'])
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=tmpfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from {cmd}".format(ret=ret, cmd=cmd))
- ERRORS += 1
- tmpfd.close()
- lines = get_lines(OTHERFILE)
- JSONOBJ = sorted(set(lines))
- (other_pgid, other_coll, other_jsondict) in json.loads(JSONOBJ[0])[0]
-
- if pgid != other_pgid or jsondict != other_jsondict or coll != other_coll:
- logging.error("the first line of --op list is different "
- "from the first line of --op list --pgid {pg} {object}".format(pg=pgid, object=jsondict['oid']))
- ERRORS += 1
-
- print("Test --op list by generating json for all objects using default format")
- for pg in ALLPGS:
- OSDS = get_osds(pg, OSDDIR)
- for osd in OSDS:
- tmpfd = open(TMPFILE, "ab")
- cmd = (CFSD_PREFIX + "--op list --pgid {pg}").format(osd=osd, pg=pg)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=tmpfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from --op list request".format(ret=ret))
- ERRORS += 1
-
- tmpfd.close()
- lines = get_lines(TMPFILE)
- JSONOBJ = sorted(set(lines))
- for JSON in JSONOBJ:
- (pgid, jsondict) = json.loads(JSON)
- # Skip clones for now
- if jsondict['snapid'] != -2:
- continue
- db[jsondict['namespace']][jsondict['oid']]['json'] = json.dumps((pgid, jsondict))
- # print db[jsondict['namespace']][jsondict['oid']]['json']
- if jsondict['oid'].find(EC_NAME) == 0 and 'shard_id' not in jsondict:
- logging.error("Malformed JSON {json}".format(json=JSON))
- ERRORS += 1
-
- # Test get-bytes
- print("Test get-bytes and set-bytes")
- for nspace in db.keys():
- for basename in db[nspace].keys():
- file = os.path.join(DATADIR, nspace + "-" + basename + "__head")
- JSON = db[nspace][basename]['json']
- GETNAME = "/tmp/getbytes.{pid}".format(pid=pid)
- TESTNAME = "/tmp/testbytes.{pid}".format(pid=pid)
- SETNAME = "/tmp/setbytes.{pid}".format(pid=pid)
- BADNAME = "/tmp/badbytes.{pid}".format(pid=pid)
- for pg in OBJREPPGS:
- OSDS = get_osds(pg, OSDDIR)
- for osd in OSDS:
- DIR = os.path.join(OSDDIR, os.path.join(osd, os.path.join("current", "{pg}_head".format(pg=pg))))
- fnames = [f for f in os.listdir(DIR) if os.path.isfile(os.path.join(DIR, f))
- and f.split("_")[0] == basename and f.split("_")[4] == nspace]
- if not fnames:
- continue
- try:
- os.unlink(GETNAME)
- except:
- pass
- cmd = (CFSD_PREFIX + " --pgid {pg} '{json}' get-bytes {fname}").format(osd=osd, pg=pg, json=JSON, fname=GETNAME)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret}".format(ret=ret))
- ERRORS += 1
- continue
- cmd = "diff -q {file} {getfile}".format(file=file, getfile=GETNAME)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Data from get-bytes differ")
- logging.debug("Got:")
- cat_file(logging.DEBUG, GETNAME)
- logging.debug("Expected:")
- cat_file(logging.DEBUG, file)
- ERRORS += 1
- fd = open(SETNAME, "w")
- data = "put-bytes going into {file}\n".format(file=file)
- fd.write(data)
- fd.close()
- cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' set-bytes {sname}").format(osd=osd, pg=pg, json=JSON, sname=SETNAME)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret} from set-bytes".format(ret=ret))
- ERRORS += 1
- fd = open(TESTNAME, "wb")
- cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' get-bytes -").format(osd=osd, pg=pg, json=JSON)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=fd)
- fd.close()
- if ret != 0:
- logging.error("Bad exit status {ret} from get-bytes".format(ret=ret))
- ERRORS += 1
- cmd = "diff -q {setfile} {testfile}".format(setfile=SETNAME, testfile=TESTNAME)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Data after set-bytes differ")
- logging.debug("Got:")
- cat_file(logging.DEBUG, TESTNAME)
- logging.debug("Expected:")
- cat_file(logging.DEBUG, SETNAME)
- ERRORS += 1
-
- # Use set-bytes with --dry-run and make sure contents haven't changed
- fd = open(BADNAME, "w")
- data = "Bad data for --dry-run in {file}\n".format(file=file)
- fd.write(data)
- fd.close()
- cmd = (CFSD_PREFIX + "--dry-run --pgid {pg} '{json}' set-bytes {sname}").format(osd=osd, pg=pg, json=JSON, sname=BADNAME)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from set-bytes --dry-run".format(ret=ret))
- ERRORS += 1
- fd = open(TESTNAME, "wb")
- cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' get-bytes -").format(osd=osd, pg=pg, json=JSON)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=fd)
- fd.close()
- if ret != 0:
- logging.error("Bad exit status {ret} from get-bytes".format(ret=ret))
- ERRORS += 1
- cmd = "diff -q {setfile} {testfile}".format(setfile=SETNAME, testfile=TESTNAME)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Data after set-bytes --dry-run changed!")
- logging.debug("Got:")
- cat_file(logging.DEBUG, TESTNAME)
- logging.debug("Expected:")
- cat_file(logging.DEBUG, SETNAME)
- ERRORS += 1
-
- fd = open(file, "rb")
- cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' set-bytes").format(osd=osd, pg=pg, json=JSON)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdin=fd)
- if ret != 0:
- logging.error("Bad exit status {ret} from set-bytes to restore object".format(ret=ret))
- ERRORS += 1
- fd.close()
-
- try:
- os.unlink(GETNAME)
- except:
- pass
- try:
- os.unlink(TESTNAME)
- except:
- pass
- try:
- os.unlink(SETNAME)
- except:
- pass
- try:
- os.unlink(BADNAME)
- except:
- pass
-
- # Test get-attr, set-attr, rm-attr, get-omaphdr, set-omaphdr, get-omap, set-omap, rm-omap
- print("Test get-attr, set-attr, rm-attr, get-omaphdr, set-omaphdr, get-omap, set-omap, rm-omap")
- for nspace in db.keys():
- for basename in db[nspace].keys():
- file = os.path.join(DATADIR, nspace + "-" + basename + "__head")
- JSON = db[nspace][basename]['json']
- for pg in OBJREPPGS:
- OSDS = get_osds(pg, OSDDIR)
- for osd in OSDS:
- DIR = os.path.join(OSDDIR, os.path.join(osd, os.path.join("current", "{pg}_head".format(pg=pg))))
- fnames = [f for f in os.listdir(DIR) if os.path.isfile(os.path.join(DIR, f))
- and f.split("_")[0] == basename and f.split("_")[4] == nspace]
- if not fnames:
- continue
- for key, val in db[nspace][basename]["xattr"].items():
- attrkey = "_" + key
- cmd = (CFSD_PREFIX + " '{json}' get-attr {key}").format(osd=osd, json=JSON, key=attrkey)
- logging.debug(cmd)
- getval = check_output(cmd, shell=True)
- if getval != val:
- logging.error("get-attr of key {key} returned wrong val: {get} instead of {orig}".format(key=attrkey, get=getval, orig=val))
- ERRORS += 1
- continue
- # set-attr to bogus value "foobar"
- cmd = ("echo -n foobar | " + CFSD_PREFIX + " --pgid {pg} '{json}' set-attr {key}").format(osd=osd, pg=pg, json=JSON, key=attrkey)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret} from set-attr".format(ret=ret))
- ERRORS += 1
- continue
- # Test set-attr with dry-run
- cmd = ("echo -n dryrunbroken | " + CFSD_PREFIX + "--dry-run '{json}' set-attr {key}").format(osd=osd, pg=pg, json=JSON, key=attrkey)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from set-attr".format(ret=ret))
- ERRORS += 1
- continue
- # Check the set-attr
- cmd = (CFSD_PREFIX + " --pgid {pg} '{json}' get-attr {key}").format(osd=osd, pg=pg, json=JSON, key=attrkey)
- logging.debug(cmd)
- getval = check_output(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret} from get-attr".format(ret=ret))
- ERRORS += 1
- continue
- if getval != "foobar":
- logging.error("Check of set-attr failed because we got {val}".format(val=getval))
- ERRORS += 1
- continue
- # Test rm-attr
- cmd = (CFSD_PREFIX + "'{json}' rm-attr {key}").format(osd=osd, pg=pg, json=JSON, key=attrkey)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret} from rm-attr".format(ret=ret))
- ERRORS += 1
- continue
- # Check rm-attr with dry-run
- cmd = (CFSD_PREFIX + "--dry-run '{json}' rm-attr {key}").format(osd=osd, pg=pg, json=JSON, key=attrkey)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from rm-attr".format(ret=ret))
- ERRORS += 1
- continue
- cmd = (CFSD_PREFIX + "'{json}' get-attr {key}").format(osd=osd, pg=pg, json=JSON, key=attrkey)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stderr=nullfd, stdout=nullfd)
- if ret == 0:
- logging.error("For rm-attr expect get-attr to fail, but it succeeded")
- ERRORS += 1
- # Put back value
- cmd = ("echo -n {val} | " + CFSD_PREFIX + " --pgid {pg} '{json}' set-attr {key}").format(osd=osd, pg=pg, json=JSON, key=attrkey, val=val)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret} from set-attr".format(ret=ret))
- ERRORS += 1
- continue
-
- hdr = db[nspace][basename].get("omapheader", "")
- cmd = (CFSD_PREFIX + "'{json}' get-omaphdr").format(osd=osd, json=JSON)
- logging.debug(cmd)
- gethdr = check_output(cmd, shell=True)
- if gethdr != hdr:
- logging.error("get-omaphdr was wrong: {get} instead of {orig}".format(get=gethdr, orig=hdr))
- ERRORS += 1
- continue
- # set-omaphdr to bogus value "foobar"
- cmd = ("echo -n foobar | " + CFSD_PREFIX + "'{json}' set-omaphdr").format(osd=osd, pg=pg, json=JSON)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret} from set-omaphdr".format(ret=ret))
- ERRORS += 1
- continue
- # Check the set-omaphdr
- cmd = (CFSD_PREFIX + "'{json}' get-omaphdr").format(osd=osd, pg=pg, json=JSON)
- logging.debug(cmd)
- gethdr = check_output(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret} from get-omaphdr".format(ret=ret))
- ERRORS += 1
- continue
- if gethdr != "foobar":
- logging.error("Check of set-omaphdr failed because we got {val}".format(val=getval))
- ERRORS += 1
- continue
- # Test dry-run with set-omaphdr
- cmd = ("echo -n dryrunbroken | " + CFSD_PREFIX + "--dry-run '{json}' set-omaphdr").format(osd=osd, pg=pg, json=JSON)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from set-omaphdr".format(ret=ret))
- ERRORS += 1
- continue
- # Put back value
- cmd = ("echo -n {val} | " + CFSD_PREFIX + "'{json}' set-omaphdr").format(osd=osd, pg=pg, json=JSON, val=hdr)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret} from set-omaphdr".format(ret=ret))
- ERRORS += 1
- continue
-
- for omapkey, val in db[nspace][basename]["omap"].items():
- cmd = (CFSD_PREFIX + " '{json}' get-omap {key}").format(osd=osd, json=JSON, key=omapkey)
- logging.debug(cmd)
- getval = check_output(cmd, shell=True)
- if getval != val:
- logging.error("get-omap of key {key} returned wrong val: {get} instead of {orig}".format(key=omapkey, get=getval, orig=val))
- ERRORS += 1
- continue
- # set-omap to bogus value "foobar"
- cmd = ("echo -n foobar | " + CFSD_PREFIX + " --pgid {pg} '{json}' set-omap {key}").format(osd=osd, pg=pg, json=JSON, key=omapkey)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret} from set-omap".format(ret=ret))
- ERRORS += 1
- continue
- # Check set-omap with dry-run
- cmd = ("echo -n dryrunbroken | " + CFSD_PREFIX + "--dry-run --pgid {pg} '{json}' set-omap {key}").format(osd=osd, pg=pg, json=JSON, key=omapkey)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from set-omap".format(ret=ret))
- ERRORS += 1
- continue
- # Check the set-omap
- cmd = (CFSD_PREFIX + " --pgid {pg} '{json}' get-omap {key}").format(osd=osd, pg=pg, json=JSON, key=omapkey)
- logging.debug(cmd)
- getval = check_output(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret} from get-omap".format(ret=ret))
- ERRORS += 1
- continue
- if getval != "foobar":
- logging.error("Check of set-omap failed because we got {val}".format(val=getval))
- ERRORS += 1
- continue
- # Test rm-omap
- cmd = (CFSD_PREFIX + "'{json}' rm-omap {key}").format(osd=osd, pg=pg, json=JSON, key=omapkey)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret} from rm-omap".format(ret=ret))
- ERRORS += 1
- # Check rm-omap with dry-run
- cmd = (CFSD_PREFIX + "--dry-run '{json}' rm-omap {key}").format(osd=osd, pg=pg, json=JSON, key=omapkey)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from rm-omap".format(ret=ret))
- ERRORS += 1
- cmd = (CFSD_PREFIX + "'{json}' get-omap {key}").format(osd=osd, pg=pg, json=JSON, key=omapkey)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stderr=nullfd, stdout=nullfd)
- if ret == 0:
- logging.error("For rm-omap expect get-omap to fail, but it succeeded")
- ERRORS += 1
- # Put back value
- cmd = ("echo -n {val} | " + CFSD_PREFIX + " --pgid {pg} '{json}' set-omap {key}").format(osd=osd, pg=pg, json=JSON, key=omapkey, val=val)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret} from set-omap".format(ret=ret))
- ERRORS += 1
- continue
-
- # Test dump
- print("Test dump")
- for nspace in db.keys():
- for basename in db[nspace].keys():
- file = os.path.join(DATADIR, nspace + "-" + basename + "__head")
- JSON = db[nspace][basename]['json']
- GETNAME = "/tmp/getbytes.{pid}".format(pid=pid)
- for pg in OBJREPPGS:
- OSDS = get_osds(pg, OSDDIR)
- for osd in OSDS:
- DIR = os.path.join(OSDDIR, os.path.join(osd, os.path.join("current", "{pg}_head".format(pg=pg))))
- fnames = [f for f in os.listdir(DIR) if os.path.isfile(os.path.join(DIR, f))
- and f.split("_")[0] == basename and f.split("_")[4] == nspace]
- if not fnames:
- continue
- if int(basename.split(REP_NAME)[1]) > int(NUM_CLONED_REP_OBJECTS):
- continue
- cmd = (CFSD_PREFIX + " '{json}' dump | grep '\"snap\": 1,' > /dev/null").format(osd=osd, json=JSON)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Invalid dump for {json}".format(json=JSON))
- ERRORS += 1
-
- print("Test list-attrs get-attr")
- ATTRFILE = r"/tmp/attrs.{pid}".format(pid=pid)
- VALFILE = r"/tmp/val.{pid}".format(pid=pid)
- for nspace in db.keys():
- for basename in db[nspace].keys():
- file = os.path.join(DATADIR, nspace + "-" + basename)
- JSON = db[nspace][basename]['json']
- jsondict = json.loads(JSON)
-
- if 'shard_id' in jsondict:
- logging.debug("ECobject " + JSON)
- found = 0
- for pg in OBJECPGS:
- OSDS = get_osds(pg, OSDDIR)
- # Fix shard_id since we only have one json instance for each object
- jsondict['shard_id'] = int(pg.split('s')[1])
- JSON = json.dumps(jsondict)
- for osd in OSDS:
- cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' get-attr hinfo_key").format(osd=osd, pg=pg, json=JSON)
- logging.debug("TRY: " + cmd)
- try:
- out = check_output(cmd, shell=True, stderr=subprocess.STDOUT)
- logging.debug("FOUND: {json} in {osd} has value '{val}'".format(osd=osd, json=JSON, val=out))
- found += 1
- except subprocess.CalledProcessError as e:
- if "No such file or directory" not in e.output and "No data available" not in e.output:
- raise
- # Assuming k=2 m=1 for the default ec pool
- if found != 3:
- logging.error("{json} hinfo_key found {found} times instead of 3".format(json=JSON, found=found))
- ERRORS += 1
-
- for pg in ALLPGS:
- # Make sure rep obj with rep pg or ec obj with ec pg
- if ('shard_id' in jsondict) != (pg.find('s') > 0):
- continue
- if 'shard_id' in jsondict:
- # Fix shard_id since we only have one json instance for each object
- jsondict['shard_id'] = int(pg.split('s')[1])
- JSON = json.dumps(jsondict)
- OSDS = get_osds(pg, OSDDIR)
- for osd in OSDS:
- DIR = os.path.join(OSDDIR, os.path.join(osd, os.path.join("current", "{pg}_head".format(pg=pg))))
- fnames = [f for f in os.listdir(DIR) if os.path.isfile(os.path.join(DIR, f))
- and f.split("_")[0] == basename and f.split("_")[4] == nspace]
- if not fnames:
- continue
- afd = open(ATTRFILE, "wb")
- cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' list-attrs").format(osd=osd, pg=pg, json=JSON)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=afd)
- afd.close()
- if ret != 0:
- logging.error("list-attrs failed with {ret}".format(ret=ret))
- ERRORS += 1
- continue
- keys = get_lines(ATTRFILE)
- values = dict(db[nspace][basename]["xattr"])
- for key in keys:
- if key == "_" or key == "snapset" or key == "hinfo_key":
- continue
- key = key.strip("_")
- if key not in values:
- logging.error("Unexpected key {key} present".format(key=key))
- ERRORS += 1
- continue
- exp = values.pop(key)
- vfd = open(VALFILE, "wb")
- cmd = (CFSD_PREFIX + "--pgid {pg} '{json}' get-attr {key}").format(osd=osd, pg=pg, json=JSON, key="_" + key)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=vfd)
- vfd.close()
- if ret != 0:
- logging.error("get-attr failed with {ret}".format(ret=ret))
- ERRORS += 1
- continue
- lines = get_lines(VALFILE)
- val = lines[0]
- if exp != val:
- logging.error("For key {key} got value {got} instead of {expected}".format(key=key, got=val, expected=exp))
- ERRORS += 1
- if len(values) != 0:
- logging.error("Not all keys found, remaining keys:")
- print(values)
-
- print("Test --op meta-list")
- tmpfd = open(TMPFILE, "wb")
- cmd = (CFSD_PREFIX + "--op meta-list").format(osd=ONEOSD)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=tmpfd)
- if ret != 0:
- logging.error("Bad exit status {ret} from --op meta-list request".format(ret=ret))
- ERRORS += 1
-
- print("Test get-bytes on meta")
- tmpfd.close()
- lines = get_lines(TMPFILE)
- JSONOBJ = sorted(set(lines))
- for JSON in JSONOBJ:
- (pgid, jsondict) = json.loads(JSON)
- if pgid != "meta":
- logging.error("pgid incorrect for --op meta-list {pgid}".format(pgid=pgid))
- ERRORS += 1
- if jsondict['namespace'] != "":
- logging.error("namespace non null --op meta-list {ns}".format(ns=jsondict['namespace']))
- ERRORS += 1
- logging.info(JSON)
- try:
- os.unlink(GETNAME)
- except:
- pass
- cmd = (CFSD_PREFIX + "'{json}' get-bytes {fname}").format(osd=ONEOSD, json=JSON, fname=GETNAME)
- logging.debug(cmd)
- ret = call(cmd, shell=True)
- if ret != 0:
- logging.error("Bad exit status {ret}".format(ret=ret))
- ERRORS += 1
-
- try:
- os.unlink(GETNAME)
- except:
- pass
- try:
- os.unlink(TESTNAME)
- except:
- pass
-
- print("Test pg info")
- for pg in ALLREPPGS + ALLECPGS:
- for osd in get_osds(pg, OSDDIR):
- cmd = (CFSD_PREFIX + "--op info --pgid {pg} | grep '\"pgid\": \"{pg}\"'").format(osd=osd, pg=pg)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Getting info failed for pg {pg} from {osd} with {ret}".format(pg=pg, osd=osd, ret=ret))
- ERRORS += 1
-
- print("Test pg logging")
- if len(ALLREPPGS + ALLECPGS) == len(OBJREPPGS + OBJECPGS):
- logging.warning("All PGs have objects, so no log without modify entries")
- for pg in ALLREPPGS + ALLECPGS:
- for osd in get_osds(pg, OSDDIR):
- tmpfd = open(TMPFILE, "wb")
- cmd = (CFSD_PREFIX + "--op log --pgid {pg}").format(osd=osd, pg=pg)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=tmpfd)
- if ret != 0:
- logging.error("Getting log failed for pg {pg} from {osd} with {ret}".format(pg=pg, osd=osd, ret=ret))
- ERRORS += 1
- HASOBJ = pg in OBJREPPGS + OBJECPGS
- MODOBJ = False
- for line in get_lines(TMPFILE):
- if line.find("modify") != -1:
- MODOBJ = True
- break
- if HASOBJ != MODOBJ:
- logging.error("Bad log for pg {pg} from {osd}".format(pg=pg, osd=osd))
- MSG = (HASOBJ and [""] or ["NOT "])[0]
- print("Log should {msg}have a modify entry".format(msg=MSG))
- ERRORS += 1
-
- try:
- os.unlink(TMPFILE)
- except:
- pass
-
- print("Test list-pgs")
- for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]:
-
- CHECK_PGS = get_osd_pgs(os.path.join(OSDDIR, osd), None)
- CHECK_PGS = sorted(CHECK_PGS)
-
- cmd = (CFSD_PREFIX + "--op list-pgs").format(osd=osd)
- logging.debug(cmd)
- TEST_PGS = check_output(cmd, shell=True).split("\n")
- TEST_PGS = sorted(TEST_PGS)[1:] # Skip extra blank line
-
- if TEST_PGS != CHECK_PGS:
- logging.error("list-pgs got wrong result for osd.{osd}".format(osd=osd))
- logging.error("Expected {pgs}".format(pgs=CHECK_PGS))
- logging.error("Got {pgs}".format(pgs=TEST_PGS))
- ERRORS += 1
-
- EXP_ERRORS = 0
- print("Test pg export --dry-run")
- pg = ALLREPPGS[0]
- osd = get_osds(pg, OSDDIR)[0]
- fname = "/tmp/fname.{pid}".format(pid=pid)
- cmd = (CFSD_PREFIX + "--dry-run --op export --pgid {pg} --file {file}").format(osd=osd, pg=pg, file=fname)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- if ret != 0:
- logging.error("Exporting --dry-run failed for pg {pg} on {osd} with {ret}".format(pg=pg, osd=osd, ret=ret))
- EXP_ERRORS += 1
- elif os.path.exists(fname):
- logging.error("Exporting --dry-run created file")
- EXP_ERRORS += 1
-
- cmd = (CFSD_PREFIX + "--dry-run --op export --pgid {pg} > {file}").format(osd=osd, pg=pg, file=fname)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- if ret != 0:
- logging.error("Exporting --dry-run failed for pg {pg} on {osd} with {ret}".format(pg=pg, osd=osd, ret=ret))
- EXP_ERRORS += 1
- else:
- outdata = get_lines(fname)
- if len(outdata) > 0:
- logging.error("Exporting --dry-run to stdout not empty")
- logging.error("Data: " + outdata)
- EXP_ERRORS += 1
-
- os.mkdir(TESTDIR)
- for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]:
- os.mkdir(os.path.join(TESTDIR, osd))
- print("Test pg export")
- for pg in ALLREPPGS + ALLECPGS:
- for osd in get_osds(pg, OSDDIR):
- mydir = os.path.join(TESTDIR, osd)
- fname = os.path.join(mydir, pg)
- if pg == ALLREPPGS[0]:
- cmd = (CFSD_PREFIX + "--op export --pgid {pg} > {file}").format(osd=osd, pg=pg, file=fname)
- elif pg == ALLREPPGS[1]:
- cmd = (CFSD_PREFIX + "--op export --pgid {pg} --file - > {file}").format(osd=osd, pg=pg, file=fname)
- else:
- cmd = (CFSD_PREFIX + "--op export --pgid {pg} --file {file}").format(osd=osd, pg=pg, file=fname)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- if ret != 0:
- logging.error("Exporting failed for pg {pg} on {osd} with {ret}".format(pg=pg, osd=osd, ret=ret))
- EXP_ERRORS += 1
-
- ERRORS += EXP_ERRORS
-
- print("Test pg removal")
- RM_ERRORS = 0
- for pg in ALLREPPGS + ALLECPGS:
- for osd in get_osds(pg, OSDDIR):
- # This should do nothing
- cmd = (CFSD_PREFIX + "--op remove --pgid {pg} --dry-run").format(pg=pg, osd=osd)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Removing --dry-run failed for pg {pg} on {osd} with {ret}".format(pg=pg, osd=osd, ret=ret))
- RM_ERRORS += 1
- cmd = (CFSD_PREFIX + "--force --op remove --pgid {pg}").format(pg=pg, osd=osd)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Removing failed for pg {pg} on {osd} with {ret}".format(pg=pg, osd=osd, ret=ret))
- RM_ERRORS += 1
-
- ERRORS += RM_ERRORS
-
- IMP_ERRORS = 0
- if EXP_ERRORS == 0 and RM_ERRORS == 0:
- print("Test pg import")
- for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]:
- dir = os.path.join(TESTDIR, osd)
- PGS = [f for f in os.listdir(dir) if os.path.isfile(os.path.join(dir, f))]
- for pg in PGS:
- file = os.path.join(dir, pg)
- # This should do nothing
- cmd = (CFSD_PREFIX + "--op import --file {file} --dry-run").format(osd=osd, file=file)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Import failed from {file} with {ret}".format(file=file, ret=ret))
- IMP_ERRORS += 1
- if pg == PGS[0]:
- cmd = ("cat {file} |".format(file=file) + CFSD_PREFIX + "--op import").format(osd=osd)
- elif pg == PGS[1]:
- cmd = (CFSD_PREFIX + "--op import --file - --pgid {pg} < {file}").format(osd=osd, file=file, pg=pg)
- else:
- cmd = (CFSD_PREFIX + "--op import --file {file}").format(osd=osd, file=file)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Import failed from {file} with {ret}".format(file=file, ret=ret))
- IMP_ERRORS += 1
- else:
- logging.warning("SKIPPING IMPORT TESTS DUE TO PREVIOUS FAILURES")
-
- ERRORS += IMP_ERRORS
- logging.debug(cmd)
-
- if EXP_ERRORS == 0 and RM_ERRORS == 0 and IMP_ERRORS == 0:
- print("Verify replicated import data")
- data_errors, _ = check_data(DATADIR, TMPFILE, OSDDIR, REP_NAME)
- ERRORS += data_errors
- else:
- logging.warning("SKIPPING CHECKING IMPORT DATA DUE TO PREVIOUS FAILURES")
-
- print("Test all --op dump-journal again")
- ALLOSDS = [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]
- ERRORS += test_dump_journal(CFSD_PREFIX, ALLOSDS)
-
- vstart(new=False)
- wait_for_health()
-
- if EXP_ERRORS == 0 and RM_ERRORS == 0 and IMP_ERRORS == 0:
- print("Verify erasure coded import data")
- ERRORS += verify(DATADIR, EC_POOL, EC_NAME, db)
- # Check replicated data/xattr/omap using rados
- print("Verify replicated import data using rados")
- ERRORS += verify(DATADIR, REP_POOL, REP_NAME, db)
-
- if EXP_ERRORS == 0:
- NEWPOOL = "rados-import-pool"
- cmd = "{path}/rados mkpool {pool}".format(pool=NEWPOOL, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
-
- print("Test rados import")
- first = True
- for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]:
- dir = os.path.join(TESTDIR, osd)
- for pg in [f for f in os.listdir(dir) if os.path.isfile(os.path.join(dir, f))]:
- if pg.find("{id}.".format(id=REPID)) != 0:
- continue
- file = os.path.join(dir, pg)
- if first:
- first = False
- # This should do nothing
- cmd = "{path}/rados import -p {pool} --dry-run {file}".format(pool=NEWPOOL, file=file, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Rados import --dry-run failed from {file} with {ret}".format(file=file, ret=ret))
- ERRORS += 1
- cmd = "{path}/rados -p {pool} ls".format(pool=NEWPOOL, path=CEPH_BIN)
- logging.debug(cmd)
- data = check_output(cmd, shell=True)
- if data:
- logging.error("'{data}'".format(data=data))
- logging.error("Found objects after dry-run")
- ERRORS += 1
- cmd = "{path}/rados import -p {pool} {file}".format(pool=NEWPOOL, file=file, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Rados import failed from {file} with {ret}".format(file=file, ret=ret))
- ERRORS += 1
- cmd = "{path}/rados import -p {pool} --no-overwrite {file}".format(pool=NEWPOOL, file=file, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Rados import --no-overwrite failed from {file} with {ret}".format(file=file, ret=ret))
- ERRORS += 1
-
- ERRORS += verify(DATADIR, NEWPOOL, REP_NAME, db)
- else:
- logging.warning("SKIPPING IMPORT-RADOS TESTS DUE TO PREVIOUS FAILURES")
-
- # Clear directories of previous portion
- call("/bin/rm -rf {dir}".format(dir=TESTDIR), shell=True)
- call("/bin/rm -rf {dir}".format(dir=DATADIR), shell=True)
- os.mkdir(TESTDIR)
- os.mkdir(DATADIR)
-
- # Cause SPLIT_POOL to split and test import with object/log filtering
- print("Testing import all objects after a split")
- SPLIT_POOL = "split_pool"
- PG_COUNT = 1
- SPLIT_OBJ_COUNT = 5
- SPLIT_NSPACE_COUNT = 2
- SPLIT_NAME = "split"
- cmd = "{path}/ceph osd pool create {pool} {pg} {pg} replicated".format(pool=SPLIT_POOL, pg=PG_COUNT, path=CEPH_BIN)
- logging.debug(cmd)
- call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- SPLITID = get_pool_id(SPLIT_POOL, nullfd)
- pool_size = int(check_output("{path}/ceph osd pool get {pool} size".format(pool=SPLIT_POOL, path=CEPH_BIN), shell=True, stderr=nullfd).split(" ")[1])
- EXP_ERRORS = 0
- RM_ERRORS = 0
- IMP_ERRORS = 0
-
- objects = range(1, SPLIT_OBJ_COUNT + 1)
- nspaces = range(SPLIT_NSPACE_COUNT)
- for n in nspaces:
- nspace = get_nspace(n)
-
- for i in objects:
- NAME = SPLIT_NAME + "{num}".format(num=i)
- LNAME = nspace + "-" + NAME
- DDNAME = os.path.join(DATADIR, LNAME)
- DDNAME += "__head"
-
- cmd = "rm -f " + DDNAME
- logging.debug(cmd)
- call(cmd, shell=True)
-
- if i == 1:
- dataline = range(DATALINECOUNT)
- else:
- dataline = range(1)
- fd = open(DDNAME, "w")
- data = "This is the split data for " + LNAME + "\n"
- for _ in dataline:
- fd.write(data)
- fd.close()
-
- cmd = "{path}/rados -p {pool} -N '{nspace}' put {name} {ddname}".format(pool=SPLIT_POOL, name=NAME, ddname=DDNAME, nspace=nspace, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stderr=nullfd)
- if ret != 0:
- logging.critical("Rados put command failed with {ret}".format(ret=ret))
- return 1
-
- wait_for_health()
- kill_daemons()
-
- for osd in [f for f in os.listdir(OSDDIR) if os.path.isdir(os.path.join(OSDDIR, f)) and f.find("osd") == 0]:
- os.mkdir(os.path.join(TESTDIR, osd))
-
- pg = "{pool}.0".format(pool=SPLITID)
- EXPORT_PG = pg
-
- export_osds = get_osds(pg, OSDDIR)
- for osd in export_osds:
- mydir = os.path.join(TESTDIR, osd)
- fname = os.path.join(mydir, pg)
- cmd = (CFSD_PREFIX + "--op export --pgid {pg} --file {file}").format(osd=osd, pg=pg, file=fname)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- if ret != 0:
- logging.error("Exporting failed for pg {pg} on {osd} with {ret}".format(pg=pg, osd=osd, ret=ret))
- EXP_ERRORS += 1
-
- ERRORS += EXP_ERRORS
-
- if EXP_ERRORS == 0:
- vstart(new=False)
- wait_for_health()
-
- cmd = "{path}/ceph osd pool set {pool} pg_num 2".format(pool=SPLIT_POOL, path=CEPH_BIN)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd, stderr=nullfd)
- time.sleep(5)
- wait_for_health()
-
- kill_daemons()
-
- # Now 2 PGs, poolid.0 and poolid.1
- for seed in range(2):
- pg = "{pool}.{seed}".format(pool=SPLITID, seed=seed)
-
- which = 0
- for osd in get_osds(pg, OSDDIR):
- cmd = (CFSD_PREFIX + "--force --op remove --pgid {pg}").format(pg=pg, osd=osd)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
-
- # This is weird. The export files are based on only the EXPORT_PG
- # and where that pg was before the split. Use 'which' to use all
- # export copies in import.
- mydir = os.path.join(TESTDIR, export_osds[which])
- fname = os.path.join(mydir, EXPORT_PG)
- which += 1
- cmd = (CFSD_PREFIX + "--op import --pgid {pg} --file {file}").format(osd=osd, pg=pg, file=fname)
- logging.debug(cmd)
- ret = call(cmd, shell=True, stdout=nullfd)
- if ret != 0:
- logging.error("Import failed from {file} with {ret}".format(file=file, ret=ret))
- IMP_ERRORS += 1
-
- ERRORS += IMP_ERRORS
-
- # Start up again to make sure imports didn't corrupt anything
- if IMP_ERRORS == 0:
- print("Verify split import data")
- data_errors, count = check_data(DATADIR, TMPFILE, OSDDIR, SPLIT_NAME)
- ERRORS += data_errors
- if count != (SPLIT_OBJ_COUNT * SPLIT_NSPACE_COUNT * pool_size):
- logging.error("Incorrect number of replicas seen {count}".format(count=count))
- ERRORS += 1
- vstart(new=False)
- wait_for_health()
-
- call("/bin/rm -rf {dir}".format(dir=TESTDIR), shell=True)
- call("/bin/rm -rf {dir}".format(dir=DATADIR), shell=True)
-
- ERRORS += test_removeall(CFSD_PREFIX, db, OBJREPPGS, REP_POOL, CEPH_BIN, OSDDIR, REP_NAME, NUM_CLONED_REP_OBJECTS)
-
- # vstart() starts 4 OSDs
- ERRORS += test_get_set_osdmap(CFSD_PREFIX, list(range(4)), ALLOSDS)
- ERRORS += test_get_set_inc_osdmap(CFSD_PREFIX, ALLOSDS[0])
-
- kill_daemons()
- CORES = [f for f in os.listdir(CEPH_DIR) if f.startswith("core.")]
- if CORES:
- CORE_DIR = os.path.join("/tmp", "cores.{pid}".format(pid=os.getpid()))
- os.mkdir(CORE_DIR)
- call("/bin/mv {ceph_dir}/core.* {core_dir}".format(ceph_dir=CEPH_DIR, core_dir=CORE_DIR), shell=True)
- logging.error("Failure due to cores found")
- logging.error("See {core_dir} for cores".format(core_dir=CORE_DIR))
- ERRORS += len(CORES)
-
- if ERRORS == 0:
- print("TEST PASSED")
- return 0
- else:
- print("TEST FAILED WITH {errcount} ERRORS".format(errcount=ERRORS))
- return 1
-
-
-def remove_btrfs_subvolumes(path):
- if platform.system() == "FreeBSD":
- return
- result = subprocess.Popen("stat -f -c '%%T' %s" % path, shell=True, stdout=subprocess.PIPE)
- for line in result.stdout:
- filesystem = decode(line).rstrip('\n')
- if filesystem == "btrfs":
- result = subprocess.Popen("sudo btrfs subvolume list %s" % path, shell=True, stdout=subprocess.PIPE)
- for line in result.stdout:
- subvolume = decode(line).split()[8]
- # extracting the relative volume name
- m = re.search(".*(%s.*)" % path, subvolume)
- if m:
- found = m.group(1)
- call("sudo btrfs subvolume delete %s" % found, shell=True)
-
-
-if __name__ == "__main__":
- status = 1
- try:
- status = main(sys.argv[1:])
- finally:
- kill_daemons()
- os.chdir(CEPH_BUILD_DIR)
- remove_btrfs_subvolumes(CEPH_DIR)
- call("/bin/rm -fr {dir}".format(dir=CEPH_DIR), shell=True)
- sys.exit(status)
diff --git a/src/ceph/qa/standalone/special/test-failure.sh b/src/ceph/qa/standalone/special/test-failure.sh
deleted file mode 100755
index cede887..0000000
--- a/src/ceph/qa/standalone/special/test-failure.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env bash
-set -ex
-
-source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
-
-function run() {
- local dir=$1
- shift
-
- export CEPH_MON="127.0.0.1:7202" # git grep '\<7202\>' : there must be only one
- export CEPH_ARGS
- CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
- CEPH_ARGS+="--mon-host=$CEPH_MON "
-
- local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
- for func in $funcs ; do
- setup $dir || return 1
- $func $dir || return 1
- teardown $dir || return 1
- done
-}
-
-function TEST_failure_log() {
- local dir=$1
-
- cat > $dir/test_failure.log << EOF
-This is a fake log file
-*
-*
-*
-*
-*
-This ends the fake log file
-EOF
-
- # Test fails
- return 1
-}
-
-function TEST_failure_core_only() {
- local dir=$1
-
- run_mon $dir a || return 1
- kill_daemons $dir SEGV mon 5
- return 0
-}
-
-main test_failure "$@"