Commit 243df982 authored by Francesc Guasch's avatar Francesc Guasch
Browse files

Merge branch 'master' into develop

parents 537fae11 61123c77
......@@ -3,19 +3,12 @@
**Implemented enhancements:**
- Remote nodes support
- Shared storage remote nodes [\#1014]
- Manage Network interfaces [\#1011]
- New permission to rename the machine [\#986]
- Manage CDROM [\#973]
- Start and Stop nodes [\#953]
- Shutdown machines when disabling node enhancement [\#947]
- Upgrade Bootstrap to 4.x [\#886]
- Allow volatile machines in remote nodes [#865]
- Remote machines sync back with no shared storage [\#583]
- Add more storage to a VM [\#495]
- Sync clock after hibernate [\#466]
- Show the Internal IP [\#465]
- Support TLS encryption channels in SPICE [\#249]
- Allow add volumes to a virtual machine [\#198]
- Check free disk space [\#10]
- Add ISO for Debian Buster [\#1108]
- non-predictable MAC addresses [\#1103]
- first login fails after inactivity logout [\#1102]
**Bugfixes**
- Specified key was too long with MariaDB 10.1 in Debian [\#1104]
- Login name with spaces [\#1100]
- Volatile domains get invalid SPICE IP [\#1099]
......@@ -3,7 +3,7 @@ package Ravada;
use warnings;
use strict;
our $VERSION = '0.4.4';
our $VERSION = '0.4.7';
use Carp qw(carp croak);
use Data::Dumper;
......@@ -2475,7 +2475,15 @@ sub _can_fork {
my $type = $req->type;
my $n_pids = scalar(keys %{$self->{pids}->{$type}});
return 1 if !$self->{pids}->{$type};
my %reqs = %{$self->{pids}->{$type}};
for my $pid (keys %reqs) {
my $id_req = $reqs{$pid};
my $request = Ravada::Request->open($id_req);
delete $reqs{$pid} if !$request || $request->status eq 'done';
}
my $n_pids = scalar(keys %reqs);
return 1 if $n_pids <= $req->requests_limit();
my $msg = $req->command
......@@ -2998,9 +3006,9 @@ sub _cmd_refresh_vms($self, $request=undef) {
$self->_refresh_disabled_nodes( $request );
$self->_refresh_down_nodes( $request );
my ($active_domain, $active_vm) = $self->_refresh_active_domains($request);
my $active_vm = $self->_refresh_active_vms();
my $active_domain = $self->_refresh_active_domains($request);
$self->_refresh_down_domains($active_domain, $active_vm);
$self->_remove_unnecessary_downs();
$self->_clean_requests('refresh_vms', $request);
$self->_refresh_volatile_domains();
......@@ -3095,11 +3103,15 @@ sub _cmd_list_isos($self, $request){
$request->output(encode_json(\@isos));
}
sub _clean_requests($self, $command, $request=undef) {
sub _clean_requests($self, $command, $request=undef, $status='requested') {
my $query = "DELETE FROM requests "
." WHERE command=? "
." AND status='requested'";
." AND status=?";
if ($status eq 'done') {
my $date= Time::Piece->localtime(time - 300);
$query .= " AND date_changed < ".$CONNECTOR->dbh->quote($date->ymd." ".$date->hms);
}
if ($request) {
confess "Wrong request" if !ref($request) || ref($request) !~ /Request/;
$query .= " AND id <> ?";
......@@ -3107,21 +3119,16 @@ sub _clean_requests($self, $command, $request=undef) {
my $sth = $CONNECTOR->dbh->prepare($query);
if ($request) {
$sth->execute($command, $request->id);
$sth->execute($command, $status, $request->id);
} else {
$sth->execute($command);
$sth->execute($command, $status);
}
}
sub _refresh_active_domains($self, $request=undef) {
my $id_domain;
$id_domain = $request->defined_arg('id_domain') if $request;
sub _refresh_active_vms ($self) {
my %active_domain;
my %active_vm;
for my $vm ($self->list_vms) {
$request->status('working',"checking active domains on ".$vm->name)
if $request;
if ( !$vm->enabled() || !$vm->is_active ) {
$vm->shutdown_domains();
$active_vm{$vm->id} = 0;
......@@ -3129,21 +3136,30 @@ sub _refresh_active_domains($self, $request=undef) {
next;
}
$active_vm{$vm->id} = 1;
}
return \%active_vm;
}
sub _refresh_active_domains($self, $request=undef) {
my $id_domain;
$id_domain = $request->defined_arg('id_domain') if $request;
my %active_domain;
if ($id_domain) {
my $domain = $vm->search_domain_by_id($id_domain);
$self->_refresh_active_domain($vm, $domain, \%active_domain) if $domain;
my $domain = $self->search_domain_by_id($id_domain);
$self->_refresh_active_domain($domain, \%active_domain) if $domain;
} else {
my @domains;
eval { @domains = $vm->list_domains };
eval { @domains = $self->list_domains };
warn $@ if $@;
for my $domain (@domains) {
next if $active_domain{$domain->id};
next if $domain->is_hibernated;
$self->_refresh_active_domain($vm, $domain, \%active_domain);
$self->_refresh_active_domain($domain, \%active_domain);
$self->_remove_unnecessary_downs($domain) if !$domain->is_active;
}
}
}
return \%active_domain, \%active_vm;
return \%active_domain;
}
sub _refresh_down_nodes($self, $request = undef ) {
......@@ -3180,7 +3196,7 @@ sub _refresh_disabled_nodes($self, $request = undef ) {
$sth->finish;
}
sub _refresh_active_domain($self, $vm, $domain, $active_domain) {
sub _refresh_active_domain($self, $domain, $active_domain) {
return if $domain->is_hibernated();
my $is_active = $domain->is_active();
......@@ -3188,9 +3204,6 @@ sub _refresh_active_domain($self, $vm, $domain, $active_domain) {
my $status = 'shutdown';
if ( $is_active ) {
$status = 'active';
$domain->_data(id_vm => $vm->id)
if !defined$domain->_data('id_vm')
|| $domain->_data('id_vm') != $vm->id;
}
$domain->_set_data(status => $status);
$domain->info(Ravada::Utils::user_daemon) if $is_active;
......@@ -3223,16 +3236,13 @@ sub _refresh_down_domains($self, $active_domain, $active_vm) {
}
}
sub _remove_unnecessary_downs($self, @domains) {
@domains = $self->list_domains( active => 0 ) if !scalar @domains;
sub _remove_unnecessary_downs($self, $domain) {
for my $domain (@domains) {
my @requests = $domain->list_requests(1);
for my $req (@requests) {
$req->status('done') if $req->command =~ /shutdown/;
$req->_remove_messages();
}
}
}
sub _refresh_volatile_domains($self) {
......@@ -3294,6 +3304,9 @@ sub _cmd_set_base_vm {
sub _cmd_cleanup($self, $request) {
$self->_clean_volatile_machines( request => $request);
$self->_clean_requests('cleanup', $request);
$self->_clean_requests('cleanup', $request,'done');
$self->_clean_requests('enforce_limits', $request,'done');
$self->_clean_requests('refresh_vms', $request,'done');
$self->_wait_pids();
}
......@@ -3334,7 +3347,6 @@ sub _req_method {
,rebase_volumes => \&_cmd_rebase_volumes
,refresh_storage => \&_cmd_refresh_storage
,refresh_machine => \&_cmd_refresh_machine
,refresh_vms => \&_cmd_refresh_vms
,domain_autostart=> \&_cmd_domain_autostart
,change_owner => \&_cmd_change_owner
,add_hardware => \&_cmd_add_hardware
......
......@@ -99,6 +99,16 @@ ravadaApp.directive("solShowMachine", swMach)
$scope.seeswap = !($scope.seeswap);
};
$scope.get_machine_info = function(id) {
$http.get('/machine/info/'+id+'.json')
.then( function(response) {
$scope.machine = response.data;
$scope.ramsize = ($scope.machine.max_mem / 1024 / 1024);
if ( $scope.ramsize <1 ) {
$scope.ramsize = 1;
}
});
};
$http.get('/list_machines.json').then(function(response) {
$scope.base = response.data;
......
......@@ -255,6 +255,11 @@ any '/new_machine' => sub {
return new_machine($c);
};
any '/copy_machine' => sub {
my $c = shift;
return new_machine_copy($c);
};
get '/domain/new.html' => sub {
my $c = shift;
......@@ -2095,6 +2100,24 @@ sub copy_machine {
return $c->render(json => { request => [map { $_->id } @ reqs ] } );
}
sub new_machine_copy($c) {
my $id_base = $c->param('src_machine');
my $copy_name = $c->param('copy_name');
my $ram = $c->param('copy_ram');
$ram = 0 if !$ram || $ram !~ /^\d+(\.\d+)?$/;
$ram = int($ram*1024*1024);
my $req = Ravada::Request->clone(
uid => $USER->id
,id_domain => $id_base
,name => $copy_name
,memory => $ram
);
return $c->redirect_to("/admin/machines");
}
sub copy_machine_many($base, $number, $create_args) {
my $domains = $RAVADA->list_domains;
my %domain_exists = map { $_->{name} => 1 } @$domains;
......
......@@ -26,6 +26,7 @@
<li>Pascal Scholz</li>
<li>Raghav Mittal</li>
<li>Robert-André Mauchin</li>
<li>Roger Ferre</li>
<li>Sandra Marsà</li>
<li>Sanjiv Lobo</li>
<li>Shobhit Srivastava</li>
......
<div class="tab-pane fade" id="frommachine" role="tabpanel">
<div class="card-body">
<form class="form" method="post" action="/machine/copy">
<form name="new_machine_other_form"
role="form" method="post" action="/copy_machine" novalidate>
<div class="form-group row">
<input class="form-control" type="hidden" name="id_base" value="{{src_machine.id}}">
<label for="src_machine" class="col-xl-3 col-form-label"><%=l 'Source Machine' %></label>
......@@ -8,8 +9,9 @@
<select class="form-control"
name ="src_machine"
ng-model="src_machine"
ng-options="item.name for item in base track by item.id"
ng-options="item.name for item in base | orderBy:'name' track by item.id "
required=""
ng-change="get_machine_info(src_machine.id)"
></select>
</div>
</div>
......@@ -21,10 +23,13 @@
</div>
<div class="form-group row">
<div class="col-xl-2">
<label class="col-xl-12 text-muted" for="copy_name_{{src_machine.id}}"><%=l 'Name' %>:</label>
<label class="col-xl-12 text-muted" for="copy_name"><%=l 'Name' %>:</label>
</div>
<div class="col-xl-10">
<input class="form-control" name="copy_name_{{src_machine.id}}" type="text" size="40"
<input class="form-control" name="copy_name" type="text" size="40"
ng-model="name"
ng-pattern ="/^[a-zA-Z0-9_-]+$/"
ng-change="validate_new_name()"
value="{{src_machine.name}}-copy">
<!-- todo check unique name -->
</div>
......@@ -34,8 +39,10 @@
<label class="col-xl-12 text-muted" for="copy_ram">RAM (Gb):</label>
</div>
<div class="col-xl-2">
<input class="form-control" ng-model="ramsize" type="number" name="copy_ram"
min="1" max="4" required="">
<input class="form-control" ng-model="ramsize" type="text"
ng-pattern ="/^[0-9]+\.?[0-9]*$/"
name="copy_ram"
required="">
</div>
</div>
<div class="form-group row alert alert-warning"
......@@ -44,11 +51,24 @@
prepared before it can be copied. This
process may take some minutes.
</div>
<div ng-show="name_duplicated" class="form-group row alert alert-danger"
role="alert">
<strong><%=l 'Error' %> : </strong> <%=l 'A machine with that name already exists.' %>
</div>
<div ng-show="new_machine_other_form.copy_name.$error.pattern"
class="form-group row alert alert-danger" role="alert">
<strong><%=l 'Error' %> : </strong> <%=l 'The machine name must contain only alphabetic, numbers, undercores and dashes.' %>
</div>
<div class="form-group row">
<button type="reset" class="btn btn-outline-secondary mr-2" onclick = "location='/admin/machines'"><%=l 'Cancel' %></button>
<input type="submit" class="btn btn-primary" value="<%=l 'Submit' %>">
<input type="submit" class="btn btn-primary" value="<%=l 'Submit' %>"
ng-disabled="new_machine_other_form.$invalid || name_duplicated"
>
</div>
</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