]> git.proxmox.com Git - pve-storage.git/blobdiff - PVE/Storage/Plugin.pm
fix 2317: list images on 'rootdir' only storages
[pve-storage.git] / PVE / Storage / Plugin.pm
index aefc7f80cae6102d0aaff7765e743b0b36b26ede..27f832fc161a8da761fe2741fdf0d5280b6c6084 100644 (file)
@@ -5,6 +5,7 @@ use warnings;
 
 use File::chdir;
 use File::Path;
+use File::Basename;
 
 use PVE::Tools qw(run_command);
 use PVE::JSONSchema qw(get_standard_option);
@@ -25,7 +26,6 @@ our @SHARED_STORAGE = (
     'cifs',
     'rbd',
     'cephfs',
-    'sheepdog',
     'iscsidirect',
     'glusterfs',
     'zfs',
@@ -326,7 +326,7 @@ sub parse_config {
            priority => 0, # force first entry
            path => '/var/lib/vz',
            maxfiles => 0,
-           content => { images => 1, rootdir => 1, vztmpl => 1, iso => 1},
+           content => { images => 1, rootdir => 1, vztmpl => 1, iso => 1, snippets => 1},
        };
     }
 
@@ -427,6 +427,8 @@ sub parse_volname {
            return ('backup', $fn, $2);
        }
        return ('backup', $fn);
+    } elsif ($volname =~ m!^snippets/([^/]+)$!) {
+       return ('snippets', $1);
     }
 
     die "unable to parse directory volume name '$volname'\n";
@@ -438,6 +440,7 @@ my $vtype_subdirs = {
     iso => 'template/iso',
     vztmpl => 'template/cache',
     backup => 'dump',
+    snippets => 'snippets',
 };
 
 sub get_subdir {
@@ -528,13 +531,15 @@ sub create_base {
 my $get_vm_disk_number = sub {
     my ($disk_name, $scfg, $vmid, $suffix) = @_;
 
+    my $disk_regex = qr/(vm|base)-$vmid-disk-(\d+)$suffix/;
+
     my $type = $scfg->{type};
     my $def = { %{$defaultData->{plugindata}->{$type}} };
-    my $valid_formats = $def->{format}[0];
 
-    my $disk_regex = qr/(vm|base)-$vmid-disk-(\d+)$suffix/;
-    $disk_regex = qr/(vm|base|subvol|basevol)-$vmid-disk-(\d+)/
-       if $valid_formats->{subvol};
+    my $valid = $def->{format}[0];
+    if ($valid->{subvol}) {
+       $disk_regex = qr/(vm|base|subvol|basevol)-$vmid-disk-(\d+)/;
+    }
 
     if ($disk_name =~ m/$disk_regex/) {
        return $2;
@@ -659,7 +664,12 @@ sub alloc_image {
        
        push @$cmd, '-f', $fmt, $path, "${size}K";
 
-       run_command($cmd, errmsg => "unable to create image");
+       eval { run_command($cmd, errmsg => "unable to create image"); };
+       if ($@) {
+           unlink $path;
+           rmdir $imagedir;
+           die "$@";
+       }
     }
     
     return "$vmid/$name";
@@ -679,14 +689,18 @@ sub free_image {
     if (defined($format) && ($format eq 'subvol')) {
        File::Path::remove_tree($path);
     } else {
-    
-       if (! -f $path) {
+       if (!(-f $path || -l $path)) {
            warn "disk image '$path' does not exists\n";
            return undef;
        }
 
        unlink($path) || die "unlink '$path' failed - $!\n";
     }
+
+    # try to cleanup directory to not clutter storage with empty $vmid dirs if
+    # all images from a guest got deleted
+    my $dir = dirname($path);
+    rmdir($dir);
     
     return undef;
 }
@@ -888,6 +902,85 @@ sub list_images {
     return $res;
 }
 
+# list templates ($tt = <iso|vztmpl|backup|snippets>)
+my $get_subdir_files = sub {
+    my ($sid, $path, $tt, $vmid) = @_;
+
+    my $res = [];
+
+    foreach my $fn (<$path/*>) {
+
+       next if -d $fn;
+
+       my $info;
+
+       if ($tt eq 'iso') {
+           next if $fn !~ m!/([^/]+\.iso)$!i;
+
+           $info = { volid => "$sid:iso/$1", format => 'iso' };
+
+       } elsif ($tt eq 'vztmpl') {
+           next if $fn !~ m!/([^/]+\.tar\.([gx]z))$!;
+
+           $info = { volid => "$sid:vztmpl/$1", format => "t$2" };
+
+       } elsif ($tt eq 'backup') {
+           next if $fn !~ m!/([^/]+\.(tar|tar\.gz|tar\.lzo|tgz|vma|vma\.gz|vma\.lzo))$!;
+           next if defined($vmid) && $fn !~  m/\S+-$vmid-\S+/;
+
+           $info = { volid => "$sid:backup/$1", format => $2 };
+
+       } elsif ($tt eq 'snippets') {
+
+           $info = {
+               volid => "$sid:snippets/". basename($fn),
+               format => 'snippet',
+           };
+       }
+
+       $info->{size} = -s $fn // 0;
+
+       push @$res, $info;
+    }
+
+    return $res;
+};
+
+sub list_volumes {
+    my ($class, $storeid, $scfg, $vmid, $content_types) = @_;
+
+    my $res = [];
+
+    foreach my $ct (@$content_types) {
+       my $data;
+
+       if ($ct eq 'images' || $ct eq 'rootdir') {
+           $data = $class->list_images($storeid, $scfg, $vmid);
+       } elsif ($scfg->{path}) {
+           my $path = $class->get_subdir($scfg, $ct);
+
+           if ($ct eq 'iso' && !defined($vmid)) {
+               $data = $get_subdir_files->($storeid, $path, 'iso');
+           } elsif ($ct eq 'vztmpl'&& !defined($vmid)) {
+               $data = $get_subdir_files->($storeid, $path, 'vztmpl');
+           } elsif ($ct eq 'backup') {
+               $data = $get_subdir_files->($storeid, $path, 'backup', $vmid);
+           } elsif ($ct eq 'snippets') {
+               $data = $get_subdir_files->($storeid, $path, 'snippets');
+           }
+       }
+
+       next if !$data;
+
+       foreach my $item (@$data) {
+           $item->{content} = $ct;
+           push @$res, $item;
+       }
+    }
+
+    return $res;
+}
+
 sub status {
     my ($class, $storeid, $scfg, $cache) = @_;
 
@@ -947,6 +1040,19 @@ sub deactivate_storage {
     # do nothing by default
 }
 
+sub map_volume {
+    my ($class, $storeid, $scfg, $volname, $snapname) = @_;
+
+    my ($path) = $class->path($scfg, $volname, $storeid, $snapname);
+    return $path;
+}
+
+sub unmap_volume {
+    my ($class, $storeid, $scfg, $volname, $snapname) = @_;
+
+    return 1;
+}
+
 sub activate_volume {
     my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;