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