From: Kefu Chai Date: Tue, 23 Jun 2015 12:30:02 +0000 (+0800) Subject: tools: add ceph-monstore-update-crush.sh X-Git-Tag: v9.1.0~527^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=39e25b97797ad547800c41a49619874f4b9456eb;p=ceph.git tools: add ceph-monstore-update-crush.sh Fixes: #11815 Signed-off-by: Kefu Chai --- diff --git a/src/tools/ceph-monstore-update-crush.sh b/src/tools/ceph-monstore-update-crush.sh new file mode 100755 index 000000000000..3f24a0836432 --- /dev/null +++ b/src/tools/ceph-monstore-update-crush.sh @@ -0,0 +1,172 @@ +#!/bin/bash +# +# Copyright (C) 2015 Red Hat +# +# Author: Kefu Chai +# +# 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. +# + +verbose= + +test -d ../src && export PATH=$PATH:. + +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 + +function osdmap_get() { + local store_path=$1 + local query=$2 + local epoch=${3:+-v $3} + local osdmap=`mktemp` + + ceph-monstore-tool $store_path get osdmap -- \ + $epoch -o $osdmap > /dev/null + echo $(osdmaptool --dump xml $osdmap 2> /dev/null | \ + $XMLSTARLET sel -t -m "$query" -v .) + + rm -f $osdmap +} + +function test_crush() { + local store_path=$1 + local epoch=$2 + local max_osd=$3 + local crush=$4 + local osdmap=`mktemp` + + ceph-monstore-tool $store_path get osdmap -- \ + -v $epoch -o $osdmap > /dev/null + osdmaptool --export-crush $crush $osdmap &> /dev/null + + if crushtool --check $max_osd -i $crush > /dev/null; then + good=true + else + good=false + fi + rm -f $osdmap + $good || return 1 +} + +function get_crush() { + local store_path=$1 + local osdmap_epoch=$2 + local osdmap_path=`mktemp` + local crush_path=`mktemp` + + ceph-monstore-tool $store_path get osdmap -- \ + -v $osdmap_epoch -o $osdmap_path + osdmaptool --export-crush $crush $osdmap_path 2>&1 > /dev/null +} + +function usage() { + [ $# -gt 0 ] && echo -e "\n$@" + cat < + +Search backward for a latest known-good epoch in monstore. Rewrite the osdmap +epochs after it with the crush map in the found epoch if asked to do so. By +default, print out the crush map in the good epoch. + + [-h|--help] display this message + [--out] write the found crush map to given file (default: stdout) + [--rewrite] rewrite the monitor storage with the found crush map + [--verbose] be more chatty +EOF + [ $# -gt 0 ] && exit 1 + exit 0 +} + +function main() { + local temp + temp=$(getopt -o h --long verbose,help,mon-store:,out:,rewrite -n $0 -- "$@") || return 1 + + eval set -- "$temp" + local rewrite + while [ "$1" != "--" ]; do + case "$1" in + --verbose) + verbose=true + # set -xe + # PS4='${FUNCNAME[0]}: $LINENO: ' + shift;; + -h|--help) + usage + return 0;; + --out) + output=$2 + shift 2;; + --osdmap-epoch) + osdmap_epoch=$2 + shift 2;; + --rewrite) + rewrite=true + shift;; + *) + usage "unexpected argument $1" + shift;; + esac + done + shift + + local store_path="$1" + test $store_path || usage "I need the path to mon-store." + + local last_osdmap_epoch=$(osdmap_get $store_path "/osdmap/epoch") + # get the max_osd # in last osdmap epoch, crushtool will use it to check + # the crush maps in previous osdmaps + max_osd=$(osdmap_get $store_path "/osdmap/max_osd" $last_osdmap_epoch) + + local good_crush + local good_epoch + test $verbose && echo "the latest osdmap epoch is $last_osdmap_epoch" + for epoch in `seq $last_osdmap_epoch -1 1`; do + local crush_path=`mktemp` + test $verbose && echo "checking crush map #$epoch" + if test_crush $store_path $epoch $max_osd $crush_path; then + test $verbose && echo "crush map version #$epoch works with osdmap epoch #$osdmap_epoch" + good_epoch=$epoch + good_crush=$crush_path + break + fi + rm -f $crush_path + done + + if test $good_epoch; then + echo "good crush map found at epoch $epoch/$last_osdmap_epoch" + else + echo "Unable to find a crush map for osdmap version #$osdmap_epoch." 2>&1 + return 1 + fi + + if test $good_epoch -eq $last_osdmap_epoch; then + echo "and mon store has no faulty crush maps." + elif test $output; then + crushtool --decompile $good_crush --outfn $output + elif test $rewrite; then + ceph-monstore-tool $store_path rewrite-crush -- \ + --crush $good_crush \ + --good-epoch $good_epoch + else + echo + crushtool --decompile $good_crush + fi + rm -f $good_crush +} + +main "$@"