mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-30 22:50:10 +03:00
F #3256: NUMA information in Sunstone
This commit is contained in:
parent
35cfaf5e68
commit
8ebb79ef74
@ -259,6 +259,7 @@ tabs:
|
||||
Template.unlock: true
|
||||
Template.edit_labels: true
|
||||
Template.menu_labels: true
|
||||
Template.numa: true
|
||||
template_creation_tabs:
|
||||
general: true
|
||||
storage: true
|
||||
@ -272,6 +273,7 @@ tabs:
|
||||
hybrid: true
|
||||
vmgroup: true
|
||||
other: true
|
||||
numa: true
|
||||
oneflow-templates-tab:
|
||||
panel_tabs:
|
||||
service_template_info_tab: true
|
||||
@ -530,6 +532,7 @@ tabs:
|
||||
host_zombies_tab: true
|
||||
host_esx_tab: true
|
||||
host_pci_tab: true
|
||||
host_numa_tab: true
|
||||
table_columns:
|
||||
- 0 # Checkbox
|
||||
- 1 # ID
|
||||
|
@ -258,6 +258,7 @@ tabs:
|
||||
Template.unlock: true
|
||||
Template.edit_labels: true
|
||||
Template.menu_labels: true
|
||||
Template.numa: true
|
||||
template_creation_tabs:
|
||||
general: true
|
||||
storage: true
|
||||
@ -271,6 +272,7 @@ tabs:
|
||||
hybrid: true
|
||||
vmgroup: true
|
||||
other: true
|
||||
numa: true
|
||||
oneflow-templates-tab:
|
||||
panel_tabs:
|
||||
service_template_info_tab: true
|
||||
@ -531,6 +533,7 @@ tabs:
|
||||
host_zombies_tab: true
|
||||
host_esx_tab: true
|
||||
host_pci_tab: true
|
||||
host_numa_tab: true
|
||||
table_columns:
|
||||
- 0 # Checkbox
|
||||
- 1 # ID
|
||||
|
@ -251,6 +251,7 @@ tabs:
|
||||
Template.unlock: true
|
||||
Template.edit_labels: true
|
||||
Template.menu_labels: true
|
||||
Template.numa: true
|
||||
template_creation_tabs:
|
||||
general: true
|
||||
storage: true
|
||||
@ -264,6 +265,7 @@ tabs:
|
||||
hybrid: true
|
||||
vmgroup: true
|
||||
other: true
|
||||
numa: true
|
||||
oneflow-templates-tab:
|
||||
panel_tabs:
|
||||
service_template_info_tab: true
|
||||
@ -524,6 +526,7 @@ tabs:
|
||||
host_zombies_tab: true
|
||||
host_esx_tab: true
|
||||
host_pci_tab: true
|
||||
host_numa_tab: true
|
||||
table_columns:
|
||||
- 0 # Checkbox
|
||||
- 1 # ID
|
||||
|
@ -259,6 +259,7 @@ tabs:
|
||||
Template.unlock: true
|
||||
Template.edit_labels: true
|
||||
Template.menu_labels: true
|
||||
Template.numa: true
|
||||
template_creation_tabs:
|
||||
general: true
|
||||
storage: true
|
||||
@ -272,6 +273,7 @@ tabs:
|
||||
hybrid: true
|
||||
vmgroup: true
|
||||
other: true
|
||||
numa: true
|
||||
oneflow-templates-tab:
|
||||
panel_tabs:
|
||||
service_template_info_tab: true
|
||||
@ -532,6 +534,7 @@ tabs:
|
||||
host_zombies_tab: true
|
||||
host_esx_tab: true
|
||||
host_pci_tab: true
|
||||
host_numa_tab: true
|
||||
table_columns:
|
||||
- 0 # Checkbox
|
||||
- 1 # ID
|
||||
|
@ -258,6 +258,7 @@ tabs:
|
||||
Template.unlock: true
|
||||
Template.edit_labels: true
|
||||
Template.menu_labels: true
|
||||
Template.numa: true
|
||||
template_creation_tabs:
|
||||
general: true
|
||||
storage: true
|
||||
@ -271,6 +272,7 @@ tabs:
|
||||
hybrid: true
|
||||
vmgroup: true
|
||||
other: true
|
||||
numa: true
|
||||
oneflow-templates-tab:
|
||||
panel_tabs:
|
||||
service_template_info_tab: true
|
||||
@ -531,6 +533,7 @@ tabs:
|
||||
host_zombies_tab: true
|
||||
host_esx_tab: true
|
||||
host_pci_tab: true
|
||||
host_numa_tab: true
|
||||
table_columns:
|
||||
- 0 # Checkbox
|
||||
- 1 # ID
|
||||
|
@ -251,6 +251,7 @@ tabs:
|
||||
Template.unlock: true
|
||||
Template.edit_labels: true
|
||||
Template.menu_labels: true
|
||||
Template.numa: true
|
||||
template_creation_tabs:
|
||||
general: true
|
||||
storage: true
|
||||
@ -264,6 +265,7 @@ tabs:
|
||||
hybrid: true
|
||||
vmgroup: true
|
||||
other: true
|
||||
numa: true
|
||||
oneflow-templates-tab:
|
||||
panel_tabs:
|
||||
service_template_info_tab: true
|
||||
@ -524,6 +526,7 @@ tabs:
|
||||
host_zombies_tab: true
|
||||
host_esx_tab: true
|
||||
host_pci_tab: true
|
||||
host_numa_tab: true
|
||||
table_columns:
|
||||
- 0 # Checkbox
|
||||
- 1 # ID
|
||||
|
@ -257,6 +257,7 @@ tabs:
|
||||
Template.unlock: false
|
||||
Template.edit_labels: true
|
||||
Template.menu_labels: true
|
||||
Template.numa: true
|
||||
template_creation_tabs:
|
||||
general: true
|
||||
storage: true
|
||||
@ -270,6 +271,7 @@ tabs:
|
||||
hybrid: true
|
||||
vmgroup: true
|
||||
other: true
|
||||
numa: true
|
||||
oneflow-templates-tab:
|
||||
panel_tabs:
|
||||
service_template_info_tab: true
|
||||
@ -530,6 +532,7 @@ tabs:
|
||||
host_zombies_tab: true
|
||||
host_esx_tab: true
|
||||
host_pci_tab: true
|
||||
host_numa_tab: true
|
||||
table_columns:
|
||||
- 0 # Checkbox
|
||||
- 1 # ID
|
||||
|
@ -258,6 +258,7 @@ tabs:
|
||||
Template.unlock: true
|
||||
Template.edit_labels: true
|
||||
Template.menu_labels: true
|
||||
Template.numa: true
|
||||
template_creation_tabs:
|
||||
general: true
|
||||
storage: true
|
||||
@ -271,6 +272,7 @@ tabs:
|
||||
hybrid: true
|
||||
vmgroup: true
|
||||
other: true
|
||||
numa: true
|
||||
oneflow-templates-tab:
|
||||
panel_tabs:
|
||||
service_template_info_tab: true
|
||||
@ -531,6 +533,7 @@ tabs:
|
||||
host_zombies_tab: true
|
||||
host_esx_tab: true
|
||||
host_pci_tab: true
|
||||
host_numa_tab: true
|
||||
table_columns:
|
||||
- 0 # Checkbox
|
||||
- 1 # ID
|
||||
|
@ -251,6 +251,7 @@ tabs:
|
||||
Template.unlock: true
|
||||
Template.edit_labels: true
|
||||
Template.menu_labels: true
|
||||
Template.numa: true
|
||||
template_creation_tabs:
|
||||
general: true
|
||||
storage: true
|
||||
@ -264,6 +265,7 @@ tabs:
|
||||
hybrid: true
|
||||
vmgroup: true
|
||||
other: true
|
||||
numa: true
|
||||
oneflow-templates-tab:
|
||||
panel_tabs:
|
||||
service_template_info_tab: true
|
||||
@ -524,6 +526,7 @@ tabs:
|
||||
host_zombies_tab: true
|
||||
host_esx_tab: true
|
||||
host_pci_tab: true
|
||||
host_numa_tab: true
|
||||
table_columns:
|
||||
- 0 # Checkbox
|
||||
- 1 # ID
|
||||
|
@ -434,7 +434,9 @@ define(function(require) {
|
||||
|
||||
return ""+id;
|
||||
},
|
||||
|
||||
"get_all_cache": function() {
|
||||
return listCache;
|
||||
},
|
||||
"clear_cache": _clearCache
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,8 @@ define(function(require) {
|
||||
require('./hosts-tab/panels/wilds'),
|
||||
require('./hosts-tab/panels/zombies'),
|
||||
require('./hosts-tab/panels/esx'),
|
||||
require('./hosts-tab/panels/pci')
|
||||
require('./hosts-tab/panels/pci'),
|
||||
require('./hosts-tab/panels/numa')
|
||||
];
|
||||
|
||||
var _panelsHooks = [
|
||||
|
217
src/sunstone/public/app/tabs/hosts-tab/panels/numa.js
Normal file
217
src/sunstone/public/app/tabs/hosts-tab/panels/numa.js
Normal file
@ -0,0 +1,217 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2019, 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
define(function(require) {
|
||||
/*
|
||||
DEPENDENCIES
|
||||
*/
|
||||
var ProgressBar = require('utils/progress-bar');
|
||||
var Humanize = require('utils/humanize');
|
||||
var Sunstone = require('sunstone');
|
||||
var TemplateUtils = require('utils/template-utils');
|
||||
|
||||
/*
|
||||
TEMPLATES
|
||||
*/
|
||||
|
||||
var TemplateNUMA = require('hbs!./numa/html');
|
||||
|
||||
/*
|
||||
CONSTANTS
|
||||
*/
|
||||
|
||||
var PANEL_ID = require('./numa/panelId');
|
||||
var RESOURCE = "Host";
|
||||
var SELECT_ID = "numa-pinned-host";
|
||||
|
||||
/*
|
||||
CONSTRUCTOR
|
||||
*/
|
||||
|
||||
function Panel(info) {
|
||||
this.title = Locale.tr("Numa");
|
||||
this.icon = "fa-chart-pie";
|
||||
this.element = info[RESOURCE.toUpperCase()];
|
||||
return this;
|
||||
};
|
||||
|
||||
Panel.PANEL_ID = PANEL_ID;
|
||||
Panel.prototype.html = _html;
|
||||
Panel.prototype.setup = _setup;
|
||||
Panel.prototype.onShow = _onShow;
|
||||
|
||||
return Panel;
|
||||
|
||||
/*
|
||||
FUNCTION DEFINITIONS
|
||||
*/
|
||||
|
||||
function _html() {
|
||||
return TemplateNUMA();
|
||||
}
|
||||
|
||||
function _onShow(context){
|
||||
var that = this;
|
||||
$("#"+SELECT_ID).change(function(e){
|
||||
if(that.element && that.element.ID && that.element.TEMPLATE){
|
||||
var template = $.extend({}, that.element.TEMPLATE);
|
||||
template.PIN_POLICY = $(this).val();
|
||||
template_str = TemplateUtils.templateToString(template);
|
||||
Sunstone.runAction(RESOURCE + ".update_template", that.element.ID, template_str);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function capitalize(string){
|
||||
return typeof string !== 'string'? "" : string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
|
||||
}
|
||||
|
||||
function _setup(context) {
|
||||
var that = this;
|
||||
if (that && that.element && that.element.HOST_SHARE && that.element.HOST_SHARE.NUMA_NODES) {
|
||||
var numaNodes = that.element.HOST_SHARE.NUMA_NODES.NODE;
|
||||
if (!(numaNodes instanceof Array)) {
|
||||
numaNodes = [numaNodes];
|
||||
}
|
||||
var options = [{'value':'NONE'},{'value':'PINNED'}];
|
||||
var select = $("<select/>",{'id': SELECT_ID});
|
||||
options.map(function(element){
|
||||
if(element && element.value){
|
||||
var selected = that && that.element && that.element.TEMPLATE && that.element.TEMPLATE.PIN_POLICY && that.element.TEMPLATE.PIN_POLICY === element.value;
|
||||
select.append($("<option/>",{'value':element.value}).text(capitalize(element.value)).prop('selected', selected));
|
||||
}
|
||||
});
|
||||
var selectTable = $("<table/>");
|
||||
selectTable.append($("<thead/>").append($("<tr>").append($("<th/>").text("Pin Policy"))));
|
||||
selectTable.append($("<tbody>").append($("<tr>").append($("<td/>"))));
|
||||
selectTable.find("td").append(select);
|
||||
$("#placeNumaInfo").append(selectTable);
|
||||
numaNodes.map(function(node,i){
|
||||
var displaySubtitle = true;
|
||||
var title = $("<h4/>");
|
||||
var subtitle = $("<h6/>");
|
||||
var coreTable = $("<table/>");
|
||||
var memory = $("<div/>",{'class':'memory small-12 large-6 columns'});
|
||||
var hugepage = $("<div/>",{'class':'hugepage small-12 large-6 columns'});
|
||||
if(node){
|
||||
var infoNode = node;
|
||||
title.text(infoNode.NODE_ID? "Node #"+infoNode.NODE_ID : "");
|
||||
//CORES
|
||||
if(infoNode.CORE){
|
||||
if(displaySubtitle){
|
||||
subtitle.text("Cores & CPUS");
|
||||
displaySubtitle = false;
|
||||
}
|
||||
var tBody = $("<tbody/>");
|
||||
var numaCores = infoNode.CORE;
|
||||
if (!(infoNode.CORE instanceof Array)) {
|
||||
numaCores = [numaCores];
|
||||
}
|
||||
var limit = 3; //start in 0 is index of array
|
||||
var count = 0;
|
||||
numaCores.map(function(core,i){
|
||||
|
||||
var placeBody = tBody.find("tr:last");
|
||||
if(count === 0){
|
||||
placeBody = tBody.append($("<tr/>")).find("tr:last");
|
||||
}
|
||||
placeBody.append(
|
||||
$("<td/>",{"colspan":2,"class":"text-center"}).append(
|
||||
$("<h6/>").text(core.ID? "Core "+core.ID : "")
|
||||
)
|
||||
);
|
||||
if(core.CPUS){
|
||||
var cpus = core.CPUS.split(",");
|
||||
if(cpus instanceof Array){
|
||||
cpus.map(function(cpu){
|
||||
var cpuInfo = cpu.split(":");
|
||||
var state = cpuInfo && cpuInfo[1] && cpuInfo[1]>=0? "busy" : "free";
|
||||
placeBody.find("td:last").append(
|
||||
$("<div/>",{"class":"small-6 columns cpu "+state}).append(
|
||||
$("<div/>",{"class":""}).text("CPU #"+cpuInfo[0]).add(
|
||||
cpuInfo && cpuInfo[1] && cpuInfo[1] >= 0?
|
||||
$("<a/>",{"class":"","href":"/#vms-tab/"+cpuInfo[1]}).text("VM #"+cpuInfo[1])
|
||||
:
|
||||
$("<div/>",{"class":"no-vm"}).text("FREE")
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
count = count >= limit ? 0 : count+1;
|
||||
});
|
||||
coreTable.append(tBody);
|
||||
}
|
||||
//MEMORY
|
||||
if(infoNode.MEMORY){
|
||||
var infoMemory = infoNode.MEMORY;
|
||||
memory.append($("<h6/>").text("Memory"));
|
||||
var total = infoMemory && infoMemory.TOTAL? parseInt(infoMemory.TOTAL): 0;
|
||||
var used = infoMemory && infoMemory.TOTAL? parseInt(infoMemory.USED) : 0;
|
||||
var parser = Humanize.sizeFromKB;
|
||||
if (total > 0) {
|
||||
var ratio = Math.round((used / total) * 100);
|
||||
info_str = parser(used) + ' / ' + parser(total) + ' (' + ratio + '%)';
|
||||
} else {
|
||||
if (info.TYPE == 1) {
|
||||
info_str = '- / -';
|
||||
} else {
|
||||
info_str = Humanize.size(used) + ' / -';
|
||||
}
|
||||
}
|
||||
memory.append(ProgressBar.html(used, total, info_str, 'memory-used'));
|
||||
}
|
||||
//HUGEPAGE
|
||||
if(infoNode.HUGEPAGE){
|
||||
var infoHugepages = infoNode.HUGEPAGE;
|
||||
hugepage.append($("<h6/>").text("Hugepage"));
|
||||
var hugepageTable = $("<table/>");
|
||||
hugepageTable.append(
|
||||
$("<thead/>").append(
|
||||
$("<tr/>").append(
|
||||
$("<th/>").text("SIZE")
|
||||
.add($("<th/>").text("FREE"))
|
||||
.add($("<th/>").text("PAGES"))
|
||||
.add($("<th/>").text("USAGE"))
|
||||
)
|
||||
)
|
||||
);
|
||||
var body = $("<tbody/>");
|
||||
infoHugepages.map(function(element,index){
|
||||
body.append(
|
||||
$("<tr/>").append(
|
||||
$("<td/>").text(
|
||||
element["SIZE"]
|
||||
).add(
|
||||
$("<td/>").text(element["FREE"])
|
||||
).add(
|
||||
$("<td/>").text(element["PAGES"])
|
||||
).add(
|
||||
$("<td/>").text(element["USAGE"])
|
||||
)
|
||||
)
|
||||
)
|
||||
});
|
||||
hugepage.append(hugepageTable.append(body));
|
||||
}
|
||||
}
|
||||
$("#placeNumaInfo").append(title.add(subtitle).add(coreTable).add($("<div/>",{"class":"row"}).append(memory.add(hugepage))));
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
|
20
src/sunstone/public/app/tabs/hosts-tab/panels/numa/html.hbs
Normal file
20
src/sunstone/public/app/tabs/hosts-tab/panels/numa/html.hbs
Normal file
@ -0,0 +1,20 @@
|
||||
{{! -------------------------------------------------------------------------- }}
|
||||
{{! Copyright 2002-2019, 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. }}
|
||||
{{! -------------------------------------------------------------------------- }}
|
||||
|
||||
<div class="row">
|
||||
<div id="placeNumaInfo">
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,19 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2019, 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
define(function(require) {
|
||||
return 'host_numa_tab';
|
||||
})
|
@ -49,7 +49,8 @@ define(function(require) {
|
||||
require("./create/wizard-tabs/scheduling"),
|
||||
require("./create/wizard-tabs/hybrid"),
|
||||
require("./create/wizard-tabs/vmgroup"),
|
||||
require("./create/wizard-tabs/other")
|
||||
require("./create/wizard-tabs/other"),
|
||||
require("./create/wizard-tabs/numa")
|
||||
];
|
||||
|
||||
var TEMPLATES_TAB_ID = require("tabs/templates-tab/tabId");
|
||||
@ -161,10 +162,32 @@ define(function(require) {
|
||||
var templateJSON = {};
|
||||
$.each(this.wizardTabs, function(index, wizardTab) {
|
||||
$.extend(true, templateJSON, wizardTab.retrieve($("#" + wizardTab.wizardTabId, context)));
|
||||
|
||||
var a = templateJSON;
|
||||
});
|
||||
|
||||
|
||||
if(templateJSON["TOPOLOGY"] && templateJSON["TOPOLOGY"]["BORRAR"]){
|
||||
delete templateJSON["TOPOLOGY"];
|
||||
}
|
||||
|
||||
if(
|
||||
templateJSON["TOPOLOGY"] &&
|
||||
templateJSON["TOPOLOGY"]["HUGEPAGE_SIZE"] !== undefined &&
|
||||
templateJSON["TOPOLOGY"]["HUGEPAGE_SIZE"] !== null &&
|
||||
templateJSON["TOPOLOGY"]["HUGEPAGE_SIZE"].length<=0
|
||||
){
|
||||
delete templateJSON["TOPOLOGY"]["HUGEPAGE_SIZE"];
|
||||
}
|
||||
|
||||
if(
|
||||
templateJSON["TOPOLOGY"] &&
|
||||
templateJSON["TOPOLOGY"]["MEMORY_ACCESS"] !== undefined &&
|
||||
templateJSON["TOPOLOGY"]["MEMORY_ACCESS"] !== null &&
|
||||
templateJSON["TOPOLOGY"]["MEMORY_ACCESS"].length<=0
|
||||
){
|
||||
delete templateJSON["TOPOLOGY"]["MEMORY_ACCESS"];
|
||||
}
|
||||
|
||||
// vCenter PUBLIC_CLOUD is not defined in the hybrid tab. Because it is
|
||||
// part of an array, and it is filled in different tabs, the $.extend deep
|
||||
// merge can't work. We define an auxiliary attribute for it.
|
||||
@ -196,7 +219,6 @@ define(function(require) {
|
||||
|
||||
delete templateJSON["NIC_PCI"];
|
||||
}
|
||||
|
||||
return templateJSON;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,227 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2019, 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
define(function(require) {
|
||||
/*
|
||||
DEPENDENCIES
|
||||
*/
|
||||
|
||||
var Config = require("sunstone-config");
|
||||
var Locale = require("utils/locale");
|
||||
var Tips = require("utils/tips");
|
||||
var WizardFields = require("utils/wizard-fields");
|
||||
var FilesTable = require("tabs/files-tab/datatable");
|
||||
var UniqueId = require("utils/unique-id");
|
||||
var OpenNebulaAction = require('opennebula/action');
|
||||
|
||||
/*
|
||||
TEMPLATES
|
||||
*/
|
||||
|
||||
var TemplateHTML = require("hbs!./numa/html");
|
||||
|
||||
/*
|
||||
CONSTANTS
|
||||
*/
|
||||
|
||||
var WIZARD_TAB_ID = require("./numa/wizardTabId");
|
||||
var RESOURCE = "HOST";
|
||||
var BUTTON_NUMA_TOPOLOGY = "#numa-topology";
|
||||
var HUGEPAGE_SELECTED_VALUE = "";
|
||||
var idsElements = {
|
||||
cores: "#numa-cores",
|
||||
threads: "#numa-threads",
|
||||
hugepages: "#numa-hugepages",
|
||||
sockets: "#numa-sockets",
|
||||
memory: "#numa-memory",
|
||||
pin: "#numa-pin-policy"
|
||||
}
|
||||
|
||||
var numaStatus = null;
|
||||
/*
|
||||
CONSTRUCTOR
|
||||
*/
|
||||
|
||||
function WizardTab(opts) {
|
||||
if (!Config.isTemplateCreationTabEnabled(opts.tabId, "os_booting")) {
|
||||
throw "Wizard Tab not enabled";
|
||||
}
|
||||
this.wizardTabId = WIZARD_TAB_ID + UniqueId.id();
|
||||
this.icon = "fa-chart-pie";
|
||||
this.title = Locale.tr("NUMA");
|
||||
}
|
||||
|
||||
WizardTab.prototype.constructor = WizardTab;
|
||||
WizardTab.prototype.html = _html;
|
||||
WizardTab.prototype.setup = _setup;
|
||||
WizardTab.prototype.onShow = _onShow;
|
||||
WizardTab.prototype.retrieve = _retrieve;
|
||||
WizardTab.prototype.fill = _fill;
|
||||
|
||||
return WizardTab;
|
||||
|
||||
/*
|
||||
FUNCTION DEFINITIONS
|
||||
*/
|
||||
|
||||
function _html() {
|
||||
var that = this;
|
||||
return TemplateHTML();
|
||||
}
|
||||
|
||||
function successCallback(request, opts, infohost){
|
||||
//console.log("CACHE ", OpenNebulaAction.get_all_cache());
|
||||
var selector = $(idsElements.hugepages);
|
||||
selector.empty();
|
||||
if(infohost && infohost.HOST_POOL && infohost.HOST_POOL.HOST){
|
||||
var hosts = infohost.HOST_POOL.HOST;
|
||||
var hugepages = [];
|
||||
if (!(hosts instanceof Array)) {
|
||||
hosts = [hosts];
|
||||
}
|
||||
hosts.map(function(host){
|
||||
if(host && host.HOST_SHARE && host.NAME && host.HOST_SHARE.NUMA_NODES && host.HOST_SHARE.NUMA_NODES.NODE){
|
||||
var name = host.NAME;
|
||||
var numaNodes = host.HOST_SHARE.NUMA_NODES.NODE;
|
||||
if (!(numaNodes instanceof Array)) {
|
||||
numaNodes = [numaNodes];
|
||||
}
|
||||
numaNodes.map(function(node){
|
||||
if(node && node.HUGEPAGE && node.NODE_ID){
|
||||
node.HUGEPAGE.map(function(hugepage){
|
||||
if(!hugepages.includes(hugepage.SIZE)){
|
||||
hugepages.push(hugepage.SIZE);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
selector.append($("<option/>",{"value":""}).text("-"));
|
||||
hugepages.map(function(hugepage){
|
||||
var selected = hugepage === HUGEPAGE_SELECTED_VALUE;
|
||||
selector.append($("<option/>",{"value": hugepage}).text(hugepage).prop('selected', selected));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getStatusNuma(){
|
||||
return numaStatus;
|
||||
}
|
||||
|
||||
function errorCallback(error, error1){
|
||||
console.log("error->", error, error1);
|
||||
}
|
||||
|
||||
function _onShow(context, panelForm) {
|
||||
var that = this;
|
||||
$(BUTTON_NUMA_TOPOLOGY, context).on( 'click', function() {
|
||||
var form = $(".numa-form",context);
|
||||
if( $(this).is(':checked') ){
|
||||
form.removeClass("hide");
|
||||
OpenNebulaAction.clear_cache(RESOURCE);
|
||||
OpenNebulaAction.list(
|
||||
{
|
||||
data: {pool_filter: -2},
|
||||
success: successCallback,
|
||||
error: errorCallback
|
||||
},
|
||||
RESOURCE
|
||||
);
|
||||
numaStatus = true;
|
||||
}else{
|
||||
form.addClass("hide");
|
||||
numaStatus = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function _setup(context) {
|
||||
var that = this;
|
||||
Foundation.reflow(context, "tabs");
|
||||
}
|
||||
|
||||
function _retrieve(context) {
|
||||
var templateJSON = { TOPOLOGY : {BORRAR:"BORRAR"} };
|
||||
if(getStatusNuma()){
|
||||
delete templateJSON["TOPOLOGY"]["BORRAR"];
|
||||
|
||||
var temp = {};
|
||||
var policy = _getValue(idsElements.pin, context);
|
||||
if(policy && policy.length){
|
||||
temp.PIN_POLICY = policy;
|
||||
}
|
||||
var sockets = _getValue(idsElements.sockets, context);
|
||||
if(sockets && sockets.length){
|
||||
temp.SOCKETS = sockets;
|
||||
}
|
||||
var cores = _getValue(idsElements.cores, context);
|
||||
if(cores && cores.length){
|
||||
temp.CORES = cores;
|
||||
}
|
||||
var threads = _getValue(idsElements.threads, context);
|
||||
if(threads && threads.length){
|
||||
temp.THREADS = threads;
|
||||
}
|
||||
temp.HUGEPAGE_SIZE = _getValue(idsElements.hugepages, context);
|
||||
|
||||
temp.MEMORY_ACCESS = _getValue(idsElements.memory, context);
|
||||
|
||||
templateJSON.TOPOLOGY = temp;
|
||||
}
|
||||
return templateJSON;
|
||||
}
|
||||
|
||||
function _getValue(id="", context=null){
|
||||
rtn = null;
|
||||
if(id.length && context){
|
||||
rtn = $(String(id), context).val();
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
function _fillBootValue(id="", context=null, value="") {
|
||||
if(id.length && context && value.length){
|
||||
$(String(id), context).val(value);
|
||||
}
|
||||
}
|
||||
|
||||
function _fill(context, templateJSON) {
|
||||
if(templateJSON && templateJSON.TOPOLOGY){
|
||||
var topology = templateJSON.TOPOLOGY;
|
||||
$(BUTTON_NUMA_TOPOLOGY).click();
|
||||
if(topology && topology.CORES){
|
||||
_fillBootValue(idsElements.cores, context, topology.CORES);
|
||||
}
|
||||
HUGEPAGE_SELECTED_VALUE = "";
|
||||
if(topology && topology.HUGEPAGE_SIZE){
|
||||
HUGEPAGE_SELECTED_VALUE = topology.HUGEPAGE_SIZE;
|
||||
}
|
||||
if(topology && topology.MEMORY_ACCESS){
|
||||
_fillBootValue(idsElements.memory, context, topology.MEMORY_ACCESS);
|
||||
}
|
||||
if(topology && topology.PIN_POLICY){
|
||||
_fillBootValue(idsElements.pin, context, topology.PIN_POLICY);
|
||||
}
|
||||
if(topology && topology.SOCKETS){
|
||||
_fillBootValue(idsElements.sockets, context, topology.SOCKETS);
|
||||
}
|
||||
if(topology && topology.THREADS){
|
||||
_fillBootValue(idsElements.threads, context, topology.THREADS);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
@ -0,0 +1,73 @@
|
||||
{{! -------------------------------------------------------------------------- }}
|
||||
{{! Copyright 2002-2019, 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. }}
|
||||
{{! -------------------------------------------------------------------------- }}
|
||||
<div id="tabs-numa" class="row collapse">
|
||||
<div class="small-12 columns">
|
||||
<div class="row">
|
||||
<div class="small-12 columns numa-topology-display">
|
||||
<input type="checkbox" id="numa-topology">
|
||||
<label for="numa-topology">
|
||||
{{tr "NUMA Topology"}}
|
||||
{{{tip (tr "These settings will help you to fine tune the performance of VMs")}}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row numa-form hide">
|
||||
<div class="small-6 columns">
|
||||
<label for="numa-pin-policy">
|
||||
{{tr "Pin Policy"}}
|
||||
{{{tip (tr "vCPU pinning preference: CORE, THREAD, SHARED, NONE")}}}
|
||||
</label>
|
||||
<select id="numa-pin-policy">
|
||||
<option value="NONE">{{tr "none"}}</option>
|
||||
<option value="THREAD">{{tr "thread"}}</option>
|
||||
<option value="SHARED">{{tr "shared"}}</option>
|
||||
<option value="CORE">{{tr "core"}}</option>
|
||||
</select>
|
||||
<label for="numa-sockets">
|
||||
{{tr "Sockets"}}
|
||||
{{{tip (tr "Number of sockets or NUMA nodes")}}}
|
||||
</label>
|
||||
<input type="number" id="numa-sockets">
|
||||
<label for="numa-cores">
|
||||
{{tr "Cores"}}
|
||||
{{{tip (tr "Number of cores per node")}}}
|
||||
</label>
|
||||
<input type="number" id="numa-cores">
|
||||
</div>
|
||||
<div class="small-6 columns">
|
||||
<label for="numa-threads">
|
||||
{{tr "Threads"}}
|
||||
{{{tip (tr "Number of threads per core")}}}
|
||||
</label>
|
||||
<input type="number" id="numa-threads">
|
||||
<label for="numa-hugepages">
|
||||
{{tr "Hugepages Size"}}
|
||||
{{{tip (tr "Size of the hugepages (MB). If not defined no hugepages will be used")}}}
|
||||
</label>
|
||||
<select id="numa-hugepages"></select>
|
||||
<label for="numa-memory">
|
||||
{{tr "Memory Access"}}
|
||||
{{{tip (tr "Control if the memory is to be mapped shared or private")}}}
|
||||
</label>
|
||||
<select id="numa-memory">
|
||||
<option value="">{{tr "-"}}</option>
|
||||
<option value="SHARED">{{tr "Shared"}}</option>
|
||||
<option value="PRIVATE">{{tr "Private"}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,19 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2019, 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
define(function(require){
|
||||
return 'numaTab';
|
||||
});
|
@ -26,7 +26,9 @@ define(function(require) {
|
||||
var Notifier = require('utils/notifier');
|
||||
var Graphs = require('utils/graphs');
|
||||
var StateActions = require('tabs/vms-tab/utils/state-actions');
|
||||
|
||||
var OpenNebulaAction = require('opennebula/action');
|
||||
var Humanize = require('utils/humanize');
|
||||
var ProgressBar = require('utils/progress-bar');
|
||||
/*
|
||||
TEMPLATES
|
||||
*/
|
||||
@ -149,5 +151,88 @@ define(function(require) {
|
||||
},
|
||||
error: Notifier.onError
|
||||
});
|
||||
|
||||
//NUMA DATA
|
||||
var element = this.element;
|
||||
var displaySubtitle = true;
|
||||
var coreTable = $("<table/>");
|
||||
if(element && element.TEMPLATE && element.TEMPLATE.NUMA_NODE){
|
||||
var info = element.TEMPLATE.NUMA_NODE;
|
||||
if (!(info instanceof Array)) {
|
||||
info = [info];
|
||||
}
|
||||
var limit = 3; //start in 0 is index of array
|
||||
var count = 0;
|
||||
var subtitle = $("<h6/>");
|
||||
var description = $("<small>").css({'margin-left':'1rem','font-size': '0.9rem'});
|
||||
var descriptionText = [];
|
||||
var space = false;
|
||||
var tBody = $("<tbody/>");
|
||||
var progress = "";
|
||||
//description info
|
||||
if(element.TEMPLATE && element.TEMPLATE.TOPOLOGY ){
|
||||
for (var prop in element.TEMPLATE.TOPOLOGY){
|
||||
var styles = 'display: inline-block;font-weight: bold;color: #5f5d5d;';
|
||||
if(space){
|
||||
styles += 'margin-left: 0.3rem;';
|
||||
}
|
||||
space = true;
|
||||
descriptionText.push("<div style='"+styles+"'>"+prop.toLocaleLowerCase()+":</div> "+element.TEMPLATE.TOPOLOGY[prop]);
|
||||
}
|
||||
description.append("("+descriptionText.join(" ").trim()+")");
|
||||
}
|
||||
info.map(function(core, index){
|
||||
if(displaySubtitle){
|
||||
subtitle.text("Cores & CPUS");
|
||||
displaySubtitle = false;
|
||||
}
|
||||
|
||||
var placeBody = tBody.find("tr:last");
|
||||
if(count === 0){
|
||||
placeBody = tBody.append($("<tr/>")).find("tr:last");
|
||||
}
|
||||
placeBody.append(
|
||||
$("<td/>",{"colspan":2,"class":"text-center"}).append(
|
||||
$("<h6/>").text("Node "+index)
|
||||
)
|
||||
);
|
||||
if(core.CPUS){
|
||||
var cpus = core.CPUS.split(",");
|
||||
if(cpus instanceof Array){
|
||||
cpus.map(function(cpu){
|
||||
if(core.MEMORY){
|
||||
var infoMemory = core.MEMORY;
|
||||
var total = infoMemory ? parseInt(infoMemory): 0;
|
||||
var used = infoMemory ? parseInt(infoMemory) : 0;
|
||||
var parser = Humanize.sizeFromKB;
|
||||
if (total > 0) {
|
||||
var ratio = Math.round((used / total) * 100);
|
||||
info_str = parser(used) + ' / ' + parser(total) + ' (' + ratio + '%)';
|
||||
} else {
|
||||
if (info.TYPE == 1) {
|
||||
info_str = '- / -';
|
||||
} else {
|
||||
info_str = Humanize.size(used) + ' / -';
|
||||
}
|
||||
}
|
||||
progress = ProgressBar.html(used, total, info_str, 'memory-used');
|
||||
}
|
||||
|
||||
placeBody.find("td:last").append(
|
||||
$("<div/>",{"class":"small-6 columns cpu busy"}).append(
|
||||
$("<div/>",{"class":""}).text("CPU #"+cpu)
|
||||
)
|
||||
);
|
||||
|
||||
});
|
||||
}
|
||||
placeBody.find("td:last").append($("<div/>",{'class':'small-12 columns'}).css({"padding": "0px",
|
||||
"margin-top": "2rem"}).append($("<h6/>",{'class':'text-left'}).text("Memory").css({'padding-bottom':'0px'}).add(progress)));
|
||||
}
|
||||
count = count >= limit ? 0 : count+1;
|
||||
});
|
||||
coreTable.append(tBody);
|
||||
$("#numaPlaceVM").empty().append(subtitle.append(description).add(coreTable));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -90,3 +90,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="numaPlaceVM">
|
||||
</div>
|
||||
|
@ -15,7 +15,7 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
define(function(require) {
|
||||
var _quotaBarHtml = function(usage, limit, info_str) {
|
||||
var _quotaBarHtml = function(usage, limit, info_str, className="" ) {
|
||||
info_str = info_str || (usage + ' / ' + ((limit >= 0) ? limit : '-'));
|
||||
|
||||
var value = "0";
|
||||
@ -26,11 +26,14 @@ define(function(require) {
|
||||
max = limit;
|
||||
}
|
||||
|
||||
html = '<span class="progress-text right" style="font-size: 12px">' + info_str + '</span>' +
|
||||
'<br>' +
|
||||
'<progress value="' + value + '" max="' + limit + '"></progress>';
|
||||
|
||||
return html;
|
||||
html = $("<span/>",{'class':'progress-text right', 'style':'font-size: 12px'}).text(
|
||||
info_str
|
||||
).add(
|
||||
$("<br/>")
|
||||
).add(
|
||||
$("<progress/>",{'class':className, 'value':value,'max':limit})
|
||||
);
|
||||
return $("<div/>").append(html).html();
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -134,4 +134,29 @@
|
||||
|
||||
overflow-y: auto;
|
||||
max-height: 6em;
|
||||
}
|
||||
|
||||
#numa-topology-display{
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
progress{
|
||||
&.memory-used{
|
||||
height: 1rem;
|
||||
color: $busy;
|
||||
margin-bottom: 2rem;
|
||||
background-color: $free;
|
||||
&::-webkit-progress-value{
|
||||
background-color: $busy;
|
||||
}
|
||||
&::-webkit-progress-bar{
|
||||
background-color: $free;
|
||||
}
|
||||
&::-moz-progress-bar{
|
||||
background-color: $busy;
|
||||
}
|
||||
&::-ms-fill{
|
||||
background-color: $busy;
|
||||
}
|
||||
}
|
||||
}
|
@ -66,6 +66,8 @@ $black: #0a0a0a;
|
||||
$dark-black: #000;
|
||||
//$black: #333;
|
||||
$white: #fefefe;
|
||||
$free: #cacaca;
|
||||
$busy: #4DBBD3;
|
||||
$deploying-color: #C7731F;
|
||||
$error-color: #cf280e;
|
||||
$powering_off-color: #cf280e;
|
||||
|
@ -32,6 +32,34 @@ table {
|
||||
border-bottom: 1px solid smart-scale($table-background, $table-hover-scale);
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
td{
|
||||
.cpu{
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
a,.no-vm{
|
||||
color: $white;
|
||||
font-weight: bold;
|
||||
padding: 5px;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
.busy{
|
||||
background-color: $busy;
|
||||
color: $white;
|
||||
font-weight: bold;
|
||||
border: 1px solid $white;
|
||||
}
|
||||
|
||||
.free{
|
||||
background-color: $free;
|
||||
font-weight: bold;
|
||||
color: $white;
|
||||
border: 1px solid $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tfoot {
|
||||
|
Loading…
x
Reference in New Issue
Block a user