4 # Copyright (C) 2015 Ubuntu Kylin
6 # Author: Min Chen <minchen@ubuntukylin.com>
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)
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.
19 my_dir
=$
(dirname "$0")
23 # put origin name in $image_name_in: for output
24 # put convert "_" name in $image_name: for grep image hobjects from database
27 function input_image
()
29 local func
="input_image"
30 if [ "$1"x
= ""x
];then
31 echo "$func: no image name input"
37 image_name
=`convert_underline $image_name_in`
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
()
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
49 function get_image_format_by_hobject
()
51 local func
="get_image_format"
52 if [ "$1"x
= ""x
];then
55 local res1
=`cat $image_list_v1|grep $1`
56 if [ "$res1"x
!= ""x
];then
61 local res2
=`cat $image_list_v2|grep $1`
62 if [ "$res2"x
= ""x
];then
68 #======================================== image format v1 ========================================
69 # <image_name>.rbd include 3 parts:
70 # header + snap_count*snapshot + snap_count*snap_name
72 # struct rbd_obj_header_ondisk {
74 # 24 char block_name[RBD_MAX_BLOCK_NAME_SIZE];
75 # 4 char signature[4];
82 # } __attribute__((packed)) options;
83 # 8 ceph_le64 image_size;//hexdump -C s=80 n=8
84 # 8 ceph_le64 snap_seq; //hexdump -C s=88 n=8
85 # 4 ceph_le32 snap_count;//hexdump -C s=96 n=4
86 # 4 ceph_le32 reserved;
87 # 8 ceph_le64 snap_names_len;//hexdump -C s=104 n=8
88 # struct rbd_obj_snap_ondisk snaps[0];
89 # } __attribute__((packed));
91 # sizeof(rbd_obj_header_ondisk): 112
93 # struct rbd_obj_snap_ondisk {
94 # 8 ceph_le64 id; //hexdump -C s=112+i*16 n=8 , i=[0, snap_count)
95 # 8 ceph_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
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
103 function get_image_metadata_v1
()
105 local func
="get_image_metadata_v1"
106 if [ "$1"x
= ""x
];then
107 echo "$func: no image head object input"
111 if [ "$2"x
!= ""x
];then
116 echo "$func: $1 not exists"
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"
127 if [ ! -e $hobject_path ];then
128 echo "$func: $hobject_path not exists"
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);}'`
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"
149 # decode N rbd_obj_snap_ondisk of <image_name>.rbd
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)
158 for ((i
=0; i
<$snap_count; i
++))
160 offset
=$
(($size_header + $i * $size_snap))
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);}'`
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" "} }'`);
172 echo -e "\t\tID\tNAME\t\tSIZE"
173 for ((i
=0; i
<$snap_count; i
++))
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]}"
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]}"
188 #======================================== end image format v1 ========================================
190 #======================================== image format v2 ========================================
192 # map_header, header_seq, header, key/value
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)
202 # decode image id from image_id_hobject
203 function get_image_id
()
205 local func
="get_image_id"
206 if [ "$1"x
= ""x
];then
209 local image_id_hobject
=$1 #from admin node's database
211 if [ ! -e $image_id_hobject ];then
212 #echo "$func: $image_id_hobject not exists"
217 local n
=`hexdump -e '10/4 "%u"' -s 0 -n 4 $image_id_hobject`
219 hexdump -e '10/1 "%c"' -s 4 -n $n $image_id_hobject
222 #find image_id omap entry in omaplist
225 function get_map_header
()
227 local func
="get_map_header"
229 if [ "$image_id"x
= ""x
];then
230 echo "$func: no image_id input"
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)"
242 #get meta header seq from map_header
244 function get_meta_header_seq
()
246 local func
="get_meta_header_seq"
247 if [ "$1"x
== ""x
];then
248 echo "$func: no prefix input"
250 elif [ "$2"x
== ""x
];then
251 echo "$func: no key input"
256 meta_header_seq
=`get_header_seq $prefix $key`
259 # get image metadata : object_prefix, order, image_size, snap_seq
264 function get_image_metadata_v2
()
266 local func
="get_image_metadata_v2"
267 if [ "$1"x
= ""x
];then
268 echo "$func: no meta_header_seq input"
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
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`
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"
291 # struct cls_rbd_snap {
294 # uint64_t image_size;
296 # uint8_t protection_status;
297 # cls_rbd_parent parent;
299 # decode cls_rbd_snap
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
310 function list_snaps_v2
()
312 local func
="list_snaps_v2"
313 if [ "$1"x
= ""x
];then
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[@]}
328 local arr
=(`ceph-kvstore-tool $omap_path get $prefix $key|awk -F ":" '{print $2}'`);
331 for ((i
=17; i
>13; i--
))
335 local len
=$
((16#$tmp))
337 for ((i
=18; i
<$
((18+$len)); i
++))
339 # convert ascii to char
340 local char
=`echo -e "\x${arr[$i]}"`
341 snap_name
="$snap_name$char"
343 # get snap_id (little endian)
345 for ((i
=13; i
>5; i--
))
349 local snap_id
=$
((16#$tmp))
350 # get image_size of current snap (little endian)
352 for ((i
=$
((25+$len)); i
>$
((17+$len)); i--
))
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"
361 if [ "$sname"x
= "$snap_name"x
];then
362 echo -e "snapshot:\t$snap_id\t$snap_name\t\t$image_size"
368 #======================================== end image format v2 ========================================