Welcome to mirror list, hosted at ThFree Co, Russian Federation.

create-lvm-snapshot.sh « lvm-scripts « Snapshots « Library « Duplicati - github.com/duplicati/duplicati.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 693d9fc8164349d0ccc433ddb521bcca9961f763 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/bin/bash

# This script creates a lvm snapshot, modify as required
# 
# Input is always:
#  $1 = name of the snapshot, a random name with no spaces or non-printable chars, usually something like "duplicati-0102030011234567"
#  $2 = name of the device to create the snapshot for, this is the output of find-volume.sh, and usually a LVM id like "vg_name/lv_name"
#  $3 = the full path to the temporary folder used by the application, suffixed with a /, eg "/tmp/"
#
# The script MUST output a line with tmpdir="<dir>", where dir is the temporary mounted directory
# This ensures that the script can override the settings to better fit the distro, 
#  and disregard the naming conventions used normally. It also helps if the tools invoked write info
#  to the console that could be misinterpreted as the output path.

# Rename arguments to better symbols
NAME=$1
DEVICE=$2
TMPDIR=$3$NAME

# A snapshot requires that the volume has spare blocks, where changes are written.
# If the snapshot runs out of free space, it will be dropped, resulting in a partial
#  backup. The required size depends on how much data the system writes to disk while
#  the snapshot is active.
# Adjust these numbers to your system needs.
MIN_FREE_BLOCKS=20
MAX_FREE_BLOCKS=1000

#
# Get the number of free blocks on the volume
#
FREEBLOCKS=`lvs "$DEVICE" --noheadings --options vg_free_count | tail -1 | awk '{printf $NF}'`
if [ "$?" -ne 0 ]
then
	EXIT_CODE=$?
	echo "Error: lvs failed to find free space: lvs \"$DEVICE\" --noheadings --options vg_free_count"
	exit $EXIT_CODE
fi

if [ -z "$FREEBLOCKS" ]
then
        echo "Error: Unable to read free space for snapshot device \"$DEVICE\""
        exit -1
fi

#
# If there is too little space the snapshot may be dropped, 
#  resulting in an incomplete backup.
# Some users may want to change this number
#
if [ "$FREEBLOCKS" -lt "$MIN_FREE_BLOCKS" ]
then
	echo "Error: Not enough free space for snapshot device \"$DEVICE\""
	exit -1
fi

#
# If there is too much space, just take some, 
#  some users may want to change this number
#
if [ "$FREEBLOCKS" -gt "$MAX_FREE_BLOCKS" ]
then
	FREEBLOCKS=$MAX_FREE_BLOCKS
fi

LV_GROUP=`lvs "$DEVICE" --noheadings --options vg_name | tail -1 | awk '{printf $NF}'`
if [ "$?" -ne 0 ]
then
	EXIT_CODE=$?
	echo "Error: lvs failed to read VG: lvs \"$DEVICE\" --noheadings --options vg_name"
	exit $EXIT_CODE
fi


#
# Create the logical volume snapsnot
#
lvcreate --extents $FREEBLOCKS --snapshot --name "$NAME" "$DEVICE"
if [ "$?" -ne 0 ]
then
	EXIT_CODE=$?
	echo "Error: lvcreate failed: lvcreate --extents $FREEBLOCKS --snapshot --name \"$NAME\" \"$DEVICE\""
	exit $EXIT_CODE
fi

#
# Get the path to the volume snapshot
# The cases are here to support various versions of lvdisplay
#
LV_SNAPSHOT=`lvdisplay "$LV_GROUP/$NAME" | grep "LV Path" | awk '{ print $NF}'`
if [ "$?" -ne 0 ] || [ -z "$LV_SNAPSHOT" ] || [ ! -e "$LV_SNAPSHOT" ]
then
	LV_SNAPSHOT=`lvdisplay "$LV_GROUP/$NAME" | grep "LV Name" | awk '{ print $NF}'`
fi

if [ "$?" -ne 0 ] || [ -z "$LV_SNAPSHOT" ] || [ ! -e "$LV_SNAPSHOT" ]
then
	EXIT_CODE=$?
	echo "Error: Unable to determine LV path for volume $LV_GROUP/$NAME"
	
	#We have created the volume, so remove it before exit
	lvremove --force "$LV_GROUP/$NAME"
	exit $EXIT_CODE
fi

#
# Create a mount point
#
mkdir "$TMPDIR"
if [ "$?" -ne 0 ]
then
	EXIT_CODE=$?
	echo "Error: mkdir \"$TMPDIR\" failed!"
	
	#We have created the volume, so remove it before exit
	lvremove --force "$LV_GROUP/$NAME"
	exit $EXIT_CODE
fi

#
# Find filesystem used on $DEVICE.
# XFS filesystems need to be mounted with option -o nouuid.
# Other filesystems do not support that option.
#

FILESYSTEM=`df -PT /dev/"$DEVICE" | tail -1 | awk '{print $2}'`
if [ "$FILESYSTEM" == "xfs" ]; then
    MOUNT_OPTIONS="ro,nouuid"
else
    MOUNT_OPTIONS="ro"
fi

#
# Mount the snapshot on the mount point
#
mount -o "$MOUNT_OPTIONS" "$LV_SNAPSHOT" "$TMPDIR"
if [ "$?" -ne 0 ]
then
	EXIT_CODE=$?
	echo "Error: mount -o \"$MOUNTOPTIONS\" \"$LV_SNAPSHOT\" \"$TMPDIR\" failed!"

	#We have created the volume, so remove it before exit
	lvremove --force "$LV_GROUP/$NAME"
	exit $EXIT_CODE
fi

#
# Report back to the caller what the name of the snapshot volume is
#
echo "tmpdir=\"$TMPDIR\""
exit 0