]> git.proxmox.com Git - pve-container.git/commitdiff
use /etc/os-release
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Tue, 1 Aug 2017 09:28:55 +0000 (11:28 +0200)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 2 Aug 2017 07:46:47 +0000 (09:46 +0200)
This should exist everywhere, its content look like shell
assignments but are limited enough to not require a shell to
parse (see os-release(5) or its parts pasted as a comment to
the parse function).
Further motivation for this is the fact that in suse the
/etc/SuSE-release file is declared deprecated in favor of
/etc/os-release.
Note that we have to read the file in a protected_call to
avoid symlink issues.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
src/PVE/LXC/Setup.pm
src/PVE/LXC/Setup/Base.pm

index f05c32ea3eeb49b468ca5987999f4714724deff6..aa8bc45dd5d1969029d46e6132b68fdb0e8fc895 100644 (file)
@@ -27,7 +27,13 @@ my $plugins = {
 };
 
 my $autodetect_type = sub {
 };
 
 my $autodetect_type = sub {
-    my ($rootdir) = @_;
+    my ($self, $rootdir, $os_release) = @_;
+
+    if (my $id = $os_release->{ID}) {
+       return $id if $id =~ /^(?:alpine|arch|centos|debian|fedora|gentoo|opensuse|ubuntu)$/;
+    }
+
+    # fallback compatibility checks
 
     my $lsb_fn = "$rootdir/etc/lsb-release";
     if (-f $lsb_fn) {
 
     my $lsb_fn = "$rootdir/etc/lsb-release";
     if (-f $lsb_fn) {
@@ -62,11 +68,13 @@ sub new {
 
     my $self = bless { conf => $conf, rootdir => $rootdir};
 
 
     my $self = bless { conf => $conf, rootdir => $rootdir};
 
+    my $os_release = $self->get_ct_os_release();
+
     if ($conf->{ostype} && $conf->{ostype} eq 'unmanaged') {
        return $self;
     } elsif (!defined($type)) {
        # try to autodetect type
     if ($conf->{ostype} && $conf->{ostype} eq 'unmanaged') {
        return $self;
     } elsif (!defined($type)) {
        # try to autodetect type
-       $type = &$autodetect_type($rootdir);
+       $type = &$autodetect_type($self, $rootdir, $os_release);
        my $expected_type = $conf->{ostype} || $type;
 
        die "got unexpected ostype ($type != $expected_type)\n"
        my $expected_type = $conf->{ostype} || $type;
 
        die "got unexpected ostype ($type != $expected_type)\n"
@@ -76,7 +84,7 @@ sub new {
     my $plugin_class = $plugins->{$type} ||
        "no such OS type '$type'\n";
 
     my $plugin_class = $plugins->{$type} ||
        "no such OS type '$type'\n";
 
-    my $plugin = $plugin_class->new($conf, $rootdir);
+    my $plugin = $plugin_class->new($conf, $rootdir, $os_release);
     $self->{plugin} = $plugin;
     $self->{in_chroot} = 0;
 
     $self->{plugin} = $plugin;
     $self->{in_chroot} = 0;
 
@@ -287,4 +295,53 @@ sub post_create_hook {
     $self->rewrite_ssh_host_keys();
 }
 
     $self->rewrite_ssh_host_keys();
 }
 
+# os-release(5):
+#   (...) a newline-separated list of environment-like shell-compatible
+#   variable assignments. (...) beyond mere variable assignments, no shell
+#   features are supported (this means variable expansion is explicitly not
+#   supported) (...). Variable assignment values must be enclosed in double or
+#   single quotes *if* they include spaces, semicolons or other special
+#   characters outside of A-Z, a-z, 0-9. Shell special characters ("$", quotes,
+#   backslash, backtick) must be escaped with backslashes (...). All strings
+#   should be in UTF-8 format, and non-printable characters should not be used.
+#   It is not supported to concatenate multiple individually quoted strings.
+#   Lines beginning with "#" shall be ignored as comments.
+my $parse_os_release = sub {
+    my ($data) = @_;
+    my $variables = {};
+    while (defined($data) && $data =~ /^(.+)$/gm) {
+       next if $1 !~ /^\s*([a-zA-Z_][a-zA-Z0-9_]*)=(.*)$/;
+       my ($var, $content) = ($1, $2);
+       chomp $content;
+
+       if ($content =~ /^'([^']*)'/) {
+           $variables->{$var} = $1;
+       } elsif ($content =~ /^"((?:[^"\\]|\\.)*)"/) {
+           my $s = $1;
+           $s =~ s/(\\["'`nt\$\\])/"\"$1\""/eeg;
+           $variables->{$var} = $s;
+       } elsif ($content =~ /^([A-Za-z0-9]*)/) {
+           $variables->{$var} = $1;
+       }
+    }
+    return $variables;
+};
+
+sub get_ct_os_release {
+    my ($self) = @_;
+
+    my $code = sub {
+       if (-f '/etc/os-release') {
+           return PVE::Tools::file_get_contents('/etc/os-release');
+       } elsif (-f '/usr/lib/os-release') {
+           return PVE::Tools::file_get_contents('/usr/lib/os-release');
+       }
+       return undef;
+    };
+
+    my $data = $self->protected_call($code);
+
+    return &$parse_os_release($data);
+}
+
 1;
 1;
index 7bf66ca81d62de49c0b0dd06723dfc3a2ba7479b..0228fe7655b1d59721503431c1d31a2fafe5a038 100644 (file)
@@ -17,9 +17,9 @@ use PVE::Tools;
 use PVE::Network;
 
 sub new {
 use PVE::Network;
 
 sub new {
-    my ($class, $conf, $rootdir) = @_;
+    my ($class, $conf, $rootdir, $os_release) = @_;
 
 
-    return bless { conf => $conf, rootdir => $rootdir }, $class;
+    return bless { conf => $conf, rootdir => $rootdir, os_release => $os_release }, $class;
 }
 
 sub lookup_dns_conf {
 }
 
 sub lookup_dns_conf {