# targets are either a VMID, or a 'host:zpool/path' with 'host:' being optional
my $TARGETRE = qr!^(?:($HOSTRE):)?(\d+|(?:[\w\-_]+)(/.+)?)$!;
+my $DISK_KEY_RE = qr/^(?:(?:(?:virtio|ide|scsi|sata|efidisk|mp)\d+)|rootfs): /;
+
my $command = $ARGV[0];
if (defined($command) && $command ne 'help' && $command ne 'printpod') {
my $sync_path = sub {
my ($source, $dest, $job, $param, $date) = @_;
- ($source->{old_snap}, $source->{last_snap}) = snapshot_get($source, $dest, $param->{maxsnap}, $param->{name}, $param->{source_user});
+ ($dest->{old_snap}, $dest->{last_snap}) = snapshot_get($source, $dest, $param->{maxsnap}, $param->{name}, $param->{dest_user});
snapshot_add($source, $dest, $param->{name}, $date, $param->{source_user}, $param->{dest_user});
send_image($source, $dest, $param);
- snapshot_destroy($source, $dest, $param->{method}, $source->{old_snap}, $param->{source_user}, $param->{dest_user}) if ($source->{destroy} && $source->{old_snap});
+ snapshot_destroy($source, $dest, $param->{method}, $dest->{old_snap}, $param->{source_user}, $param->{dest_user}) if ($source->{destroy} && $dest->{old_snap});
};
}
sub snapshot_get{
- my ($source, $dest, $max_snap, $name, $source_user) = @_;
+ my ($source, $dest, $max_snap, $name, $dest_user) = @_;
my $cmd = [];
- push @$cmd, 'ssh', "$source_user\@$source->{ip}", '--', if $source->{ip};
+ push @$cmd, 'ssh', "$dest_user\@$dest->{ip}", '--', if $dest->{ip};
push @$cmd, 'zfs', 'list', '-r', '-t', 'snapshot', '-Ho', 'name', '-S', 'creation';
- push @$cmd, $source->{all};
- my $raw = run_cmd($cmd);
+ my $path = $dest->{all};
+ $path .= "/$source->{last_part}" if $source->{last_part};
+ push @$cmd, $path;
+
+ my $raw;
+ eval {$raw = run_cmd($cmd)};
+ if (my $erro =$@) { #this means the volume doesn't exist on dest yet
+ return undef;
+ }
+
my $index = 0;
my $line = "";
my $last_snap = undef;
while ($raw && $raw =~ s/^(.*?)(\n|$)//) {
$line = $1;
- if ($line =~ m/(rep_\Q${name}\E_\d{4}-\d{2}-\d{2}_\d{2}:\d{2}:\d{2})$/) {
-
+ if ($line =~ m/@(.*)$/) {
$last_snap = $1 if (!$last_snap);
+ }
+ if ($line =~ m/(rep_\Q${name}\E_\d{4}-\d{2}-\d{2}_\d{2}:\d{2}:\d{2})$/) {
$old_snap = $1;
$index++;
if ($index == $max_snap) {
}
}
-sub write_cron {
- my ($cfg) = @_;
-
- my $text = "SHELL=/bin/sh\n";
- $text .= "PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin\n";
-
- my $fh = IO::File->new("> $CRONJOBS");
- die "Could not open file: $!\n" if !$fh;
-
- foreach my $source (sort keys%{$cfg}) {
- foreach my $sync_name (sort keys%{$cfg->{$source}}) {
- next if $cfg->{$source}->{$sync_name}->{status} ne 'ok';
- $text .= "$PROG_PATH sync";
- $text .= " -source ";
- if ($cfg->{$source}->{$sync_name}->{vmid}) {
- $text .= "$cfg->{$source}->{$sync_name}->{source_ip}:" if $cfg->{$source}->{$sync_name}->{source_ip};
- $text .= "$cfg->{$source}->{$sync_name}->{vmid} ";
- } else {
- $text .= "$cfg->{$source}->{$sync_name}->{source_ip}:" if $cfg->{$source}->{$sync_name}->{source_ip};
- $text .= "$cfg->{$source}->{$sync_name}->{source_pool}";
- $text .= "$cfg->{$source}->{$sync_name}->{source_path}" if $cfg->{$source}->{$sync_name}->{source_path};
- }
- $text .= " -dest ";
- $text .= "$cfg->{$source}->{$sync_name}->{dest_ip}:" if $cfg->{$source}->{$sync_name}->{dest_ip};
- $text .= "$cfg->{$source}->{$sync_name}->{dest_pool}";
- $text .= "$cfg->{$source}->{$sync_name}->{dest_path}" if $cfg->{$source}->{$sync_name}->{dest_path};
- $text .= " -name $sync_name ";
- $text .= " -limit $cfg->{$source}->{$sync_name}->{limit}" if $cfg->{$source}->{$sync_name}->{limit};
- $text .= " -maxsnap $cfg->{$source}->{$sync_name}->{maxsnap}" if $cfg->{$source}->{$sync_name}->{maxsnap};
- $text .= "\n";
- }
- }
- die "Can't write to cron\n" if (!print($fh $text));
- close($fh);
-}
-
sub get_disks {
my ($target, $user) = @_;
my $line = $1;
next if $line =~ /media=cdrom/;
- next if $line !~ m/^(?:((?:virtio|ide|scsi|sata|mp)\d+)|rootfs): /;
+ next if $line !~ m/$DISK_KEY_RE/;
#QEMU if backup is not set include in sync
next if $vm_type eq 'qemu' && ($line =~ m/backup=(?i:0|no|off|false)/);
my $disk = undef;
my $stor = undef;
- if($line =~ m/^(?:(?:(?:virtio|ide|scsi|sata|mp)\d+)|rootfs): (.*)$/) {
+ if($line =~ m/$DISK_KEY_RE(.*)$/) {
my @parameter = split(/,/,$1);
foreach my $opt (@parameter) {
}
}
+# check if snapshot for incremental sync exist on source side
sub snapshot_exist {
- my ($source , $dest, $method, $dest_user) = @_;
+ my ($source , $dest, $method, $source_user) = @_;
my $cmd = [];
- push @$cmd, 'ssh', "$dest_user\@$dest->{ip}", '--' if $dest->{ip};
+ push @$cmd, 'ssh', "$source_user\@$source->{ip}", '--' if $source->{ip};
push @$cmd, 'zfs', 'list', '-rt', 'snapshot', '-Ho', 'name';
- my $path = $dest->{all};
- $path .= "/$source->{last_part}" if $source->{last_part};
- $path .= "\@$source->{old_snap}";
+ my $path = $source->{all};
+ $path .= "\@$dest->{last_snap}";
push @$cmd, $path;
-
- my $text = "";
- eval {$text =run_cmd($cmd);};
+ eval {run_cmd($cmd)};
if (my $erro =$@) {
warn "WARN: $erro";
return undef;
}
-
- while ($text && $text =~ s/^(.*?)(\n|$)//) {
- my $line =$1;
- return 1 if $line =~ m/^.*$source->{old_snap}$/;
- }
+ return 1;
}
sub send_image {
push @$cmd, '-p', if $param->{properties};
push @$cmd, '-v' if $param->{verbose};
- if($source->{last_snap} && snapshot_exist($source , $dest, $param->{method}, $param->{dest_user})) {
- push @$cmd, '-i', "$source->{all}\@$source->{last_snap}";
+ if($dest->{last_snap} && snapshot_exist($source , $dest, $param->{method}, $param->{source_user})) {
+ push @$cmd, '-i', "$source->{all}\@$dest->{last_snap}";
}
push @$cmd, '--', "$source->{all}\@$source->{new_snap}";
}
if ($source->{destroy}){
- my $dest_target_old ="${config_dir}/$source->{vmid}.conf.$source->{vm_type}.$source->{old_snap}";
+ my $dest_target_old ="${config_dir}/$source->{vmid}.conf.$source->{vm_type}.$dest->{old_snap}";
if($dest->{ip}){
run_cmd(['ssh', "$dest_user\@$dest->{ip}", '--', 'rm', '-f', '--', $dest_target_old]);
} else {