Upstream proxmox-git/pve-manager state of the touched files before cf848bda29
This commit is contained in:
1 parent
c09a3d7d49
commit
92f8784d03
2 files changed
+338
No files matched your search
@@ -0,0 +1,108 @@
|
|||||||
|
Ext.define('PVE.form.NodeSelector', {
|
||||||
|
extend: 'Proxmox.form.ComboGrid',
|
||||||
|
alias: ['widget.pveNodeSelector'],
|
||||||
|
|
||||||
|
// invalidate nodes which are offline
|
||||||
|
onlineValidator: false,
|
||||||
|
|
||||||
|
selectCurNode: false,
|
||||||
|
|
||||||
|
// do not allow those nodes (array)
|
||||||
|
disallowedNodes: undefined,
|
||||||
|
|
||||||
|
// only allow those nodes (array)
|
||||||
|
allowedNodes: undefined,
|
||||||
|
|
||||||
|
valueField: 'node',
|
||||||
|
displayField: 'node',
|
||||||
|
store: {
|
||||||
|
fields: ['node', 'cpu', 'maxcpu', 'mem', 'maxmem', 'uptime'],
|
||||||
|
proxy: {
|
||||||
|
type: 'proxmox',
|
||||||
|
url: '/api2/json/nodes',
|
||||||
|
},
|
||||||
|
sorters: [
|
||||||
|
{
|
||||||
|
property: 'node',
|
||||||
|
direction: 'ASC',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: 'mem',
|
||||||
|
direction: 'DESC',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
listConfig: {
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
header: gettext('Node'),
|
||||||
|
dataIndex: 'node',
|
||||||
|
sortable: true,
|
||||||
|
hideable: false,
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: gettext('Memory usage') + ' %',
|
||||||
|
renderer: PVE.Utils.render_mem_usage_percent,
|
||||||
|
sortable: true,
|
||||||
|
width: 100,
|
||||||
|
dataIndex: 'mem',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: gettext('CPU usage'),
|
||||||
|
renderer: Proxmox.Utils.render_cpu,
|
||||||
|
sortable: true,
|
||||||
|
width: 100,
|
||||||
|
dataIndex: 'cpu',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
validator: function (value) {
|
||||||
|
let me = this;
|
||||||
|
if (!me.onlineValidator || (me.allowBlank && !value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let offline = [],
|
||||||
|
notAllowed = [];
|
||||||
|
Ext.Array.each(value.split(/\s*,\s*/), function (node) {
|
||||||
|
let rec = me.store.findRecord(me.valueField, node, 0, false, true, true);
|
||||||
|
if (!(rec && rec.data) || rec.data.status !== 'online') {
|
||||||
|
offline.push(node);
|
||||||
|
} else if (me.allowedNodes && !Ext.Array.contains(me.allowedNodes, node)) {
|
||||||
|
notAllowed.push(node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (value && notAllowed.length !== 0) {
|
||||||
|
return 'Node ' + notAllowed.join(', ') + ' is not allowed for this action!';
|
||||||
|
}
|
||||||
|
if (value && offline.length !== 0) {
|
||||||
|
return 'Node ' + offline.join(', ') + ' seems to be offline!';
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
initComponent: function () {
|
||||||
|
var me = this;
|
||||||
|
|
||||||
|
if (me.selectCurNode && PVE.curSelectedNode && PVE.curSelectedNode.data.node) {
|
||||||
|
me.preferredValue = PVE.curSelectedNode.data.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
me.callParent();
|
||||||
|
me.getStore().load();
|
||||||
|
|
||||||
|
me.getStore().addFilter(
|
||||||
|
new Ext.util.Filter({
|
||||||
|
// filter out disallowed nodes
|
||||||
|
filterFn: (item) =>
|
||||||
|
!(me.disallowedNodes && me.disallowedNodes.includes(item.data.node)),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
me.mon(me.getStore(), 'load', () => me.isValid());
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,230 @@
|
|||||||
|
Ext.define('PVE.forms.NodePrioritySelector', {
|
||||||
|
extend: 'Ext.grid.Panel',
|
||||||
|
alias: 'widget.pveNodePrioritySelector',
|
||||||
|
|
||||||
|
mixins: {
|
||||||
|
field: 'Ext.form.field.Field',
|
||||||
|
},
|
||||||
|
|
||||||
|
allowBlank: true,
|
||||||
|
isFormField: true,
|
||||||
|
|
||||||
|
config: {
|
||||||
|
useNodePriority: null,
|
||||||
|
},
|
||||||
|
|
||||||
|
publishes: ['useNodePriority'],
|
||||||
|
|
||||||
|
viewModel: {
|
||||||
|
data: {
|
||||||
|
showNodePriority: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
store: {
|
||||||
|
autoLoad: true,
|
||||||
|
fields: ['node', 'cpu', 'mem', 'priority'],
|
||||||
|
proxy: {
|
||||||
|
type: 'proxmox',
|
||||||
|
url: '/api2/json/nodes',
|
||||||
|
},
|
||||||
|
sorters: [
|
||||||
|
{
|
||||||
|
property: 'node',
|
||||||
|
direction: 'ASC',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
header: gettext('Node'),
|
||||||
|
width: 150,
|
||||||
|
dataIndex: 'node',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: gettext('Memory usage') + ' %',
|
||||||
|
renderer: PVE.Utils.render_mem_usage_percent,
|
||||||
|
sortable: true,
|
||||||
|
width: 150,
|
||||||
|
dataIndex: 'mem',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: gettext('CPU usage'),
|
||||||
|
renderer: Proxmox.Utils.render_cpu,
|
||||||
|
sortable: true,
|
||||||
|
flex: 1,
|
||||||
|
dataIndex: 'cpu',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: gettext('Priority'),
|
||||||
|
xtype: 'widgetcolumn',
|
||||||
|
dataIndex: 'priority',
|
||||||
|
sortable: true,
|
||||||
|
stopSelection: true,
|
||||||
|
widget: {
|
||||||
|
xtype: 'proxmoxintegerfield',
|
||||||
|
minValue: 0,
|
||||||
|
maxValue: 1000,
|
||||||
|
isFormField: false,
|
||||||
|
listeners: {
|
||||||
|
change: function (field, value) {
|
||||||
|
let record = field.getWidgetRecord();
|
||||||
|
record.set('priority', value);
|
||||||
|
record.commit();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bind: {
|
||||||
|
hidden: '{!showNodePriority}',
|
||||||
|
disabled: '{!showNodePriority}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bind: {
|
||||||
|
hidden: '{!showNodePriority}',
|
||||||
|
disabled: '{!showNodePriority}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
selModel: {
|
||||||
|
selType: 'checkboxmodel',
|
||||||
|
mode: 'SIMPLE',
|
||||||
|
},
|
||||||
|
|
||||||
|
checkChangeEvents: ['selectionchange'],
|
||||||
|
|
||||||
|
listeners: {
|
||||||
|
selectionchange: function () {
|
||||||
|
// to trigger validity and error checks
|
||||||
|
this.checkChange();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
invertCheckboxSelection: function () {
|
||||||
|
let me = this;
|
||||||
|
|
||||||
|
let sm = me.getSelectionModel();
|
||||||
|
|
||||||
|
let allNodeModels = sm.getStore().getRange();
|
||||||
|
let selectedNodeModels = new Set(sm.getSelection());
|
||||||
|
|
||||||
|
if (!allNodeModels.length || !selectedNodeModels.size) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sm.deselectAll();
|
||||||
|
sm.select(allNodeModels.filter((node) => !selectedNodeModels.has(node)));
|
||||||
|
},
|
||||||
|
|
||||||
|
applyUseNodePriority: function (newValue) {
|
||||||
|
let me = this;
|
||||||
|
|
||||||
|
me.getViewModel().set('showNodePriority', newValue);
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
},
|
||||||
|
|
||||||
|
getSubmitData: function () {
|
||||||
|
let me = this;
|
||||||
|
let res = {};
|
||||||
|
res[me.name] = me.getValue();
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue: function () {
|
||||||
|
let me = this;
|
||||||
|
|
||||||
|
if (me.savedValue !== undefined) {
|
||||||
|
return me.savedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sm = me.getSelectionModel();
|
||||||
|
let selectedNodeModels = sm.getSelection();
|
||||||
|
let nodes = selectedNodeModels
|
||||||
|
.map(({ data }) => {
|
||||||
|
let nodeEntry = data.node;
|
||||||
|
|
||||||
|
if (me.useNodePriority && data.priority) {
|
||||||
|
nodeEntry += `:${data.priority}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeEntry;
|
||||||
|
})
|
||||||
|
.join(',');
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
},
|
||||||
|
|
||||||
|
setValueSelection: function (value) {
|
||||||
|
let me = this;
|
||||||
|
|
||||||
|
let store = me.getStore();
|
||||||
|
store.beginUpdate();
|
||||||
|
let nodenames = value.length ? value.split(',') : [];
|
||||||
|
let nodes = nodenames.map((item) => {
|
||||||
|
let [node, priority] = item.split(':');
|
||||||
|
|
||||||
|
let record = store.findRecord('node', node, 0, false, true, true);
|
||||||
|
if (record) {
|
||||||
|
record.set('priority', priority);
|
||||||
|
record.commit();
|
||||||
|
} else {
|
||||||
|
let addedRecords = store.add({ node, priority });
|
||||||
|
record = addedRecords[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return record;
|
||||||
|
});
|
||||||
|
store.endUpdate();
|
||||||
|
|
||||||
|
let sm = me.getSelectionModel();
|
||||||
|
if (nodes.length) {
|
||||||
|
sm.select(nodes);
|
||||||
|
} else {
|
||||||
|
sm.deselectAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
me.getErrors();
|
||||||
|
},
|
||||||
|
|
||||||
|
setValue: function (value) {
|
||||||
|
let me = this;
|
||||||
|
|
||||||
|
let store = me.getStore();
|
||||||
|
if (!store.isLoaded()) {
|
||||||
|
me.savedValue = value;
|
||||||
|
store.on(
|
||||||
|
'load',
|
||||||
|
function () {
|
||||||
|
me.setValueSelection(value);
|
||||||
|
delete me.savedValue;
|
||||||
|
},
|
||||||
|
{ single: true },
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
me.setValueSelection(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return me.mixins.field.setValue.call(me, value);
|
||||||
|
},
|
||||||
|
|
||||||
|
getErrors: function (value) {
|
||||||
|
let me = this;
|
||||||
|
|
||||||
|
if (!me.isDisabled() && me.allowBlank === false && me.getValue().length === 0) {
|
||||||
|
me.addBodyCls(['x-form-trigger-wrap-default', 'x-form-trigger-wrap-invalid']);
|
||||||
|
return [gettext('No nodes selected')];
|
||||||
|
}
|
||||||
|
|
||||||
|
me.removeBodyCls(['x-form-trigger-wrap-default', 'x-form-trigger-wrap-invalid']);
|
||||||
|
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
|
||||||
|
initComponent: function () {
|
||||||
|
let me = this;
|
||||||
|
|
||||||
|
me.callParent();
|
||||||
|
me.initField();
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in new issue
Block a user