Commit 6fe68586 authored by Francesc Guasch's avatar Francesc Guasch
Browse files

Merge branch 'robertperez-upc-add-buttons-tab' into develop

parents e7d98ccf eb77381a
......@@ -1049,6 +1049,7 @@ sub _alias_grants($self) {
my %alias= (
remove_clone => 'remove_clones'
,shutdown_clone => 'shutdown_clones'
,reboot_clone => 'reboot_clones'
);
my $sth_old = $CONNECTOR->dbh->prepare("SELECT id FROM grant_types_alias"
......@@ -1070,6 +1071,9 @@ sub _add_grants($self) {
$self->_add_grant('rename_all', 0,"Can rename any virtual machine.");
$self->_add_grant('rename_clones', 0,"Can rename clones from virtual machines owned by the user.");
$self->_add_grant('shutdown', 1,"Can shutdown own virtual machines.");
$self->_add_grant('reboot', 1,"Can reboot own virtual machines.");
$self->_add_grant('reboot_all', 0,"Can reboot all virtual machines.");
$self->_add_grant('reboot_clones', 0,"Can reboot clones own virtual machines.");
$self->_add_grant('screenshot', 1,"Can get a screenshot of own virtual machines.");
$self->_add_grant('start_many',0,"Can have more than one machine started.");
$self->_add_grant('expose_ports',0,"Can expose virtual machine ports.");
......@@ -1141,6 +1145,7 @@ sub _enable_grants($self) {
,'remove', 'remove_all', 'remove_clone', 'remove_clone_all'
,'screenshot'
,'shutdown', 'shutdown_all', 'shutdown_clone'
,'reboot', 'reboot_all', 'reboot_clones'
,'screenshot'
,'start_many'
);
......@@ -3580,6 +3585,72 @@ sub _cmd_force_shutdown {
}
sub _cmd_reboot {
my $self = shift;
my $request = shift;
my $uid = $request->args('uid');
my $name = $request->defined_arg('name');
my $id_domain = $request->defined_arg('id_domain');
my $timeout = ($request->args('timeout') or 60);
my $id_vm = $request->defined_arg('id_vm');
confess "ERROR: Missing id_domain or name" if !$id_domain && !$name;
my $domain;
if ($name) {
if ($id_vm) {
my $vm = Ravada::VM->open($id_vm);
$domain = $vm->search_domain($name);
} else {
$domain = $self->search_domain($name);
}
die "Unknown domain '$name'\n" if !$domain;
}
if ($id_domain) {
my $domain2 = Ravada::Domain->open(id => $id_domain, id_vm => $id_vm);
die "ERROR: Domain $id_domain is ".$domain2->name." not $name."
if $domain && $domain->name ne $domain2->name;
$domain = $domain2;
die "Unknown domain '$id_domain'\n" if !$domain
}
Ravada::Request->refresh_machine(
uid => $uid
,id_domain => $id_domain
,after_request => $request->id
);
my $user = Ravada::Auth::SQL->search_by_id( $uid);
$domain->reboot(timeout => $timeout, user => $user
, request => $request);
}
sub _cmd_force_reboot {
my $self = shift;
my $request = shift;
my $uid = $request->args('uid');
my $id_domain = $request->args('id_domain');
my $id_vm = $request->defined_arg('id_vm');
my $domain;
if ($id_vm) {
my $vm = Ravada::VM->open($id_vm);
$domain = $vm->search_domain_by_id($id_domain);
} else {
$domain = $self->search_domain_by_id($id_domain);
}
die "Unknown domain '$id_domain'\n" if !$domain;
my $user = Ravada::Auth::SQL->search_by_id( $uid);
$domain->force_reboot($user,$request);
}
sub _cmd_list_vm_types {
my $self = shift;
my $request = shift;
......@@ -4229,6 +4300,7 @@ sub _req_method {
,cleanup => \&_cmd_cleanup
,download => \&_cmd_download
,shutdown => \&_cmd_shutdown
,reboot => \&_cmd_reboot
,hybernate => \&_cmd_hybernate
,set_driver => \&_cmd_set_driver
,screenshot => \&_cmd_screenshot
......@@ -4249,6 +4321,7 @@ sub _req_method {
,list_vm_types => \&_cmd_list_vm_types
,enforce_limits => \&_cmd_enforce_limits
,force_shutdown => \&_cmd_force_shutdown
,force_reboot => \&_cmd_force_reboot
,rebase => \&_cmd_rebase
,refresh_storage => \&_cmd_refresh_storage
......
......@@ -632,7 +632,7 @@ Returns if the user is allowed to perform a privileged action in a virtual machi
=cut
sub can_do_domain($self, $grant, $domain) {
my %valid_grant = map { $_ => 1 } qw(change_settings shutdown rename);
my %valid_grant = map { $_ => 1 } qw(change_settings shutdown reboot rename);
confess "Invalid grant here '$grant'" if !$valid_grant{$grant};
return 0 if !$self->can_do($grant) && !$self->_domain_id_base($domain);
......@@ -735,6 +735,7 @@ sub grant_user_permissions($self,$user) {
$self->grant($user, 'remove');
$self->grant($user, 'shutdown');
$self->grant($user, 'screenshot');
$self->grant($user, 'reboot');
}
=head2 grant_operator_permissions
......
......@@ -28,6 +28,7 @@ use Ravada::Domain::Driver;
use Ravada::Utils;
our $TIMEOUT_SHUTDOWN = 20;
our $TIMEOUT_REBOOT = 20;
our $CONNECTOR;
our $MIN_FREE_MEMORY = 1024*1024;
......@@ -56,6 +57,10 @@ requires 'shutdown';
requires 'shutdown_now';
requires 'force_shutdown';
requires '_do_force_shutdown';
requires 'reboot';
requires 'reboot_now';
requires 'force_reboot';
requires '_do_force_reboot';
requires 'pause';
requires 'resume';
......@@ -107,6 +112,12 @@ has 'timeout_shutdown' => (
,default => $TIMEOUT_SHUTDOWN
);
has 'timeout_reboot' => (
isa => 'Int'
,is => 'ro'
,default => $TIMEOUT_REBOOT
);
has 'readonly' => (
isa => 'Int'
,is => 'ro'
......@@ -178,6 +189,12 @@ after 'shutdown' => \&_post_shutdown;
around 'shutdown_now' => \&_around_shutdown_now;
around 'force_shutdown' => \&_around_shutdown_now;
before 'reboot' => \&_allow_shutdown;
after 'reboot' => \&_post_reboot;
around 'reboot_now' => \&_around_reboot_now;
around 'force_reboot' => \&_around_reboot_now;
before 'remove_base' => \&_pre_remove_base;
after 'remove_base' => \&_post_remove_base;
after 'spinoff' => \&_post_spinoff;
......@@ -2254,6 +2271,8 @@ sub _post_spinoff($self) {
sub _pre_shutdown_domain {}
sub _pre_reboot_domain {}
sub _post_remove_base_domain {}
sub _remove_base_db {
......@@ -2555,6 +2574,13 @@ sub _post_shutdown {
&& !$is_active;
}
sub _post_reboot {
my $self = shift;
$self->_data(status => 'rebooted');
$self->_remove_iptables();
$self->_close_exposed_port();
}
sub _around_is_active($orig, $self) {
if (!$self->_vm) {
......@@ -2610,6 +2636,20 @@ sub _around_shutdown_now {
$self->_post_shutdown(user => $user) if $self->is_known();
}
sub _around_reboot_now {
my $orig = shift;
my $self = shift;
my $user = shift;
$self->_vm->connect;
$self->list_disks;
$self->_pre_shutdown(user => $user);
if ($self->is_active) {
$self->$orig($user);
}
$self->_post_shutdown(user => $user) if $self->is_known();
}
sub _around_name($orig,$self) {
return $self->{_name} if $self->{_name};
......@@ -3159,6 +3199,11 @@ sub _timeout_shutdown($self, $value) {
return $TIMEOUT_SHUTDOWN;
}
sub _timeout_reboot($self, $value) {
$TIMEOUT_REBOOT = $value if defined $value;
return $TIMEOUT_REBOOT;
}
sub _post_start {
my $self = shift;
my %arg;
......
......@@ -49,6 +49,7 @@ has readonly => (
##################################################
#
our $TIMEOUT_SHUTDOWN = 60;
our $TIMEOUT_REBOOT = 60;
our $OUT;
our %SET_DRIVER_SUB = (
......@@ -862,6 +863,57 @@ sub _do_force_shutdown {
warn $@ if $@;
}
=head2 reboot
Stops the domain
=cut
sub reboot {
my $self = shift;
my %args = @_;
my $req = $args{req};
if (!$self->is_active) {
$req->status("done") if $req;
$req->error("Domain is down") if $req;
return;
}
return $self->_do_force_shutdown() if $args{force};
return $self->_do_reboot();
}
sub force_reboot {
my $self = shift;
return $self->_do_force_reboot() if $self->is_active;
}
sub _do_force_reboot {
my $self = shift;
return if !$self->domain->is_active;
eval { $self->domain->reset() };
warn $@ if $@;
}
sub _do_reboot {
my $self = shift;
return if !$self->domain->is_active;
eval { $self->domain->reboot() };
die $@ if $@;
}
=head2 reboot_now
Reboots uncleanly the domain
=cut
sub reboot_now {
my $self = shift;
return $self->_do_reboot() if $self->is_active;
}
=head2 pause
......
......@@ -234,6 +234,26 @@ sub shutdown_now {
return $self->shutdown(user => $user);
}
sub reboot {
my $self = shift;
$self->_store(is_active => 0);
}
sub force_reboot {
return reboot_now(@_);
}
sub _do_force_reboot {
my $self = shift;
return $self->_store(is_active => 0);
}
sub reboot_now {
my $self = shift;
my $user = shift;
return $self->reboot(user => $user);
}
sub start($self, @args) {
my %args;
%args = @args if scalar(@args) % 2 == 0;
......
......@@ -221,20 +221,25 @@ sub list_machines($self, $user, @filter) {
sub _init_available_actions($user, $m) {
eval { $m->{can_shutdown} = $user->can_shutdown($m->{id}) };
$m->{can_start} = 0;
$m->{can_start} = 1 if $m->{id_owner} == $user->id || $user->is_admin;
$m->{can_start} = 0;
$m->{can_start} = 1 if $m->{id_owner} == $user->id || $user->is_admin;
$m->{can_view} = 0;
$m->{can_view} = 1 if $m->{id_owner} == $user->id || $user->is_admin;
$m->{can_reboot} = $m->{can_shutdown} && $m->{can_start};
$m->{can_manage} = ( $user->can_manage_machine($m->{id}) or 0);
eval {
$m->{can_change_settings} = ( $user->can_change_settings($m->{id}) or 0);
};
die $@ if $@ && $@ !~ /Unknown domain/;
$m->{can_view} = 0;
$m->{can_view} = 1 if $m->{id_owner} == $user->id || $user->is_admin;
$m->{can_hibernate} = 0;
$m->{can_hibernate} = 1 if $user->can_shutdown($m->{id}) && !$m->{is_volatile};
$m->{can_manage} = ( $user->can_manage_machine($m->{id}) or 0);
eval {
$m->{can_change_settings} = ( $user->can_change_settings($m->{id}) or 0);
};
#may have been deleted just now
next if $@ && $@ =~ /Unknown domain/;
die $@ if $@;
$m->{can_hibernate} = 0;
$m->{can_hibernate} = 1 if $user->can_shutdown($m->{id})
&& !$m->{is_volatile};
}
sub _around_list_machines($orig, $self, $user, @filter) {
......@@ -1021,8 +1026,10 @@ sub list_requests($self, $id_domain_req=undef, $seconds=60) {
|| $command eq 'manage_pools'
;
next if ( $command eq 'force_shutdown'
|| $command eq 'force_reboot'
|| $command eq 'start'
|| $command eq 'shutdown'
|| $command eq 'reboot'
|| $command eq 'hibernate'
)
&& time - $epoch_date_changed > 5
......
......@@ -68,6 +68,7 @@ sub open($self, $id) {
sub autostart($self ) { return $self->_data('autostart') }
sub _do_force_shutdown { confess "TODO" }
sub _do_force_reboot { confess "TODO" }
sub add_volume { confess "TODO" }
sub remove_volume { confess "TODO" }
sub clean_swap_volumes { confess "TODO" }
......@@ -92,6 +93,8 @@ sub display_file_tls($self, $user) {
sub force_shutdown { confess "TODO" }
sub force_reboot { confess "TODO" }
sub get_info($self) {
my $info = $self->_data('info');
return {} if !$info;
......@@ -177,6 +180,8 @@ sub set_max_mem { confess "TODO" }
sub set_memory { confess "TODO" }
sub shutdown { confess "TODO" }
sub shutdown_now { confess "TODO" }
sub reboot { confess "TODO" }
sub reboot_now { confess "TODO" }
sub spinoff { confess "TODO" }
sub start { confess "TODO" }
......
......@@ -66,6 +66,9 @@ our %VALID_ARG = (
,shutdown_domain => { name => 2, id_domain => 2, uid => 1, timeout => 2, at => 2
, id_vm => 2 }
,force_shutdown_domain => { id_domain => 1, uid => 1, at => 2, id_vm => 2 }
,reboot_domain => { name => 2, id_domain => 2, uid => 1, timeout => 2, at => 2
, id_vm => 2 }
,force_reboot_domain => { id_domain => 1, uid => 1, at => 2, id_vm => 2 }
,screenshot => { id_domain => 1 }
,domain_autostart => { id_domain => 1 , uid => 1, value => 2 }
,copy_screenshot => { id_domain => 1 }
......@@ -132,7 +135,7 @@ our %VALID_ARG = (
);
our %CMD_SEND_MESSAGE = map { $_ => 1 }
qw( create start shutdown force_shutdown prepare_base remove remove_base rename_domain screenshot download
qw( create start shutdown force_shutdown reboot prepare_base remove remove_base rename_domain screenshot download
clone
set_base_vm remove_base_vm
domain_autostart hibernate hybernate
......@@ -140,7 +143,7 @@ our %CMD_SEND_MESSAGE = map { $_ => 1 }
add_hardware remove_hardware set_driver change_hardware
expose remove_expose
rebase rebase_volumes
shutdown_node start_node
shutdown_node reboot_node start_node
);
our %CMD_NO_DUPLICATE = map { $_ => 1 }
......@@ -152,6 +155,7 @@ qw(
);
our $TIMEOUT_SHUTDOWN = 120;
our $TIMEOUT_REBOOT = 20;
our $CONNECTOR;
......@@ -495,7 +499,7 @@ sub _check_args {
Requests to stop a domain now !
my $req = Ravada::Request->shutdown_domain( name => 'name' , uid => $user->id );
my $req = Ravada::Request->force_shutdown_domain( name => 'name' , uid => $user->id );
=cut
......@@ -538,6 +542,53 @@ sub shutdown_domain {
return $self->_new_request(command => 'shutdown' , args => $args);
}
=head2 force_reboot_domain
Requests to stop a domain now !
my $req = Ravada::Request->force_reboot_domain( name => 'name' , uid => $user->id );
=cut
sub force_reboot_domain {
my $proto = shift;
my $class=ref($proto) || $proto;
my $args = _check_args('force_reboot_domain', @_ );
my $self = {};
bless($self,$class);
return $self->_new_request(command => 'force_reboot' , args => $args);
}
=head2 reboot_domain
Requests to reboot a domain
my $req = Ravada::Request->reboot_domain( name => 'name' , uid => $user->id );
my $req = Ravada::Request->reboot_domain( name => 'name' , uid => $user->id
,timeout => $timeout );
=cut
sub reboot_domain {
my $proto = shift;
my $class=ref($proto) || $proto;
my $args = _check_args('reboot_domain', @_ );
$args->{timeout} = $TIMEOUT_REBOOT if !exists $args->{timeout};
confess "ERROR: You must supply either id_domain or name ".Dumper($args)
if !$args->{id_domain} && !$args->{name};
my $self = {};
bless($self,$class);
return $self->_new_request(command => 'reboot' , args => $args);
}
=head2 new_request
Creates a new request
......
......@@ -209,8 +209,20 @@
}
};
$scope.action = function(target,action,machineId){
$http.get('/'+target+'/'+action+'/'+machineId+'.json')
$scope.getQueryStringFromObject = function(object) {
var string = '';
if (object) {
var separator = '';
for (var key in object) {
string += separator + key + '=' + escape(object[key]);
separator = '&';
}
}
return string;
};
$scope.action = function(target,action,machineId,params){
$http.get('/'+target+'/'+action+'/'+machineId+'.json'+'?'+$scope.getQueryStringFromObject(params))
.then(function() {
}, function(data,status) {
console.error('Repos error', status, data);
......
......@@ -691,6 +691,14 @@ get '/machine/force_shutdown/(:id).(:type)' => sub {
return force_shutdown_machine($c);
};
get '/machine/reboot/(:id).(:type)' => sub {
my $c = shift;
return access_denied($c) if !$USER ->can_reboot($c->stash('id'));
return reboot_machine($c);
};
any '/machine/remove/(:id).(:type)' => sub {
my $c = shift;
return access_denied($c) if !$USER->can_remove_machine($c->stash('id'));
......@@ -2258,6 +2266,17 @@ sub manage_machine {
$c->stash(domain => $domain);
$c->stash(USER => $USER);
$c->stash(ldap_attributes_cn => ( $c->session('ldap_attributes_cn') or $USER->name or ''));
my ($active_actions, $active_description, $show_actions, $show_description)
=('','','','');
if (!$domain->is_base) {
$active_actions = "active";
$show_actions = "active show";
} else {
$active_description = "active";
$show_description = "active show";
}
$c->stash(active_actions => $active_actions , show_actions => $show_actions);
$c->stash(active_description => $active_description , show_description => $show_description);
my @messages;
my @errors;
......@@ -2386,7 +2405,24 @@ sub shutdown_machine {
return login($c) if !_logged_in($c);
my ($domain, $type) = _search_requested_machine($c);
my $req = Ravada::Request->shutdown_domain(id_domain => $domain->id, uid => $USER->id);
my $req;
$req = Ravada::Request->force_shutdown_domain(id_domain => $domain->id, uid => $USER->id) if ($c->param('force'));
$req = Ravada::Request->shutdown_domain(id_domain => $domain->id, uid => $USER->id) unless ($c->param('force'));
return $c->redirect_to('/machines') if $type eq 'html';
return $c->render(json => { req => $req->id });
}
sub reboot_machine {
my $c = shift;
return login($c) if !_logged_in($c);
my ($domain, $type) = _search_requested_machine($c);
my $req;
$req = Ravada::Request->force_reboot_domain(id_domain => $domain->id, uid => $USER->id) if ($c->param('force'));;
$req = Ravada::Request->reboot_domain(id_domain => $domain->id, uid => $USER->id) unless ($c->param('force'));;
return $c->redirect_to('/machines') if $type eq 'html';
return $c->render(json => { req => $req->id });
......
......@@ -57,7 +57,7 @@ sub test_defaults {
for my $perm (user_admin->list_permissions) {
$perm = $perm->[0];
if ( $perm =~ m{^(clone|change_settings|screenshot|remove|shutdown)$}) {
if ( $perm =~ m{^(clone|change_settings|screenshot|remove|shutdown|reboot)$}) {
is($user->can_do($perm),1,$perm);
} else {
is($user->can_do($perm),undef,$perm);
......@@ -71,7 +71,7 @@ sub test_admin {
my $user = create_user("foo$$","bar",1);
ok($user->is_admin);
for my $perm ($user->list_all_permissions) {
is($user->can_do($perm->{name}),1);
is($user->can_do($perm->{name}),1,$perm->{name});
}
$user->remove();
}
......
......@@ -13,7 +13,7 @@
<div class="tab-content" id="v-pills-tabContent">
% if ($USER->can_change_settings($domain->id)) {
<div class="tab-pane fade" id="v-pills-description" role="tabpanel" aria-labelledby="v-pills-description-tab">
<div class="tab-pane fade <%= $show_description %>" id="v-pills-description" role="tabpanel" aria-labelledby="v-pills-description-tab">
%= include 'main/vm_description'
</div>
<div class="tab-pane fade" id="v-pills-rename" role="tabpanel" aria-labelledby="v-pills-rename-tab">
......@@ -52,7 +52,7 @@
</div>
% }
% if ($USER->can_change_settings($domain->id) && !$domain->is_base) {
<div class="tab-pane fade show active" id="v-pills-actions" role="tabpanel" aria-labelledby="v-pills-actions-tab" >
<div class="tab-pane fade <%= $show_actions %>" id="v-pills-actions" role="tabpanel" aria-labelledby="v-pills-actions-tab" >
%= include 'main/vm_actions'
</div>
% }
......
<div class="nav flex-column nav-pills bg-light" id="v-pills-tab" role="tablist" aria-orientation="vertical">
% if (($USER->can_change_settings($domain->id)) && !$domain->is_base) {
<a class="nav-link active" id="v-pills-actions-tab" href="#v-pills-actions" data-toggle="pill" role="tab" aria-controls="v-pills-actions" aria-selected="true"><%=l 'Actions' %></a>
<a class="nav-link <%= $active_actions %>" id="v-pills-actions-tab" href="#v-pills-actions" data-toggle="pill" role="tab" aria-controls="v-pills-actions" aria-selected="true"><%=l 'Actions' %></a>
% }
% if ($USER->can_change_settings($domain->id)) {
<a class="nav-link" id="v-pills-description-tab" ng-click="refresh_machine()" href="#v-pills-description" data-toggle="pill" role="tab" aria-controls="v-pills-description" aria-selected="false"><%=l 'Description' %></a>
<a class="nav-link <%= $active_description %>" id="v-pills-description-tab" ng-click="refresh_machine()" href="#v-pills-description" data-toggle="pill" role="tab" aria-controls="v-pills-description" aria-selected="false"><%=l 'Description' %></a>
% }
% if ($USER->can_change_settings($domain->id)) {