]>
Commit | Line | Data |
---|---|---|
7d44036a | 1 | Ext.define('PVE.qemu.Options', { |
bc0eaf58 | 2 | extend: 'Proxmox.grid.PendingObjectGrid', |
7d44036a DM |
3 | alias: ['widget.PVE.qemu.Options'], |
4 | ||
ba93a9c6 DC |
5 | onlineHelp: 'qm_options', |
6 | ||
8058410f | 7 | initComponent: function() { |
7d44036a | 8 | var me = this; |
7d44036a DM |
9 | |
10 | var nodename = me.pveSelNode.data.node; | |
11 | if (!nodename) { | |
12 | throw "no node name specified"; | |
13 | } | |
14 | ||
15 | var vmid = me.pveSelNode.data.vmid; | |
16 | if (!vmid) { | |
17 | throw "no VM ID specified"; | |
18 | } | |
19 | ||
20 | var caps = Ext.state.Manager.get('GuiCap'); | |
21 | ||
22 | var rows = { | |
23 | name: { | |
24 | required: true, | |
25 | defaultValue: me.pveSelNode.data.name, | |
26 | header: gettext('Name'), | |
27 | editor: caps.vms['VM.Config.Options'] ? { | |
9fccc702 | 28 | xtype: 'proxmoxWindowEdit', |
7d44036a DM |
29 | subject: gettext('Name'), |
30 | items: { | |
3335a948 | 31 | xtype: 'inputpanel', |
8058410f | 32 | items: { |
3335a948 DC |
33 | xtype: 'textfield', |
34 | name: 'name', | |
35 | vtype: 'DnsName', | |
36 | value: '', | |
37 | fieldLabel: gettext('Name'), | |
f6710aac | 38 | allowBlank: true, |
3335a948 DC |
39 | }, |
40 | onGetValues: function(values) { | |
41 | var params = values; | |
42 | if (values.name === undefined || | |
43 | values.name === null || | |
44 | values.name === '') { | |
8058410f | 45 | params = { 'delete': 'name' }; |
3335a948 DC |
46 | } |
47 | return params; | |
f6710aac TL |
48 | }, |
49 | }, | |
50 | } : undefined, | |
7d44036a DM |
51 | }, |
52 | onboot: { | |
53 | header: gettext('Start at boot'), | |
54 | defaultValue: '', | |
e7ade592 | 55 | renderer: Proxmox.Utils.format_boolean, |
7d44036a | 56 | editor: caps.vms['VM.Config.Options'] ? { |
9fccc702 | 57 | xtype: 'proxmoxWindowEdit', |
7d44036a DM |
58 | subject: gettext('Start at boot'), |
59 | items: { | |
896c0d50 | 60 | xtype: 'proxmoxcheckbox', |
7d44036a DM |
61 | name: 'onboot', |
62 | uncheckedValue: 0, | |
63 | defaultValue: 0, | |
64 | deleteDefaultValue: true, | |
f6710aac TL |
65 | fieldLabel: gettext('Start at boot'), |
66 | }, | |
67 | } : undefined, | |
7d44036a DM |
68 | }, |
69 | startup: { | |
70 | header: gettext('Start/Shutdown order'), | |
71 | defaultValue: '', | |
72 | renderer: PVE.Utils.render_kvm_startup, | |
8058410f TL |
73 | editor: caps.vms['VM.Config.Options'] && caps.nodes['Sys.Modify'] |
74 | ? { | |
a255dd7e | 75 | xtype: 'pveWindowStartupEdit', |
f6710aac TL |
76 | onlineHelp: 'qm_startup_and_shutdown', |
77 | } : undefined, | |
7d44036a DM |
78 | }, |
79 | ostype: { | |
80 | header: gettext('OS Type'), | |
81 | editor: caps.vms['VM.Config.Options'] ? 'PVE.qemu.OSTypeEdit' : undefined, | |
82 | renderer: PVE.Utils.render_kvm_ostype, | |
f6710aac | 83 | defaultValue: 'other', |
7d44036a DM |
84 | }, |
85 | bootdisk: { | |
f6710aac | 86 | visible: false, |
7d44036a DM |
87 | }, |
88 | boot: { | |
ec99b1c3 | 89 | header: gettext('Boot Order'), |
7d44036a DM |
90 | defaultValue: 'cdn', |
91 | editor: caps.vms['VM.Config.Disk'] ? 'PVE.qemu.BootOrderEdit' : undefined, | |
16c162ec | 92 | multiKey: ['boot', 'bootdisk'], |
7d44036a | 93 | renderer: function(order, metaData, record, rowIndex, colIndex, store, pending) { |
1cc7c672 SR |
94 | if (/^\s*$/.test(order)) { |
95 | return gettext('(No boot device selected)'); | |
96 | } | |
97 | let boot = PVE.Parser.parsePropertyString(order, "legacy"); | |
98 | if (boot.order) { | |
99 | let list = boot.order.split(';'); | |
100 | let ret = ''; | |
1cc7c672 SR |
101 | list.forEach(dev => { |
102 | if (ret) { | |
103 | ret += ', '; | |
104 | } | |
105 | ret += dev; | |
106 | }); | |
107 | return ret; | |
108 | } | |
109 | ||
110 | // legacy style and fallback | |
55ee6ba1 | 111 | let i; |
7d44036a DM |
112 | var text = ''; |
113 | var bootdisk = me.getObjectValue('bootdisk', undefined, pending); | |
1cc7c672 | 114 | order = boot.legacy || 'cdn'; |
7d44036a | 115 | for (i = 0; i < order.length; i++) { |
7d44036a DM |
116 | if (text) { |
117 | text += ', '; | |
118 | } | |
1cc7c672 | 119 | var sel = order.substring(i, i + 1); |
7d44036a DM |
120 | if (sel === 'c') { |
121 | if (bootdisk) { | |
1cc7c672 | 122 | text += bootdisk; |
7d44036a | 123 | } else { |
5f1b4ea3 | 124 | text += gettext('first disk'); |
7d44036a DM |
125 | } |
126 | } else if (sel === 'n') { | |
1cc7c672 | 127 | text += gettext('any net'); |
7d44036a | 128 | } else if (sel === 'a') { |
1cc7c672 | 129 | text += gettext('Floppy'); |
7d44036a | 130 | } else if (sel === 'd') { |
1cc7c672 | 131 | text += gettext('any CD-ROM'); |
7d44036a DM |
132 | } else { |
133 | text += sel; | |
134 | } | |
135 | } | |
136 | return text; | |
f6710aac | 137 | }, |
7d44036a DM |
138 | }, |
139 | tablet: { | |
140 | header: gettext('Use tablet for pointer'), | |
141 | defaultValue: true, | |
e7ade592 | 142 | renderer: Proxmox.Utils.format_boolean, |
7d44036a | 143 | editor: caps.vms['VM.Config.HWType'] ? { |
9fccc702 | 144 | xtype: 'proxmoxWindowEdit', |
7d44036a DM |
145 | subject: gettext('Use tablet for pointer'), |
146 | items: { | |
896c0d50 | 147 | xtype: 'proxmoxcheckbox', |
7d44036a DM |
148 | name: 'tablet', |
149 | checked: true, | |
150 | uncheckedValue: 0, | |
151 | defaultValue: 1, | |
152 | deleteDefaultValue: true, | |
f6710aac TL |
153 | fieldLabel: gettext('Enabled'), |
154 | }, | |
155 | } : undefined, | |
7d44036a DM |
156 | }, |
157 | hotplug: { | |
158 | header: gettext('Hotplug'), | |
159 | defaultValue: 'disk,network,usb', | |
8058410f | 160 | renderer: PVE.Utils.render_hotplug_features, |
7d44036a | 161 | editor: caps.vms['VM.Config.HWType'] ? { |
9fccc702 | 162 | xtype: 'proxmoxWindowEdit', |
7d44036a DM |
163 | subject: gettext('Hotplug'), |
164 | items: { | |
165 | xtype: 'pveHotplugFeatureSelector', | |
166 | name: 'hotplug', | |
167 | value: '', | |
168 | multiSelect: true, | |
169 | fieldLabel: gettext('Hotplug'), | |
f6710aac TL |
170 | allowBlank: true, |
171 | }, | |
172 | } : undefined, | |
7d44036a DM |
173 | }, |
174 | acpi: { | |
175 | header: gettext('ACPI support'), | |
176 | defaultValue: true, | |
e7ade592 | 177 | renderer: Proxmox.Utils.format_boolean, |
7d44036a | 178 | editor: caps.vms['VM.Config.HWType'] ? { |
9fccc702 | 179 | xtype: 'proxmoxWindowEdit', |
7d44036a DM |
180 | subject: gettext('ACPI support'), |
181 | items: { | |
896c0d50 | 182 | xtype: 'proxmoxcheckbox', |
7d44036a DM |
183 | name: 'acpi', |
184 | checked: true, | |
185 | uncheckedValue: 0, | |
186 | defaultValue: 1, | |
187 | deleteDefaultValue: true, | |
f6710aac TL |
188 | fieldLabel: gettext('Enabled'), |
189 | }, | |
190 | } : undefined, | |
7d44036a | 191 | }, |
7d44036a DM |
192 | kvm: { |
193 | header: gettext('KVM hardware virtualization'), | |
194 | defaultValue: true, | |
e7ade592 | 195 | renderer: Proxmox.Utils.format_boolean, |
7d44036a | 196 | editor: caps.vms['VM.Config.HWType'] ? { |
9fccc702 | 197 | xtype: 'proxmoxWindowEdit', |
7d44036a DM |
198 | subject: gettext('KVM hardware virtualization'), |
199 | items: { | |
896c0d50 | 200 | xtype: 'proxmoxcheckbox', |
7d44036a DM |
201 | name: 'kvm', |
202 | checked: true, | |
203 | uncheckedValue: 0, | |
204 | defaultValue: 1, | |
205 | deleteDefaultValue: true, | |
f6710aac TL |
206 | fieldLabel: gettext('Enabled'), |
207 | }, | |
208 | } : undefined, | |
7d44036a DM |
209 | }, |
210 | freeze: { | |
211 | header: gettext('Freeze CPU at startup'), | |
212 | defaultValue: false, | |
e7ade592 | 213 | renderer: Proxmox.Utils.format_boolean, |
7d44036a | 214 | editor: caps.vms['VM.PowerMgmt'] ? { |
9fccc702 | 215 | xtype: 'proxmoxWindowEdit', |
7d44036a DM |
216 | subject: gettext('Freeze CPU at startup'), |
217 | items: { | |
896c0d50 | 218 | xtype: 'proxmoxcheckbox', |
7d44036a DM |
219 | name: 'freeze', |
220 | uncheckedValue: 0, | |
221 | defaultValue: 0, | |
222 | deleteDefaultValue: true, | |
223 | labelWidth: 140, | |
f6710aac TL |
224 | fieldLabel: gettext('Freeze CPU at startup'), |
225 | }, | |
226 | } : undefined, | |
7d44036a DM |
227 | }, |
228 | localtime: { | |
229 | header: gettext('Use local time for RTC'), | |
0beff18b FE |
230 | defaultValue: '__default__', |
231 | renderer: PVE.Utils.render_localtime, | |
7d44036a | 232 | editor: caps.vms['VM.Config.Options'] ? { |
9fccc702 | 233 | xtype: 'proxmoxWindowEdit', |
7d44036a | 234 | subject: gettext('Use local time for RTC'), |
bc92b15f | 235 | width: 400, |
7d44036a | 236 | items: { |
0beff18b | 237 | xtype: 'proxmoxKVComboBox', |
7d44036a | 238 | name: 'localtime', |
0beff18b FE |
239 | value: '__default__', |
240 | comboItems: [ | |
241 | ['__default__', PVE.Utils.render_localtime('__default__')], | |
242 | [1, PVE.Utils.render_localtime(1)], | |
243 | [0, PVE.Utils.render_localtime(0)], | |
244 | ], | |
7d44036a | 245 | labelWidth: 140, |
f6710aac TL |
246 | fieldLabel: gettext('Use local time for RTC'), |
247 | }, | |
248 | } : undefined, | |
7d44036a DM |
249 | }, |
250 | startdate: { | |
251 | header: gettext('RTC start date'), | |
252 | defaultValue: 'now', | |
253 | editor: caps.vms['VM.Config.Options'] ? { | |
9fccc702 | 254 | xtype: 'proxmoxWindowEdit', |
7d44036a DM |
255 | subject: gettext('RTC start date'), |
256 | items: { | |
dbed4c1c | 257 | xtype: 'proxmoxtextfield', |
7d44036a DM |
258 | name: 'startdate', |
259 | deleteEmpty: true, | |
260 | value: 'now', | |
261 | fieldLabel: gettext('RTC start date'), | |
262 | vtype: 'QemuStartDate', | |
f6710aac TL |
263 | allowBlank: true, |
264 | }, | |
265 | } : undefined, | |
7d44036a DM |
266 | }, |
267 | smbios1: { | |
268 | header: gettext('SMBIOS settings (type1)'), | |
269 | defaultValue: '', | |
270 | renderer: Ext.String.htmlEncode, | |
f6710aac | 271 | editor: caps.vms['VM.Config.HWType'] ? 'PVE.qemu.Smbios1Edit' : undefined, |
7d44036a DM |
272 | }, |
273 | agent: { | |
ea6a4b52 | 274 | header: 'QEMU Guest Agent', |
7d44036a | 275 | defaultValue: false, |
1662ccdb | 276 | renderer: PVE.Utils.render_qga_features, |
7d44036a | 277 | editor: caps.vms['VM.Config.Options'] ? { |
9fccc702 | 278 | xtype: 'proxmoxWindowEdit', |
7d44036a | 279 | subject: gettext('Qemu Agent'), |
ea6a4b52 | 280 | width: 350, |
8c4ec1ae | 281 | onlineHelp: 'qm_qemu_agent', |
7d44036a | 282 | items: { |
1662ccdb | 283 | xtype: 'pveAgentFeatureSelector', |
f6710aac TL |
284 | name: 'agent', |
285 | }, | |
286 | } : undefined, | |
7d44036a DM |
287 | }, |
288 | protection: { | |
16152937 | 289 | header: gettext('Protection'), |
7d44036a | 290 | defaultValue: false, |
e7ade592 | 291 | renderer: Proxmox.Utils.format_boolean, |
7d44036a | 292 | editor: caps.vms['VM.Config.Options'] ? { |
9fccc702 | 293 | xtype: 'proxmoxWindowEdit', |
16152937 | 294 | subject: gettext('Protection'), |
7d44036a | 295 | items: { |
896c0d50 | 296 | xtype: 'proxmoxcheckbox', |
7d44036a DM |
297 | name: 'protection', |
298 | uncheckedValue: 0, | |
299 | defaultValue: 0, | |
300 | deleteDefaultValue: true, | |
f6710aac TL |
301 | fieldLabel: gettext('Enabled'), |
302 | }, | |
303 | } : undefined, | |
95f2a8a2 | 304 | }, |
9c22da32 AL |
305 | spice_enhancements: { |
306 | header: gettext('Spice Enhancements'), | |
307 | defaultValue: false, | |
8058410f | 308 | renderer: PVE.Utils.render_spice_enhancements, |
9c22da32 AL |
309 | editor: caps.vms['VM.Config.Options'] ? { |
310 | xtype: 'proxmoxWindowEdit', | |
311 | subject: gettext('Spice Enhancements'), | |
312 | onlineHelp: 'qm_spice_enhancements', | |
313 | items: { | |
314 | xtype: 'pveSpiceEnhancementSelector', | |
315 | name: 'spice_enhancements', | |
f6710aac TL |
316 | }, |
317 | } : undefined, | |
9c22da32 | 318 | }, |
ab84ee74 DC |
319 | vmstatestorage: { |
320 | header: gettext('VM State storage'), | |
321 | defaultValue: '', | |
322 | renderer: val => val || gettext('Automatic'), | |
323 | editor: caps.vms['VM.Config.Options'] ? { | |
324 | xtype: 'proxmoxWindowEdit', | |
325 | subject: gettext('VM State storage'), | |
4fe2c21c | 326 | onlineHelp: 'chapter_virtual_machines', // FIXME: use 'qm_vmstatestorage' once available |
56054937 | 327 | width: 350, |
ab84ee74 DC |
328 | items: { |
329 | xtype: 'pveStorageSelector', | |
330 | storageContent: 'images', | |
331 | allowBlank: true, | |
56054937 | 332 | emptyText: gettext("Automatic (Storage used by the VM, or 'local')"), |
ab84ee74 DC |
333 | autoSelect: false, |
334 | deleteEmpty: true, | |
335 | skipEmptyText: true, | |
336 | nodename: nodename, | |
337 | name: 'vmstatestorage', | |
f6710aac TL |
338 | }, |
339 | } : undefined, | |
ab84ee74 | 340 | }, |
95f2a8a2 | 341 | hookscript: { |
f6710aac TL |
342 | header: gettext('Hookscript'), |
343 | }, | |
7d44036a DM |
344 | }; |
345 | ||
346 | var baseurl = 'nodes/' + nodename + '/qemu/' + vmid + '/config'; | |
347 | ||
7d44036a DM |
348 | var edit_btn = new Ext.Button({ |
349 | text: gettext('Edit'), | |
350 | disabled: true, | |
f6710aac | 351 | handler: function() { me.run_editor(); }, |
7d44036a DM |
352 | }); |
353 | ||
417f904f | 354 | var revert_btn = new PVE.button.PendingRevert(); |
7d44036a DM |
355 | |
356 | var set_button_status = function() { | |
357 | var sm = me.getSelectionModel(); | |
358 | var rec = sm.getSelection()[0]; | |
359 | ||
360 | if (!rec) { | |
361 | edit_btn.disable(); | |
362 | return; | |
363 | } | |
364 | ||
365 | var key = rec.data.key; | |
399ffa76 | 366 | var pending = rec.data.delete || me.hasPendingChanges(key); |
7d44036a DM |
367 | var rowdef = rows[key]; |
368 | ||
369 | edit_btn.setDisabled(!rowdef.editor); | |
370 | revert_btn.setDisabled(!pending); | |
371 | }; | |
372 | ||
a26cb711 | 373 | Ext.apply(me, { |
7d44036a DM |
374 | url: "/api2/json/nodes/" + nodename + "/qemu/" + vmid + "/pending", |
375 | interval: 5000, | |
3c813f74 | 376 | cwidth1: 250, |
8058410f | 377 | tbar: [edit_btn, revert_btn], |
7d44036a | 378 | rows: rows, |
998922c3 | 379 | editorConfig: { |
f6710aac | 380 | url: "/api2/extjs/" + baseurl, |
998922c3 | 381 | }, |
7d44036a | 382 | listeners: { |
998922c3 | 383 | itemdblclick: me.run_editor, |
f6710aac TL |
384 | selectionchange: set_button_status, |
385 | }, | |
7d44036a DM |
386 | }); |
387 | ||
388 | me.callParent(); | |
389 | ||
43364516 TL |
390 | me.on('activate', () => me.rstore.startUpdate()); |
391 | me.on('destroy', () => me.rstore.stopUpdate()); | |
392 | me.on('deactivate', () => me.rstore.stopUpdate()); | |
7d44036a | 393 | |
141aba6b | 394 | me.mon(me.getStore(), 'datachanged', function() { |
7d44036a DM |
395 | set_button_status(); |
396 | }); | |
f6710aac | 397 | }, |
7d44036a DM |
398 | }); |
399 |