5 Commits

Author SHA1 Message Date
Bastian
8467bcd08e improvement: precise wording 2023-08-04 16:05:56 +02:00
Bastian
48eb3f840e fix: missing vm_id in log message 2023-08-04 15:59:07 +02:00
Bastian
514d19b9f6 added: retrieve ceph versions for compatibility checks 2023-08-04 15:54:37 +02:00
Bastian
a6e1f9342a added: support for EFI Disks 2023-08-04 15:36:18 +02:00
Bastian
59b8ab5ce2 added: default pool, feature: confirm --migrate, add: --noconfirm 2023-08-04 13:38:26 +02:00

View File

@@ -39,6 +39,8 @@ declare -A -g dvmids
declare -g scluster declare -g scluster
declare -g dcluster declare -g dcluster
declare -g scephversion
declare -g dcephversion
# global integers # global integers
declare -g -i perf_freeze_ok=0 declare -g -i perf_freeze_ok=0
@@ -65,6 +67,7 @@ declare opt_destination
declare opt_vm_ids='' declare opt_vm_ids=''
declare opt_snapshot_prefix='mirror-' declare opt_snapshot_prefix='mirror-'
declare opt_rewrite='' declare opt_rewrite=''
declare opt_pool='rbd'
declare -i opt_prefix_id declare -i opt_prefix_id
declare opt_exclude_vmids='' declare opt_exclude_vmids=''
declare -i opt_debug=0 declare -i opt_debug=0
@@ -76,6 +79,7 @@ declare -i opt_keepdlock=0
declare -i opt_overwrite=0 declare -i opt_overwrite=0
declare -i opt_online=0 declare -i opt_online=0
declare -i opt_migrate=0 declare -i opt_migrate=0
declare -i opt_noconfirm=0
declare opt_keep_local='0s' declare opt_keep_local='0s'
declare opt_keep_remote='0s' declare opt_keep_remote='0s'
@@ -118,7 +122,7 @@ Options:
--prefixid Prefix for VMID's on target System [optional] --prefixid Prefix for VMID's on target System [optional]
--excludevmids Exclusde VM IDs when using --vmid==all --excludevmids Exclusde VM IDs when using --vmid==all
--destination Target PVE Host in target pool. e.g. --destination=pve04 --destination Target PVE Host in target pool. e.g. --destination=pve04
--pool Ceph pool name in target pool. e.g. --pool=data --pool Ceph pool name in target pool. e.g. --pool=data [default=rbd]
--keeplocal How many additional Snapshots to keep locally. e.g. --keeplocal=2d --keeplocal How many additional Snapshots to keep locally. e.g. --keeplocal=2d
--keepremote How many additional Snapshots to keep remote. e.g. --keepremote=7d --keepremote How many additional Snapshots to keep remote. e.g. --keepremote=7d
--rewrite PCRE Regex to rewrite the Config Files (eg. --rewrite='s/(net0:)(.*)tag=([0-9]+)/\1\2tag=1/g' would --rewrite PCRE Regex to rewrite the Config Files (eg. --rewrite='s/(net0:)(.*)tag=([0-9]+)/\1\2tag=1/g' would
@@ -135,6 +139,7 @@ Switches:
--keep-slock Keep source VM locked on Transfer --keep-slock Keep source VM locked on Transfer
--keep-dlock Keep VM locked after transfer on Destination --keep-dlock Keep VM locked after transfer on Destination
--overwrite Overwrite Destination --overwrite Overwrite Destination
--noconfirm Don't ask for confirmation before starting --migrate mode (use with care!)
--debug Show Debug Output --debug Show Debug Output
Report bugs to <mephisto@mephis.to> Report bugs to <mephisto@mephis.to>
@@ -149,7 +154,7 @@ function parse_opts(){
local args local args
args=$(getopt \ args=$(getopt \
--options '' \ --options '' \
--longoptions=vmid:,prefixid:,excludevmids:,destination:,pool:,keeplocal:,keepremote:,rewrite:,influxurl:,influxorg:,influxtoken:,influxbucket:,jobname:,mail:,online,migrate,nolock,keep-slock,keep-dlock,overwrite,dry-run,debug,syslog \ --longoptions=vmid:,prefixid:,excludevmids:,destination:,pool:,keeplocal:,keepremote:,rewrite:,influxurl:,influxorg:,influxtoken:,influxbucket:,jobname:,mail:,online,migrate,nolock,keep-slock,keep-dlock,overwrite,dry-run,noconfirm,debug,syslog \
--name "$PROGNAME" \ --name "$PROGNAME" \
-- "$@") \ -- "$@") \
|| end_process 128 || end_process 128
@@ -175,6 +180,7 @@ function parse_opts(){
--online) opt_online=1; shift ;; --online) opt_online=1; shift ;;
--migrate) opt_migrate=1; shift ;; --migrate) opt_migrate=1; shift ;;
--dry-run) opt_dry_run=1; shift;; --dry-run) opt_dry_run=1; shift;;
--noconfirm) opt_noconfirm=1; shift;;
--debug) opt_debug=1; shift;; --debug) opt_debug=1; shift;;
--nolock) opt_lock=0; shift;; --nolock) opt_lock=0; shift;;
--keep-slock) opt_keepslock=1; shift;; --keep-slock) opt_keepslock=1; shift;;
@@ -325,7 +331,7 @@ function get_disks_from_config(){
[[ "$line" == "" ]] && break [[ "$line" == "" ]] && break
echo "$line" echo "$line"
done < "$file_config" | \ done < "$file_config" | \
grep -P '^(?:((?:virtio|ide|scsi|sata|mp)\d+)|rootfs): ' | \ grep -P '^(?:((?:efidisk|virtio|ide|scsi|sata|mp)\d+)|rootfs): ' | \
grep -v -P 'cdrom|none' | \ grep -v -P 'cdrom|none' | \
grep -v -P 'backup=0' | \ grep -v -P 'backup=0' | \
awk '{ split($0,a,","); split(a[1],b," "); print b[2]}') awk '{ split($0,a,","); split(a[1],b," "); print b[2]}')
@@ -408,6 +414,7 @@ function mirror() {
local -i diskcount=0 local -i diskcount=0
local -i startdowntime local -i startdowntime
local -i enddowntime local -i enddowntime
local -i ga_ping
local disp_perf_freeze_failed local disp_perf_freeze_failed
local disp_perf_ss_failed local disp_perf_ss_failed
@@ -418,6 +425,9 @@ function mirror() {
log info "Start mirror $(date "+%F %T")" log info "Start mirror $(date "+%F %T")"
startjob=$(date +%s) startjob=$(date +%s)
get_ceph_version
log info "Local Ceph Version: $scephversion, Remote Ceph Version: $dcephversion"
#create pid file #create pid file
local pid_file="/var/run/$PROGNAME.pid" local pid_file="/var/run/$PROGNAME.pid"
if [[ -e "$pid_file" ]]; then if [[ -e "$pid_file" ]]; then
@@ -435,6 +445,20 @@ function mirror() {
scluster=$(grep cluster_name /etc/pve/corosync.conf | cut -d " " -f 4) scluster=$(grep cluster_name /etc/pve/corosync.conf | cut -d " " -f 4)
dcluster=$(ssh "$opt_destination" grep cluster_name /etc/pve/corosync.conf | cut -d " " -f 4) dcluster=$(ssh "$opt_destination" grep cluster_name /etc/pve/corosync.conf | cut -d " " -f 4)
if [ $opt_migrate -eq 1 ] && [ $opt_noconfirm -eq 0 ]; then
echo "VM(s) $opt_vm_ids will subsequently be shutdown on [$scluster] and started on [$dcluster]"
read -p "Do you want to proceed? (yes/no) " yn
case $yn in
yes ) echo ok, we will proceed;;
no ) echo exiting...;
exit;;
* ) echo invalid response;
exit 1;;
esac
fi
map_source_to_destination_vmid map_source_to_destination_vmid
map_vmids_to_host map_vmids_to_host
map_vmids_to_dsthost "$opt_destination" map_vmids_to_dsthost "$opt_destination"
@@ -450,6 +474,12 @@ function mirror() {
log error "VM $vm_id - Preflight check: VM $vm_id does not exist on source cluster [$scluster] - skipping to next VM." log error "VM $vm_id - Preflight check: VM $vm_id does not exist on source cluster [$scluster] - skipping to next VM."
continue continue
fi fi
ga_ping=$(gaping "$vm_id")
log debug "ga_ping: $ga_ping"
if [ "$ga_ping" -eq 255 ] ; then #vm running but no qemu-guest-agent answering
log error "VM $vm_id - Preflight check: VM $vm_id on source cluster [$scluster] has no qemu-guest-agent running - skipping to next VM."
continue
fi
(( vmcount++ )) (( vmcount++ ))
local disk='' local disk=''
dvmid=${dvmids[$vm_id]} dvmid=${dvmids[$vm_id]}
@@ -482,7 +512,7 @@ function mirror() {
log error "Source VM genid ($srcvmgenid) doesn't match destination VM genid ($dstvmgenid). This should not happen. Bailing out.." log error "Source VM genid ($srcvmgenid) doesn't match destination VM genid ($dstvmgenid). This should not happen. Bailing out.."
end_process 255 end_process 255
fi fi
log info "VM $vm_id - Transmitting Config for to destination $opt_destination VMID $dvmid" log info "VM $vm_id - Transmitting Config for VM $vm_id to destination $opt_destination VMID $dvmid"
rewriteconfig $PVE_NODES/"${pvnode[$vm_id]}"/$QEMU/"$vm_id".conf $opt_destination "$opt_pool" $PVE_NODES/"$opt_destination"/$QEMU/"$dvmid".conf "$dvmid" rewriteconfig $PVE_NODES/"${pvnode[$vm_id]}"/$QEMU/"$vm_id".conf $opt_destination "$opt_pool" $PVE_NODES/"$opt_destination"/$QEMU/"$dvmid".conf "$dvmid"
map_vmids_to_dsthost "$opt_destination" map_vmids_to_dsthost "$opt_destination"
fi fi
@@ -505,8 +535,8 @@ function mirror() {
do_run "ssh root@""${dstpvnode[$dvmid]}"" qm set ""$dvmid"" --lock backup" >/dev/null do_run "ssh root@""${dstpvnode[$dvmid]}"" qm set ""$dvmid"" --lock backup" >/dev/null
log info "VM $dvmid - locked $dvmid [rc:$?] on destination" log info "VM $dvmid - locked $dvmid [rc:$?] on destination"
fi fi
#Freeze fs only if no migration running #Freeze fs only if no migration running and qemu-guest-agent okay.
if [ $opt_migrate -eq 0 ]; then if [ $opt_migrate -eq 0 ] && [ $ga_ping -eq 0 ]; then
vm_freeze "$vm_id" "${pvnode[$vm_id]}" >/dev/null vm_freeze "$vm_id" "${pvnode[$vm_id]}" >/dev/null
freezerc=$? freezerc=$?
if [ $freezerc -gt 0 ]; then if [ $freezerc -gt 0 ]; then
@@ -709,6 +739,15 @@ function do_housekeeping(){
done done
} }
function gaping() {
local vmid=$1
local rc
cmd="ssh root@${pvnode[$vmid]} qm guest cmd $vmid ping >/dev/null 2>&1"
eval "$cmd"
rc=$?
echo $rc
}
function create_snapshot(){ function create_snapshot(){
local snap="$1" local snap="$1"
log info "VM $vm_id - Creating snapshot $snap" log info "VM $vm_id - Creating snapshot $snap"
@@ -765,7 +804,7 @@ function rewriteconfig(){
else else
sedcmd='sed -e /^$/,$d' sedcmd='sed -e /^$/,$d'
fi fi
cat "$oldconfig" | sed -r -e "s/^(virtio|ide|scsi|sata|mp)([0-9]+):\s([a-zA-Z0-9]+):(.*)-([0-9]+)-disk-([0-9]+).*,(.*)$/\1\2: $newpool:\4-$newvmid-disk-\6-\3,\7/g" | $sedcmd | sed -e '/^$/,$d' | sed -e '/ide[0-9]:.*-cloudinit,media=cdrom.*/d' | grep -v "^parent:\s.*$" | ssh "$dst" "cat - >$newconfig" cat "$oldconfig" | sed -r -e "s/^(efidisk|virtio|ide|scsi|sata|mp)([0-9]+):\s([a-zA-Z0-9]+):(.*)-([0-9]+)-disk-([0-9]+).*,(.*)$/\1\2: $newpool:\4-$newvmid-disk-\6-\3,\7/g" | $sedcmd | sed -e '/^$/,$d' | sed -e '/ide[0-9]:.*-cloudinit,media=cdrom.*/d' | grep -v "^parent:\s.*$" | ssh "$dst" "cat - >$newconfig"
} }
function checkvmid(){ function checkvmid(){
@@ -849,6 +888,11 @@ function check_pool_exist() {
echo $exists echo $exists
} }
function get_ceph_version() {
scephversion=$(ceph -v | cut -d " " -f 3)
dcephversion=$(ssh $opt_destination ceph -v | cut -d " " -f 3)
}
function main(){ function main(){
[ $# = 0 ] && usage; [ $# = 0 ] && usage;