X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=pve-zsync;h=b3241ff2f19ddd2ae4b33a1b966a0e4281e29714;hb=57e0588db3538a001d568ec2ad489034700419a5;hp=4491d1a5062a256e175f8a1ad6b899cfbacea280;hpb=148408c3256ecd166b8144a858464136f725d504;p=pve-zsync.git diff --git a/pve-zsync b/pve-zsync index 4491d1a..b3241ff 100644 --- a/pve-zsync +++ b/pve-zsync @@ -7,7 +7,6 @@ use Fcntl qw(:flock SEEK_END); use Getopt::Long qw(GetOptionsFromArray); use File::Copy qw(move); use File::Path qw(make_path); -use Switch; use JSON; use IO::File; use String::ShellQuote 'shell_quote'; @@ -52,6 +51,11 @@ check_bin ('zfs'); check_bin ('ssh'); check_bin ('scp'); +$SIG{TERM} = $SIG{QUIT} = $SIG{PIPE} = $SIG{HUP} = $SIG{KILL} = $SIG{INT} = + sub { + die "Signal aborting sync\n"; + }; + sub check_bin { my ($bin) = @_; @@ -66,21 +70,33 @@ sub check_bin { } sub cut_target_width { - my ($target, $max) = @_; + my ($path, $maxlen) = @_; + $path =~ s@/+@/@g; + + return $path if length($path) <= $maxlen; + + return '..'.substr($path, -$maxlen+2) if $path !~ m@/@; - return $target if (length($target) <= $max); - my @spl = split('/', $target); + $path =~ s@/([^/]+/?)$@@; + my $tail = $1; - my $count = length($spl[@spl-1]); - return "..\/".substr($spl[@spl-1],($count-$max)+3 , $count) if $count > $max; + if (length($tail)+3 == $maxlen) { + return "../$tail"; + } elsif (length($tail)+2 >= $maxlen) { + return '..'.substr($tail, -$maxlen+2) + } - $count += length($spl[0]) if @spl > 1; - return substr($spl[0], 0, $max-4-length($spl[@spl-1]))."\/..\/".$spl[@spl-1] if $count > $max; + $path =~ s@(/[^/]+)(?:/|$)@@; + my $head = $1; + my $both = length($head) + length($tail); + my $remaining = $maxlen-$both-4; # -4 for "/../" - my $rest = 1; - $rest = $max-$count if ($max-$count > 0); + if ($remaining < 0) { + return substr($head, 0, $maxlen - length($tail) - 3) . "../$tail"; # -3 for "../" + } - return "$spl[0]".substr($target, length($spl[0]), $rest)."..\/".$spl[@spl-1]; + substr($path, ($remaining/2), (length($path)-$remaining), '..'); + return "$head/" . $path . "/$tail"; } sub lock { @@ -107,7 +123,10 @@ sub check_pool_exists { my ($target) = @_; my $cmd = []; - push @$cmd, 'ssh', "root\@$target->{ip}", '--', if $target->{ip}; + + if ($target->{ip}) { + push @$cmd, 'ssh', "root\@$target->{ip}", '--'; + } push @$cmd, 'zfs', 'list', '-H', '--', $target->{all}; eval { run_cmd($cmd); @@ -474,11 +493,11 @@ sub init { run_cmd(['ssh-copy-id', '-i', '/root/.ssh/id_rsa.pub', "root\@$ip"]); } - die "Pool $dest->{all} does not exists\n" if check_pool_exists($dest); + die "Pool $dest->{all} does not exists\n" if !check_pool_exists($dest); - my $check = check_pool_exists($source->{path}, $source->{ip}) if !$source->{vmid} && $source->{path}; - - die "Pool $source->{path} does not exists\n" if undef($check); + if (!defined($source->{vmid})) { + die "Pool $source->{all} does not exists\n" if !check_pool_exists($source); + } my $vm_type = vm_exists($source); $job->{vm_type} = $vm_type; @@ -489,7 +508,7 @@ sub init { die "Config already exists\n" if $cfg->{$job->{source}}->{$job->{name}}; #check if vm has zfs disks if not die; - get_disks($source, 1) if $source->{vmid}; + get_disks($source) if $source->{vmid}; update_cron($job); update_state($job); @@ -629,7 +648,7 @@ sub snapshot_get{ while ($raw && $raw =~ s/^(.*?)(\n|$)//) { $line = $1; - if ($line =~ m/(rep_$name.*)$/) { + if ($line =~ m/(rep_\Q${name}\E_\d{4}-\d{2}-\d{2}_\d{2}:\d{2}:\d{2})$/) { $last_snap = $1 if (!$last_snap); $old_snap = $1; @@ -705,7 +724,7 @@ sub write_cron { } sub get_disks { - my ($target, $get_err) = @_; + my ($target) = @_; my $cmd = []; push @$cmd, 'ssh', "root\@$target->{ip}", '--', if $target->{ip}; @@ -720,7 +739,7 @@ sub get_disks { my $res = run_cmd($cmd); - my $disks = parse_disks($res, $target->{ip}, $target->{vm_type}, $get_err); + my $disks = parse_disks($res, $target->{ip}, $target->{vm_type}); return $disks; } @@ -743,23 +762,22 @@ sub run_cmd { } sub parse_disks { - my ($text, $ip, $vm_type, $get_err) = @_; + my ($text, $ip, $vm_type) = @_; my $disks; my $num = 0; while ($text && $text =~ s/^(.*?)(\n|$)//) { my $line = $1; - my $error = $vm_type eq 'qemu' ? 1 : 0 ; - next if $line =~ /cdrom|none/; + next if $line =~ /media=cdrom/; next if $line !~ m/^(?:((?:virtio|ide|scsi|sata|mp)\d+)|rootfs): /; #QEMU if backup is not set include in sync - next if $vm_type eq 'qemu && ($line =~ m/backup=(?i:0|no|off|false)/)'; + next if $vm_type eq 'qemu' && ($line =~ m/backup=(?i:0|no|off|false)/); #LXC if backup is not set do no in sync - $error = ($line =~ m/backup=(?i:1|yes|on|true)/) if $vm_type eq 'lxc'; + next if $vm_type eq 'lxc' && ($line =~ m/^mp\d:/) && ($line !~ m/backup=(?i:1|yes|on|true)/); my $disk = undef; my $stor = undef; @@ -773,9 +791,9 @@ sub parse_disks { last; } } - - } else { - print "Disk: \"$line\" will not include in pve-sync\n" if $get_err || $error; + } + if (!defined($disk) || !defined($stor)) { + print "Disk: \"$line\" has no valid zfs dataset format and will be skipped\n"; next; } @@ -879,7 +897,7 @@ sub send_image { my $cmd = []; - push @$cmd, 'ssh', "root\@$source->{ip}", '--' if $source->{ip}; + push @$cmd, 'ssh', '-o', 'BatchMode=yes', "root\@$source->{ip}", '--' if $source->{ip}; push @$cmd, 'zfs', 'send'; push @$cmd, '-v' if $param->{verbose}; @@ -896,7 +914,7 @@ sub send_image { $target =~ s!/+!/!g; push @$cmd, \'|'; - push @$cmd, 'ssh', "root\@$dest->{ip}", '--' if $dest->{ip}; + push @$cmd, 'ssh', '-o', 'BatchMode=yes', "root\@$dest->{ip}", '--' if $dest->{ip}; push @$cmd, 'zfs', 'recv', '-F', '--'; push @$cmd, "$target"; @@ -930,7 +948,7 @@ sub send_image { run_cmd(['scp', '--', $source_target, "root\@[$dest->{ip}]:$dest_target_new"]); } elsif ($source->{ip}) { run_cmd(['mkdir', '-p', '--', $config_dir]); - run_cmd(['scp', '--', "root\@$source->{ip}:$source_target", $dest_target_new]); + run_cmd(['scp', '--', "root\@[$source->{ip}]:$source_target", $dest_target_new]); } if ($source->{destroy}){ @@ -1072,39 +1090,30 @@ sub send_image { sub help { my ($command) = @_; - switch($command){ - case 'help' - { - die "$help_help\n"; - } - case 'sync' - { - die "$help_sync\n"; - } - case 'destroy' - { - die "$help_destroy\n"; - } - case 'create' - { - die "$help_create\n"; - } - case 'list' - { - die "$help_list\n"; - } - case 'status' - { - die "$help_status\n"; - } - case 'enable' - { - die "$help_enable\n"; - } - case 'disable' - { - die "$help_enable\n"; - } + if ($command eq 'help') { + die "$help_help\n"; + + } elsif ($command eq 'sync') { + die "$help_sync\n"; + + } elsif ($command eq 'destroy') { + die "$help_destroy\n"; + + } elsif ($command eq 'create') { + die "$help_create\n"; + + } elsif ($command eq 'list') { + die "$help_list\n"; + + } elsif ($command eq 'status') { + die "$help_status\n"; + + } elsif ($command eq 'enable') { + die "$help_enable\n"; + + } elsif ($command eq 'disable') { + die "$help_disable\n"; + } } @@ -1112,60 +1121,59 @@ sub send_image { my @arg = @ARGV; my $param = parse_argv(@arg); + if ($command eq 'destroy') { + die "$help_destroy\n" if !$param->{source}; + + check_target($param->{source}); + destroy_job($param); + + } elsif ($command eq 'sync') { + die "$help_sync\n" if !$param->{source} || !$param->{dest}; + + check_target($param->{source}); + check_target($param->{dest}); + sync($param); + + } elsif ($command eq 'create') { + die "$help_create\n" if !$param->{source} || !$param->{dest}; + + check_target($param->{source}); + check_target($param->{dest}); + init($param); + + } elsif ($command eq 'status') { + print status(); + + } elsif ($command eq 'list') { + print list(); + + } elsif ($command eq 'help') { + my $help_command = $ARGV[1]; + + if ($help_command && $commands->{$help_command}) { + print help($help_command); - switch($command) { - case "destroy" - { - die "$help_destroy\n" if !$param->{source}; - check_target($param->{source}); - destroy_job($param); - } - case "sync" - { - die "$help_sync\n" if !$param->{source} || !$param->{dest}; - check_target($param->{source}); - check_target($param->{dest}); - sync($param); - } - case "create" - { - die "$help_create\n" if !$param->{source} || !$param->{dest}; - check_target($param->{source}); - check_target($param->{dest}); - init($param); - } - case "status" - { - print status(); - } - case "list" - { - print list(); - } - case "help" - { - my $help_command = $ARGV[1]; - if ($help_command && $commands->{$help_command}) { - print help($help_command); - } - if ($param->{verbose} == 1){ - exec("man $PROGNAME"); - } else { - usage(1); - } - } - case "enable" - { - die "$help_enable\n" if !$param->{source}; - check_target($param->{source}); - enable_job($param); } - case "disable" - { - die "$help_disable\n" if !$param->{source}; - check_target($param->{source}); - disable_job($param); + if ($param->{verbose} == 1){ + exec("man $PROGNAME"); + + } else { + usage(1); + } + + } elsif ($command eq 'enable') { + die "$help_enable\n" if !$param->{source}; + + check_target($param->{source}); + enable_job($param); + + } elsif ($command eq 'disable') { + die "$help_disable\n" if !$param->{source}; + + check_target($param->{source}); + disable_job($param); + } sub usage {