]> git.proxmox.com Git - pve-manager.git/blame_incremental - www/manager6/qemu/Clone.js
use DiskStorageSelector in qemu/HDEfi.js
[pve-manager.git] / www / manager6 / qemu / Clone.js
... / ...
CommitLineData
1Ext.define('PVE.window.Clone', {
2 extend: 'Ext.window.Window',
3
4 resizable: false,
5
6 isTemplate: false,
7
8 onlineHelp: 'qm_copy_and_clone',
9
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
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 },
45
46 create_clone: function(values) {
47 var me = this;
48
49 var params = { newid: values.newvmid };
50
51 if (values.snapname && values.snapname !== 'current') {
52 params.snapname = values.snapname;
53 }
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
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
96 updateVisibility: function() {
97 var me = this;
98
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);
105
106 storagesel.setDisabled(clonemode === 'clone');
107
108 if (!rec || clonemode === 'clone') {
109 formatsel.setDisabled(true);
110 return;
111 }
112
113 if (rec.data.type === 'lvm' ||
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 }
127 },
128
129 // add to the list of valid nodes each node where
130 // all the VM disks are available
131 verifyFeature: function() {
132 var me = this;
133
134 var snapname = me.lookupReference('snapshotsel').getValue();
135 var clonemode = me.lookupReference('clonemodesel').getValue();
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) {
148 me.lookupReference('submitBtn').setDisabled(true);
149 Ext.Msg.alert('Error', response.htmlStatus);
150 },
151 success: function(response, options) {
152 var res = response.result.data;
153
154 me.lookupReference('targetsel').allowedNodes = res.nodes;
155 me.lookupReference('targetsel').validate();
156 }
157 });
158 },
159
160 initComponent : function() {
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
175 var titletext = me.isTemplate ? "Template" : "VM";
176 me.title = "Clone " + titletext + " " + me.vmid;
177
178 var col1 = [];
179 var col2 = [];
180
181 col1.push({
182 xtype: 'pveNodeSelector',
183 name: 'target',
184 reference: 'targetsel',
185 fieldLabel: gettext('Target node'),
186 selectCurNode: true,
187 allowBlank: false,
188 onlineValidator: true,
189 listeners: {
190 change: function(f, value) {
191 me.lookupReference('storagesel').setTargetNode(value);
192 }
193 }
194 });
195
196 var modelist = [['copy', gettext('Full Clone')]];
197 if (me.isTemplate) {
198 modelist.push(['clone', gettext('Linked Clone')]);
199 }
200
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 );
223
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',
242 name: 'snapname',
243 reference: 'snapshotsel',
244 fieldLabel: gettext('Snapshot'),
245 nodename: me.nodename,
246 vmid: me.vmid,
247 hidden: me.isTemplate || !me.hasSnapshots ? true : false,
248 disabled: false,
249 allowBlank: false,
250 value : me.snapname,
251 listeners: {
252 change: function(f, value) {
253 me.verifyFeature();
254 }
255 }
256 },
257 {
258 xtype: 'pveStorageSelector',
259 name: 'storage',
260 reference: 'storagesel',
261 nodename: me.nodename,
262 fieldLabel: gettext('Target Storage'),
263 storageContent: 'images',
264 autoSelect: false, // will use for each disk the same storage as source
265 allowBlank: true,
266 emptyText: gettext('Same as source'),
267 disabled: me.isTemplate ? true : false, // because default mode is clone for templates
268 hidden: false,
269 listeners: {
270 change: function(f, value) {
271 me.updateVisibility();
272 }
273 }
274 },
275 {
276 xtype: 'pveDiskFormatSelector',
277 name: 'diskformat',
278 reference: 'formatsel',
279 fieldLabel: gettext('Format'),
280 value: 'raw',
281 disabled: true,
282 hidden: false,
283 allowBlank: false
284 });
285
286 var formPanel = Ext.create('Ext.form.Panel', {
287 bodyPadding: 10,
288 reference: 'cloneform',
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
313 Ext.apply(me, {
314 modal: true,
315 width: 600,
316 height: 250,
317 border: false,
318 layout: 'fit',
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 ]
338 });
339
340 me.callParent();
341
342 me.verifyFeature();
343 }
344});