[pve-devel] applied-series: [PATCH stable-7 container 0/2] setup: cherry-pick ubuntu 24.04 support

2024-06-04 Thread Thomas Lamprecht
Am 04/06/2024 um 10:34 schrieb Christoph Heiss:
> This backports the series to support Ubuntu 24.04 "Noble" CTs [0].
> 
> They could be cherry-picked cleanly. Tested on a up-to-date PVE 7.4
> system (running on `pvetest`), template for Ubuntu 24.04
> (`ubuntu-24.04-standard_24.04-2_amd64.tar.zst`) was copied from a 8.2
> host for testing.
> 
> Tested creating new CT from that template, using either a static IP or
> DHCP. Then working around with the system a bit, everything seems to
> work just fine.
> 
> [0] https://lists.proxmox.com/pipermail/pve-devel/2024-April/063766.html
> 
> Fiona Ebner (2):
>   setup: support Ubuntu 24.04 Noble
>   setup: unlink default netplan configuration even with Ubuntu >= 23.04
> 
>  src/PVE/LXC/Setup/Ubuntu.pm | 3 +++
>  1 file changed, 3 insertions(+)
> 


applied, thanks!


___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH v1 pve-common 1/3] section config: document package and its methods with POD

2024-06-04 Thread Max Carrara
Apart from the obvious benefits that documentation has, this also
allows LSPs to provide docstrings e.g. via 'textDocument/hover' [0].

Tested with Perl Navigator [1].

[0]: 
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_hover
[1]: https://github.com/bscan/PerlNavigator

Signed-off-by: Max Carrara 
---
 src/PVE/SectionConfig.pm | 737 +++
 1 file changed, 672 insertions(+), 65 deletions(-)

diff --git a/src/PVE/SectionConfig.pm b/src/PVE/SectionConfig.pm
index a18e9d8..99ee348 100644
--- a/src/PVE/SectionConfig.pm
+++ b/src/PVE/SectionConfig.pm
@@ -10,65 +10,102 @@ use PVE::Exception qw(raise_param_exc);
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::Tools;
 
-# This package provides a way to have multiple (often similar) types of entries
-# in the same config file, each in its own section, thus "Section Config".
-#
-# The intended structure is to have a single 'base' plugin that inherits from
-# this class and provides meaningful defaults in its '$defaultData', e.g. a
-# default list of the core properties in its propertyList (most often only 'id'
-# and 'type')
-#
-# Each 'real' plugin then has it's own package that should inherit from the
-# 'base' plugin and returns it's specific properties in the 'properties' 
method,
-# its type in the 'type' method and all the known options, from both parent and
-# itself, in the 'options' method.
-# The options method can also be used to define if a property is 'optional' or
-# 'fixed' (only settable on config entity-creation), for example:
-#
-# 
-# sub options {
-# return {
-# 'some-optional-property' => { optional => 1 },
-# 'a-fixed-property' => { fixed => 1 },
-# 'a-required-but-not-fixed-property' => {},
-# };
-# }
-# ```
-#
-# 'fixed' options can be set on create, but not changed afterwards.
-#
-# To actually use it, you have to first register all the plugins and then init
-# the 'base' plugin, like so:
-#
-# ```
-# use PVE::Dummy::Plugin1;
-# use PVE::Dummy::Plugin2;
-# use PVE::Dummy::BasePlugin;
-#
-# PVE::Dummy::Plugin1->register();
-# PVE::Dummy::Plugin2->register();
-# PVE::Dummy::BasePlugin->init();
-# ```
-#
-# There are two modes for how properties are exposed, the default 'unified'
-# mode and the 'isolated' mode.
-# In the default unified mode, there is only a global list of properties
-# which the plugins can use, so you cannot define the same property name twice
-# in different plugins. The reason for this is to force the use of identical
-# properties for multiple plugins.
-#
-# The second way is to use the 'isolated' mode, which can be achieved by
-# calling init with `1` as its parameter like this:
-#
-# ```
-# PVE::Dummy::BasePlugin->init(property_isolation => 1);
-# ```
-#
-# With this, each plugin get's their own isolated list of properties which it
-# can use. Note that in this mode, you only have to specify the property in the
-# options method when it is either 'fixed' or comes from the global list of
-# properties. All locally defined ones get automatically added to the schema
-# for that plugin.
+=pod
+
+=head1 NAME
+
+SectionConfig
+
+=head1 DESCRIPTION
+
+This package provides a way to have multiple (often similar) types of entries
+in the same config file, each in its own section, thus I.
+
+Under the hood, this package automatically creates and manages a matching
+I for one's plugin architecture that is used to represent data
+that is read from and written to the config file.
+
+Where this config file is located, as well as its permissions and other related
+things, is up to the plugin author and is not handled by C
+at all.
+
+=head1 USAGE
+
+The intended structure is to have a single I that inherits from
+this class and provides meaningful defaults in its C<$defaultData>, such as a
+default list of core C I. The I is
+thus very similar to an I.
+
+Each I is then defined in its own package that should inherit
+from the I and defines which I it itself provides and
+uses, as well as which I it uses from the I.
+
+The methods that need to be implemented are annotated in the L 
section
+below.
+
+  ┌─┐  
+  │  SectionConfig  │  
+  └┬┘  
+   │   
+   │   
+   │   
+  ┌▼┐  
+  │BasePlugin   │  
+  └┬┘  
+   │   
+ ┌─┴─┐ 
+ │   │ 
+┌▼┐ ┌▼┐
+│ConcretePluginFoo│ │ConcretePluginBar│
+└─┘ └─┘
+
+=head2 REGISTERING PLUGINS
+
+In order to actually be able to use plugins, they must first be I
+and then I via the "base" plugin:
+
+u

