]>
git.proxmox.com Git - pve-container.git/blob - src/PVE/VZDump/LXC.pm
1 package PVE
::VZDump
::LXC
;
8 use PVE
::Cluster
qw(cfs_read_file);
14 use base qw
(PVE
::VZDump
::Plugin
);
17 my ($self, $task, $from, $to, $text) = @_;
19 $self->loginfo ("starting $text sync $from to $to");
21 my $starttime = time();
23 my $opts = $self->{vzdump
}->{opts
};
25 my $rsyncopts = "--stats -x -X --numeric-ids";
27 $rsyncopts .= " --bwlimit=$opts->{bwlimit}" if $opts->{bwlimit
};
29 $self->cmd ("rsync $rsyncopts -aH --delete --no-whole-file --inplace '$from' '$to'");
31 my $delay = time () - $starttime;
33 $self->loginfo ("$text sync finished ($delay seconds)");
37 my ($class, $vzdump) = @_;
39 PVE
::VZDump
::check_bin
('lxc-stop');
40 PVE
::VZDump
::check_bin
('lxc-start');
41 PVE
::VZDump
::check_bin
('lxc-freeze');
42 PVE
::VZDump
::check_bin
('lxc-unfreeze');
46 $self->{vzdump
} = $vzdump;
47 $self->{storecfg
} = PVE
::Storage
::config
();
49 $self->{vmlist
} = PVE
::LXC
::config_list
();
59 my ($self, $vmid) = @_;
61 my $running = PVE
::LXC
::check_running
($vmid) ?
1 : 0;
63 return wantarray ?
($running, $running ?
'running' : 'stopped') : $running;
66 my $check_mointpoint_empty = sub {
67 my ($mountpoint) = @_;
69 PVE
::Tools
::dir_glob_foreach
($mountpoint, qr/.*/, sub {
71 return if $entry eq '.' || $entry eq '..';
72 die "mointpoint '$mountpoint' not empty\n";
77 my ($self, $task, $vmid, $mode) = @_;
79 my $conf = $self->{vmlist
}->{$vmid} = PVE
::LXC
::load_config
($vmid);
81 PVE
::LXC
::foreach_mountpoint
($conf, sub {
82 my ($ms, $mountpoint) = @_;
84 return if $ms eq 'rootfs';
85 # TODO: implement support for mountpoints
86 die "unable to backup mountpoint '$ms' - feature not implemented\n";
89 my $running = PVE
::LXC
::check_running
($vmid);
92 $task->{diskinfo
} = $diskinfo;
94 $task->{hostname
} = $conf->{'hostname'} || "CT$vmid";
96 my $rootinfo = PVE
::LXC
::parse_ct_mountpoint
($conf->{rootfs
});
97 my $volid = $rootinfo->{volume
};
99 die "missing root volid (no volid)\n" if !$volid;
101 # fixme: when do we deactivate ??
102 PVE
::Storage
::activate_volumes
($self->{storecfg
}, [$volid]);
104 if ($mode eq 'snapshot') {
106 die "mode failure - storage does not support snapshots\n"
107 if !PVE
::Storage
::volume_has_feature
($self->{storecfg
}, 'snapshot', $volid);
109 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid);
111 my $scfg = PVE
::Storage
::storage_config
($self->{storecfg
}, $sid);
113 # we only handle well known types for now, because the storage
114 # library dos not handle mount/unmount of snapshots
116 if ($scfg->{type
} ne 'zfs') {
117 $diskinfo->{mountpoint
} = "/mnt/vzsnap0";
118 &$check_mointpoint_empty($diskinfo->{mountpoint
});
120 die "mode failure - storage does not support snapshot mount\n"
123 PVE
::Storage
::volume_snapshot
($self->{storecfg
}, $volid, '__vzdump__');
124 $task->{cleanup
}->{snap_volid
} = $volid;
128 } elsif ($mode eq 'stop') {
129 my $mountpoint = "/mnt/vzsnap0";
131 &$check_mointpoint_empty($mountpoint);
133 my $volid_list = [$volid];
134 $task->{cleanup
}->{dettach_loops
} = $volid_list;
135 my $loopdevs = PVE
::LXC
::attach_loops
($self->{storecfg
}, $volid_list);
136 my $mp = { volume
=> $volid, mp
=> "/" };
137 PVE
::LXC
::mountpoint_mount
($mp, $mountpoint, $self->{storecfg
}, $loopdevs);
138 $diskinfo->{dir
} = $diskinfo->{mountpoint
} = $mountpoint;
139 $task->{snapdir
} = $diskinfo->{dir
};
140 } elsif ($mode eq 'suspend') {
141 my $tasks_fn = "/sys/fs/cgroup/cpu/lxc/$vmid/tasks";
142 my $init_pid = PVE
::Tools
::file_read_firstline
($tasks_fn);
143 if ($init_pid =~ m/^(\d+)$/) {
144 $diskinfo->{dir
} = "/proc/$1/root";
146 die "unable to find container init task\n";
148 $task->{snapdir
} = $task->{tmpdir
};
150 die "unknown mode '$mode'\n"; # should not happen
155 my ($self, $vmid) = @_;
157 PVE
::LXC
::lock_aquire
($vmid);
161 my ($self, $vmid) = @_;
163 PVE
::LXC
::lock_release
($vmid);
166 sub copy_data_phase1
{
167 my ($self, $task) = @_;
169 $self->$rsync_vm($task, "$task->{diskinfo}->{dir}/", $task->{snapdir
}, "first");
172 sub copy_data_phase2
{
173 my ($self, $task) = @_;
175 $self->$rsync_vm ($task, "$task->{diskinfo}->{dir}/", $task->{snapdir
}, "final");
179 my ($self, $task, $vmid) = @_;
181 $self->cmd("lxc-stop -n $vmid");
185 my ($self, $task, $vmid) = @_;
187 $self->cmd ("lxc-start -n $vmid");
191 my ($self, $task, $vmid) = @_;
193 $self->cmd ("lxc-freeze -n $vmid");
197 my ($self, $task, $vmid) = @_;
199 $self->cmd ("lxc-unfreeze -n $vmid");
203 my ($self, $task, $vmid) = @_;
205 my $tmpdir = $task->{tmpdir
};
207 mkpath
"$tmpdir/etc/vzdump/";
209 my $conf = PVE
::LXC
::load_config
($vmid);
210 delete $conf->{snapshots
};
211 delete $conf->{'pve.parent'};
213 PVE
::Tools
::file_set_contents
("$tmpdir/etc/vzdump/pct.conf", PVE
::LXC
::write_pct_config
("/lxc/$vmid.conf", $conf));
217 my ($self, $task, $vmid, $filename, $comp) = @_;
219 my $findexcl = $self->{vzdump
}->{findexcl
};
220 push @$findexcl, "'('", '-path', "./etc/vzdump", "-prune", "')'", '-o';
222 my $findargs = join (' ', @$findexcl) . ' -print0';
223 my $opts = $self->{vzdump
}->{opts
};
225 my $srcdir = $task->{diskinfo
}->{dir
};
226 my $snapdir = $task->{snapdir
};
227 my $tmpdir = $task->{tmpdir
};
229 my $taropts = "--totals --sparse --numeric-owner --no-recursion --xattrs --one-file-system";
231 # note: --remove-files does not work because we do not
232 # backup all files (filters). tar complains:
233 # Cannot rmdir: Directory not empty
234 # we we disable this optimization for now
235 #if ($snapdir eq $task->{tmpdir} && $snapdir =~ m|^$opts->{dumpdir}/|) {
236 # $taropts .= " --remove-files"; # try to save space
241 $cmd .= "cd $snapdir;find . $findargs|sed 's/\\\\/\\\\\\\\/g'|";
242 $cmd .= "tar cpf - $taropts ";
243 # The directory parameter can give a alternative directory as source.
244 # the second parameter gives the structure in the tar.
245 $cmd .= "--directory=$tmpdir ./etc/vzdump/pct.conf ";
246 $cmd .= "--directory=$snapdir --null -T -";
248 my $bwl = $opts->{bwlimit
}*1024; # bandwidth limit for cstream
249 $cmd .= "|cstream -t $bwl" if $opts->{bwlimit
};
250 $cmd .= "|$comp" if $comp;
254 if ($opts->{stdout
}) {
255 $self->cmd ($cmd, output
=> ">&" . fileno($opts->{stdout
}));
257 $self->cmd ("$cmd >$filename");
262 my ($self, $task, $vmid) = @_;
264 my $di = $task->{diskinfo
};
266 if (my $mountpoint = $di->{mountpoint
}) {
267 PVE
::Tools
::run_command
(['umount', '-l', '-d', $mountpoint]);
270 if (my $volid_list = $task->{cleanup
}->{dettach_loops
}) {
271 PVE
::LXC
::dettach_loops
($self->{storecfg
}, $volid_list);
274 if (my $volid = $task->{cleanup
}->{snap_volid
}) {
275 eval { PVE
::Storage
::volume_snapshot_delete
($self->{storecfg
}, $volid, '__vzdump__'); };