-
Notifications
You must be signed in to change notification settings - Fork 14
/
fast-vm-helper.sh
executable file
·190 lines (176 loc) · 6.15 KB
/
fast-vm-helper.sh
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#!/bin/sh
# fast-vm helper script for privileged root actions
DEBUG_LOG_CMD="logger -p debug -t fast-vm-helper-dbg"
LOG_LEVEL=7
DISPLAY_LEVEL=7
## terminal colors
c_red=$(tput setaf 1)
c_yellow=$(tput setaf 3)
c_green=$(tput setaf 2)
c_cyan=$(tput setaf 6)
c_normal=$(tput sgr0)
## LOG priorities
P_DEBUG=7
P_INFO=6
P_WARNING=4
P_ERROR=3
# function for message output to display&logs based on LOG/DISPLAY level
pmsg () {
priority="$1"
message="$2"
if [ "$LOG_LEVEL" -ge "$priority" ]; then
printf "%s | %s" "$USER" "$message"|logger -p "$priority" --id -t fast-vm-helper
fi
if [ "$DISPLAY_LEVEL" -ge "$priority" ]; then
case "$priority" in
"$P_DEBUG")
# shellcheck disable=SC2059
printf "[${c_cyan}inf${c_normal}] %b" "$message"
;;
"$P_INFO")
# shellcheck disable=SC2059
printf "[${c_green}ok${c_normal}] %b" "$message"
;;
"$P_WARNING")
# shellcheck disable=SC2059
printf "[${c_yellow}wrn${c_normal}] %b" "$message"
;;
"$P_ERROR")
# shellcheck disable=SC2059
printf "[${c_red}err${c_normal}] %b" "$message"
;;
*)
printf "[unk] %s" "$message"
;;
esac
fi
}
if [ ! "$(whoami)" = 'root' ];
then
pmsg $P_ERROR "this must be run as root\n"
exit 1
fi
if [ ! -f '/etc/fast-vm.conf' ]; then
pmsg $P_ERROR "global configuration file /etc/fast-vm.conf not found\n"
exit 1
fi
# load global configuration file
. /etc/fast-vm.conf
check_empty () {
var_name="$1"
var_value="$2"
if [ -z "$var_value" ]; then
pmsg $P_ERROR "variable $var_name not declared in global configuration run configure-fast-vm again or fix manually\n"
exit 2
fi
}
check_empty "VM_PREFIX" "$VM_PREFIX"
check_empty "THINPOOL_VG" "$THINPOOL_VG"
check_empty "THINPOOL_LV" "$THINPOOL_LV"
check_empty "LIBVIRT_NETWORK" "$LIBVIRT_NETWORK"
check_empty "SUBNET_NUMBER" "$SUBNET_NUMBER"
check_empty "FASTVM_GROUP" "$FASTVM_GROUP"
read -r action arg1 arg2 arg3
case "$action" in
lvcreate)
arg2=$(echo "$arg2"|grep -E '^[a-zA-Z0-9.-]+$')
if [ -z "$arg2" ]; then
pmsg $P_ERROR "LV name validation failed\n"
exit 1
fi
arg3=$(echo "$arg3"|grep -E '^[a-zA-Z0-9.-]+$')
if [ "$arg1" = "newvm" ]; then
if [ -z "$arg3" ] || [ ! -b "/dev/$THINPOOL_VG/$VM_PREFIX$arg2" ]; then
echo "[err] newvm LV name validation failed"
exit 1
fi
fi
case "$arg1" in
base)
arg3=$(echo "$arg3"|grep -E '^[0-9]+$')
if [ -z "$arg3" ]; then
pmsg $P_ERROR "LV size validation failed\n"
exit 1
fi
lvcreate -n "$VM_PREFIX$arg2" -V "${arg3}G" --thinpool "$THINPOOL_VG/$THINPOOL_LV" 2>&1|$DEBUG_LOG_CMD
;;
newvm)
lvcreate -k n -s --thinpool "$THINPOOL_VG/$THINPOOL_LV" "/dev/$THINPOOL_VG/$VM_PREFIX$arg2" --name "$VM_PREFIX$arg3" 2>&1|$DEBUG_LOG_CMD
;;
*)
pmsg $P_ERROR "wrong action for lvcreate\n"
exit 1
esac
;;
lvremove)
arg1=$(echo "$arg1" | grep -E "/dev/$THINPOOL_VG/${VM_PREFIX}[a-zA-Z0-9.-]+$")
if [ -z "$arg1" ] || [ ! -b "$arg1" ]; then
pmsg $P_ERROR "LV not found, not a block device or not allowed to be removed\n"
exit 1
fi
lvremove -f "$arg1" 2>&1|$DEBUG_LOG_CMD
;;
lvresize)
arg1=$(echo "$arg1" | grep -E "/dev/$THINPOOL_VG/${VM_PREFIX}[a-zA-Z0-9.-]+$")
if [ -z "$arg1" ] || [ ! -b "$arg1" ]; then
pmsg $P_ERROR "LV not found, not a block device or not allowed to be resized\n"
exit 1
fi
arg2=$(echo "$arg2"|grep -E '^[0-9]+$')
if [ -z "$arg2" ]; then
pmsg $P_ERROR "LV size validation failed\n"
exit 1
fi
lvresize -f -L "${arg2}G" "$arg1" 2>&1|$DEBUG_LOG_CMD
;;
lvs)
LC_NUMERIC=C.UTF-8 lvs $THINPOOL_VG -o lv_name,lv_size,data_percent,role,thin_id --separator ' ' --units g |grep -E "($THINPOOL_LV|$VM_PREFIX)"
;;
thin_dump)
## try to detect if the defined thin pool is available
double_dash_lv=$(echo "$THINPOOL_LV"|sed 's/-/--/g') # LVM uses double dash in the /dev/mapper
double_dash_vg=$(echo "$THINPOOL_VG"|sed 's/-/--/g') # also for VGs
if [ -b "/dev/mapper/${double_dash_vg}-${double_dash_lv}-tpool" ];then
THINPOOL_PATH="/dev/mapper/${double_dash_vg}-${double_dash_lv}-tpool"
fi
if [ -b "/dev/mapper/${double_dash_vg}-${double_dash_lv}_tdata" ] && [ -b "/dev/mapper/${double_dash_vg}-${double_dash_lv}_tmeta" ];then
THINPOOL_PATH="/dev/mapper/${double_dash_vg}-${double_dash_lv}"
fi
if [ -z "$THINPOOL_PATH" ]; then
pmsg $P_ERROR "thinpool $THINPOOL_VG/$THINPOOL_LV not found or not a thinpool LV, try running configure-fast-vm as root to check/correct\n"
exit 1
fi
# dump thinpool metadata from temporary metadata snapshot in memory
dmsetup message "$THINPOOL_PATH-tpool" 0 reserve_metadata_snap
thin_dump --format xml -m "${THINPOOL_PATH}_tmeta"
dmsetup message "$THINPOOL_PATH-tpool" 0 release_metadata_snap
;;
chgrp)
arg1=$(echo "$arg1" | grep -E "/dev/$THINPOOL_VG/${VM_PREFIX}[a-zA-Z0-9.-]+$")
if [ -z "$arg1" ] || [ ! -b "$arg1" ]; then
pmsg $P_ERROR "LV not found, not a block device or not allowed to be chgrp\n"
exit 1
fi
chgrp "$FASTVM_GROUP" "$arg1" 2>&1|$DEBUG_LOG_CMD
;;
dhcp_release)
if PATH="$PATH:/usr/sbin" command -v dhcp_release >/dev/null 2>&1; then
arg2=$(echo "$arg2"| grep -E '^[0-9]+$')
arg3=$(echo "$arg3"| grep -E '^[a-f0-9]{2,2}:[a-f0-9]{2,2}:[a-f0-9]{2,2}:[a-f0-9]{2,2}:[a-f0-9]{2,2}:[a-f0-9]{2,2}$')
if [ -z "$arg2" ] || [ -z "$arg3" ] || [ "$arg2" -lt 20 ] || [ "$arg2" -gt 220 ]; then
pmsg $P_ERROR "validation of VM number or mac address failed\n"
exit 1
fi
dhcp_release "$LIBVIRT_NETWORK" "192.168.$SUBNET_NUMBER.$arg2" "$arg3" 2>&1|$DEBUG_LOG_CMD
else
printf "[wrn] dhcp_release not found, to reuse the same VM number you would need to delete DHCP leases file for %s network and restart this network in the libvirt.\nhttp://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2007q1/001094.html\n" "$LIBVIRT_NETWORK"
fi
;;
vm_desc)
grep -H description /etc/libvirt/qemu/$VM_PREFIX*.xml 2>/dev/null
;;
*)
pmsg $P_ERROR "unknown action\n"
exit 3
;;
esac