diff --git a/src/PVE/Storage/LVMPlugin.pm b/src/PVE/Storage/LVMPlugin.pm index 8a61bc5..0e2c38c 100644 --- a/src/PVE/Storage/LVMPlugin.pm +++ b/src/PVE/Storage/LVMPlugin.pm @@ -443,20 +443,6 @@ sub parse_volname { die "unable to parse lvm volume name '$volname'\n"; } -#return snapshot name from a file path -sub get_snapname_from_path { - my ($class, $volname, $path) = @_; - - my $basepath = basename($path); - my $name = ($volname =~ s/\.[^.]+$//r); - if ($basepath =~ m/^snap_${name}_(.*)\.qcow2$/) { - return $1; - } elsif ($basepath eq $volname) { - return 'current'; - } - return undef; -} - my sub get_snap_name { my ($class, $volname, $snapname) = @_; @@ -472,12 +458,6 @@ my sub get_snap_name { } } -sub get_snap_volname { - my ($class, $volname, $snapname) = @_; - - return get_snap_name($class, $volname, $snapname); -} - sub filesystem_path { my ($class, $scfg, $volname, $snapname) = @_; @@ -787,6 +767,62 @@ sub status { return undef; } +sub volume_snapshot_info { + my ($class, $scfg, $storeid, $volname) = @_; + + my $get_snapname_from_path = sub { + my ($volname, $path) = @_; + + my $basepath = basename($path); + my $name = ($volname =~ s/\.[^.]+$//r); + if ($basepath =~ m/^snap_${name}_(.*)\.qcow2$/) { + return $1; + } elsif ($basepath eq $volname) { + return 'current'; + } + return undef; + }; + + my $path = $class->filesystem_path($scfg, $volname); + my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) = + $class->parse_volname($volname); + + my $json = PVE::Storage::Common::qemu_img_info($path, undef, 10, 1); + die "failed to query file information with qemu-img\n" if !$json; + my $json_decode = eval { decode_json($json) }; + if ($@) { + die "Can't decode qemu snapshot list. Invalid JSON: $@\n"; + } + my $info = {}; + my $order = 0; + return $info if ref($json_decode) ne 'ARRAY'; + + #no snapshot or external snapshots is an arrayref + my $snapshots = $json_decode; + for my $snap (@$snapshots) { + my $snapfile = $snap->{filename}; + my $snapname = $get_snapname_from_path->($volname, $snapfile); + #not a proxmox snapshot + next if !$snapname; + + my $snapvolname = get_snap_name($class, $volname, $snapname); + + $info->{$snapname}->{order} = $order; + $info->{$snapname}->{file} = $snapfile; + $info->{$snapname}->{volname} = "$snapvolname"; + $info->{$snapname}->{volid} = "$storeid:$snapvolname"; + + my $parentfile = $snap->{'backing-filename'}; + if ($parentfile) { + my $parentname = $get_snapname_from_path->($volname, $parentfile); + $info->{$snapname}->{parent} = $parentname; + $info->{$parentname}->{child} = $snapname; + } + $order++; + } + return $info; +} + sub activate_storage { my ($class, $storeid, $scfg, $cache) = @_; diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm index 8ea62e4..aafb13c 100644 --- a/src/PVE/Storage/Plugin.pm +++ b/src/PVE/Storage/Plugin.pm @@ -1718,27 +1718,6 @@ sub status { return ($res->{total}, $res->{avail}, $res->{used}, 1); } -sub get_snap_volname { - my ($class, $volname, $snapname) = @_; - - my $vmid = ($class->parse_volname($volname))[2]; - my $name = get_snap_name($class, $volname, $snapname); - return "$vmid/$name"; -} - -#return snapshot name from a file path -sub get_snapname_from_path { - my ($class, $volname, $path) = @_; - - my $basepath = basename($path); - if ($basepath =~ m/^snap-(.*)-vm(.*)$/) { - return $1; - } elsif ($basepath eq basename($volname)) { - return 'current'; - } - return undef; -} - # Returns a hash with the snapshot names as keys and the following data: # id - Unique id to distinguish different snapshots even if the have the same name. # timestamp - Creation time of the snapshot (seconds since epoch). @@ -1746,6 +1725,18 @@ sub get_snapname_from_path { sub volume_snapshot_info { my ($class, $scfg, $storeid, $volname) = @_; + my $get_snapname_from_path = sub { + my ($volname, $path) = @_; + + my $basepath = basename($path); + if ($basepath =~ m/^snap-(.*)-vm(.*)$/) { + return $1; + } elsif ($basepath eq basename($volname)) { + return 'current'; + } + return undef; + }; + my $path = $class->filesystem_path($scfg, $volname); my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) = $class->parse_volname($volname); @@ -1772,11 +1763,13 @@ sub volume_snapshot_info { my $snapshots = $json_decode; for my $snap (@$snapshots) { my $snapfile = $snap->{filename}; - my $snapname = $class->get_snapname_from_path($volname, $snapfile); + my $snapname = $get_snapname_from_path->($volname, $snapfile); #not a proxmox snapshot next if !$snapname; - my $snapvolname = $class->get_snap_volname($volname, $snapname); + my $snapvolname = get_snap_name($class, $volname, $snapname); + $snapvolname = "$vmid/$snapvolname"; + $info->{$snapname}->{order} = $order; $info->{$snapname}->{file} = $snapfile; $info->{$snapname}->{volname} = "$snapvolname"; @@ -1785,7 +1778,7 @@ sub volume_snapshot_info { my $parentfile = $snap->{'backing-filename'}; if ($parentfile) { - my $parentname = $class->get_snapname_from_path($volname, $parentfile); + my $parentname = $get_snapname_from_path->($volname, $parentfile); $info->{$snapname}->{parent} = $parentname; $info->{$parentname}->{child} = $snapname; }