Commit 2a5c25c6 authored by Estefany's avatar Estefany Committed by Francesc Guasch
Browse files

Fix/1180 save screenshot database (#1207)

fix(frontend): save screenshot in database

* The screenshot is now storaged in the database and included as a JSON field
* The test has been modified according to the new functions.

fixes #1180
parent 6bc0a4a8
......@@ -1262,6 +1262,7 @@ sub _upgrade_tables {
$self->_upgrade_table('domains','is_pool','int NOT NULL default 0');
$self->_upgrade_table('domains','needs_restart','int not null default 0');
$self->_upgrade_table('domains','screenshot','BLOB');
$self->_upgrade_table('domains_network','allowed','int not null default 1');
$self->_upgrade_table('iptables','id_vm','int DEFAULT NULL');
......@@ -2487,14 +2488,11 @@ sub _cmd_screenshot {
my $id_domain = $request->args('id_domain');
my $domain = $self->search_domain_by_id($id_domain);
my $bytes = 0;
if (!$domain->can_screenshot) {
die "I can't take a screenshot of the domain ".$domain->name;
} else {
$bytes = $domain->screenshot($request->args('filename'));
$bytes = $domain->screenshot($request->args('filename')) if !$bytes;
}
$request->error("No data received") if !$bytes;
$domain->screenshot();
}
}
sub _cmd_copy_screenshot {
......
......@@ -1312,6 +1312,7 @@ sub info($self, $user) {
,pool_clones => $self->pool_clones
,is_pool => $self->is_pool
,comment => $self->_data('comment')
,screenshot => $self->_data('screenshot')
};
if ($is_active) {
eval {
......@@ -1786,6 +1787,8 @@ sub _convert_png {
$in->Scale(width => 250, height => 188);
$in->Write("png24:$file_out");
my @blobs = $in->ImageToBlob(magick => 'png');
return $blobs[0];
chmod 0755,$file_out or die "$! chmod 0755 $file_out";
}
......
......@@ -15,6 +15,7 @@ use File::Copy;
use File::Path qw(make_path);
use Hash::Util qw(lock_keys lock_hash);
use IPC::Run3 qw(run3);
use MIME::Base64;
use Moose;
use Sys::Virt::Stream;
use Sys::Virt::Domain;
......@@ -1213,13 +1214,7 @@ sub handler {
return $n;
}
sub screenshot {
my $self = shift;
my $file = (shift or $self->_file_screenshot);
my ($path) = $file =~ m{(.*)/};
make_path($path) if ! -e $path;
sub screenshot($self) {
$self->domain($self->_vm->vm->get_domain_by_name($self->name));
my $stream = $self->{_vm}->vm->new_stream();
......@@ -1229,7 +1224,9 @@ sub screenshot {
my $file_tmp = "/var/tmp/$$.tmp";
$stream->finish;
$self->_convert_png($file_tmp,$file);
my $file = "$file_tmp.png";
my $blob_file = $self->_convert_png($file_tmp,$file);
$self->_data(screenshot => encode_base64($blob_file));
unlink $file_tmp or warn "$! removing $file_tmp";
}
......
......@@ -13,6 +13,8 @@ use Hash::Util qw(lock_keys);
use IPC::Run3 qw(run3);
use Moose;
use YAML qw(Load Dump LoadFile DumpFile);
use Image::Magick;
use MIME::Base64;
use Ravada::Volume;
......@@ -450,13 +452,13 @@ sub list_volumes_info($self, $attribute=undef, $value=undef) {
sub screenshot {
my $self = shift;
my $file = (shift or $self->_file_screenshot);
my @cmd =($CONVERT,'-size', '400x300', 'xc:white'
,$file
);
my ($in,$out,$err);
run3(\@cmd, \$in, \$out, \$err);
my $DPI = 300; # 600;
my $image = Image::Magick->new(density => $DPI,width=>100, height=>100);
$image = Image::Magick->new;
$image->Set(size=>'100x100');
$image->ReadImage('canvas:white');
$image->Set('pixel[49,49]'=>'red');
$self->_data(screenshot => encode_base64($image));
}
sub _file_screenshot {
......
......@@ -132,7 +132,7 @@ sub list_machines_user {
my $user = shift;
my $sth = $CONNECTOR->dbh->prepare(
"SELECT id,name,is_public, file_screenshot"
"SELECT id,name,is_public, screenshot"
." FROM domains "
." WHERE is_base=1"
." ORDER BY name "
......@@ -169,7 +169,7 @@ sub list_machines_user {
);
}
$base{name_clone} = $clone->name;
$base{screenshot} = ( $clone->_data('file_screenshot')
$base{screenshot} = ( $clone->_data('screenshot')
or $base{screenshot});
$base{is_active} = $clone->is_active;
$base{id_clone} = $clone->id;
......
......@@ -1173,17 +1173,19 @@ sub user_settings {
get '/img/screenshots/:file' => sub {
my $c = shift;
my $file = $c->param('file');
my $path = $DOCUMENT_ROOT."/".$c->req->url->to_abs->path;
my ($id_domain) =$path =~ m{/(\d+)\..+$};
my $domain = $RAVADA->search_domain_by_id($id_domain);
my ($id_domain ) =$path =~ m{/(\d+)\..+$};
my $image = new Image::Magick;
my $sshot = $image->BlobToImage($domain->get_info()->{screenshot});
if (!$id_domain) {
warn"ERROR : no id domain in $path";
return $c->reply->not_found;
}
if ($USER && !$USER->is_admin) {
my $domain = $RAVADA->search_domain_by_id($id_domain);
#my $domain = $RAVADA->search_domain_by_id($id_domain);
return $c->reply->not_found if !$domain;
unless ($domain->is_base && $domain->is_public) {
return access_denied($c) if $USER->id != $domain->id_owner;
......
......@@ -21,6 +21,7 @@ CREATE TABLE `domains` (
, `info` varchar(255) default NULL
, `internal_id` varchar(64) DEFAULT NULL
, `needs_resetart`int not null default 0
, `screenshot` BLOB
, UNIQUE (`id_base`,`name`)
, UNIQUE (`name`)
);
......@@ -153,6 +153,24 @@ sub test_start {
}
sub test_screenshot_db {
my $vm_name = shift;
my $domain_name = shift;
my $domain = $RAVADA->search_domain($domain_name);
$domain->start($USER) if !$domain->is_active();
return if !$domain->can_screenshot();
sleep 2;
$domain->screenshot();
$domain->shutdown(user => $USER, timeout => 1);
my $sth = connector->dbh->prepare("SELECT screenshot FROM domains WHERE id=?");
$sth->execute($domain->id);
my @fields = $sth->fetchrow;
ok($fields[0]);
}
sub test_screenshot {
my $vm_name = shift;
my $domain_name = shift;
......@@ -247,8 +265,7 @@ for my $vm_name (qw(KVM Void)) {
my $domain_name = $domain->name;
$domain = undef;
test_screenshot($vm_name, $domain_name);
test_screenshot_file($vm_name, $domain_name);
test_screenshot_db($vm_name, $domain_name);
};
}
clean();
......
......@@ -367,37 +367,19 @@ sub test_json {
}
sub test_screenshot {
sub test_screenshot_db {
my $vm_name = shift;
my $domain= shift;
return if !$domain->can_screenshot;
my $file = "/var/tmp/screenshot.$$.png";
# diag("[$vm_name] testing screenshot");
$domain->start($USER) if !$domain->is_active;
sleep 2;
eval { $domain->screenshot($file) };
ok(!$@,"[$vm_name] $@");
$domain->screenshot();
$domain->shutdown(user => $USER, timeout => 1);
ok(-e $file,"[$vm_name] Checking screenshot $file");
ok(-e $file && -s $file,"[$vm_name] Checking screenshot $file should not be empty")
and do {
unlink $file or die "$! unlinking $file";
};
}
sub test_screenshot_file {
my $vm_name = shift;
my $domain= shift;
return if !$domain->can_screenshot;
my $file = $domain->_file_screenshot();
ok($file,"Expecting a screnshot filename, got '".($file or '<UNDEF>'));
my $sth = connector->dbh->prepare("SELECT screenshot FROM domains WHERE id=?");
$sth->execute($domain->id);
my @fields = $sth->fetchrow;
#ok($fields[0],"Expecting child node listen , got :'".substr( $fields[0], 0, 10 ) or ''));
ok($fields[0]);
}
sub test_change_interface {
......@@ -594,14 +576,13 @@ for my $vm_name ( vm_names() ) {
test_json($vm_name, $domain->name);
test_search_domain($domain);
test_screenshot_file($vm_name, $domain);
test_remove_domain($vm_name, $clone1);
test_remove_domain($vm_name, $clone2);
$domain->remove_base($USER);
test_manage_domain($vm_name, $domain);
test_screenshot($vm_name, $domain);
test_screenshot_db($vm_name, $domain);
test_shutdown_suspended_domain($vm_name, $domain);
test_pause_domain($vm_name, $domain);
......
......@@ -23,9 +23,9 @@
role="button">{{machine.name}}</a>
<i ng-show="!machine.is_public"><i class="far fa-eye-slash fa-xs" title="<%=l 'not public' %>"></i></i>
</h3>
<a ng-show="machine.screenshot" href="/machine/clone/{{machine.id}}.html"><img
ng-src="{{machine.screenshot}}" class="img-thumbnail" width="260"
alt="{{machine.description}}"></a>
<a ng-show="machine.screenshot" href="/machine/clone/{{machine.id}}.html"><img
ng-src="data:image/png;base64,{{machine.screenshot}}" alt="{{machine.description}}" class="img-thumbnail" width="260"
></a>
<a ng-show="!machine.screenshot" href="/machine/clone/{{machine.id}}.html"><img
src="/img/default_screenshot.png" class="screenshot-default img-thumbnail"
alt="{{machine.description}}"
......
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