]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/lxc/CreateWizard.js
ui: lxc: resources: consider rootfs as a disk again
[pve-manager.git] / www / manager6 / lxc / CreateWizard.js
1 Ext.define('PVE.lxc.CreateWizard', {
2 extend: 'PVE.window.Wizard',
3 mixins: ['Proxmox.Mixin.CBind'],
4
5 viewModel: {
6 data: {
7 nodename: '',
8 storage: '',
9 unprivileged: true,
10 },
11 },
12
13 cbindData: {
14 nodename: undefined,
15 },
16
17 subject: gettext('LXC Container'),
18
19 items: [
20 {
21 xtype: 'inputpanel',
22 title: gettext('General'),
23 onlineHelp: 'pct_general',
24 column1: [
25 {
26 xtype: 'pveNodeSelector',
27 name: 'nodename',
28 cbind: {
29 selectCurNode: '{!nodename}',
30 preferredValue: '{nodename}',
31 },
32 bind: {
33 value: '{nodename}',
34 },
35 fieldLabel: gettext('Node'),
36 allowBlank: false,
37 onlineValidator: true,
38 },
39 {
40 xtype: 'pveGuestIDSelector',
41 name: 'vmid', // backend only knows vmid
42 guestType: 'lxc',
43 value: '',
44 loadNextFreeID: true,
45 validateExists: false,
46 },
47 {
48 xtype: 'proxmoxtextfield',
49 name: 'hostname',
50 vtype: 'DnsName',
51 value: '',
52 fieldLabel: gettext('Hostname'),
53 skipEmptyText: true,
54 allowBlank: true,
55 },
56 {
57 xtype: 'proxmoxcheckbox',
58 name: 'unprivileged',
59 value: true,
60 bind: {
61 value: '{unprivileged}',
62 },
63 fieldLabel: gettext('Unprivileged container'),
64 },
65 {
66 xtype: 'proxmoxcheckbox',
67 name: 'features',
68 inputValue: 'nesting=1',
69 value: true,
70 bind: {
71 disabled: '{!unprivileged}',
72 },
73 fieldLabel: gettext('Nesting'),
74 },
75 ],
76 column2: [
77 {
78 xtype: 'pvePoolSelector',
79 fieldLabel: gettext('Resource Pool'),
80 name: 'pool',
81 value: '',
82 allowBlank: true,
83 },
84 {
85 xtype: 'textfield',
86 inputType: 'password',
87 name: 'password',
88 value: '',
89 fieldLabel: gettext('Password'),
90 allowBlank: false,
91 minLength: 5,
92 change: function(f, value) {
93 if (f.rendered) {
94 f.up().down('field[name=confirmpw]').validate();
95 }
96 },
97 },
98 {
99 xtype: 'textfield',
100 inputType: 'password',
101 name: 'confirmpw',
102 value: '',
103 fieldLabel: gettext('Confirm password'),
104 allowBlank: true,
105 submitValue: false,
106 validator: function(value) {
107 var pw = this.up().down('field[name=password]').getValue();
108 if (pw !== value) {
109 return "Passwords do not match!";
110 }
111 return true;
112 },
113 },
114 {
115 xtype: 'proxmoxtextfield',
116 name: 'ssh-public-keys',
117 value: '',
118 fieldLabel: gettext('SSH public key'),
119 allowBlank: true,
120 validator: function(value) {
121 let pwfield = this.up().down('field[name=password]');
122 if (value.length) {
123 let key = PVE.Parser.parseSSHKey(value);
124 if (!key) {
125 return "Failed to recognize ssh key";
126 }
127 pwfield.allowBlank = true;
128 } else {
129 pwfield.allowBlank = false;
130 }
131 pwfield.validate();
132 return true;
133 },
134 afterRender: function() {
135 if (!window.FileReader) {
136 return; // No FileReader support in this browser
137 }
138 let cancelEvent = ev => {
139 ev = ev.event;
140 if (ev.preventDefault) {
141 ev.preventDefault();
142 }
143 };
144 this.inputEl.on('dragover', cancelEvent);
145 this.inputEl.on('dragenter', cancelEvent);
146 this.inputEl.on('drop', ev => {
147 cancelEvent(ev);
148 let files = ev.event.dataTransfer.files;
149 PVE.Utils.loadSSHKeyFromFile(files[0], v => this.setValue(v));
150 });
151 },
152 },
153 {
154 xtype: 'filebutton',
155 name: 'file',
156 hidden: !window.FileReader,
157 text: gettext('Load SSH Key File'),
158 listeners: {
159 change: function(btn, e, value) {
160 e = e.event;
161 let field = this.up().down('proxmoxtextfield[name=ssh-public-keys]');
162 PVE.Utils.loadSSHKeyFromFile(e.target.files[0], v => field.setValue(v));
163 btn.reset();
164 },
165 },
166 },
167 ],
168 },
169 {
170 xtype: 'inputpanel',
171 title: gettext('Template'),
172 onlineHelp: 'pct_container_images',
173 column1: [
174 {
175 xtype: 'pveStorageSelector',
176 name: 'tmplstorage',
177 fieldLabel: gettext('Storage'),
178 storageContent: 'vztmpl',
179 autoSelect: true,
180 allowBlank: false,
181 bind: {
182 value: '{storage}',
183 nodename: '{nodename}',
184 },
185 },
186 {
187 xtype: 'pveFileSelector',
188 name: 'ostemplate',
189 storageContent: 'vztmpl',
190 fieldLabel: gettext('Template'),
191 bind: {
192 storage: '{storage}',
193 nodename: '{nodename}',
194 },
195 allowBlank: false,
196 },
197 ],
198 },
199 {
200 xtype: 'pveMultiMPPanel',
201 title: gettext('Disks'),
202 insideWizard: true,
203 isCreate: true,
204 unused: false,
205 confid: 'rootfs',
206 },
207 {
208 xtype: 'pveLxcCPUInputPanel',
209 title: gettext('CPU'),
210 insideWizard: true,
211 },
212 {
213 xtype: 'pveLxcMemoryInputPanel',
214 title: gettext('Memory'),
215 insideWizard: true,
216 },
217 {
218 xtype: 'pveLxcNetworkInputPanel',
219 title: gettext('Network'),
220 insideWizard: true,
221 bind: {
222 nodename: '{nodename}',
223 },
224 isCreate: true,
225 },
226 {
227 xtype: 'pveLxcDNSInputPanel',
228 title: gettext('DNS'),
229 insideWizard: true,
230 },
231 {
232 title: gettext('Confirm'),
233 layout: 'fit',
234 items: [
235 {
236 xtype: 'grid',
237 store: {
238 model: 'KeyValue',
239 sorters: [{
240 property: 'key',
241 direction: 'ASC',
242 }],
243 },
244 columns: [
245 { header: 'Key', width: 150, dataIndex: 'key' },
246 { header: 'Value', flex: 1, dataIndex: 'value' },
247 ],
248 },
249 ],
250 dockedItems: [
251 {
252 xtype: 'proxmoxcheckbox',
253 name: 'start',
254 dock: 'bottom',
255 margin: '5 0 0 0',
256 boxLabel: gettext('Start after created'),
257 },
258 ],
259 listeners: {
260 show: function(panel) {
261 let wizard = this.up('window');
262 let kv = wizard.getValues();
263 let data = [];
264 Ext.Object.each(kv, function(key, value) {
265 if (key === 'delete' || key === 'tmplstorage') { // ignore
266 return;
267 }
268 if (key === 'password') { // don't show pw
269 return;
270 }
271 data.push({ key: key, value: value });
272 });
273
274 let summaryStore = panel.down('grid').getStore();
275 summaryStore.suspendEvents();
276 summaryStore.removeAll();
277 summaryStore.add(data);
278 summaryStore.sort();
279 summaryStore.resumeEvents();
280 summaryStore.fireEvent('refresh');
281 },
282 },
283 onSubmit: function() {
284 let wizard = this.up('window');
285 let kv = wizard.getValues();
286 delete kv.delete;
287
288 let nodename = kv.nodename;
289 delete kv.nodename;
290 delete kv.tmplstorage;
291
292 if (!kv.pool.length) {
293 delete kv.pool;
294 }
295 if (!kv.password.length && kv['ssh-public-keys']) {
296 delete kv.password;
297 }
298
299 Proxmox.Utils.API2Request({
300 url: `/nodes/${nodename}/lxc`,
301 waitMsgTarget: wizard,
302 method: 'POST',
303 params: kv,
304 success: function(response, opts) {
305 Ext.create('Proxmox.window.TaskViewer', {
306 autoShow: true,
307 upid: response.result.data,
308 });
309 wizard.close();
310 },
311 failure: (response, opts) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
312 });
313 },
314 },
315 ],
316 });