]>
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 $loop_mount_image = sub {
67 my ($image_path, $mountpoint) = @_;
74 $loopdev = $line if $line =~m
|^/dev/loop\d
+$|;
76 PVE
::Tools
::run_command
(['losetup', '--find', '--show', $image_path], outfunc
=> $parser);
78 File
::Path
::mkpath
($mountpoint);
79 PVE
::Tools
::run_command
(['mount', '-t', 'ext4', $loopdev, $mountpoint]);
84 eval { PVE
::Tools
::run_command
(['umount', '-d', $mountpoint]) };
87 eval { PVE
::Tools
::run_command
(['losetup', '-d', $loopdev]) if $loopdev; };
95 my ($self, $task, $vmid, $mode) = @_;
97 my $conf = $self->{vmlist
}->{$vmid} = PVE
::LXC
::load_config
($vmid);
99 my $running = PVE
::LXC
::check_running
($vmid);
102 $task->{diskinfo
} = $diskinfo;
104 $task->{hostname
} = $conf->{'lxc.utsname'} || "CT$vmid";
106 my $volid = $conf->{'pve.volid'};
108 # fixme: whe do we deactivate ??
109 PVE
::Storage
::activate_volumes
($self->{storecfg
}, [$volid]) if $volid;
111 my $rootfs = $conf->{'lxc.rootfs'};
113 if ($mode eq 'snapshot') {
115 die "mode failure - storage does not support snapshots (no volid)\n"
118 die "mode failure - storage does not support snapshots\n"
119 if !PVE
::Storage
::volume_has_feature
($self->{storecfg
}, 'snapshot', $volid);
121 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1);
123 my $scfg = PVE
::Storage
::storage_config
($self->{storecfg
}, $sid);
125 # we only handle well known types for now, because the storage
126 # library dos not handle mount/unmount of snapshots
128 if ($scfg->{type
} ne 'zfs') {
129 $diskinfo->{mountpoint
} = "/mnt/vzsnap0";
131 die "mode failure - storage does not support snapshot mount\n"
134 PVE
::Storage
::volume_snapshot
($self->{storecfg
}, $volid, '__vzdump__');
135 $task->{cleanup
}->{snap_volid
} = $volid;
137 # $diskinfo->{dir} = $rootfs;
142 if ($rootfs =~ m!^/! && -d
$rootfs) {
143 $diskinfo->{dir
} = $rootfs;
145 if ($mode eq 'stop') {
146 my $mountpoint = "/mnt/vzsnap0";
147 my $path = PVE
::Storage
::path
($self->{storecfg
}, $volid);
148 &$loop_mount_image($path, $mountpoint);
149 $task->{cleanup
}->{snapshot_mount
} = 1;
150 $diskinfo->{dir
} = $diskinfo->{mountpoint
} = $mountpoint;
151 } elsif ($mode eq 'suspend') {
152 my $tasks_fn = "/sys/fs/cgroup/cpu/lxc/$vmid/tasks";
153 my $init_pid = PVE
::Tools
::file_read_firstline
($tasks_fn);
154 if ($init_pid =~ m/^(\d+)$/) {
155 $diskinfo->{dir
} = "/proc/$1/root";
157 die "unable to find container init task\n";
160 die "unknown mode '$mode'\n"; # should not happen
165 if ($mode eq 'suspend') {
166 $task->{snapdir
} = $task->{tmpdir
};
168 $task->{snapdir
} = $diskinfo->{dir
};
175 my ($self, $vmid) = @_;
177 PVE
::LXC
::lock_aquire
($vmid);
181 my ($self, $vmid) = @_;
183 PVE
::LXC
::lock_release
($vmid);
186 sub copy_data_phase1
{
187 my ($self, $task) = @_;
189 $self->$rsync_vm($task, "$task->{diskinfo}->{dir}/", $task->{snapdir
}, "first");
192 sub copy_data_phase2
{
193 my ($self, $task) = @_;
195 $self->$rsync_vm ($task, "$task->{diskinfo}->{dir}/", $task->{snapdir
}, "final");
199 my ($self, $task, $vmid) = @_;
201 $self->cmd("lxc-stop -n $vmid");
205 my ($self, $task, $vmid) = @_;
207 $self->cmd ("lxc-start -n $vmid");
211 my ($self, $task, $vmid) = @_;
213 $self->cmd ("lxc-freeze -n $vmid");
217 my ($self, $task, $vmid) = @_;
219 $self->cmd ("lxc-unfreeze -n $vmid");
223 my ($self, $task, $vmid) = @_;
225 my $dir = $task->{snapdir
};
227 $task->{cleanup
}->{etc_vzdump
} = 1;
229 mkpath
"$dir/etc/vzdump/";
231 my $conf = PVE
::LXC
::load_config
($vmid);
232 delete $conf->{snapshots
};
233 delete $conf->{'pve.parent'};
235 PVE
::Tools
::file_set_contents
("$dir/etc/vzdump/lxc.conf", PVE
::LXC
::write_lxc_config
("/lxc/$vmid/config", $conf));
240 my ($self, $task, $vmid, $filename, $comp) = @_;
242 my $findexcl = $self->{vzdump
}->{findexcl
};
243 my $findargs = join (' ', @$findexcl) . ' -print0';
244 my $opts = $self->{vzdump
}->{opts
};
246 my $srcdir = $task->{diskinfo
}->{dir
};
247 my $snapdir = $task->{snapdir
};
249 my $taropts = "--totals --sparse --numeric-owner --no-recursion --xattrs --one-file-system";
251 # note: --remove-files does not work because we do not
252 # backup all files (filters). tar complains:
253 # Cannot rmdir: Directory not empty
254 # we we disable this optimization for now
255 #if ($snapdir eq $task->{tmpdir} && $snapdir =~ m|^$opts->{dumpdir}/|) {
256 # $taropts .= " --remove-files"; # try to save space
261 $cmd .= "cd $snapdir;find . $findargs|sed 's/\\\\/\\\\\\\\/g'|";
262 $cmd .= "tar cpf - $taropts ./etc/vzdump/lxc.conf --null -T -";
263 my $bwl = $opts->{bwlimit
}*1024; # bandwidth limit for cstream
264 $cmd .= "|cstream -t $bwl" if $opts->{bwlimit
};
265 $cmd .= "|$comp" if $comp;
269 if ($opts->{stdout
}) {
270 $self->cmd ($cmd, output
=> ">&" . fileno($opts->{stdout
}));
272 $self->cmd ("$cmd >$filename");
277 my ($self, $task, $vmid) = @_;
279 my $di = $task->{diskinfo
};
281 if ($task->{cleanup
}->{snapshot_mount
}) {
282 # Note: sleep to avoid 'device is busy' message.
283 # Seems Kernel need some time to cleanup open file list,
284 # for example when we stop the tar with kill (stop task)
285 # We use -d to automatically free used loop devices
287 $self->cmd_noerr("umount -d $di->{mountpoint}");
290 if (my $volid = $task->{cleanup
}->{snap_volid
}) {
291 eval { PVE
::Storage
::volume_snapshot_delete
($self->{storecfg
}, $volid, '__vzdump__'); };
295 if ($task->{cleanup
}->{etc_vzdump
}) {
296 my $dir = "$task->{snapdir}/etc/vzdump";
297 eval { rmtree
$dir if -d
$dir; };
298 $self->logerr ($@) if $@;