]> git.proxmox.com Git - pve-storage.git/commitdiff
LvmThinPlugin: improve basic functionality, better code reuse
authorDietmar Maurer <dietmar@proxmox.com>
Wed, 11 Nov 2015 08:07:55 +0000 (09:07 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Wed, 11 Nov 2015 08:14:06 +0000 (09:14 +0100)
PVE/Storage/LvmThinPlugin.pm

index fa12e864b30e5f0c4bb2a7d4011a0be5ec3c3897..9198bac54806adffb4e868e7c812bc1c3bf1521b 100644 (file)
@@ -2,12 +2,18 @@ package PVE::Storage::LvmThinPlugin;
 
 use strict;
 use warnings;
+use Data::Dumper;
 use IO::File;
 use PVE::Tools qw(run_command trim);
 use PVE::Storage::Plugin;
+use PVE::Storage::LVMPlugin;
 use PVE::JSONSchema qw(get_standard_option);
 
 # see: man lvmthin
+# lvcreate -n ThinDataLV -L LargeSize VG
+# lvconvert --type thin-pool VG/ThinDataLV
+# lvcreate -n pvepool -L 20G pve
+# lvconvert --type thin-pool pve/pvepool
 
 use base qw(PVE::Storage::LVMPlugin);
 
@@ -45,10 +51,29 @@ sub alloc_image {
 
     die "unsupported format '$fmt'" if $fmt ne 'raw';
 
-    die "illegal name '$name' - sould be 'vm-$vmid-*'\n" 
+    die "illegal name '$name' - sould be 'vm-$vmid-*'\n"
        if  $name && $name !~ m/^vm-$vmid-/;
 
-    die "implement me";
+    my $vg = $scfg->{vgname};
+
+    if (!$name) {
+       my $lvs = PVE::Storage::LVMPlugin::lvm_list_volumes($scfg->{vgname});
+
+       for (my $i = 1; $i < 100; $i++) {
+           my $tn = "vm-$vmid-disk-$i";
+           if (!defined ($lvs->{$vg}->{$tn})) {
+               $name = $tn;
+               last;
+           }
+       }
+    }
+
+    my $cmd = ['/sbin/lvcreate', '-aly', '-V', "${size}k", '--name', $name,
+              '--thinpool', "$vg/$scfg->{thinpool}" ];
+
+    run_command($cmd, errmsg => "lvcreate '$vg/$name' error");
+
+    return $name;
 }
 
 sub free_image {
@@ -64,55 +89,81 @@ sub free_image {
 sub list_images {
     my ($class, $storeid, $scfg, $vmid, $vollist, $cache) = @_;
 
-    die "implement me";
+    my $vgname = $scfg->{vgname};
+
+    $cache->{lvs} = PVE::Storage::LVMPlugin::lvm_list_volumes() if !$cache->{lvs};
+
+    my $res = [];
+
+    if (my $dat = $cache->{lvs}->{$vgname}) {
+
+       foreach my $volname (keys %$dat) {
+
+           next if $volname !~ m/^vm-(\d+)-/;
+           my $owner = $1;
+
+           my $info = $dat->{$volname};
+
+           next if $info->{lv_type} ne 'V';
+
+           next if $info->{pool_lv} ne $scfg->{thinpool};
+
+           my $volid = "$storeid:$volname";
+
+           if ($vollist) {
+               my $found = grep { $_ eq $volid } @$vollist;
+               next if !$found;
+           } else {
+               next if defined($vmid) && ($owner ne $vmid);
+           }
+
+           push @$res, {
+               volid => $volid, format => 'raw', size => $info->{lv_size}, vmid => $owner,
+           };
+       }
+    }
+
+    return $res;
 }
 
 sub status {
     my ($class, $storeid, $scfg, $cache) = @_;
 
     my $lvname = "$scfg->{vgname}/$scfg->{thinpool}";
-    
-    my $cmd = ['/sbin/lvs', '--separator', ':', '--noheadings', '--units', 'b',
-              '--unbuffered', '--nosuffix', '--options',
-              'vg_name,lv_name,lv_size,data_percent,metadata_percent,snap_percent', $lvname];
-
-    my $total = 0;
-    my $used = 0;
-    
-    run_command($cmd, outfunc => sub {
-       my $line = shift;
-
-       $line = trim($line);
-
-       my ($vg, $lv, $size, $data_percent, $meta_percent, $snap_percent) = split(':', $line);
-
-       return if !$vg || $vg ne $scfg->{vgname};
-       return if !$lv || $lv ne $scfg->{thinpool};
-       
-       $data_percent ||= 0;
-       $meta_percent ||= 0;
-       $snap_percent ||= 0;
-               
-       $total = $size;
-       $used = int((($data_percent + $meta_percent + $snap_percent) * $size)/100)
-    });
-    
-    return ($total, $total - $used, $used, 1) if $total;
+
+    $cache->{lvs} = PVE::Storage::LVMPlugin::lvm_list_volumes() if !$cache->{lvs};
+
+    my $lvs = $cache->{lvs};
+
+    return undef if !$lvs->{$scfg->{vgname}};
+
+    my $info = $lvs->{$scfg->{vgname}}->{$scfg->{thinpool}};
+
+    return undef if !$info;
+
+    return undef if $info->{lv_type} ne 't';
+
+    return ($info->{lv_size}, $info->{lv_size} - $info->{used}, $info->{used}, 1) if $info->{lv_size};
 
     return undef;
 }
 
 sub activate_volume {
     my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;
+
+    # do nothing
 }
 
 sub deactivate_volume {
     my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;
+
+    # do nothing
 }
 
 sub volume_resize {
     my ($class, $scfg, $storeid, $volname, $size, $running) = @_;
-    die "implement me";
+
+    die "volume_resize is not implemented for storage type 'lvmthin'\n";
 }
 
 sub volume_has_feature {