]> git.proxmox.com Git - pve-container.git/blobdiff - src/PVE/VZDump/LXC.pm
Use foreach_volume instead of foreach_mountpoint-variants
[pve-container.git] / src / PVE / VZDump / LXC.pm
index 0d871a1cd921e44b12bcb8394532fbc6aacb5404..2d003d0f45cf7fb04a92682cfc6b416aa5817195 100644 (file)
@@ -2,15 +2,17 @@ package PVE::VZDump::LXC;
 
 use strict;
 use warnings;
-use File::Path;
+
 use File::Basename;
-use PVE::INotify;
+use File::Path;
+
 use PVE::Cluster qw(cfs_read_file);
-use PVE::Storage;
-use PVE::VZDump;
-use PVE::LXC;
+use PVE::INotify;
 use PVE::LXC::Config;
+use PVE::LXC;
+use PVE::Storage;
 use PVE::Tools;
+use PVE::VZDump;
 
 use base qw (PVE::VZDump::Plugin);
 
@@ -56,7 +58,7 @@ my $rsync_vm = sub {
 
 sub new {
     my ($class, $vzdump) = @_;
-    
+
     PVE::VZDump::check_bin('lxc-stop');
     PVE::VZDump::check_bin('lxc-start');
     PVE::VZDump::check_bin('lxc-freeze');
@@ -66,7 +68,7 @@ sub new {
 
     $self->{vzdump} = $vzdump;
     $self->{storecfg} = PVE::Storage::config();
-    
+
     $self->{vmlist} = PVE::LXC::config_list();
 
     return $self;
@@ -80,8 +82,8 @@ sub vm_status {
     my ($self, $vmid) = @_;
 
     my $running = PVE::LXC::check_running($vmid) ? 1 : 0;
-   
-    return wantarray ? ($running, $running ? 'running' : 'stopped') : $running; 
+
+    return wantarray ? ($running, $running ? 'running' : 'stopped') : $running;
 }
 
 my $check_mountpoint_empty = sub {
@@ -114,9 +116,11 @@ sub prepare {
 
     my ($id_map, $rootuid, $rootgid) = PVE::LXC::parse_id_maps($conf);
     $task->{userns_cmd} = PVE::LXC::userns_command($id_map);
+    $task->{rootuid} = $rootuid;
+    $task->{rootgid} = $rootgid;
 
     my $volids = $task->{volids} = [];
-    PVE::LXC::Config->foreach_mountpoint($conf, sub {
+    PVE::LXC::Config->foreach_volume($conf, sub {
        my ($name, $data) = @_;
        my $volid = $data->{volume};
        my $mount = $data->{mp};
@@ -130,6 +134,12 @@ sub prepare {
            return;
        }
 
+       $data->{name} = $name;
+
+       # immutable raw base images need RO mount
+       if ($conf->{template} && !defined($data->{ro})) {
+           $data->{ro} = 1;
+       }
        push @$disks, $data;
        push @$volids, $volid
            if $type eq 'volume';
@@ -160,7 +170,6 @@ sub prepare {
        my $rootdir = $default_mount_point;
        mkpath $rootdir;
        &$check_mountpoint_empty($rootdir);
-       PVE::Storage::activate_volumes($storage_cfg, $volids);
     } elsif ($mode eq 'suspend') {
        my $pid = PVE::LXC::find_lxc_pid($vmid);
        foreach my $disk (@$disks) {
@@ -204,7 +213,7 @@ sub snapshot {
        $self->lock_vm($vmid);
     });
     $task->{cleanup}->{remove_snapshot} = 1;
-    
+
     # reload config
     my $conf = $self->{vmlist}->{$vmid} = PVE::LXC::Config->load_config($vmid);
     die "unable to read vzdump snapshot config - internal error"
@@ -219,7 +228,7 @@ sub snapshot {
     PVE::Storage::activate_volumes($storage_cfg, $volids, 'vzdump');
     foreach my $disk (@$disks) {
        $disk->{dir} = "${rootdir}$disk->{mp}";
-       PVE::LXC::mountpoint_mount($disk, $rootdir, $storage_cfg, 'vzdump');
+       PVE::LXC::mountpoint_mount($disk, $rootdir, $storage_cfg, 'vzdump', $task->{rootuid}, $task->{rootgid});
     }
 
     $task->{snapdir} = $rootdir;
@@ -230,8 +239,10 @@ sub copy_data_phase1 {
 
     if (my $mntinfo = PVE::VZDump::get_mount_info($task->{snapdir})) {
        if ($mntinfo->{fstype} =~ /^nfs4?/) {
-           warn "temporary directory is on NFS, disabling xattr and acl support"
-           . ", consider configuring a local tmpdir via /etc/vzdump.conf\n";
+           $self->loginfo(
+                "temporary directory is on NFS, disabling xattr and acl"
+               ." support, consider configuring a local tmpdir via"
+               ." /etc/vzdump.conf\n");
            $task->{no_xattrs} = 1;
        }
     }
@@ -251,16 +262,13 @@ sub stop_vm {
     my $opts = $self->{vzdump}->{opts};
     my $timeout = $opts->{stopwait} * 60;
 
-    $self->cmd("lxc-stop -n $vmid -t $timeout");
-
-    # make sure container is stopped
-    $self->cmd("lxc-wait -n $vmid -s STOPPED");
+    PVE::LXC::vm_stop($vmid, 0, $timeout);
 }
 
 sub start_vm {
     my ($self, $task, $vmid) = @_;
 
-    $self->cmd ("lxc-start -n $vmid");
+    $self->cmd(['systemctl', 'start', "pve-container\@$vmid"]);
 }
 
 sub suspend_vm {
@@ -278,20 +286,34 @@ sub resume_vm {
 sub assemble {
     my ($self, $task, $vmid) = @_;
 
-    my $tmpdir = $task->{tmpdir};
-
-    mkpath "$tmpdir/etc/vzdump/";
+    my $opts = $self->{vzdump}->{opts};
 
     my $conf = PVE::LXC::Config->load_config($vmid);
     delete $conf->{lock};
     delete $conf->{snapshots};
     delete $conf->{parent};
+    delete $conf->{pending};
+
+    my $tmpdir = $task->{tmpdir};
+
+    mkpath "$tmpdir/etc/vzdump/";
 
     PVE::Tools::file_set_contents("$tmpdir/etc/vzdump/pct.conf", PVE::LXC::Config::write_pct_config("/lxc/$vmid.conf", $conf));
 
     my $firewall ="/etc/pve/firewall/$vmid.fw";
-    if (-e  $firewall) {
-       PVE::Tools::file_copy($firewall, "$tmpdir/etc/vzdump/pct.fw");
+    my $fwconftmp = "$tmpdir/etc/vzdump/pct.fw";
+
+    if ($opts->{scfg}->{type} eq 'pbs') {
+       # fixme: do not store pct.conf and fw.conf into $tmpdir
+       if (-e  $firewall) {
+           PVE::Tools::file_copy($firewall, $fwconftmp);
+       }
+    } else {
+       if (-e  $firewall) {
+           PVE::Tools::file_copy($firewall, $fwconftmp);
+       } else {
+           PVE::Tools::file_set_contents($fwconftmp, '');
+       }
        $task->{fw} = 1;
     }
 }
@@ -303,11 +325,14 @@ sub archive {
     my @sources;
 
     if ($task->{mode} eq 'stop') {
-       my $rootdir = $default_mount_point;
        my $storage_cfg = $self->{storecfg};
+
+       PVE::Storage::activate_volumes($storage_cfg, $task->{volids});
+
+       my $rootdir = $default_mount_point;
        foreach my $disk (@$disks) {
            $disk->{dir} = "${rootdir}$disk->{mp}";
-           PVE::LXC::mountpoint_mount($disk, $rootdir, $storage_cfg);
+           PVE::LXC::mountpoint_mount($disk, $rootdir, $storage_cfg, undef, $task->{rootuid}, $task->{rootgid});
            # add every enabled mountpoint (since we use --one-file-system)
            # mp already starts with a / so we only need to add the dot
            push @sources, ".$disk->{mp}";
@@ -330,40 +355,73 @@ sub archive {
     my $tmpdir = $task->{tmpdir};
 
     my $userns_cmd = $task->{userns_cmd};
-    my $tar = [@$userns_cmd, 'tar', 'cpf', '-', '--totals',
-               @$PVE::LXC::COMMON_TAR_FLAGS,
-               '--one-file-system', '--warning=no-file-ignored'];
-
-    # note: --remove-files does not work because we do not 
-    # backup all files (filters). tar complains:
-    # Cannot rmdir: Directory not empty
-    # we disable this optimization for now
-    #if ($snapdir eq $task->{tmpdir} && $snapdir =~ m|^$opts->{dumpdir}/|) {
-    #       push @$tar, "--remove-files"; # try to save space
-    #}
-
-    # The directory parameter can give an alternative directory as source.
-    # the second parameter gives the structure in the tar.
-    push @$tar, "--directory=$tmpdir", './etc/vzdump/pct.conf';
-    push @$tar, "./etc/vzdump/pct.fw" if $task->{fw};
-    push @$tar, "--directory=$snapdir";
-    push @$tar, '--no-anchored', '--exclude=lost+found' if $userns_cmd;
-    push @$tar, '--anchored';
-    push @$tar, map { "--exclude=.$_" } @{$self->{vzdump}->{findexcl}};
-
-    push @$tar, @sources;
-
-    my $cmd = [ $tar ];
-
-    my $bwl = $opts->{bwlimit}*1024; # bandwidth limit for cstream
-    push @$cmd, [ 'cstream', '-t', $bwl ] if $opts->{bwlimit};
-    push @$cmd, [ split(/\s+/, $comp) ] if $comp;
-
-    if ($opts->{stdout}) {
-       $self->cmd($cmd, output => ">&" . fileno($opts->{stdout}));
+
+    if ($opts->{scfg}->{type} eq 'pbs') {
+
+       my $rootdir = $default_mount_point;
+       my $param = [];
+
+       push @$param, "pct.conf:$tmpdir/etc/vzdump/pct.conf";
+
+       my $fw_conf = "$tmpdir/etc/vzdump/pct.fw";
+       if (-f $fw_conf) {
+           push @$param, "fw.conf:$fw_conf";
+       }
+
+       push @$param, "root.pxar:$rootdir";
+
+       foreach my $disk (@$disks) {
+           push @$param, '--include-dev', $disk->{dir};
+       }
+
+       push @$param, '--skip-lost-and-found' if $userns_cmd;
+
+       push @$param, '--backup-type', 'ct';
+       push @$param, '--backup-id', $vmid;
+       push @$param, '--backup-time', $task->{backup_time};
+
+       my $logfunc = sub { my $line = shift; $self->loginfo($line); };
+       PVE::Storage::PBSPlugin::run_raw_client_cmd(
+           $opts->{scfg}, $opts->{storage}, 'backup', $param,
+           logfunc => $logfunc, userns_cmd => $userns_cmd);
+
     } else {
-       push @{$cmd->[-1]}, \(">" . PVE::Tools::shellquote($filename));
-       $self->cmd($cmd);
+
+       my $tar = [@$userns_cmd, 'tar', 'cpf', '-', '--totals',
+                  @PVE::Storage::Plugin::COMMON_TAR_FLAGS,
+                  '--one-file-system', '--warning=no-file-ignored'];
+
+       # note: --remove-files does not work because we do not
+       # backup all files (filters). tar complains:
+       # Cannot rmdir: Directory not empty
+       # we disable this optimization for now
+       #if ($snapdir eq $task->{tmpdir} && $snapdir =~ m|^$opts->{dumpdir}/|) {
+       #       push @$tar, "--remove-files"; # try to save space
+       #}
+
+       # The directory parameter can give an alternative directory as source.
+       # the second parameter gives the structure in the tar.
+       push @$tar, "--directory=$tmpdir", './etc/vzdump/pct.conf';
+       push @$tar, "./etc/vzdump/pct.fw" if $task->{fw};
+       push @$tar, "--directory=$snapdir";
+       push @$tar, '--no-anchored', '--exclude=lost+found' if $userns_cmd;
+       push @$tar, '--anchored';
+       push @$tar, map { "--exclude=.$_" } @{$self->{vzdump}->{findexcl}};
+
+       push @$tar, @sources;
+
+       my $cmd = [ $tar ];
+
+       my $bwl = $opts->{bwlimit}*1024; # bandwidth limit for cstream
+       push @$cmd, [ 'cstream', '-t', $bwl ] if $opts->{bwlimit};
+       push @$cmd, [ split(/\s+/, $comp) ] if $comp;
+
+       if ($opts->{stdout}) {
+           $self->cmd($cmd, output => ">&" . fileno($opts->{stdout}));
+       } else {
+           push @{$cmd->[-1]}, \(">" . PVE::Tools::shellquote($filename));
+           $self->cmd($cmd);
+        }
     }
 }