1
0
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:
Jorge Lobo 2019-07-16 17:27:05 +02:00 committed by Ruben S. Montero
parent 35cfaf5e68
commit 8ebb79ef74
24 changed files with 784 additions and 12 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -434,7 +434,9 @@ define(function(require) {
return ""+id;
},
"get_all_cache": function() {
return listCache;
},
"clear_cache": _clearCache
};

View File

@ -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 = [

View 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))));
});
}
}
})

View 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>

View File

@ -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';
})

View File

@ -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;
}

View File

@ -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);
}
}
}
});

View File

@ -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>

View File

@ -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';
});

View File

@ -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));
}
}
});

View File

@ -90,3 +90,5 @@
</div>
</div>
</div>
<div id="numaPlaceVM">
</div>

View File

@ -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 {

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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 {