Introduce allow_rename parameter for pvesm import and storage_migrate
and also return the ID of the allocated volume. This option allows plugins to choose a new name if there is a collision. In storage_migrate, the API version of the receiving side is checked. In Storage.pm's volume_import, when a plugin returns 'undef', it can be assumed that the import with the requested volid was successful (it should've died otherwise) and so volid is returned. This is done for backwards compatibility with foreign plugins. Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
This commit is contained in:
committed by
Fabian Grünbichler
parent
5f184292fe
commit
a97d3ee49f
@ -631,7 +631,7 @@ sub volume_import_formats {
|
||||
}
|
||||
|
||||
sub volume_import {
|
||||
my ($class, $scfg, $storeid, $fh, $volname, $format, $base_snapshot, $with_snapshots) = @_;
|
||||
my ($class, $scfg, $storeid, $fh, $volname, $format, $base_snapshot, $with_snapshots, $allow_rename) = @_;
|
||||
die "volume import format $format not available for $class\n"
|
||||
if $format ne 'raw+size';
|
||||
die "cannot import volumes together with their snapshots in $class\n"
|
||||
@ -645,17 +645,20 @@ sub volume_import {
|
||||
|
||||
my $vg = $scfg->{vgname};
|
||||
my $lvs = lvm_list_volumes($vg);
|
||||
die "volume $vg/$volname already exists\n"
|
||||
if $lvs->{$vg}->{$volname};
|
||||
if ($lvs->{$vg}->{$volname}) {
|
||||
die "volume $vg/$volname already exists\n" if !$allow_rename;
|
||||
warn "volume $vg/$volname already exists - importing with a different name\n";
|
||||
$name = undef;
|
||||
}
|
||||
|
||||
my ($size) = PVE::Storage::Plugin::read_common_header($fh);
|
||||
$size = int($size/1024);
|
||||
|
||||
eval {
|
||||
my $allocname = $class->alloc_image($storeid, $scfg, $vmid, 'raw', $name, $size);
|
||||
if ($allocname ne $volname) {
|
||||
my $oldname = $volname;
|
||||
$volname = $allocname; # Let the cleanup code know what to free
|
||||
my $oldname = $volname;
|
||||
$volname = $allocname;
|
||||
if (defined($name) && $allocname ne $oldname) {
|
||||
die "internal error: unexpected allocated name: '$allocname' != '$oldname'\n";
|
||||
}
|
||||
my $file = $class->path($scfg, $volname, $storeid)
|
||||
@ -668,6 +671,8 @@ sub volume_import {
|
||||
warn $@ if $@;
|
||||
die $err;
|
||||
}
|
||||
|
||||
return "$storeid:$volname";
|
||||
}
|
||||
|
||||
sub volume_import_write {
|
||||
|
||||
@ -1227,7 +1227,7 @@ sub volume_export_formats {
|
||||
|
||||
# Import data from a stream, creating a new or replacing or adding to an existing volume.
|
||||
sub volume_import {
|
||||
my ($class, $scfg, $storeid, $fh, $volname, $format, $base_snapshot, $with_snapshots) = @_;
|
||||
my ($class, $scfg, $storeid, $fh, $volname, $format, $base_snapshot, $with_snapshots, $allow_rename) = @_;
|
||||
|
||||
die "volume import format '$format' not available for $class\n"
|
||||
if $format !~ /^(raw|tar|qcow2|vmdk)\+size$/;
|
||||
@ -1249,16 +1249,20 @@ sub volume_import {
|
||||
# Check for an existing file first since interrupting alloc_image doesn't
|
||||
# free it.
|
||||
my $file = $class->path($scfg, $volname, $storeid);
|
||||
die "file '$file' already exists\n" if -e $file;
|
||||
if (-e $file) {
|
||||
die "file '$file' already exists\n" if !$allow_rename;
|
||||
warn "file '$file' already exists - importing with a different name\n";
|
||||
$name = undef;
|
||||
}
|
||||
|
||||
my ($size) = read_common_header($fh);
|
||||
$size = int($size/1024);
|
||||
|
||||
eval {
|
||||
my $allocname = $class->alloc_image($storeid, $scfg, $vmid, $file_format, $name, $size);
|
||||
if ($allocname ne $volname) {
|
||||
my $oldname = $volname;
|
||||
$volname = $allocname; # Let the cleanup code know what to free
|
||||
my $oldname = $volname;
|
||||
$volname = $allocname;
|
||||
if (defined($name) && $allocname ne $oldname) {
|
||||
die "internal error: unexpected allocated name: '$allocname' != '$oldname'\n";
|
||||
}
|
||||
my $file = $class->path($scfg, $volname, $storeid)
|
||||
@ -1278,6 +1282,8 @@ sub volume_import {
|
||||
warn $@ if $@;
|
||||
die $err;
|
||||
}
|
||||
|
||||
return "$storeid:$volname";
|
||||
}
|
||||
|
||||
sub volume_import_formats {
|
||||
|
||||
@ -743,7 +743,7 @@ sub volume_export_formats {
|
||||
}
|
||||
|
||||
sub volume_import {
|
||||
my ($class, $scfg, $storeid, $fh, $volname, $format, $base_snapshot, $with_snapshots) = @_;
|
||||
my ($class, $scfg, $storeid, $fh, $volname, $format, $base_snapshot, $with_snapshots, $allow_rename) = @_;
|
||||
|
||||
die "unsupported import stream format for $class: $format\n"
|
||||
if $format ne 'zfs';
|
||||
@ -752,15 +752,18 @@ sub volume_import {
|
||||
die "internal error: invalid file handle for volume_import\n"
|
||||
if !defined($fd);
|
||||
|
||||
my $dataset = ($class->parse_volname($volname))[1];
|
||||
my (undef, $dataset, $vmid) = $class->parse_volname($volname);
|
||||
my $zfspath = "$scfg->{pool}/$dataset";
|
||||
my $suffix = defined($base_snapshot) ? "\@$base_snapshot" : '';
|
||||
my $exists = 0 == run_command(['zfs', 'get', '-H', 'name', $zfspath.$suffix],
|
||||
noerr => 1, errfunc => sub {});
|
||||
if (defined($base_snapshot)) {
|
||||
die "base snapshot '$zfspath\@$base_snapshot' doesn't exist\n" if !$exists;
|
||||
} else {
|
||||
die "volume '$zfspath' already exists\n" if $exists;
|
||||
} elsif ($exists) {
|
||||
die "volume '$zfspath' already exists\n" if !$allow_rename;
|
||||
warn "volume '$zfspath' already exists - importing with a different name\n";
|
||||
$dataset = $class->find_free_diskname($storeid, $scfg, $vmid, $format);
|
||||
$zfspath = "$scfg->{pool}/$dataset";
|
||||
}
|
||||
|
||||
eval { run_command(['zfs', 'recv', '-F', '--', $zfspath], input => "<&$fd") };
|
||||
@ -773,7 +776,7 @@ sub volume_import {
|
||||
die $err;
|
||||
}
|
||||
|
||||
return;
|
||||
return "$storeid:$dataset";
|
||||
}
|
||||
|
||||
sub volume_import_formats {
|
||||
|
||||
Reference in New Issue
Block a user