Commit 7cbf3e4a authored by Francesc Guasch's avatar Francesc Guasch
Browse files

wip(frontend): improve machine settings

issue #1196
parent 1612c647
......@@ -585,14 +585,21 @@ Returns a reference to a list of the ISOs known by the system
=cut
sub iso_file ($self, $vm_type) {
my $cache = $self->_cache_get("list_isos");
return $cache if $cache;
my $req = Ravada::Request->list_isos(
vm_type => $vm_type
);
return [] if !$req;
$self->wait_request($req);
return [] if $req->status ne 'done';
my $isos = decode_json($req->output());
$self->_cache_store("list_isos",$isos);
return $isos;
}
......@@ -706,8 +713,6 @@ Return true if alive, false otherwise.
sub ping_backend {
my $self = shift;
return 1 if $self->_ping_backend_localhost();
my $req = Ravada::Request->ping_backend();
$self->wait_request($req, 2);
......@@ -1098,6 +1103,22 @@ sub add_node($self,%arg) {
return $req->id;
}
sub _cache_store($self, $key, $value, $timeout=60) {
$self->{cache}->{$key} = [ $value, time+$timeout ];
}
sub _cache_get($self, $key) {
delete $self->{cache}->{$key}
if exists $self->{cache}->{$key}
&& $self->{cache}->{$key}->[1] < time;
return if !exists $self->{cache}->{$key};
return $self->{cache}->{$key}->[0];
}
sub list_network_interfaces($self, %args) {
my $vm_type = delete $args{vm_type}or confess "Error: missing vm_type";
......
......@@ -553,7 +553,7 @@ sub _new_request {
$args{args} = encode_json($args{args});
}
_init_connector() if !$CONNECTOR || !$$CONNECTOR;
if ($args{command} =~ /^(clone|manage_pools)$/) {
if ($args{command} =~ /^(clone|manage_pools|list_isos)$/) {
if ( _duplicated_request($args{command}, $args{args})
|| ( $args{command} ne 'clone' && done_recently(undef, 60, $args{command}))) {
# warn "Warning: duplicated request for $args{command} $args{args}";
......
......@@ -10,6 +10,7 @@ use Moose;
no warnings "experimental::signatures";
use feature qw(signatures);
my $DEBUG=0;
has clients => (
is => 'ro'
......@@ -25,12 +26,14 @@ has ravada => (
my %SUB = (
list_alerts => \&_list_alerts
,list_isos => \&_list_isos
,list_machines => \&_list_machines
,list_machines_user => \&_list_machines_user
,list_bases_anonymous => \&_list_bases_anonymous
,list_requests => \&_list_requests
,machine_info => \&_get_machine_info
,ping_backend => \&_ping_backend
,request => \&_request
);
######################################################################
......@@ -62,6 +65,19 @@ sub _list_alerts($rvd, $args) {
return [@ret2,@ret];
}
sub _list_isos($rvd, $args) {
my ($type) = $args->{channel} =~ m{/(.*)};
$type = 'KVM' if !defined $type;
return $rvd->iso_file($type);
}
sub _request($rvd, $args) {
my ($id_request) = $args->{channel} =~ m{/(.*)};
my $req = Ravada::Request->open($id_request);
return {status => $req->status, error => $req->error};
}
sub _list_machines($rvd, $args) {
my $login = $args->{login} or die "Error: no login arg ".Dumper($args);
my $user = Ravada::Auth::SQL->new(name => $login)
......@@ -172,6 +188,7 @@ sub BUILD {
my $ret = $exec->($self->ravada, $self->clients->{$key});
my $old_ret = $self->clients->{$key}->{ret};
if ( _different($ret, $old_ret )) {
warn "WS: send $channel" if $DEBUG;
$ws_client->send( { json => $ret } );
$self->clients->{$key}->{ret} = $ret;
}
......@@ -182,6 +199,9 @@ sub BUILD {
sub subscribe($self, %args) {
my $ws = $args{ws};
my %args2 = %args;
delete $args2{ws};
warn "Subscribe ".Dumper(\%args2) if $DEBUG;
$self->clients->{$ws} = {
ws => $ws
, %args
......
......@@ -191,12 +191,30 @@
});
}
};
$scope.subscribe_ws = function(url) {
subscribe_isos = function(url) {
var ws = new WebSocket(url);
ws.onopen = function(event) { ws.send('list_isos') };
ws.onmessage = function(event) {
var data = JSON.parse(event.data);
$scope.$apply(function () {
$scope.list_isos = data;
});
}
};
subscribe_ws = function(url) {
subscribe_machine_info(url);
subscribe_requests(url);
subscribe_isos(url);
};
$scope.init = function(id) {
var url_ws;
$scope.init = function(id, url) {
url_ws = url;
$scope.showmachineId=id;
subscribe_ws(url_ws);
$http.get('/machine/info/'+$scope.showmachineId+'.json')
.then(function(response) {
$scope.showmachine=response.data;
......@@ -206,12 +224,13 @@
}
$scope.init_ldap_access();
$scope.list_ldap_attributes();
$scope.list_interfaces();
list_interfaces();
$scope.hardware_types = Object.keys(response.data.hardware);
$scope.copy_ram = $scope.showmachine.max_mem / 1024 / 1024;
});
};
$scope.list_interfaces = function() {
list_interfaces = function() {
if (! $scope.network_nats) {
$http.get('/network/interfaces/'+$scope.showmachine.type+'/nat')
.then(function(response) {
......@@ -278,11 +297,29 @@
}
};
subscribe_request = function(id_request, action) {
var ws = new WebSocket(url_ws);
ws.onopen = function(event) { ws.send('request/'+id_request) };
ws.onmessage = function(event) {
var data = JSON.parse(event.data);
action(data);
}
};
$scope.rename = function(machineId, old_name) {
if ($scope.new_name_duplicated || $scope.new_name_invalid) return;
$scope.rename_requested=1;
$scope.rename_request= { 'status': 'requested' };
$http.get('/machine/rename/'+machineId+'/'
+$scope.new_name);
+$scope.new_name).then(function(response) {
subscribe_request(response.data.req, function(data) {
$scope.$apply(function () {
$scope.rename_request=data;
});
});
});
};
$scope.cancel_rename=function(old_name) {
$scope.new_name = old_name;
......@@ -340,6 +377,7 @@
});
};
$scope.copy_machine = function() {
$scope.copy_request= { 'status': 'requested' };
$http.post('/machine/copy/'
, JSON.stringify({ 'id_base': $scope.showmachine.id
,'copy_number': $scope.copy_number
......@@ -347,6 +385,13 @@
,'new_name': $scope.new_name
})
).then(function(response) {
// if there are many , we pick the last one
id_request = response.data.request[response.data.request.length-1];
subscribe_request(id_request, function(data) {
$scope.$apply(function () {
$scope.copy_request=data;
});
});
});
};
......
......@@ -1904,7 +1904,6 @@ sub manage_machine {
$c->stash(errors => \@errors);
return $c->render(template => 'main/settings_machine'
, nodes => [$RAVADA->list_vms($domain->type)]
, isos => $RAVADA->iso_file($domain->type)
, list_clones => [map { $_->{name} } $domain->clones]
, action => $c->req->url->to_abs->path
);
......
......@@ -286,7 +286,7 @@
<i class="fa fa-desktop"></i>
</a>
</div>
<div ng-show="{{machine.is_locked}}" ng-cloak>Machine locked by <a href="/request/{{machine.is_locked}}.html"><%=l 'process' %></a></div>
<div ng-show="{{machine.is_locked}}" ng-cloak>Machine <a href="/request/{{machine.is_locked}}.html"><%=l 'locked' %></a></div>
<div ng-show="{{machine.is_base}} && !{{machine.is_locked}}"
ng-cloak><span class="badge badge-pill badge-light"><%=l 'This Machine is a base' %></span></div>
</td>
......@@ -417,7 +417,7 @@
<i class="fa fa-desktop"></i>
</a>
</div>
<div ng-show="{{child.is_locked}}" ng-cloak><%=l 'Machine locked by' %><a href="/request/{{child.is_locked}}.html"> <%=l 'process' %></a></div>
<div ng-show="{{child.is_locked}}" ng-cloak><%=l 'Machine' %> <a href="/request/{{child.is_locked}}.html"> <%=l 'locked' %></a></div>
</td>
<td class="lgMachToggle"><span class="badge badge-info" title="<%=l 'Node'%>">{{child.node}}</span></td>
</tr>
......
......@@ -43,10 +43,9 @@
<label for="file"><%=l 'ISO file' %></label>
</div>
<div class="col-lg-3">
<select name="file" ng-model="add_disk.file">
% for (@$isos) {
<option value="<%= $_ %>"><%= $_ %></option>
% }
<select name="file" ng-model="add_disk.file"
ng-options="iso for iso in list_isos"
>
</select>
</div>
</div>
......
......@@ -8,7 +8,8 @@
<!--BASES AND DOMAINS LIST-->
<div class="page-header">
<div class="card"
ng-controller="singleMachinePage" ng-init="init(<%= $id %>)">
ng-controller="singleMachinePage"
ng-init="init(<%= $id %>, '<%= url_for('ws_subscribe')->to_abs %>' )">
<div class="card-header">
% if ($domain->is_base) {
<h2><%=l 'Virtual Machine' %>
......
......@@ -33,10 +33,19 @@
<input class="form-control" ng-model="copy_ram" type="text" size="3">
</div>
</div>
<div ng-show="copy_request" class="alert alert-info">
Copy {{shownamchine.name}} {{copy_request.status}}.
<br/>
{{copy_request.error}}
</div>
<div ng-hide="copy_request && copy_request.status !== 'done'">
<button type="reset" class="btn btn-outline-secondary mr-2"><%=l 'Cancel' %></button>
<button class="btn btn-primary"
ng-click="copy_machine()"
ng-disabled="copy_number <1 || copy_number == 1 && (new_name_duplicated || new_name_invalid || new_name === showmachine.name)"><%=l 'Submit' %></button>
ng-disabled="copy_number <1 || copy_number == 1 && (new_name_duplicated || new_name_invalid || new_name === showmachine.name )
|| (copy_request && copy_request.status !== 'done')"><%=l 'Submit' %></button>
</div>
</div>
<div class="form-group has-error">
<label ng-show="copy_number==1 && new_name_duplicated"
......
......@@ -79,10 +79,9 @@
<p class="text-right"><%=l 'ISO file' %></p>
</div>
<div class="col-lg-2">
<select name="file" ng-model="item.file">
% for (@$isos) {
<option value="<%= $_ %>"><%= $_ %></option>
% }
<select name="file" ng-model="item.file"
ng-options="iso for iso in list_isos"
>
</select>
</div>
</div>
......
......@@ -7,11 +7,17 @@
<div class="alert alert-danger" role="alert" ng-show="showmachine.is_hibernated">
This machine is hibernated and can't be renamed.
</div>
<div ng-hide="pending_requests">
<input class="form-control" type="text" name="new_name" ng-model="new_name"
ng-change="validate_new_name(showmachine.name)"
ng-disabled="showmachine.is_active || showmachine.is_hibernated"
ng-disabled="showmachine.is_active || showmachine.is_hibernated
|| (rename_request && rename_request.status !== 'done')"
>
<div ng-show="rename_request" class="alert alert-info">
Rename {{shownamchine.name}} {{rename_request.status}}.
<br/>
{{rename_request.error}}
</div>
<div ng-hide="rename_request && rename_request.status !== 'done'">
<input type="reset" class="btn btn-outline-secondary mt-3" value="<%=l 'Cancel' %>" onclick = "location='/admin/machines'"/>
<button type="button" class="btn btn-primary mt-3" ng-disabled="showmachine.is_active || showmachine.is_hibernated || new_name_duplicated || new_name_invalid || message_rename"
ng-click="rename(showmachine.id, showmachine.name)">
......
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