3 # Copyright (C) 2015 Red Hat <contact@redhat.com>
5 # Author: Kefu Chai <kchai@redhat.com>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU Library Public License as published by
9 # the Free Software Foundation; either version 2, or (at your option)
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Library Public License for more details.
20 test -d ../src && export PATH=$PATH:.
23 echo "Missing jq binary!"
27 if [ `uname` = FreeBSD ]; then
28 GETOPT=/usr/local/bin/getopt
33 function osdmap_get() {
36 local epoch=${3:+-v $3}
39 $CEPH_BIN/ceph-monstore-tool $store_path get osdmap -- \
40 $epoch -o $osdmap > /dev/null || return
42 echo $($CEPH_BIN/osdmaptool --dump json $osdmap 2> /dev/null | \
48 function test_crush() {
55 $CEPH_BIN/ceph-monstore-tool $store_path get osdmap -- \
56 -v $epoch -o $osdmap > /dev/null
57 $CEPH_BIN/osdmaptool --export-crush $crush $osdmap &> /dev/null
59 if $CEPH_BIN/crushtool --test --check $max_osd -i $crush > /dev/null; then
75 [ $# -gt 0 ] && echo -e "\n$@"
78 Usage: $0 [options ...] <mon-store>
80 Search backward for a latest known-good epoch in monstore. Rewrite the osdmap
81 epochs after it with the crush map in the found epoch if asked to do so. By
82 default, print out the crush map in the good epoch.
84 [-h|--help] display this message
85 [--out] write the found crush map to given file (default: stdout)
86 [--rewrite] rewrite the monitor storage with the found crush map
87 [--verbose] be more chatty
89 [ $# -gt 0 ] && exit 1
95 temp=$($GETOPT -o h --long verbose,help,mon-store:,out:,rewrite -n $0 -- "$@") || return 1
99 while [ "$1" != "--" ]; do
104 # PS4='${FUNCNAME[0]}: $LINENO: '
119 usage "unexpected argument $1"
125 local store_path="$1"
126 test $store_path || usage "I need the path to mon-store."
128 # try accessing the store; if it fails, likely means a mon is running
129 local last_osdmap_epoch
131 last_osdmap_epoch=$(osdmap_get $store_path ".epoch") || \
132 die "error accessing mon store at $store_path"
133 # get the max_osd # in last osdmap epoch, crushtool will use it to check
134 # the crush maps in previous osdmaps
135 max_osd=$(osdmap_get $store_path ".max_osd" $last_osdmap_epoch)
139 test $verbose && echo "the latest osdmap epoch is $last_osdmap_epoch"
140 for epoch in `seq $last_osdmap_epoch -1 1`; do
141 local crush_path=`mktemp`
142 test $verbose && echo "checking crush map #$epoch"
143 if test_crush $store_path $epoch $max_osd $crush_path; then
144 test $verbose && echo "crush map version #$epoch works with osdmap epoch #$osdmap_epoch"
146 good_crush=$crush_path
152 if test $good_epoch; then
153 echo "good crush map found at epoch $epoch/$last_osdmap_epoch"
155 echo "Unable to find a crush map for osdmap version #$osdmap_epoch." 2>&1
159 if test $good_epoch -eq $last_osdmap_epoch; then
160 echo "and mon store has no faulty crush maps."
161 elif test $output; then
162 $CEPH_BIN/crushtool --decompile $good_crush --outfn $output
163 elif test $rewrite; then
164 $CEPH_BIN/ceph-monstore-tool $store_path rewrite-crush -- \
165 --crush $good_crush \
166 --good-epoch $good_epoch
169 $CEPH_BIN/crushtool --decompile $good_crush