]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/Parser.js
1 // Some configuration values are complex strings -
2 // so we need parsers/generators for them.
4 Ext
.define('PVE.Parser', {
7 // this class only contains static functions
9 printACME: function(value
) {
10 if (Ext
.isArray(value
.domains
)) {
11 value
.domains
= value
.domains
.join(';');
13 return PVE
.Parser
.printPropertyString(value
);
16 parseACME: function(value
) {
24 Ext
.Array
.each(value
.split(','), function(p
) {
25 var kv
= p
.split('=', 2);
26 if (Ext
.isDefined(kv
[1])) {
29 error
= 'Failed to parse key-value pair: '+p
;
34 if (error
!== undefined) {
39 if (res
.domains
!== undefined) {
40 res
.domains
= res
.domains
.split(/;/);
46 parseBoolean: function(value
, default_value
) {
47 if (!Ext
.isDefined(value
)) {
50 value
= value
.toLowerCase();
51 return value
=== '1' ||
57 parsePropertyString: function(value
, defaultKey
) {
61 if (typeof value
!== 'string' || value
=== '') {
65 Ext
.Array
.each(value
.split(','), function(p
) {
66 var kv
= p
.split('=', 2);
67 if (Ext
.isDefined(kv
[1])) {
69 } else if (Ext
.isDefined(defaultKey
)) {
70 if (Ext
.isDefined(res
[defaultKey
])) {
71 error
= 'defaultKey may be only defined once in propertyString';
72 return false; // break
74 res
[defaultKey
] = kv
[0];
76 error
= 'invalid propertyString, not a key=value pair and no defaultKey defined';
77 return false; // break
81 if (error
!== undefined) {
89 printPropertyString: function(data
, defaultKey
) {
91 gotDefaultKeyVal
= false,
94 Ext
.Object
.each(data
, function(key
, value
) {
95 if (defaultKey
!== undefined && key
=== defaultKey
) {
96 gotDefaultKeyVal
= true;
97 defaultKeyVal
= value
;
98 } else if (value
!== '') {
99 stringparts
.push(key
+ '=' + value
);
103 stringparts
= stringparts
.sort();
104 if (gotDefaultKeyVal
) {
105 stringparts
.unshift(defaultKeyVal
);
108 return stringparts
.join(',');
111 parseQemuNetwork: function(key
, value
) {
112 if (!(key
&& value
)) {
119 Ext
.Array
.each(value
.split(','), function(p
) {
120 if (!p
|| p
.match(/^\s*$/)) {
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();
129 res
.macaddr
= match_res
[3];
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) {
136 res
.tag
= match_res
[1];
137 } else if ((match_res
= p
.match(/^firewall=(\d+)$/)) !== null) {
138 res
.firewall
= match_res
[1];
139 } else if ((match_res
= p
.match(/^link_down=(\d+)$/)) !== null) {
140 res
.disconnect
= match_res
[1];
141 } else if ((match_res
= p
.match(/^queues=(\d+)$/)) !== null) {
142 res
.queues
= match_res
[1];
143 } else if ((match_res
= p
.match(/^trunks=(\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*)$/)) !== null) {
144 res
.trunks
= match_res
[1];
145 } else if ((match_res
= p
.match(/^mtu=(\d+)$/)) !== null) {
146 res
.mtu
= match_res
[1];
149 return false; // break
153 if (errors
|| !res
.model
) {
160 printQemuNetwork: function(net
) {
161 var netstr
= net
.model
;
163 netstr
+= "=" + net
.macaddr
;
166 netstr
+= ",bridge=" + net
.bridge
;
168 netstr
+= ",tag=" + net
.tag
;
171 netstr
+= ",firewall=" + net
.firewall
;
175 netstr
+= ",rate=" + net
.rate
;
178 netstr
+= ",queues=" + net
.queues
;
180 if (net
.disconnect
) {
181 netstr
+= ",link_down=" + net
.disconnect
;
184 netstr
+= ",trunks=" + net
.trunks
;
187 netstr
+= ",mtu=" + net
.mtu
;
192 parseQemuDrive: function(key
, value
) {
193 if (!(key
&& value
)) {
199 var match_res
= key
.match(/^([a-z]+)(\d+)$/);
203 res
.interface = match_res
[1];
204 res
.index
= match_res
[2];
207 Ext
.Array
.each(value
.split(','), function(p
) {
208 if (!p
|| p
.match(/^\s*$/)) {
211 var match_res
= p
.match(/^([a-z_]+)=(\S+)$/);
213 if (!p
.match(/\=/)) {
218 return false; // break
220 var k
= match_res
[1];
221 if (k
=== 'volume') {
225 if (Ext
.isDefined(res
[k
])) {
227 return false; // break
230 var v
= match_res
[2];
232 if (k
=== 'cache' && v
=== 'off') {
239 if (errors
|| !res
.file
) {
246 printQemuDrive: function(drive
) {
247 var drivestr
= drive
.file
;
249 Ext
.Object
.each(drive
, function(key
, value
) {
250 if (!Ext
.isDefined(value
) || key
=== 'file' ||
251 key
=== 'index' || key
=== 'interface') {
254 drivestr
+= ',' + key
+ '=' + value
;
260 parseIPConfig: function(key
, value
) {
261 if (!(key
&& value
)) {
268 Ext
.Array
.each(value
.split(','), function(p
) {
269 if (!p
|| p
.match(/^\s*$/)) {
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];
284 return false; // break
295 printIPConfig: function(cfg
) {
299 str
+= "ip=" + cfg
.ip
;
303 str
+= c
+ "gw=" + cfg
.gw
;
307 str
+= c
+ "ip6=" + cfg
.ip6
;
311 str
+= c
+ "gw6=" + cfg
.gw6
;
317 parseOpenVZNetIf: function(value
) {
325 Ext
.Array
.each(value
.split(';'), function(item
) {
326 if (!item
|| item
.match(/^\s*$/)) {
331 Ext
.Array
.each(item
.split(','), function(p
) {
332 if (!p
|| p
.match(/^\s*$/)) {
335 var match_res
= p
.match(/^(ifname|mac|bridge|host_ifname|host_mac|mac_filter)=(\S+)$/);
338 return false; // break
340 if (match_res
[1] === 'bridge') {
341 var bridgevlanf
= match_res
[2];
342 var bridge_res
= bridgevlanf
.match(/^(vmbr(\d+))(v(\d+))?(f)?$/);
345 return false; // break
347 data
.bridge
= bridge_res
[1];
348 data
.tag
= bridge_res
[4];
349 data
.firewall
= bridge_res
[5] ? 1 : 0;
351 data
[match_res
[1]] = match_res
[2];
355 if (errors
|| !data
.ifname
) {
357 return false; // break
362 res
[data
.ifname
] = data
;
365 return errors
? undefined: res
;
368 printOpenVZNetIf: function(netif
) {
371 Ext
.Object
.each(netif
, function(iface
, data
) {
373 Ext
.Array
.each(['ifname', 'mac', 'bridge', 'host_ifname', 'host_mac', 'mac_filter', 'tag', 'firewall'], function(key
) {
374 var value
= data
[key
];
375 if (key
=== 'bridge') {
377 value
= value
+ 'v' + data
.tag
;
384 tmparray
.push(key
+ '=' + value
);
387 netarray
.push(tmparray
.join(','));
390 return netarray
.join(';');
393 parseLxcNetwork: function(value
) {
399 Ext
.Array
.each(value
.split(','), function(p
) {
400 if (!p
|| p
.match(/^\s*$/)) {
403 var match_res
= p
.match(/^(bridge|hwaddr|mtu|name|ip|ip6|gw|gw6|tag|rate)=(\S+)$/);
405 data
[match_res
[1]] = match_res
[2];
406 } else if ((match_res
= p
.match(/^firewall=(\d+)$/)) !== null) {
407 data
.firewall
= PVE
.Parser
.parseBoolean(match_res
[1]);
409 // todo: simply ignore errors ?
417 printLxcNetwork: function(data
) {
419 Ext
.Array
.each(['bridge', 'hwaddr', 'mtu', 'name', 'ip',
420 'gw', 'ip6', 'gw6', 'firewall', 'tag'], function(key
) {
421 var value
= data
[key
];
423 tmparray
.push(key
+ '=' + value
);
428 tmparray
.push('rate=' + data
.rate
);
430 return tmparray
.join(',');
433 parseLxcMountPoint: function(value
) {
441 Ext
.Array
.each(value
.split(','), function(p
) {
442 if (!p
|| p
.match(/^\s*$/)) {
445 var match_res
= p
.match(/^([a-z_]+)=(.+)$/);
447 if (!p
.match(/\=/)) {
452 return false; // break
454 var k
= match_res
[1];
455 if (k
=== 'volume') {
459 if (Ext
.isDefined(res
[k
])) {
461 return false; // break
464 var v
= match_res
[2];
469 if (errors
|| !res
.file
) {
473 var m
= res
.file
.match(/^([a-z][a-z0-9\-\_\.]*[a-z0-9]):/i);
477 } else if (res
.file
.match(/^\/dev\//)) {
486 printLxcMountPoint: function(mp
) {
487 var drivestr
= mp
.file
;
489 Ext
.Object
.each(mp
, function(key
, value
) {
490 if (!Ext
.isDefined(value
) || key
=== 'file' ||
491 key
=== 'type' || key
=== 'storage') {
494 drivestr
+= ',' + key
+ '=' + value
;
500 parseStartup: function(value
) {
501 if (value
=== undefined) {
508 Ext
.Array
.each(value
.split(','), function(p
) {
509 if (!p
|| p
.match(/^\s*$/)) {
515 if ((match_res
= p
.match(/^(order)?=(\d+)$/)) !== null) {
516 res
.order
= match_res
[2];
517 } else if ((match_res
= p
.match(/^up=(\d+)$/)) !== null) {
518 res
.up
= match_res
[1];
519 } else if ((match_res
= p
.match(/^down=(\d+)$/)) !== null) {
520 res
.down
= match_res
[1];
523 return false; // break
534 printStartup: function(startup
) {
536 if (startup
.order
!== undefined && startup
.order
!== '') {
537 arr
.push('order=' + startup
.order
);
539 if (startup
.up
!== undefined && startup
.up
!== '') {
540 arr
.push('up=' + startup
.up
);
542 if (startup
.down
!== undefined && startup
.down
!== '') {
543 arr
.push('down=' + startup
.down
);
546 return arr
.join(',');
549 parseQemuSmbios1: function(value
) {
550 var res
= value
.split(',').reduce(function(accumulator
, currentValue
) {
551 var splitted
= currentValue
.split(new RegExp("=(.+)"));
552 accumulator
[splitted
[0]] = splitted
[1];
556 if (PVE
.Parser
.parseBoolean(res
.base64
, false)) {
557 Ext
.Object
.each(res
, function(key
, value
) {
558 if (key
=== 'uuid') { return; }
559 res
[key
] = Ext
.util
.Base64
.decode(value
);
566 printQemuSmbios1: function(data
) {
569 Ext
.Object
.each(data
, function(key
, value
) {
570 if (value
=== '') { return; }
571 if (key
=== 'uuid') {
572 datastr
+= (datastr
!== '' ? ',' : '') + key
+ '=' + value
;
574 // values should be base64 encoded from now on, mark config strings correspondingly
577 datastr
+= (datastr
!== '' ? ',' : '') + 'base64=1';
579 datastr
+= (datastr
!== '' ? ',' : '') + key
+ '=' + Ext
.util
.Base64
.encode(value
);
586 parseTfaConfig: function(value
) {
589 Ext
.Array
.each(value
.split(','), function(p
) {
590 var kva
= p
.split('=', 2);
591 res
[kva
[0]] = kva
[1];
597 parseTfaType: function(value
) {
599 if (!value
|| !value
.length
) {
601 } else if (value
=== 'x!oath') {
603 } else if (match
= value
.match(/^x!(.+)$/)) {
610 parseQemuCpu: function(value
) {
618 Ext
.Array
.each(value
.split(','), function(p
) {
619 if (!p
|| p
.match(/^\s*$/)) {
623 if (!p
.match(/\=/)) {
624 if (Ext
.isDefined(res
.cpu
)) {
626 return false; // break
632 var match_res
= p
.match(/^([a-z_]+)=(\S+)$/);
635 return false; // break
638 var k
= match_res
[1];
639 if (Ext
.isDefined(res
[k
])) {
641 return false; // break
644 res
[k
] = match_res
[2];
647 if (errors
|| !res
.cputype
) {
654 printQemuCpu: function(cpu
) {
655 var cpustr
= cpu
.cputype
;
658 Ext
.Object
.each(cpu
, function(key
, value
) {
659 if (!Ext
.isDefined(value
) || key
=== 'cputype') {
662 optstr
+= ',' + key
+ '=' + value
;
667 return 'kvm64' + optstr
;
672 return cpustr
+ optstr
;
675 parseSSHKey: function(key
) {
676 // |--- options can have quotes--| type key comment
677 var keyre
= /^(?:((?:[^\s"]|\"(?:\\.|[^"\\])*")+)\s+)?(\S+)\s+(\S+)(?:\s+(.*))?$/;
678 var typere
= /^(?:ssh-(?:dss|rsa|ed25519)|ecdsa-sha2-nistp\d+)$/;
680 var m
= key
.match(keyre
);
684 if (m
.length
< 3 || !m
[2]) { // [2] is always either type or key
687 if (m
[1] && m
[1].match(typere
)) {
694 if (m
[2].match(typere
)) {
705 parseACMEPluginData: function(data
) {
708 data
.split('\n').forEach((line
) => {
709 // capture everything after the first = as value
710 let [key
, value
] = line
.split(/=(.+)/);
711 if (value
!== undefined) {
714 extradata
.push(line
);
717 return [res
, extradata
];