-
Notifications
You must be signed in to change notification settings - Fork 175
[DEVEL] Create new action request
The Ravada frontend and backend processes talk to each other through Ravada Requests. These are stored in a Database on creation. The backend checks for new requests to run.
In this example we take a simplified version of the shutdown procedure to see how it could have been implemented. Notice the real shutdown is more complicated with more checks and code, but this should be enough to get started.
Create the new request in the file lib/Ravada/Request.pm
A basic request only needs the parameter definition. More demanding request run some code before being created.
Define the request in the file lib/Ravada/Request.pm in the %VALID_ARG
hash.
Example:
shutdown => { uid => 1
, id_domain => 2
, name => 2
, timeout => 2
, at => 2
}
In this example uid is mandatory argument so we tag it with a "1", the other arguments are optional so a "2" is given to them.
That definition it is enough so the front end can create new requests this way:
Ravada::Request->shutdown( uid => $user->id, id_domain => $id_domain )
You can create a new method with the name of the request in lib/Ravada/Request.pm . Maybe to check the validity of the arguments or something else. If all is fine, in the end run this code to finally create the request in the database:
sub shutdown {
my $proto = shift;
my $class=ref($proto) || $proto;
my $args = _check_args('shutdown', @_ );
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 => 'shutdown' , args => $args);
}
To run the request add a method in lib/Ravada.pm. Also add an entry in sub _req_method
do define what method will be run for each request:
my %methods = (
...
,shutdown => \&_cmd_shutdown
When shutdown is executed it will run the method _cmd_shutdown in lib/Ravada.pm. It would be something like this:
sub _cmd_shutdown($self, $request) {
my $uid = $request->args('uid');
my $timeout = ($request->args('timeout') or 60);
my $name = $request->defined_arg('name');
my $id_domain = $request->defined_arg('id_domain');
my $domain;
$domain = Ravada::Domain->open($id_domain) if $id_domain;
$domain = $self->search_domain($name) if $name;
die "Error: No domain ".($id_domain or $name) if !$domain;
my $user = Ravada::Auth::SQL->search_by_id($uid);
die "Error: user ".$user->name." is not allowed to shutdown ".$domain->name
unless $user->is_operator || $domain->_data('id_owner') == $uid;
$domain->shutdown(timeout => $timeout, user => $user);
}
The final step of the request is executing the shutdown method in the virtual machine. To do so create the method in lib/Ravada/Domain/KVM.pm
In this case we use the Sys::Virt::Domain object that has a shutdown method we can call.
sub shutdown($self, %args) {
my $timeout = delete $args{timeout};
$self->domain->shutdown();
}
We can add modifiers for all the methods, in our example we force a shutdown if the timeout argument has been requested. Add this to lib/Ravada/Domain.pm
before 'shutdown' => \&_pre_shutdown
after 'shutdown' => \&_post_shutdown
After the shutdown is executed this code will be run for any kind of virtual machines. We call another request to force the shutdown if the timeout argument has been passed.
sub _pre_shutdown($self, %args) {
... check some stuff
}
sub _post_shutdown($self, %args) {
my $timeout = delete $args{timeout};
my $user = delete $args{user};
Ravada::Request->force_shutdown( uid => $user->id
, at => time+60
, id_domain => $self->id
)
if $timeout;
}