]>
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', {
225 canEdit
: !!caps
.vms
['VM.Config.Options'],
227 change: function(tags
) {
228 Proxmox
.Utils
.API2Request({
229 url
: base_url
+ '/config',
234 success: function() {
235 me
.statusStore
.load();
237 failure: function(response
) {
238 Ext
.Msg
.alert('Error', response
.htmlStatus
);
239 me
.statusStore
.load();
246 let vm_text
= `${vm.vmid} (${vm.name})`;
249 title
: Ext
.String
.format(gettext("Virtual Machine {0} on node '{1}'"), vm_text
, nodename
),
252 tbar
: [statusTxt
, tagsContainer
, '->', resumeBtn
, startBtn
, shutdownBtn
, migrateBtn
, consoleBtn
, moreBtn
],
253 defaults
: { statusStore
: me
.statusStore
},
256 title
: gettext('Summary'),
257 xtype
: 'pveGuestSummary',
258 iconCls
: 'fa fa-book',
264 if (caps
.vms
['VM.Console'] && !template
) {
266 title
: gettext('Console'),
268 iconCls
: 'fa fa-terminal',
269 xtype
: 'pveNoVncConsole',
278 title
: gettext('Hardware'),
280 iconCls
: 'fa fa-desktop',
281 xtype
: 'PVE.qemu.HardwareView',
286 iconCls
: 'fa fa-cloud',
290 title
: gettext('Options'),
291 iconCls
: 'fa fa-gear',
293 xtype
: 'PVE.qemu.Options',
296 title
: gettext('Task History'),
298 xtype
: 'proxmoxNodeTasks',
299 iconCls
: 'fa fa-list-alt',
307 if (caps
.vms
['VM.Monitor'] && !template
) {
309 title
: gettext('Monitor'),
310 iconCls
: 'fa fa-eye',
312 xtype
: 'pveQemuMonitor',
316 if (caps
.vms
['VM.Backup']) {
318 title
: gettext('Backup'),
319 iconCls
: 'fa fa-floppy-o',
320 xtype
: 'pveBackupView',
324 title
: gettext('Replication'),
325 iconCls
: 'fa fa-retweet',
326 xtype
: 'pveReplicaView',
327 itemId
: 'replication',
331 if ((caps
.vms
['VM.Snapshot'] || caps
.vms
['VM.Snapshot.Rollback'] ||
332 caps
.vms
['VM.Audit']) && !template
) {
334 title
: gettext('Snapshots'),
335 iconCls
: 'fa fa-history',
337 xtype
: 'pveGuestSnapshotTree',
342 if (caps
.vms
['VM.Audit']) {
345 xtype
: 'pveFirewallRules',
346 title
: gettext('Firewall'),
347 iconCls
: 'fa fa-shield',
349 base_url
: base_url
+ '/firewall/rules',
350 list_refs_url
: base_url
+ '/firewall/refs',
354 xtype
: 'pveFirewallOptions',
355 groups
: ['firewall'],
356 iconCls
: 'fa fa-gear',
357 onlineHelp
: 'pve_firewall_vm_container_configuration',
358 title
: gettext('Options'),
359 base_url
: base_url
+ '/firewall/options',
361 itemId
: 'firewall-options',
364 xtype
: 'pveFirewallAliases',
365 title
: gettext('Alias'),
366 groups
: ['firewall'],
367 iconCls
: 'fa fa-external-link',
368 base_url
: base_url
+ '/firewall/aliases',
369 itemId
: 'firewall-aliases',
373 title
: gettext('IPSet'),
374 groups
: ['firewall'],
375 iconCls
: 'fa fa-list-ol',
376 base_url
: base_url
+ '/firewall/ipset',
377 list_refs_url
: base_url
+ '/firewall/refs',
378 itemId
: 'firewall-ipset',
383 if (caps
.vms
['VM.Console']) {
386 title
: gettext('Log'),
387 groups
: ['firewall'],
388 iconCls
: 'fa fa-list',
389 onlineHelp
: 'chapter_pve_firewall',
390 itemId
: 'firewall-fwlog',
391 xtype
: 'proxmoxLogView',
392 url
: '/api2/extjs' + base_url
+ '/firewall/log',
397 if (caps
.vms
['Permissions.Modify']) {
400 title
: gettext('Permissions'),
401 iconCls
: 'fa fa-unlock',
402 itemId
: 'permissions',
403 path
: '/vms/' + vmid
,
409 var prevQMPStatus
= 'unknown';
410 me
.mon(me
.statusStore
, 'load', function(s
, records
, success
) {
419 status
= qmpstatus
= 'unknown';
421 rec
= s
.data
.get('status');
422 status
= rec
? rec
.data
.value
: 'unknown';
423 rec
= s
.data
.get('qmpstatus');
424 qmpstatus
= rec
? rec
.data
.value
: 'unknown';
425 rec
= s
.data
.get('template');
426 template
= rec
? rec
.data
.value
: false;
427 rec
= s
.data
.get('lock');
428 lock
= rec
? rec
.data
.value
: undefined;
430 spice
= !!s
.data
.get('spice');
431 xtermjs
= !!s
.data
.get('serial');
434 rec
= s
.data
.get('tags');
435 tagsContainer
.loadTags(rec
?.data
?.value
);
441 var resume
= ['prelaunch', 'paused', 'suspended'].indexOf(qmpstatus
) !== -1;
443 if (resume
|| lock
=== 'suspended') {
444 startBtn
.setVisible(false);
445 resumeBtn
.setVisible(true);
447 startBtn
.setVisible(true);
448 resumeBtn
.setVisible(false);
451 consoleBtn
.setEnableSpice(spice
);
452 consoleBtn
.setEnableXtermJS(xtermjs
);
454 statusTxt
.update({ lock
: lock
});
456 let guest_running
= status
=== 'running' &&
457 !(qmpstatus
=== "shutdown" || qmpstatus
=== "prelaunch");
458 startBtn
.setDisabled(!caps
.vms
['VM.PowerMgmt'] || template
|| guest_running
);
460 shutdownBtn
.setDisabled(!caps
.vms
['VM.PowerMgmt'] || status
!== 'running');
461 me
.down('#removeBtn').setDisabled(!caps
.vms
['VM.Allocate'] || status
!== 'stopped');
462 consoleBtn
.setDisabled(template
);
464 let wasStopped
= ['prelaunch', 'stopped', 'suspended'].indexOf(prevQMPStatus
) !== -1;
465 if (wasStopped
&& qmpstatus
=== 'running') {
466 let con
= me
.down('#console');
472 prevQMPStatus
= qmpstatus
;
475 me
.on('afterrender', function() {
476 me
.statusStore
.startUpdate();
479 me
.on('destroy', function() {
480 me
.statusStore
.stopUpdate();