]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/lxc/Config.js
ui: tree/ResourceTree: show Tags in tree
[pve-manager.git] / www / manager6 / lxc / Config.js
CommitLineData
56166a78
DM
1Ext.define('PVE.lxc.Config', {
2 extend: 'PVE.panel.Config',
16875928 3 alias: 'widget.pveLXCConfig',
56166a78 4
c8802a60 5 onlineHelp: 'chapter_pct',
7f1ac74c 6
d70be8cd
DC
7 userCls: 'proxmox-tags-full',
8
56166a78
DM
9 initComponent: function() {
10 var me = this;
fe45dd5f 11 var vm = me.pveSelNode.data;
56166a78 12
fe45dd5f 13 var nodename = vm.node;
56166a78
DM
14 if (!nodename) {
15 throw "no node name specified";
16 }
17
fe45dd5f 18 var vmid = vm.vmid;
56166a78
DM
19 if (!vmid) {
20 throw "no VM ID specified";
21 }
22
fe45dd5f 23 var template = !!vm.template;
3a8508a8 24
fe45dd5f 25 var running = !!vm.uptime;
9fe20b3f 26
56166a78
DM
27 var caps = Ext.state.Manager.get('GuiCap');
28
29 var base_url = '/nodes/' + nodename + '/lxc/' + vmid;
540fdc8b 30
9cb193cf 31 me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
56166a78 32 url: '/api2/json' + base_url + '/status/current',
f6710aac 33 interval: 1000,
56166a78
DM
34 });
35
36 var vm_command = function(cmd, params) {
e7ade592 37 Proxmox.Utils.API2Request({
56166a78
DM
38 params: params,
39 url: base_url + "/status/" + cmd,
40 waitMsgTarget: me,
41 method: 'POST',
42 failure: function(response, opts) {
43 Ext.Msg.alert('Error', response.htmlStatus);
f6710aac 44 },
56166a78
DM
45 });
46 };
47
540fdc8b 48 var startBtn = Ext.create('Ext.Button', {
56166a78 49 text: gettext('Start'),
9fe20b3f 50 disabled: !caps.vms['VM.PowerMgmt'] || running,
768dd5e4 51 hidden: template,
56166a78
DM
52 handler: function() {
53 vm_command('start');
d4333933 54 },
f6710aac 55 iconCls: 'fa fa-play',
540fdc8b 56 });
56166a78 57
889c7083 58 var shutdownBtn = Ext.create('PVE.button.Split', {
56166a78 59 text: gettext('Shutdown'),
9fe20b3f 60 disabled: !caps.vms['VM.PowerMgmt'] || !running,
768dd5e4 61 hidden: template,
e7ade592 62 confirmMsg: Proxmox.Utils.format_task_description('vzshutdown', vmid),
56166a78
DM
63 handler: function() {
64 vm_command('shutdown');
889c7083
DC
65 },
66 menu: {
8058410f 67 items: [{
ba3c982e
TL
68 text: gettext('Reboot'),
69 disabled: !caps.vms['VM.PowerMgmt'],
70 confirmMsg: Proxmox.Utils.format_task_description('vzreboot', vmid),
71 tooltip: Ext.String.format(gettext('Reboot {0}'), 'CT'),
72 handler: function() {
73 vm_command("reboot");
74 },
f6710aac 75 iconCls: 'fa fa-refresh',
ba3c982e
TL
76 },
77 {
2f13fde3
OB
78 text: gettext('Stop'),
79 disabled: !caps.vms['VM.PowerMgmt'],
80 confirmMsg: Proxmox.Utils.format_task_description('vzstop', vmid),
81 tooltip: Ext.String.format(gettext('Stop {0} immediately'), 'CT'),
82 dangerous: true,
83 handler: function() {
84 vm_command("stop");
85 },
f6710aac
TL
86 iconCls: 'fa fa-stop',
87 }],
d4333933 88 },
f6710aac 89 iconCls: 'fa fa-power-off',
56166a78 90 });
540fdc8b
DC
91
92 var migrateBtn = Ext.create('Ext.Button', {
56166a78
DM
93 text: gettext('Migrate'),
94 disabled: !caps.vms['VM.Migrate'],
3dc5644c 95 hidden: PVE.data.ResourceStore.getNodes().length < 2,
56166a78 96 handler: function() {
540fdc8b 97 var win = Ext.create('PVE.window.Migrate', {
56166a78
DM
98 vmtype: 'lxc',
99 nodename: nodename,
f6710aac 100 vmid: vmid,
56166a78
DM
101 });
102 win.show();
d4333933 103 },
f6710aac 104 iconCls: 'fa fa-send-o',
56166a78
DM
105 });
106
5720fafa 107 var moreBtn = Ext.create('Proxmox.button.Button', {
66b8fc0b 108 text: gettext('More'),
8058410f
TL
109 menu: {
110 items: [
9bad05bd
DC
111 {
112 text: gettext('Clone'),
113 iconCls: 'fa fa-fw fa-clone',
ef725143 114 hidden: !caps.vms['VM.Clone'],
9bad05bd
DC
115 handler: function() {
116 PVE.window.Clone.wrap(nodename, vmid, template, 'lxc');
f6710aac 117 },
9bad05bd
DC
118 },
119 {
120 text: gettext('Convert to template'),
121 disabled: template,
122 xtype: 'pveMenuItem',
123 iconCls: 'fa fa-fw fa-file-o',
ef725143 124 hidden: !caps.vms['VM.Allocate'],
9bad05bd
DC
125 confirmMsg: Proxmox.Utils.format_task_description('vztemplate', vmid),
126 handler: function() {
127 Proxmox.Utils.API2Request({
128 url: base_url + '/template',
129 waitMsgTarget: me,
130 method: 'POST',
131 failure: function(response, opts) {
132 Ext.Msg.alert('Error', response.htmlStatus);
f6710aac 133 },
9bad05bd 134 });
f6710aac 135 },
9bad05bd 136 },
66b8fc0b
TL
137 {
138 iconCls: 'fa fa-heartbeat ',
139 hidden: !caps.nodes['Sys.Console'],
140 text: gettext('Manage HA'),
141 handler: function() {
fe45dd5f 142 var ha = vm.hastate;
66b8fc0b
TL
143 Ext.create('PVE.ha.VMResourceEdit', {
144 vmid: vmid,
145 guestType: 'ct',
53e3ea84 146 isCreate: !ha || ha === 'unmanaged',
66b8fc0b 147 }).show();
f6710aac 148 },
66b8fc0b
TL
149 },
150 {
151 text: gettext('Remove'),
152 disabled: !caps.vms['VM.Allocate'],
153 itemId: 'removeBtn',
154 handler: function() {
2452e18d 155 Ext.create('PVE.window.SafeDestroyGuest', {
66b8fc0b 156 url: base_url,
f6710aac 157 item: { type: 'CT', id: vmid },
2452e18d 158 taskName: 'vzdestroy',
66b8fc0b
TL
159 }).show();
160 },
f6710aac
TL
161 iconCls: 'fa fa-trash-o',
162 },
fa8d3971 163 ],
8058410f 164},
56166a78
DM
165 });
166
56166a78
DM
167 var consoleBtn = Ext.create('PVE.button.ConsoleButton', {
168 disabled: !caps.vms['VM.Console'],
169 consoleType: 'lxc',
4ad508ef 170 consoleName: vm.name,
768dd5e4 171 hidden: template,
56166a78 172 nodename: nodename,
f6710aac 173 vmid: vmid,
56166a78
DM
174 });
175
375d2918
DC
176 var statusTxt = Ext.create('Ext.toolbar.TextItem', {
177 data: {
f6710aac 178 lock: undefined,
375d2918
DC
179 },
180 tpl: [
181 '<tpl if="lock">',
182 '<i class="fa fa-lg fa-lock"></i> ({lock})',
f6710aac
TL
183 '</tpl>',
184 ],
375d2918
DC
185 });
186
d70be8cd
DC
187 let tagsContainer = Ext.create('PVE.panel.TagEditContainer', {
188 tags: vm.tags,
189 listeners: {
190 change: function(tags) {
191 Proxmox.Utils.API2Request({
192 url: base_url + '/config',
193 method: 'PUT',
194 params: {
195 tags,
196 },
197 success: function() {
198 me.statusStore.load();
199 },
200 failure: function(response) {
201 Ext.Msg.alert('Error', response.htmlStatus);
202 me.statusStore.load();
203 },
204 });
205 },
206 },
207 });
375d2918 208
366558a7
DC
209 let vm_text = `${vm.vmid} (${vm.name})`;
210
56166a78 211 Ext.apply(me, {
366558a7 212 title: Ext.String.format(gettext("Container {0} on node '{1}'"), vm_text, nodename),
56166a78 213 hstateid: 'lxctab',
375d2918 214 tbarSpacing: false,
d70be8cd 215 tbar: [statusTxt, tagsContainer, '->', startBtn, shutdownBtn, migrateBtn, consoleBtn, moreBtn],
56166a78
DM
216 defaults: { statusStore: me.statusStore },
217 items: [
218 {
8132a620 219 title: gettext('Summary'),
df0875c2 220 xtype: 'pveGuestSummary',
e62ebded 221 iconCls: 'fa fa-book',
f6710aac
TL
222 itemId: 'summary',
223 },
224 ],
56166a78
DM
225 });
226
768dd5e4 227 if (caps.vms['VM.Console'] && !template) {
d345d7ad
DC
228 me.items.push(
229 {
230 title: gettext('Console'),
d345d7ad
DC
231 itemId: 'consolejs',
232 iconCls: 'fa fa-terminal',
233 xtype: 'pveNoVncConsole',
234 vmid: vmid,
235 consoleType: 'lxc',
236 xtermjs: true,
f6710aac
TL
237 nodename: nodename,
238 },
d345d7ad 239 );
4224e7c4 240 }
540fdc8b 241
e72f4285
DC
242 me.items.push(
243 {
244 title: gettext('Resources'),
245 itemId: 'resources',
246 expandedOnInit: true,
247 iconCls: 'fa fa-cube',
f6710aac 248 xtype: 'pveLxcRessourceView',
e72f4285
DC
249 },
250 {
251 title: gettext('Network'),
252 iconCls: 'fa fa-exchange',
253 itemId: 'network',
f6710aac 254 xtype: 'pveLxcNetworkView',
e72f4285
DC
255 },
256 {
257 title: gettext('DNS'),
258 iconCls: 'fa fa-globe',
259 itemId: 'dns',
f6710aac 260 xtype: 'pveLxcDNS',
e72f4285
DC
261 },
262 {
263 title: gettext('Options'),
264 itemId: 'options',
265 iconCls: 'fa fa-gear',
f6710aac 266 xtype: 'pveLxcOptions',
e72f4285
DC
267 },
268 {
269 title: gettext('Task History'),
270 itemId: 'tasks',
56bc50b8 271 iconCls: 'fa fa-list-alt',
6c60ab5e
DC
272 xtype: 'proxmoxNodeTasks',
273 nodename: nodename,
c313af0f
DC
274 preFilter: {
275 vmid,
276 },
f6710aac 277 },
e72f4285
DC
278 );
279
280 if (caps.vms['VM.Backup']) {
281 me.items.push({
282 title: gettext('Backup'),
283 iconCls: 'fa fa-floppy-o',
284 xtype: 'pveBackupView',
f6710aac 285 itemId: 'backup',
cb6df20c
DC
286 },
287 {
288 title: gettext('Replication'),
289 iconCls: 'fa fa-retweet',
290 xtype: 'pveReplicaView',
f6710aac 291 itemId: 'replication',
e72f4285
DC
292 });
293 }
294
b06d011e
DC
295 if ((caps.vms['VM.Snapshot'] || caps.vms['VM.Snapshot.Rollback'] ||
296 caps.vms['VM.Audit']) && !template) {
4224e7c4
EK
297 me.items.push({
298 title: gettext('Snapshots'),
e62ebded 299 iconCls: 'fa fa-history',
5b1b9360
DC
300 xtype: 'pveGuestSnapshotTree',
301 type: 'lxc',
f6710aac 302 itemId: 'snapshot',
4224e7c4
EK
303 });
304 }
b70496d6 305
4224e7c4
EK
306 if (caps.vms['VM.Console']) {
307 me.items.push(
308 {
e62ebded 309 xtype: 'pveFirewallRules',
4224e7c4 310 title: gettext('Firewall'),
e62ebded
DC
311 iconCls: 'fa fa-shield',
312 allow_iface: true,
313 base_url: base_url + '/firewall/rules',
816b62b0 314 list_refs_url: base_url + '/firewall/refs',
f6710aac 315 itemId: 'firewall',
e62ebded
DC
316 },
317 {
318 xtype: 'pveFirewallOptions',
319 groups: ['firewall'],
320 iconCls: 'fa fa-gear',
c8802a60 321 onlineHelp: 'pve_firewall_vm_container_configuration',
e62ebded
DC
322 title: gettext('Options'),
323 base_url: base_url + '/firewall/options',
324 fwtype: 'vm',
f6710aac 325 itemId: 'firewall-options',
e62ebded
DC
326 },
327 {
328 xtype: 'pveFirewallAliases',
329 title: gettext('Alias'),
330 groups: ['firewall'],
331 iconCls: 'fa fa-external-link',
332 base_url: base_url + '/firewall/aliases',
f6710aac 333 itemId: 'firewall-aliases',
e62ebded
DC
334 },
335 {
336 xtype: 'pveIPSet',
337 title: gettext('IPSet'),
338 groups: ['firewall'],
339 iconCls: 'fa fa-list-ol',
340 base_url: base_url + '/firewall/ipset',
816b62b0 341 list_refs_url: base_url + '/firewall/refs',
f6710aac 342 itemId: 'firewall-ipset',
e62ebded
DC
343 },
344 {
345 title: gettext('Log'),
346 groups: ['firewall'],
347 iconCls: 'fa fa-list',
c8802a60 348 onlineHelp: 'chapter_pve_firewall',
e62ebded 349 itemId: 'firewall-fwlog',
0ee5a21e 350 xtype: 'proxmoxLogView',
f6710aac
TL
351 url: '/api2/extjs' + base_url + '/firewall/log',
352 },
4224e7c4
EK
353 );
354 }
b70496d6 355
8132a620
EK
356 if (caps.vms['Permissions.Modify']) {
357 me.items.push({
358 xtype: 'pveACLView',
359 title: gettext('Permissions'),
360 itemId: 'permissions',
e62ebded 361 iconCls: 'fa fa-unlock',
f6710aac 362 path: '/vms/' + vmid,
8132a620
EK
363 });
364 }
56166a78
DM
365
366 me.callParent();
367
e341425c 368 var prevStatus = 'unknown';
540fdc8b 369 me.mon(me.statusStore, 'load', function(s, records, success) {
56166a78 370 var status;
375d2918 371 var lock;
d70be8cd
DC
372 var rec;
373
56166a78 374 if (!success) {
56166a78
DM
375 status = 'unknown';
376 } else {
d70be8cd 377 rec = s.data.get('status');
56166a78 378 status = rec ? rec.data.value : 'unknown';
3a8508a8 379 rec = s.data.get('template');
23b596dc 380 template = rec ? rec.data.value : false;
375d2918
DC
381 rec = s.data.get('lock');
382 lock = rec ? rec.data.value : undefined;
56166a78 383 }
375d2918
DC
384
385 statusTxt.update({ lock: lock });
386
d70be8cd
DC
387 rec = s.data.get('tags');
388 tagsContainer.loadTags(rec?.data?.value);
389
3a8508a8 390 startBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status === 'running' || template);
56166a78 391 shutdownBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status !== 'running');
66b8fc0b 392 me.down('#removeBtn').setDisabled(!caps.vms['VM.Allocate'] || status !== 'stopped');
3a8508a8 393 consoleBtn.setDisabled(template);
e341425c
SR
394
395 if (prevStatus === 'stopped' && status === 'running') {
396 let con = me.down('#consolejs');
397 if (con) {
398 con.reload();
399 }
400 }
401
402 prevStatus = status;
56166a78
DM
403 });
404
405 me.on('afterrender', function() {
406 me.statusStore.startUpdate();
407 });
408
409 me.on('destroy', function() {
410 me.statusStore.stopUpdate();
411 });
f6710aac 412 },
56166a78 413});