]> git.proxmox.com Git - pve-storage.git/blobdiff - PVE/Storage.pm
return the volid, not the storage path
[pve-storage.git] / PVE / Storage.pm
index 92dcc546ef0a4678f3c6b60015aec0d2d08d7e7a..710c7ae25a35879e42f5da7244cb2bcbd0935727 100755 (executable)
@@ -93,12 +93,6 @@ sub storage_check_enabled {
        return undef;
     }
 
-    my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
-    if (!$plugin->check_connection($storeid, $scfg)) {
-       die "storage '$storeid' is not available\n" if !$noerr;
-       return undef;
-    }
-
     return storage_check_node($cfg, $storeid, $node, $noerr);
 }
 
@@ -114,6 +108,96 @@ sub file_size_info {
     return PVE::Storage::Plugin::file_size_info($filename, $timeout);
 }
 
+sub volume_size_info {
+    my ($cfg, $volid, $timeout) = @_;
+
+    my ($storeid, $volname) = parse_volume_id($volid, 1);
+    if ($storeid) {
+       my $scfg = storage_config($cfg, $storeid);
+       my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+       return $plugin->volume_size_info($scfg, $storeid, $volname, $timeout);
+    } elsif ($volid =~ m|^(/.+)$| && -e $volid) {
+       return file_size_info($volid, $timeout);
+    } else {
+       return 0;
+    }
+}
+
+sub volume_resize {
+    my ($cfg, $volid, $size, $running) = @_;
+
+    my ($storeid, $volname) = parse_volume_id($volid, 1);
+    if ($storeid) {
+        my $scfg = storage_config($cfg, $storeid);
+        my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+        return $plugin->volume_resize($scfg, $storeid, $volname, $size, $running);
+    } elsif ($volid =~ m|^(/.+)$| && -e $volid) {
+        die "resize device is not possible";
+    } else {
+        die "can't resize";
+    }
+}
+
+sub volume_snapshot {
+    my ($cfg, $volid, $snap, $running) = @_;
+
+    my ($storeid, $volname) = parse_volume_id($volid, 1);
+    if ($storeid) {
+        my $scfg = storage_config($cfg, $storeid);
+        my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+        return $plugin->volume_snapshot($scfg, $storeid, $volname, $snap, $running);
+    } elsif ($volid =~ m|^(/.+)$| && -e $volid) {
+        die "snapshot device is not possible";
+    } else {
+        die "can't snapshot";
+    }
+}
+
+sub volume_snapshot_rollback {
+    my ($cfg, $volid, $snap) = @_;
+
+    my ($storeid, $volname) = parse_volume_id($volid, 1);
+    if ($storeid) {
+        my $scfg = storage_config($cfg, $storeid);
+        my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+        return $plugin->volume_snapshot_rollback($scfg, $storeid, $volname, $snap);
+    } elsif ($volid =~ m|^(/.+)$| && -e $volid) {
+        die "snapshot rollback device is not possible";
+    } else {
+        die "can't snapshot";
+    }
+}
+
+sub volume_snapshot_delete {
+    my ($cfg, $volid, $snap, $running) = @_;
+
+    my ($storeid, $volname) = parse_volume_id($volid, 1);
+    if ($storeid) {
+        my $scfg = storage_config($cfg, $storeid);
+        my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+        return $plugin->volume_snapshot_delete($scfg, $storeid, $volname, $snap, $running);
+    } elsif ($volid =~ m|^(/.+)$| && -e $volid) {
+        die "snapshot delete device is not possible";
+    } else {
+        die "can't delete snapshot";
+    }
+}
+
+sub volume_has_feature {
+    my ($cfg, $feature, $volid, $snap, $running) = @_;
+
+    my ($storeid, $volname) = parse_volume_id($volid, 1);
+    if ($storeid) {
+        my $scfg = storage_config($cfg, $storeid);
+        my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+        return $plugin->volume_has_feature($scfg, $feature, $storeid, $volname, $snap, $running);
+    } elsif ($volid =~ m|^(/.+)$| && -e $volid) {
+       return undef;
+    } else {
+       return undef;
+    }
+}
+
 sub get_image_dir {
     my ($cfg, $storeid, $vmid) = @_;
 
@@ -184,6 +268,27 @@ sub parse_volume_id {
     die "unable to parse volume ID '$volid'\n";
 }
 
+sub volume_is_base {
+    my ($cfg, $volid) = @_;
+
+    my ($sid, $volname) = parse_volume_id($volid, 1);
+    return 0 if !$sid;
+
+    if (my $scfg = $cfg->{ids}->{$sid}) {
+       my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+       my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) = 
+           $plugin->parse_volname($volname);
+       return $isBase ? 1 : 0;
+    } else {
+       # stale volid with undefined storage - so we can just guess
+       if ($volid =~ m/base-/) {
+           return 1;
+       }
+    }
+
+    return 0;
+}
+
 # try to map a filesystem path to a volume identifier
 sub path_to_volume_id {
     my ($cfg, $path) = @_;
@@ -193,7 +298,7 @@ sub path_to_volume_id {
     my ($sid, $volname) = parse_volume_id($path, 1);
     if ($sid) {
        if (my $scfg = $ids->{$sid}) {
-           if (my $path = $scfg->{path}) {
+           if ($scfg->{path}) {
                my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
                my ($vtype, $name, $vmid) = $plugin->parse_volname($volname);
                return ($vtype, $path);
@@ -219,7 +324,15 @@ sub path_to_volume_id {
        if ($path =~ m!^$imagedir/(\d+)/([^/\s]+)$!) {
            my $vmid = $1;
            my $name = $2;
-           return ('images', "$sid:$vmid/$name");
+
+           my $vollist = $plugin->list_images($sid, $scfg, $vmid);
+           foreach my $info (@$vollist) {
+               my ($storeid, $volname) = parse_volume_id($info->{volid});
+               my $volpath = $plugin->path($scfg, $volname, $storeid);
+               if ($volpath eq $path) {
+                   return ('images', $info->{volid});
+               }
+           }
        } elsif ($path =~ m!^$isodir/([^/]+\.[Ii][Ss][Oo])$!) {
            my $name = $1;
            return ('iso', "$sid:iso/$name");   
@@ -229,7 +342,7 @@ sub path_to_volume_id {
        } elsif ($path =~ m!^$privatedir/(\d+)$!) {
            my $vmid = $1;
            return ('rootdir', "$sid:rootdir/$vmid");
-       } elsif ($path =~ m!^$backupdir/([^/]+\.(tar|tar\.gz|tar\.lzo|tgz))$!) {
+       } elsif ($path =~ m!^$backupdir/([^/]+\.(tar|tar\.gz|tar\.lzo|tgz|vma|vma\.gz|vma\.lzo))$!) {
            my $name = $1;
            return ('iso', "$sid:backup/$name");        
        }
@@ -268,8 +381,7 @@ sub storage_migrate {
 
     my $errstr = "unable to migrate '$volid' to '${target_volid}' on host '$target_host'";
 
-    # blowfish is a fast block cipher, much faster then 3des
-    my $sshoptions = "-c blowfish -o 'BatchMode=yes'";
+    my $sshoptions = "-o 'BatchMode=yes'";
     my $ssh = "/usr/bin/ssh $sshoptions";
 
     local $ENV{RSYNC_RSH} = $ssh;
@@ -334,6 +446,42 @@ sub storage_migrate {
     }
 }
 
+sub vdisk_clone {
+    my ($cfg, $volid, $vmid) = @_;
+    
+    my ($storeid, $volname) = parse_volume_id($volid);
+
+    my $scfg = storage_config($cfg, $storeid);
+
+    my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+    
+    activate_storage($cfg, $storeid);
+
+    # lock shared storage
+    return $plugin->cluster_lock_storage($storeid, $scfg->{shared}, undef, sub {
+       my $volname = $plugin->clone_image($scfg, $storeid, $volname, $vmid);
+       return "$storeid:$volname";
+    });
+}
+
+sub vdisk_create_base {
+    my ($cfg, $volid) = @_;
+
+    my ($storeid, $volname) = parse_volume_id($volid);
+
+    my $scfg = storage_config($cfg, $storeid);
+
+    my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+    
+    activate_storage($cfg, $storeid);
+
+    # lock shared storage
+    return $plugin->cluster_lock_storage($storeid, $scfg->{shared}, undef, sub {
+       my $volname = $plugin->create_base($storeid, $scfg, $volname);
+       return "$storeid:$volname";
+    });
+}
+
 sub vdisk_alloc {
     my ($cfg, $storeid, $vmid, $fmt, $name, $size) = @_;
 
@@ -437,7 +585,7 @@ sub template_list {
                    $info = { volid => "$sid:vztmpl/$1", format => 'tgz' };
 
                } elsif ($tt eq 'backup') {
-                   next if $fn !~ m!/([^/]+\.(tar|tar\.gz|tar\.lzo|tgz))$!;
+                   next if $fn !~ m!/([^/]+\.(tar|tar\.gz|tar\.lzo|tgz|vma|vma\.gz|vma\.lzo))$!;
                    
                    $info = { volid => "$sid:backup/$1", format => $2 };
                }
@@ -455,6 +603,7 @@ sub template_list {
     return $res;
 }
 
+
 sub vdisk_list {
     my ($cfg, $storeid, $vmid, $vollist) = @_;
 
@@ -514,9 +663,11 @@ sub uevent_seqnum {
     return $seqnum;
 }
 
-sub __activate_storage_full {
+sub activate_storage {
     my ($cfg, $storeid, $cache) = @_;
 
+    $cache = {} if !$cache;
+
     my $scfg = storage_check_enabled($cfg, $storeid);
 
     return if $cache->{activated}->{$storeid};
@@ -527,7 +678,11 @@ sub __activate_storage_full {
 
     if ($scfg->{base}) {
        my ($baseid, undef) = parse_volume_id ($scfg->{base});
-       __activate_storage_full ($cfg, $baseid, $cache);
+       activate_storage($cfg, $baseid, $cache);
+    }
+
+    if (!$plugin->check_connection($storeid, $scfg)) {
+       die "storage '$storeid' is not online\n";
     }
 
     $plugin->activate_storage($storeid, $scfg, $cache);
@@ -550,19 +705,10 @@ sub activate_storage_list {
     $cache = {} if !$cache;
 
     foreach my $storeid (@$storeid_list) {
-       __activate_storage_full ($cfg, $storeid, $cache);
+       activate_storage($cfg, $storeid, $cache);
     }
 }
 
-sub activate_storage {
-    my ($cfg, $storeid) = @_;
-
-    my $cache = {};
-
-    __activate_storage_full ($cfg, $storeid, $cache);
-}
-
-
 sub deactivate_storage {
     my ($cfg, $storeid) = @_;
 
@@ -654,12 +800,16 @@ sub storage_info {
 
     my $cache = {};
 
-    eval { activate_storage_list($cfg, $slist, $cache); };
-
     foreach my $storeid (keys %$ids) {
        my $scfg = $ids->{$storeid};
        next if !$info->{$storeid};
 
+       eval { activate_storage($cfg, $storeid, $cache); };
+       if (my $err = $@) {
+           warn $err;
+           next;
+       }
+
        my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
        my ($total, $avail, $used, $active);
        eval { ($total, $avail, $used, $active) = $plugin->status($storeid, $scfg, $cache); };