X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=src%2FPVE%2FJSONSchema.pm;h=527e40980ffa86661484d0aa236f3e95861d68a9;hb=666b0d869c223c89dab5164398bbe37187ba9c12;hp=6297fff0e24abe6f3f79b98e8c2484ef007b0545;hpb=31d4beb47c3639bd7f6873f903569db06606a51b;p=pve-common.git diff --git a/src/PVE/JSONSchema.pm b/src/PVE/JSONSchema.pm index 6297fff..527e409 100644 --- a/src/PVE/JSONSchema.pm +++ b/src/PVE/JSONSchema.pm @@ -16,9 +16,10 @@ use Data::Dumper; use base 'Exporter'; our @EXPORT_OK = qw( +register_standard_option get_standard_option parse_property_string -register_standard_option +print_property_string ); our $CONFIGID_RE = qr/[a-z][a-z0-9_-]+/i; @@ -82,6 +83,12 @@ register_standard_option('pve-storage-id', { type => 'string', format => 'pve-storage-id', }); +register_standard_option('pve-bridge-id', { + description => "Bridge to attach guest network devices to.", + type => 'string', format => 'pve-bridge-id', + format_description => 'bridge', +}); + register_standard_option('pve-config-digest', { description => 'Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.', type => 'string', @@ -193,6 +200,17 @@ sub parse_storage_id { return parse_id($storeid, 'storage', $noerr); } +PVE::JSONSchema::register_format('pve-bridge-id', \&parse_bridge_id); +sub parse_bridge_id { + my ($id, $noerr) = @_; + + if ($id !~ m/^[-_.\w\d]+$/) { + return undef if $noerr; + die "invalid bridge ID '$id'\n"; + } + return $id; +} + PVE::JSONSchema::register_format('acme-plugin-id', \&parse_acme_plugin_id); sub parse_acme_plugin_id { my ($pluginid, $noerr) = @_; @@ -232,6 +250,21 @@ sub pve_verify_node_name { return $node; } +# maps source to target ID using an ID map +sub map_id { + my ($map, $source) = @_; + + return $source if !defined($map); + + return $map->{entries}->{$source} + if $map->{entries} && defined($map->{entries}->{$source}); + + return $map->{default} if $map->{default}; + + # identity (fallback) + return $source; +} + sub parse_idmap { my ($idmap, $idformat) = @_; @@ -285,15 +318,31 @@ my $verify_idpair = sub { return $input; }; +PVE::JSONSchema::register_standard_option('pve-targetstorage', { + description => "Mapping from source to target storages. Providing only a single storage ID maps all source storages to that storage. Providing the special value '1' will map each source storage to itself.", + type => 'string', + format => 'storage-pair-list', + optional => 1, +}); + # note: this only checks a single list entry -# when using a storagepair-list map, you need to pass the full parameter to +# when using a storage-pair-list map, you need to pass the full parameter to # parse_idmap -register_format('storagepair', \&verify_storagepair); +register_format('storage-pair', \&verify_storagepair); sub verify_storagepair { my ($storagepair, $noerr) = @_; return $verify_idpair->($storagepair, $noerr, 'pve-storage-id'); } +# note: this only checks a single list entry +# when using a bridge-pair-list map, you need to pass the full parameter to +# parse_idmap +register_format('bridge-pair', \&verify_bridgepair); +sub verify_bridgepair { + my ($bridgepair, $noerr) = @_; + return $verify_idpair->($bridgepair, $noerr, 'pve-bridge-id'); +} + register_format('mac-addr', \&pve_verify_mac_addr); sub pve_verify_mac_addr { my ($mac_addr, $noerr) = @_; @@ -627,12 +676,41 @@ register_standard_option('bwlimit', { format => $bwlimit_format, }); +my $remote_format = { + host => { + type => 'string', + format_description => 'Remote Proxmox hostname or IP', + }, + port => { + type => 'integer', + optional => 1, + }, + apitoken => { + type => 'string', + format_description => 'A full Proxmox API token including the secret value.', + }, + fingerprint => get_standard_option( + 'fingerprint-sha256', + { + optional => 1, + format_description => 'Remote host\'s certificate fingerprint, if not trusted by system store.', + } + ), +}; +register_format('proxmox-remote', $remote_format); +register_standard_option('proxmox-remote', { + description => "Specification of a remote endpoint.", + type => 'string', format => 'proxmox-remote', +}); + +our $PVE_TAG_RE = qr/[a-z0-9_][a-z0-9_\-\+\.]*/i; + # used for pve-tag-list in e.g., guest configs register_format('pve-tag', \&pve_verify_tag); sub pve_verify_tag { my ($value, $noerr) = @_; - return $value if $value =~ m/^[a-z0-9_][a-z0-9_\-\+\.]*$/i; + return $value if $value =~ m/^${PVE_TAG_RE}$/i; return undef if $noerr; @@ -689,6 +767,18 @@ sub pve_verify_tfa_secret { die "unable to decode TFA secret\n"; } + +PVE::JSONSchema::register_format('pve-task-status-type', \&verify_task_status_type); +sub verify_task_status_type { + my ($value, $noerr) = @_; + + return $value if $value =~ m/^(ok|error|warning|unknown)$/i; + + return undef if $noerr; + + die "invalid status '$value'\n"; +} + sub check_format { my ($format, $value, $path) = @_; @@ -1743,8 +1833,8 @@ sub get_options { } # A way to parse configuration data by giving a json schema -sub parse_config { - my ($schema, $filename, $raw) = @_; +sub parse_config : prototype($$$;$) { + my ($schema, $filename, $raw, $comment_key) = @_; # do fast check (avoid validate_schema($schema)) die "got strange schema" if !$schema->{type} || @@ -1752,10 +1842,24 @@ sub parse_config { my $cfg = {}; + my $comment_data; + my $handle_comment = sub { $_[0] =~ /^#/ }; + if (defined($comment_key)) { + $comment_data = ''; + my $comment_re = qr/^\Q$comment_key\E:\s*(.*\S)\s*$/; + $handle_comment = sub { + if ($_[0] =~ /^\#(.*)\s*$/ || $_[0] =~ $comment_re) { + $comment_data .= PVE::Tools::decode_text($1) . "\n"; + return 1; + } + return undef; + }; + } + while ($raw =~ /^\s*(.+?)\s*$/gm) { my $line = $1; - next if $line =~ /^#/; + next if $handle_comment->($line); if ($line =~ m/^(\S+?):\s*(.*)$/) { my $key = $1; @@ -1771,6 +1875,10 @@ sub parse_config { } } + if (defined($comment_data)) { + $cfg->{$comment_key} = $comment_data; + } + my $errors = {}; check_prop($cfg, $schema, '', $errors);