]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/lxc/Resources.js
dde920bf8870e176ae280b906f30b67507eb93af
[pve-manager.git] / www / manager6 / lxc / Resources.js
1 /*jslint confusion: true */
2 Ext.define('PVE.lxc.RessourceView', {
3 extend: 'Proxmox.grid.PendingObjectGrid',
4 alias: ['widget.pveLxcRessourceView'],
5
6 onlineHelp: 'pct_configuration',
7
8 renderKey: function(key, metaData, rec, rowIndex, colIndex, store) {
9 var me = this;
10 var rowdef = me.rows[key] || {};
11
12 metaData.tdAttr = "valign=middle";
13 if (rowdef.tdCls) {
14 metaData.tdCls = rowdef.tdCls;
15 }
16 return rowdef.header || key;
17 },
18
19 initComponent : function() {
20 var me = this;
21 var i, confid;
22
23 var nodename = me.pveSelNode.data.node;
24 if (!nodename) {
25 throw "no node name specified";
26 }
27
28 var vmid = me.pveSelNode.data.vmid;
29 if (!vmid) {
30 throw "no VM ID specified";
31 }
32
33 var caps = Ext.state.Manager.get('GuiCap');
34 var diskCap = caps.vms['VM.Config.Disk'];
35
36 var mpeditor = caps.vms['VM.Config.Disk'] ? 'PVE.lxc.MountPointEdit' : undefined;
37
38 var rows = {
39 memory: {
40 header: gettext('Memory'),
41 editor: caps.vms['VM.Config.Memory'] ? 'PVE.lxc.MemoryEdit' : undefined,
42 defaultValue: 512,
43 tdCls: 'pve-itype-icon-memory',
44 group: 1,
45 renderer: function(value) {
46 return Proxmox.Utils.format_size(value*1024*1024);
47 }
48 },
49 swap: {
50 header: gettext('Swap'),
51 editor: caps.vms['VM.Config.Memory'] ? 'PVE.lxc.MemoryEdit' : undefined,
52 defaultValue: 512,
53 tdCls: 'pve-itype-icon-swap',
54 group: 2,
55 renderer: function(value) {
56 return Proxmox.Utils.format_size(value*1024*1024);
57 }
58 },
59 cores: {
60 header: gettext('Cores'),
61 editor: caps.vms['VM.Config.CPU'] ? 'PVE.lxc.CPUEdit' : undefined,
62 defaultValue: '',
63 tdCls: 'pve-itype-icon-processor',
64 group: 3,
65 renderer: function(value) {
66 var cpulimit = me.getObjectValue('cpulimit');
67 var cpuunits = me.getObjectValue('cpuunits');
68 var res;
69 if (value) {
70 res = value;
71 } else {
72 res = gettext('unlimited');
73 }
74
75 if (cpulimit) {
76 res += ' [cpulimit=' + cpulimit + ']';
77 }
78
79 if (cpuunits) {
80 res += ' [cpuunits=' + cpuunits + ']';
81 }
82 return res;
83 }
84 },
85 rootfs: {
86 header: gettext('Root Disk'),
87 defaultValue: Proxmox.Utils.noneText,
88 editor: mpeditor,
89 tdCls: 'pve-itype-icon-storage',
90 group: 4
91 },
92 cpulimit: {
93 visible: false
94 },
95 cpuunits: {
96 visible: false
97 },
98 unprivileged: {
99 visible: false
100 }
101 };
102
103 PVE.Utils.forEachMP(function(bus, i) {
104 confid = bus + i;
105 var group = 5;
106 var header;
107 if (bus === 'mp') {
108 header = gettext('Mount Point') + ' (' + confid + ')';
109 } else {
110 header = gettext('Unused Disk') + ' ' + i;
111 group += 1;
112 }
113 rows[confid] = {
114 group: group,
115 order: i,
116 tdCls: 'pve-itype-icon-storage',
117 editor: mpeditor,
118 header: header
119 };
120 }, true);
121
122 var baseurl = 'nodes/' + nodename + '/lxc/' + vmid + '/config';
123
124 me.selModel = Ext.create('Ext.selection.RowModel', {});
125
126 var run_resize = function() {
127 var rec = me.selModel.getSelection()[0];
128 if (!rec) {
129 return;
130 }
131
132 var win = Ext.create('PVE.window.MPResize', {
133 disk: rec.data.key,
134 nodename: nodename,
135 vmid: vmid
136 });
137
138 win.show();
139 };
140
141 var run_remove = function(b, e, rec) {
142 Proxmox.Utils.API2Request({
143 url: '/api2/extjs/' + baseurl,
144 waitMsgTarget: me,
145 method: 'PUT',
146 params: {
147 'delete': rec.data.key
148 },
149 failure: function (response, opts) {
150 Ext.Msg.alert('Error', response.htmlStatus);
151 }
152 });
153 };
154
155 var run_move = function(b, e, rec) {
156 if (!rec) {
157 return;
158 }
159
160 var win = Ext.create('PVE.window.HDMove', {
161 disk: rec.data.key,
162 nodename: nodename,
163 vmid: vmid,
164 type: 'lxc'
165 });
166
167 win.show();
168
169 win.on('destroy', me.reload, me);
170 };
171
172 var edit_btn = new Proxmox.button.Button({
173 text: gettext('Edit'),
174 selModel: me.selModel,
175 disabled: true,
176 enableFn: function(rec) {
177 if (!rec) {
178 return false;
179 }
180 var rowdef = rows[rec.data.key];
181 return !!rowdef.editor;
182 },
183 handler: function() { me.run_editor(); }
184 });
185
186 var resize_btn = new Proxmox.button.Button({
187 text: gettext('Resize disk'),
188 selModel: me.selModel,
189 disabled: true,
190 handler: run_resize
191 });
192
193 var remove_btn = new Proxmox.button.Button({
194 text: gettext('Remove'),
195 selModel: me.selModel,
196 disabled: true,
197 dangerous: true,
198 confirmMsg: function(rec) {
199 var msg = Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
200 "'" + me.renderKey(rec.data.key, {}, rec) + "'");
201 if (rec.data.key.match(/^unused\d+$/)) {
202 msg += " " + gettext('This will permanently erase all data.');
203 }
204
205 return msg;
206 },
207 handler: run_remove
208 });
209
210 var move_btn = new Proxmox.button.Button({
211 text: gettext('Move Volume'),
212 selModel: me.selModel,
213 disabled: true,
214 dangerous: true,
215 handler: run_move
216 });
217
218 var revert_btn = new PVE.button.PendingRevert();
219
220 var set_button_status = function() {
221 var rec = me.selModel.getSelection()[0];
222
223 if (!rec) {
224 edit_btn.disable();
225 remove_btn.disable();
226 resize_btn.disable();
227 revert_btn.disable();
228 return;
229 }
230 var key = rec.data.key;
231 var value = rec.data.value;
232 var rowdef = rows[key];
233
234 var pending = rec.data['delete'] || me.hasPendingChanges(key);
235 var isDisk = (rowdef.tdCls == 'pve-itype-icon-storage');
236
237 var noedit = rec.data['delete'] || !rowdef.editor;
238 if (!noedit && Proxmox.UserName !== 'root@pam' && key.match(/^mp\d+$/)) {
239 var mp = PVE.Parser.parseLxcMountPoint(value);
240 if (mp.type !== 'volume') {
241 noedit = true;
242 }
243 }
244 edit_btn.setDisabled(noedit);
245
246 remove_btn.setDisabled(!isDisk || rec.data.key === 'rootfs' || !diskCap || pending);
247 resize_btn.setDisabled(!isDisk || !diskCap);
248 move_btn.setDisabled(!isDisk || !diskCap);
249 revert_btn.setDisabled(!pending);
250
251 };
252
253 var sorterFn = function(rec1, rec2) {
254 var v1 = rec1.data.key;
255 var v2 = rec2.data.key;
256 var g1 = rows[v1].group || 0;
257 var g2 = rows[v2].group || 0;
258 var order1 = rows[v1].order || 0;
259 var order2 = rows[v2].order || 0;
260
261 if ((g1 - g2) !== 0) {
262 return g1 - g2;
263 }
264
265 if ((order1 - order2) !== 0) {
266 return order1 - order2;
267 }
268
269 if (v1 > v2) {
270 return 1;
271 } else if (v1 < v2) {
272 return -1;
273 } else {
274 return 0;
275 }
276 };
277
278 Ext.apply(me, {
279 url: "/api2/json/nodes/" + nodename + "/lxc/" + vmid + "/pending",
280 selModel: me.selModel,
281 interval: 2000,
282 cwidth1: 170,
283 tbar: [
284 {
285 text: gettext('Add'),
286 menu: new Ext.menu.Menu({
287 items: [
288 {
289 text: gettext('Mount Point'),
290 iconCls: 'pve-itype-icon-storage',
291 disabled: !caps.vms['VM.Config.Disk'],
292 handler: function() {
293 var win = Ext.create('PVE.lxc.MountPointEdit', {
294 url: '/api2/extjs/' + baseurl,
295 unprivileged: me.getObjectValue('unprivileged'),
296 pveSelNode: me.pveSelNode
297 });
298 win.on('destroy', me.reload, me);
299 win.show();
300 }
301 }
302 ]
303 })
304 },
305 edit_btn,
306 remove_btn,
307 resize_btn,
308 move_btn,
309 revert_btn
310 ],
311 rows: rows,
312 sorterFn: sorterFn,
313 editorConfig: {
314 pveSelNode: me.pveSelNode,
315 url: '/api2/extjs/' + baseurl
316 },
317 listeners: {
318 itemdblclick: me.run_editor,
319 selectionchange: set_button_status
320 }
321 });
322
323 me.callParent();
324
325 me.on('activate', me.rstore.startUpdate);
326 me.on('destroy', me.rstore.stopUpdate);
327 me.on('deactivate', me.rstore.stopUpdate);
328
329 me.mon(me.getStore(), 'datachanged', function() {
330 set_button_status();
331 });
332
333 Ext.apply(me.editorConfig, { unprivileged: me.getObjectValue('unprivileged') });
334 }
335 });