use PVE::Storage::ZFSPoolPlugin;
use PVE::Storage::ZFSPlugin;
use PVE::Storage::PBSPlugin;
+use PVE::Storage::BTRFSPlugin;
# Storage API version. Increment it on changes in storage API interface.
-use constant APIVER => 8;
+use constant APIVER => 9;
# Age is the number of versions we're backward compatible with.
# This is like having 'current=APIVER' and age='APIAGE' in libtool,
# see https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
-use constant APIAGE => 7;
+use constant APIAGE => 0;
# load standard plugins
PVE::Storage::DirPlugin->register();
PVE::Storage::ZFSPoolPlugin->register();
PVE::Storage::ZFSPlugin->register();
PVE::Storage::PBSPlugin->register();
+PVE::Storage::BTRFSPlugin->register();
# load third-party plugins
if ( -d '/usr/share/perl5/PVE/Storage/Custom' ) {
our $iso_extension_re = qr/\.(?:iso|img)/i;
+our $vztmpl_extension_re = qr/\.tar\.([gx]z)/i;
+
# PVE::Storage utility functions
sub config {
# storage_can_replicate:
# return true if storage supports replication
-# (volumes alocated with vdisk_alloc() has replication feature)
+# (volumes allocated with vdisk_alloc() has replication feature)
sub storage_can_replicate {
my ($cfg, $storeid, $format) = @_;
} elsif ($path =~ m!^$isodir/([^/]+$iso_extension_re)$!) {
my $name = $1;
return ('iso', "$sid:iso/$name");
- } elsif ($path =~ m!^$tmpldir/([^/]+\.tar\.gz)$!) {
+ } elsif ($path =~ m!^$tmpldir/([^/]+$vztmpl_extension_re)$!) {
my $name = $1;
return ('vztmpl', "$sid:vztmpl/$name");
} elsif ($path =~ m!^$privatedir/(\d+)$!) {
my $migration_snapshot;
if (!defined($snapshot)) {
- if ($scfg->{type} eq 'zfspool') {
+ if ($scfg->{type} eq 'zfspool' || $scfg->{type} eq 'btrfs') {
$migration_snapshot = 1;
$snapshot = '__migration__';
}
my $send = ['pvesm', 'export', $volid, $format, '-', '-with-snapshots', $with_snapshots];
my $recv = [@$ssh, '--', 'pvesm', 'import', $target_volid, $format, $import_fn, '-with-snapshots', $with_snapshots];
if (defined($snapshot)) {
- push @$send, '-snapshot', $snapshot
+ push @$send, '-snapshot', $snapshot;
+ push @$recv, '-snapshot', $snapshot;
}
if ($migration_snapshot) {
push @$recv, '-delete-snapshot', $snapshot;
if (defined($base_snapshot)) {
# Check if the snapshot exists on the remote side:
push @$send, '-base', $base_snapshot;
- push @$recv, '-base', $base_snapshot;
+ push @$recv, '-base', $base_snapshot if $target_apiver >= 9;
}
my $new_volid;
}
}
-sub volume_export {
+sub volume_export : prototype($$$$$$$) {
my ($cfg, $fh, $volid, $format, $snapshot, $base_snapshot, $with_snapshots) = @_;
my ($storeid, $volname) = parse_volume_id($volid, 1);
$snapshot, $base_snapshot, $with_snapshots);
}
-sub volume_import {
- my ($cfg, $fh, $volid, $format, $base_snapshot, $with_snapshots, $allow_rename) = @_;
+sub volume_import : prototype($$$$$$$$) {
+ my ($cfg, $fh, $volid, $format, $snapshot, $base_snapshot, $with_snapshots, $allow_rename) = @_;
my ($storeid, $volname) = parse_volume_id($volid, 1);
die "cannot import into volume '$volid'\n" if !$storeid;
my $scfg = storage_config($cfg, $storeid);
my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
- return $plugin->volume_import($scfg, $storeid, $fh, $volname, $format,
- $base_snapshot, $with_snapshots, $allow_rename) // $volid;
-}
-
-sub volume_export_formats {
+ return $plugin->volume_import(
+ $scfg,
+ $storeid,
+ $fh,
+ $volname,
+ $format,
+ $snapshot,
+ $base_snapshot,
+ $with_snapshots,
+ $allow_rename,
+ ) // $volid;
+}
+
+sub volume_export_formats : prototype($$$$$) {
my ($cfg, $volid, $snapshot, $base_snapshot, $with_snapshots) = @_;
my ($storeid, $volname) = parse_volume_id($volid, 1);
$with_snapshots);
}
-sub volume_import_formats {
- my ($cfg, $volid, $base_snapshot, $with_snapshots) = @_;
+sub volume_import_formats : prototype($$$$$) {
+ my ($cfg, $volid, $snapshot, $base_snapshot, $with_snapshots) = @_;
my ($storeid, $volname) = parse_volume_id($volid, 1);
return if !$storeid;
my $scfg = storage_config($cfg, $storeid);
my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
- return $plugin->volume_import_formats($scfg, $storeid, $volname,
- $base_snapshot, $with_snapshots);
+ return $plugin->volume_import_formats(
+ $scfg,
+ $storeid,
+ $volname,
+ $snapshot,
+ $base_snapshot,
+ $with_snapshots,
+ );
}
sub volume_transfer_formats {
my ($cfg, $src_volid, $dst_volid, $snapshot, $base_snapshot, $with_snapshots) = @_;
my @export_formats = volume_export_formats($cfg, $src_volid, $snapshot, $base_snapshot, $with_snapshots);
- my @import_formats = volume_import_formats($cfg, $dst_volid, $base_snapshot, $with_snapshots);
+ my @import_formats = volume_import_formats($cfg, $dst_volid, $snapshot, $base_snapshot, $with_snapshots);
my %import_hash = map { $_ => 1 } @import_formats;
my @common = grep { $import_hash{$_} } @export_formats;
return @common;
my ($operation, $storage_list, $override) = @_;
# called for each limit (global, per-storage) with the 'default' and the
- # $operation limit and should udpate $override for every limit affecting
+ # $operation limit and should update $override for every limit affecting
# us.
my $use_global_limits = 0;
my $apply_limit = sub {