[pve-devel] [PATCH v1 pve-common 3/3] section config: clean up parser logic

2024-06-04 Thread Max Carrara
In order to make the parser somewhat more maintainable in the future,
this commit cleans up its logic and makes its control flow easier to
follow.

Signed-off-by: Max Carrara 
---
 src/PVE/SectionConfig.pm | 189 ---
 1 file changed, 98 insertions(+), 91 deletions(-)

diff --git a/src/PVE/SectionConfig.pm b/src/PVE/SectionConfig.pm
index a6b0183..30faaa4 100644
--- a/src/PVE/SectionConfig.pm
+++ b/src/PVE/SectionConfig.pm
@@ -1014,25 +1014,26 @@ The error.
 sub parse_config {
 my ($class, $filename, $raw, $allow_unknown) = @_;
 
-my $pdata = $class->private();
+if (!defined($raw)) {
+   return {
+   ids => {},
+   order => {},
+   digest => Digest::SHA::sha1_hex(''),
+   };
+}
+
+my $re_begins_with_comment = qr/^\s*#/;
+my $re_kv_pair = qr/^\s+  (\S+)  (\s+ (.*\S) )?  \s*$/x;
 
 my $ids = {};
 my $order = {};
-
-$raw = '' if !defined($raw);
-
 my $digest = Digest::SHA::sha1_hex($raw);
 
-my $pri = 1;
+my $current_order = 1;
+my $line_no = 0;
 
-my $lineno = 0;
 my @lines = split(/\n/, $raw);
-my $nextline = sub {
-   while (defined(my $line = shift @lines)) {
-   $lineno++;
-   return $line if ($line !~ /^\s*#/);
-   }
-};
+my @errors;
 
 my $is_array = sub {
my ($type, $key) = @_;
@@ -1043,106 +1044,112 @@ sub parse_config {
return $schema->{type} eq 'array';
 };
 
-my $errors = [];
-while (@lines) {
-   my $line = $nextline->();
+my $get_next_line = sub {
+   while (scalar(@lines)) {
+   my $line = shift(@lines);
+   $line_no++;
+
+   next if ($line =~ m/$re_begins_with_comment/);
+
+   return $line;
+   }
+
+   return undef;
+};
+
+my $skip_to_next_empty_line = sub {
+   while ($get_next_line->() ne '') {}
+};
+
+while (defined(my $line = $get_next_line->())) {
next if !$line;
 
-   my $errprefix = "file $filename line $lineno";
+   my $errprefix = "file $filename line $line_no";
 
-   my ($type, $sectionId, $errmsg, $config) = 
$class->parse_section_header($line);
-   if ($config) {
-   my $skip = 0;
-   my $unknown = 0;
+   my ($type, $section_id, $errmsg, $config) = 
$class->parse_section_header($line);
 
-   my $plugin;
+   if (!defined($config)) {
+   warn "$errprefix - ignore config line: $line\n";
+   next;
+   }
 
-   if ($errmsg) {
-   $skip = 1;
-   chomp $errmsg;
-   warn "$errprefix (skip section '$sectionId'): $errmsg\n";
-   } elsif (!$type) {
-   $skip = 1;
-   warn "$errprefix (skip section '$sectionId'): missing type - 
internal error\n";
-   } else {
-   if (!($plugin = $pdata->{plugins}->{$type})) {
-   if ($allow_unknown) {
-   $unknown = 1;
-   } else {
-   $skip = 1;
-   warn "$errprefix (skip section '$sectionId'): 
unsupported type '$type'\n";
-   }
-   }
-   }
+   if ($errmsg) {
+   chomp $errmsg;
+   warn "$errprefix (skip section '$section_id'): $errmsg\n";
+   $skip_to_next_empty_line->();
+   next;
+   }
+
+   if (!$type) {
+   warn "$errprefix (skip section '$section_id'): missing type - 
internal error\n";
+   $skip_to_next_empty_line->();
+   next;
+   }
+
+   my $plugin = eval { $class->lookup($type) };
+   my $is_unknown_type = defined($@) && $@ ne '';
+
+   if ($is_unknown_type && !$allow_unknown) {
+   warn "$errprefix (skip section '$section_id'): unsupported type 
'$type'\n";
+   $skip_to_next_empty_line->();
+   next;
+   }
+
+   # Parse kv-pairs of section - will go on until empty line is encountered
+   while (my $section_line = $get_next_line->()) {
+   if ($section_line =~ m/$re_kv_pair/) {
+   my ($key, $value) = ($1, $3);
 
-   while ($line = $nextline->()) {
-   next if $skip;
-
-   $errprefix = "file $filename line $lineno";
-
-   if ($line =~ m/^\s+(\S+)(\s+(.*\S))?\s*$/) {
-   my ($k, $v) = ($1, $3);
-
-   eval {
-   if ($unknown) {
-   if (!defined($config->{$k})) {
-   $config->{$k} = $v;
-   } else {
-   if (!ref($config->{$k})) {
-   $config->{$k} = [$config->{$k}];
-   }
-   push $config->{$k}->@*, $v;
-   }
-   } elsif ($is_array->($type, $k)) {
-   $v = $plugin->check_value($type, $k, $v, 
$sectionId);
-  

[pve-devel] [PATCH v1 pve-common 0/3] Section Config: Documentation & Code Cleanup

2024-06-04 Thread Max Carrara
Section Config: Documentation & Code Cleanup


The main focus of this series is the comprehensive documentation which
is added in patch 01. While not every single quirk and implementation
detail may be covered, it should be decent enough to help developers
quickly get started with writing their own Section Config plugin
architecture.

The docs are written in POD - not necessarily because it is a convenient
format to write documentation in, but rather because the entire Perl
ecosystem uses it. No need to reinvent the wheel. Furthermore, POD is
supported by LSPs (at least Perl Navigator), which means that the
"docstrings" for Section Config methods will actually show up as inlay
hints.

Patch 02 updates the module's code style to be more in line with our
Perl Style Guide [0].

Patch 03 cleans up the Section Config parser's internal logic and makes
its control flow easier to follow. Note that this patch does *not* mean
to change the parsing behaviour in any way, as that would risk
accidentally breaking existing Section Config plugin architectures or
config APIs.

Testing
---

Even though the existing unit tests pass, it would be nice if someone
could give this series a spin and tried to change or add various config
settings, e.g. storage settings and SDN settings, to make sure that the
updated parser logic really does behave the same as before.

Generating Docs
---

If you prefer to read the added docs in a different format, you may use
`perldoc` to render e.g. a webpage of the module's docs instead:

  $ perldoc -ohtml src/PVE/SectionConfig.pm > docs.html
  $ firefox docs.html

Summary of Changes
--

Max Carrara (3):
  section config: document package and its methods with POD
  section config: update code style
  section config: clean up parser logic

 src/PVE/SectionConfig.pm | 982 +++
 1 file changed, 798 insertions(+), 184 deletions(-)

-- 
2.39.2



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH v1 pve-common 2/3] section config: update code style

2024-06-04 Thread Max Carrara
Replace `foreach` with `for` and use postfix deref instead of block
(circumfix) dereference (`$foo->%*` instead of `%$foo`).

Furthermore, make `format_config_line` a private sub instead of
unnecessarily declaring it as an anonymous subroutine, which avoids
the `&$sub_ref(...)` syntax altogether.

Signed-off-by: Max Carrara 
---
 src/PVE/SectionConfig.pm | 62 
 1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/src/PVE/SectionConfig.pm b/src/PVE/SectionConfig.pm
index 99ee348..a6b0183 100644
--- a/src/PVE/SectionConfig.pm
+++ b/src/PVE/SectionConfig.pm
@@ -422,7 +422,7 @@ sub createSchema {
 my $props = $base || {};
 
 if (!$class->has_isolated_properties()) {
-   foreach my $p (keys %$propertyList) {
+   for my $p (keys $propertyList->%*) {
next if $skip_type && $p eq 'type';
 
if (!$propertyList->{$p}->{optional}) {
@@ -435,7 +435,7 @@ sub createSchema {
my $copts = $class->options();
$required = 0 if defined($copts->{$p}) && $copts->{$p}->{optional};
 
-   foreach my $t (keys %$plugins) {
+   for my $t (keys $plugins->%*) {
my $opts = $pdata->{options}->{$t} || {};
$required = 0 if !defined($opts->{$p}) || 
$opts->{$p}->{optional};
}
@@ -450,7 +450,7 @@ sub createSchema {
}
}
 } else {
-   for my $type (sort keys %$plugins) {
+   for my $type (sort keys $plugins->%*) {
my $opts = $pdata->{options}->{$type} || {};
for my $key (sort keys $opts->%*) {
my $schema = $class->get_property_schema($type, $key);
@@ -510,7 +510,7 @@ sub updateSchema {
 my $filter_type = $single_class ? $class->type() : undef;
 
 if (!$class->has_isolated_properties()) {
-   foreach my $p (keys %$propertyList) {
+   for my $p (keys $propertyList->%*) {
next if $p eq 'type';
 
my $copts = $class->options();
@@ -526,7 +526,7 @@ sub updateSchema {
 
$modifyable = 1 if defined($copts->{$p}) && !$copts->{$p}->{fixed};
 
-   foreach my $t (keys %$plugins) {
+   for my $t (keys $plugins->%*) {
my $opts = $pdata->{options}->{$t} || {};
next if !defined($opts->{$p});
$modifyable = 1 if !$opts->{$p}->{fixed};
@@ -536,7 +536,7 @@ sub updateSchema {
$props->{$p} = $propertyList->{$p};
}
 } else {
-   for my $type (sort keys %$plugins) {
+   for my $type (sort keys $plugins->%*) {
my $opts = $pdata->{options}->{$type} || {};
for my $key (sort keys $opts->%*) {
next if $opts->{$key}->{fixed};
@@ -605,7 +605,7 @@ sub init {
 
 my $pdata = $class->private();
 
-foreach my $k (qw(options plugins plugindata propertyList 
isolatedPropertyList)) {
+for my $k (qw(options plugins plugindata propertyList 
isolatedPropertyList)) {
$pdata->{$k} = {} if !$pdata->{$k};
 }
 
@@ -613,9 +613,9 @@ sub init {
 my $propertyList = $pdata->{propertyList};
 my $isolatedPropertyList = $pdata->{isolatedPropertyList};
 
-foreach my $type (keys %$plugins) {
+for my $type (keys $plugins->%*) {
my $props = $plugins->{$type}->properties();
-   foreach my $p (keys %$props) {
+   for my $p (keys $props->%*) {
my $res;
if ($property_isolation) {
$res = $isolatedPropertyList->{$type}->{$p} = {};
@@ -624,16 +624,16 @@ sub init {
$res = $propertyList->{$p} = {};
}
my $data = $props->{$p};
-   for my $a (keys %$data) {
+   for my $a (keys $data->%*) {
$res->{$a} = $data->{$a};
}
$res->{optional} = 1;
}
 }
 
-foreach my $type (keys %$plugins) {
+for my $type (keys $plugins->%*) {
my $opts = $plugins->{$type}->options();
-   foreach my $p (keys %$opts) {
+   for my $p (keys $opts->%*) {
my $prop;
if ($property_isolation) {
$prop = $isolatedPropertyList->{$type}->{$p};
@@ -644,7 +644,7 @@ sub init {
 
# automatically the properties to options (if not specified explicitly)
if ($property_isolation) {
-   foreach my $p (keys $isolatedPropertyList->{$type}->%*) {
+   for my $p (keys $isolatedPropertyList->{$type}->%*) {
next if $opts->{$p};
$opts->{$p} = {};
$opts->{$p}->{optional} = 1 if 
$isolatedPropertyList->{$type}->{$p}->{optional};
@@ -655,7 +655,7 @@ sub init {
 }
 
 $propertyList->{type}->{type} = 'string';
-$propertyList->{type}->{enum} = [sort keys %$plugins];
+$propertyList->{type}->{enum} = [sort keys $plugins->%*];
 }
 
 =pod
@@ -796,7 +796,7 @@ sub check_value {
}
 
PVE::JSONSchema::check_prop($value, $checkschema, '', $errors);
-   if (scalar(keys %$errors)) {
+ 

[pve-devel] applied-series: [PATCH many v3 0/8] notifications: move template strings to template files

2024-06-04 Thread Wolfgang Bumiller
applied series & bumped packages, thanks


___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH stable-7 container 2/2] setup: unlink default netplan configuration even with Ubuntu >= 23.04

2024-06-04 Thread Christoph Heiss
From: Fiona Ebner 

It seems like commit 02d9462 ("setup: enable systemd-networkd via
preset for ubuntu 23.04+") also resulted in the default netplan
configuration no longer being unlinked. That should still happen, even
if systemd-networkd is now enabled via preset. Otherwise, the network
configuration created by Proxmox VE is not ordered before the one
generated by netplan and thus not applied by systemd-networkd.

Reported in the community forum:
https://forum.proxmox.com/threads/145848/post-658058

Fixes: 02d9462 ("setup: enable systemd-networkd via preset for ubuntu 23.04+")
Signed-off-by: Fiona Ebner 
(cherry picked from commit dfcbad017361d4e3ded20af573fbaeacc05231eb)
Signed-off-by: Christoph Heiss 
---
 src/PVE/LXC/Setup/Ubuntu.pm | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/PVE/LXC/Setup/Ubuntu.pm b/src/PVE/LXC/Setup/Ubuntu.pm
index cea8ef5..897eab9 100644
--- a/src/PVE/LXC/Setup/Ubuntu.pm
+++ b/src/PVE/LXC/Setup/Ubuntu.pm
@@ -73,7 +73,9 @@ sub template_fixup {
  
'/etc/systemd/system/multi-user.target.wants/systemd-networkd.service');
$self->ct_symlink('/lib/systemd/system/systemd-networkd.socket',
  
'/etc/systemd/system/socket.target.wants/systemd-networkd.socket');
+}
 
+if ($version >= '17.10') {
# unlink default netplan lxc config
$self->ct_unlink('/etc/netplan/10-lxc.yaml');
 }
-- 
2.44.1



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH stable-7 container 0/2] setup: cherry-pick ubuntu 24.04 support

2024-06-04 Thread Christoph Heiss
This backports the series to support Ubuntu 24.04 "Noble" CTs [0].

They could be cherry-picked cleanly. Tested on a up-to-date PVE 7.4
system (running on `pvetest`), template for Ubuntu 24.04
(`ubuntu-24.04-standard_24.04-2_amd64.tar.zst`) was copied from a 8.2
host for testing.

Tested creating new CT from that template, using either a static IP or
DHCP. Then working around with the system a bit, everything seems to
work just fine.

[0] https://lists.proxmox.com/pipermail/pve-devel/2024-April/063766.html

Fiona Ebner (2):
  setup: support Ubuntu 24.04 Noble
  setup: unlink default netplan configuration even with Ubuntu >= 23.04

 src/PVE/LXC/Setup/Ubuntu.pm | 3 +++
 1 file changed, 3 insertions(+)

-- 
2.44.1



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH stable-7 container 1/2] setup: support Ubuntu 24.04 Noble

2024-06-04 Thread Christoph Heiss
From: Fiona Ebner 

Minimally tested, that an upgrade from an existing 23.04 container
works, there still is network and no obviously bad messages in the
container's journal.

Reported in the community forum:
https://forum.proxmox.com/threads/145848/

Signed-off-by: Fiona Ebner 
(cherry picked from commit 3d800f832c25e4bf2435d88ab190fd8e681a67b1)
Signed-off-by: Christoph Heiss 
---
 src/PVE/LXC/Setup/Ubuntu.pm | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/PVE/LXC/Setup/Ubuntu.pm b/src/PVE/LXC/Setup/Ubuntu.pm
index 905cacb..cea8ef5 100644
--- a/src/PVE/LXC/Setup/Ubuntu.pm
+++ b/src/PVE/LXC/Setup/Ubuntu.pm
@@ -12,6 +12,7 @@ use PVE::LXC::Setup::Debian;
 use base qw(PVE::LXC::Setup::Debian);
 
 my $known_versions = {
+'24.04' => 1, # noble
 '23.10' => 1, # mantic
 '23.04' => 1, # lunar
 '22.10' => 1, # kinetic
-- 
2.44.1



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel