8e995d21ff
Change-Id: Ib96f22ee69266b251701aeb194d4fe41ceb3c61d
153 lines
3.8 KiB
Plaintext
153 lines
3.8 KiB
Plaintext
# vim syntax=sh
|
|
if type zfs > /dev/null 2>&1; then
|
|
SNAP_METHOD="zfs"
|
|
STATE_PATH="/vms/state"
|
|
else
|
|
SNAP_METHOD="lvm"
|
|
STATE_PATH="/var/lib/libvirt/qemu/save"
|
|
fi
|
|
|
|
lvm_snapshot() {
|
|
local volume=$1 snapname=$2
|
|
sudo lvcreate -sn $volume-$snapname -l 100%ORIGIN vms/$volume
|
|
}
|
|
|
|
lvm_revert() {
|
|
local volume=$1 snapname=$2
|
|
sudo lvconvert --merge vms/$volume-$snapname -i 5
|
|
sudo lvcreate -sn $volume-$snapname -l 100%ORIGIN vms/$volume # keep snapshot around
|
|
}
|
|
|
|
lvm_discard() {
|
|
local volume=$1 snapname=$2
|
|
sudo lvremove -f vms/$volume-$snapname
|
|
}
|
|
|
|
zfs_snapshot() {
|
|
local volume=$1 snapname=$2
|
|
sudo zfs snapshot vms/$volume@$snapname
|
|
sudo zfs clone vms/$volume@$snapname vms/$volume-$snapname
|
|
sudo zfs promote vms/$volume-$snapname
|
|
}
|
|
|
|
zfs_revert() {
|
|
local volume=$1 snapname=$2
|
|
sudo zfs destroy vms/$volume
|
|
sudo zfs clone vms/$volume-$snapname@$snapname vms/$volume
|
|
}
|
|
|
|
zfs_discard() {
|
|
local volume=$1 snapname=$2
|
|
clones="$(sudo zfs get -H clones vms/$volume-$snapname@$snapname | cut -f3)"
|
|
case $clones in
|
|
"" )
|
|
sudo zfs destroy vms/$volume-$snapname@$snapname
|
|
sudo zfs destroy vms/$volume-$snapname
|
|
;;
|
|
vms/$volume )
|
|
sudo zfs promote vms/$volume
|
|
sudo zfs destroy vms/$volume-$snapname
|
|
sudo zfs destroy vms/$volume@$snapname
|
|
;;
|
|
* )
|
|
echo "Can't remove snapshot vms/$volume-$snapname@$snapname since it has clones: $clones"
|
|
esac
|
|
}
|
|
|
|
virsh_all() {
|
|
local action=$1
|
|
shift
|
|
echo "$@" | xargs -P0 -n1 virsh $action | sed -n '/./p'
|
|
}
|
|
|
|
snapshot_vms() {
|
|
local snapname=$1 domain snap_arg
|
|
shift
|
|
sudo mkdir -p "$STATE_PATH"
|
|
sudo chown libvirt-qemu:kvm "$STATE_PATH"
|
|
virsh_all suspend "$@"
|
|
for domain; do
|
|
${SNAP_METHOD}_snapshot $domain $snapname
|
|
snap_arg=""
|
|
case $domain in
|
|
fuel )
|
|
snap_arg="--diskspec hdb,snapshot=no"
|
|
;;
|
|
compute-* )
|
|
snap_arg="--diskspec hdb,snapshot=no"
|
|
${SNAP_METHOD}_snapshot $domain-ceph $snapname
|
|
;;
|
|
esac
|
|
virsh snapshot-create-as $domain $domain-$snapname --atomic --memspec "$STATE_PATH/$domain-$snapname" --diskspec hda,snapshot=no $snap_arg
|
|
done
|
|
virsh_all resume "$@"
|
|
}
|
|
|
|
revert_vms() {
|
|
local snapname=$1 domain
|
|
shift
|
|
virsh_all destroy "$@"
|
|
for domain; do
|
|
${SNAP_METHOD}_revert $domain $snapname
|
|
case $domain in
|
|
compute-* )
|
|
${SNAP_METHOD}_revert $domain-ceph $snapname
|
|
;;
|
|
esac
|
|
virsh restore "$STATE_PATH/$domain-$snapname" --paused
|
|
done
|
|
virsh_all resume "$@"
|
|
}
|
|
|
|
discard_snapshots() {
|
|
local snapname=$1 domain
|
|
shift
|
|
for domain; do
|
|
${SNAP_METHOD}_discard $domain $snapname
|
|
case $domain in
|
|
compute-* )
|
|
${SNAP_METHOD}_discard $domain-ceph $snapname
|
|
;;
|
|
esac
|
|
virsh snapshot-delete $domain $domain-$snapname --metadata
|
|
sudo rm -f "$STATE_PATH/$domain-$snapname"
|
|
done
|
|
}
|
|
|
|
zfs_transfer() {
|
|
local volume=$1 snapname=$2 target=$3
|
|
local dataset="vms/$volume-$snapname@$snapname"
|
|
sudo zfs send "$dataset" | pv -cN $domain -s "$(sudo zfs list -Hp "$dataset" | cut -f4)" | ssh $target sudo zfs recv -vd vms
|
|
}
|
|
|
|
transfer_snapshots() {
|
|
local snapname=$1 target=$2 domain
|
|
shift; shift
|
|
if [ "$SNAP_METHOD" != "zfs" ]; then
|
|
echo "Can transfer only ZFS snapshots"
|
|
return 1
|
|
fi
|
|
if ! type pv > /dev/null 2>&1; then
|
|
sudo apt-get install -y pv
|
|
fi
|
|
if ! ssh -o KbdInteractiveAuthentication=no $target true; then
|
|
echo "Please set up passwordless SSH to node $target"
|
|
return 1
|
|
fi
|
|
if ! ssh $target sudo -nv 2> /dev/null; then
|
|
echo "Please set up passwordless sudo on node $target"
|
|
return 1
|
|
fi
|
|
ssh $target sudo mkdir -p "$STATE_PATH"
|
|
for domain; do
|
|
${SNAP_METHOD}_transfer $domain $snapname $target
|
|
case $domain in
|
|
compute-* )
|
|
${SNAP_METHOD}_transfer $domain-ceph $snapname $target
|
|
;;
|
|
esac
|
|
local state_file="$STATE_PATH/$domain-$snapname"
|
|
sudo pv "$state_file" | ssh $target sudo "sh -c \"cat > \\\"$state_file\\\"\""
|
|
done
|
|
}
|