# defaults:
# origin: debian
+# flags:
+# systemd: true (except for devuan ostypes)
my $supported_suites = {
'bookworm' => {
ostype => "debian-12",
ostype => "debian-8.0",
},
'wheezy' => {
+ flags => {
+ systemd => 0,
+ },
ostype => "debian-7.0",
},
'squeeze' => {
+ flags => {
+ systemd => 0,
+ },
ostype => "debian-6.0",
},
'lenny' => {
+ flags => {
+ systemd => 0,
+ },
ostype => "debian-5.0",
},
'etch' => {
+ flags => {
+ systemd => 0,
+ },
ostype => "debian-4.0",
},
-# DEVUAN
+# DEVUAN (imply systemd = 0 default)
'devuan-jessie' => {
suite => 'jessie',
ostype => "devuan-1.0",
'chimaera' => {
ostype => "devuan-4.0",
},
+ 'daedalus' => {
+ ostype => "devuan-5.0",
+ },
# UBUNTU
'hardy' => {
+ flags => {
+ systemd => 0,
+ },
ostype => "ubuntu-8.04",
origin => 'ubuntu',
},
'intrepid' => {
+ flags => {
+ systemd => 0,
+ },
ostype => "ubuntu-8.10",
origin => 'ubuntu',
},
'jaunty' => {
+ flags => {
+ systemd => 0,
+ },
ostype => "ubuntu-9.04",
origin => 'ubuntu',
},
'precise' => {
+ flags => {
+ systemd => 0,
+ },
ostype => "ubuntu-12.04",
origin => 'ubuntu',
},
'trusty' => {
+ flags => {
+ systemd => 0,
+ },
ostype => "ubuntu-14.04",
origin => 'ubuntu',
},
ostype => "ubuntu-21.10",
origin => 'ubuntu',
},
+ 'jammy' => {
+ ostype => "ubuntu-22.04",
+ origin => 'ubuntu',
+ },
};
sub get_suite_info {
$suiteinfo->{origin} //= 'debian';
$suiteinfo->{suite} //= $suite;
+ $suiteinfo->{flags} //= {};
+ if ($suiteinfo->{ostype} =~ /^devuan/) {
+ $suiteinfo->{flags}->{systemd} //= 0;
+ } else {
+ $suiteinfo->{flags}->{systemd} //= 1;
+ }
+
return $suiteinfo;
}
sub download {
my ($self, $url, $path) = @_;
+ my $tmpfn = "$path.tmp$$";
$self->logmsg ("download: $url\n");
- my $tmpfn = "$path.tmp$$";
- eval {
- $self->run_command ("wget -q '$url' -O '$tmpfn'");
- };
- my $err = $@;
- if ($err) {
+ eval { $self->run_command ("wget -q '$url' -O '$tmpfn'") };
+ if (my $err = $@) {
unlink $tmpfn;
die $err;
}
print $writer $input if defined $input;
close $writer;
- my $select = new IO::Select;
+ my $select = IO::Select->new();
$select->add ($reader);
$select->add ($error);
$self->{infodir} = "info";
- $self->__allocate_ve ();
+ $self->__allocate_ve();
$self->{cachedir} = ($config->{cachedir} || 'cache') . "/$suite";;
my $incl = [qw (less ssh openssh-server logrotate)];
- my $excl = [qw (modutils reiserfsprogs ppp pppconfig pppoe
- pppoeconf nfs-common mtools ntp)];
+ my $excl = [qw (modutils reiserfsprogs ppp pppconfig pppoe pppoeconf nfs-common mtools ntp)];
# ubuntu has too many dependencies on udev, so
# we cannot exclude it (instead we disable udevd)
- if ($suite eq 'vivid' || $suite eq 'wily' || $suite eq 'xenial' ||
- $suite eq 'yakkety' || $suite eq 'zesty' || $suite eq 'artful' ||
- $suite eq 'bionic' || $suite eq 'cosmic' || $suite eq 'disco' ||
- $suite eq 'eoan' || $suite eq 'focal' || $suite eq 'groovy'
- || $suite eq 'hirsute' || $suite eq 'impish'
- ) {
+ if (lc($suiteinfo->{origin}) eq 'ubuntu' && $suiteinfo->{flags}->{systemd}) {
push @$incl, 'isc-dhcp-client';
- push @$excl, qw(libmodule-build-perl);
+ push @$excl, qw(libmodule-build-perl plymouth plymouth-theme-ubuntu-text powermgmt-base);
+ if ($suite eq 'jammy') {
+ push @$excl, qw(fuse); # avoid fuse2 <-> fuse3 conflict
+ }
} elsif ($suite eq 'trusty') {
push @$excl, qw(systemd systemd-services libpam-systemd libsystemd-daemon0 memtest86+);
} elsif ($suite eq 'precise') {
push @$excl, qw(systemd systemd-services libpam-systemd libsystemd-daemon0 memtest86+ ubuntu-standard);
} elsif ($suite eq 'hardy') {
push @$excl, qw(kbd);
- push @$excl, qw(apparmor apparmor-utils ntfs-3g
- friendly-recovery);
+ push @$excl, qw(apparmor apparmor-utils ntfs-3g friendly-recovery);
} elsif ($suite eq 'intrepid' || $suite eq 'jaunty') {
- push @$excl, qw(apparmor apparmor-utils libapparmor1 libapparmor-perl
- libntfs-3g28 ntfs-3g friendly-recovery);
+ push @$excl, qw(apparmor apparmor-utils libapparmor1 libapparmor-perl libntfs-3g28);
+ push @$excl, qw(ntfs-3g friendly-recovery);
} elsif ($suite eq 'jessie') {
push @$incl, 'sysvinit-core'; # avoid systemd and udev
push @$incl, 'libperl4-corelibs-perl'; # to make lsof happy
$self->run_command ("lxc-stop -n $veid --rcfile $conffile --kill");
unlink "$rootdir/sbin/defenv";
-
unlink <$rootdir/root/dead.letter*>;
-
unlink "$rootdir/var/log/init.log";
-
- unlink "$rootdir/aquota.group";
-
- unlink "$rootdir/aquota.user";
+ unlink "$rootdir/aquota.group", "$rootdir/aquota.user";
write_file ("", "$rootdir/var/log/syslog");
my $pkgfilelist = "$rootdir/var/lib/dpkg/status";
local $/ = '';
- open (PKGLST, "<$pkgfilelist") ||
- die "unable to open '$pkgfilelist'";
+ open(my $PKGLST, '<', $pkgfilelist) or die "unable to open '$pkgfilelist' - $!";
my $pkglist = {};
- while (my $rec = <PKGLST>) {
+ while (my $rec = <$PKGLST>) {
chomp $rec;
$rec =~ s/\n\s+/ /g;
$rec .= "\n";
my $res = {};
- while ($rec =~ s/^([^:]+):\s+(.*)\s*\n//) {
+ while ($rec =~ s/^([^:]+):\s+(.*?)\s*\n//) {
$res->{lc $1} = $2;
}
}
}
- close (PKGLST);
+ close ($PKGLST);
return $pkglist;
}
}
}
close($fh);
-
+
return $res;
}
if (ref ($cmd) eq 'ARRAY') {
unshift @$cmd, 'lxc-attach', '-n', $veid, '--rcfile', $conffile, '--clear-env', '--', 'defenv';
- $self->run_command ($cmd, $input);
+ $self->run_command($cmd, $input);
} else {
- $self->run_command ("lxc-attach -n $veid --rcfile $conffile --clear-env -- defenv $cmd", $input);
+ $self->run_command("lxc-attach -n $veid --rcfile $conffile --clear-env -- defenv $cmd", $input);
}
}
my ($pkginfo, $filename, $src) = @_;
local $/ = '';
- open (PKGLST, "<$filename") ||
- die "unable to open '$filename'";
+ open(my $PKGLST, '<', $filename) or die "unable to open '$filename' - $!";
- while (my $rec = <PKGLST>) {
+ while (my $rec = <$PKGLST>) {
$rec =~ s/\n\s+/ /g;
chomp $rec;
$rec .= "\n";
my $res = {};
- while ($rec =~ s/^([^:]+):\s+(.*)\s*\n//) {
+ while ($rec =~ s/^([^:]+):\s+(.*?)\s*\n//) {
$res->{lc $1} = $2;
}
}
}
- close (PKGLST);
+ close ($PKGLST);
}
sub pkginfo {
my ($self, $script, $runlevel, $prio) = @_;
my $suite = $self->{config}->{suite};
+ my $suiteinfo = get_suite_info($suite);
my $rootdir = $self->{rootfs};
my $base = basename ($script);
$self->run_command ("install -m 0755 '$script' '$target'");
if ($suite eq 'etch' || $suite eq 'lenny') {
$self->ve_command ("update-rc.d $base start $prio $runlevel .");
- } elsif ($suite eq 'xenial' || $suite eq 'wily' || $suite eq 'vivid' ||
- $suite eq 'yakkety' || $suite eq 'zesty' || $suite eq 'artful' ||
- $suite eq 'bionic' || $suite eq 'cosmic' || $suite eq 'disco' ||
- $suite eq 'eoan' || $suite eq 'focal' || $suite eq 'groovy'
- || $suite eq 'hirsute' || $suite eq 'impish'
- ) {
+ } elsif ($suiteinfo->{flags}->{systemd}) {
die "unable to install init script (system uses systemd)\n";
} elsif ($suite eq 'trusty' || $suite eq 'precise') {
die "unable to install init script (system uses upstart)\n";
my $pkginfo = $self->pkginfo();
my $veid = $self->{veid};
my $suite = $self->{config}->{suite};
+ my $suiteinfo = get_suite_info($suite);
my $important = [ @{$self->{incl}} ];
my $required;
my $standard;
my $mta = $opts->{exim} ? 'exim' : 'postfix';
-
if ($mta eq 'postfix') {
push @$important, "postfix";
}
+ if ($opts->{include}) {
+ push @$important, split(',', $opts->{include});
+ }
+
+ my $exclude = {};
+ if ($opts->{exclude}) {
+ $exclude->{$_} = 1 for split(',', $opts->{exclude});
+ }
+
foreach my $p (sort keys %$pkginfo) {
next if grep { $p eq $_ } @{$self->{excl}};
my $pri = $pkginfo->{$p}->{priority};
next if $p =~ m/(selinux|semanage|policycoreutils)/;
push @$required, $p if $pri eq 'required';
+ next if $exclude->{$p};
push @$important, $p if $pri eq 'important';
push @$standard, $p if $pri eq 'standard' && !$opts->{minimal};
}
my $closure = {};
- $required = $self->closure ($closure, $required);
- $important = $self->closure ($closure, $important);
+ $required = $self->closure($closure, $required);
+ $important = $self->closure($closure, $important);
if (!$opts->{minimal}) {
- push @$standard, 'xbase-clients';
- $standard = $self->closure ($closure, $standard);
+ $standard = $self->closure($closure, $standard);
}
# test if we have all 'ubuntu-minimal' and 'ubuntu-standard' packages
$self->setup_usr_merge();
}
+ my $compressor2opt = {
+ 'zst' => '--zstd',
+ 'gz' => '--gzip',
+ 'xz' => '--xz',
+ };
+ my $compressor_re = join('|', keys $compressor2opt->%*);
+
$self->logmsg ("extract required packages to rootfs\n");
foreach my $p (@$required) {
my $filename = $self->getpkgfile ($p);
my $content = $self->run_command("ar -t '$self->{cachedir}/$filename'", undef, 1);
- if ($content =~ m/^data.tar.xz$/m) {
- $self->run_command ("ar -p '$self->{cachedir}/$filename' data.tar.xz | tar -C '$rootdir' -xJf - --keep-directory-symlink");
+ if ($content =~ m/^(data.tar.($compressor_re))$/m) {
+ my $archive = $1;
+ my $tar_opts = "--keep-directory-symlink $compressor2opt->{$2}";
+
+ $self->run_command("ar -p '$self->{cachedir}/$filename' '$archive' | tar -C '$rootdir' -xf - $tar_opts");
} else {
- $self->run_command ("ar -p '$self->{cachedir}/$filename' data.tar.gz | tar -C '$rootdir' -xzf - --keep-directory-symlink");
+ die "unexpected error for $p: no data.tar.{xz,gz,zst} found...";
}
}
# avoid warnings about non-existent resolv.conf
write_file ("", "$rootdir/etc/resolv.conf", 0644);
- if (
- $suite eq 'impish' ||
- $suite eq 'hirsute' || $suite eq 'groovy' || $suite eq 'focal' ||
- $suite eq 'eoan' || $suite eq 'disco' || $suite eq 'cosmic' ||
- $suite eq 'bionic' || $suite eq 'artful' ||
- $suite eq 'zesty' || $suite eq 'yakkety' || $suite eq 'xenial' ||
- $suite eq 'wily'
- ) {
+ if (lc($suiteinfo->{origin}) eq 'ubuntu' && $suiteinfo->{flags}->{systemd}) {
# no need to configure loopback device
+ # FIXME: Debian (systemd based?) too?
} else {
$data = "auto lo\niface lo inet loopback\n";
mkdir "$rootdir/etc/network";
$self->ve_divert_add ("/sbin/udevd");
if ($suite eq 'etch') {
- # disable apache2 startup
- write_file ("NO_START=1\n", "$rootdir/etc/default/apache2");
+ write_file ("NO_START=1\n", "$rootdir/etc/default/apache2"); # disable apache2 startup
}
$self->logmsg ("configure required packages\n");
my $instpkgs = $self->read_installed ();
my $closure = {};
- __record_provides ($pkginfo, $closure, [keys %$instpkgs]);
+ __record_provides($pkginfo, $closure, [keys $instpkgs->%*]);
return $self->closure ($closure, $pkglist);
}
my ($self, $opts) = @_;
my @supp = ('7.4', '8.1');
- my $pgversion = '8.1';
+ my $pgversion; # NOTE: not setting that defaults to the distro default, normally the best choice
my $suite = $self->{config}->{suite};
@supp = ('8.4');
$pgversion = '8.4';
} elsif ($suite eq 'wheezy') {
- @supp = ('9.1');
- $pgversion = '9.1';
+ @supp = ('9.1');
+ $pgversion = '9.1';
} elsif ($suite eq 'jessie') {
- @supp = ('9.4');
- $pgversion = '9.4';
+ @supp = ('9.4');
+ $pgversion = '9.4';
} elsif ($suite eq 'stretch') {
- @supp = ('9.6');
- $pgversion = '9.6';
+ @supp = ('9.6');
+ $pgversion = '9.6';
} elsif ($suite eq 'buster') {
- @supp = ('11');
- $pgversion = '11';
+ @supp = ('11');
+ $pgversion = '11';
} elsif ($suite eq 'bullseye') {
@supp = ('13');
- $pgversion = '13';
} elsif ($suite eq 'bookworm') {
# FIXME: update once froozen
- @supp = ('13');
- $pgversion = '13';
+ @supp = ('13', '14');
}
-
$pgversion = $opts->{version} if $opts->{version};
- die "unsupported postgres version '$pgversion'\n"
- if !grep { $pgversion eq $_; } @supp;
-
- my $rootdir = $self->{rootfs};
+ my $required;
+ if (defined($pgversion)) {
+ die "unsupported postgres version '$pgversion'\n" if !grep { $pgversion eq $_; } @supp;
- my $required = $self->compute_required (["postgresql-$pgversion"]);
+ $required = $self->compute_required (["postgresql-$pgversion"]);
+ } else {
+ $required = $self->compute_required (["postgresql"]);
+ }
$self->cache_packages ($required);
my $rootdir = $self->{rootfs};
my $suite = $self->{config}->{suite};
-
+
my $ver = '5.0';
if ($suite eq 'squeeze') {
$ver = '5.1';
my $memlimit = $opts->{memlimit};
my $rootdir = $self->{rootfs};
+ my $suite = $self->{config}->{suite};
- my $required = $self->compute_required ([qw (php5 php5-cli libapache2-mod-php5 php5-gd)]);
+ my $base_set = [qw(php-cli libapache2-mod-php php-gd)];
+ if ($suite =~ /(?:squeeze|wheezy|jessie)$/) {
+ $self->logmsg("WARN: using EOL php release on EOL suite");
+ $base_set = [qw(php5 php5-cli libapache2-mod-php5 php5-gd)];
+ }
+ my $required = $self->compute_required($base_set);
$self->cache_packages ($required);
$self->ve_dpkg ('install', @$required);
if ($memlimit) {
- $self->run_command ("sed -e 's/^\\s*memory_limit\\s*=.*;/memory_limit = ${memlimit}M;/' -i $rootdir/etc/php5/apache2/php.ini");
+ my $sed_cmd = ['sed', '-e', "s/^\\s*memory_limit\\s*=.*;/memory_limit = ${memlimit}M;/", '-i'];
+ if ($suite =~ /(?:squeeze|wheezy|jessie)$/) {
+ push @$sed_cmd, "$rootdir/etc/php5/apache2/php.ini";
+ } else {
+ my $found = 0;
+ for my $fn (glob("'${rootdir}/etc/php/*/apache2/php.ini'")) {
+ push @$sed_cmd, "$rootdir/$fn";
+ $found = 1;
+ }
+ if (!$found) {
+ warn "WARN: did not found any php.ini to set the memlimit!\n";
+ return;
+ }
+ }
+ $self->run_command($sed_cmd);
}
}
my ($self, $pkglist, $unpack) = @_;
my $required = $self->compute_required ($pkglist);
-
+
$self->cache_packages ($required);
$self->ve_dpkg ($unpack ? 'unpack' : 'install', @$required);