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:
parent
bb017685aa
commit
c911ffdc8c
@ -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
|
||||
|
@ -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 \
|
||||
|
120
src/im_mad/remotes/kvm-probes.d/machines-models.rb
Executable file
120
src/im_mad/remotes/kvm-probes.d/machines-models.rb
Executable 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
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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'];
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user