66# to you under the Apache License, Version 2.0 (the
77# "License"); you may not use this file except in compliance
88# with the License. You may obtain a copy of the License at
9- #
9+ #
1010# http://www.apache.org/licenses/LICENSE-2.0
11- #
11+ #
1212# Unless required by applicable law or agreed to in writing,
1313# software distributed under the License is distributed on an
1414# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1515# KIND, either express or implied. See the License for the
1616# specific language governing permissions and limitations
1717# under the License.
1818
19-
19+
2020
2121# $Id: managesnapshot.sh 11601 2010-08-11 17:26:15Z kris $ $HeadURL: svn://svn.lab.vmops.com/repos/branches/2.1.refactor/java/scripts/storage/qcow2/managesnapshot.sh $
22- # managesnapshot.sh -- manage snapshots for a single disk (create, destroy, rollback)
22+ # managesnapshot.sh -- manage snapshots for a single disk (create, destroy, rollback, backup )
2323
2424usage () {
2525 printf " Usage: %s: -c <path to disk> -n <snapshot name>\n" $( basename $0 ) >&2
2626 printf " Usage: %s: -d <path to disk> -n <snapshot name>\n" $( basename $0 ) >&2
2727 printf " Usage: %s: -r <path to disk> -n <snapshot name>\n" $( basename $0 ) >&2
28- printf " Usage: %s: -b <path to disk> -n <snapshot name> -p <dest name >\n" $( basename $0 ) >&2
28+ printf " Usage: %s: -b <path to disk> -n <snapshot name> -p <dest dir> -t <dest file >\n" $( basename $0 ) >&2
2929 exit 2
3030}
3131
4040 fi
4141fi
4242
43+ is_lv () {
44+ # Must be a block device
45+ if [ -b " ${1} " ]; then
46+ # But not a volume group or physical volume
47+ lvm vgs " ${1} " > /dev/null 2>&1 && return 1
48+ # And a logical volume
49+ lvm lvs " ${1} " > /dev/null 2>&1 && return 0
50+ fi
51+ return 1
52+ }
53+
54+ get_vg () {
55+ lvm lvs --noheadings --unbuffered --separator=/ " ${1} " | cut -d ' /' -f 2
56+ }
57+
58+ get_lv () {
59+ lvm lvs --noheadings --unbuffered --separator=/ " ${1} " | cut -d ' /' -f 1
60+ }
61+
62+ double_hyphens () {
63+ echo ${1} | sed -e " s/-/--/g"
64+ }
65+
4366create_snapshot () {
4467 local disk=$1
4568 local snapshotname=" $2 "
4669 local failed=0
4770
48- if [ -f " ${disk} " ]; then
71+ if [ ${dmsnapshot} = " yes" ] && is_lv ${disk} ; then
72+ local lv=` get_lv ${disk} `
73+ local vg=` get_vg ${disk} `
74+ local lv_dm=` double_hyphens ${lv} `
75+ local vg_dm=` double_hyphens ${vg} `
76+ local lvdevice=/dev/mapper/${vg_dm} -${lv_dm}
77+ local lv_bytes=` blockdev --getsize64 ${lvdevice} `
78+ local lv_sectors=` blockdev --getsz ${lvdevice} `
79+
80+ lvm lvcreate --size ${lv_bytes} b --name " ${snapshotname} -cow" ${vg} >&2 || return 2
81+ dmsetup suspend ${vg_dm} -${lv_dm} >&2
82+ if dmsetup info -c --noheadings -o name ${vg_dm} -${lv_dm} -real > /dev/null 2>&1 ; then
83+ echo " 0 ${lv_sectors} snapshot ${lvdevice} -real /dev/mapper/${vg_dm} -${snapshotname} --cow p 64" | \
84+ dmsetup create " ${vg_dm} -${snapshotname} " >&2 || ( destroy_snapshot ${disk} " ${snapshotname} " ; return 2 )
85+ dmsetup resume " ${vg_dm} -${snapshotname} " >&2 || ( destroy_snapshot ${disk} " ${snapshotname} " ; return 2 )
86+ else
87+ dmsetup table ${vg_dm} -${lv_dm} | dmsetup create ${vg_dm} -${lv_dm} -real >&2 || ( destroy_snapshot ${disk} " ${snapshotname} " ; return 2 )
88+ dmsetup resume ${vg_dm} -${lv_dm} -real >&2 || ( destroy_snapshot ${disk} " ${snapshotname} " ; return 2 )
89+ echo " 0 ${lv_sectors} snapshot ${lvdevice} -real /dev/mapper/${vg_dm} -${snapshotname} --cow p 64" | \
90+ dmsetup create " ${vg_dm} -${snapshotname} " >&2 || ( destroy_snapshot ${disk} " ${snapshotname} " ; return 2 )
91+ echo " 0 ${lv_sectors} snapshot-origin ${lvdevice} -real" | \
92+ dmsetup load ${vg_dm} -${lv_dm} >&2 || ( destroy_snapshot ${disk} " ${snapshotname} " ; return 2 )
93+ dmsetup resume " ${vg_dm} -${snapshotname} " >&2 || ( destroy_snapshot ${disk} " ${snapshotname} " ; return 2 )
94+ fi
95+ dmsetup resume " ${vg_dm} -${lv_dm} " >&2
96+ elif [ -f " ${disk} " ]; then
4997 $qemu_img snapshot -c " $snapshotname " $disk
5098
51-
99+
52100 if [ $? -gt 0 ]
53101 then
54102 failed=2
55103 printf " ***Failed to create snapshot $snapshotname for path $disk \n" >&2
56104 $qemu_img snapshot -d " $snapshotname " $disk
57-
105+
58106 if [ $? -gt 0 ]
59107 then
60108 printf " ***Failed to delete snapshot $snapshotname for path $disk \n" >&2
@@ -65,26 +113,46 @@ create_snapshot() {
65113 printf " ***Failed to create snapshot $snapshotname , undefined type $disk \n" >&2
66114 fi
67115
68- return $failed
116+ return $failed
69117}
70118
71119destroy_snapshot () {
72120 local disk=$1
73- local snapshotname=$2
121+ local snapshotname=" $2 "
74122 local failed=0
75123
76- if [ -f $disk ]; then
124+ if is_lv ${disk} ; then
125+ local lv=` get_lv ${disk} `
126+ local vg=` get_vg ${disk} `
127+ local lv_dm=` double_hyphens ${lv} `
128+ local vg_dm=` double_hyphens ${vg} `
129+ if [ -e /dev/mapper/${vg_dm} -${lv_dm} -real ]; then
130+ local dm_refcount=` dmsetup info -c --noheadings -o open ${vg_dm} -${lv_dm} -real`
131+ if [ ${dm_refcount} -le 2 ]; then
132+ dmsetup suspend ${vg_dm} -${lv_dm} >&2
133+ dmsetup table ${vg_dm} -${lv_dm} -real | dmsetup load ${vg_dm} -${lv_dm} >&2
134+ dmsetup resume ${vg_dm} -${lv_dm}
135+ dmsetup remove " ${vg_dm} -${snapshotname} "
136+ dmsetup remove ${vg_dm} -${lv_dm} -real
137+ else
138+ dmsetup remove " ${vg_dm} -${snapshotname} "
139+ fi
140+ else
141+ dmsetup remove " ${vg_dm} -${snapshotname} "
142+ fi
143+ lvm lvremove -f " ${vg} /${snapshotname} -cow"
144+ elif [ -f $disk ]; then
77145 $qemu_img snapshot -d " $snapshotname " $disk
78146 if [ $? -gt 0 ]
79147 then
80148 failed=2
81149 printf " Failed to delete snapshot $snapshotname for path $disk \n" >&2
82- fi
150+ fi
83151 else
84152 failed=3
85153 printf " ***Failed to delete snapshot $snapshotname , undefined type $disk \n" >&2
86154 fi
87- return $failed
155+ return $failed
88156}
89157
90158rollback_snapshot () {
@@ -93,18 +161,19 @@ rollback_snapshot() {
93161 local failed=0
94162
95163 $qemu_img snapshot -a $snapshotname $disk
96-
164+
97165 if [ $? -gt 0 ]
98166 then
99167 printf " ***Failed to apply snapshot $snapshotname for path $disk \n" >&2
100168 failed=1
101169 fi
102-
103- return $failed
170+
171+ return $failed
104172}
173+
105174backup_snapshot () {
106175 local disk=$1
107- local snapshotname=$2
176+ local snapshotname=" $2 "
108177 local destPath=$3
109178 local destName=$4
110179
@@ -113,24 +182,37 @@ backup_snapshot() {
113182 mkdir -p $destPath >& /dev/null
114183 if [ $? -gt 0 ]
115184 then
116- printf " Failed to create $destPath " >&2
185+ printf " Failed to create $destPath \n " >&2
117186 return 3
118187 fi
119188 fi
120189
121- if [ -f ${disk} ]; then
122- # Does the snapshot exist?
190+ if [ ${dmsnapshot} = " yes" ] && is_lv ${disk} ; then
191+ local vg=` get_vg ${disk} `
192+ local vg_dm=` double_hyphens ${vg} `
193+ local scriptdir=` dirname ${0} `
194+
195+ if ! dmsetup info -c --noheadings -o name ${vg_dm} -${snapshotname} > /dev/null 2>&1 ; then
196+ printf " Disk ${disk} has no snapshot called ${snapshotname} .\n" >&2
197+ return 1
198+ fi
199+
200+ ${qemu_img} convert -f raw -O qcow2 " /dev/mapper/${vg_dm} -${snapshotname} " " ${destPath} /${destName} " || \
201+ ( printf " ${qemu_img} failed to create backup of snapshot ${snapshotname} for disk ${disk} to ${destPath} .\n" >&2 ; return 2 )
202+
203+ elif [ -f ${disk} ]; then
204+ # Does the snapshot exist?
123205 $qemu_img snapshot -l $disk | grep -w " $snapshotname " >& /dev/null
124206 if [ $? -gt 0 ]
125207 then
126- printf " there is no $snapshotname on disk $disk " >&2
208+ printf " there is no $snapshotname on disk $disk \n " >&2
127209 return 1
128210 fi
129211
130212 $qemu_img convert -f qcow2 -O qcow2 -s $snapshotname $disk $destPath /$destName >& /dev/null
131213 if [ $? -gt 0 ]
132214 then
133- printf " Failed to backup $snapshotname for disk $disk to $destPath " >&2
215+ printf " Failed to backup $snapshotname for disk $disk to $destPath \n " >&2
134216 return 2
135217 fi
136218 else
@@ -150,6 +232,8 @@ pathval=
150232snapshot=
151233tmplName=
152234deleteDir=
235+ dmsnapshot=no
236+ dmrollback=no
153237
154238while getopts ' c:d:r:n:b:p:t:f' OPTION
155239do
180264 esac
181265done
182266
267+ if modprobe dm-snapshot; then
268+ dmsnapshot=yes
269+ dmsetup targets | grep -q " ^snapshot-merge" && dmrollback=yes
270+ fi
271+
272+ [ -z " ${snapshot} " ] && usage
273+
183274[ -b " $pathval " ] && snapshot=` echo " ${snapshot} " | md5sum -t | awk ' { print $1 }' `
184275
185276if [ " $cflag " == " 1" ]
192283 exit $?
193284elif [ " $bflag " == " 1" ]
194285then
286+ [ -z " ${destPath} " -o -z " ${tmplName} " ] && usage
195287 backup_snapshot $pathval $snapshot $destPath $tmplName
196288 exit $?
197289elif [ " $rflag " == " 1" ]
0 commit comments