Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Projets publics
Ravada-Mirror
Commits
759c4a42
Unverified
Commit
759c4a42
authored
Apr 04, 2022
by
Francesc Guasch
Committed by
GitHub
Apr 04, 2022
Browse files
Feat: cpu settings (#1736)
featt: manage CPU and features settings closes #1726
parent
9a49862c
Changes
11
Hide whitespace changes
Inline
Side-by-side
lib/Ravada.pm
View file @
759c4a42
...
...
@@ -926,6 +926,43 @@ sub _add_domain_drivers_display($self) {
}
}
sub
_add_domain_drivers_cpu
($self) {
my
%data
=
(
'
KVM
'
=>
[
'
custom
'
,'
host-model
'
,'
host-passthrough
'
]
);
my
$id_type
=
Ravada::Utils::
max_id
(
$CONNECTOR
->
dbh
,
'
domain_drivers_types
')
+
1
;
my
$id_option
=
Ravada::Utils::
max_id
(
$CONNECTOR
->
dbh
,
'
domain_drivers_options
');
for
my
$vm
(
keys
%data
)
{
my
$type
=
{
id
=>
$id_type
,
name
=>
'
cpu
'
,
description
=>
'
CPU
'
,
vm
=>
$vm
};
$self
->
_update_table
('
domain_drivers_types
','
name,vm
',
$type
)
and
do
{
for
my
$option
(
@
{
$data
{
$vm
}}
)
{
if
(
!
ref
(
$option
))
{
$option
=
{
name
=>
$option
,
value
=>
$option
};
}
$option
->
{
value
}
=
$option
->
{
name
}
if
!
exists
$option
->
{
value
};
$option
->
{
id_driver_type
}
=
$id_type
;
$option
->
{
id
}
=
++
$id_option
;
$self
->
_update_table
('
domain_drivers_options
','
id_driver_type,name
',
$option
)
}
$id_type
++
;
};
}
}
sub
_update_domain_drivers_types
($self) {
my
$data
=
{
...
...
@@ -1299,6 +1336,7 @@ sub _update_data {
$self
->
_update_old_qemus
();
$self
->
_add_domain_drivers_display
();
$self
->
_add_domain_drivers_cpu
();
$self
->
_add_indexes
();
}
...
...
@@ -4967,6 +5005,20 @@ sub _cmd_list_machine_types($self, $request) {
$request
->
output
(
encode_json
(
\
%out
));
}
sub
_cmd_list_cpu_models
($self, $request) {
my
$id_domain
=
$request
->
args
('
id_domain
');
my
$domain
=
Ravada::
Domain
->
open
(
$id_domain
);
my
$info
=
$domain
->
get_info
();
warn
Dumper
(
$info
);
my
$vm
=
$domain
->
_vm
->
vm
;
my
@out
=
$vm
->
get_cpu_model_names
('
x86_64
');
$request
->
output
(
encode_json
(
\
@out
));
}
sub
_cmd_set_time
($self, $request) {
my
$id_domain
=
$request
->
args
('
id_domain
');
my
$domain
=
Ravada::
Domain
->
open
(
$id_domain
)
...
...
@@ -5534,6 +5586,7 @@ sub _req_method {
,
open_iptables
=>
\
&_cmd_open_iptables
,
list_vm_types
=>
\
&_cmd_list_vm_types
,
list_machine_types
=>
\
&_cmd_list_machine_types
,
list_cpu_models
=>
\
&_cmd_list_cpu_models
,
enforce_limits
=>
\
&_cmd_enforce_limits
,
force_shutdown
=>
\
&_cmd_force_shutdown
,
force_reboot
=>
\
&_cmd_force_reboot
...
...
lib/Ravada/Domain.pm
View file @
759c4a42
...
...
@@ -4388,24 +4388,10 @@ sub get_controllers($self) {
for
my
$name
(
sort
keys
%controllers
)
{
$info
->
{
$name
}
=
[
$self
->
get_controller
(
$name
)];
}
my %sub = (
);
for my $name ( sort $self->_list_hardware_common ) {
confess "Error: hardware $name already parsed in ".$self->name
if $info->{$name};
my $sub = $sub{$name} or confess "Error: no sub for $name ".Dumper(\%sub);
$info->{$name} = $sub->($self);
}
return
$info
;
}
sub _list_hardware_common($self) {
# return ('display');
}
=head2 drivers
List the drivers available for a domain. It may filter for a given type.
...
...
lib/Ravada/Domain/KVM.pm
View file @
759c4a42
...
...
@@ -90,7 +90,9 @@ our %REMOVE_CONTROLLER_SUB = (
our
%CHANGE_HARDWARE_SUB
=
(
disk
=>
\
&_change_hardware_disk
,
cpu
=>
\
&_change_hardware_cpu
,
display
=>
\
&_change_hardware_display
,
features
=>
\
&_change_hardware_features
,
vcpus
=>
\
&_change_hardware_vcpus
,
memory
=>
\
&_change_hardware_memory
,
network
=>
\
&_change_hardware_network
...
...
@@ -2775,6 +2777,103 @@ sub _fix_hw_video_args($data) {
delete
$data
->
{
acceleration
}
unless
$driver
eq
'
virtio
';
}
sub
_change_hardware_features
($self, $index, $data) {
$data
=
{
'
acpi
'
=>
1
,
'
apic
'
=>
1
,
'
kvm
'
=>
undef
,
'
hap
'
=>
0
}
if
!
keys
%$data
;
$data
->
{
kvm
}
=
{
hidden
=>
{
state
=>
'
off
'}}
if
exists
$data
->
{
kvm
}
&&
$data
->
{
kvm
}
==
1
;
lock_hash
(
%$data
);
my
$doc
=
XML::
LibXML
->
load_xml
(
string
=>
$self
->
xml_description
);
my
$count
=
0
;
my
$changed
=
0
;
my
(
$features
)
=
$doc
->
findnodes
('
/domain/features
');
for
my
$field
(
keys
%$data
)
{
next
if
$field
=~
/^_/
;
my
(
$item
)
=
$features
->
findnodes
(
$field
);
next
if
!
$item
&&
!
$data
->
{
$field
};
if
(
ref
(
$data
->
{
$field
}))
{
if
(
!
$item
)
{
$item
=
$features
->
addNewChild
(
undef
,
$field
);
$changed
++
;
}
_change_xml
(
$features
,
$field
,
$data
->
{
$field
});
$changed
++
;
}
if
(
!
$item
)
{
$item
=
$features
->
addNewChild
(
undef
,
$field
);
$changed
++
;
}
elsif
(
!
$data
->
{
$field
})
{
$features
->
removeChild
(
$item
);
$changed
++
;
}
}
$self
->
reload_config
(
$doc
)
if
$changed
;
}
sub
_default_cpu
($self) {
my
$doc
=
XML::
LibXML
->
load_xml
(
string
=>
$self
->
xml_description
);
my
(
$type
)
=
$doc
->
findnodes
("
/domain/os/type
");
my
$data
=
{
'
vcpu
'
=>
{
_text
=>
1
,
'
placement
'
=>
'
static
'}
,'
cpu
'
=>
{
'
model
'
=>
{
'
_text
'
=>
'
qemu64
'
}
}
};
my
(
$x86
)
=
$type
->
getAttribute
('
arch
')
=~
/^x86_(\d+)/
;
if
(
$x86
)
{
$data
->
{
cpu
}
=
{
'
mode
'
=>
'
custom
'
,
'
model
'
=>
{
'
_text
'
=>
'
qemu
'
.
$x86
}
};
}
else
{
warn
"
I don't know default CPU for arch
"
.
$type
->
getAttribute
()
.
"
in domain
"
.
$self
->
name
;
$data
->
{
cpu
}
=
{
'
mode
'
=>
'
host-model
'
};
}
return
$data
;
}
sub
_change_hardware_cpu
($self, $index, $data) {
$data
=
$self
->
_default_cpu
()
if
!
keys
%$data
;
lock_hash
(
%$data
);
delete
$data
->
{
cpu
}
->
{
model
}
->
{'
$$hashKey
'};
my
$doc
=
XML::
LibXML
->
load_xml
(
string
=>
$self
->
xml_description
);
my
$count
=
0
;
my
$changed
=
0
;
my
(
$n_vcpu
)
=
$doc
->
findnodes
('
/domain/vcpu/text()
');
if
(
$n_vcpu
ne
$data
->
{
vcpu
}
->
{
_text
})
{
my
(
$vcpu
)
=
$doc
->
findnodes
('
/domain/vcpu
');
$vcpu
->
removeChildNodes
();
$vcpu
->
appendText
(
$data
->
{
vcpu
}
->
{
_text
});
}
my
(
$cpu
)
=
$doc
->
findnodes
('
/domain/cpu
');
for
my
$field
(
keys
%
{
$data
->
{
cpu
}})
{
if
(
ref
(
$data
->
{
cpu
}
->
{
$field
}))
{
_change_xml
(
$cpu
,
$field
,
$data
->
{
cpu
}
->
{
$field
});
$changed
++
;
next
;
}
if
(
!
defined
$cpu
->
getAttribute
(
$field
)
||
$cpu
->
getAttribute
(
$field
)
ne
$data
->
{
cpu
}
->
{
$field
})
{
$cpu
->
setAttribute
(
$field
,
$data
->
{
cpu
}
->
{
$field
});
$changed
++
;
}
}
$self
->
reload_config
(
$doc
)
if
$changed
;
}
sub
_change_hardware_sound
($self, $index, $data) {
confess
"
Error: nothing to change
"
.
Dumper
(
$data
)
if
!
keys
%$data
;
...
...
@@ -2859,8 +2958,19 @@ sub _change_xml($xml, $name, $data) {
my
(
$node
)
=
$xml
->
findnodes
(
$name
);
$node
=
$xml
->
addNewChild
(
undef
,
$name
)
if
!
$node
;
confess
Dumper
([
$name
,
$data
])
if
!
ref
(
$data
)
||
ref
(
$data
)
ne
'
HASH
';
my
$text
=
delete
$data
->
{
_text
};
if
(
$text
)
{
$node
->
removeChildNodes
();
$node
->
appendText
(
$text
);
}
for
my
$field
(
keys
%$data
)
{
$node
->
setAttribute
(
$field
,
$data
->
{
$field
});
if
(
ref
(
$data
->
{
$field
}))
{
_change_xml
(
$node
,
$field
,
$data
->
{
$field
});
}
else
{
$node
->
setAttribute
(
$field
,
$data
->
{
$field
});
}
}
}
...
...
lib/Ravada/Front.pm
View file @
759c4a42
...
...
@@ -1524,6 +1524,38 @@ sub list_machine_types($self, $uid, $vm_type) {
return
$types
;
}
=head2 list_cpu_models
Returns a reference to a list of the CPU models
=cut
sub
list_cpu_models
($self, $uid, $id_domain) {
my
$key
=
"
list_cpu_models
";
my
$dom
=
Ravada::Front::
Domain
->
open
(
$id_domain
);
$key
.=
'
#
'
.
$dom
->
type
;
my
$cache
=
$self
->
_cache_get
(
$key
);
return
$cache
if
$cache
;
my
$req
=
Ravada::
Request
->
list_cpu_models
(
id_domain
=>
$id_domain
,
uid
=>
$uid
);
return
{}
if
!
$req
;
$self
->
wait_request
(
$req
);
return
{}
if
$req
->
status
ne
'
done
';
my
$models
=
{};
$models
=
decode_json
(
$req
->
output
())
if
$req
->
output
;
$self
->
_cache_store
(
$key
,
$models
);
return
$models
;
}
=head2 version
...
...
lib/Ravada/Front/Domain/KVM.pm
View file @
759c4a42
...
...
@@ -14,8 +14,10 @@ use feature qw(signatures);
our
%GET_CONTROLLER_SUB
=
(
usb
=>
\
&_get_controller_usb
,'
0cpu
'
=>
\
&_get_controller_cpu
,
disk
=>
\
&_get_controller_disk
,
display
=>
\
&_get_controller_display
,'
1features
'
=>
\
&_get_controller_features
,
network
=>
\
&_get_controller_network
,
video
=>
\
&_get_controller_video
,
sound
=>
\
&_get_controller_sound
...
...
@@ -105,8 +107,48 @@ sub _get_controller_generic($self,$type) {
}
sub
_get_controller_cpu
($self) {
my
$doc
=
XML::
LibXML
->
load_xml
(
string
=>
$self
->
_data_extra
('
xml
'));
my
$item
=
{
_name
=>
'
cpu
'
,
_order
=>
0
,
cpu
=>
{}
,
vcpu
=>
{}
};
my
(
$xml_cpu
)
=
$doc
->
findnodes
("
/domain/cpu
");
_xml_elements
(
$xml_cpu
,
$item
->
{
cpu
});
my
(
$xml_vcpu
)
=
$doc
->
findnodes
("
/domain/vcpu
");
_xml_elements
(
$xml_vcpu
,
$item
->
{
vcpu
});
lock_hash
(
%$item
);
return
(
$item
);
}
sub
_get_controller_features
($self) {
my
$doc
=
XML::
LibXML
->
load_xml
(
string
=>
$self
->
_data_extra
('
xml
'));
my
$item
=
{
_name
=>
'
features
'
,
_order
=>
1
};
my
(
$xml
)
=
$doc
->
findnodes
("
/domain/features
");
_xml_elements
(
$xml
,
$item
);
for
my
$feat
(
sort
qw(acpi pae apic hap kvm vmport)
)
{
$item
->
{
$feat
}
=
0
if
!
exists
$item
->
{
$feat
};
}
lock_hash
(
%$item
);
return
(
$item
);
}
sub
_xml_elements
($xml, $item) {
my
$text
=
$xml
->
textContent
;
$item
->
{
_text
}
=
$text
if
$text
&&
$text
!~
/\n/m
;
for
my
$attribute
(
$xml
->
attributes
)
{
$item
->
{
$attribute
->
name
}
=
$attribute
->
value
;
}
...
...
@@ -114,6 +156,7 @@ sub _xml_elements($xml, $item) {
for
my
$node
(
$xml
->
findnodes
('
*
')
)
{
my
$h_node
=
{};
_xml_elements
(
$node
,
$h_node
);
$h_node
=
1
if
!
keys
%$h_node
;
$item
->
{
$node
->
nodeName
}
=
$h_node
;
}
}
...
...
lib/Ravada/Request.pm
View file @
759c4a42
...
...
@@ -127,6 +127,7 @@ our %VALID_ARG = (
,
purge
=>
{
uid
=>
1
,
id_domain
=>
1
}
,
list_machine_types
=>
{
uid
=>
1
,
id_vm
=>
2
,
vm_type
=>
2
}
,
list_cpu_models
=>
{
uid
=>
1
,
id_domain
=>
1
}
#users
,
post_login
=>
{
user
=>
1
,
locale
=>
2
}
...
...
public/js/ravada.js
View file @
759c4a42
...
...
@@ -451,6 +451,7 @@
$scope
.
list_ldap_attributes
();
list_ldap_groups
();
}
$scope
.
list_cpu_models
();
};
var
list_interfaces
=
function
()
{
...
...
@@ -831,10 +832,10 @@
$scope
.
change_hardware
=
function
(
item
,
hardware
,
index
)
{
var
new_settings
=
$scope
.
showmachine
.
hardware
[
hardware
][
index
];
delete
new_settings
.
_edit
;
delete
new_settings
.
_name
;
var
hw2
=
hardware
.
replace
(
/
\d
+
(
.*
)
/
,
'
$1
'
)
;
$scope
.
request
(
'
change_hardware
'
,
{
'
id_domain
'
:
$scope
.
showmachine
.
id
,
'
hardware
'
:
h
ardware
,
'
hardware
'
:
h
w2
,
'
index
'
:
index
,
'
data
'
:
new_settings
}
...
...
@@ -963,6 +964,14 @@
list_access_groups
();
});
};
$scope
.
list_cpu_models
=
function
()
{
$http
.
get
(
"
/list_cpu_models.json?id_domain=
"
+
$scope
.
showmachineId
).
then
(
function
(
response
)
{
$scope
.
cpu_models
=
response
.
data
;
});
};
$scope
.
message
=
[];
$scope
.
disk_remove
=
[];
$scope
.
pending_before
=
10
;
...
...
script/rvd_front
View file @
759c4a42
...
...
@@ -609,6 +609,18 @@ get '/list_machine_types.json' => sub {
$c->render(json => $types);
};
get '/list_cpu_models.json' => sub {
my $c = shift;
return access_denied($c) unless _logged_in($c)
&&
$USER->can_create_machine();
my $id_domain = $c->param('id_domain');
my $models = $RAVADA->list_cpu_models($USER->id, $id_domain);
$c->render(json => $models);
};
get '/iso_file.json' => sub {
my $c = shift;
...
...
@@ -1553,6 +1565,8 @@ post '/request/(:name)/' => sub {
delete($args->{exec_sequentially});
delete($args->{at}) if ((! $args->{at}) || ($args->{at}
<
time
()));
delete
$
args-
>
{data}->{_name} if $name eq 'change_hardware';
if ($name eq 'start_clones_sequentially') {
my $domain = $RAVADA->search_domain_by_id($args->{'id_domain'}) or do {
...
...
templates/main/manage_machine_edit_cpu.html.ep
0 → 100644
View file @
759c4a42
<div ng-show="name=='0cpu' && is_edit(name,$index)">
<div class="p-2">
<label for="vcpu"><%=l 'vCPU allocation' %></label>
<input type="text" ng-model="item.vcpu._text" name="vcpu"/>
</div>
<ul class="list-group list-group-horizontal-md">
<li class="list-group-item list-group-item-primary"><%=l 'mode' %></li>
<li class="list-group-item">
<select ng-model="item.cpu.mode"
ng-options="mode.toLowerCase() for mode in showmachine.drivers['cpu']"
>
</select>
</li>
<li class="list-group-item list-group-item-primary"><%=l 'check' %></li>
<li class="list-group-item">
<select ng-model="item.cpu.check"
ng-options="check for check in ['none','partial','full']"
>
</select>
</li>
<li ng-show="item.cpu.mode=='custom'"
class="list-group-item list-group-item-primary"><%=l 'match' %></li>
<li ng-show="item.cpu.mode=='custom'"
class="list-group-item">
<select ng-model="item.cpu.match"
ng-options="match for match in ['exact','strict']"
>
</select>
</li>
</ul>
<div class="p-2" ng-show="item.cpu.mode=='custom'">
<label for="model">
<%=l 'model' %>
</label>
<select ng-model="item.cpu.model._text" name="model"
ng-options="cpu for cpu in cpu_models"
>
</select>
<label for="fallback">
<%=l 'fallback' %>
</label>
<select ng-model="item.cpu.model.fallback" name="fallback"
ng-options="option for option in ['allow','forbid']"
>
</select>
</div>
</div>
templates/main/manage_machine_edit_features.html.ep
0 → 100644
View file @
759c4a42
<div ng-show="name=='1features' && is_edit(name,$index)">
<div ng-repeat="(feat,value) in item "
ng-show="feat.substr(0,1) != '_'"
>
<b>{{feat}}:</b>
<input type="checkbox" ng-model="item[feat]"
ng-true-value="1" ng-false-value="0"
ng-show="value=='0' || value=='1'"
/>
<span ng-show="(feat=='vmport' || feat == 'hap')
&& ( value != '1' && value != '0' )">
state
<select ng-model="item[feat].state" >
<option>on</option>
<option>off</option>
</select>
</span>
<span ng-show="feat == 'kvm' && value != '1' && value != '0'">
hidden
<select ng-model="item[feat].hidden.state">
<option>on</option>
<option>off</option>
</select>
</span>
<small>
<button type="badge"
ng-show="(feat=='kvm' || feat=='hap' || feat=='vmport')
&& value !='0' && value!='1'"
ng-click="item[feat]=0"
>
<span aria-hidden="true">×</span>
</button>
</small>
</div>
</div>
templates/main/vm_hardware.html.ep
View file @
759c4a42
...
...
@@ -9,24 +9,24 @@
<div class="panel-body">
%= include "main/needs_restart"
<div ng-repeat="(name,value) in showmachine.hardware" ng-hide="show_new_disk||show_new_display">
<h2>{{name}}</h2>
<h2
ng-hide="name=='0cpu' || name=='1features'"
>{{name}}</h2>
<div ng-show="value">
<div ng-repeat="item in value track by $index"
ng-class='{"border rounded border-primary mb-4 p-4": item._edit}'
>
<button title="edit {{name}} {{$index+1}}"
ng-show="(name == 'network' ||name == 'disk' || name == 'video' || name == 'sound') && !item._edit && !item.remove"
ng-show="(name == 'network' ||name == 'disk' || name == 'video' || name == 'sound'
|| name=='0cpu' || name=='1features'
) && !item._edit && !item.remove"
ng-disabled="showmachine.requests > 0 || showmachine.is_active || showmachine.is_base"
ng-click="toggle_edit(item)"
><i class="fas fa-pencil-alt"></i>
</button>
<button title="remove {{name}} {{$index+1}}"
ng-hide="item._edit"
ng-hide="item._edit
|| name=='0cpu' || name=='1features'
"
ng-disabled="showmachine.requests > 0 || item.is_secondary || showmachine.is_active || showmachine.is_base"
ng-click="confirm_remove='';remove_hardware(name,$index,item)"><i class="fa fa-times"></i>
</button>
<span ng-class='{"h5": item._edit }'>
{{item.name || item.driver || item.type || item.model}}
{{item.name ||
item._name ||
item.driver || item.type || item.model}}
</span>
<div ng-show="name == 'disk' && item.remove"
ng-class='{"border border-danger p-4 m-4": item.device == "disk"}'
...
...
@@ -50,6 +50,8 @@
><%=l 'Cancel' %></button>
</p>
</div>
%= include 'main/manage_machine_edit_cpu'
%= include 'main/manage_machine_edit_features'
%= include 'main/manage_machine_edit_net'
%= include 'main/manage_machine_edit_video'
%= include 'main/manage_machine_edit_sound'
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment