]> git.proxmox.com Git - pve-storage.git/blobdiff - PVE/Storage/ZFSPoolPlugin.pm
zfs pool: bump non-worker timeoiut default to 10s
[pve-storage.git] / PVE / Storage / ZFSPoolPlugin.pm
index b73d895d1a19205d0b68bc9613f1915c437fdf26..e264fde91c028b587a3a05e004352b9bdbe7b68c 100644 (file)
@@ -178,7 +178,12 @@ sub zfs_request {
     my $msg = '';
     my $output = sub { $msg .= "$_[0]\n" };
 
-    $timeout = PVE::RPCEnvironment->is_worker() ? 60*60 : 5 if !$timeout;
+    if (PVE::RPCEnvironment->is_worker()) {
+       $timeout = 60*60 if !$timeout;
+       $timeout = 60*5 if $timeout < 60*5;
+    } else {
+       $timeout = 10 if !$timeout;
+    }
 
     run_command($cmd, errmsg => "zfs error", outfunc => $output, timeout => $timeout);
 
@@ -398,9 +403,11 @@ sub zfs_list_zvol {
 sub zfs_get_sorted_snapshot_list {
     my ($class, $scfg, $volname, $sort_params) = @_;
 
+    my @params = ('-H', '-r', '-t', 'snapshot', '-o', 'name', $sort_params->@*);
+
     my $vname = ($class->parse_volname($volname))[1];
+    push @params, "$scfg->{pool}\/$vname";
 
-    my @params = ('-H', '-t', 'snapshot', '-o', 'name', $sort_params->@*, "$scfg->{pool}\/$vname");
     my $text = $class->zfs_request($scfg, undef, 'list', @params);
     my @snapshots = split(/\n/, $text);
 
@@ -510,13 +517,28 @@ sub volume_rollback_is_possible {
     return 1;
 }
 
-sub volume_snapshot_list {
+sub volume_snapshot_info {
     my ($class, $scfg, $storeid, $volname) = @_;
 
-    my $snaps = [];
-    # return an empty array if dataset does not exist.
-    eval { $snaps = $class->zfs_get_sorted_snapshot_list($scfg, $volname, ['-S', 'name']); };
-    return $snaps;
+    my @params = ('-Hp', '-r', '-t', 'snapshot', '-o', 'name,guid,creation');
+
+    my $vname = ($class->parse_volname($volname))[1];
+    push @params, "$scfg->{pool}\/$vname";
+
+    my $text = $class->zfs_request($scfg, undef, 'list', @params);
+    my @lines = split(/\n/, $text);
+
+    my $info = {};
+    for my $line (@lines) {
+       my ($snapshot, $guid, $creation) = split(/\s+/, $line);
+       (my $snap_name = $snapshot) =~ s/^.*@//;
+
+       $info->{$snap_name} = {
+           id => $guid,
+           timestamp => $creation,
+       };
+    }
+    return $info;
 }
 
 my sub dataset_mounted_heuristic {
@@ -683,6 +705,7 @@ sub volume_has_feature {
        copy => { base => 1, current => 1},
        sparseinit => { base => 1, current => 1},
        replicate => { base => 1, current => 1},
+       rename => {current => 1},
     };
 
     my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
@@ -752,7 +775,9 @@ sub volume_import {
     die "internal error: invalid file handle for volume_import\n"
        if !defined($fd);
 
-    my (undef, $dataset, $vmid) = $class->parse_volname($volname);
+    my (undef, $dataset, $vmid, undef, undef, undef, $volume_format) =
+       $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],
@@ -762,7 +787,7 @@ sub volume_import {
     } 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);
+       $dataset = $class->find_free_diskname($storeid, $scfg, $vmid, $volume_format);
        $zfspath = "$scfg->{pool}/$dataset";
     }
 
@@ -785,4 +810,34 @@ sub volume_import_formats {
     return $class->volume_export_formats($scfg, $storeid, $volname, $snapshot, $base_snapshot, $with_snapshots);
 }
 
+sub rename_volume {
+    my ($class, $scfg, $storeid, $source_volname, $target_vmid, $target_volname) = @_;
+
+    my (
+       undef,
+       $source_image,
+       $source_vmid,
+       $base_name,
+       $base_vmid,
+       undef,
+       $format
+    ) = $class->parse_volname($source_volname);
+    $target_volname = $class->find_free_diskname($storeid, $scfg, $target_vmid, $format)
+       if !$target_volname;
+
+    my $pool = $scfg->{pool};
+    my $source_zfspath = "${pool}/${source_image}";
+    my $target_zfspath = "${pool}/${target_volname}";
+
+    my $exists = 0 == run_command(['zfs', 'get', '-H', 'name', $target_zfspath],
+                                 noerr => 1, quiet => 1);
+    die "target volume '${target_volname}' already exists\n" if $exists;
+
+    $class->zfs_request($scfg, 5, 'rename', ${source_zfspath}, ${target_zfspath});
+
+    $base_name = $base_name ? "${base_name}/" : '';
+
+    return "${storeid}:${base_name}${target_volname}";
+}
+
 1;