From d8ec4891c55b6a76e558ff8aa0808ecb9ded1dc6 Mon Sep 17 00:00:00 2001 From: Bastian Date: Fri, 21 Oct 2022 17:31:45 +0200 Subject: [PATCH] Changed logic of locking, changed help accordingly --- crossover | 80 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/crossover b/crossover index 7ca0820..a1ac87e 100755 --- a/crossover +++ b/crossover @@ -29,7 +29,8 @@ declare -i opt_debug=0 declare -i opt_dry_run=0 declare -i opt_syslog=0 declare -i opt_lock=1 -declare -i opt_keeplock=0 +declare -i opt_keepslock=0 +declare -i opt_keepdlock=0 declare -i opt_overwrite=0 declare -i opt_online=0 declare -i opt_keep_local=0 @@ -37,8 +38,6 @@ declare -i opt_keep_remote=0 declare -r redstconf='^\/etc\/pve\/nodes\/(.*)\/qemu-server\/([0-9]+).conf$' declare -r recephimg='([a-zA-Z0-9]+)\:(.*)' -declare -r resnapname=".*@$opt_snapshot_prefix(.*)" -declare -r resplitvmid='^([0-9]+):([0-9]+)$' function usage(){ shift @@ -68,17 +67,15 @@ Commands: mirror Replicate a stopped VM to another Cluster (full clone) Options: - --vmid The ID of the VM/CT, comma separated (es. 100,101,102), - 'all-???' for all known guest systems in specific host (es. all-pve1, all-\$(hostname)), - 'all' for all known guest systems in cluster, - 'storage-???' storage Proxmox VE (pool Ceph) + --vmid The source+target ID of the VM/CT, comma separated (eg. --vmid=100:100,101:101), --destination 'Target PVE Host in target pool. e.g. --destination=pve04 --pool 'Ceph pool name in target pool. e.g. --pool=data --keeplocal 'How many additional Snapshots to keep locally. e.g. --keeplocal=2 --keepremote 'How many additional Snapshots to keep remote. e.g. --keepremote=2 --online 'Allow online Copy - --nolock 'Don't lock source VM on Transfer - --keeplock 'Keep source VM locked on Transfer + --nolock 'Don't lock source VM on Transfer (mainly for test purposes) + --keep-slock 'Keep source VM locked on Transfer + --keep-dlock 'Keep VM locked after transfer on Destination --overwrite 'Overwrite Destination --debug 'Show Debug Output @@ -95,7 +92,7 @@ function parse_opts(){ local args args=$(getopt \ --options '' \ - --longoptions=vmid:,destination:,pool:,keeplocal:,keepremote:,online,nolock,keeplock,overwrite,dry-run,debug \ + --longoptions=vmid:,destination:,pool:,keeplocal:,keepremote:,online,nolock,keep-slock,keep-dlock,overwrite,dry-run,debug \ --name "$PROGNAME" \ -- "$@") \ || end_process 128 @@ -113,7 +110,8 @@ function parse_opts(){ --dry-run) opt_dry_run=1; shift;; --debug) opt_debug=1; shift;; --nolock) opt_lock=0; shift;; - --keeplock) opt_keeplock=1; shift;; + --keep-slock) opt_keepslock=1; shift;; + --keep-dlock) opt_keepdlock=1; shift;; --overwrite) opt_overwrite=1; shift;; --) shift; break;; *) break;; @@ -297,38 +295,45 @@ function mirror() { local disk='' dvmid=${dvmids[$vm_id]} - dststatus=$(ssh root@${dstpvnode[$dvmid]} qm status $dvmid|cut -d' ' -f 2) - if [ $dststatus == "running" ]; then - log error "Destination VM is running. bailing out" - end_process 255 - fi srcvmgenid=$(cat $PVE_NODES/"${pvnode[$vm_id]}"/$QEMU/"$vm_id".conf|grep vmgenid|sed -r -e 's/^vmgenid:\s(.*)/\1/') - dstvmgenid=$(ssh $opt_destination cat $PVE_NODES/"${dstpvnode[$dvmid]}"/$QEMU/"$dvmid".conf|grep vmgenid|sed -r -e 's/^vmgenid:\s(.*)/\1/') + dstvmgenid=$(ssh $opt_destination cat $PVE_NODES/"${dstpvnode[$dvmid]}"/$QEMU/"$dvmid".conf 2>/dev/null|grep vmgenid|sed -r -e 's/^vmgenid:\s(.*)/\1/') log debug "Checking for VM $dvmid on Destination Host $opt_destination $QEMU_CONF_CLUSTER" log debug "DVMID: $dvmid" conf_on_destination=$(ssh $opt_destination "ls -d $QEMU_CONF_CLUSTER/$dvmid$EXT_CONF 2>/dev/null") [[ "$conf_on_destination" =~ $redstconf ]] host_on_destination=${BASH_REMATCH[1]} + + if [ $host_on_destination ]; then + dststatus=$(ssh root@${dstpvnode[$dvmid]} qm status $dvmid|cut -d' ' -f 2) + if [ $dststatus == "running" ]; then + log error "Destination VM is running. bailing out" + end_process 255 + fi + fi + #Check if source VM is running srcstatus=$(ssh root@${pvnode[$vm_id]} qm status $vm_id|cut -d' ' -f 2) if [ $srcstatus == "running" ] && [ $opt_online -eq 0 ]; then log error "Source VM is running .. exiting" end_process 1 fi - if [ -z "$host_on_destination" ] || [ $opt_overwrite -eq 1 ]; then - if [ $srcvmgenid != $dstvmgenid ]; then - log error "Source VM genid ($srcvmgenid) doesn't match destination VM genid ($dstvmgenid). This should not happen. Bailing out" + + if [ ! "$host_on_destination" ] || [ $opt_overwrite -eq 1 ]; then + if [ "$host_on_destination" ] && [ $srcvmgenid != $dstvmgenid ]; then + log error "Source VM genid ($srcvmgenid) doesn't match destination VM genid ($dstvmgenid). This should not happen. Bailing out.." end_process 255 fi log info "Transmitting Config for VM $vm_id to desination $dvmid" rewriteconfig $PVE_NODES/"${pvnode[$vm_id]}"/$QEMU/"$vm_id".conf $opt_destination "$opt_pool" $PVE_NODES/"$opt_destination"/$QEMU/"$dvmid".conf "$dvmid" fi - exit - #Lock on source + + #Lock on source + destination if [ $opt_lock -eq 1 ]; then ssh root@"${pvnode[$vm_id]}" qm set "$vm_id" --lock backup + ssh root@"${dstpvnode[$dvmid]}" qm set "$dvmid" --lock backup fi - #Take Rbd Snapshot + + #Freeze, take Rbd Snapshot then unfreeze vm_freeze "$vm_id" "${pvnode[$vm_id]}" for disk in $(get_disks_from_config "$file_config"); do src_image_spec=$(get_image_spec "$disk") @@ -342,13 +347,11 @@ function mirror() { [ -z "$src_image_spec" ] && continue dst_image_spec=$(echo $src_image_spec | sed -r -e "s/([a-zA-Z0-9]+\/[a-zA-Z0-9]+\-)([0-9]+)(\-[a-zA-Z0-9]+\-[0-9]+)/\1$dvmid\3/") [ -z "$dst_image_spec" ] && continue - echo "src_image_spec: $src_image_spec dst_image_spec: $dst_image_spec" [[ $disk =~ $recephimg ]] src_image_pool=${BASH_REMATCH[1]} src_image_name=${BASH_REMATCH[2]} [[ $dst_image_spec =~ ^[a-zA-Z0-9]+\/(.*)$ ]] dst_image_name=${BASH_REMATCH[1]} - echo "dst:image_name: $dst_image_name" snapshot_name="@$opt_snapshot_prefix$timestamp" localsnapcount=$(rbd ls -l $src_image_pool | grep $src_image_name@$opt_snapshot_prefix | cut -d ' ' -f 1|wc -l) if [ $localsnapcount -ge 2 ]; then @@ -357,13 +360,15 @@ function mirror() { localts=$(rbd ls -l $src_image_pool | grep $src_image_name@$opt_snapshot_prefix | cut -d ' ' -f 1 | sed -r -e 's/.*@mirror-(.*)/\1/') fi latestremote=$(ssh $opt_destination rbd ls -l $opt_pool | grep $dst_image_name@$opt_snapshot_prefix | cut -d ' ' -f 1|tail -n 1) - [[ $latestremote =~ ^.*@$opt_snapshot_prefix([0-9]+)$ ]] - latestremotets=${BASH_REMATCH[1]} - for ts in $localts; do - if [ $ts == $latestremotets ]; then - basets=$ts - fi - done + if [ $latestremote ]; then + [[ $latestremote =~ ^.*@$opt_snapshot_prefix([0-9]+)$ ]] + latestremotets=${BASH_REMATCH[1]} + for ts in $localts; do + if [ $ts == $latestremotets ]; then + basets=$ts + fi + done + fi if [ -z $basets ]; then log debug "No matching Snapshot found on destination - Full Copy $src_image_pool/$src_image_name$snapshot_name to $opt_pool/$dst_image_name" xmitjob="rbd export --rbd-concurrent-management-ops 8 $src_image_pool/$src_image_name$snapshot_name --no-progress -|pv -r|ssh $opt_destination rbd import --image-format 2 - $opt_pool/$dst_image_name" @@ -376,7 +381,6 @@ function mirror() { do_run $cmd else log debug "Basecopy + snapshot on destination - let's just transfer the diff" -# [[ $previouslocal =~ $resnapname ]] xmitjob="rbd export-diff --from-snap $opt_snapshot_prefix$basets $src_image_pool/$currentlocal - | ssh $opt_destination rbd import-diff - $opt_pool/$dst_image_name" if ! do_run $xmitjob; then log error "Transmitting Image failed" @@ -386,9 +390,13 @@ function mirror() { do_housekeeping "$opt_destination" "$opt_pool" "$dst_image_name" $opt_keep_remote fi done - if [ ! $opt_keeplock -eq 1 ] && [ ! $opt_lock -eq 1 ]; then + if [ ! $opt_keepslock -eq 1 ]; then ssh root@${pvnode[$vm_id]} qm unlock $vm_id - log info "Unlocking VM $vm_id" + log info "Unlocking source VM $vm_id" + fi + if [ $opt_keepdlock -eq 0 ]; then + ssh root@${dstpvnode[$dvmid]} qm unlock $dvmid + log info "Unlocking destination VM $dvmid" fi done } @@ -427,7 +435,6 @@ function vm_freeze() { fi local cmd="ssh root@$fhost /usr/sbin/qm guest cmd $fvm fsfreeze-freeze" log info "VM $fvm - Issuing fsfreeze-freeze to $fvm on $fhost" - log debug "$cmd" do_run "$cmd" rc=$? log debug "vm_freeze() return $rc" @@ -443,7 +450,6 @@ function vm_unfreeze() { fi local cmd="ssh root@$fhost /usr/sbin/qm guest cmd $fvm fsfreeze-thaw" log info "VM $fvm - Issuing fsfreeze-thaw to $fvm on $fhost" - log debug "$cmd" do_run "$cmd" rc=$? log debug "vm_unfreeze() return $rc"