]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/Parser.js
ui: parser: drop old openVZ parser
[pve-manager.git] / www / manager6 / Parser.js
CommitLineData
fcb64fe4
DM
1// Some configuration values are complex strings -
2// so we need parsers/generators for them.
3
8058410f
TL
4Ext.define('PVE.Parser', {
5 statics: {
fcb64fe4
DM
6
7 // this class only contains static functions
8
899c4f45
DC
9 printACME: function(value) {
10 if (Ext.isArray(value.domains)) {
11 value.domains = value.domains.join(';');
12 }
13 return PVE.Parser.printPropertyString(value);
14 },
15
488be4c2
DC
16 parseACME: function(value) {
17 if (!value) {
6ac64c3a 18 return {};
488be4c2
DC
19 }
20
21 var res = {};
08a61c7b 22 var error;
488be4c2
DC
23
24 Ext.Array.each(value.split(','), function(p) {
08a61c7b
FG
25 var kv = p.split('=', 2);
26 if (Ext.isDefined(kv[1])) {
27 res[kv[0]] = kv[1];
488be4c2 28 } else {
08a61c7b 29 error = 'Failed to parse key-value pair: '+p;
488be4c2
DC
30 return false;
31 }
32 });
33
08a61c7b
FG
34 if (error !== undefined) {
35 console.error(error);
488be4c2
DC
36 return;
37 }
38
08a61c7b
FG
39 if (res.domains !== undefined) {
40 res.domains = res.domains.split(/;/);
41 }
42
488be4c2
DC
43 return res;
44 },
45
4c1c0d5d 46 parseBoolean: function(value, default_value) {
84de645d 47 if (!Ext.isDefined(value)) {
4c1c0d5d 48 return default_value;
84de645d 49 }
4c1c0d5d 50 value = value.toLowerCase();
ec0bd652 51 return value === '1' ||
4c1c0d5d
EK
52 value === 'on' ||
53 value === 'yes' ||
54 value === 'true';
55 },
56
3d6189d3
SI
57 parsePropertyString: function(value, defaultKey) {
58 var res = {},
9bbdcdff 59 error;
3d6189d3 60
4a7248d4
TL
61 if (typeof value !== 'string' || value === '') {
62 return res;
63 }
64
3d6189d3
SI
65 Ext.Array.each(value.split(','), function(p) {
66 var kv = p.split('=', 2);
67 if (Ext.isDefined(kv[1])) {
68 res[kv[0]] = kv[1];
69 } else if (Ext.isDefined(defaultKey)) {
70 if (Ext.isDefined(res[defaultKey])) {
9bbdcdff
TL
71 error = 'defaultKey may be only defined once in propertyString';
72 return false; // break
3d6189d3
SI
73 }
74 res[defaultKey] = kv[0];
75 } else {
9bbdcdff 76 error = 'invalid propertyString, not a key=value pair and no defaultKey defined';
3d6189d3
SI
77 return false; // break
78 }
79 });
80
9bbdcdff
TL
81 if (error !== undefined) {
82 console.error(error);
3d6189d3
SI
83 return;
84 }
85
86 return res;
87 },
88
89 printPropertyString: function(data, defaultKey) {
6de2baee
TL
90 var stringparts = [],
91 gotDefaultKeyVal = false,
92 defaultKeyVal;
3d6189d3
SI
93
94 Ext.Object.each(data, function(key, value) {
8007aaaf 95 if (defaultKey !== undefined && key === defaultKey) {
6de2baee
TL
96 gotDefaultKeyVal = true;
97 defaultKeyVal = value;
08e38f03 98 } else if (value !== '') {
8007aaaf 99 stringparts.push(key + '=' + value);
3d6189d3 100 }
3d6189d3
SI
101 });
102
6de2baee
TL
103 stringparts = stringparts.sort();
104 if (gotDefaultKeyVal) {
105 stringparts.unshift(defaultKeyVal);
106 }
107
3d6189d3
SI
108 return stringparts.join(',');
109 },
110
fcb64fe4
DM
111 parseQemuNetwork: function(key, value) {
112 if (!(key && value)) {
113 return;
114 }
115
116 var res = {};
117
118 var errors = false;
119 Ext.Array.each(value.split(','), function(p) {
120 if (!p || p.match(/^\s*$/)) {
121 return; // continue
122 }
123
124 var match_res;
125
126 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) {
127 res.model = match_res[1].toLowerCase();
128 if (match_res[3]) {
129 res.macaddr = match_res[3];
130 }
131 } else if ((match_res = p.match(/^bridge=(\S+)$/)) !== null) {
132 res.bridge = match_res[1];
133 } else if ((match_res = p.match(/^rate=(\d+(\.\d+)?)$/)) !== null) {
134 res.rate = match_res[1];
135 } else if ((match_res = p.match(/^tag=(\d+(\.\d+)?)$/)) !== null) {
63e62a6f 136 res.tag = match_res[1];
fcb64fe4 137 } else if ((match_res = p.match(/^firewall=(\d+)$/)) !== null) {
63e62a6f 138 res.firewall = match_res[1];
fcb64fe4 139 } else if ((match_res = p.match(/^link_down=(\d+)$/)) !== null) {
63e62a6f 140 res.disconnect = match_res[1];
fcb64fe4 141 } else if ((match_res = p.match(/^queues=(\d+)$/)) !== null) {
63e62a6f 142 res.queues = match_res[1];
a2ed0697
WB
143 } else if ((match_res = p.match(/^trunks=(\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*)$/)) !== null) {
144 res.trunks = match_res[1];
ced67201
DC
145 } else if ((match_res = p.match(/^mtu=(\d+)$/)) !== null) {
146 res.mtu = match_res[1];
fcb64fe4
DM
147 } else {
148 errors = true;
149 return false; // break
150 }
151 });
152
153 if (errors || !res.model) {
154 return;
155 }
156
157 return res;
158 },
159
160 printQemuNetwork: function(net) {
fcb64fe4
DM
161 var netstr = net.model;
162 if (net.macaddr) {
163 netstr += "=" + net.macaddr;
164 }
165 if (net.bridge) {
166 netstr += ",bridge=" + net.bridge;
167 if (net.tag) {
168 netstr += ",tag=" + net.tag;
169 }
170 if (net.firewall) {
171 netstr += ",firewall=" + net.firewall;
172 }
173 }
174 if (net.rate) {
175 netstr += ",rate=" + net.rate;
176 }
177 if (net.queues) {
178 netstr += ",queues=" + net.queues;
179 }
180 if (net.disconnect) {
181 netstr += ",link_down=" + net.disconnect;
182 }
a2ed0697
WB
183 if (net.trunks) {
184 netstr += ",trunks=" + net.trunks;
185 }
ced67201
DC
186 if (net.mtu) {
187 netstr += ",mtu=" + net.mtu;
188 }
fcb64fe4
DM
189 return netstr;
190 },
191
192 parseQemuDrive: function(key, value) {
193 if (!(key && value)) {
194 return;
195 }
196
197 var res = {};
198
199 var match_res = key.match(/^([a-z]+)(\d+)$/);
200 if (!match_res) {
201 return;
202 }
399ffa76 203 res.interface = match_res[1];
fcb64fe4
DM
204 res.index = match_res[2];
205
206 var errors = false;
207 Ext.Array.each(value.split(','), function(p) {
208 if (!p || p.match(/^\s*$/)) {
209 return; // continue
210 }
211 var match_res = p.match(/^([a-z_]+)=(\S+)$/);
212 if (!match_res) {
213 if (!p.match(/\=/)) {
214 res.file = p;
215 return; // continue
216 }
217 errors = true;
218 return false; // break
219 }
220 var k = match_res[1];
221 if (k === 'volume') {
222 k = 'file';
223 }
224
225 if (Ext.isDefined(res[k])) {
226 errors = true;
227 return false; // break
228 }
229
230 var v = match_res[2];
231
232 if (k === 'cache' && v === 'off') {
233 v = 'none';
234 }
235
236 res[k] = v;
237 });
238
239 if (errors || !res.file) {
240 return;
241 }
242
243 return res;
244 },
245
246 printQemuDrive: function(drive) {
fcb64fe4
DM
247 var drivestr = drive.file;
248
249 Ext.Object.each(drive, function(key, value) {
250 if (!Ext.isDefined(value) || key === 'file' ||
251 key === 'index' || key === 'interface') {
252 return; // continue
253 }
254 drivestr += ',' + key + '=' + value;
255 });
256
257 return drivestr;
258 },
259
01e02121
DC
260 parseIPConfig: function(key, value) {
261 if (!(key && value)) {
262 return;
263 }
264
265 var res = {};
266
267 var errors = false;
268 Ext.Array.each(value.split(','), function(p) {
269 if (!p || p.match(/^\s*$/)) {
270 return; // continue
271 }
272
273 var match_res;
274 if ((match_res = p.match(/^ip=(\S+)$/)) !== null) {
275 res.ip = match_res[1];
276 } else if ((match_res = p.match(/^gw=(\S+)$/)) !== null) {
277 res.gw = match_res[1];
278 } else if ((match_res = p.match(/^ip6=(\S+)$/)) !== null) {
279 res.ip6 = match_res[1];
280 } else if ((match_res = p.match(/^gw6=(\S+)$/)) !== null) {
281 res.gw6 = match_res[1];
282 } else {
283 errors = true;
284 return false; // break
285 }
286 });
287
288 if (errors) {
289 return;
290 }
291
292 return res;
293 },
294
295 printIPConfig: function(cfg) {
296 var c = "";
297 var str = "";
298 if (cfg.ip) {
299 str += "ip=" + cfg.ip;
300 c = ",";
301 }
302 if (cfg.gw) {
303 str += c + "gw=" + cfg.gw;
304 c = ",";
305 }
306 if (cfg.ip6) {
307 str += c + "ip6=" + cfg.ip6;
308 c = ",";
309 }
310 if (cfg.gw6) {
311 str += c + "gw6=" + cfg.gw6;
312 c = ",";
313 }
314 return str;
315 },
316
fcb64fe4
DM
317 parseLxcNetwork: function(value) {
318 if (!value) {
319 return;
320 }
321
322 var data = {};
323 Ext.Array.each(value.split(','), function(p) {
324 if (!p || p.match(/^\s*$/)) {
325 return; // continue
326 }
95e77b22
TL
327 var match_res = p.match(/^(bridge|hwaddr|mtu|name|ip|ip6|gw|gw6|tag|rate)=(\S+)$/);
328 if (match_res) {
329 data[match_res[1]] = match_res[2];
330 } else if ((match_res = p.match(/^firewall=(\d+)$/)) !== null) {
805a7cb8 331 data.firewall = PVE.Parser.parseBoolean(match_res[1]);
95e77b22 332 } else {
fcb64fe4
DM
333 // todo: simply ignore errors ?
334 return; // continue
335 }
fcb64fe4
DM
336 });
337
338 return data;
339 },
340
341 printLxcNetwork: function(data) {
342 var tmparray = [];
343 Ext.Array.each(['bridge', 'hwaddr', 'mtu', 'name', 'ip',
344 'gw', 'ip6', 'gw6', 'firewall', 'tag'], function(key) {
345 var value = data[key];
346 if (value) {
347 tmparray.push(key + '=' + value);
348 }
349 });
519ca7fa 350
6efbc4cb 351 if (data.rate > 0) {
519ca7fa
DM
352 tmparray.push('rate=' + data.rate);
353 }
fcb64fe4
DM
354 return tmparray.join(',');
355 },
356
4c1c0d5d
EK
357 parseLxcMountPoint: function(value) {
358 if (!value) {
359 return;
360 }
361
362 var res = {};
363
364 var errors = false;
365 Ext.Array.each(value.split(','), function(p) {
366 if (!p || p.match(/^\s*$/)) {
367 return; // continue
368 }
a108c35a 369 var match_res = p.match(/^([a-z_]+)=(.+)$/);
4c1c0d5d
EK
370 if (!match_res) {
371 if (!p.match(/\=/)) {
372 res.file = p;
373 return; // continue
374 }
375 errors = true;
376 return false; // break
377 }
378 var k = match_res[1];
379 if (k === 'volume') {
380 k = 'file';
381 }
382
383 if (Ext.isDefined(res[k])) {
384 errors = true;
385 return false; // break
386 }
387
388 var v = match_res[2];
389
390 res[k] = v;
391 });
392
393 if (errors || !res.file) {
394 return;
395 }
396
283b450e 397 var m = res.file.match(/^([a-z][a-z0-9\-\_\.]*[a-z0-9]):/i);
4c1c0d5d
EK
398 if (m) {
399 res.storage = m[1];
400 res.type = 'volume';
401 } else if (res.file.match(/^\/dev\//)) {
402 res.type = 'device';
403 } else {
404 res.type = 'bind';
405 }
406
407 return res;
408 },
409
410 printLxcMountPoint: function(mp) {
411 var drivestr = mp.file;
412
413 Ext.Object.each(mp, function(key, value) {
414 if (!Ext.isDefined(value) || key === 'file' ||
415 key === 'type' || key === 'storage') {
416 return; // continue
417 }
418 drivestr += ',' + key + '=' + value;
419 });
420
421 return drivestr;
422 },
423
fcb64fe4
DM
424 parseStartup: function(value) {
425 if (value === undefined) {
426 return;
427 }
428
429 var res = {};
430
431 var errors = false;
432 Ext.Array.each(value.split(','), function(p) {
433 if (!p || p.match(/^\s*$/)) {
434 return; // continue
435 }
436
437 var match_res;
438
439 if ((match_res = p.match(/^(order)?=(\d+)$/)) !== null) {
440 res.order = match_res[2];
441 } else if ((match_res = p.match(/^up=(\d+)$/)) !== null) {
442 res.up = match_res[1];
443 } else if ((match_res = p.match(/^down=(\d+)$/)) !== null) {
444 res.down = match_res[1];
445 } else {
446 errors = true;
447 return false; // break
448 }
449 });
450
451 if (errors) {
452 return;
453 }
454
455 return res;
456 },
457
458 printStartup: function(startup) {
459 var arr = [];
460 if (startup.order !== undefined && startup.order !== '') {
461 arr.push('order=' + startup.order);
462 }
463 if (startup.up !== undefined && startup.up !== '') {
464 arr.push('up=' + startup.up);
465 }
466 if (startup.down !== undefined && startup.down !== '') {
467 arr.push('down=' + startup.down);
468 }
469
470 return arr.join(',');
471 },
472
473 parseQemuSmbios1: function(value) {
8058410f 474 var res = value.split(',').reduce(function(accumulator, currentValue) {
150ad74a
CE
475 var splitted = currentValue.split(new RegExp("=(.+)"));
476 accumulator[splitted[0]] = splitted[1];
477 return accumulator;
478 }, {});
479
480 if (PVE.Parser.parseBoolean(res.base64, false)) {
481 Ext.Object.each(res, function(key, value) {
482 if (key === 'uuid') { return; }
483 res[key] = Ext.util.Base64.decode(value);
484 });
485 }
fcb64fe4
DM
486
487 return res;
488 },
489
490 printQemuSmbios1: function(data) {
fcb64fe4 491 var datastr = '';
150ad74a 492 var base64 = false;
fcb64fe4 493 Ext.Object.each(data, function(key, value) {
84de645d 494 if (value === '') { return; }
150ad74a
CE
495 if (key === 'uuid') {
496 datastr += (datastr !== '' ? ',' : '') + key + '=' + value;
497 } else {
498 // values should be base64 encoded from now on, mark config strings correspondingly
499 if (!base64) {
500 base64 = true;
501 datastr += (datastr !== '' ? ',' : '') + 'base64=1';
502 }
503 datastr += (datastr !== '' ? ',' : '') + key + '=' + Ext.util.Base64.encode(value);
504 }
fcb64fe4
DM
505 });
506
507 return datastr;
508 },
509
510 parseTfaConfig: function(value) {
511 var res = {};
512
513 Ext.Array.each(value.split(','), function(p) {
ec0bd652 514 var kva = p.split('=', 2);
fcb64fe4
DM
515 res[kva[0]] = kva[1];
516 });
517
518 return res;
4c1c0d5d
EK
519 },
520
1cdb49c1
WB
521 parseTfaType: function(value) {
522 var match;
523 if (!value || !value.length) {
524 return undefined;
525 } else if (value === 'x!oath') {
526 return 'totp';
d2021707 527 } else if (match = value.match(/^x!(.+)$/)) {
1cdb49c1
WB
528 return match[1];
529 } else {
530 return 1;
531 }
532 },
533
4c1c0d5d
EK
534 parseQemuCpu: function(value) {
535 if (!value) {
536 return {};
537 }
538
539 var res = {};
540
541 var errors = false;
542 Ext.Array.each(value.split(','), function(p) {
543 if (!p || p.match(/^\s*$/)) {
544 return; // continue
545 }
fcb64fe4 546
ec0bd652
DC
547 if (!p.match(/\=/)) {
548 if (Ext.isDefined(res.cpu)) {
4c1c0d5d
EK
549 errors = true;
550 return false; // break
551 }
552 res.cputype = p;
553 return; // continue
554 }
555
556 var match_res = p.match(/^([a-z_]+)=(\S+)$/);
557 if (!match_res) {
558 errors = true;
559 return false; // break
560 }
561
562 var k = match_res[1];
563 if (Ext.isDefined(res[k])) {
564 errors = true;
565 return false; // break
566 }
567
568 res[k] = match_res[2];
569 });
570
571 if (errors || !res.cputype) {
572 return;
573 }
574
575 return res;
576 },
577
578 printQemuCpu: function(cpu) {
579 var cpustr = cpu.cputype;
580 var optstr = '';
581
582 Ext.Object.each(cpu, function(key, value) {
583 if (!Ext.isDefined(value) || key === 'cputype') {
584 return; // continue
585 }
586 optstr += ',' + key + '=' + value;
587 });
588
589 if (!cpustr) {
84de645d 590 if (optstr) {
4c1c0d5d 591 return 'kvm64' + optstr;
84de645d 592 }
4c1c0d5d
EK
593 return;
594 }
595
596 return cpustr + optstr;
b1339314
WB
597 },
598
599 parseSSHKey: function(key) {
600 // |--- options can have quotes--| type key comment
601 var keyre = /^(?:((?:[^\s"]|\"(?:\\.|[^"\\])*")+)\s+)?(\S+)\s+(\S+)(?:\s+(.*))?$/;
91c729d3 602 var typere = /^(?:(?:sk-)?ssh-(?:dss|rsa|ed25519)|ecdsa-sha2-nistp\d+)$/;
b1339314
WB
603
604 var m = key.match(keyre);
605 if (!m) {
606 return null;
607 }
608 if (m.length < 3 || !m[2]) { // [2] is always either type or key
609 return null;
610 }
611 if (m[1] && m[1].match(typere)) {
612 return {
613 type: m[1],
614 key: m[2],
f6710aac 615 comment: m[3],
b1339314
WB
616 };
617 }
618 if (m[2].match(typere)) {
619 return {
620 options: m[1],
621 type: m[2],
622 key: m[3],
f6710aac 623 comment: m[4],
b1339314
WB
624 };
625 }
626 return null;
45708891
DC
627 },
628
629 parseACMEPluginData: function(data) {
630 let res = {};
631 let extradata = [];
632 data.split('\n').forEach((line) => {
633 // capture everything after the first = as value
634 let [key, value] = line.split(/=(.+)/);
635 if (value !== undefined) {
636 res[key] = value;
637 } else {
638 extradata.push(line);
639 }
640 });
641 return [res, extradata];
642 },
fa8d3971 643},
8058410f 644});