source: MondoRescue/branches/3.0/mindi/analyze-my-lvm @ 3029

Last change on this file since 3029 was 3029, checked in by Bruno Cornec, 8 years ago
  • Fix an issue in analyzing dm devices, when habing more than 10 LVs, the sort wasn't respecting the numerical order, and at restore time, the LVs were not created back correctly (11 coming before 2) (Martin Kitka/Didier? Diaz)
  • Property svn:keywords set to Id
File size: 11.3 KB
Line 
1#!/bin/bash
2#
3# $Id: analyze-my-lvm 3029 2012-08-21 13:11:04Z bruno $
4#
5
6Die() {
7    echo "$1" >> /dev/stderr
8    exit -1
9}
10
11
12
13GetValueFromField() {
14    local res
15    grep -i "$2" "$1" | perl -pi -e 's/\s*(.*)\s\s\s+(.+)$/$2/;s/\sT[i]*B/t/;s/\sG[i]*B/g/;s/\sM[i]*B/m/;s/\sK[i]*B/k/'
16}
17
18
19GetLastBit() {
20    local i res
21    i=20
22    res=""
23    while [ ! "$res" ] ; do
24        i=$(($i-1))
25        res=`echo "$1" | cut -d'/' -f$i`
26    done
27    echo "$res"
28}
29
30
31ProcessLogicalVolume() {
32    local LV_full_string fname logical_volume volume_group device
33    LV_full_string=$1
34    if [ ! -e "$1" ]; then
35        echo "WARNING - cannot find LV file $1" | tee -a /dev/stderr
36        return
37    fi
38    volume_group=`echo "$LV_full_string" | cut -d'/' -f3`
39    logical_volume=`echo "$LV_full_string" | cut -d'/' -f4`
40    if [ $lvmversion = 2 ]; then
41        device=$LV_full_string
42        params=`GenerateLvcreateParameters $device`
43    else
44        fname=/proc/lvm/VGs/$volume_group/LVs/$logical_volume
45        if [ ! -e "$fname" ] ; then
46            echo "WARNING - cannot find $volume_group's $logical_volume LV file" | tee -a /dev/stderr
47            return
48        else
49            device=`GetValueFromField $fname "name:"`
50            params=`GenerateLvcreateParameters $device`
51        fi
52    fi
53
54    # Exclude LVs member of that env var
55    if [ "$MINDI_EXCLUDE_DEVS" ] ; then
56        list_of_devices="`mindi --nolog --readalllink $LV_full_string 2> /dev/null`"
57        l=""
58        for d in $list_of_devices; do
59            l="$l `GiveMapperOfdm $d`"
60        done
61        list_of_devices="`echo $l | sort -u`"
62        for ed in `echo $MINDI_EXCLUDE_DEVS | sed 's/|/ /g'`; do
63            if  [ "`echo " $list_of_devices" | grep " $ed"`" != "" ]; then
64                echo "Not including device $LV_full_string as it was excluded"
65                return
66            fi
67        done
68    fi
69    # Do not process LV whose VG are excluded
70    if [ -f $MINDI_TMP/excludedvgs ]; then
71        if [ "`grep -x $volume_group $MINDI_TMP/excludedvgs`" != "" ]; then
72            echo "Not including LV $logical_volume as VG $volume_group was excluded"
73            return
74        fi
75    fi
76
77    echo "# $LVMCMD lvcreate$params -n $logical_volume $volume_group"
78}
79
80
81GenerateLvcreateParameters() {
82    local device stripes stripesize device fname allocation output readahead
83    fname=$MINDI_TMP/PLF.$$.txt
84    device=$1
85    output=""
86    $LVMCMD lvdisplay $device | cat > $fname
87    stripes=`GetValueFromField $fname "Stripes"`
88    stripesize=`GetValueFromField $fname "Stripe size (MByte)"`m
89    [ "$stripesize" = "m" ] && stripesize=`GetValueFromField $fname "Stripe size (KByte)"`k
90    [ "$stripesize" = "k" ] && stripesize=""
91    allocation=`GetValueFromField $fname "LV Size"`
92    [ ! "`echo "$allocation" | grep "[k,m,g,t]"`" ] && allocation="$allocation"m
93    if echo "$allocation" | grep -E '^.*g$' > /dev/null 2> /dev/null ; then
94        val=`echo "$allocation" | sed s/g//`
95        allocation=`echo "$val" | awk '{c=$1; printf "%d", c*1024;}'`m
96    fi
97    readahead=`GetValueFromField $fname "Read ahead sectors"`
98    rm -f $fname
99    [ "$stripes" ]    && output="$output -i $stripes"
100    [ "$stripesize" ] && output="$output -I $stripesize"
101    [ "$allocation" ] && output="$output -L $allocation"
102    [ "$readahead" ]  && output="$output -r $readahead"
103    echo "$output"
104}
105
106
107
108GenerateVgcreateParameters() {
109    local current_VG device fname incoming VG_info_file max_logical_volumes max_physical_volumes physical_extent_size output blanklines
110    current_VG=$1
111    VG_info_file=$MINDI_TMP/$$.vg-info.txt
112    # We use cat here as a way to avoid SElinux to prevent us from writing in $VG_info_file
113    $LVMCMD vgdisplay $current_VG | cat > $VG_info_file
114    max_logical_volumes=`GetValueFromField "$VG_info_file" "MAX LV"`
115    [ $max_logical_volumes -ge 256 ] && max_logical_volumes=255
116    max_physical_volumes=`GetValueFromField "$VG_info_file" "MAX PV"`
117    [ $max_physical_volumes -ge 256 ] && max_physical_volumes=255
118    physical_extent_size=`GetValueFromField "$VG_info_file" "PE Size"`
119    output=""
120    [ "$max_logical_volumes" ]  && output="$output -l $max_logical_volumes"
121    [ "$max_physical_volumes" ] && output="$output -p $max_physical_volumes"
122    [ "$physical_extent_size" ] && output="$output -s $physical_extent_size"
123    echo "$output"
124    rm -f $VG_info_file
125}
126
127
128
129ProcessVolumeGroup() {
130    local current_VG physical_volumes i list_of_devices VG_params
131    current_VG=$1
132    if [ $lvmversion = 2 ]; then
133        VG_params=`GenerateVgcreateParameters $current_VG`
134        current_PVs=`$LVMCMD pvscan | grep " $current_VG " | awk '{print $2}' | tr '\n' ' '`
135        list_of_devices=$current_PVs
136    else
137        info_file=/proc/lvm/VGs/$current_VG/group
138        physical_volumes=`ls /proc/lvm/VGs/$current_VG/PVs`
139        VG_params=`GenerateVgcreateParameters $current_VG`
140        list_of_devices=""
141        for i in $physical_volumes ; do
142            fname=/proc/lvm/VGs/$current_VG/PVs/$i
143            device=`GetValueFromField $fname "name:"`
144            list_of_devices="$list_of_devices $device"
145        done
146        current_PVs=$list_of_devices
147    fi
148    l=""
149    if [ -f /etc/multipath.conf ]; then
150        # If multipath check which type of devide are given, mpath prefered
151        for d in $list_of_devices; do
152            l="$l `mindi --nolog --readalllink $d 2> /dev/null`"
153            l="$l `GiveMapperOfdm $d`"
154        done
155        list_of_devices="`echo $l | sort -u`"
156    fi
157
158    if [ "$MINDI_EXCLUDE_DEVS" ] ; then
159        for ed in `echo $MINDI_EXCLUDE_DEVS | sed 's/|/ /g'`; do
160            if  [ "`echo " $list_of_devices" | grep " $ed"`" != "" ]; then
161                echo $current_VG >> $MINDI_TMP/excludedvgs
162                return
163            fi
164        done
165    fi
166    echo "# $LVMCMD vgcreate $current_VG$VG_params $current_PVs"
167    echo "# $LVMCMD vgchange -a y $current_VG"
168}
169
170
171
172ListAllPhysicalVolumes() {
173    if [ $lvmversion = 2 ]; then
174        $LVMCMD pvscan 2> /dev/null | grep 'PV' | grep -v unknown | awk '{print $2}' >  $MINDI_TMP/pv.tmp
175    else
176        pvscan 2> /dev/null | grep '"' | cut -d'"' -f2  >  $MINDI_TMP/pv.tmp
177    fi
178
179    rm -f $MINDI_TMP/pv.tmp2
180    for d in `cat $MINDI_TMP/pv.tmp`; do
181        # Skip devices excluded, coming from mondoarchive
182        skip=0
183        l=""
184        l="$l `mindi --nolog --readalllink $d 2> /dev/null`"
185        l="$l `GiveMapperOfdm $d`"
186        list_of_devices="`echo $l | sort -u`"
187        if [ "$MINDI_EXCLUDE_DEVS" ] ; then
188            for ed in `echo $MINDI_EXCLUDE_DEVS | sed 's/|/ /g'`; do
189                if  [ "`echo " $list_of_devices " | grep " $ed"`" != "" ]; then
190                    skip=1
191                    continue
192                fi
193            done
194        fi
195        if [ $skip -eq 1 ]; then
196            continue
197        fi
198        echo $d >> $MINDI_TMP/pv.tmp2
199    done
200
201    if [ -f /etc/multipath.conf ]; then
202        # If multipath check which type of devide are given, mpath prefered
203        if [ -f  $MINDI_TMP/pv.tmp2 ]; then
204            l=""
205            for d in `cat $MINDI_TMP/pv.tmp2`; do
206                skip=0
207                l="$l `mindi --nolog --readalllink $d 2> /dev/null`"
208                l="$l `GiveMapperOfdm $d`"
209                list_of_devices="`echo $l | sort -u`"
210                if [ "$MINDI_EXCLUDE_DEVS" ] ; then
211                    for ed in `echo $MINDI_EXCLUDE_DEVS | sed 's/|/ /g'`; do
212                        if  [ "`echo " $list_of_devices " | grep " $ed"`" != "" ]; then
213                            skip=1
214                            continue
215                        fi
216                    done
217                fi
218                if [ $skip -eq 1 ]; then
219                    continue
220                fi
221                GiveMapperOfdm $d
222            done
223        fi
224    else
225        if [ -f  $MINDI_TMP/pv.tmp2 ]; then
226            cat $MINDI_TMP/pv.tmp2
227        fi
228    fi
229    rm -f $MINDI_TMP/pv.tmp $MINDI_TMP/pv.tmp2
230}
231
232
233ListAllVolumeGroups() {
234    $LVMCMD vgdisplay 2> /dev/null | awk '/^ *VG Name/ {print $3;}'
235}
236
237GiveMapperOfdm () {
238
239major=`stat -L -c "%t" $1 2> /dev/null`
240minor=`stat -L -c "%T" $1 2> /dev/null`
241
242for i in `ls /dev/mapper/*`; do
243    mj=`stat -L -c "%t" $i`
244    mn=`stat -L -c "%T" $i`
245    if [ "$mj" = "$major" ] && [ "$mn" = "$minor" ]; then
246        echo "$i"
247        return
248    fi
249done
250echo $1
251}
252
253
254ListLvmDrivesAndPartitions() {
255    # We get partitions in this loop not devices
256    for d in `$LVMCMD vgdisplay -v 2> /dev/null | grep "PV Name" | sed 's/(#)//' | awk '{print $3}'`; do 
257        # If multipath check which type of devices are given, mpath prefered
258        if [ -f /etc/multipath.conf ]; then
259            i=`GiveMapperOfdm $d`
260            rep=$i
261        else
262            rep=$d
263        fi
264        skip=0
265        if [ "$MINDI_EXCLUDE_DEVS" ] ; then
266            for ed in `echo $MINDI_EXCLUDE_DEVS | sed 's/|/ /g'`; do
267                if  [ "`echo " $rep " | grep " $ed"`" != "" ]; then
268                    skip=1
269                    continue
270                fi
271            done
272        fi
273        if [ $skip -eq 1 ]; then
274            continue
275        fi
276        echo $rep
277    done
278}
279
280
281
282PrettifyList() {
283    local i
284    echo -en "$1"
285    for i in $2 ; do
286        echo -en "$i "
287    done
288    echo ""
289}
290
291ListAllLogicalVolumesSortedBydm() {
292    rm -f $MINDI_TMP/sorteddm
293    for d in `ListAllLogicalVolumes` ; do
294        dm=`mindi --nolog --readalllink $d 2> /dev/null | tail -1`
295        echo "$dm|$d" >> $MINDI_TMP/sorteddm
296    done
297    if [ -f $MINDI_TMP/sorteddm ]; then
298        sort -t'|' -n $MINDI_TMP/sorteddm | cut -d'|' -f2
299    fi
300}
301
302ListAllLogicalVolumes() {
303    if [ $lvmversion = 2 ]; then
304        $LVMCMD lvscan 2> /dev/null | grep "'" | grep -iw "ACTIVE" | cut -d"'" -f2
305    else
306        lvscan 2> /dev/null | grep '"' | grep -iw "ACTIVE" | cut -d'"' -f2
307    fi
308}
309
310
311
312WriteShutdownScript() {
313    local i
314    echo ""
315    echo "Finally, to shut down and delete the volumes, do this:-"
316    for i in `ListAllLogicalVolumes` ; do
317        echo "($LVMCMD lvremove -f $i)"
318    done
319    for i in `ListAllVolumeGroups` ; do
320        echo "($LVMCMD vgchange -a n $i)"
321    done
322    for i in `ListAllVolumeGroups` ; do
323        echo "($LVMCMD vgremove $i)"
324    done
325    if [ $lvmversion = 2 ]; then
326        echo "(rmmod dm-mod & rmmod dm_mod & )"
327    else
328        echo "(rmmod lvm-mod)"
329    fi
330}
331
332
333
334# -------------------------------- main -----------------------------------
335
336if [ "$1" = "--givemapperofdm" ] ; then
337    shift
338    if [ _"$1" != _"" ] ; then
339        GiveMapperOfdm $1
340    fi
341    exit 0
342fi
343
344
345which lvmdiskscan 2>/dev/null 2>&1 || Die "lvmdiskscan not found. Won't handle LVM."
346if [ -e "/proc/lvm/global" ] && [ "`tr -s '\t' ' ' < /proc/lvm/global | grep "0 VGs 0 PVs 0 LVs"`" != "" ]; then
347    exit 1
348fi
349
350if [ _"$MINDI_TMP" = _"" ]; then
351    # Launched stdalone, so create a temp dir
352    STDALONE="true"
353    MINDI_TMP=`mktemp -d $TMPDIR/mindi.XXXXXXXXXX`
354    if [ $? -ne 0 ]; then
355        df $TMPDIR
356        Die "Unable to create a temporary directory ! Check space on $TMPDIR"
357    fi
358    if [ _"$MINDI_TMP" = _"" ]; then
359        Die "MINDI_TMP is empty, aborting"
360    fi
361    if [ _"$MINDI_TMP" = _"/" ]; then
362        Die "MINDI_TMP is /, aborting"
363    fi
364fi
365
366# Older lvmdiskscan use --help, newer --version
367lvmopt="--help"
368lvmdiskscan $lvmopt 2>&1 | grep -q -- "--version"
369if [ $? -eq 0 ]; then
370    lvmopt="--version"
371fi
372
373
374lvmversion=`lvmdiskscan --help 2>&1 |
375  grep -E "Logical Volume Manager|LVM version:" |
376  cut -d: -f2 | cut -d. -f1 |
377  awk '{print $NF}' |
378  sed -e 's/ //g'`
379
380if which lvm 2>/dev/null; then
381    version=`lvm version | grep "LVM version" | awk '{print $3}'`
382    i="`echo "$version" | cut -d'.' -f1`"
383    echo "i=$i"
384    if [ "$i" -ge "2" ] ; then
385        lvmversion=2
386    fi
387fi
388
389if [ $lvmversion = 2 ]; then
390    echo "LVM version >= 2.0 found."
391    LVMCMD="lvm"
392else
393    LVMCMD=""
394fi
395
396rm -f $MINDI_TMP/excludedvgs
397all_lvm_drives_and_partitions=`ListLvmDrivesAndPartitions`
398echo "Just before you extrapolate mountlist to include RAID partitions,"
399echo "extrapolate it to include the following LVM drives and partitions:-"
400PrettifyList ">>>>> " "$all_lvm_drives_and_partitions"
401echo "To get started, type:-"
402if [ $lvmversion = 2 ]; then
403    echo "(insmod dm-mod)"
404    echo "(insmod dm_mod)"
405else
406    echo "(insmod lvm-mod)"
407fi
408echo "# $LVMCMD vgchange -an"
409for i in `ListAllPhysicalVolumes` ; do
410    echo "# echo y | $LVMCMD pvcreate -ff $i"
411done
412echo "# $LVMCMD vgscan"
413echo ""
414echo "Create and activate the VG's (volume groups)."
415all_volume_groups=`ListAllVolumeGroups`
416for current_VG in $all_volume_groups ; do
417    if [ $lvmversion -ne 2 ]; then
418        echo "# rm -Rf /dev/$current_VG"
419    fi
420    ProcessVolumeGroup $current_VG
421done
422echo ""
423echo "Finally, create the LV's (logical volumes)."
424all_logical_volumes=`ListAllLogicalVolumesSortedBydm`
425for current_LV in $all_logical_volumes ; do
426    ProcessLogicalVolume $current_LV
427done
428echo ""
429echo "# $LVMCMD vgscan"
430echo "Now you may format the LV's:-"
431for i in `ListAllLogicalVolumes` ; do
432    echo "(mkfs -t foo $i or something like that)"
433done
434rm -f $MINDI_TMP/excludedvgs
435WriteShutdownScript
436if [ _"$STDALONE" = _"true" ]; then
437    rm -rf $MINDI_TMP
438fi
439exit 0
440
441
442
Note: See TracBrowser for help on using the repository browser.