Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / tools / ceph-monstore-update-crush.sh
1 #!/bin/bash
2 #
3 # Copyright (C) 2015 Red Hat <contact@redhat.com>
4 #
5 # Author: Kefu Chai <kchai@redhat.com>
6 #
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)
10 # any later version.
11 #
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.
16 #
17
18 verbose=
19
20 test -d ../src && export PATH=$PATH:.
21
22 if ! which jq ; then
23     echo "Missing jq binary!"
24     exit 1
25 fi
26
27 if [ `uname` = FreeBSD ]; then
28     GETOPT=/usr/local/bin/getopt
29 else
30     GETOPT=getopt
31 fi
32
33 function osdmap_get() {
34     local store_path=$1
35     local query=$2
36     local epoch=${3:+-v $3}
37     local osdmap=`mktemp`
38
39     $CEPH_BIN/ceph-monstore-tool $store_path get osdmap -- \
40                        $epoch -o $osdmap > /dev/null || return
41
42     echo $($CEPH_BIN/osdmaptool --dump json $osdmap 2> /dev/null | \
43            jq "$query")
44
45     rm -f $osdmap
46 }
47
48 function test_crush() {
49     local store_path=$1
50     local epoch=$2
51     local max_osd=$3
52     local crush=$4
53     local osdmap=`mktemp`
54
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
58
59     if $CEPH_BIN/crushtool --test --check $max_osd -i $crush > /dev/null; then
60         good=true
61     else
62         good=false
63     fi
64     rm -f $osdmap
65     $good || return 1
66 }
67
68 function die() {
69     local retval=$?
70     echo "$@" >&2
71     exit $retval
72 }
73
74 function usage() {
75     [ $# -gt 0 ] && echo -e "\n$@"
76     cat <<EOF
77
78 Usage: $0 [options ...] <mon-store>
79
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.
83
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
88 EOF
89     [ $# -gt 0 ] && exit 1
90     exit 0
91 }
92
93 function main() {
94     local temp
95     temp=$($GETOPT -o h --long verbose,help,mon-store:,out:,rewrite -n $0 -- "$@") || return 1
96
97     eval set -- "$temp"
98     local rewrite
99     while [ "$1" != "--" ]; do
100         case "$1" in
101             --verbose)
102                 verbose=true
103                 # set -xe
104                 # PS4='${FUNCNAME[0]}: $LINENO: '
105                 shift;;
106             -h|--help)
107                 usage
108                 return 0;;
109             --out)
110                 output=$2
111                 shift 2;;
112             --osdmap-epoch)
113                 osdmap_epoch=$2
114                 shift 2;;
115             --rewrite)
116                 rewrite=true
117                 shift;;
118             *)
119                 usage "unexpected argument $1"
120                 shift;;
121         esac
122     done
123     shift
124
125     local store_path="$1"
126     test $store_path || usage "I need the path to mon-store."
127
128     # try accessing the store; if it fails, likely means a mon is running
129     local last_osdmap_epoch
130     local max_osd
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)
136
137     local good_crush
138     local good_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"
145             good_epoch=$epoch
146             good_crush=$crush_path
147             break
148         fi
149         rm -f $crush_path
150     done
151
152     if test $good_epoch; then
153         echo "good crush map found at epoch $epoch/$last_osdmap_epoch"
154     else
155         echo "Unable to find a crush map for osdmap version #$osdmap_epoch." 2>&1
156         return 1
157     fi
158
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
167     else
168         echo
169         $CEPH_BIN/crushtool --decompile $good_crush
170     fi
171     rm -f $good_crush
172 }
173
174 main "$@"