]>
Commit | Line | Data |
---|---|---|
1 | Ext.define('PVE.qemu.CmdMenu', { | |
2 | extend: 'Ext.menu.Menu', | |
3 | ||
4 | showSeparator: false, | |
5 | initComponent: function() { | |
6 | let me = this; | |
7 | ||
8 | let info = me.pveSelNode.data; | |
9 | if (!info.node) { | |
10 | throw "no node name specified"; | |
11 | } | |
12 | if (!info.vmid) { | |
13 | throw "no VM ID specified"; | |
14 | } | |
15 | ||
16 | let vm_command = function(cmd, params) { | |
17 | Proxmox.Utils.API2Request({ | |
18 | params: params, | |
19 | url: `/nodes/${info.node}/${info.type}/${info.vmid}/status/${cmd}`, | |
20 | method: 'POST', | |
21 | failure: (response, opts) => Ext.Msg.alert(gettext('Error'), response.htmlStatus), | |
22 | }); | |
23 | }; | |
24 | let confirmedVMCommand = (cmd, params, confirmTask) => { | |
25 | let task = confirmTask || `qm${cmd}`; | |
26 | let msg = Proxmox.Utils.format_task_description(task, info.vmid); | |
27 | Ext.Msg.confirm(gettext('Confirm'), msg, btn => { | |
28 | if (btn === 'yes') { | |
29 | vm_command(cmd, params); | |
30 | } | |
31 | }); | |
32 | }; | |
33 | ||
34 | let caps = Ext.state.Manager.get('GuiCap'); | |
35 | let standalone = PVE.data.ResourceStore.getNodes().length < 2; | |
36 | ||
37 | let running = false, stopped = true, suspended = false; | |
38 | switch (info.status) { | |
39 | case 'running': | |
40 | running = true; | |
41 | stopped = false; | |
42 | break; | |
43 | case 'suspended': | |
44 | stopped = false; | |
45 | suspended = true; | |
46 | break; | |
47 | case 'paused': | |
48 | stopped = false; | |
49 | suspended = true; | |
50 | break; | |
51 | default: break; | |
52 | } | |
53 | ||
54 | me.title = "VM " + info.vmid; | |
55 | ||
56 | me.items = [ | |
57 | { | |
58 | text: gettext('Start'), | |
59 | iconCls: 'fa fa-fw fa-play', | |
60 | hidden: running || suspended, | |
61 | disabled: running || suspended, | |
62 | handler: () => vm_command('start'), | |
63 | }, | |
64 | { | |
65 | text: gettext('Pause'), | |
66 | iconCls: 'fa fa-fw fa-pause', | |
67 | hidden: stopped || suspended, | |
68 | disabled: stopped || suspended, | |
69 | handler: () => confirmedVMCommand('suspend', undefined, 'qmpause'), | |
70 | }, | |
71 | { | |
72 | text: gettext('Hibernate'), | |
73 | iconCls: 'fa fa-fw fa-download', | |
74 | hidden: stopped || suspended, | |
75 | disabled: stopped || suspended, | |
76 | tooltip: gettext('Suspend to disk'), | |
77 | handler: () => confirmedVMCommand('suspend', { todisk: 1 }), | |
78 | }, | |
79 | { | |
80 | text: gettext('Resume'), | |
81 | iconCls: 'fa fa-fw fa-play', | |
82 | hidden: !suspended, | |
83 | handler: () => vm_command('resume'), | |
84 | }, | |
85 | { | |
86 | text: gettext('Shutdown'), | |
87 | iconCls: 'fa fa-fw fa-power-off', | |
88 | disabled: stopped || suspended, | |
89 | handler: () => confirmedVMCommand('shutdown'), | |
90 | }, | |
91 | { | |
92 | text: gettext('Stop'), | |
93 | iconCls: 'fa fa-fw fa-stop', | |
94 | disabled: stopped, | |
95 | tooltip: Ext.String.format(gettext('Stop {0} immediately'), 'VM'), | |
96 | handler: () => confirmedVMCommand('stop'), | |
97 | }, | |
98 | { | |
99 | text: gettext('Reboot'), | |
100 | iconCls: 'fa fa-fw fa-refresh', | |
101 | disabled: stopped, | |
102 | tooltip: Ext.String.format(gettext('Reboot {0}'), 'VM'), | |
103 | handler: () => confirmedVMCommand('reboot'), | |
104 | }, | |
105 | { | |
106 | xtype: 'menuseparator', | |
107 | hidden: (standalone || !caps.vms['VM.Migrate']) && !caps.vms['VM.Allocate'] && !caps.vms['VM.Clone'], | |
108 | }, | |
109 | { | |
110 | text: gettext('Migrate'), | |
111 | iconCls: 'fa fa-fw fa-send-o', | |
112 | hidden: standalone || !caps.vms['VM.Migrate'], | |
113 | handler: function() { | |
114 | Ext.create('PVE.window.Migrate', { | |
115 | vmtype: 'qemu', | |
116 | nodename: info.node, | |
117 | vmid: info.vmid, | |
118 | autoShow: true, | |
119 | }); | |
120 | }, | |
121 | }, | |
122 | { | |
123 | text: gettext('Clone'), | |
124 | iconCls: 'fa fa-fw fa-clone', | |
125 | hidden: !caps.vms['VM.Clone'], | |
126 | handler: () => PVE.window.Clone.wrap(info.node, info.vmid, me.isTemplate, 'qemu'), | |
127 | }, | |
128 | { | |
129 | text: gettext('Convert to template'), | |
130 | iconCls: 'fa fa-fw fa-file-o', | |
131 | hidden: !caps.vms['VM.Allocate'], | |
132 | handler: function() { | |
133 | let msg = Proxmox.Utils.format_task_description('qmtemplate', info.vmid); | |
134 | Ext.Msg.confirm(gettext('Confirm'), msg, btn => { | |
135 | if (btn === 'yes') { | |
136 | Proxmox.Utils.API2Request({ | |
137 | url: `/nodes/${info.node}/qemu/${info.vmid}/template`, | |
138 | method: 'POST', | |
139 | failure: (response, opts) => Ext.Msg.alert('Error', response.htmlStatus), | |
140 | }); | |
141 | } | |
142 | }); | |
143 | }, | |
144 | }, | |
145 | { xtype: 'menuseparator' }, | |
146 | { | |
147 | text: gettext('Console'), | |
148 | iconCls: 'fa fa-fw fa-terminal', | |
149 | handler: function() { | |
150 | Proxmox.Utils.API2Request({ | |
151 | url: `/nodes/${info.node}/qemu/${info.vmid}/status/current`, | |
152 | failure: (response, opts) => Ext.Msg.alert('Error', response.htmlStatus), | |
153 | success: function({ result: { data } }, opts) { | |
154 | PVE.Utils.openDefaultConsoleWindow( | |
155 | { | |
156 | spice: data.spice, | |
157 | xtermjs: data.serial, | |
158 | }, | |
159 | 'kvm', | |
160 | info.vmid, | |
161 | info.node, | |
162 | info.name, | |
163 | ); | |
164 | }, | |
165 | }); | |
166 | }, | |
167 | }, | |
168 | ]; | |
169 | ||
170 | me.callParent(); | |
171 | }, | |
172 | }); |