]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/qemu/Clone.js
use DiskStorageSelector in qemu/HDEfi.js
[pve-manager.git] / www / manager6 / qemu / Clone.js
CommitLineData
f5226cd9
DM
1Ext.define('PVE.window.Clone', {
2 extend: 'Ext.window.Window',
3
4 resizable: false,
5
6 isTemplate: false,
7
ff79a116
DM
8 onlineHelp: 'qm_copy_and_clone',
9
26693bb9
EK
10 controller: {
11 xclass: 'Ext.app.ViewController',
12 control: {
13 'panel[reference=cloneform]': {
14 validitychange: 'disableSubmit'
15 }
16 },
17 disableSubmit: function(form) {
18 this.lookupReference('submitBtn').setDisabled(!form.isValid());
19 }
20 },
21
4e2b6cc8
EK
22 statics: {
23 // display a snapshot selector only if needed
24 wrap: function(nodename, vmid, isTemplate) {
25 PVE.Utils.API2Request({
26 url: '/nodes/' + nodename + '/qemu/' + vmid +'/snapshot',
27 failure: function(response, opts) {
28 Ext.Msg.alert('Error', response.htmlStatus);
29 },
30 success: function(response, opts) {
31 var snapshotList = response.result.data;
32 var hasSnapshots = snapshotList.length === 1 &&
33 snapshotList[0].name === 'current' ? false : true;
34
35 Ext.create('PVE.window.Clone', {
36 nodename: nodename,
37 vmid: vmid,
38 isTemplate: isTemplate,
39 hasSnapshots: hasSnapshots
40 }).show();
41 }
42 });
43 }
44 },
2f3c5c38 45
f5226cd9
DM
46 create_clone: function(values) {
47 var me = this;
48
406ac585 49 var params = { newid: values.newvmid };
f5226cd9 50
406ac585
EK
51 if (values.snapname && values.snapname !== 'current') {
52 params.snapname = values.snapname;
53 }
f5226cd9
DM
54
55 if (values.pool) {
56 params.pool = values.pool;
57 }
58
59 if (values.name) {
60 params.name = values.name;
61 }
62
63 if (values.target) {
64 params.target = values.target;
65 }
66
67 if (values.clonemode === 'copy') {
68 params.full = 1;
69 if (values.storage) {
70 params.storage = values.storage;
71 if (values.diskformat) {
72 params.format = values.diskformat;
73 }
74 }
75 }
76
77 PVE.Utils.API2Request({
78 params: params,
79 url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/clone',
80 waitMsgTarget: me,
81 method: 'POST',
82 failure: function(response, opts) {
83 Ext.Msg.alert('Error', response.htmlStatus);
84 },
85 success: function(response, options) {
86 me.close();
87 }
88 });
89
90 },
91
44494b4c
EK
92 // disable the Storage selector when clone mode is linked clone
93 // disable the disk Format selector when
94 // A) clone mode is linked clone
95 // B) clone mode is full clone and storage is block device
f5226cd9
DM
96 updateVisibility: function() {
97 var me = this;
98
406ac585
EK
99 var storagesel = me.lookupReference('storagesel');
100 var formatsel = me.lookupReference('formatsel');
101
102 var clonemode = me.lookupReference('clonemodesel').getValue();
103 var storage = storagesel.getValue();
104 var rec = storagesel.store.getById(storage);
f5226cd9 105
406ac585 106 storagesel.setDisabled(clonemode === 'clone');
f5226cd9
DM
107
108 if (!rec || clonemode === 'clone') {
406ac585 109 formatsel.setDisabled(true);
f5226cd9
DM
110 return;
111 }
112
113 if (rec.data.type === 'lvm' ||
406ac585
EK
114 rec.data.type === 'lvmthin' ||
115 rec.data.type === 'rbd' ||
116 rec.data.type === 'iscsi' ||
117 rec.data.type === 'sheepdog' ||
118 rec.data.type === 'zfs' ||
119 rec.data.type === 'zfspool'
120 ) {
121 formatsel.setValue('raw');
122 formatsel.setDisabled(true);
123 } else {
124 formatsel.setValue('qcow2');
125 formatsel.setDisabled(false);
126 }
f5226cd9
DM
127 },
128
26693bb9 129 // add to the list of valid nodes each node where
44494b4c 130 // all the VM disks are available
f5226cd9
DM
131 verifyFeature: function() {
132 var me = this;
406ac585
EK
133
134 var snapname = me.lookupReference('snapshotsel').getValue();
135 var clonemode = me.lookupReference('clonemodesel').getValue();
f5226cd9
DM
136
137 var params = { feature: clonemode };
138 if (snapname !== 'current') {
139 params.snapname = snapname;
140 }
141
142 PVE.Utils.API2Request({
143 waitMsgTarget: me,
144 url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/feature',
145 params: params,
146 method: 'GET',
147 failure: function(response, opts) {
0057ea5c 148 me.lookupReference('submitBtn').setDisabled(true);
f5226cd9
DM
149 Ext.Msg.alert('Error', response.htmlStatus);
150 },
151 success: function(response, options) {
406ac585 152 var res = response.result.data;
f5226cd9 153
406ac585
EK
154 me.lookupReference('targetsel').allowedNodes = res.nodes;
155 me.lookupReference('targetsel').validate();
f5226cd9
DM
156 }
157 });
158 },
159
160 initComponent : function() {
f5226cd9
DM
161 var me = this;
162
163 if (!me.nodename) {
164 throw "no node name specified";
165 }
166
167 if (!me.vmid) {
168 throw "no VM ID specified";
169 }
170
171 if (!me.snapname) {
172 me.snapname = 'current';
173 }
174
406ac585
EK
175 var titletext = me.isTemplate ? "Template" : "VM";
176 me.title = "Clone " + titletext + " " + me.vmid;
177
f5226cd9
DM
178 var col1 = [];
179 var col2 = [];
180
406ac585
EK
181 col1.push({
182 xtype: 'pveNodeSelector',
f5226cd9 183 name: 'target',
406ac585 184 reference: 'targetsel',
f5226cd9
DM
185 fieldLabel: gettext('Target node'),
186 selectCurNode: true,
187 allowBlank: false,
406ac585
EK
188 onlineValidator: true,
189 listeners: {
190 change: function(f, value) {
191 me.lookupReference('storagesel').setTargetNode(value);
192 }
193 }
f5226cd9
DM
194 });
195
f5226cd9
DM
196 var modelist = [['copy', gettext('Full Clone')]];
197 if (me.isTemplate) {
198 modelist.push(['clone', gettext('Linked Clone')]);
199 }
200
406ac585
EK
201 col1.push({
202 xtype: 'pveGuestIDSelector',
203 name: 'newvmid',
204 guestType: 'qemu',
205 value: '',
206 loadNextFreeID: true,
207 validateExists: false
208 },
209 {
210 xtype: 'textfield',
211 name: 'name',
212 allowBlank: true,
213 fieldLabel: gettext('Name')
214 },
215 {
216 xtype: 'pvePoolSelector',
217 fieldLabel: gettext('Resource Pool'),
218 name: 'pool',
219 value: '',
220 allowBlank: true
221 }
222 );
f5226cd9 223
406ac585
EK
224 col2.push({
225 xtype: 'pveKVComboBox',
226 fieldLabel: gettext('Mode'),
227 name: 'clonemode',
228 reference: 'clonemodesel',
229 allowBlank: false,
230 hidden: !me.isTemplate,
231 value: me.isTemplate ? 'clone' : 'copy',
232 comboItems: modelist,
233 listeners: {
234 change: function(t, value) {
235 me.updateVisibility();
236 me.verifyFeature();
237 }
238 }
239 },
240 {
241 xtype: 'PVE.form.SnapshotSelector',
f5226cd9 242 name: 'snapname',
406ac585 243 reference: 'snapshotsel',
f5226cd9 244 fieldLabel: gettext('Snapshot'),
406ac585
EK
245 nodename: me.nodename,
246 vmid: me.vmid,
2f3c5c38 247 hidden: me.isTemplate || !me.hasSnapshots ? true : false,
406ac585 248 disabled: false,
f5226cd9
DM
249 allowBlank: false,
250 value : me.snapname,
251 listeners: {
252 change: function(f, value) {
253 me.verifyFeature();
254 }
255 }
406ac585
EK
256 },
257 {
258 xtype: 'pveStorageSelector',
259 name: 'storage',
260 reference: 'storagesel',
261 nodename: me.nodename,
262 fieldLabel: gettext('Target Storage'),
263 storageContent: 'images',
22c01a44 264 autoSelect: false, // will use for each disk the same storage as source
406ac585 265 allowBlank: true,
f4f9e662 266 emptyText: gettext('Same as source'),
406ac585 267 disabled: me.isTemplate ? true : false, // because default mode is clone for templates
67cb91e4
EK
268 hidden: false,
269 listeners: {
270 change: function(f, value) {
271 me.updateVisibility();
272 }
273 }
406ac585
EK
274 },
275 {
276 xtype: 'pveDiskFormatSelector',
f5226cd9 277 name: 'diskformat',
406ac585 278 reference: 'formatsel',
f5226cd9
DM
279 fieldLabel: gettext('Format'),
280 value: 'raw',
406ac585
EK
281 disabled: true,
282 hidden: false,
f5226cd9
DM
283 allowBlank: false
284 });
285
406ac585 286 var formPanel = Ext.create('Ext.form.Panel', {
f5226cd9 287 bodyPadding: 10,
26693bb9 288 reference: 'cloneform',
f5226cd9
DM
289 border: false,
290 layout: 'column',
291 defaultType: 'container',
292 columns: 2,
293 fieldDefaults: {
294 labelWidth: 100,
295 anchor: '100%'
296 },
297 items: [
298 {
299 columnWidth: 0.5,
300 padding: '0 10 0 0',
301 layout: 'anchor',
302 items: col1
303 },
304 {
305 columnWidth: 0.5,
306 padding: '0 0 0 10',
307 layout: 'anchor',
308 items: col2
309 }
310 ]
311 });
312
f5226cd9
DM
313 Ext.apply(me, {
314 modal: true,
315 width: 600,
316 height: 250,
317 border: false,
318 layout: 'fit',
406ac585
EK
319 buttons: [ {
320 xtype: 'pveHelpButton',
321 listenToGlobalEvent: false,
322 hidden: false,
323 onlineHelp: me.onlineHelp
324 },
325 '->',
326 {
327 reference: 'submitBtn',
328 text: gettext('Clone'),
329 disabled: true,
330 handler: function() {
331 var cloneForm = me.lookupReference('cloneform');
332 if (cloneForm.isValid()) {
333 me.create_clone(cloneForm.getValues());
334 }
335 }
336 } ],
337 items: [ formPanel ]
f5226cd9
DM
338 });
339
340 me.callParent();
341
342 me.verifyFeature();
343 }
344});