return int($vmid);
}
-PVE::JSONSchema::register_format('pve-volume-id', \&parse_volume_id);
sub parse_volume_id {
my ($volid, $noerr) = @_;
- if ($volid =~ m/^([a-z][a-z0-9\-\_\.]*[a-z0-9]):(.+)$/i) {
- return wantarray ? ($1, $2) : $1;
+ return PVE::Storage::Plugin::parse_volume_id($volid, $noerr);
+}
+
+sub volume_is_base {
+ my ($cfg, $volid) = @_;
+
+ my ($sid, $volname) = parse_volume_id($volid, 1);
+ return 0 if !$sid;
+
+ if (my $scfg = $cfg->{ids}->{$sid}) {
+ my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+ my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
+ $plugin->parse_volname($volname);
+ return $isBase ? 1 : 0;
+ } else {
+ # stale volid with undefined storage - so we can just guess
+ if ($volid =~ m/base-/) {
+ return 1;
+ }
}
- return undef if $noerr;
- die "unable to parse volume ID '$volid'\n";
+
+ return 0;
}
# try to map a filesystem path to a volume identifier
my ($sid, $volname) = parse_volume_id($path, 1);
if ($sid) {
if (my $scfg = $ids->{$sid}) {
- if (my $path = $scfg->{path}) {
+ if ($scfg->{path}) {
my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
my ($vtype, $name, $vmid) = $plugin->parse_volname($volname);
return ($vtype, $path);
# lock shared storage
$plugin->cluster_lock_storage($storeid, $scfg->{shared}, undef, sub {
- my $cleanup_worker = $plugin->free_image($storeid, $scfg, $volname);
+
+ my ($vtype, $name, $vmid, undef, undef, $isBase) =
+ $plugin->parse_volname($volname);
+ if ($isBase) {
+ my $vollist = $plugin->list_images($storeid, $scfg);
+ foreach my $info (@$vollist) {
+ my (undef, $tmpvolname) = parse_volume_id($info->{volid});
+ my $basename = undef;
+ my $basevmid = undef;
+
+ eval{
+ (undef, undef, undef, $basename, $basevmid) =
+ $plugin->parse_volname($tmpvolname);
+ };
+
+ if ($basename && defined($basevmid) && $basevmid == $vmid && $basename eq $name) {
+ die "base volume '$volname' is still in use " .
+ "(use by '$tmpvolname')\n";
+ }
+ }
+ }
+ my $cleanup_worker = $plugin->free_image($storeid, $scfg, $volname, $isBase);
});
return if !$cleanup_worker;