]> git.proxmox.com Git - pve-zsync.git/blobdiff - pve-zsync
decode in config name the type of config.
[pve-zsync.git] / pve-zsync
index 4941456b664f7c803142e3fa751162a09061f533..0add81a6c98e7051dcc7826706623ab6cffe8922 100644 (file)
--- a/pve-zsync
+++ b/pve-zsync
@@ -17,7 +17,9 @@ my $CONFIG_PATH = "/var/lib/${PROGNAME}/";
 my $STATE = "${CONFIG_PATH}sync_state";
 my $CRONJOBS = "/etc/cron.d/$PROGNAME";
 my $PATH = "/usr/sbin/";
-my $QEMU_CONF = "/etc/pve/local/qemu-server/";
+my $PVE_DIR = "/etc/pve/local/";
+my $QEMU_CONF = "${PVE_DIR}qemu-server/";
+my $LXC_CONF = "${PVE_DIR}lxc/";
 my $LOCKFILE = "$CONFIG_PATH${PROGNAME}.lock";
 my $PROG_PATH = "$PATH${PROGNAME}";
 my $INTERVAL = 15;
@@ -215,6 +217,7 @@ sub add_state_to_job {
 
     $job->{state} = $state->{state};
     $job->{lsync} = $state->{lsync};
+    $job->{vm_type} = $state->{vm_type};
 
     for (my $i = 0; $state->{"snap$i"}; $i++) {
        $job->{"snap$i"} = $state->{"snap$i"};
@@ -313,6 +316,7 @@ sub update_state {
     if ($job->{state} ne "del") {
        $state->{state} = $job->{state};
        $state->{lsync} = $job->{lsync};
+       $state->{vm_type} = $job->{vm_type};
 
        for (my $i = 0; $job->{"snap$i"} ; $i++) {
            $state->{"snap$i"} = $job->{"snap$i"};
@@ -411,15 +415,16 @@ sub list {
 
     my $cfg = read_cron();
 
-    my $list = sprintf("%-25s%-15s%-7s%-20s%-5s\n" , "SOURCE", "NAME", "STATE", "LAST SYNC", "TYPE");
+    my $list = sprintf("%-25s%-10s%-7s%-20s%-5s%-5s\n" , "SOURCE", "NAME", "STATE", "LAST SYNC", "TYPE", "CON");
 
     my $states = read_state();
     foreach my $source (sort keys%{$cfg}) {
        foreach my $name (sort keys%{$cfg->{$source}}) {
            $list .= sprintf("%-25s", cut_target_width($source, 25));
-           $list .= sprintf("%-15s", cut_target_width($name, 15));
+           $list .= sprintf("%-10s", cut_target_width($name, 10));
            $list .= sprintf("%-7s", $states->{$source}->{$name}->{state});
            $list .= sprintf("%-20s",$states->{$source}->{$name}->{lsync});
+           $list .= sprintf("%-5s",$states->{$source}->{$name}->{vm_type});
            $list .= sprintf("%-5s\n",$cfg->{$source}->{$name}->{method});
        }
     }
@@ -429,14 +434,19 @@ sub list {
 
 sub vm_exists {
     my ($target) = @_;
+    
+    my @cmd = ('ssh', "root\@$target->{ip}", '--') if $target->{ip};
 
-    my $cmd = [];
-    push @$cmd, 'ssh', "root\@$target->{ip}", '--', if $target->{ip};
-    push @$cmd, 'qm', 'status', $target->{vmid};
+    my $res = undef;
 
-    my $res = run_cmd($cmd);
+    eval { $res = run_cmd([@cmd, 'ls',  "$QEMU_CONF$target->{vmid}.conf"]) };
+
+    return "qemu" if $res;
+
+    eval { $res = run_cmd([@cmd, 'ls',  "$LXC_CONF$target->{vmid}.conf"]) };
+
+    return "lxc" if $res;
 
-    return 1 if ($res =~ m/^status.*$/);
     return undef;
 }
 
@@ -467,7 +477,10 @@ sub init {
 
     die "Pool $source->{path} does not exists\n" if undef($check);
 
-    die "VM $source->{vmid} doesn't exist\n" if $param->{vmid} && !vm_exists($source);
+    my $vm_type = vm_exists($source);
+    $job->{vm_type} = $vm_type;
+
+    die "VM $source->{vmid} doesn't exist\n" if $param->{vmid} && !$vm_type;
 
     die "Config already exists\n" if $cfg->{$job->{source}}->{$job->{name}};
 
@@ -542,14 +555,18 @@ sub sync {
 
     };
 
+    my $vm_type = vm_exists($source);
+    $source->{vm_type} = $vm_type;
+
     if ($job) {
        $job->{state} = "syncing";
+       $job->{vm_type} = $vm_type if !$job->{vm_type};
        update_state($job);
     }
 
     eval{
        if ($source->{vmid}) {
-           die "VM $source->{vmid} doesn't exist\n" if !vm_exists($source);
+           die "VM $source->{vmid} doesn't exist\n" if !$vm_type;
            my $disks = get_disks($source);
 
            foreach my $disk (sort keys %{$disks}) {
@@ -559,8 +576,10 @@ sub sync {
                $source->{last_part} = $disks->{$disk}->{last_part};
                &$sync_path($source, $dest, $job, $param, $date);
            }
-           if ($param->{method} eq "ssh") {
+           if ($param->{method} eq "ssh" && ($source->{ip} || $dest->{ip})) {
                send_config($source, $dest,'ssh');
+           } else {
+               send_config($source, $dest,'local');
            }
        } else {
            &$sync_path($source, $dest, $job, $param, $date);
@@ -682,11 +701,18 @@ sub get_disks {
 
     my $cmd = [];
     push @$cmd, 'ssh', "root\@$target->{ip}", '--', if $target->{ip};
-    push @$cmd, 'qm', 'config', $target->{vmid};
+
+    if ($target->{vm_type} eq 'qemu') {
+       push @$cmd, 'qm', 'config', $target->{vmid};
+    } elsif ($target->{vm_type} eq 'lxc') {
+       push @$cmd, 'pct', 'config', $target->{vmid};
+    } else {
+       die "VM Type unknown\n";
+    }
 
     my $res = run_cmd($cmd);
 
-    my $disks = parse_disks($res, $target->{ip});
+    my $disks = parse_disks($res, $target->{ip}, $target->{vm_type});
 
     return $disks;
 }
@@ -709,7 +735,7 @@ sub run_cmd {
 }
 
 sub parse_disks {
-    my ($text, $ip) = @_;
+    my ($text, $ip, $vm_type) = @_;
 
     my $disks;
 
@@ -718,13 +744,13 @@ sub parse_disks {
        my $line = $1;
 
        next if $line =~ /cdrom|none/;
-       next if $line !~ m/^(?:virtio|ide|scsi|sata)\d+: /;
+       next if $line !~ m/^(?:((?:virtio|ide|scsi|sata|mp)\d+)|rootfs): /;
 
        my $disk = undef;
        my $stor = undef;
-       if($line =~ m/^(?:virtio|ide|scsi|sata)\d+: (.+:)([A-Za-z0-9\-]+),(.*)$/) {
-           $disk = $2;
-           $stor = $1;
+       if($line =~ m/^(?:((?:virtio|ide|scsi|sata|mp)\d+)|rootfs): (.+:)([A-Za-z0-9\-]+),(.*)$/) {
+           $disk = $3;
+           $stor = $2;
        } else {
            die "disk is not on ZFS Storage\n";
        }
@@ -734,7 +760,7 @@ sub parse_disks {
        push @$cmd, 'pvesm', 'path', "$stor$disk";
        my $path = run_cmd($cmd);
 
-       if ($path =~ m/^\/dev\/zvol\/(\w+.*)(\/$disk)$/) {
+       if ($vm_type eq 'qemu' && $path =~ m/^\/dev\/zvol\/(\w+.*)(\/$disk)$/) {
 
            my @array = split('/', $1);
            $disks->{$num}->{pool} = shift(@array);
@@ -746,6 +772,20 @@ sub parse_disks {
            $disks->{$num}->{last_part} = $disk;
            $disks->{$num}->{all} .= "\/$disk";
 
+           $num++;
+       } elsif ($vm_type eq 'lxc' && $path =~ m/^\/(\w+.+)\/(\w+.*)(\/$disk)$/) {
+
+           $disks->{$num}->{pool} = $1;
+           $disks->{$num}->{all} = $disks->{$num}->{pool};
+
+           if ($2) {
+               $disks->{$num}->{path} = $2;
+               $disks->{$num}->{all} .= "\/$disks->{$num}->{path}";
+           }
+
+           $disks->{$num}->{last_part} = $disk;
+           $disks->{$num}->{all} .= "\/$disk";
+
            $num++;
 
        } else {
@@ -825,10 +865,13 @@ sub send_image {
        my $bwl = $param->{limit}*1024;
        push @$cmd, \'|', 'cstream', '-t', $bwl;
     }
+    my $target = "$dest->{all}/$source->{last_part}";
+    $target =~ s!/+!/!g;
+
     push @$cmd, \'|';
     push @$cmd, 'ssh', "root\@$dest->{ip}", '--' if $dest->{ip};
-    push @$cmd, 'zfs', 'recv', '--';
-    push @$cmd, "$dest->{all}/$source->{last_part}\@$source->{new_snap}";
+    push @$cmd, 'zfs', 'recv', '-F', '--';
+    push @$cmd, "$target";
 
     eval {
        run_cmd($cmd)
@@ -844,29 +887,37 @@ sub send_image {
 sub send_config{
     my ($source, $dest, $method) = @_;
 
-    my $source_target ="$QEMU_CONF$source->{vmid}.conf";
-    my $dest_target_new ="$CONFIG_PATH$source->{vmid}.conf.$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;
+
+    $dest_target_new = $config_dir.$dest_target_new;
 
+    print Dumper $dest_target_new, $dest;
     if ($method eq 'ssh'){
        if ($dest->{ip} && $source->{ip}) {
-           run_cmd(['ssh', "root\@$dest->{ip}", '--', 'mkdir', '-p', '--', $CONFIG_PATH]);
+           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_PATH]);
+           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_PATH]);
+           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_PATH$source->{vmid}.conf.$source->{old_snap}";
+           my $dest_target_old ="${config_dir}$source->{vmid}.conf.$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]);
     }
 }