1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-22 13:33:52 +03:00

Feature 756 (#1664)

* F #756: Add support for CPU_MODEL.
  - new kvm monitor probe to gather model and machine types from hosts
  - generate cpu element in deployment file

* F #756: Added machine-models to install.sh

* F #756: Rename 'OS Booting' to 'OS & CPU'

* F #756: Rename 'libvirt machine' to 'machine type'

* F #756: Change 'machine type' to a drop-down

* F #756: KVM IM machines probe prioritize kvm/kqemu/qemu domain types

* F #756: Added CPU Model section
This commit is contained in:
Ruben S. Montero 2018-01-18 10:42:03 +01:00 committed by Ruben S. Montero
parent bb017685aa
commit c911ffdc8c
10 changed files with 371 additions and 60 deletions

View File

@ -1902,6 +1902,12 @@ private:
*/
int parse_os(string& error_str);
/**
* Parse the "CPU_MODEL" attribute of the template
* @return 0 on success
*/
int parse_cpu_model();
/**
* Parse the "NIC_DEFAULT" attribute
* @param error_str Returns the error reason, if any

View File

@ -785,6 +785,7 @@ IM_PROBES_KVM_PROBES_FILES="src/im_mad/remotes/kvm-probes.d/kvm.rb \
src/im_mad/remotes/kvm-probes.d/architecture.sh \
src/im_mad/remotes/kvm-probes.d/cpu.sh \
src/im_mad/remotes/kvm-probes.d/poll.sh \
src/im_mad/remotes/kvm-probes.d/machines-models.rb \
src/im_mad/remotes/kvm-probes.d/name.sh \
src/im_mad/remotes/kvm-probes.d/pci.rb \
src/im_mad/remotes/common.d/monitor_ds.sh \

View File

@ -0,0 +1,120 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'rexml/document'
require 'open3'
ENV['LANG'] = 'C'
ENV['LC_ALL'] = 'C'
GUEST_ARCHS = %w(i686 x86_64)
begin
capabilities = ""
archs = []
machines = []
models = []
Open3.popen3("virsh -r -c qemu:///system capabilities") {|i, o, e, t|
if t.value.exitstatus != 0
exit -1
end
capabilities = o.read
}
cap_xml = REXML::Document.new(capabilities)
cap_xml = cap_xml.root
GUEST_ARCHS.each { |a|
a_elem = cap_xml.elements["guest/arch[@name='#{a}']"]
next if !a_elem
# Evaluate the domain specific machines with higher priority
# over the machines listed just inside the architecture.
#
# <guest>
# <os_type>hvm</os_type>
# <arch name='x86_64'>
# <wordsize>64</wordsize>
# <emulator>/usr/bin/qemu-system-x86_64</emulator>
# <machine maxCpus='255'>pc-i440fx-2.0</machine>
# <machine canonical='pc-i440fx-2.0' maxCpus='255'>pc</machine>
# ...
# <machine maxCpus='255'>pc-1.0</machine>
# <machine maxCpus='255'>pc-0.13</machine>
# <domain type='qemu'/>
# <domain type='kvm'>
# <emulator>/usr/libexec/qemu-kvm</emulator>
# <machine maxCpus='240'>pc-i440fx-rhel7.4.0</machine>
# <machine canonical='pc-i440fx-rhel7.4.0' maxCpus='240'>pc</machine>
# ...
# <machine maxCpus='240'>rhel6.2.0</machine>
# <machine maxCpus='240'>pc-i440fx-rhel7.3.0</machine>
# </domain>
# </arch>
# ...
# </guest>
a_machines = []
['kvm', 'kqemu', 'qemu', ''].each { |type|
if type.empty?
d_elem = a_elem
else
d_elem = a_elem.elements["domain[@type='#{type}']"]
end
if d_elem
d_elem.elements.each('machine') { |m|
a_machines << m.text
}
# take only first found domain type
unless a_machines.empty?
machines.concat(a_machines)
break
end
end
}
cpu_models = ""
Open3.popen3("virsh -r -c qemu:///system cpu-models #{a}") {|i, o, e, t|
break if t.value.exitstatus != 0
cpu_models = o.read
}
cpu_models.each_line { |l|
l.chomp!
next if l.empty? or l =~ /all CPU models are accepted/i;
models << l
}
}
machines.uniq!
models.uniq!
puts "KVM_MACHINES=\"#{machines.join(' ')}\""
puts "KVM_CPU_MODELS=\"#{models.join(' ')}\""
rescue
end

View File

@ -25,6 +25,7 @@ define(function(require) {
var infrastructureWaiting = false;
var pcisCallbacks = [];
var customizationsCallbacks = [];
var kvmInfoCallbacks = [];
var CACHE_EXPIRE = 300000; //ms
@ -180,6 +181,25 @@ define(function(require) {
//console.log("Host.vcenterCustomizations. Callback queued");
_infrastructure();
},
"kvmInfo": function(params){
var callback = params.success;
var callbackError = params.error;
var request = OpenNebulaHelper.request(RESOURCE, "infrastructure");
if (infrastructureCache &&
infrastructureCache["timestamp"] + CACHE_EXPIRE > new Date().getTime()) {
return callback ?
callback(request, infrastructureCache["kvm_info"]) : null;
}
kvmInfoCallbacks.push({
success : callback,
error : callbackError
});
_infrastructure();
}
};
@ -220,10 +240,21 @@ define(function(require) {
customizations = [customizations];
}
var kvm_info = response.kvm_info;
if (kvm_info == undefined){
kvm_info = [];
}
if (!$.isArray(kvm_info)){ // If only 1 convert to array
kvm_info = [kvm_info];
}
infrastructureCache = {
timestamp : new Date().getTime(),
pcis : pcis,
customizations : customizations
customizations : customizations,
kvm_info : kvm_info
};
infrastructureWaiting = false;
@ -250,6 +281,16 @@ define(function(require) {
customizationsCallbacks = [];
for (var i = 0; i < kvmInfoCallbacks.length; i++) {
var callback = kvmInfoCallbacks[i].success;
if (callback) {
callback(request, kvm_info);
}
}
kvmInfoCallbacks = [];
return;
},
error: function(response) {

View File

@ -26,7 +26,7 @@ define(function(require) {
var WizardFields = require('utils/wizard-fields');
var FilesTable = require('tabs/files-tab/datatable');
var UniqueId = require('utils/unique-id');
var OpenNebulaHost = require('opennebula/host');
/*
TEMPLATES
*/
@ -144,7 +144,7 @@ define(function(require) {
this.wizardTabId = WIZARD_TAB_ID + UniqueId.id();
this.icon = 'fa-power-off';
this.title = Locale.tr("OS Booting");
this.title = Locale.tr("OS & CPU");
this.classes = "hypervisor only_kvm"
this.kernelFilesTable = new FilesTable(
@ -265,6 +265,48 @@ define(function(require) {
}
});
that.initrdFilesTable.refreshResourceTableSelect();
fillMachineTypesAndCPUModel();
}
function fillMachineTypesAndCPUModel(){
OpenNebulaHost.kvmInfo({
data : {},
timeout: true,
success: function (request, kvmInfo){
var m = $("#machine-type").html();
if (m === undefined){
machines = kvmInfo[0].set_kvm_machines;
var html = "<select id=\"machine-type\" wizard_field=\"MACHINE\">";
html += '<option value="">' + " " + '</option>';
$.each(machines, function(i, machine){
html += "<option value='" + machine + "'>" + machine + "</option>";
});
html += '</select>';
$("#kvm-info").append(html);
cpus = kvmInfo[0].set_cpu_models;
var html = "<select wizard_field=\"MODEL\">";
html += '<option value="">' + " " + '</option>';
html += '<option value="host-passthrough">host-passthrough</option>';
$.each(cpus, function(i, cpu){
html += "<option value='" + cpu + "'>" + cpu + "</option>";
});
html += '</select>';
$("#cpu-model").append(html);
}
},
error: function(request, error_json){
console.error("There was an error requesting the KVM info: "+
error_json.error.message);
}
});
}
function _retrieve(context) {
@ -287,6 +329,9 @@ define(function(require) {
var featuresJSON = WizardFields.retrieve('.featuresTab', context)
if (!$.isEmptyObject(featuresJSON)) { templateJSON['FEATURES'] = featuresJSON; };
var cpuModelJSON = WizardFields.retrieve('.cpuTab', context);
if (!$.isEmptyObject(cpuModelJSON)) { templateJSON['CPU_MODEL'] = cpuModelJSON; };
return templateJSON;
}
@ -316,6 +361,12 @@ define(function(require) {
WizardFields.fill(context, featuresJSON);
delete templateJSON['FEATURES'];
}
var cpuModelJSON = templateJSON['CPU_MODEL'];
if (cpuModelJSON) {
WizardFields.fill(context, cpuModelJSON);
delete templateJSON['CPU_MODEL'];
}
}
//----------------------------------------------------------------------------

View File

@ -28,6 +28,9 @@
<li class="tabs-title">
<a href="#featuresTab{{uniqueId}}">{{tr "Features"}}</a>
</li>
<li class="tabs-title">
<a href="#cpuTab{{uniqueId}}">{{tr "CPU Model"}}</a>
</li>
</ul>
</div>
<div class="medium-10 columns">
@ -45,9 +48,8 @@
</label>
</div>
<div class="medium-8 columns hypervisor only_kvm">
<label>
{{tr "libvirt machine type"}}
<input type="text" wizard_field="MACHINE"/>
<label id="kvm-info">
{{tr "machine type"}}
</label>
</div>
</div>
@ -252,6 +254,15 @@
</div>
</div>
</div>
<div class="wizard_internal_tab tabs-panel cpuTab" id="cpuTab{{uniqueId}}">
<div class="row">
<div class="medium-4 columns">
<label id="cpu-model">
{{tr "CPU Model"}}
</label>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -614,7 +614,6 @@ get '/infrastructure' do
infrastructure = {}
set = Set.new
xml = XMLElement.new
xml.initialize_xml(hpool.to_xml, 'HOST_POOL')
xml.each('HOST/HOST_SHARE/PCI_DEVICES/PCI') do |pci|
@ -636,6 +635,16 @@ get '/infrastructure' do
infrastructure[:vcenter_customizations] = set.to_a
set_cpu_models = Set.new
set_kvm_machines = Set.new
xml.each('HOST/TEMPLATE') do |kvm|
set_cpu_models += kvm['KVM_CPU_MODELS'].split(" ")
set_kvm_machines += kvm['KVM_MACHINES'].split(" ")
end
infrastructure[:kvm_info] = { :set_cpu_models => set_cpu_models.to_a, :set_kvm_machines => set_kvm_machines.to_a }
[200, infrastructure.to_json]
end

View File

@ -886,6 +886,11 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
goto error_os;
}
// ------------------------------------------------------------------------
// Check the CPU Model attribute
// ------------------------------------------------------------------------
parse_cpu_model();
// ------------------------------------------------------------------------
// PCI Devices (Needs to be parsed before network)
// ------------------------------------------------------------------------
@ -2403,58 +2408,6 @@ void VirtualMachine::get_public_clouds(const string& pname, set<string> &clouds)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::parse_public_clouds(const char * pname, string& error)
{
vector<VectorAttribute *> attrs;
vector<VectorAttribute *>::iterator it;
string * str;
string p_vatt;
int rc = 0;
int num = user_obj_template->remove(pname, attrs);
for (it = attrs.begin(); it != attrs.end(); it++)
{
str = (*it)->marshall();
if ( str == 0 )
{
ostringstream oss;
oss << "Internal error processing " << pname;
error = oss.str();
rc = -1;
break;
}
rc = parse_template_attribute(*str, p_vatt, error);
delete str;
if ( rc != 0 )
{
rc = -1;
break;
}
VectorAttribute * nvatt = new VectorAttribute(pname);
nvatt->unmarshall(p_vatt);
user_obj_template->set(nvatt);
}
for (int i = 0; i < num ; i++)
{
delete attrs[i];
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/**
* Replaces the values of a vector value, preserving the existing ones
*/

View File

@ -681,3 +681,83 @@ error_yy:
pthread_mutex_unlock(&lex_mutex);
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::parse_public_clouds(const char * pname, string& error)
{
vector<VectorAttribute *> attrs;
vector<VectorAttribute *>::iterator it;
string * str;
string p_vatt;
int rc = 0;
int num = user_obj_template->remove(pname, attrs);
for (it = attrs.begin(); it != attrs.end(); it++)
{
str = (*it)->marshall();
if ( str == 0 )
{
ostringstream oss;
oss << "Internal error processing " << pname;
error = oss.str();
rc = -1;
break;
}
rc = parse_template_attribute(*str, p_vatt, error);
delete str;
if ( rc != 0 )
{
rc = -1;
break;
}
VectorAttribute * nvatt = new VectorAttribute(pname);
nvatt->unmarshall(p_vatt);
user_obj_template->set(nvatt);
}
for (int i = 0; i < num ; i++)
{
delete attrs[i];
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::parse_cpu_model()
{
vector<VectorAttribute *> cm_attr;
vector<VectorAttribute *>::iterator it;
int num = user_obj_template->remove("CPU_MODEL", cm_attr);
if ( num == 0 )
{
return 0;
}
it = cm_attr.begin();
obj_template->set(*it);
for ( ++it; it != cm_attr.end(); ++it)
{
delete *it;
}
return 0;
}

View File

@ -111,6 +111,11 @@ int LibVirtDriver::deployment_description_kvm(
vector<string> boots;
const VectorAttribute * cpu_model_v;
string cpu_model = "";
string cpu_mode = "";
vector<const VectorAttribute *> disk;
const VectorAttribute * context;
@ -384,6 +389,40 @@ int LibVirtDriver::deployment_description_kvm(
file << "\t</os>" << endl;
// ------------------------------------------------------------------------
// CPU SECTION
// ------------------------------------------------------------------------
cpu_model_v = vm->get_template_attribute("CPU_MODEL");
if( cpu_model_v != 0 )
{
cpu_model = cpu_model_v->vector_value("MODEL");
if ( cpu_model == "host-passthrough" )
{
cpu_mode = "host-passthrough";
}
else
{
cpu_mode = "host-model";
}
//TODO #756 cache, feature
}
if ( !cpu_model.empty() )
{
file << "\t<cpu mode=" << one_util::escape_xml_attr(cpu_mode) << ">\n";
if ( cpu_mode == "host-model" )
{
file << "\t\t<model>" << one_util::escape_xml(cpu_model)
<< "</model>\n";
}
file << "\t</cpu>\n";
}
// ------------------------------------------------------------------------
// DEVICES SECTION
// ------------------------------------------------------------------------
@ -450,7 +489,7 @@ int LibVirtDriver::deployment_description_kvm(
ceph_secret = disk[i]->vector_value("CEPH_SECRET");
ceph_user = disk[i]->vector_value("CEPH_USER");
pool_name = disk[i]->vector_value("POOL_NAME");
iscsi_host = disk[i]->vector_value("ISCSI_HOST");
iscsi_user = disk[i]->vector_value("ISCSI_USER");
iscsi_usage = disk[i]->vector_value("ISCSI_USAGE");