]> git.proxmox.com Git - pve-storage.git/blobdiff - PVE/Storage/LvmThinPlugin.pm
lvm thin: don't assume that a thin pool and its volumes are active
[pve-storage.git] / PVE / Storage / LvmThinPlugin.pm
index 88060c7ecee8c45985155dbb9b08f171be4cf25c..f699acb8096dda762f912758bcd1cf687e50108d 100644 (file)
@@ -86,7 +86,7 @@ sub alloc_image {
 
     die "unsupported format '$fmt'" if $fmt ne 'raw';
 
-    die "illegal name '$name' - sould be 'vm-$vmid-*'\n"
+    die "illegal name '$name' - should be 'vm-$vmid-*'\n"
        if  $name && $name !~ m/^vm-$vmid-/;
 
     my $vgs = PVE::Storage::LVMPlugin::lvm_vgs();
@@ -117,7 +117,7 @@ sub free_image {
 
        # remove all volume snapshots first
        foreach my $lv (keys %$dat) {
-           next if $lv !~ m/^snap_${volname}_(\w+)$/;
+           next if $lv !~ m/^snap_${volname}_${PVE::JSONSchema::CONFIGID_RE}$/;
            my $cmd = ['/sbin/lvremove', '-f', "$vg/$lv"];
            run_command($cmd, errmsg => "lvremove snapshot '$vg/$lv' error");
        }
@@ -165,6 +165,7 @@ sub list_images {
 
            push @$res, {
                volid => $volid, format => 'raw', size => $info->{lv_size}, vmid => $owner,
+               ctime => $info->{ctime},
            };
        }
     }
@@ -183,6 +184,7 @@ sub list_thinpools {
            next if $lvs->{$vg}->{$lvname}->{lv_type} ne 't';
            my $lv = $lvs->{$vg}->{$lvname};
            $lv->{lv} = $lvname;
+           $lv->{vg} = $vg;
            push @$thinpools, $lv;
        }
     }
@@ -193,59 +195,69 @@ sub list_thinpools {
 sub status {
     my ($class, $storeid, $scfg, $cache) = @_;
 
-    my $lvname = "$scfg->{vgname}/$scfg->{thinpool}";
+    my $lvs = $cache->{lvs} ||= PVE::Storage::LVMPlugin::lvm_list_volumes();
 
-    $cache->{lvs} = PVE::Storage::LVMPlugin::lvm_list_volumes() if !$cache->{lvs};
+    return if !$lvs->{$scfg->{vgname}};
 
-    my $lvs = $cache->{lvs};
+    my $info = $lvs->{$scfg->{vgname}}->{$scfg->{thinpool}};
 
-    return undef if !$lvs->{$scfg->{vgname}};
+    return if !$info || $info->{lv_type} ne 't' || !$info->{lv_size};
 
-    my $info = $lvs->{$scfg->{vgname}}->{$scfg->{thinpool}};
+    return (
+       $info->{lv_size},
+       $info->{lv_size} - $info->{used},
+       $info->{used},
+       $info->{lv_state} eq 'a' ? 1 : 0,
+    );
+}
 
-    return undef if !$info;
+my $activate_lv = sub {
+    my ($vg, $lv, $cache) = @_;
 
-    return undef if $info->{lv_type} ne 't';
+    my $lvs = $cache->{lvs} ||= PVE::Storage::LVMPlugin::lvm_list_volumes();
 
-    return ($info->{lv_size}, $info->{lv_size} - $info->{used}, $info->{used}, 1) if $info->{lv_size};
+    die "no such logical volume $vg/$lv" if !$lvs->{$vg} || !$lvs->{$vg}->{$lv};
 
-    return undef;
+    return if $lvs->{$vg}->{$lv}->{lv_state} eq 'a';
+
+    run_command(['lvchange', '-ay', '-K', "$vg/$lv"], errmsg => "activating LV '$vg/$lv' failed");
+
+    $lvs->{$vg}->{$lv}->{lv_state} = 'a'; # update cache
+
+    return;
+};
+
+sub activate_storage {
+    my ($class, $storeid, $scfg, $cache) = @_;
+
+    $class->SUPER::activate_storage($storeid, $scfg, $cache);
+
+    $activate_lv->($scfg->{vgname}, $scfg->{thinpool}, $cache);
 }
 
 sub activate_volume {
     my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;
 
     my $vg = $scfg->{vgname};
+    my $lv = $snapname ? "snap_${volname}_$snapname" : $volname;
 
-    # only snapshot volumes needs activation
-    if ($snapname) {
-       my $snapvol = "snap_${volname}_$snapname";
-       my $cmd = ['/sbin/lvchange', '-ay', '-K', "$vg/$snapvol"];
-       run_command($cmd, errmsg => "activate_volume '$vg/$snapvol' error");
-    } elsif ($volname =~ /^base-/) {
-       my $cmd = ['/sbin/lvchange', '-ay', '-K', "$vg/$volname"];
-       run_command($cmd, errmsg => "activate_volume '$vg/$volname' error");
-    } else {
-       # other volumes are active by default
-    }
+    $activate_lv->($vg, $lv, $cache);
 }
 
 sub deactivate_volume {
     my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;
 
+    return if !$snapname && $volname !~ /^base-/; # other volumes are kept active
+
     my $vg = $scfg->{vgname};
+    my $lv = $snapname ? "snap_${volname}_$snapname" : $volname;
 
-    # we only deactivate snapshot volumes
-    if ($snapname) {
-       my $snapvol = "snap_${volname}_$snapname";
-       my $cmd = ['/sbin/lvchange', '-an', "$vg/$snapvol"];
-       run_command($cmd, errmsg => "deactivate_volume '$vg/$snapvol' error");
-    } elsif ($volname =~ /^base-/) {
-       my $cmd = ['/sbin/lvchange', '-an', "$vg/$volname"];
-       run_command($cmd, errmsg => "deactivate_volume '$vg/$volname' error");
-    } else {
-       # other volumes are kept active
-    }
+    run_command(['lvchange', '-an', "$vg/$lv"], errmsg => "deactivate_volume '$vg/$lv' error");
+
+    $cache->{lvs}->{$vg}->{$lv}->{lv_state} = '-' # update cache
+       if $cache->{lvs} && $cache->{lvs}->{$vg} && $cache->{lvs}->{$vg}->{$lv};
+
+    return;
 }
 
 sub clone_image {
@@ -354,6 +366,7 @@ sub volume_has_feature {
        template => { current => 1},
        copy => { base => 1, current => 1, snap => 1},
        sparseinit => { base => 1, current => 1},
+       rename => {current => 1},
     };
 
     my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =