Commit 719ecfbd authored by Francesc Guasch's avatar Francesc Guasch Committed by Fernando Verdugo
Browse files

Feature #959 linkat (#963)

* test(repository): check localized repositories

issue #959

* feature(backend): post login processing: add localized repositories

code to run after the user just logged in
adding localized repositories based on user settings

issue #959

* feature(frontend): post login

issue #959

* feature(repository): add Linkat repository

Catalan Linkat repository suggested by @pablovigo

issue #959

* feature(backend): add localized repository

issue #959

* refactor(frontend): delegate ISO files checking to backend

issue #959

* refactor(frontend): smaller ISO description

issue #959

* feature(repository): add localized repos on changing language

issue#959

* refactor(test): improve mock environment preparation

issue #959

* wip(test): clean before testing

issue #959

* feature(repository): verbose output

issue #959

* feature(frontend): load localized repos on changing language

issue #959

* feature(repository): load localized repos from CLI

issue #959

* wip(repository): help for CLI

issue #959
parent 34570d4d
......@@ -49,6 +49,8 @@ my $SHUTDOWN_DOMAIN;
my $IMPORT_DOMAIN_OWNER;
my $ADD_LOCALE_REPOSITORY;
my $USAGE = "$0 "
." [--debug] [--config=$FILE_CONFIG_DEFAULT] [--add-user=name] [--add-user-ldap=name]"
." [--change-password] [--make-admin=username] [--import-vbox=image_file.vdi]"
......@@ -65,6 +67,7 @@ my $USAGE = "$0 "
." --no-fork : start in foreground\n"
." --url-isos=(URL|default)\n"
." --import-vbox : import a VirtualBox image\n"
.' --add-locale-repository LOCALE : adds ISO repositories for this locale'
."\n"
."Operations on Virtual Machines:\n"
." --list\n"
......@@ -104,6 +107,8 @@ GetOptions ( help => \$help
,'import-domain=s' => \$IMPORT_DOMAIN
,'import-vbox=s' => \$IMPORT_VBOX
,'import-domain-owner=s' => \$IMPORT_DOMAIN_OWNER
,'add-locale-repository=s' => \$ADD_LOCALE_REPOSITORY
) or exit;
$START = 1 if $DEBUG || $FILE_CONFIG || $NOFORK;
......@@ -511,6 +516,15 @@ sub test_ldap {
exit;
}
sub add_locale_repository {
my $locale = shift;
for my $lang ( split /,/, $locale ) {
print "Adding locales for $lang.\n";
my $found = Ravada::Repository::ISO::insert_iso_locale($lang, 'verbose');
print "$found found.\n";
}
}
sub DESTROY {
}
......@@ -537,6 +551,7 @@ start_domain($START_DOMAIN) if $START_DOMAIN;
shutdown_domain($SHUTDOWN_DOMAIN, $ALL, $HIBERNATED)
if defined $SHUTDOWN_DOMAIN;
add_locale_repository($ADD_LOCALE_REPOSITORY) if $ADD_LOCALE_REPOSITORY;
}
......
name: Linkat 18.04 - 64 bits
description: Distribució educativa del Departament d'Ensenyament de Catalunya. Versió de 64 bits
url: http://download-linkat.xtec.cat/distribution/linkat-edu-18.04/iso/
file_re: linkat-edu-18.04-amd64.iso
md5_url: $url/MD5SUMS
arch: amd64
xml: bionic-amd64.xml
xml_volume: bionic64-volume.xml
min_disk_size: 19
name: Linkat Lleugera 18.04 - 64 bits
description: Distribució educativa del Departament d'Ensenyament de Catalunya. Versió lleugera de 64 bits per ordinadors amb poques prestacions
url: http://download-linkat.xtec.cat/distribution/linkat-edu-18.04/iso/
file_re: linkat-lleugera-18.04-amd64.iso
md5_url: $url/MD5SUMS
arch: amd64
xml: bionic-amd64.xml
xml_volume: bionic64-volume.xml
min_disk_size: 17
name: Linkat Lleugera 18.04 - 32 bits
description: Distribució educativa del Departament d'Ensenyament de Catalunya. Versió lleugera de 32 bits per ordinadors amb poques prestacions
url: http://download-linkat.xtec.cat/distribution/linkat-edu-18.04/iso/
file_re: linkat-lleugera-18.04-i386.iso
md5_url: $url/MD5SUMS
arch: i386
xml: bionic-i386.xml
xml_volume: bionic32-volume.xml
min_disk_size: 15
......@@ -23,6 +23,7 @@ use feature qw(signatures);
use Ravada::Auth;
use Ravada::Request;
use Ravada::Repository::ISO;
use Ravada::VM::Void;
our %VALID_VM;
......@@ -729,14 +730,17 @@ sub _update_domain_drivers_options($self) {
$self->_update_table('domain_drivers_options','id',$data);
}
sub _update_table($self, $table, $field, $data) {
sub _update_table($self, $table, $field, $data, $verbose=0) {
my $sth_search = $CONNECTOR->dbh->prepare("SELECT id FROM $table WHERE $field = ?");
for my $name (keys %$data) {
for my $name (sort keys %$data) {
my $row = $data->{$name};
$sth_search->execute($row->{$field});
my ($id) = $sth_search->fetchrow;
next if $id;
if ( $id ) {
warn("INFO: $table : $row->{$field} already added.\n") if $verbose;
next;
}
warn("INFO: updating $table : $row->{$field}\n") if $0 !~ /\.t$/;
my $sql =
......@@ -2119,6 +2123,7 @@ sub _execute {
$request->status('done') if $request->status() ne 'done'
&& $request->status !~ /retry/;
$request->error($err) if $err;
warn $err if $err;
return;
}
......@@ -2958,6 +2963,8 @@ sub _req_method {
,change_max_memory => \&_cmd_change_max_memory
,change_curr_memory => \&_cmd_change_curr_memory
#users
,post_login => \&_cmd_post_login
);
return $methods{$cmd};
}
......@@ -3133,6 +3140,26 @@ sub _clean_volatile_machines($self, %args) {
}
}
sub _cmd_post_login($self, $request) {
$self->_post_login_locale($request);
}
sub _post_login_locale($self, $request) {
return if ! $request->defined_arg('locale');
my @locales;
my $locales = $request->args('locale');
if (ref($locales)) {
@locales = @$locales;
} else {
@locales = $locales;
}
for my $locale ( @locales ) {
Ravada::Repository::ISO::insert_iso_locale($locale);
}
}
sub DESTROY($self) {
$self->{fork_manager}->reap_finished_children if $self->{fork_manager}
}
......
......@@ -534,32 +534,6 @@ sub list_iso_images {
$sth->execute;
while (my $row = $sth->fetchrow_hashref) {
push @iso,($row);
delete $row->{device} if $row->{device} && !-e $row->{device};
next if $row->{device};
my ($file);
($file) = $row->{url} =~ m{.*/(.*)} if $row->{url};
my $file_re = $row->{file_re};
next if !$file_re && !$file || !$vm_name;
$vm = $self->search_vm($vm_name) if !$vm;
next if $row->{device};
if ($file) {
my $iso_file = $vm->search_volume_path($file);
if ($iso_file) {
$row->{device} = $iso_file;
next;
}
}
if ($file_re) {
my $iso_file = $vm->search_volume_path_re(qr($file_re));
if ($iso_file) {
$row->{device} = $iso_file;
next;
}
}
}
$sth->finish;
return \@iso;
......
package Ravada::Repository::ISO;
use warnings;
use strict;
use Data::Dumper;
use YAML qw(LoadFile);
use feature qw(signatures);
no warnings "experimental::signatures";
our $DIR_ISO_YML = "etc/repository/iso";
$DIR_ISO_YML = "/var/lib/ravada/repository/iso" if $0 =~ m{^/usr/sbin};
our $CONNECTOR = \$Ravada::CONNECTOR;
sub insert_iso_yml($file, $verbose = 0) {
my $entry = LoadFile($file);
return Ravada::_update_table(undef, 'iso_images','name', { $file => $entry }, $verbose );
}
sub insert_iso_locale($locale, $verbose = 0) {
my $n_found = 0;
my $dir = "$DIR_ISO_YML/$locale";
opendir my $ls,$dir or do {
return 0;
};
while (my $file = readdir $ls) {
next if $file !~ /\.yml$/;
insert_iso_yml("$dir/$file", $verbose);
$n_found++;
}
closedir $ls;
return $n_found;
}
1;
......@@ -83,6 +83,8 @@ our %VALID_ARG = (
,enforce_limits => { timeout => 2, _force => 2 }
,refresh_machine => { id_domain => 1 }
,refresh_vms => { _force => 2 }
#users
,post_login => { uid => 1, locale => 2 }
);
our %CMD_SEND_MESSAGE = map { $_ => 1 }
......@@ -107,7 +109,7 @@ our %COMMAND = (
}
,priority => {
limit => 20
,commands => ['clone','start']
,commands => ['clone','start','create_domain','open_iptables']
}
);
lock_hash %COMMAND;
......@@ -1383,6 +1385,29 @@ sub refresh_machine {
}
sub post_login {
return _new_request_generic('post_login',@_);
}
sub _new_request_generic {
my $command = shift;
my $proto = shift;
my $class = ref($proto) || $proto;
my $args = _check_args($command, @_ );
my $self = {};
bless($self, $class);
my $req = _new_request($self
,command => $command
,args => $args
);
return $req;
}
=head2 done_recently
Returns wether this command has been requested successfully recently.
......
......@@ -322,6 +322,47 @@ Refreshes all the storage pools
sub refresh_storage($self) {
$self->_refresh_storage_pools();
$self->_refresh_isos();
}
sub _refresh_isos($self) {
$self->_init_connector();
my $sth = $$CONNECTOR->dbh->prepare(
"SELECT * FROM iso_images ORDER BY name"
);
my $sth_update = $$CONNECTOR->dbh->prepare("UPDATE iso_images set device=? WHERE id=?");
$sth->execute;
while (my $row = $sth->fetchrow_hashref) {
if ( $row->{device} && !-e $row->{device} ) {
delete $row->{device};
$sth_update->execute($row->{device}, $row->{id});
next;
}
next if $row->{device};
my ($file);
($file) = $row->{url} =~ m{.*/(.*)} if $row->{url};
my $file_re = $row->{file_re};
next if $row->{device};
if ($file) {
my $iso_file = $self->search_volume_path($file);
if ($iso_file) {
$row->{device} = $iso_file;
}
}
if (!$row->{device} && $file_re) {
my $iso_file = $self->search_volume_path_re(qr($file_re));
if ($iso_file) {
$row->{device} = $iso_file;
}
}
warn $row->{device} if $row->{device};
$sth_update->execute($row->{device}, $row->{id}) if $row->{device};
}
$sth->finish;
}
=head2 search_volume_path_re
......
......@@ -13,6 +13,8 @@ use Mojo::JSON qw(decode_json encode_json);
use Time::Piece;
#use Mojolicious::Plugin::I18N;
use Mojo::Home;
use I18N::LangTags::Detect;
#####
#my $self->plugin('I18N');
#package Ravada::I18N:en;
......@@ -972,6 +974,7 @@ sub user_settings {
if ($c->req->method('POST')) {
$USER->language($c->param('tongue'));
$changed_lang = $c->param('tongue');
Ravada::Request->post_login(uid => $USER->id, locale => $changed_lang);
_logged_in($c);
}
$c->param('tongue' => $USER->language);
......@@ -1095,7 +1098,6 @@ sub _logged_in {
sub login {
my $c = shift;
$c->session(login => undef);
my $login = $c->param('login');
......@@ -1130,6 +1132,11 @@ sub login {
my $expiration = $SESSION_TIMEOUT;
$expiration = $SESSION_TIMEOUT_ADMIN if $auth_ok->is_admin;
Ravada::Request->post_login(
uid => $auth_ok->id
, locale => [ I18N::LangTags::Detect::detect() ]
);
$c->session(expiration => $expiration);
return $c->redirect_to($url);
} else {
......
......@@ -10,6 +10,8 @@ use_ok('Ravada::VM');
use_ok('Ravada::Domain');
use_ok('Ravada::Front::Domain');
use_ok('Ravada::Repository::ISO');
my @vms = 'Void';
......
......@@ -198,24 +198,24 @@ sub new_pool_name {
return base_pool_name()."_".$CONT_POOL++;
}
sub rvd_back($config=undef) {
sub rvd_back($config=undef, $init=1) {
return $RVD_BACK if $RVD_BACK && !$config;
$RVD_BACK = 1;
init($config or $DEFAULT_CONFIG);
init($config or $DEFAULT_CONFIG) if $init;
my $rvd = Ravada->new(
connector => connector()
, config => ( $config or $DEFAULT_CONFIG)
, warn_error => 0
, warn_error => 1
);
$rvd->_install();
user_admin();
$RVD_BACK = $rvd;
$ARG_CREATE_DOM{KVM} = [ id_iso => search_id_iso('Alpine') ];
$RVD_BACK = $rvd;
return $rvd;
}
......@@ -255,7 +255,7 @@ sub init($config=undef) {
$Ravada::Domain::MIN_FREE_MEMORY = 512*1024;
rvd_back($config) if !$RVD_BACK;
rvd_back($config, 0) if !$RVD_BACK;
rvd_front($config) if !$RVD_FRONT;
$Ravada::VM::KVM::VERIFY_ISO = 0;
}
......@@ -769,6 +769,7 @@ sub remove_old_user_ldap {
sub search_id_iso {
my $name = shift;
connector() if !$CONNECTOR;
rvd_back();
my $sth = $CONNECTOR->dbh->prepare("SELECT id FROM iso_images "
." WHERE name like ?"
);
......@@ -1204,7 +1205,7 @@ sub connector {
,{sqlite_allow_multiple_statements=> 1
, AutoCommit => 1
, RaiseError => 1
, PrintError => 0
, PrintError => 1
});
_create_db_tables($connector);
......
use strict;
use warnings;
use Test::More;
use Data::Dumper;
use lib 't/lib';
use Test::Ravada;
use_ok('Ravada::Repository::ISO');
init();
##################################################################
sub test_insert_locale {
my $sth = connector->dbh->prepare("DELETE FROM iso_images WHERE name like 'Linkat %'");
$sth->execute();
my $row = $sth->fetchrow_hashref();
is($row->{name}, undef);
Ravada::Repository::ISO::insert_iso_locale('ca',1);
$sth = connector->dbh->prepare("SELECT * FROM iso_images WHERE name like 'Linkat %'");
$sth->execute();
$row = $sth->fetchrow_hashref();
like($row->{name},qr(Linkat),Dumper($row));
}
sub test_insert_request {
my $sth = connector->dbh->prepare("DELETE FROM iso_images WHERE name like 'Linkat %'");
$sth->execute();
my $row = $sth->fetchrow_hashref();
is($row->{name}, undef);
my $req = Ravada::Request->post_login( uid => user_admin->id, locale => ['en','ca'] );
rvd_back->_process_all_requests_dont_fork();
is($req->status, 'done');
is($req->error, '');
$sth = connector->dbh->prepare("SELECT * FROM iso_images WHERE name like 'Linkat %'");
$sth->execute();
$row = $sth->fetchrow_hashref();
like($row->{name},qr(Linkat));
}
sub test_download {
my $iso_name = 'linkat';
my $id_iso = search_id_iso($iso_name);
ok($id_iso) or return;
my $vm = rvd_back->search_vm('KVM');
my $iso = $vm->_search_iso($id_iso);
if ($iso->{device} && -e $iso->{device}) {
warn("$iso->{device} already downloaded");
}
my $device_cdrom = $vm->_iso_name($iso, undef, 1);
ok($device_cdrom);
my $md5 = $vm->_fetch_md5($iso);
ok($md5);
}
####################################################################
test_insert_locale();
test_insert_request();
test_download('linkat');
done_testing();
......@@ -54,6 +54,7 @@ sub test_download {
is($iso2->{rename_file}, $iso2->{filename}) if $iso2->{rename_file};
like($iso2->{device},qr'.',"Expecting something in device field ");
}
sub test_download_fail {
......
......@@ -27,8 +27,8 @@
ng-change="iso_file = change_iso(id_iso)"
required=""
></select>
<div ng-show="id_iso.description">
<i ng-bind-html="id_iso.description">{{id_iso.description}}</i>
<div class="mb-2" ng-show="id_iso.description" >
<small ng-bind-html="id_iso.description">{{id_iso.description}}</small>
</div>
<div ng-show="id_iso.name && ( !id_iso.device && id_iso.url )
&& (iso_file == '<NONE>' || !iso_file) ">
......
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