+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 file/device '$volid' is not possible\n";
+ } else {
+ die "unable to parse volume ID '$volid'\n";
+ }
+}
+
+sub volume_rollback_is_possible {
+ 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_rollback_is_possible($scfg, $storeid, $volname, $snap);
+ } elsif ($volid =~ m|^(/.+)$| && -e $volid) {
+ die "snapshot rollback file/device '$volid' is not possible\n";
+ } else {
+ die "unable to parse volume ID '$volid'\n";
+ }
+}
+
+sub volume_snapshot {
+ 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($scfg, $storeid, $volname, $snap);
+ } elsif ($volid =~ m|^(/.+)$| && -e $volid) {
+ die "snapshot file/device '$volid' is not possible\n";
+ } else {
+ die "unable to parse volume ID '$volid'\n";
+ }
+}
+
+sub volume_send {
+ my ($cfg, $volid, $snap, $ip, $incremental_snap, $verbose, $limit,
+ $target_path) = @_;
+
+ 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_send($scfg, $storeid, $volname, $ip, $snap,
+ $incremental_snap, $verbose, $limit, $target_path);
+
+ } elsif ($volid =~ m|^(/.+)$| && -e $volid) {
+ die "send file/device '$volid' is not possible\n";
+ } else {
+ die "unable to parse volume ID '$volid'\n";
+ }
+}
+
+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});
+ $plugin->volume_rollback_is_possible($scfg, $storeid, $volname, $snap);
+ return $plugin->volume_snapshot_rollback($scfg, $storeid, $volname, $snap);
+ } elsif ($volid =~ m|^(/.+)$| && -e $volid) {
+ die "snapshot rollback file/device '$volid' is not possible\n";
+ } else {
+ die "unable to parse volume ID '$volid'\n";
+ }
+}
+
+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 file/device '$volid' is not possible\n";
+ } else {
+ die "unable to parse volume ID '$volid'\n";
+ }
+}
+
+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 volume_snapshot_list {
+ my ($cfg, $volid, $prefix, $ip) = @_;
+
+ 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_list($scfg, $storeid, $volname, $prefix, $ip);
+ } elsif ($volid =~ m|^(/.+)$| && -e $volid) {
+ die "send file/device '$volid' is not possible\n";
+ } else {
+ die "unable to parse volume ID '$volid'\n";
+ }
+ # return an empty array if dataset does not exist.
+ # youngest snap first
+}
+