Commit 374bc12e authored by Francesc Guasch's avatar Francesc Guasch
Browse files

[#11] Checking memory used from the alive domains

Running domains may not claim all the memory they
need right away. Nevertheless they will eventually
use it and it may render the server unusable when
there are many domains starting at the same time.
This precondition check fixes it.

Also failing tests for this issue are fixed.
parent 60055b97
......@@ -13,6 +13,8 @@ use Sys::Statistics::Linux;
our $TIMEOUT_SHUTDOWN = 20;
our $CONNECTOR;
our $MIN_FREE_MEMORY = 1024*1024;
_init_connector();
requires 'name';
......@@ -97,7 +99,7 @@ before 'prepare_base' => \&_allow_prepare_base;
delete $self->{_was_active};
};
before 'start' => \&_preconditions;
before 'start' => \&_start_preconditions;
before 'pause' => \&_allow_manage;
before 'resume' => \&_allow_manage;
before 'shutdown' => \&_allow_manage_args;
......@@ -105,9 +107,10 @@ before 'shutdown' => \&_allow_manage_args;
before 'remove_base' => \&_can_remove_base;
after 'remove_base' => \&_remove_base_db;
sub _preconditions{
sub _start_preconditions{
_allow_manage(@_);
_check_free_memory();
_check_used_memory(@_);
}
sub _allow_manage_args {
......@@ -173,7 +176,29 @@ sub _check_has_clones {
sub _check_free_memory{
my $lxs = Sys::Statistics::Linux->new( memstats => 1 );
my $stat = $lxs->get;
die "No free memory" if ( $stat->memstats->{realfree} < 500000 );
die "No free memory" if ( $stat->memstats->{realfree} < $MIN_FREE_MEMORY );
}
sub _check_used_memory {
my $self = shift;
my $used_memory = 0;
my $lxs = Sys::Statistics::Linux->new( memstats => 1 );
my $stat = $lxs->get;
# We get mem total less the used for the system
my $mem_total = $stat->{memstats}->{memtotal} - 1*1024*1024;
for my $domain ( $self->_vm->list_domains ) {
my $alive;
eval { $alive = 1 if $domain->is_active && !$domain->is_paused };
next if !$alive;
my $info = $domain->get_info;
$used_memory += $info->{memory};
}
die "ERROR: Out of free memory. Using $used_memory RAM of $mem_total available" if $used_memory>= $mem_total;
}
sub _check_disk_modified {
......
......@@ -17,112 +17,58 @@ my $BACKEND = 'KVM';
use_ok('Ravada');
use_ok("Ravada::Domain::$BACKEND");
my $test = Test::SQL::Data->new( config => 't/etc/sql.conf');
my $RAVADA = rvd_back( $test->connector , 't/etc/ravada.conf');
my ($DOMAIN_NAME) = $0 =~ m{.*/(.*)\.};
my $DOMAIN_NAME_SON=$DOMAIN_NAME."_son";
$DOMAIN_NAME_SON =~ s/base_//;
my $RVD_BACK = rvd_back( $test->connector , 't/etc/ravada.conf');
my $USER = create_user('foo','bar');
sub test_vm_kvm {
my $vm = $RAVADA->vm->[0];
ok($vm,"No vm found") or exit;
ok(ref($vm) =~ /KVM$/,"vm is no kvm ".ref($vm)) or exit;
ok($vm->type, "Not defined $vm->type") or exit;
ok($vm->host, "Not defined $vm->host") or exit;
}
sub test_remove_domain {
my $name = shift;
my $domain;
$domain = $RAVADA->search_domain($name,1);
if ($domain) {
diag("Removing domain $name");
my @files_base = $domain->list_files_base;
eval { $domain->remove(user_admin()) };
ok(!$@ , "Error removing domain $name : $@") ;
sub test_new_domain {
my $vm = shift;
for my $file ( @files_base) {
ok(! -e $file,"Image file $file should beremoved ");
}
my $name = new_domain_name();
}
$domain = $RAVADA->search_domain($name,1);
ok(!$domain, "I can't remove old domain $name") or exit;
}
sub test_new_domain_from_iso {
my $name = $DOMAIN_NAME;
test_remove_domain($name);
diag("Creating domain $name from iso");
my $freemem = _check_free_memory();
my $domain;
eval { $domain = $RAVADA->create_domain(name => $name
eval { $domain = $vm->create_domain(name => $name
, id_iso => 1
,vm => $BACKEND
,vm => $vm->type
,id_owner => $USER->id
,memory => 1.5*1024*1024
)
};
if ($freemem < 1 ) {
ok($@,"Expecting failed because we ran out of free RAM");
return;
}
ok(!$@,"Domain $name not created: $@");
ok($domain,"Domain not created") or return;
my $exp_ref= 'Ravada::Domain::KVM';
ok(ref $domain eq $exp_ref, "Expecting $exp_ref , got ".ref($domain))
if $domain;
my @cmd = ('virsh','desc',$name);
my ($in,$out,$err);
run3(\@cmd,\$in,\$out,\$err);
ok(!$?,"@cmd \$?=$? , it should be 0 $err $out");
my $sth = $test->dbh->prepare("SELECT * FROM domains WHERE name=? ");
$sth->execute($domain->name);
my $row = $sth->fetchrow_hashref;
ok($row->{name} && $row->{name} eq $domain->name,"I can't find the domain at the db");
$sth->finish;
eval { $domain->start($USER); sleep 1; };
if ($freemem < 1 || $@ =~ /free memory/) {
ok($@,"Expecting failed start because we ran out of free RAM ($freemem MB Free)");
return;
}
ok(!$@,"Expected start domain with $freemem MB Free $@");
#Ckeck free memory
my $freemem = _check_free_memory();
print "FREEMEM: $freemem";
#virsh setmaxmem $name xG --config
#virsh setmem $name xG --config
return $domain;
}
sub remove_old_volumes {
my $name = "$DOMAIN_NAME_SON.qcow2";
my $file = "/var/lib/libvirt/images/$name";
remove_volume($file);
remove_volume("/var/lib/libvirt/images/$DOMAIN_NAME.img");
}
sub remove_volume {
my $file = shift;
return if !-e $file;
diag("removing old $file");
$RAVADA->remove_volume($file);
ok(! -e $file,"file $file not removed" );
}
sub _check_free_memory{
my $lxs = Sys::Statistics::Linux->new( memstats => 1 );
my $stat = $lxs->get;
my $freemem = $stat->memstats->{realfree};
#die "No free memory" if ( $stat->memstats->{realfree} < 500000 );
return $freemem;
my $free = int( $freemem / 1024 );
$free = $free / 1024;
$free =~ s/(\d+\.\d+)/$1/;
return $free;
}
......@@ -130,19 +76,28 @@ sub _check_free_memory{
################################################################
my $vm;
eval { $vm = $RAVADA->search_vm('kvm') } if $RAVADA;
remove_old_domains();
remove_old_disks();
SKIP: {
my $msg = "SKIPPED test: No KVM backend found";
my $vm = $RVD_BACK->search_vm('KVM');
diag($msg) if !$vm;
skip $msg,10 if !$vm;
test_vm_kvm();
test_remove_domain($DOMAIN_NAME);
remove_old_volumes();
my $domain = test_new_domain_from_iso();
test_remove_domain($domain);
my $freemem = _check_free_memory();
my $n_domains = int($freemem)+2;
diag("Checking it won't start no more than $n_domains domains with $freemem free memory");
for ( 0 .. $n_domains ) {
diag("Creating domain $_");
test_new_domain($vm) or last;
}
};
remove_old_domains();
remove_old_disks();
done_testing();
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