X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=pve-zsync;h=2503117235bbc5bb3540ba69147aa33c77faf63d;hb=dfd3d834246a5c58d5bda69bec112ba970f51a78;hp=bc06ae12cddfd433523306318275f8f5658dfddd;hpb=1fe362eb85824f9d99f4fa946a485e359f688c4a;p=pve-zsync.git diff --git a/pve-zsync b/pve-zsync index bc06ae1..2503117 100644 --- a/pve-zsync +++ b/pve-zsync @@ -508,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); @@ -724,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}; @@ -739,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; } @@ -762,16 +762,15 @@ 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 @@ -792,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; } @@ -915,288 +914,354 @@ sub send_image { $target =~ s!/+!/!g; push @$cmd, \'|'; - push @$cmd, 'ssh', '-o', 'BatchMode=yes', "root\@$dest->{ip}", '--' if $dest->{ip}; - push @$cmd, 'zfs', 'recv', '-F', '--'; - push @$cmd, "$target"; + push @$cmd, 'ssh', '-o', 'BatchMode=yes', "root\@$dest->{ip}", '--' if $dest->{ip}; + push @$cmd, 'zfs', 'recv', '-F', '--'; + push @$cmd, "$target"; - eval { - run_cmd($cmd) - }; + eval { + run_cmd($cmd) + }; - if (my $erro = $@) { - snapshot_destroy($source, undef, $param->{method}, $source->{new_snap}); - die $erro; - }; - } + if (my $erro = $@) { + snapshot_destroy($source, undef, $param->{method}, $source->{new_snap}); + die $erro; + }; +} - sub send_config{ - my ($source, $dest, $method) = @_; +sub send_config{ + my ($source, $dest, $method) = @_; - my $source_target = $source->{vm_type} eq 'qemu' ? "$QEMU_CONF/$source->{vmid}.conf": "$LXC_CONF/$source->{vmid}.conf"; - my $dest_target_new ="$source->{vmid}.conf.$source->{vm_type}.$source->{new_snap}"; + my $source_target = $source->{vm_type} eq 'qemu' ? "$QEMU_CONF/$source->{vmid}.conf": "$LXC_CONF/$source->{vmid}.conf"; + my $dest_target_new ="$source->{vmid}.conf.$source->{vm_type}.$source->{new_snap}"; - my $config_dir = $dest->{last_part} ? "${CONFIG_PATH}/$dest->{last_part}" : $CONFIG_PATH; + my $config_dir = $dest->{last_part} ? "${CONFIG_PATH}/$dest->{last_part}" : $CONFIG_PATH; - $dest_target_new = $config_dir.'/'.$dest_target_new; + $dest_target_new = $config_dir.'/'.$dest_target_new; - if ($method eq 'ssh'){ - if ($dest->{ip} && $source->{ip}) { - run_cmd(['ssh', "root\@$dest->{ip}", '--', 'mkdir', '-p', '--', $config_dir]); - run_cmd(['scp', '--', "root\@[$source->{ip}]:$source_target", "root\@[$dest->{ip}]:$dest_target_new"]); - } elsif ($dest->{ip}) { - run_cmd(['ssh', "root\@$dest->{ip}", '--', 'mkdir', '-p', '--', $config_dir]); - 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]); - } + if ($method eq 'ssh'){ + if ($dest->{ip} && $source->{ip}) { + run_cmd(['ssh', "root\@$dest->{ip}", '--', 'mkdir', '-p', '--', $config_dir]); + run_cmd(['scp', '--', "root\@[$source->{ip}]:$source_target", "root\@[$dest->{ip}]:$dest_target_new"]); + } elsif ($dest->{ip}) { + run_cmd(['ssh', "root\@$dest->{ip}", '--', 'mkdir', '-p', '--', $config_dir]); + 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]); + } - if ($source->{destroy}){ - my $dest_target_old ="${config_dir}/$source->{vmid}.conf.$source->{vm_type}.$source->{old_snap}"; - if($dest->{ip}){ - run_cmd(['ssh', "root\@$dest->{ip}", '--', 'rm', '-f', '--', $dest_target_old]); - } else { - run_cmd(['rm', '-f', '--', $dest_target_old]); - } + if ($source->{destroy}){ + my $dest_target_old ="${config_dir}/$source->{vmid}.conf.$source->{vm_type}.$source->{old_snap}"; + if($dest->{ip}){ + run_cmd(['ssh', "root\@$dest->{ip}", '--', 'rm', '-f', '--', $dest_target_old]); + } else { + run_cmd(['rm', '-f', '--', $dest_target_old]); } - } elsif ($method eq 'local') { - run_cmd(['mkdir', '-p', '--', $config_dir]); - run_cmd(['cp', $source_target, $dest_target_new]); } + } elsif ($method eq 'local') { + run_cmd(['mkdir', '-p', '--', $config_dir]); + run_cmd(['cp', $source_target, $dest_target_new]); } +} - sub get_date { - my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); - my $datestamp = sprintf ("%04d-%02d-%02d_%02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec); +sub get_date { + my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); + my $datestamp = sprintf ("%04d-%02d-%02d_%02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec); - return $datestamp; - } + return $datestamp; +} - sub status { - my $cfg = read_cron(); +sub status { + my $cfg = read_cron(); - my $status_list = sprintf("%-25s%-25s%-10s\n", "SOURCE", "NAME", "STATUS"); + my $status_list = sprintf("%-25s%-25s%-10s\n", "SOURCE", "NAME", "STATUS"); - my $states = read_state(); + my $states = read_state(); - foreach my $source (sort keys%{$cfg}) { - foreach my $sync_name (sort keys%{$cfg->{$source}}) { - $status_list .= sprintf("%-25s", cut_target_width($source, 25)); - $status_list .= sprintf("%-25s", cut_target_width($sync_name, 25)); - $status_list .= "$states->{$source}->{$sync_name}->{state}\n"; - } + foreach my $source (sort keys%{$cfg}) { + foreach my $sync_name (sort keys%{$cfg->{$source}}) { + $status_list .= sprintf("%-25s", cut_target_width($source, 25)); + $status_list .= sprintf("%-25s", cut_target_width($sync_name, 25)); + $status_list .= "$states->{$source}->{$sync_name}->{state}\n"; } - - return $status_list; } - sub enable_job { - my ($param) = @_; + return $status_list; +} - my $job = get_job($param); - $job->{state} = "ok"; - update_state($job); - update_cron($job); - } +sub enable_job { + my ($param) = @_; - sub disable_job { - my ($param) = @_; + my $job = get_job($param); + $job->{state} = "ok"; + update_state($job); + update_cron($job); +} - my $job = get_job($param); - $job->{state} = "stopped"; - update_state($job); - update_cron($job); - } +sub disable_job { + my ($param) = @_; + + my $job = get_job($param); + $job->{state} = "stopped"; + update_state($job); + update_cron($job); +} - my $command = $ARGV[0]; +my $command = $ARGV[0]; - my $commands = {'destroy' => 1, - 'create' => 1, - 'sync' => 1, - 'list' => 1, - 'status' => 1, - 'help' => 1, - 'enable' => 1, - 'disable' => 1}; +my $commands = {'destroy' => 1, + 'create' => 1, + 'sync' => 1, + 'list' => 1, + 'status' => 1, + 'help' => 1, + 'enable' => 1, + 'disable' => 1}; - if (!$command || !$commands->{$command}) { - usage(); - die "\n"; - } +if (!$command || !$commands->{$command}) { + usage(); + die "\n"; +} - my $help_sync = "$PROGNAME sync -dest -source [OPTIONS]\n -\twill sync one time\n -\t-dest\tstring\n -\t\tthe destination target is like [IP:][/Path]\n -\t-limit\tinteger\n -\t\tmax sync speed in kBytes/s, default unlimited\n -\t-maxsnap\tinteger\n -\t\thow much snapshots will be kept before get erased, default 1/n -\t-name\tstring\n -\t\tname of the sync job, if not set it is default. -\tIt is only necessary if scheduler allready contains this source.\n -\t-source\tstring\n -\t\tthe source can be an or [IP:][/Path]\n"; - - my $help_create = "$PROGNAME create -dest -source [OPTIONS]/n -\tCreate a sync Job\n -\t-dest\tstring\n -\t\tthe destination target is like [IP]:[/Path]\n -\t-limit\tinteger\n -\t\tmax sync speed in kBytes/s, default unlimited\n -\t-maxsnap\tstring\n -\t\thow much snapshots will be kept before get erased, default 1\n -\t-name\tstring\n -\t\tname of the sync job, if not set it is default\n -\t-skip\tboolean\n -\t\tif this flag is set it will skip the first sync\n -\t-source\tstring\n -\t\tthe source can be an or [IP:][/Path]\n"; - - my $help_destroy = "$PROGNAME destroy -source [OPTIONS]\n -\tremove a sync Job from the scheduler\n -\t-name\tstring\n -\t\tname of the sync job, if not set it is default\n -\t-source\tstring\n -\t\tthe source can be an or [IP:][/Path]\n"; - - my $help_help = "$PROGNAME help [OPTIONS]\n -\tGet help about specified command.\n -\t\tstring\n -\t\tCommand name\n -\t-verbose\tboolean\n -\t\tVerbose output format.\n"; - - my $help_list = "$PROGNAME list\n -\tGet a List of all scheduled Sync Jobs\n"; - - my $help_status = "$PROGNAME status\n -\tGet the status of all scheduled Sync Jobs\n"; - - my $help_enable = "$PROGNAME enable -source [OPTIONS]\n -\tenable a syncjob and reset error\n -\t-name\tstring\n -\t\tname of the sync job, if not set it is default\n -\t-source\tstring\n -\t\tthe source can be an or [IP:][/Path]\n"; - - my $help_disable = "$PROGNAME disable -source [OPTIONS]\n -\tpause a syncjob\n -\t-name\tstring\n -\t\tname of the sync job, if not set it is default\n -\t-source\tstring\n -\t\tthe source can be an or [IP:][/Path]\n"; - - sub help { - my ($command) = @_; - - 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"; +my $help_sync = < -source [OPTIONS]\n - } + will sync one time - } + -dest string + + the destination target is like [IP:][/Path] - my @arg = @ARGV; - my $param = parse_argv(@arg); + -limit integer - if ($command eq 'destroy') { - die "$help_destroy\n" if !$param->{source}; + max sync speed in kBytes/s, default unlimited - check_target($param->{source}); - destroy_job($param); + -maxsnap integer + + how much snapshots will be kept before get erased, default 1 + + -name string + + name of the sync job, if not set it is default. + It is only necessary if scheduler allready contains this source. + + -source string + + the source can be an or [IP:][/Path] + + -verbose boolean + + print out the sync progress. +EOF + +my $help_create = < -source [OPTIONS] + + Create a sync Job + + -dest string + + the destination target is like [IP]:[/Path] + + -limit integer + + max sync speed in kBytes/s, default unlimited + + -maxsnap string + + how much snapshots will be kept before get erased, default 1 + + -name string + + name of the sync job, if not set it is default + + -skip boolean + + if this flag is set it will skip the first sync + + -source string + + the source can be an or [IP:][/Path] +EOF + +my $help_destroy = < [OPTIONS] + + remove a sync Job from the scheduler + + -name string + + name of the sync job, if not set it is default + + -source string + + the source can be an or [IP:][/Path] +EOF + +my $help_help = < [OPTIONS] + + Get help about specified command. + + string + + Command name + + -verbose boolean + + Verbose output format. +EOF + +my $help_list = < [OPTIONS] + + enable a syncjob and reset error + + -name string + + name of the sync job, if not set it is default + + -source string + + the source can be an or [IP:][/Path] +EOF + +my $help_disable = < [OPTIONS] + + pause a sync job + + -name string + + name of the sync job, if not set it is default + + -source string + + the source can be an or [IP:][/Path] +EOF + +sub help { + my ($command) = @_; + + if ($command eq 'help') { + die "$help_help\n"; } elsif ($command eq 'sync') { - die "$help_sync\n" if !$param->{source} || !$param->{dest}; + die "$help_sync\n"; - check_target($param->{source}); - check_target($param->{dest}); - sync($param); + } elsif ($command eq 'destroy') { + die "$help_destroy\n"; } elsif ($command eq 'create') { - die "$help_create\n" if !$param->{source} || !$param->{dest}; + die "$help_create\n"; - check_target($param->{source}); - check_target($param->{dest}); - init($param); + } elsif ($command eq 'list') { + die "$help_list\n"; } elsif ($command eq 'status') { - print status(); + die "$help_status\n"; - } elsif ($command eq 'list') { - print list(); + } elsif ($command eq 'enable') { + die "$help_enable\n"; - } elsif ($command eq 'help') { - my $help_command = $ARGV[1]; + } elsif ($command eq 'disable') { + die "$help_disable\n"; - if ($help_command && $commands->{$help_command}) { - print help($help_command); + } - } - if ($param->{verbose} == 1){ - exec("man $PROGNAME"); +} - } else { - usage(1); +my @arg = @ARGV; +my $param = parse_argv(@arg); - } +if ($command eq 'destroy') { + die "$help_destroy\n" if !$param->{source}; - } elsif ($command eq 'enable') { - die "$help_enable\n" if !$param->{source}; + check_target($param->{source}); + destroy_job($param); - check_target($param->{source}); - enable_job($param); +} elsif ($command eq 'sync') { + die "$help_sync\n" if !$param->{source} || !$param->{dest}; - } elsif ($command eq 'disable') { - die "$help_disable\n" if !$param->{source}; + check_target($param->{source}); + check_target($param->{dest}); + sync($param); - check_target($param->{source}); - disable_job($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); - sub usage { - my ($help) = @_; - - print("ERROR:\tno command specified\n") if !$help; - print("USAGE:\t$PROGNAME [ARGS] [OPTIONS]\n"); - print("\t$PROGNAME help [] [OPTIONS]\n\n"); - print("\t$PROGNAME create -dest -source [OPTIONS]\n"); - print("\t$PROGNAME destroy -source [OPTIONS]\n"); - print("\t$PROGNAME disable -source [OPTIONS]\n"); - print("\t$PROGNAME enable -source [OPTIONS]\n"); - print("\t$PROGNAME list\n"); - print("\t$PROGNAME status\n"); - print("\t$PROGNAME sync -dest -source [OPTIONS]\n"); } + if ($param->{verbose}) { + exec("man $PROGNAME"); + + } else { + usage(1); - sub check_target { - my ($target) = @_; - parse_target($target); } +} 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 { + my ($help) = @_; + + print("ERROR:\tno command specified\n") if !$help; + print("USAGE:\t$PROGNAME [ARGS] [OPTIONS]\n"); + print("\t$PROGNAME help [] [OPTIONS]\n\n"); + print("\t$PROGNAME create -dest -source [OPTIONS]\n"); + print("\t$PROGNAME destroy -source [OPTIONS]\n"); + print("\t$PROGNAME disable -source [OPTIONS]\n"); + print("\t$PROGNAME enable -source [OPTIONS]\n"); + print("\t$PROGNAME list\n"); + print("\t$PROGNAME status\n"); + print("\t$PROGNAME sync -dest -source [OPTIONS]\n"); +} + +sub check_target { + my ($target) = @_; + parse_target($target); +} + __END__ =head1 NAME @@ -1315,6 +1380,10 @@ pve-zsync sync -dest -source [OPTIONS] the source can be an or [IP:][/Path] + -verbose boolean + + print out the sync progress. + =head1 DESCRIPTION This Tool helps you to sync your VM or directory which stored on ZFS between 2 servers.