]>
Commit | Line | Data |
---|---|---|
f5226cd9 DM |
1 | Ext.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]': { | |
f6710aac TL |
14 | validitychange: 'disableSubmit', |
15 | }, | |
26693bb9 EK |
16 | }, |
17 | disableSubmit: function(form) { | |
18 | this.lookupReference('submitBtn').setDisabled(!form.isValid()); | |
f6710aac | 19 | }, |
26693bb9 EK |
20 | }, |
21 | ||
4e2b6cc8 EK |
22 | statics: { |
23 | // display a snapshot selector only if needed | |
0718aefc | 24 | wrap: function(nodename, vmid, isTemplate, guestType) { |
e7ade592 | 25 | Proxmox.Utils.API2Request({ |
0718aefc | 26 | url: '/nodes/' + nodename + '/' + guestType + '/' + vmid +'/snapshot', |
4e2b6cc8 EK |
27 | failure: function(response, opts) { |
28 | Ext.Msg.alert('Error', response.htmlStatus); | |
29 | }, | |
30 | success: function(response, opts) { | |
31 | var snapshotList = response.result.data; | |
ef725143 TL |
32 | var hasSnapshots = !(snapshotList.length === 1 && |
33 | snapshotList[0].name === 'current'); | |
4e2b6cc8 EK |
34 | |
35 | Ext.create('PVE.window.Clone', { | |
36 | nodename: nodename, | |
0718aefc | 37 | guestType: guestType, |
4e2b6cc8 EK |
38 | vmid: vmid, |
39 | isTemplate: isTemplate, | |
f6710aac | 40 | hasSnapshots: hasSnapshots, |
4e2b6cc8 | 41 | }).show(); |
f6710aac | 42 | }, |
4e2b6cc8 | 43 | }); |
f6710aac | 44 | }, |
4e2b6cc8 | 45 | }, |
2f3c5c38 | 46 | |
f5226cd9 DM |
47 | create_clone: function(values) { |
48 | var me = this; | |
49 | ||
406ac585 | 50 | var params = { newid: values.newvmid }; |
f5226cd9 | 51 | |
406ac585 EK |
52 | if (values.snapname && values.snapname !== 'current') { |
53 | params.snapname = values.snapname; | |
54 | } | |
f5226cd9 DM |
55 | |
56 | if (values.pool) { | |
57 | params.pool = values.pool; | |
58 | } | |
59 | ||
60 | if (values.name) { | |
0718aefc DC |
61 | if (me.guestType === 'lxc') { |
62 | params.hostname = values.name; | |
63 | } else { | |
64 | params.name = values.name; | |
65 | } | |
f5226cd9 DM |
66 | } |
67 | ||
68 | if (values.target) { | |
69 | params.target = values.target; | |
70 | } | |
71 | ||
72 | if (values.clonemode === 'copy') { | |
73 | params.full = 1; | |
1490ff3d DC |
74 | if (values.hdstorage) { |
75 | params.storage = values.hdstorage; | |
0718aefc | 76 | if (values.diskformat && me.guestType !== 'lxc') { |
f5226cd9 DM |
77 | params.format = values.diskformat; |
78 | } | |
79 | } | |
80 | } | |
81 | ||
e7ade592 | 82 | Proxmox.Utils.API2Request({ |
f5226cd9 | 83 | params: params, |
0718aefc | 84 | url: '/nodes/' + me.nodename + '/' + me.guestType + '/' + me.vmid + '/clone', |
f5226cd9 DM |
85 | waitMsgTarget: me, |
86 | method: 'POST', | |
87 | failure: function(response, opts) { | |
88 | Ext.Msg.alert('Error', response.htmlStatus); | |
89 | }, | |
90 | success: function(response, options) { | |
91 | me.close(); | |
f6710aac | 92 | }, |
f5226cd9 | 93 | }); |
f5226cd9 DM |
94 | }, |
95 | ||
44494b4c | 96 | // disable the Storage selector when clone mode is linked clone |
f5226cd9 DM |
97 | updateVisibility: function() { |
98 | var me = this; | |
406ac585 | 99 | var clonemode = me.lookupReference('clonemodesel').getValue(); |
1490ff3d DC |
100 | var disksel = me.lookup('diskselector'); |
101 | disksel.setDisabled(clonemode === 'clone'); | |
f5226cd9 DM |
102 | }, |
103 | ||
26693bb9 | 104 | // add to the list of valid nodes each node where |
44494b4c | 105 | // all the VM disks are available |
f5226cd9 DM |
106 | verifyFeature: function() { |
107 | var me = this; | |
406ac585 EK |
108 | |
109 | var snapname = me.lookupReference('snapshotsel').getValue(); | |
110 | var clonemode = me.lookupReference('clonemodesel').getValue(); | |
f5226cd9 DM |
111 | |
112 | var params = { feature: clonemode }; | |
113 | if (snapname !== 'current') { | |
114 | params.snapname = snapname; | |
115 | } | |
116 | ||
e7ade592 | 117 | Proxmox.Utils.API2Request({ |
f5226cd9 | 118 | waitMsgTarget: me, |
0718aefc | 119 | url: '/nodes/' + me.nodename + '/' + me.guestType + '/' + me.vmid + '/feature', |
f5226cd9 DM |
120 | params: params, |
121 | method: 'GET', | |
122 | failure: function(response, opts) { | |
0057ea5c | 123 | me.lookupReference('submitBtn').setDisabled(true); |
f5226cd9 DM |
124 | Ext.Msg.alert('Error', response.htmlStatus); |
125 | }, | |
126 | success: function(response, options) { | |
406ac585 | 127 | var res = response.result.data; |
f5226cd9 | 128 | |
406ac585 EK |
129 | me.lookupReference('targetsel').allowedNodes = res.nodes; |
130 | me.lookupReference('targetsel').validate(); | |
f6710aac | 131 | }, |
f5226cd9 DM |
132 | }); |
133 | }, | |
134 | ||
8058410f | 135 | initComponent: function() { |
f5226cd9 DM |
136 | var me = this; |
137 | ||
138 | if (!me.nodename) { | |
139 | throw "no node name specified"; | |
140 | } | |
141 | ||
142 | if (!me.vmid) { | |
143 | throw "no VM ID specified"; | |
144 | } | |
145 | ||
146 | if (!me.snapname) { | |
147 | me.snapname = 'current'; | |
148 | } | |
149 | ||
0718aefc DC |
150 | if (!me.guestType) { |
151 | throw "no Guest Type specified"; | |
152 | } | |
153 | ||
154 | var titletext = me.guestType === 'lxc' ? 'CT' : 'VM'; | |
155 | if (me.isTemplate) { | |
156 | titletext += ' Template'; | |
157 | } | |
406ac585 EK |
158 | me.title = "Clone " + titletext + " " + me.vmid; |
159 | ||
f5226cd9 DM |
160 | var col1 = []; |
161 | var col2 = []; | |
162 | ||
406ac585 EK |
163 | col1.push({ |
164 | xtype: 'pveNodeSelector', | |
f5226cd9 | 165 | name: 'target', |
406ac585 | 166 | reference: 'targetsel', |
f5226cd9 DM |
167 | fieldLabel: gettext('Target node'), |
168 | selectCurNode: true, | |
169 | allowBlank: false, | |
406ac585 EK |
170 | onlineValidator: true, |
171 | listeners: { | |
172 | change: function(f, value) { | |
90d69e2d | 173 | me.lookup('diskselector').getComponent('hdstorage').setTargetNode(value); |
f6710aac TL |
174 | }, |
175 | }, | |
f5226cd9 DM |
176 | }); |
177 | ||
f5226cd9 DM |
178 | var modelist = [['copy', gettext('Full Clone')]]; |
179 | if (me.isTemplate) { | |
180 | modelist.push(['clone', gettext('Linked Clone')]); | |
181 | } | |
182 | ||
406ac585 EK |
183 | col1.push({ |
184 | xtype: 'pveGuestIDSelector', | |
185 | name: 'newvmid', | |
0718aefc | 186 | guestType: me.guestType, |
406ac585 EK |
187 | value: '', |
188 | loadNextFreeID: true, | |
f6710aac | 189 | validateExists: false, |
406ac585 EK |
190 | }, |
191 | { | |
192 | xtype: 'textfield', | |
193 | name: 'name', | |
54fbdcd1 | 194 | vtype: 'DnsName', |
406ac585 | 195 | allowBlank: true, |
f6710aac | 196 | fieldLabel: me.guestType === 'lxc' ? gettext('Hostname') : gettext('Name'), |
406ac585 EK |
197 | }, |
198 | { | |
199 | xtype: 'pvePoolSelector', | |
200 | fieldLabel: gettext('Resource Pool'), | |
201 | name: 'pool', | |
202 | value: '', | |
f6710aac TL |
203 | allowBlank: true, |
204 | }, | |
406ac585 | 205 | ); |
f5226cd9 | 206 | |
406ac585 | 207 | col2.push({ |
09cacce7 | 208 | xtype: 'proxmoxKVComboBox', |
406ac585 EK |
209 | fieldLabel: gettext('Mode'), |
210 | name: 'clonemode', | |
211 | reference: 'clonemodesel', | |
212 | allowBlank: false, | |
213 | hidden: !me.isTemplate, | |
214 | value: me.isTemplate ? 'clone' : 'copy', | |
dbbe181c TL |
215 | comboItems: modelist, |
216 | listeners: { | |
217 | change: function(t, value) { | |
218 | me.updateVisibility(); | |
219 | me.verifyFeature(); | |
f6710aac TL |
220 | }, |
221 | }, | |
406ac585 EK |
222 | }, |
223 | { | |
224 | xtype: 'PVE.form.SnapshotSelector', | |
f5226cd9 | 225 | name: 'snapname', |
406ac585 | 226 | reference: 'snapshotsel', |
f5226cd9 | 227 | fieldLabel: gettext('Snapshot'), |
406ac585 | 228 | nodename: me.nodename, |
0718aefc | 229 | guestType: me.guestType, |
406ac585 | 230 | vmid: me.vmid, |
ef725143 | 231 | hidden: !!(me.isTemplate || !me.hasSnapshots), |
406ac585 | 232 | disabled: false, |
f5226cd9 | 233 | allowBlank: false, |
8058410f | 234 | value: me.snapname, |
f5226cd9 DM |
235 | listeners: { |
236 | change: function(f, value) { | |
237 | me.verifyFeature(); | |
f6710aac TL |
238 | }, |
239 | }, | |
406ac585 EK |
240 | }, |
241 | { | |
1490ff3d DC |
242 | xtype: 'pveDiskStorageSelector', |
243 | reference: 'diskselector', | |
406ac585 | 244 | nodename: me.nodename, |
1490ff3d DC |
245 | autoSelect: false, |
246 | hideSize: true, | |
247 | hideSelection: true, | |
248 | storageLabel: gettext('Target Storage'), | |
406ac585 | 249 | allowBlank: true, |
0718aefc | 250 | storageContent: me.guestType === 'qemu' ? 'images' : 'rootdir', |
f4f9e662 | 251 | emptyText: gettext('Same as source'), |
ef725143 | 252 | disabled: !!me.isTemplate, // because default mode is clone for templates |
f5226cd9 DM |
253 | }); |
254 | ||
406ac585 | 255 | var formPanel = Ext.create('Ext.form.Panel', { |
f5226cd9 | 256 | bodyPadding: 10, |
26693bb9 | 257 | reference: 'cloneform', |
f5226cd9 | 258 | border: false, |
d27a44a6 | 259 | layout: 'hbox', |
f5226cd9 | 260 | defaultType: 'container', |
f5226cd9 DM |
261 | fieldDefaults: { |
262 | labelWidth: 100, | |
f6710aac | 263 | anchor: '100%', |
f5226cd9 DM |
264 | }, |
265 | items: [ | |
266 | { | |
d27a44a6 | 267 | flex: 1, |
f5226cd9 DM |
268 | padding: '0 10 0 0', |
269 | layout: 'anchor', | |
f6710aac | 270 | items: col1, |
f5226cd9 DM |
271 | }, |
272 | { | |
d27a44a6 | 273 | flex: 1, |
f5226cd9 DM |
274 | padding: '0 0 0 10', |
275 | layout: 'anchor', | |
f6710aac TL |
276 | items: col2, |
277 | }, | |
278 | ], | |
f5226cd9 DM |
279 | }); |
280 | ||
f5226cd9 DM |
281 | Ext.apply(me, { |
282 | modal: true, | |
283 | width: 600, | |
284 | height: 250, | |
285 | border: false, | |
286 | layout: 'fit', | |
8058410f | 287 | buttons: [{ |
672a6270 | 288 | xtype: 'proxmoxHelpButton', |
406ac585 EK |
289 | listenToGlobalEvent: false, |
290 | hidden: false, | |
f6710aac | 291 | onlineHelp: me.onlineHelp, |
406ac585 EK |
292 | }, |
293 | '->', | |
294 | { | |
295 | reference: 'submitBtn', | |
296 | text: gettext('Clone'), | |
297 | disabled: true, | |
298 | handler: function() { | |
299 | var cloneForm = me.lookupReference('cloneform'); | |
300 | if (cloneForm.isValid()) { | |
301 | me.create_clone(cloneForm.getValues()); | |
302 | } | |
f6710aac | 303 | }, |
8058410f TL |
304 | }], |
305 | items: [formPanel], | |
f5226cd9 DM |
306 | }); |
307 | ||
308 | me.callParent(); | |
309 | ||
310 | me.verifyFeature(); | |
f6710aac | 311 | }, |
f5226cd9 | 312 | }); |