Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / tools / rbd_recover_tool / metadata_h
1 #!/bin/bash
2 # file: metadata_h
3 #
4 # Copyright (C) 2015 Ubuntu Kylin
5 #
6 # Author: Min Chen <minchen@ubuntukylin.com>
7 #
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU Library Public License as published by
10 # the Free Software Foundation; either version 2, or (at your option)
11 # any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU Library Public License for more details.
17 #
18
19 my_dir=$(dirname "$0")
20 . $my_dir/common_h
21 . $my_dir/epoch_h
22
23 # put origin name in $image_name_in: for output
24 # put convert "_" name in $image_name: for grep image hobjects from database
25 image_name_in=
26 image_name=
27 function input_image()
28 {
29   local func="input_image"
30   if [ "$1"x = ""x ];then
31     echo "$func: no image name input"
32     exit
33   fi
34
35   image_name_in=$1
36   # "_" -> "\u"
37   image_name=`convert_underline $image_name_in`
38 }
39
40 #======================================== distinguish v1 or v2 ===================================  
41 #image_list_v1=$single_node/$cluster-$id/image_list_v1
42 #image_list_v2=$single_node/$cluster-$id/image_list_v2
43 function get_image_list()
44 {
45   find $osd_data/current/ -type f|grep ".rbd__" >$image_list_v1
46   find $osd_data/current/ -type f|grep "rbd\\\\uid." >$image_list_v2
47 }
48
49 function get_image_format_by_hobject()
50 {
51   local func="get_image_format"
52   if [ "$1"x = ""x ];then
53     exit
54   fi
55   local res1=`cat $image_list_v1|grep $1`  
56   if [ "$res1"x != ""x ];then
57     echo 1
58     exit
59   fi  
60  
61   local res2=`cat $image_list_v2|grep  $1`
62   if [ "$res2"x = ""x ];then
63     echo 2
64     exit
65   fi
66 }
67
68 #======================================== image format v1 ========================================  
69 # <image_name>.rbd inlude 3 parts:
70 # header + snap_count*snapshot + snap_count*snap_name
71
72 # struct rbd_obj_header_ondisk {
73 # 40    char text[40];
74 # 24    char block_name[RBD_MAX_BLOCK_NAME_SIZE];
75 # 4     char signature[4];
76 # 8     char version[8];
77 #       struct {
78 # 1             __u8 order;
79 # 1             __u8 crypt_type;
80 # 1             __u8 comp_type;
81 # 1             __u8 unused;
82 #       } __attribute__((packed)) options;
83 # 8     __le64 image_size;//hexdump -C s=80 n=8
84 # 8     __le64 snap_seq;  //hexdump -C s=88 n=8
85 # 4     __le32 snap_count;//hexdump -C s=96 n=4
86 # 4     __le32 reserved;
87 # 8     __le64 snap_names_len;//hexdump -C s=104 n=8
88 #       struct rbd_obj_snap_ondisk snaps[0];
89 # } __attribute__((packed));
90 #
91 # sizeof(rbd_obj_header_ondisk): 112
92 #
93 # struct rbd_obj_snap_ondisk {
94 # 8     __le64 id;    //hexdump -C s=112+i*16 n=8   , i=[0, snap_count)
95 # 8     __le64 image_size;//hexdump -C s=112+i*16+8 n=8, i=[0, snap_count)
96 # } __attribute__((packed));
97 # sizeof(rbd_obj_snap_ondisk): 16
98 #
99 # get snap_names form <image_nane>.rbd
100 # hexdump -e '10/1 "%_c"' -s $((112 + $snap_count*16)) -n $snap_names_len <image_name>.rbd
101 # then split snap_names into array
102
103 function get_image_metadata_v1()
104 {
105   local func="get_image_metadata_v1"
106   if [ "$1"x = ""x ];then
107     echo "$func: no image head object input"
108     exit
109   fi
110   local snap_name=
111   if [ "$2"x != ""x ];then
112     snap_name=$2 
113   fi
114     
115   if [ ! -e $1 ];then
116     echo "$func: $1 not exists"
117     exit
118   fi
119   local hobject_path=$1  
120   d_hobject_path=`dump_backslash $1`
121   local image_format=`get_image_format_by_hobject $d_hobject_path`
122   if [ $image_format != 1 ];then
123     echo "$func: image_format must be 1"
124     exit
125   fi
126  
127   if [ ! -e $hobject_path ];then
128     echo "$func: $hobject_path not exists"
129     exit
130   fi
131
132   # decode rbd_obj_header_ondisk of <image_name>.rbd
133   local block_name=`hexdump -e '10/1 "%c"' -s 40 -n 24 $hobject_path`
134   local order=`hexdump -e '10/4 "%u"' -s 76 -n 1 $hobject_path`
135   local image_size=`hexdump -C -s 80 -n 8 $hobject_path|head -n 1|awk '{for (i=9; i>1; i--) {printf $i}}'`
136   image_size=$((16#$image_size))
137   local snap_seq=`hexdump -C -s 88 -n 8 $hobject_path|head -n 1|
138         awk '{num=""; for(i=9; i>1; i--){ num=num""$i;} print strtonum("0x"num);}'`
139   local snap_count=`hexdump -C -s 96 -n 4 $hobject_path|head -n 1|
140         awk '{num=""; for(i=5; i>1; i--){ num=num""$i;} print strtonum("0x"num);}'` 
141   local snap_names_len=`hexdump -C -s 104 -n 8 $hobject_path|head -n 1|
142         awk '{num=""; for(i=9; i>1; i--){ num=num""$i;} print strtonum("0x"num);}'` 
143
144   echo -e "block_name:\t$block_name"
145   echo -e "order:\t\t$order"
146   echo -e "image_size:\t$image_size"
147   echo -e "snap_seq:\t$snap_seq"
148
149   # decode N rbd_obj_snap_ondisk of <image_name>.rbd
150   declare -a snap_ids
151   declare -a snap_names
152   declare -a snap_image_sizes
153   local size_header=112 #sizeof(rbd_obj_header_ondisk)
154   local size_snap=16 #sizeof(rbd_obj_snap_ondisk)
155   local offset=0
156   local id_off=0
157   local size_off=0
158   for ((i=0; i<$snap_count; i++))
159   do
160     offset=$(($size_header + $i * $size_snap)) 
161     id_off=$offset 
162     size_off=$(($offset + 8))
163     snap_ids[$i]=`hexdump -C -s $id_off -n 8 $hobject_path|head -n 1|
164         awk '{num=""; for(i=9; i>1; i--){num=num""$i;} print strtonum("0x"num);}'`
165     snap_image_sizes[$i]=`hexdump -C -s $size_off -n 8 $hobject_path|head -n 1|
166         awk '{num=""; for(i=9; i>1; i--){num=num""$i;} print strtonum("0x"num);}'`
167   done
168   offset=$(($size_header + $snap_count * $size_snap))
169   snap_names=(`hexdump -e '10/1 "%_c"' -s $offset -n $snap_names_len $hobject_path|
170         awk -F "\\\\\\\\\\\\\\\\0" '{for(i=1; i<=NF; i++) {print $i" "} }'`); 
171
172   echo -e "\t\tID\tNAME\t\tSIZE"
173   for ((i=0; i<$snap_count; i++))
174   do
175     if [ "$snap_name"x = ""x ];then
176       echo -n -e "snapshot:\t"
177       echo -e "${snap_ids[$i]}\t${snap_names[$i]}\t\t${snap_image_sizes[$i]}"
178       continue
179     fi
180     if [ "$snap_name"x = "${snap_names[$i]}"x ];then 
181       echo -n -e "snapshot:\t"
182       echo -e "${snap_ids[$i]}\t${snap_names[$i]}\t\t${snap_image_sizes[$i]}"
183       return
184     fi
185   done
186 }
187
188 #======================================== end image format v1 ========================================  
189
190 #======================================== image format v2 ======================================== 
191
192 # map_header, header_seq, header, key/value
193 # eg. 
194 # map_header            _HOBJTOSEQ_:rbd%uheader%e139a6b8b4567...head.2.68E826B6
195 # meta_header_seq       17426
196 # header:               _USER_0000000000017426_USER_:object_prefix
197 #                       _USER_0000000000017426_USER_:order
198 #                       _USER_0000000000017426_USER_:size
199 #                       _USER_0000000000017426_USER_:snap_seq
200 # key/value             ceph-kvstore-tool /storepath get _USER_0000000000017426_USER_ (object_prefix|order|size|snap_seq)
201
202 # decode image id from image_id_hobject 
203 function get_image_id()
204 {
205   local func="get_image_id"
206   if [ "$1"x = ""x ];then
207     exit;
208   fi
209   local image_id_hobject=$1 #from admin node's database
210
211   if [ ! -e $image_id_hobject ];then
212     #echo "$func: $image_id_hobject not exists"
213     exit;
214   fi
215   
216   # get len of string  
217   local n=`hexdump -e '10/4 "%u"' -s 0 -n 4 $image_id_hobject`
218   # get string
219   hexdump -e '10/1 "%c"' -s 4 -n $n $image_id_hobject
220 }
221
222 #find image_id omap entry in omaplist
223 map_header_prefix=
224 map_header_key=
225 function get_map_header()
226 {
227   local func="get_map_header"
228   local image_id=$1
229   if [ "$image_id"x = ""x ];then
230     echo "$func: no image_id input"
231     exit;
232   fi
233   map_header_prefix=`get_map_header_prefix`
234   local keyword="header%e"$image_id
235   map_header_key=`get_map_header_key $keyword`
236   if [ "$map_header_key"x = ""x ];then
237     echo "$func: map_header_key is NULL(not in omaplist)"
238     exit
239   fi
240 }
241
242 #get meta header seq from map_header
243 meta_header_seq=
244 function get_meta_header_seq() 
245 {
246   local func="get_meta_header_seq"
247   if [ "$1"x == ""x ];then
248     echo "$func: no prefix input"
249     exit;
250   elif [ "$2"x == ""x ];then
251     echo "$func: no key input"
252     exit;
253   fi
254   local prefix=$1;
255   local key=$2;
256   meta_header_seq=`get_header_seq $prefix $key`
257 }
258
259 # get image metadata : object_prefix, order, image_size, snap_seq
260 object_prefix=
261 order=
262 image_size=
263 snap_seq=
264 function get_image_metadata_v2()
265 {
266   local func="get_image_metadata_v2"
267   if [ "$1"x = ""x ];then
268     echo "$func: no meta_header_seq input"
269     exit;
270   fi
271   local meta_header_seq=`printf "%016d" $1`
272   #echo "$func: meta_header_seq = "$meta_header_seq
273   local ghobject_key="_USER_"$meta_header_seq"_USER_"
274   local prefix=$ghobject_key
275
276   object_prefix=`get_header_kv $prefix object_prefix string`
277   #object_prefix="rbd_data.$image_id"
278   order=`get_header_kv $prefix order int`
279   image_size=`get_header_kv $prefix size int` 
280   snap_seq=`get_header_kv $prefix snap_seq int`
281
282   echo -e "object_prefix:\t$object_prefix"
283   echo -e "order:\t\t$order"
284   echo -e "image_size:\t$image_size"
285   echo -e "snap_seq:\t$snap_seq"
286
287   # list snapshot
288   list_snaps_v2 $1 $2
289 }
290
291 # struct cls_rbd_snap {
292 #       snapid_t id;
293 #       string name;
294 #       uint64_t image_size;
295 #       uint64_t features;
296 #       uint8_t protection_status;
297 #       cls_rbd_parent parent;
298 # }
299 # decode cls_rbd_snap
300 # 1     u8      struct_v
301 # 1     u8      struct_compat
302 # 4     u32     struct_len
303 # 8     u64     snapid_t id //s=6 n=8
304 # 4     u32     len of name //s=14 n=4
305 # len   char    name        //s=18 n=len
306 # 8     u64     image_size
307 # 8     u64     features
308 # ......
309 #
310 function list_snaps_v2()
311 {
312   local func="list_snaps_v2"
313   if [ "$1"x = ""x ];then
314     exit
315   fi
316   local sname=
317   if [ $# -eq 2 ];then
318     sname=$2
319   fi
320   local meta_header_seq=`printf "%016d" $1`
321   local prefix="_USER_"$meta_header_seq"_USER_"
322   local keys=(`awk -F ":" '/snapshot_/ && $1 == "'"$prefix"'" {if ($2 == "") exit; split($2, arr, "_"); 
323         print arr[2];}' $omap_list|sort -r`)
324   echo -e "\t\tID\tNAME\t\tSIZE"
325   for key in ${keys[@]}
326   do
327     key="snapshot_$key"
328     local arr=(`ceph-kvstore-tool $omap_path get $prefix $key|awk -F ":" '{print $2}'`);
329     # get snap_name
330     tmp=
331     for ((i=17; i>13; i--))
332     do
333       tmp="$tmp${arr[$i]}"
334     done
335     local len=$((16#$tmp))
336     local snap_name=
337     for ((i=18; i<$((18+$len)); i++))
338     do
339       # convert ascii to char
340       local char=`echo -e "\x${arr[$i]}"` 
341       snap_name="$snap_name$char"
342     done
343     # get snap_id (little endian)
344     local tmp=
345     for ((i=13; i>5; i--))
346     do
347       tmp="$tmp${arr[$i]}" 
348     done
349     local snap_id=$((16#$tmp))
350     # get image_size of current snap (little endian)
351     tmp=
352     for ((i=$((25+$len)); i>$((17+$len)); i--))
353     do
354       tmp="$tmp${arr[$i]}"
355     done
356     local image_size=$((16#$tmp))
357     if [ "$sname"x = ""x ];then
358       echo -e "snapshot:\t$snap_id\t$snap_name\t\t$image_size" 
359       continue
360     fi
361     if [ "$sname"x = "$snap_name"x ];then
362       echo -e "snapshot:\t$snap_id\t$snap_name\t\t$image_size" 
363       return
364     fi
365   done
366 }
367
368 #======================================== end image format v2 ========================================