]> git.proxmox.com Git - pve-storage.git/blobdiff - PVE/Storage/Plugin.pm
storage: rename REs for iso and vztmpl extensions
[pve-storage.git] / PVE / Storage / Plugin.pm
index 7d2487fc1c68cca36b2b3e337f2bee501e8ae4c1..34f962301224a1cf05a30673444298fe511d8492 100644 (file)
@@ -563,9 +563,9 @@ sub parse_volname {
        my ($vmid, $name) = ($1, $2);
        my (undef, $format, $isBase) = parse_name_dir($name);
        return ('images', $name, $vmid, undef, undef, $isBase, $format);
-    } elsif ($volname =~ m!^iso/([^/]+$PVE::Storage::iso_extension_re)$!) {
+    } elsif ($volname =~ m!^iso/([^/]+$PVE::Storage::ISO_EXT_RE_0)$!) {
        return ('iso', $1);
-    } elsif ($volname =~ m!^vztmpl/([^/]+$PVE::Storage::vztmpl_extension_re)$!) {
+    } elsif ($volname =~ m!^vztmpl/([^/]+$PVE::Storage::VZTMPL_EXT_RE_1)$!) {
        return ('vztmpl', $1);
     } elsif ($volname =~ m!^rootdir/(\d+)$!) {
        return ('rootdir', $1, $1);
@@ -892,7 +892,11 @@ sub file_size_info {
     my ($size, $format, $used, $parent) = $info->@{qw(virtual-size format actual-size backing-filename)};
 
     ($size) = ($size =~ /^(\d+)$/) or die "size '$size' not an integer\n"; # untaint
+    # coerce back from string
+    $size = int($size);
     ($used) = ($used =~ /^(\d+)$/) or die "used '$used' not an integer\n"; # untaint
+    # coerce back from string
+    $used = int($used);
     ($format) = ($format =~ /^(\S+)$/) or die "format '$format' includes whitespace\n"; # untaint
     if (defined($parent)) {
        ($parent) = ($parent =~ /^(\S+)$/) or die "parent '$parent' includes whitespace\n"; # untaint
@@ -1049,6 +1053,7 @@ sub volume_has_feature {
                  snap => {qcow2 => 1} },
        sparseinit => { base => {qcow2 => 1, raw => 1, vmdk => 1},
                        current => {qcow2 => 1, raw => 1, vmdk => 1} },
+       rename => { current => {qcow2 => 1, raw => 1, vmdk => 1} },
     };
 
     # clone_image creates a qcow2 volume
@@ -1056,6 +1061,8 @@ sub volume_has_feature {
                defined($opts->{valid_target_formats}) &&
                !(grep { $_ eq 'qcow2' } @{$opts->{valid_target_formats}});
 
+    return 0 if $feature eq 'rename' && $class->can('api') && $class->api() < 10;
+
     my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
        $class->parse_volname($volname);
 
@@ -1134,12 +1141,12 @@ my $get_subdir_files = sub {
        my $info;
 
        if ($tt eq 'iso') {
-           next if $fn !~ m!/([^/]+$PVE::Storage::iso_extension_re)$!i;
+           next if $fn !~ m!/([^/]+$PVE::Storage::ISO_EXT_RE_0)$!i;
 
            $info = { volid => "$sid:iso/$1", format => 'iso' };
 
        } elsif ($tt eq 'vztmpl') {
-           next if $fn !~ m!/([^/]+$PVE::Storage::vztmpl_extension_re)$!;
+           next if $fn !~ m!/([^/]+$PVE::Storage::VZTMPL_EXT_RE_1)$!;
 
            $info = { volid => "$sid:vztmpl/$1", format => "t$2" };
 
@@ -1578,4 +1585,39 @@ sub volume_import_formats {
     return ();
 }
 
+sub rename_volume {
+    my ($class, $scfg, $storeid, $source_volname, $target_vmid, $target_volname) = @_;
+    die "not implemented in storage plugin '$class'\n" if $class->can('api') && $class->api() < 10;
+    die "no path found\n" if !$scfg->{path};
+
+    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, 1)
+       if !$target_volname;
+
+    my $basedir = $class->get_subdir($scfg, 'images');
+
+    mkpath "${basedir}/${target_vmid}";
+
+    my $old_path = "${basedir}/${source_vmid}/${source_image}";
+    my $new_path = "${basedir}/${target_vmid}/${target_volname}";
+
+    die "target volume '${target_volname}' already exists\n" if -e $new_path;
+
+    my $base = $base_name ? "${base_vmid}/${base_name}/" : '';
+
+    rename($old_path, $new_path) ||
+       die "rename '$old_path' to '$new_path' failed - $!\n";
+
+    return "${storeid}:${base}${target_vmid}/${target_volname}";
+}
+
 1;