Commit 5f7f9241 authored by Francesc Guasch's avatar Francesc Guasch Committed by Francesc Guasch
Browse files

Fix linked volumes (#1525)

fix(volumes): check file exists when linked

* test(volumes): check when files are linked

issue #1524
parent b29552d8
......@@ -454,12 +454,21 @@ Returns true if the file exists in this virtual manager storage
=cut
sub file_exists($self, $file) {
return -e $file if $self->is_local;
return $self->_file_exists_remote($file);
}
sub _file_exists_remote($self, $file) {
$file = $self->_follow_link($file);
for my $pool ($self->vm->list_all_storage_pools ) {
$self->_wait_storage( sub { $pool->refresh() } );
my @volumes = $self->_wait_storage( sub { $pool->list_all_volumes });
for my $vol ( @volumes ) {
my $found;
eval { $found = 1 if $vol->get_path eq $file };
eval {
my $path = $self->_follow_link($vol->get_path);
$found = 1 if $path eq $file;
};
# volume was removed in the nick of time
die $@ if $@ && ( !ref($@) || $@->code != 50);
return 1 if $found;
......@@ -468,6 +477,20 @@ sub file_exists($self, $file) {
return 0;
}
sub _follow_link($self, $file) {
my ($dir, $name) = $file =~ m{(.*)/(.*)};
if (!defined $self->{_is_link}->{$dir} ) {
my ($out,$err) = $self->run_command("stat", $dir );
chomp $out;
$out =~ m{ -> (/.*)};
$self->{_is_link}->{$dir} = $1;
}
my $path = $self->{_is_link}->{$dir};
return $file if !$path;
return "$path/$name";
}
sub _wait_storage($self, $sub) {
my @ret;
for ( 1 .. 10 ) {
......
......@@ -429,7 +429,191 @@ sub test_default_pool_base {
}
}
#
sub _create_pool_linked($vm) {
my $capacity = 1 * 1024 * 1024;
my $pool_name = new_pool_name();
my $dir = "/var/tmp/$pool_name";
my $dir_link = "$dir.link";
mkdir $dir if ! -e $dir;
unlink $dir_link or die "$! $dir_link" if -e $dir_link;
symlink($dir, $dir_link) or die "$! linking $dir -> $dir_link";
my $pool;
for ( ;; ) {
my $uuid = Ravada::VM::KVM::_new_uuid('68663afc-aaf4-4f1f-9fff-93684c260942');
my $xml =
"<pool type='dir'>
<name>$pool_name</name>
<uuid>$uuid</uuid>
<capacity unit='bytes'>$capacity</capacity>
<allocation unit='bytes'></allocation>
<available unit='bytes'>$capacity</available>
<source>
</source>
<target>
<path>$dir_link</path>
<permissions>
<mode>0711</mode>
<owner>0</owner>
<group>0</group>
</permissions>
</target>
</pool>"
;
eval { $pool = $vm->vm->create_storage_pool($xml) };
last if !$@ || $@ !~ /libvirt error code: 9,/;
};
ok(!$@,"Expecting \$@='', got '".($@ or '')."'") or return;
ok($pool,"Expecting a pool , got ".($pool or ''));
return ($pool_name, $dir, $dir_link);
}
sub _create_pool_linked_reverse($vm) {
my $capacity = 1 * 1024 * 1024;
my $pool_name = new_pool_name();
my $dir = "/var/tmp/$pool_name";
my $dir_link = "$dir.link";
mkdir $dir if ! -e $dir;
unlink $dir_link or die "$! $dir_link" if -e $dir_link;
symlink($dir, $dir_link) or die "$! linking $dir -> $dir_link";
my $pool;
for ( ;; ) {
my $uuid = Ravada::VM::KVM::_new_uuid('68663afc-aaf4-4f1f-9fff-93684c260942');
my $xml =
"<pool type='dir'>
<name>$pool_name</name>
<uuid>$uuid</uuid>
<capacity unit='bytes'>$capacity</capacity>
<allocation unit='bytes'></allocation>
<available unit='bytes'>$capacity</available>
<source>
</source>
<target>
<path>$dir</path>
<permissions>
<mode>0711</mode>
<owner>0</owner>
<group>0</group>
</permissions>
</target>
</pool>"
;
eval { $pool = $vm->vm->create_storage_pool($xml) };
last if !$@ || $@ !~ /libvirt error code: 9,/;
};
ok(!$@,"Expecting \$@='', got '".($@ or '')."'") or return;
ok($pool,"Expecting a pool , got ".($pool or ''));
return ($pool_name, $dir, $dir_link);
}
sub test_pool_linked($vm) {
my ($pool_name, $dir, $dir_link) = _create_pool_linked($vm);
$vm->default_storage_pool_name($pool_name);
my $domain1 = create_domain($vm);
$domain1->prepare_base(user_admin);
my $clone1 = $domain1->clone(
name => new_domain_name
,user => user_admin
);
$clone1->remove(user_admin);
$domain1->remove(user_admin);
}
sub test_pool_linked_reverse($vm) {
my ($pool_name, $dir, $dir_link) = _create_pool_linked_reverse($vm);
$vm->default_storage_pool_name($pool_name);
my $domain1 = create_domain($vm);
$domain1->prepare_base(user_admin);
my $clone1 = $domain1->clone(
name => new_domain_name
,user => user_admin
);
$clone1->remove(user_admin);
$domain1->remove(user_admin);
}
sub test_pool_linked2($vm) {
my ($pool_name, $dir, $dir_link) = _create_pool_linked($vm);
$vm->default_storage_pool_name($pool_name);
my $domain1 = create_domain($vm);
my $new_vol = "$dir/new_volume.qcow2";
my $new_vol_linked = "$dir_link/new_volume.link.qcow2";
$vm->run_command('qemu-img','create','-f','qcow2',$new_vol,'128M');
ok( -e $new_vol);
$vm->run_command('qemu-img','create','-f','qcow2',$new_vol_linked,'128M');
ok( -e $new_vol_linked);
$domain1->add_volume(file => $new_vol);
$domain1->add_volume(file => $new_vol_linked);
for my $vol ( $domain1->list_volumes_info ) {
my $capacity;
eval { $capacity = $vol->capacity };
is($@, '', $vol->file);
ok($capacity, $vol->file);
}
$domain1->prepare_base(user_admin);
my $clone1 = $domain1->clone(
name => new_domain_name
,user => user_admin
);
$clone1->remove(user_admin);
$domain1->remove(user_admin);
}
sub test_pool_linked2_reverse($vm) {
my ($pool_name, $dir, $dir_link) = _create_pool_linked_reverse($vm);
$vm->default_storage_pool_name($pool_name);
my $domain1 = create_domain($vm);
my $new_vol = "$dir/new_volume.qcow2";
my $new_vol_linked = "$dir_link/new_volume.link.qcow2";
$vm->run_command('qemu-img','create','-f','qcow2',$new_vol,'128M');
ok( -e $new_vol);
$vm->run_command('qemu-img','create','-f','qcow2',$new_vol_linked,'128M');
ok( -e $new_vol_linked);
$domain1->add_volume(file => $new_vol);
$domain1->add_volume(file => $new_vol_linked);
for my $vol ( $domain1->list_volumes_info ) {
my $capacity;
eval { $capacity = $vol->capacity };
is($@, '', $vol->file);
ok($capacity, $vol->file);
}
$domain1->prepare_base(user_admin);
my $clone1 = $domain1->clone(
name => new_domain_name
,user => user_admin
);
$clone1->remove(user_admin);
$domain1->remove(user_admin);
}
#########################################################################
clean();
......@@ -448,6 +632,11 @@ SKIP: {
skip($msg,10) if !$vm;
test_pool_linked($vm);
test_pool_linked2($vm);
test_pool_linked_reverse($vm);
test_pool_linked2_reverse($vm);
my $pool_name = create_pool($vm_name);
my $domain = test_create_domain($vm_name, $pool_name);
......@@ -465,6 +654,8 @@ SKIP: {
test_base_clone_pool($vm, $pool_name, $pool_name2);
$domain->remove(user_admin);
test_pool_linked($vm);
}
end();
......
......@@ -1144,7 +1144,11 @@ sub _delete_qemu_pool($pool) {
my $path ="$dir/$file";
unlink $path or die "$! $path" if -e $path;
}
rmdir($dir) or die "$! $dir";
if (-l $dir) {
unlink $dir or die "$! $dir";
} else {
rmdir($dir) or die "$! $dir";
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment