]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/Parser.js
api: add proxmox-firewall to versions pkg list
[pve-manager.git] / www / manager6 / Parser.js
1 // Some configuration values are complex strings -
2 // so we need parsers/generators for them.
3
4 Ext.define('PVE.Parser', { statics: {
5
6 // this class only contains static functions
7
8 parseBoolean: function(value, default_value) {
9 if (!Ext.isDefined(value)) {
10 return default_value;
11 }
12 value = value.toLowerCase();
13 return value === '1' ||
14 value === 'on' ||
15 value === 'yes' ||
16 value === 'true';
17 },
18
19 parseQemuNetwork: function(key, value) {
20 if (!(key && value)) {
21 return;
22 }
23
24 var res = {};
25
26 var errors = false;
27 Ext.Array.each(value.split(','), function(p) {
28 if (!p || p.match(/^\s*$/)) {
29 return; // continue
30 }
31
32 var match_res;
33
34 if ((match_res = p.match(/^(ne2k_pci|e1000|e1000-82540em|e1000-82544gc|e1000-82545em|vmxnet3|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i)) !== null) {
35 res.model = match_res[1].toLowerCase();
36 if (match_res[3]) {
37 res.macaddr = match_res[3];
38 }
39 } else if ((match_res = p.match(/^bridge=(\S+)$/)) !== null) {
40 res.bridge = match_res[1];
41 } else if ((match_res = p.match(/^rate=(\d+(\.\d+)?)$/)) !== null) {
42 res.rate = match_res[1];
43 } else if ((match_res = p.match(/^tag=(\d+(\.\d+)?)$/)) !== null) {
44 res.tag = match_res[1];
45 } else if ((match_res = p.match(/^firewall=(\d+)$/)) !== null) {
46 res.firewall = match_res[1];
47 } else if ((match_res = p.match(/^link_down=(\d+)$/)) !== null) {
48 res.disconnect = match_res[1];
49 } else if ((match_res = p.match(/^queues=(\d+)$/)) !== null) {
50 res.queues = match_res[1];
51 } else if ((match_res = p.match(/^trunks=(\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*)$/)) !== null) {
52 res.trunks = match_res[1];
53 } else {
54 errors = true;
55 return false; // break
56 }
57 });
58
59 if (errors || !res.model) {
60 return;
61 }
62
63 return res;
64 },
65
66 printQemuNetwork: function(net) {
67
68 var netstr = net.model;
69 if (net.macaddr) {
70 netstr += "=" + net.macaddr;
71 }
72 if (net.bridge) {
73 netstr += ",bridge=" + net.bridge;
74 if (net.tag) {
75 netstr += ",tag=" + net.tag;
76 }
77 if (net.firewall) {
78 netstr += ",firewall=" + net.firewall;
79 }
80 }
81 if (net.rate) {
82 netstr += ",rate=" + net.rate;
83 }
84 if (net.queues) {
85 netstr += ",queues=" + net.queues;
86 }
87 if (net.disconnect) {
88 netstr += ",link_down=" + net.disconnect;
89 }
90 if (net.trunks) {
91 netstr += ",trunks=" + net.trunks;
92 }
93 return netstr;
94 },
95
96 parseQemuDrive: function(key, value) {
97 if (!(key && value)) {
98 return;
99 }
100
101 var res = {};
102
103 var match_res = key.match(/^([a-z]+)(\d+)$/);
104 if (!match_res) {
105 return;
106 }
107 res['interface'] = match_res[1];
108 res.index = match_res[2];
109
110 var errors = false;
111 Ext.Array.each(value.split(','), function(p) {
112 if (!p || p.match(/^\s*$/)) {
113 return; // continue
114 }
115 var match_res = p.match(/^([a-z_]+)=(\S+)$/);
116 if (!match_res) {
117 if (!p.match(/\=/)) {
118 res.file = p;
119 return; // continue
120 }
121 errors = true;
122 return false; // break
123 }
124 var k = match_res[1];
125 if (k === 'volume') {
126 k = 'file';
127 }
128
129 if (Ext.isDefined(res[k])) {
130 errors = true;
131 return false; // break
132 }
133
134 var v = match_res[2];
135
136 if (k === 'cache' && v === 'off') {
137 v = 'none';
138 }
139
140 res[k] = v;
141 });
142
143 if (errors || !res.file) {
144 return;
145 }
146
147 return res;
148 },
149
150 printQemuDrive: function(drive) {
151
152 var drivestr = drive.file;
153
154 Ext.Object.each(drive, function(key, value) {
155 if (!Ext.isDefined(value) || key === 'file' ||
156 key === 'index' || key === 'interface') {
157 return; // continue
158 }
159 drivestr += ',' + key + '=' + value;
160 });
161
162 return drivestr;
163 },
164
165 parseOpenVZNetIf: function(value) {
166 if (!value) {
167 return;
168 }
169
170 var res = {};
171
172 var errors = false;
173 Ext.Array.each(value.split(';'), function(item) {
174 if (!item || item.match(/^\s*$/)) {
175 return; // continue
176 }
177
178 var data = {};
179 Ext.Array.each(item.split(','), function(p) {
180 if (!p || p.match(/^\s*$/)) {
181 return; // continue
182 }
183 var match_res = p.match(/^(ifname|mac|bridge|host_ifname|host_mac|mac_filter)=(\S+)$/);
184 if (!match_res) {
185 errors = true;
186 return false; // break
187 }
188 if (match_res[1] === 'bridge'){
189 var bridgevlanf = match_res[2];
190 var bridge_res = bridgevlanf.match(/^(vmbr(\d+))(v(\d+))?(f)?$/);
191 if (!bridge_res) {
192 errors = true;
193 return false; // break
194 }
195 data.bridge = bridge_res[1];
196 data.tag = bridge_res[4];
197 /*jslint confusion: true*/
198 data.firewall = bridge_res[5] ? 1 : 0;
199 /*jslint confusion: false*/
200 } else {
201 data[match_res[1]] = match_res[2];
202 }
203 });
204
205 if (errors || !data.ifname) {
206 errors = true;
207 return false; // break
208 }
209
210 data.raw = item;
211
212 res[data.ifname] = data;
213 });
214
215 return errors ? undefined: res;
216 },
217
218 printOpenVZNetIf: function(netif) {
219 var netarray = [];
220
221 Ext.Object.each(netif, function(iface, data) {
222 var tmparray = [];
223 Ext.Array.each(['ifname', 'mac', 'bridge', 'host_ifname' , 'host_mac', 'mac_filter', 'tag', 'firewall'], function(key) {
224 var value = data[key];
225 if (key === 'bridge'){
226 if(data.tag){
227 value = value + 'v' + data.tag;
228 }
229 if (data.firewall){
230 value = value + 'f';
231 }
232 }
233 if (value) {
234 tmparray.push(key + '=' + value);
235 }
236
237 });
238 netarray.push(tmparray.join(','));
239 });
240
241 return netarray.join(';');
242 },
243
244 parseLxcNetwork: function(value) {
245 if (!value) {
246 return;
247 }
248
249 var data = {};
250 Ext.Array.each(value.split(','), function(p) {
251 if (!p || p.match(/^\s*$/)) {
252 return; // continue
253 }
254 var match_res = p.match(/^(bridge|hwaddr|mtu|name|ip|ip6|gw|gw6|firewall|tag|rate)=(\S+)$/);
255 if (!match_res) {
256 // todo: simply ignore errors ?
257 return; // continue
258 }
259 data[match_res[1]] = match_res[2];
260 });
261
262 return data;
263 },
264
265 printLxcNetwork: function(data) {
266 var tmparray = [];
267 Ext.Array.each(['bridge', 'hwaddr', 'mtu', 'name', 'ip',
268 'gw', 'ip6', 'gw6', 'firewall', 'tag'], function(key) {
269 var value = data[key];
270 if (value) {
271 tmparray.push(key + '=' + value);
272 }
273 });
274
275 /*jslint confusion: true*/
276 if (data.rate > 0) {
277 tmparray.push('rate=' + data.rate);
278 }
279 /*jslint confusion: false*/
280 return tmparray.join(',');
281 },
282
283 parseLxcMountPoint: function(value) {
284 if (!value) {
285 return;
286 }
287
288 var res = {};
289
290 var errors = false;
291 Ext.Array.each(value.split(','), function(p) {
292 if (!p || p.match(/^\s*$/)) {
293 return; // continue
294 }
295 var match_res = p.match(/^([a-z_]+)=(\S+)$/);
296 if (!match_res) {
297 if (!p.match(/\=/)) {
298 res.file = p;
299 return; // continue
300 }
301 errors = true;
302 return false; // break
303 }
304 var k = match_res[1];
305 if (k === 'volume') {
306 k = 'file';
307 }
308
309 if (Ext.isDefined(res[k])) {
310 errors = true;
311 return false; // break
312 }
313
314 var v = match_res[2];
315
316 res[k] = v;
317 });
318
319 if (errors || !res.file) {
320 return;
321 }
322
323 var m = res.file.match(/^([a-z][a-z0-9\-\_\.]*[a-z0-9]):/i);
324 if (m) {
325 res.storage = m[1];
326 res.type = 'volume';
327 } else if (res.file.match(/^\/dev\//)) {
328 res.type = 'device';
329 } else {
330 res.type = 'bind';
331 }
332
333 return res;
334 },
335
336 printLxcMountPoint: function(mp) {
337 var drivestr = mp.file;
338
339 Ext.Object.each(mp, function(key, value) {
340 if (!Ext.isDefined(value) || key === 'file' ||
341 key === 'type' || key === 'storage') {
342 return; // continue
343 }
344 drivestr += ',' + key + '=' + value;
345 });
346
347 return drivestr;
348 },
349
350 parseStartup: function(value) {
351 if (value === undefined) {
352 return;
353 }
354
355 var res = {};
356
357 var errors = false;
358 Ext.Array.each(value.split(','), function(p) {
359 if (!p || p.match(/^\s*$/)) {
360 return; // continue
361 }
362
363 var match_res;
364
365 if ((match_res = p.match(/^(order)?=(\d+)$/)) !== null) {
366 res.order = match_res[2];
367 } else if ((match_res = p.match(/^up=(\d+)$/)) !== null) {
368 res.up = match_res[1];
369 } else if ((match_res = p.match(/^down=(\d+)$/)) !== null) {
370 res.down = match_res[1];
371 } else {
372 errors = true;
373 return false; // break
374 }
375 });
376
377 if (errors) {
378 return;
379 }
380
381 return res;
382 },
383
384 printStartup: function(startup) {
385 var arr = [];
386 if (startup.order !== undefined && startup.order !== '') {
387 arr.push('order=' + startup.order);
388 }
389 if (startup.up !== undefined && startup.up !== '') {
390 arr.push('up=' + startup.up);
391 }
392 if (startup.down !== undefined && startup.down !== '') {
393 arr.push('down=' + startup.down);
394 }
395
396 return arr.join(',');
397 },
398
399 parseQemuSmbios1: function(value) {
400 var res = {};
401
402 Ext.Array.each(value.split(','), function(p) {
403 var kva = p.split('=', 2);
404 res[kva[0]] = kva[1];
405 });
406
407 return res;
408 },
409
410 printQemuSmbios1: function(data) {
411
412 var datastr = '';
413
414 Ext.Object.each(data, function(key, value) {
415 if (value === '') { return; }
416 datastr += (datastr !== '' ? ',' : '') + key + '=' + value;
417 });
418
419 return datastr;
420 },
421
422 parseTfaConfig: function(value) {
423 var res = {};
424
425 Ext.Array.each(value.split(','), function(p) {
426 var kva = p.split('=', 2);
427 res[kva[0]] = kva[1];
428 });
429
430 return res;
431 },
432
433 parseQemuCpu: function(value) {
434 if (!value) {
435 return {};
436 }
437
438 var res = {};
439
440 var errors = false;
441 Ext.Array.each(value.split(','), function(p) {
442 if (!p || p.match(/^\s*$/)) {
443 return; // continue
444 }
445
446 if (!p.match(/\=/)) {
447 if (Ext.isDefined(res.cpu)) {
448 errors = true;
449 return false; // break
450 }
451 res.cputype = p;
452 return; // continue
453 }
454
455 var match_res = p.match(/^([a-z_]+)=(\S+)$/);
456 if (!match_res) {
457 errors = true;
458 return false; // break
459 }
460
461 var k = match_res[1];
462 if (Ext.isDefined(res[k])) {
463 errors = true;
464 return false; // break
465 }
466
467 res[k] = match_res[2];
468 });
469
470 if (errors || !res.cputype) {
471 return;
472 }
473
474 return res;
475 },
476
477 printQemuCpu: function(cpu) {
478 var cpustr = cpu.cputype;
479 var optstr = '';
480
481 Ext.Object.each(cpu, function(key, value) {
482 if (!Ext.isDefined(value) || key === 'cputype') {
483 return; // continue
484 }
485 optstr += ',' + key + '=' + value;
486 });
487
488 if (!cpustr) {
489 if (optstr) {
490 return 'kvm64' + optstr;
491 }
492 return;
493 }
494
495 return cpustr + optstr;
496 },
497
498 parseSSHKey: function(key) {
499 // |--- options can have quotes--| type key comment
500 var keyre = /^(?:((?:[^\s"]|\"(?:\\.|[^"\\])*")+)\s+)?(\S+)\s+(\S+)(?:\s+(.*))?$/;
501 var typere = /^(?:ssh-(?:dss|rsa|ed25519)|ecdsa-sha2-nistp\d+)$/;
502
503 var m = key.match(keyre);
504 if (!m) {
505 return null;
506 }
507 if (m.length < 3 || !m[2]) { // [2] is always either type or key
508 return null;
509 }
510 if (m[1] && m[1].match(typere)) {
511 return {
512 type: m[1],
513 key: m[2],
514 comment: m[3]
515 };
516 }
517 if (m[2].match(typere)) {
518 return {
519 options: m[1],
520 type: m[2],
521 key: m[3],
522 comment: m[4]
523 };
524 }
525 return null;
526 }
527 }});