X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=PVE%2FStorage.pm;h=1ef5ed2c7f5d3ec709266567b1c9acb73d765d7e;hb=892dc992490bb0b983699fd59bfa9d5e553d2eb5;hp=4863d8405885f6bcb1973502be4b34b872b0642d;hpb=683a3f463fdf190fc3700b233ce1284b3c02fcf5;p=pve-storage.git diff --git a/PVE/Storage.pm b/PVE/Storage.pm index 4863d84..1ef5ed2 100755 --- a/PVE/Storage.pm +++ b/PVE/Storage.pm @@ -285,6 +285,21 @@ sub volume_snapshot_delete { } } +# check if a volume or snapshot supports a given feature +# $feature - one of: +# clone - linked clone is possible +# copy - full clone is possible +# replicate - replication is possible +# snapshot - taking a snapshot is possible +# sparseinit - volume is sparsely initialized +# template - conversion to base image is possible +# $snap - check if the feature is supported for a given snapshot +# $running - if the guest owning the volume is running +# $opts - hash with further options: +# valid_target_formats - list of formats for the target of a copy/clone +# operation that the caller could work with. The +# format of $volid is always considered valid and if +# no list is specified, all formats are considered valid. sub volume_has_feature { my ($cfg, $feature, $volid, $snap, $running, $opts) = @_; @@ -521,7 +536,7 @@ sub path_to_volume_id { return ('rootdir', "$sid:rootdir/$vmid"); } elsif ($path =~ m!^$backupdir/([^/]+\.(tar|tar\.gz|tar\.lzo|tgz|vma|vma\.gz|vma\.lzo))$!) { my $name = $1; - return ('iso', "$sid:backup/$name"); + return ('backup', "$sid:backup/$name"); } } @@ -1210,7 +1225,7 @@ sub scan_cifs { sub scan_zfs { - my $cmd = ['zfs', 'list', '-t', 'filesystem', '-H', '-o', 'name,avail,used']; + my $cmd = ['zfs', 'list', '-t', 'filesystem', '-Hp', '-o', 'name,avail,used']; my $res = []; run_command($cmd, outfunc => sub { @@ -1218,8 +1233,8 @@ sub scan_zfs { if ($line =~m/^(\S+)\s+(\S+)\s+(\S+)$/) { my ($pool, $size_str, $used_str) = ($1, $2, $3); - my $size = PVE::Storage::ZFSPoolPlugin::zfs_parse_size($size_str); - my $used = PVE::Storage::ZFSPoolPlugin::zfs_parse_size($used_str); + my $size = $size_str + 0; + my $used = $used_str + 0; # ignore subvolumes generated by our ZFSPoolPlugin return if $pool =~ m!/subvol-\d+-[^/]+$!; return if $pool =~ m!/basevol-\d+-[^/]+$!; @@ -1336,6 +1351,53 @@ sub foreach_volid { } } +sub decompressor_info { + my ($format, $comp) = @_; + + if ($format eq 'tgz' && !defined($comp)) { + ($format, $comp) = ('tar', 'gz'); + } + + my $decompressor = { + tar => { + gz => ['tar', '-z'], + lzo => ['tar', '--lzop'], + }, + vma => { + gz => ['zcat'], + lzo => ['lzop', '-d', '-c'], + }, + }; + + die "ERROR: archive format not defined\n" + if !defined($decompressor->{$format}); + + my $decomp = $decompressor->{$format}->{$comp} if $comp; + + my $info = { + format => $format, + compression => $comp, + decompressor => $decomp, + }; + + return $info; +} + +sub archive_info { + my ($archive) = shift; + my $info; + + my $volid = basename($archive); + if ($volid =~ /vzdump-(lxc|openvz|qemu)-\d+-(?:\d{4})_(?:\d{2})_(?:\d{2})-(?:\d{2})_(?:\d{2})_(?:\d{2})\.(tgz$|tar|vma)(?:\.(gz|lzo))?$/) { + $info = decompressor_info($2, $3); + $info->{type} = $1; + } else { + die "ERROR: couldn't determine format and compression type\n"; + } + + return $info; +} + sub extract_vzdump_config_tar { my ($archive, $conf_re) = @_; @@ -1381,16 +1443,12 @@ sub extract_vzdump_config_vma { }; + my $info = archive_info($archive); + $comp //= $info->{compression}; + my $decompressor = $info->{decompressor}; + if ($comp) { - my $uncomp; - if ($comp eq 'gz') { - $uncomp = ["zcat", $archive]; - } elsif ($comp eq 'lzo') { - $uncomp = ["lzop", "-d", "-c", $archive]; - } else { - die "unknown compression method '$comp'\n"; - } - $cmd = [$uncomp, ["vma", "config", "-"]]; + $cmd = [ [@$decompressor, $archive], ["vma", "config", "-"] ]; # in some cases, lzop/zcat exits with 1 when its stdout pipe is # closed early by vma, detect this and ignore the exit code later @@ -1440,20 +1498,14 @@ sub extract_vzdump_config { } my $archive = abs_filesystem_path($cfg, $volid); + my $info = archive_info($archive); + my $format = $info->{format}; + my $comp = $info->{compression}; + my $type = $info->{type}; - if ($volid =~ /vzdump-(lxc|openvz)-\d+-(\d{4})_(\d{2})_(\d{2})-(\d{2})_(\d{2})_(\d{2})\.(tgz|(tar(\.(gz|lzo))?))$/) { + if ($type eq 'lxc' || $type eq 'openvz') { return extract_vzdump_config_tar($archive, qr!^(\./etc/vzdump/(pct|vps)\.conf)$!); - } elsif ($volid =~ /vzdump-qemu-\d+-(\d{4})_(\d{2})_(\d{2})-(\d{2})_(\d{2})_(\d{2})\.(tgz|((tar|vma)(\.(gz|lzo))?))$/) { - my $format; - my $comp; - if ($7 eq 'tgz') { - $format = 'tar'; - $comp = 'gz'; - } else { - $format = $9; - $comp = $11 if defined($11); - } - + } elsif ($type eq 'qemu') { if ($format eq 'tar') { return extract_vzdump_config_tar($archive, qr!\(\./qemu-server\.conf\)!); } else {