]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/qemu/Config.js
1 Ext
.define('PVE.qemu.Config', {
2 extend
: 'PVE.panel.Config',
3 alias
: 'widget.PVE.qemu.Config',
5 onlineHelp
: 'chapter_virtual_machines',
6 userCls
: 'proxmox-tags-full',
8 initComponent: function() {
10 var vm
= me
.pveSelNode
.data
;
12 var nodename
= vm
.node
;
14 throw "no node name specified";
19 throw "no VM ID specified";
22 var template
= !!vm
.template
;
24 var running
= !!vm
.uptime
;
26 var caps
= Ext
.state
.Manager
.get('GuiCap');
28 var base_url
= '/nodes/' + nodename
+ "/qemu/" + vmid
;
30 me
.statusStore
= Ext
.create('Proxmox.data.ObjectStore', {
31 url
: '/api2/json' + base_url
+ '/status/current',
35 var vm_command = function(cmd
, params
) {
36 Proxmox
.Utils
.API2Request({
38 url
: base_url
+ '/status/' + cmd
,
41 failure: function(response
, opts
) {
42 Ext
.Msg
.alert('Error', response
.htmlStatus
);
47 var resumeBtn
= Ext
.create('Ext.Button', {
48 text
: gettext('Resume'),
49 disabled
: !caps
.vms
['VM.PowerMgmt'],
54 iconCls
: 'fa fa-play',
57 var startBtn
= Ext
.create('Ext.Button', {
58 text
: gettext('Start'),
59 disabled
: !caps
.vms
['VM.PowerMgmt'] || running
,
64 iconCls
: 'fa fa-play',
67 var migrateBtn
= Ext
.create('Ext.Button', {
68 text
: gettext('Migrate'),
69 disabled
: !caps
.vms
['VM.Migrate'],
70 hidden
: PVE
.data
.ResourceStore
.getNodes().length
< 2,
72 var win
= Ext
.create('PVE.window.Migrate', {
79 iconCls
: 'fa fa-send-o',
82 var moreBtn
= Ext
.create('Proxmox.button.Button', {
83 text
: gettext('More'),
87 text
: gettext('Clone'),
88 iconCls
: 'fa fa-fw fa-clone',
89 hidden
: !caps
.vms
['VM.Clone'],
91 PVE
.window
.Clone
.wrap(nodename
, vmid
, template
, 'qemu');
95 text
: gettext('Convert to template'),
98 iconCls
: 'fa fa-fw fa-file-o',
99 hidden
: !caps
.vms
['VM.Allocate'],
100 confirmMsg
: Proxmox
.Utils
.format_task_description('qmtemplate', vmid
),
101 handler: function() {
102 Proxmox
.Utils
.API2Request({
103 url
: base_url
+ '/template',
106 failure: function(response
, opts
) {
107 Ext
.Msg
.alert('Error', response
.htmlStatus
);
113 iconCls
: 'fa fa-heartbeat ',
114 hidden
: !caps
.nodes
['Sys.Console'],
115 text
: gettext('Manage HA'),
116 handler: function() {
118 Ext
.create('PVE.ha.VMResourceEdit', {
120 isCreate
: !ha
|| ha
=== 'unmanaged',
125 text
: gettext('Remove'),
127 disabled
: !caps
.vms
['VM.Allocate'],
128 handler: function() {
129 Ext
.create('PVE.window.SafeDestroyGuest', {
131 item
: { type
: 'VM', id
: vmid
},
132 taskName
: 'qmdestroy',
135 iconCls
: 'fa fa-trash-o',
141 var shutdownBtn
= Ext
.create('PVE.button.Split', {
142 text
: gettext('Shutdown'),
143 disabled
: !caps
.vms
['VM.PowerMgmt'] || !running
,
145 confirmMsg
: Proxmox
.Utils
.format_task_description('qmshutdown', vmid
),
146 handler: function() {
147 vm_command('shutdown');
151 text
: gettext('Reboot'),
152 disabled
: !caps
.vms
['VM.PowerMgmt'],
153 tooltip
: Ext
.String
.format(gettext('Shutdown, apply pending changes and reboot {0}'), 'VM'),
154 confirmMsg
: Proxmox
.Utils
.format_task_description('qmreboot', vmid
),
155 handler: function() {
156 vm_command("reboot");
158 iconCls
: 'fa fa-refresh',
160 text
: gettext('Pause'),
161 disabled
: !caps
.vms
['VM.PowerMgmt'],
162 confirmMsg
: Proxmox
.Utils
.format_task_description('qmpause', vmid
),
163 handler: function() {
164 vm_command("suspend");
166 iconCls
: 'fa fa-pause',
168 text
: gettext('Hibernate'),
169 disabled
: !caps
.vms
['VM.PowerMgmt'],
170 confirmMsg
: Proxmox
.Utils
.format_task_description('qmsuspend', vmid
),
171 tooltip
: gettext('Suspend to disk'),
172 handler: function() {
173 vm_command("suspend", { todisk
: 1 });
175 iconCls
: 'fa fa-download',
177 text
: gettext('Stop'),
178 disabled
: !caps
.vms
['VM.PowerMgmt'],
180 tooltip
: Ext
.String
.format(gettext('Stop {0} immediately'), 'VM'),
181 confirmMsg
: Proxmox
.Utils
.format_task_description('qmstop', vmid
),
182 handler: function() {
183 vm_command("stop", { timeout
: 30 });
185 iconCls
: 'fa fa-stop',
187 text
: gettext('Reset'),
188 disabled
: !caps
.vms
['VM.PowerMgmt'],
189 tooltip
: Ext
.String
.format(gettext('Reset {0} immediately'), 'VM'),
190 confirmMsg
: Proxmox
.Utils
.format_task_description('qmreset', vmid
),
191 handler: function() {
194 iconCls
: 'fa fa-bolt',
197 iconCls
: 'fa fa-power-off',
200 var consoleBtn
= Ext
.create('PVE.button.ConsoleButton', {
201 disabled
: !caps
.vms
['VM.Console'],
204 // disable spice/xterm for default action until status api call succeeded
206 enableXtermjs
: false,
207 consoleName
: vm
.name
,
212 var statusTxt
= Ext
.create('Ext.toolbar.TextItem', {
218 '<i class="fa fa-lg fa-lock"></i> ({lock})',
223 let tagsContainer
= Ext
.create('PVE.panel.TagEditContainer', {
226 change: function(tags
) {
227 Proxmox
.Utils
.API2Request({
228 url
: base_url
+ '/config',
233 success: function() {
234 me
.statusStore
.load();
236 failure: function(response
) {
237 Ext
.Msg
.alert('Error', response
.htmlStatus
);
238 me
.statusStore
.load();
245 let vm_text
= `${vm.vmid} (${vm.name})`;
248 title
: Ext
.String
.format(gettext("Virtual Machine {0} on node '{1}'"), vm_text
, nodename
),
251 tbar
: [statusTxt
, tagsContainer
, '->', resumeBtn
, startBtn
, shutdownBtn
, migrateBtn
, consoleBtn
, moreBtn
],
252 defaults
: { statusStore
: me
.statusStore
},
255 title
: gettext('Summary'),
256 xtype
: 'pveGuestSummary',
257 iconCls
: 'fa fa-book',
263 if (caps
.vms
['VM.Console'] && !template
) {
265 title
: gettext('Console'),
267 iconCls
: 'fa fa-terminal',
268 xtype
: 'pveNoVncConsole',
277 title
: gettext('Hardware'),
279 iconCls
: 'fa fa-desktop',
280 xtype
: 'PVE.qemu.HardwareView',
285 iconCls
: 'fa fa-cloud',
289 title
: gettext('Options'),
290 iconCls
: 'fa fa-gear',
292 xtype
: 'PVE.qemu.Options',
295 title
: gettext('Task History'),
297 xtype
: 'proxmoxNodeTasks',
298 iconCls
: 'fa fa-list-alt',
306 if (caps
.vms
['VM.Monitor'] && !template
) {
308 title
: gettext('Monitor'),
309 iconCls
: 'fa fa-eye',
311 xtype
: 'pveQemuMonitor',
315 if (caps
.vms
['VM.Backup']) {
317 title
: gettext('Backup'),
318 iconCls
: 'fa fa-floppy-o',
319 xtype
: 'pveBackupView',
323 title
: gettext('Replication'),
324 iconCls
: 'fa fa-retweet',
325 xtype
: 'pveReplicaView',
326 itemId
: 'replication',
330 if ((caps
.vms
['VM.Snapshot'] || caps
.vms
['VM.Snapshot.Rollback'] ||
331 caps
.vms
['VM.Audit']) && !template
) {
333 title
: gettext('Snapshots'),
334 iconCls
: 'fa fa-history',
336 xtype
: 'pveGuestSnapshotTree',
341 if (caps
.vms
['VM.Console']) {
344 xtype
: 'pveFirewallRules',
345 title
: gettext('Firewall'),
346 iconCls
: 'fa fa-shield',
348 base_url
: base_url
+ '/firewall/rules',
349 list_refs_url
: base_url
+ '/firewall/refs',
353 xtype
: 'pveFirewallOptions',
354 groups
: ['firewall'],
355 iconCls
: 'fa fa-gear',
356 onlineHelp
: 'pve_firewall_vm_container_configuration',
357 title
: gettext('Options'),
358 base_url
: base_url
+ '/firewall/options',
360 itemId
: 'firewall-options',
363 xtype
: 'pveFirewallAliases',
364 title
: gettext('Alias'),
365 groups
: ['firewall'],
366 iconCls
: 'fa fa-external-link',
367 base_url
: base_url
+ '/firewall/aliases',
368 itemId
: 'firewall-aliases',
372 title
: gettext('IPSet'),
373 groups
: ['firewall'],
374 iconCls
: 'fa fa-list-ol',
375 base_url
: base_url
+ '/firewall/ipset',
376 list_refs_url
: base_url
+ '/firewall/refs',
377 itemId
: 'firewall-ipset',
380 title
: gettext('Log'),
381 groups
: ['firewall'],
382 iconCls
: 'fa fa-list',
383 onlineHelp
: 'chapter_pve_firewall',
384 itemId
: 'firewall-fwlog',
385 xtype
: 'proxmoxLogView',
386 url
: '/api2/extjs' + base_url
+ '/firewall/log',
391 if (caps
.vms
['Permissions.Modify']) {
394 title
: gettext('Permissions'),
395 iconCls
: 'fa fa-unlock',
396 itemId
: 'permissions',
397 path
: '/vms/' + vmid
,
403 var prevQMPStatus
= 'unknown';
404 me
.mon(me
.statusStore
, 'load', function(s
, records
, success
) {
413 status
= qmpstatus
= 'unknown';
415 rec
= s
.data
.get('status');
416 status
= rec
? rec
.data
.value
: 'unknown';
417 rec
= s
.data
.get('qmpstatus');
418 qmpstatus
= rec
? rec
.data
.value
: 'unknown';
419 rec
= s
.data
.get('template');
420 template
= rec
? rec
.data
.value
: false;
421 rec
= s
.data
.get('lock');
422 lock
= rec
? rec
.data
.value
: undefined;
424 spice
= !!s
.data
.get('spice');
425 xtermjs
= !!s
.data
.get('serial');
428 rec
= s
.data
.get('tags');
429 tagsContainer
.loadTags(rec
?.data
?.value
);
435 var resume
= ['prelaunch', 'paused', 'suspended'].indexOf(qmpstatus
) !== -1;
437 if (resume
|| lock
=== 'suspended') {
438 startBtn
.setVisible(false);
439 resumeBtn
.setVisible(true);
441 startBtn
.setVisible(true);
442 resumeBtn
.setVisible(false);
445 consoleBtn
.setEnableSpice(spice
);
446 consoleBtn
.setEnableXtermJS(xtermjs
);
448 statusTxt
.update({ lock
: lock
});
450 let guest_running
= status
=== 'running' &&
451 !(qmpstatus
=== "shutdown" || qmpstatus
=== "prelaunch");
452 startBtn
.setDisabled(!caps
.vms
['VM.PowerMgmt'] || template
|| guest_running
);
454 shutdownBtn
.setDisabled(!caps
.vms
['VM.PowerMgmt'] || status
!== 'running');
455 me
.down('#removeBtn').setDisabled(!caps
.vms
['VM.Allocate'] || status
!== 'stopped');
456 consoleBtn
.setDisabled(template
);
458 let wasStopped
= ['prelaunch', 'stopped', 'suspended'].indexOf(prevQMPStatus
) !== -1;
459 if (wasStopped
&& qmpstatus
=== 'running') {
460 let con
= me
.down('#console');
466 prevQMPStatus
= qmpstatus
;
469 me
.on('afterrender', function() {
470 me
.statusStore
.startUpdate();
473 me
.on('destroy', function() {
474 me
.statusStore
.stopUpdate();