]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/ceph-monstore-update-crush.sh
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / tools / ceph-monstore-update-crush.sh
CommitLineData
7c673cae
FG
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
18verbose=
19
20test -d ../src && export PATH=$PATH:.
21
22if type xmlstarlet > /dev/null 2>&1; then
23 XMLSTARLET=xmlstarlet
24elif type xml > /dev/null 2>&1; then
25 XMLSTARLET=xml
26else
27 echo "Missing xmlstarlet binary!"
28 exit 1
29fi
30
31if [ `uname` = FreeBSD ]; then
32 GETOPT=/usr/local/bin/getopt
33else
34 GETOPT=getopt
35fi
36
37function osdmap_get() {
38 local store_path=$1
39 local query=$2
40 local epoch=${3:+-v $3}
41 local osdmap=`mktemp`
42
43 $CEPH_BIN/ceph-monstore-tool $store_path get osdmap -- \
44 $epoch -o $osdmap > /dev/null || return
45
46 echo $($CEPH_BIN/osdmaptool --dump xml $osdmap 2> /dev/null | \
47 $XMLSTARLET sel -t -m "$query" -v .)
48
49 rm -f $osdmap
50}
51
52function test_crush() {
53 local store_path=$1
54 local epoch=$2
55 local max_osd=$3
56 local crush=$4
57 local osdmap=`mktemp`
58
59 $CEPH_BIN/ceph-monstore-tool $store_path get osdmap -- \
60 -v $epoch -o $osdmap > /dev/null
61 $CEPH_BIN/osdmaptool --export-crush $crush $osdmap &> /dev/null
62
63 if $CEPH_BIN/crushtool --test --check $max_osd -i $crush > /dev/null; then
64 good=true
65 else
66 good=false
67 fi
68 rm -f $osdmap
69 $good || return 1
70}
71
72function die() {
73 local retval=$?
74 echo "$@" >&2
75 exit $retval
76}
77
78function usage() {
79 [ $# -gt 0 ] && echo -e "\n$@"
80 cat <<EOF
81
82Usage: $0 [options ...] <mon-store>
83
84Search backward for a latest known-good epoch in monstore. Rewrite the osdmap
85epochs after it with the crush map in the found epoch if asked to do so. By
86default, print out the crush map in the good epoch.
87
88 [-h|--help] display this message
89 [--out] write the found crush map to given file (default: stdout)
90 [--rewrite] rewrite the monitor storage with the found crush map
91 [--verbose] be more chatty
92EOF
93 [ $# -gt 0 ] && exit 1
94 exit 0
95}
96
97function main() {
98 local temp
99 temp=$($GETOPT -o h --long verbose,help,mon-store:,out:,rewrite -n $0 -- "$@") || return 1
100
101 eval set -- "$temp"
102 local rewrite
103 while [ "$1" != "--" ]; do
104 case "$1" in
105 --verbose)
106 verbose=true
107 # set -xe
108 # PS4='${FUNCNAME[0]}: $LINENO: '
109 shift;;
110 -h|--help)
111 usage
112 return 0;;
113 --out)
114 output=$2
115 shift 2;;
116 --osdmap-epoch)
117 osdmap_epoch=$2
118 shift 2;;
119 --rewrite)
120 rewrite=true
121 shift;;
122 *)
123 usage "unexpected argument $1"
124 shift;;
125 esac
126 done
127 shift
128
129 local store_path="$1"
130 test $store_path || usage "I need the path to mon-store."
131
132 # try accessing the store; if it fails, likely means a mon is running
133 local last_osdmap_epoch
134 local max_osd
135 last_osdmap_epoch=$(osdmap_get $store_path "/osdmap/epoch") || \
136 die "error accessing mon store at $store_path"
137 # get the max_osd # in last osdmap epoch, crushtool will use it to check
138 # the crush maps in previous osdmaps
139 max_osd=$(osdmap_get $store_path "/osdmap/max_osd" $last_osdmap_epoch)
140
141 local good_crush
142 local good_epoch
143 test $verbose && echo "the latest osdmap epoch is $last_osdmap_epoch"
144 for epoch in `seq $last_osdmap_epoch -1 1`; do
145 local crush_path=`mktemp`
146 test $verbose && echo "checking crush map #$epoch"
147 if test_crush $store_path $epoch $max_osd $crush_path; then
148 test $verbose && echo "crush map version #$epoch works with osdmap epoch #$osdmap_epoch"
149 good_epoch=$epoch
150 good_crush=$crush_path
151 break
152 fi
153 rm -f $crush_path
154 done
155
156 if test $good_epoch; then
157 echo "good crush map found at epoch $epoch/$last_osdmap_epoch"
158 else
159 echo "Unable to find a crush map for osdmap version #$osdmap_epoch." 2>&1
160 return 1
161 fi
162
163 if test $good_epoch -eq $last_osdmap_epoch; then
164 echo "and mon store has no faulty crush maps."
165 elif test $output; then
166 $CEPH_BIN/crushtool --decompile $good_crush --outfn $output
167 elif test $rewrite; then
168 $CEPH_BIN/ceph-monstore-tool $store_path rewrite-crush -- \
169 --crush $good_crush \
170 --good-epoch $good_epoch
171 else
172 echo
173 $CEPH_BIN/crushtool --decompile $good_crush
174 fi
175 rm -f $good_crush
176}
177
178main "$@"