Unverified Commit 386069ff authored by Francesc Guasch's avatar Francesc Guasch Committed by GitHub
Browse files

Feature #731 start all (#954)

* 731_start_all: feat: New tab clones created. issue #731

* 731_start_all: feat: Request to start all clones of a base implemented. issue #731

* feat: test created. issue [#731].

* test(start): check clones are started

issue #731

* wip(frontend): merged bs4.1 intro clones tab

* refactor(backend): set starting domains to help balance

Count starting domains as if already started when balancing.
This way the load is best spread among nodes.

issue #731

* wip(backend): add new valid status *starting*

issue #731
parent 6dacac73
......@@ -1938,6 +1938,7 @@ sub process_requests {
);
$sth->execute(time);
my @reqs;
while (my ($id_request,$id_domain)= $sth->fetchrow) {
my $req;
eval { $req = Ravada::Request->open($id_request) };
......@@ -1951,6 +1952,12 @@ sub process_requests {
next if $req->command !~ /shutdown/i
&& $self->_domain_working($id_domain, $id_request);
push @reqs,($req);
}
for my $req (@reqs) {
next if $req eq 'refresh_vms' && scalar@reqs > 2;
warn "[$request_type] $$ executing request ".$req->id." ".$req->status()." "
.$req->command
." ".Dumper($req->args) if $DEBUG || $debug;
......@@ -2394,6 +2401,35 @@ sub _cmd_start {
}
sub _cmd_start_clones {
my $self = shift;
my $request = shift;
my $remote_ip = $request->args('remote_ip');
my $id_domain = $request->defined_arg('id_domain');
my $domain = $self->search_domain_by_id($id_domain);
die "Unknown domain '$id_domain'\n" if !$domain;
my $uid = $request->args('uid');
my $user = Ravada::Auth::SQL->search_by_id($uid);
my $sth = $CONNECTOR->dbh->prepare(
"SELECT id, name, is_base FROM domains WHERE id_base = ?"
);
$sth->execute($id_domain);
while ( my ($id, $name, $is_base) = $sth->fetchrow) {
if ($is_base == 0) {
my $domain2 = $self->search_domain_by_id($id);
if (!$domain2->is_active) {
my $req = Ravada::Request->start_domain(
uid => $uid
,name => $name
,remote_ip => $remote_ip);
}
}
}
}
sub _cmd_prepare_base {
my $self = shift;
my $request = shift;
......@@ -2887,6 +2923,7 @@ sub _req_method {
clone => \&_cmd_clone
,start => \&_cmd_start
,start_clones => \&_cmd_start_clones
,pause => \&_cmd_pause
,create => \&_cmd_create
,remove => \&_cmd_remove
......
......@@ -307,12 +307,14 @@ sub _start_preconditions{
return if $self->_search_already_started();
# if it is a clone ( it is not a base )
if ($self->id_base) {
$self->status('starting');
# $self->_set_last_vm(1)
if ( !$self->is_local && ( !$self->_vm->enabled || !$self->_vm->ping) ) {
my $vm_local = $self->_vm->new( host => 'localhost' );
$self->_set_vm($vm_local, 1);
}
$self->_balance_vm();
$self->status('starting');
$self->rsync(request => $request) if !$self->is_volatile && !$self->_vm->is_local();
} elsif (!$self->is_local) {
my $vm_local = $self->_vm->new( host => 'localhost' );
......@@ -3006,7 +3008,7 @@ Valid values are:
sub status($self, $value=undef) {
confess "ERROR: the status can't be updated on read only mode."
if $self->readonly;
my %valid_value = map { $_ => 1 } qw(active shutdown);
my %valid_value = map { $_ => 1 } qw(active shutdown starting);
confess "ERROR: invalid value '$value'" if $value && !$valid_value{$value};
return $self->_data('status', $value);
}
......
......@@ -612,6 +612,7 @@ sub start {
$set_password = 1 if $network->requires_password();
}
$self->_set_spice_ip($set_password);
$self->status('starting');
eval { $self->domain->create() };
if ( $@ && $@ !~ /already running/i ) {
if ( $self->domain->has_managed_save_image ) {
......
......@@ -543,6 +543,9 @@ msgstr ""
msgid "clones"
msgstr ""
msgid "Clones"
msgstr ""
msgid "This machine has not Graphics parameters!"
msgstr ""
......@@ -785,3 +788,6 @@ msgstr ""
msgid "Update password"
msgstr ""
msgid "Start all clones"
msgstr ""
......@@ -67,6 +67,7 @@ our %VALID_ARG = (
,domain_autostart => { id_domain => 1 , uid => 1, value => 2 }
,copy_screenshot => { id_domain => 1, filename => 2 }
,start_domain => {%$args_manage, remote_ip => 1, name => 2, id_domain => 2 }
,start_clones => { id_domain => 1, uid => 1, remote_ip => 1 }
,rename_domain => { uid => 1, name => 1, id_domain => 1}
,set_driver => {uid => 1, id_domain => 1, id_option => 1}
,hybernate=> {uid => 1, id_domain => 1}
......@@ -290,6 +291,26 @@ sub start_domain {
return $self->_new_request(command => 'start' , args => $args);
}
=head2 start_clones
Requests to start the clones of a base
my $req = Ravada::Request->start_clones( name => 'name', uid => $user->id );
=cut
sub start_clones {
my $proto = shift;
my $class=ref($proto) || $proto;
my $args = _check_args('start_clones', @_);
my $self = {};
bless($self,$class);
return $self->_new_request(command => 'start_clones' , args => encode_json($args));
}
=head2 pause_domain
Requests to pause a domain
......
......@@ -1082,7 +1082,10 @@ sub balance_vm($self, $base=undef) {
my $free_memory = $vm->free_memory;
next if $free_memory < $Ravada::Domain::MIN_FREE_MEMORY;
my $key = $vm->count_domains(status => 'active').".".$free_memory;
my $active = $vm->count_domains(status => 'active')
+ $vm->count_domains(status => 'starting');
my $key = $active.".".$free_memory;
$vm_list{$key} = $vm;
last if $key =~ /^[01]+\./; # don't look for other nodes when this one is empty !
}
......
......@@ -1613,6 +1613,13 @@ sub manage_machine {
}
}
if ($c->param("start-clones") ne "") {
my $req = Ravada::Request->start_clones(
id_domain => $domain->id,
,uid => $USER->id
,remote_ip => _remote_ip($c)
);
}
my $req = Ravada::Request->shutdown_domain(id_domain => $domain->id, uid => $USER->id)
if $c->param('shutdown') && $domain->is_active;
......
......@@ -46,6 +46,41 @@ sub test_change_owner {
$USER2->remove();
}
sub test_start_clones {
my $vm_name = shift;
my $ravada = Ravada->new(@ARG_RVD);
my $vm = $ravada->search_vm($vm_name);
ok($vm,"I can't find VM $vm_name") or return;
diag("Testing start clones");
my $name = new_domain_name();
my $user_name = $USER->id;
my $domain = $vm->create_domain(name => $name
, id_owner => $user_name
, arg_create_dom($vm_name));
my $clone1 = $domain->clone( user=>$USER, name=>new_domain_name() );
my $clone2 = $domain->clone( user=>$USER, name=>new_domain_name() );
my $clone3 = $domain->clone( user=>$USER, name=>new_domain_name() );
is($clone1->is_active,0);
is($clone2->is_active,0);
is($clone3->is_active,0);
my $req = Ravada::Request->start_clones(uid => $USER->id, id_domain => $domain->id, remote_ip => '127.0.0.1' );
rvd_back->_process_all_requests_dont_fork(); #we make sure that the sql has updated.
is($req->status,'done');
is($req->error,'');
# The first requests creates 3 more requests, process them
rvd_back->_process_all_requests_dont_fork();
is($clone1->is_active,1);
is($clone2->is_active,1);
is($clone3->is_active,1);
$clone1->remove(user_admin);
$clone2->remove(user_admin);
$clone3->remove(user_admin);
$domain->remove(user_admin);
}
sub test_vm_connect {
my $vm_name = shift;
my $host = (shift or 'localhost');
......@@ -497,6 +532,10 @@ for my $vm_name (qw( Void KVM )) {
test_search_vm($vm_name, $host, $conf);
test_change_owner($vm_name);
test_start_clones($vm_name);
test_vm_connect($vm_name);
test_search_vm($vm_name);
test_remove_domain_already_gone($vm_name);
test_create_domain_nocd($vm_name, $host);
......
......@@ -63,7 +63,11 @@
<div class="tab-pane fade" id="nav-copy" role="tabpanel" aria-labelledby="nav-copy-tab">
%= include 'main/vm_copy'
</div>
% if ( $USER->is_admin) {
<div class="tab-pane fade" id="nav-clones" >
%= include 'main/vm_clones'
</div>
% }
% if ( $USER->can_remove_machine($domain->id)) {
<div class="tab-pane fade" id="nav-remove" role="tabpanel" aria-labelledby="nav-remove-tab">
%= include 'main/vm_remove'
......
......@@ -30,6 +30,9 @@
% if ( $USER->can_remove_machine($domain->id)) {
<a class="nav-item nav-link" id="nav-remove-tab" ng-click="refresh_machine()" href="#nav-remove" data-toggle="tab" role="tab" aria-controls="nav-remove" aria-selected="false"><%=l 'Remove' %></a>
% }
% if ($USER->is_admin && $domain->is_base){
<a class="nav-item nav-link" id="nav-remove-tab" ng-click="refresh_machine()" href="#nav-clones" data-toggle="tab" role="tab" aria-controls="nav-clones" aria-selected="false"><%=l 'Clones' %></a>
% }
% if ( $monitoring && $USER->is_admin && $domain->is_active ) {
<a class="nav-item nav-link" id="nav-monitoring-tab" ng-click="refresh_machine()" href="#nav-monitoring" data-toggle="tab" role="tab" aria-controls="nav-monitoring" aria-selected="false"><%=l 'System overview' %></a>
% }
......
<div class="panel-body">
<div class="form-group">
<form class="form-inline" action="<%= $action %>" method="post">
<div class="row">
<input type="submit" id="start-clones" name="start-clones" value="<%=l 'Start all clones' %>"></input>
</div>
</form>
</div>
</div>
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