]>
Commit | Line | Data |
---|---|---|
df15b3da | 1 | /*jslint confusion: true */ |
d5e771ce | 2 | /* 'change' property is assigned a string and then a function */ |
df15b3da DM |
3 | Ext.define('PVE.qemu.HDInputPanel', { |
4 | extend: 'PVE.panel.InputPanel', | |
85806e47 | 5 | alias: 'widget.pveQemuHDInputPanel', |
c8802a60 | 6 | onlineHelp: 'qm_hard_disk', |
df15b3da DM |
7 | |
8 | insideWizard: false, | |
9 | ||
10 | unused: false, // ADD usused disk imaged | |
11 | ||
12 | vmconfig: {}, // used to select usused disks | |
13 | ||
180d7ef5 DM |
14 | controller: { |
15 | ||
16 | xclass: 'Ext.app.ViewController', | |
17 | ||
18 | onControllerChange: function(field) { | |
19 | var value = field.getValue(); | |
ed1ac8f4 TL |
20 | |
21 | var allowIOthread = value.match(/^(virtio|scsi)/); | |
22 | this.lookup('iothread').setDisabled(!allowIOthread); | |
23 | if (!allowIOthread) { | |
24 | this.lookup('iothread').setValue(false); | |
25 | } | |
36958639 TL |
26 | |
27 | var allowDiscard = value.match(/^scsi/); | |
28 | this.lookup('discard').setDisabled(!allowDiscard); | |
29 | if (!allowDiscard) { | |
30 | this.lookup('discard').setValue(false); | |
31 | } | |
180d7ef5 DM |
32 | }, |
33 | ||
34 | control: { | |
9cac6b75 | 35 | 'field[name=controller]': { |
180d7ef5 DM |
36 | change: 'onControllerChange', |
37 | afterrender: 'onControllerChange' | |
9cac6b75 DM |
38 | }, |
39 | 'field[name=hdstorage]': { | |
40 | change: function(f, value) { | |
41 | if (!value) { // initial store loading fires an unwanted 'change' | |
42 | return; | |
43 | } | |
44 | var me = this.getView(); | |
45 | var rec = f.store.getById(value); | |
46 | if (rec.data.type === 'iscsi') { | |
47 | me.hdfilesel.setStorage(value); | |
48 | me.hdfilesel.setDisabled(false); | |
49 | me.formatsel.setValue('raw'); | |
50 | me.formatsel.setDisabled(true); | |
51 | me.hdfilesel.setVisible(true); | |
52 | me.hdsizesel.setDisabled(true); | |
53 | me.hdsizesel.setVisible(false); | |
54 | } else if (rec.data.type === 'lvm' || | |
55 | rec.data.type === 'lvmthin' || | |
56 | rec.data.type === 'drbd' || | |
57 | rec.data.type === 'rbd' || | |
58 | rec.data.type === 'sheepdog' || | |
59 | rec.data.type === 'zfs' || | |
60 | rec.data.type === 'zfspool') { | |
61 | me.hdfilesel.setDisabled(true); | |
62 | me.hdfilesel.setVisible(false); | |
63 | me.formatsel.setValue('raw'); | |
64 | me.formatsel.setDisabled(true); | |
65 | me.hdsizesel.setDisabled(false); | |
66 | me.hdsizesel.setVisible(true); | |
67 | } else { | |
68 | me.hdfilesel.setDisabled(true); | |
69 | me.hdfilesel.setVisible(false); | |
70 | me.formatsel.setValue('qcow2'); | |
71 | me.formatsel.setDisabled(false); | |
72 | me.hdsizesel.setDisabled(false); | |
73 | me.hdsizesel.setVisible(true); | |
74 | } | |
75 | } | |
180d7ef5 DM |
76 | } |
77 | } | |
78 | }, | |
79 | ||
df15b3da DM |
80 | onGetValues: function(values) { |
81 | var me = this; | |
82 | ||
9a8a5735 | 83 | var params = {}; |
df15b3da | 84 | var confid = me.confid || (values.controller + values.deviceid); |
7a6e0635 | 85 | |
df15b3da DM |
86 | if (me.unused) { |
87 | me.drive.file = me.vmconfig[values.unusedId]; | |
88 | confid = values.controller + values.deviceid; | |
d5e771ce | 89 | } else if (me.isCreate) { |
df15b3da DM |
90 | if (values.hdimage) { |
91 | me.drive.file = values.hdimage; | |
92 | } else { | |
93 | me.drive.file = values.hdstorage + ":" + values.disksize; | |
94 | } | |
95 | me.drive.format = values.diskformat; | |
96 | } | |
7a6e0635 | 97 | |
df15b3da DM |
98 | if (values.nobackup) { |
99 | me.drive.backup = 'no'; | |
100 | } else { | |
101 | delete me.drive.backup; | |
102 | } | |
103 | ||
1b6f87ab EK |
104 | if (values.noreplicate) { |
105 | me.drive.replicate = 'no'; | |
106 | } else { | |
107 | delete me.drive.replicate; | |
108 | } | |
109 | ||
df15b3da DM |
110 | if (values.discard) { |
111 | me.drive.discard = 'on'; | |
112 | } else { | |
113 | delete me.drive.discard; | |
114 | } | |
115 | ||
ed1ac8f4 | 116 | if (values.iothread) { |
df15b3da | 117 | me.drive.iothread = 'on'; |
2a2dce70 EK |
118 | // do not silently change a VM-wide option after creating it |
119 | if (me.insideWizard) { | |
120 | params.scsihw = 'virtio-scsi-single'; | |
121 | } | |
df15b3da DM |
122 | } else { |
123 | delete me.drive.iothread; | |
124 | } | |
125 | ||
126 | if (values.cache) { | |
127 | me.drive.cache = values.cache; | |
128 | } else { | |
129 | delete me.drive.cache; | |
130 | } | |
131 | ||
df15b3da | 132 | params[confid] = PVE.Parser.printQemuDrive(me.drive); |
7a6e0635 TL |
133 | |
134 | return params; | |
df15b3da DM |
135 | }, |
136 | ||
137 | setVMConfig: function(vmconfig) { | |
138 | var me = this; | |
139 | ||
140 | me.vmconfig = vmconfig; | |
141 | ||
142 | if (me.bussel) { | |
143 | me.bussel.setVMConfig(vmconfig, true); | |
144 | } | |
145 | if (me.unusedDisks) { | |
7a6e0635 | 146 | var disklist = []; |
df15b3da DM |
147 | Ext.Object.each(vmconfig, function(key, value) { |
148 | if (key.match(/^unused\d+$/)) { | |
149 | disklist.push([key, value]); | |
150 | } | |
151 | }); | |
152 | me.unusedDisks.store.loadData(disklist); | |
153 | me.unusedDisks.setValue(me.confid); | |
154 | } | |
155 | }, | |
156 | ||
157 | setDrive: function(drive) { | |
158 | var me = this; | |
159 | ||
160 | me.drive = drive; | |
161 | ||
162 | var values = {}; | |
163 | var match = drive.file.match(/^([^:]+):/); | |
164 | if (match) { | |
165 | values.hdstorage = match[1]; | |
166 | } | |
167 | ||
168 | values.hdimage = drive.file; | |
169 | values.nobackup = !PVE.Parser.parseBoolean(drive.backup, 1); | |
1b6f87ab | 170 | values.noreplicate = !PVE.Parser.parseBoolean(drive.replicate, 1); |
df15b3da | 171 | values.diskformat = drive.format || 'raw'; |
ac7db8f7 | 172 | values.cache = drive.cache || '__default__'; |
df15b3da DM |
173 | values.discard = (drive.discard === 'on'); |
174 | values.iothread = PVE.Parser.parseBoolean(drive.iothread); | |
175 | ||
176 | me.setValues(values); | |
177 | }, | |
178 | ||
179 | setNodename: function(nodename) { | |
180 | var me = this; | |
181 | me.hdstoragesel.setNodename(nodename); | |
182 | me.hdfilesel.setStorage(undefined, nodename); | |
183 | }, | |
184 | ||
185 | initComponent : function() { | |
186 | var me = this; | |
187 | ||
188 | me.drive = {}; | |
189 | ||
190 | me.column1 = []; | |
191 | me.column2 = []; | |
192 | ||
193 | if (!me.confid || me.unused) { | |
42902182 | 194 | me.bussel = Ext.create('PVE.form.ControllerSelector', { |
df15b3da DM |
195 | vmconfig: me.insideWizard ? {ide2: 'cdrom'} : {} |
196 | }); | |
197 | me.column1.push(me.bussel); | |
198 | } | |
199 | ||
200 | if (me.unused) { | |
201 | me.unusedDisks = Ext.create('PVE.form.KVComboBox', { | |
7a6e0635 | 202 | name: 'unusedId', |
df15b3da DM |
203 | fieldLabel: gettext('Disk image'), |
204 | matchFieldWidth: false, | |
205 | listConfig: { | |
206 | width: 350 | |
207 | }, | |
208 | data: [], | |
209 | allowBlank: false | |
210 | }); | |
211 | me.column1.push(me.unusedDisks); | |
d5e771ce | 212 | } else if (me.isCreate) { |
df15b3da DM |
213 | me.formatsel = Ext.create('PVE.form.DiskFormatSelector', { |
214 | name: 'diskformat', | |
215 | fieldLabel: gettext('Format'), | |
216 | value: 'qcow2', | |
217 | allowBlank: false | |
218 | }); | |
219 | ||
220 | me.hdfilesel = Ext.create('PVE.form.FileSelector', { | |
221 | name: 'hdimage', | |
222 | nodename: me.nodename, | |
223 | storageContent: 'images', | |
224 | fieldLabel: gettext('Disk image'), | |
225 | disabled: true, | |
226 | hidden: true, | |
227 | allowBlank: false | |
228 | }); | |
229 | ||
230 | me.hdsizesel = Ext.createWidget('numberfield', { | |
231 | name: 'disksize', | |
232 | minValue: 0.001, | |
233 | maxValue: 128*1024, | |
234 | decimalPrecision: 3, | |
235 | value: '32', | |
236 | fieldLabel: gettext('Disk size') + ' (GB)', | |
237 | allowBlank: false | |
238 | }); | |
239 | ||
240 | me.hdstoragesel = Ext.create('PVE.form.StorageSelector', { | |
241 | name: 'hdstorage', | |
242 | nodename: me.nodename, | |
243 | fieldLabel: gettext('Storage'), | |
244 | storageContent: 'images', | |
245 | autoSelect: me.insideWizard, | |
9cac6b75 | 246 | allowBlank: false |
df15b3da DM |
247 | }); |
248 | me.column1.push(me.hdstoragesel); | |
249 | me.column1.push(me.hdfilesel); | |
250 | me.column1.push(me.hdsizesel); | |
251 | me.column1.push(me.formatsel); | |
252 | ||
253 | } else { | |
254 | me.column1.push({ | |
255 | xtype: 'textfield', | |
256 | disabled: true, | |
257 | submitValue: false, | |
258 | fieldLabel: gettext('Disk image'), | |
259 | name: 'hdimage' | |
260 | }); | |
261 | } | |
262 | ||
263 | me.column2.push({ | |
264 | xtype: 'CacheTypeSelector', | |
265 | name: 'cache', | |
ca6372bd | 266 | value: '__default__', |
df15b3da | 267 | fieldLabel: gettext('Cache') |
2d06e723 TL |
268 | }, |
269 | { | |
df15b3da DM |
270 | xtype: 'pvecheckbox', |
271 | fieldLabel: gettext('No backup'), | |
272 | name: 'nobackup' | |
2d06e723 TL |
273 | }, |
274 | { | |
1b6f87ab EK |
275 | xtype: 'pvecheckbox', |
276 | hidden: me.insideWizard, | |
277 | fieldLabel: gettext('Skip replication'), | |
278 | name: 'noreplicate' | |
2d06e723 TL |
279 | }, |
280 | { | |
df15b3da DM |
281 | xtype: 'pvecheckbox', |
282 | fieldLabel: gettext('Discard'), | |
36958639 TL |
283 | disabled: me.confid && !me.confid.match(/^scsi/), |
284 | reference: 'discard', | |
df15b3da | 285 | name: 'discard' |
2d06e723 TL |
286 | }, |
287 | { | |
df15b3da | 288 | xtype: 'pvecheckbox', |
ed1ac8f4 | 289 | disabled: me.confid && !me.confid.match(/^(virtio|scsi)/), |
185a77e5 | 290 | fieldLabel: gettext('IO thread'), |
180d7ef5 | 291 | reference: 'iothread', |
df15b3da DM |
292 | name: 'iothread' |
293 | }); | |
294 | ||
295 | me.callParent(); | |
296 | } | |
297 | }); | |
d5e771ce | 298 | /*jslint confusion: false */ |
df15b3da DM |
299 | |
300 | Ext.define('PVE.qemu.HDEdit', { | |
301 | extend: 'PVE.window.Edit', | |
302 | ||
303 | isAdd: true, | |
304 | ||
305 | initComponent : function() { | |
306 | var me = this; | |
307 | ||
308 | var nodename = me.pveSelNode.data.node; | |
7a6e0635 TL |
309 | if (!nodename) { |
310 | throw "no node name specified"; | |
df15b3da DM |
311 | } |
312 | ||
313 | var unused = me.confid && me.confid.match(/^unused\d+$/); | |
314 | ||
d5e771ce | 315 | me.isCreate = me.confid ? unused : true; |
df15b3da DM |
316 | |
317 | var ipanel = Ext.create('PVE.qemu.HDInputPanel', { | |
318 | confid: me.confid, | |
319 | nodename: nodename, | |
320 | unused: unused, | |
d5e771ce | 321 | isCreate: me.isCreate |
df15b3da DM |
322 | }); |
323 | ||
324 | var subject; | |
325 | if (unused) { | |
326 | me.subject = gettext('Unused Disk'); | |
d5e771ce | 327 | } else if (me.isCreate) { |
df15b3da DM |
328 | me.subject = gettext('Hard Disk'); |
329 | } else { | |
330 | me.subject = gettext('Hard Disk') + ' (' + me.confid + ')'; | |
331 | } | |
332 | ||
333 | me.items = [ ipanel ]; | |
334 | ||
335 | me.callParent(); | |
d5e771ce EK |
336 | /*jslint confusion: true*/ |
337 | /* 'data' is assigned an empty array in same file, and here we | |
338 | * use it like an object | |
339 | */ | |
df15b3da DM |
340 | me.load({ |
341 | success: function(response, options) { | |
342 | ipanel.setVMConfig(response.result.data); | |
343 | if (me.confid) { | |
344 | var value = response.result.data[me.confid]; | |
345 | var drive = PVE.Parser.parseQemuDrive(me.confid, value); | |
346 | if (!drive) { | |
185a77e5 | 347 | Ext.Msg.alert(gettext('Error'), 'Unable to parse drive options'); |
df15b3da DM |
348 | me.close(); |
349 | return; | |
350 | } | |
351 | ipanel.setDrive(drive); | |
352 | me.isValid(); // trigger validation | |
353 | } | |
354 | } | |
355 | }); | |
d5e771ce | 356 | /*jslint confusion: false*/ |
df15b3da DM |
357 | } |
358 | }); |