-
Notifications
You must be signed in to change notification settings - Fork 1
/
00-grow-disk-online
115 lines (105 loc) · 5.24 KB
/
00-grow-disk-online
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
#!/bin/bash
#############################################################################
# ganeti hook for growing (resize) a qemu/KVM disk online
#
# !!!!! use at your own risk !!!!!
#
# please note: due to needed naming conventions of disks inside qemu, this
# hook needs at least ganeti-2.10 or newer
#
# potential data lose:
# ----------------------
# For file based instances (disk template file or sharedfile) there is a
# risk of losing data (shrinking the disk). The reason is, that the qemu HMP
# command block_resize sets the size of the disk/file on its own (after
# ganeti has grown the disk/file). If something in this hook went wrong, you
# may end up with a shrunken disk.
#
# The same may be true for rbd template (can't test this).
#
# Host block devices like DRBD, LVM or blockdev template are safe, because
# qemu does nothing expect to get the new size from the device and notify
# the guest.
#
# To prevent users from overlooking this warning you have to place a
# confirmation variable into this script. The variable's name is
# RUN_ON_UNSAFE_DISK_TEMPLATES and its value is I_DONT_CARE_FOR_DATALOSE.
#
### (c) 2017 [email protected] ######################################
### Installation instrunctions
# * copy this script into
# /etc/ganeti/hooks/disk-grow-post.d/ on every node
# * make sure it is executable
#
# You can use the following commands on the master node
# to install this hook in your cluster
#
# $ gnt-cluster command mkdir -p /etc/ganeti/hooks/disk-grow-post.d/
# $ install -o root -g root -m 0700 /source/path/to/this/script /etc/ganeti/hooks/disk-grow-post.d/50-grow-disk-online
# $ gnt-cluster copyfile /etc/ganeti/hooks/disk-grow-post.d/50-grow-disk-online
#
# This hook will log into the instance's primary nodes syslog (i.e.
# /var/log/syslog). Look there for general actions and errors.
#
# In order to determine the instance's primary node make sure that
# "hostname -f" is identical to ganeti's node name.
### playing safe in shell scripts
set -e
set -u
### some vars and functions
GANETI_RUN_DIR="/var/run/ganeti"
QEMU_HMP_SOCKET="${GANETI_RUN_DIR}/kvm-hypervisor/ctrl/${GANETI_INSTANCE_NAME}.monitor"
SOCAT_COMMAND="timeout 10s socat STDIO UNIX-CONNECT:${QEMU_HMP_SOCKET}"
log_err() {
echo "${@}" >&2
logger -p local1.err -t ${0}[$$] -- "${@}"
}
log_info() {
echo "${@}" >&2
logger -p local1.info -t ${0}[$$] -- "${@}"
}
log_fail() {
log_err "${@}"
log_err "exiting now ..."
exit 1
}
### main
trap "log_info signal for ERR recived (unexpected command error)" ERR
# run only on the instance primary node, if the instance is online
[[ "${GANETI_INSTANCE_PRIMARY}" = "$(hostname -f)" ]] || exit 0
[[ "${GANETI_INSTANCE_STATUS}" = "up" ]] || exit 0
# otherwise let's see if we get called right
[[ "${GANETI_INSTANCE_HYPERVISOR}" = "kvm" ]] || log_fail "this hook is only for hypervisor kvm, but got ${GANETI_INSTANCE_HYPERVISOR}"
[[ "${GANETI_HOOKS_PATH}" = "disk-grow" ]] || log_fail "this hook is only for disk-grow, but got ${GANETI_HOOKS_PATH}"
[[ "${GANETI_HOOKS_PHASE}" = "post" ]] || log_fail "this hook is only for post phase, but got ${GANETI_HOOKS_PHASE}"
[[ "${GANETI_HOOKS_VERSION}" = "2" ]] || log_fail "this hook is tested with hooks version 2, but got ${GANETI_HOOKS_VERSION}"
case "${GANETI_INSTANCE_DISK_TEMPLATE}" in
blockdev|drbd|plain) :;;
file|sharedfile) set +u
[[ "${RUN_ON_UNSAFE_DISK_TEMPLATES}" = "I_DONT_CARE_FOR_DATALOSE" ]] || log_fail "sorry: you need to confirm possible datalose with disk templates file or sharedfile. Read the script to see how."
set -u;;
*) log_fail "sorry: disk templates ${GANETI_INSTANCE_DISK_TEMPLATE} is not tested by this hook";;
esac
[[ -S "${QEMU_HMP_SOCKET}" ]] || log_fail "can't find the qemu monitor soecket at ${QEMU_HMP_SOCKET}"
# identify the resized disk parameters
var_name_old_size="GANETI_INSTANCE_DISK${GANETI_DISK}_SIZE"
var_name_new_size="GANETI_POST_INSTANCE_DISK${GANETI_DISK}_SIZE"
var_name_uuid="GANETI_INSTANCE_DISK${GANETI_DISK}_UUID"
old_size="${!var_name_old_size}"
new_size="${!var_name_new_size}"
disk_uuid="${!var_name_uuid}"
# double check size extration logic
[[ "${old_size}" -lt "${new_size}" ]] || log_fail "new size ${new_size} is less or equal then old size ${old_size}"
# note http://docs.ganeti.org/ganeti/2.17/html/design-scsi-kvm.html
# with this design, the qemu ID generated by ganeti will change
# an old one: hotdisk-123456-pci-4
# a new one: disk-9e7c85f6-b6e5-4243
# to be compatible, I chose to look for the first part of the UUID only
disk_id_short="${disk_uuid%%-*}"
# let's see if we can find one matching disk
disk_id_qemu_line=`echo "info block" | ${SOCAT_COMMAND} | grep -F ${disk_id_short}`
[[ $(echo "${disk_id_qemu_line}" | wc -l) -eq 1 ]] || log_fail "found more then one disk that match ${disk_id_short}"
disk_id_qemu=`echo "${disk_id_qemu_line}" | cut -d':' -f1 | cut -d' ' -f1`
log_info "attempting to resize ${GANETI_INSTANCE_NAME} disk IDX=${GANETI_DISK} UUID=${disk_uuid} qemu-ID=${disk_id_qemu} from ${old_size}MiB to ${new_size}MiB"
result=`echo "block_resize ${disk_id_qemu} ${new_size}" | ${SOCAT_COMMAND}`
log_info "finished to resize ${GANETI_INSTANCE_NAME} disk IDX=${GANETI_DISK} UUID=${disk_uuid} qemu-ID=${disk_id_qemu} from ${old_size}MiB to ${new_size}MiB"