X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=src%2FPVE%2FSectionConfig.pm;h=6273afa35a22cb09ca14d2f010f5aad8b96dba47;hb=885641fb6a52ce2095180d912070af378026d631;hp=06ebbe79cf11cea7545dc21b71c279d085b08265;hpb=b51b16e6f58de4cb385bd461d97866b3d94c93ec;p=pve-common.git diff --git a/src/PVE/SectionConfig.pm b/src/PVE/SectionConfig.pm index 06ebbe7..6273afa 100644 --- a/src/PVE/SectionConfig.pm +++ b/src/PVE/SectionConfig.pm @@ -26,6 +26,9 @@ sub register { my $type = $class->type(); my $pdata = $class->private(); + die "duplicate plugin registration (type = $type)" + if defined($pdata->{plugins}->{$type}); + my $plugindata = $class->plugindata(); $pdata->{plugindata}->{$type} = $plugindata; $pdata->{plugins}->{$type} = $class; @@ -52,16 +55,56 @@ sub createSchema { my $pdata = $class->private(); my $propertyList = $pdata->{propertyList}; + my $plugins = $pdata->{plugins}; + + my $props = {}; + + my $copy_property = sub { + my ($src) = @_; + + my $res = {}; + foreach my $k (keys %$src) { + $res->{$k} = $src->{$k}; + } + + return $res; + }; + + foreach my $p (keys %$propertyList) { + if (!$propertyList->{$p}->{optional}) { + $props->{$p} = $propertyList->{$p}; + next; + } + + my $required = 1; + + my $copts = $class->options(); + $required = 0 if defined($copts->{$p}) && $copts->{$p}->{optional}; + + foreach my $t (keys %$plugins) { + my $opts = $pdata->{options}->{$t} || {}; + $required = 0 if !defined($opts->{$p}) || $opts->{$p}->{optional}; + } + + if ($required) { + # make a copy, because we modify the optional property + my $res = &$copy_property($propertyList->{$p}); + $res->{optional} = 0; + $props->{$p} = $res; + } else { + $props->{$p} = $propertyList->{$p}; + } + } return { type => "object", additionalProperties => 0, - properties => $propertyList, + properties => $props, }; } sub updateSchema { - my ($class) = @_; + my ($class, $single_class) = @_; my $pdata = $class->private(); my $propertyList = $pdata->{propertyList}; @@ -69,19 +112,32 @@ sub updateSchema { my $props = {}; + my $filter_type = $class->type() if $single_class; + foreach my $p (keys %$propertyList) { next if $p eq 'type'; + + my $copts = $class->options(); + + next if defined($filter_type) && !defined($copts->{$p}); + if (!$propertyList->{$p}->{optional}) { $props->{$p} = $propertyList->{$p}; next; } + + my $modifyable = 0; + + $modifyable = 1 if defined($copts->{$p}) && !$copts->{$p}->{fixed}; + foreach my $t (keys %$plugins) { - my $opts = $pdata->{options}->{$t}; + my $opts = $pdata->{options}->{$t} || {}; next if !defined($opts->{$p}); - if (!$opts->{$p}->{fixed}) { - $props->{$p} = $propertyList->{$p}; - } + $modifyable = 1 if !$opts->{$p}->{fixed}; } + next if !$modifyable; + + $props->{$p} = $propertyList->{$p}; } $props->{digest} = get_standard_option('pve-config-digest'); @@ -134,7 +190,7 @@ sub init { } $propertyList->{type}->{type} = 'string'; - $propertyList->{type}->{enum} = [keys %$plugins]; + $propertyList->{type}->{enum} = [sort keys %$plugins]; } sub lookup { @@ -153,7 +209,7 @@ sub lookup_types { my $pdata = $class->private(); - return [ keys %{$pdata->{plugins}} ]; + return [ sort keys %{$pdata->{plugins}} ]; } sub decode_value { @@ -231,19 +287,22 @@ sub parse_config { my $ids = {}; my $order = {}; - my $digest = Digest::SHA::sha1_hex(defined($raw) ? $raw : ''); + $raw = '' if !defined($raw); + + my $digest = Digest::SHA::sha1_hex($raw); my $pri = 1; my $lineno = 0; + my @lines = split(/\n/, $raw); + my $nextline = sub { + while (my $line = shift @lines) { + $lineno++; + return $line if $line !~ /^\s*(?:#|$)/; + } + }; - while ($raw && $raw =~ s/^(.*?)(\n|$)//) { - my $line = $1; - $lineno++; - - next if $line =~ m/^\#/; - next if $line =~ m/^\s*$/; - + while (my $line = &$nextline()) { my $errprefix = "file $filename line $lineno"; my ($type, $sectionId, $errmsg, $config) = $class->parse_section_header($line); @@ -266,13 +325,7 @@ sub parse_config { } } - while ($raw && $raw =~ s/^(.*?)(\n|$)//) { - $line = $1; - $lineno++; - - next if $line =~ m/^\#/; - last if $line =~ m/^\s*$/; - + while ($line = &$nextline()) { next if $ignore; # skip $errprefix = "file $filename line $lineno"; @@ -349,8 +402,12 @@ my $format_config_line = sub { my $ct = $schema->{type}; + die "property '$key' contains a line feed\n" + if ($key =~ m/[\n\r]/) || ($value =~ m/[\n\r]/); + if ($ct eq 'boolean') { - return $value ? "\t$key\n" : ''; + return "\t$key " . ($value ? 1 : 0) . "\n" + if defined($value); } else { return "\t$key $value\n" if "$value" ne ''; }