aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xiurt248
-rwxr-xr-xiurt_root_command30
-rw-r--r--lib/Iurt/Chroot.pm96
3 files changed, 119 insertions, 55 deletions
diff --git a/iurt2 b/iurt2
index 8529c45..a0f10ac 100755
--- a/iurt2
+++ b/iurt2
@@ -39,7 +39,7 @@ use URPM;
use Iurt::DKMS;
use Iurt::Urpmi;
-use Iurt::Chroot qw(add_local_user create_temp_chroot remove_chroot clean_all_chroot_tmp create_build_chroot clean_chroot);
+use Iurt::Chroot qw(add_local_user create_temp_chroot remove_chroot create_build_chroot clean_chroot);
use Iurt::Process qw(perform_command kill_for_good sudo);
use Iurt::Mail qw(sendmail);
use Iurt::Util qw(plog_init plog);
@@ -351,6 +351,12 @@ $run{todo} = [];
sub {
$run{icecream} = $_[0];
}, "Enabling icecream usage" ],
+ ###############################
+ [ "", "storage", 1, "[btrfs|tar]",
+ "Select how to store reference chroot",
+ sub {
+ $run{storage} = $_[0];
+ }, "Setting storage" ],
);
open(my $LOG, ">&STDERR");
@@ -364,7 +370,6 @@ plog_init($program_name, $run{logfd} || $LOG, 7, 1); # For parsing command line
(my $iurt_dat = '$Date$') =~ s/.*: ([\d-]* [\d:]*) .*/$1/;
plog("MSG", "This is iurt2 revision $iurt_rev-$iurt_aut ($iurt_dat)");
-
my $todo = parseCommandLine($program_name, \@ARGV, \@params);
@ARGV and usage($program_name, \@params, "@ARGV, too many arguments");
foreach my $t (@$todo) {
@@ -436,6 +441,10 @@ my %config_usage = (
'curl',
]
},
+ btrfs_base => {
+ desc => 'Where to create btrfs subvolumes',
+ default => $HOME
+ },
build_timeout => {
desc => 'Maximum build time after which the build process is terminated',
default => {
@@ -687,20 +696,25 @@ my (%done, $done);
$run{done} = \%done;
my $home = $config->{local_home};
-my ($chroot_name, $chroot_tmp, $chroot, $chroot_tar);
+my $chroot_base;
+if ($run{storage} eq 'btrfs') {
+ $chroot_base = $config->{btrfs_base};
+} else {
+ $chroot_base = $config->{local_home};
+}
+my ($chroot_name, $chroot_tmp, $chroot, $chroot_ref);
$chroot_name = "chroot_$run{distro_tag}$debug_tag.$run{my_arch}";
if (!$run{use_old_chroot}) {
- $chroot_tmp = "$config->{local_home}/chroot_tmp";
+ $chroot_tmp = "$chroot_base/chroot_tmp";
if (!-d $chroot_tmp) {
mkdir $chroot_tmp;
} else {
- remove_chroot(\%run, $chroot_tmp, \&clean_all_chroot_tmp, $chroot_name);
+ remove_chroot(\%run, $chroot_tmp, $chroot_name);
}
- $chroot_tmp = "$config->{local_home}/chroot_tmp/$run{user}";
- mkdir_p($chroot_tmp);
- $chroot_tmp = "$config->{local_home}/chroot_tmp/$run{user}/$chroot_name.$run{run}";
+ mkdir_p("$chroot_tmp/$run{user}");
+ $chroot_tmp = "$chroot_tmp/$run{user}/$chroot_name.$run{run}";
$run{chroot_tmp} = $chroot_tmp;
$chroot = "$config->{local_home}/$chroot_name";
@@ -710,13 +724,17 @@ if (!$run{use_old_chroot}) {
$chroot = $run{use_old_chroot};
}
$run{chroot_path} = $chroot;
-$chroot_tar = "$config->{local_home}/$chroot_name.tar.gz";
-$run{chroot_tar} = $chroot_tar;
+if ($run{storage} eq 'btrfs') {
+ $chroot_ref = "$chroot_base/$chroot_name";
+} else {
+ $chroot_ref = "$chroot_base/$chroot_name.tar.gz";
+}
+$run{chroot_ref} = $chroot_ref;
# 20061222 warly
# even in use_old_chroot mode we create the chroot if it does not exist (useful
# if the option is used for the first time
if ($run{chroot} || !-d "$chroot/dev") {
- create_build_chroot($chroot, $chroot_tar, \%run, $config) or die "FATAL $program_name: could not prepare initial chroot";
+ create_build_chroot($chroot, $chroot_ref, \%run, $config) or die "FATAL $program_name: could not prepare initial chroot";
}
# now exit if there is nothing to do and it was just a cleaning pass
@@ -737,7 +755,7 @@ if ($df->{per} >= 99) {
if ($run{shell}) {
if (!$run{use_old_chroot}) {
- create_temp_chroot(\%run, $config, $chroot_tmp, $chroot_tar)
+ create_temp_chroot(\%run, $config, $chroot_tmp, $chroot_ref)
or die "FATAL $program_name: could not create temporary chroot";
}
add_local_user($chroot_tmp, \%run, $config, $luser, $run{uid}) or die "FATAL $program_name: could not add local user";
@@ -836,7 +854,7 @@ retry:
if (!$run{use_old_chroot}) {
$chroot_tmp = create_temp_chroot(\%run, $config,
- $chroot_tmp, $chroot_tar) or next;
+ $chroot_tmp, $chroot_ref) or next;
}
if (!$urpmi->urpmi_command($chroot_tmp)) {
@@ -864,7 +882,7 @@ retry:
($ret, $srpm, $spec) = $urpmi->recreate_srpm(\%run, $config,
$chroot_tmp, $dir, $srpm, $luser, $retry);
if ($ret == -1) {
- if (create_build_chroot($run{chroot_path}, $run{chroot_tar}, \%run, $config)) {
+ if (create_build_chroot($run{chroot_path}, $run{chroot_ref}, \%run, $config)) {
$retry = 1;
goto retry;
} else {
@@ -1063,7 +1081,7 @@ retry:
} while $rebuild;
if (!$run{debug} && !$run{use_old_chroot}) {
- clean_chroot($chroot_tmp, $chroot_tar, \%run, $config, 1);
+ clean_chroot($chroot_tmp, $chroot_ref, \%run, $config, 1);
}
plog("reprocess generated packages queue");
process_queue($config, \%run, \@wrong_rpm);
diff --git a/iurt_root_command b/iurt_root_command
index fad6c13..90abf38 100755
--- a/iurt_root_command
+++ b/iurt_root_command
@@ -147,6 +147,18 @@ $run{todo} = [];
"umount the given directory",
\&umount, "Unmounting" ],
+ [ "", "btrfs_create", 1, "<directory>",
+ "create a btrfs subvolume",
+ \&btrfs_create, "Create btrfs" ],
+
+ [ "", "btrfs_delete", 1, "<directory>",
+ "delete a btrfs subvolume",
+ \&btrfs_delete, "Delete btrfs" ],
+
+ [ "", "btrfs_snapshot", 2, "<source> <dest>",
+ "create a btrfs snapshot",
+ \&btrfs_snapshot, "btrfs snapshot" ],
+
[ "", "useradd", 3, "<directory> <username> [uid]",
"Add user in given chroot",
\&useradd, "Useradd" ],
@@ -381,6 +393,24 @@ sub untar {
return !system('tar', 'xf', $file, '-C', $dir, @o_files);
}
+sub btrfs_create {
+ my ($_run, $dest) = @_;
+ check_path_authorized($dest) or return;
+ return !system("btrfs", "subvolume", "create", $dest);
+}
+
+sub btrfs_delete {
+ my ($_run, $dest) = @_;
+ check_path_authorized($dest) or return;
+ return !system("btrfs", "subvolume", "delete", $dest);
+}
+
+sub btrfs_snapshot {
+ my ($_run, $source, $dest) = @_;
+ check_path_authorized($dest) or return;
+ return !system("btrfs", "subvolume", "snapshot", $source, $dest);
+}
+
sub bindmount {
my ($_run, $source, $dest) = @_;
check_path_authorized($dest) or return;
diff --git a/lib/Iurt/Chroot.pm b/lib/Iurt/Chroot.pm
index e3ca280..7b15950 100644
--- a/lib/Iurt/Chroot.pm
+++ b/lib/Iurt/Chroot.pm
@@ -12,8 +12,6 @@ use File::Path 'mkpath';
use urpm;
our @EXPORT = qw(
- clean_chroot_tmp
- clean_all_chroot_tmp
clean_chroot
dump_rpmmacros
add_local_user
@@ -35,14 +33,11 @@ Return true.
=cut
sub clean_chroot {
- my ($chroot, $chroot_tar, $run, $config, $o_only_clean) = @_;
+ my ($chroot, $chroot_ref, $run, $config, $o_only_clean) = @_;
plog('DEBUG', "clean chroot");
if (-d $chroot) {
_clean_mounts($run, $config, $chroot);
- if (-d "$chroot/urpmi_medias/") {
- sudo($config, "--umount", "$chroot/urpmi_medias");
- }
# Do not run rm if there is something still mounted there
open(my $FP, "/proc/mounts") or die $!;
@@ -53,12 +48,12 @@ sub clean_chroot {
return 1;
}
- sudo($config, '--rm', '-r', $chroot);
+ delete_chroot($run, $config, $chroot);
}
return 1 if $o_only_clean;
- if (!create_build_chroot($chroot, $chroot_tar, $run, $config)) {
+ if (!create_build_chroot($chroot, $chroot_ref, $run, $config)) {
plog('ERROR', "Failed to create chroot");
return;
}
@@ -116,6 +111,10 @@ sub _clean_mounts {
if ($run->{icecream}) {
sudo($config, "--umount", "$chroot/var/cache/icecream");
}
+
+ if (-d "$chroot/urpmi_medias") {
+ sudo($config, "--umount", "$chroot/urpmi_medias");
+ }
}
sub dump_rpmmacros {
@@ -176,11 +175,11 @@ sub add_local_user {
}
sub create_temp_chroot {
- my ($run, $config, $chroot_tmp, $chroot_tar) = @_;
+ my ($run, $config, $chroot_tmp, $chroot_ref) = @_;
plog("Install new chroot");
plog('DEBUG', "... in $chroot_tmp");
- clean_chroot($chroot_tmp, $chroot_tar, $run, $config) or return;
+ clean_chroot($chroot_tmp, $chroot_ref, $run, $config) or return;
$chroot_tmp;
}
@@ -196,18 +195,18 @@ sub remove_chroot {
foreach (readdir $chroot_dir) {
next if !-d "$dir/$_" || /\.{1,2}/;
plog("cleaning old chroot for $_ in $dir");
- $func->($run, "$dir/$_", $prefix);
+ clean_all_chroot_tmp($run, "$dir/$_", $prefix);
}
} else {
foreach my $user (@{$run->{clean}}) {
plog("cleaning old chroot for $user in $dir");
- $func->($run, "$dir/$user", $prefix);
+ clean_all_chroot_tmp($run, "$dir/$user", $prefix);
}
}
}
sub clean_all_chroot_tmp {
- my ($run, $chroot_dir, $prefix) = @_;
+ my ($run, $config, $chroot_dir, $prefix) = @_;
plog(1, "cleaning all old chroot remaining dir in $chroot_dir");
@@ -218,30 +217,25 @@ sub clean_all_chroot_tmp {
}
foreach (readdir($dir)) {
/$prefix/ or next;
- clean_chroot_tmp($run, $chroot_dir, $_);
+ delete_chroot($run, $config, "$chroot_dir/$_");
}
closedir $dir;
}
-sub clean_chroot_tmp {
- my ($run, $chroot_dir, $dir) = @_;
- my $d = "$chroot_dir/$dir";
-
- foreach my $m ('proc', 'dev/pts', 'urpmi_medias', 'var/cache/icecream') {
- if (system("$sudo umount $d/$m &>/dev/null") && $run->{verbose} > 1) {
- plog("ERROR: could not umount /$m in $d/");
- # FIXME: <mrl> We can't go on, otherelse we will remove something
- # that we shouldn't. But for that, we should:
- # a) Check for all mount-points inside the chroot
- # b) Try to unmount only the needed ones, otherelse the errors
- # can be misleading.
- }
- }
+sub delete_chroot {
+ my ($run, $config, $chroot) = @_;
- plog(1, "cleaning $d");
- system("$sudo /sbin/fuser -k $d &> /dev/null");
- plog(1, "removing $d");
- system($sudo, 'rm', '-rf', $d);
+ _clean_mounts($run, $config, $chroot);
+
+ plog(1, "cleaning $chroot");
+ # Needs to be added to iurt_root_command
+ # system("$sudo /sbin/fuser -k $chroot &> /dev/null");
+ plog(1, "removing $chroot");
+ if ($run->{storage} eq 'btrfs') {
+ sudo($config, '--btrfs_delete', $chroot);
+ } else {
+ sudo($config, '--rm', '-r', $chroot);
+ }
}
sub check_mounted {
@@ -284,6 +278,15 @@ sub check_chroot_need_update {
}
sub create_build_chroot {
+ my ($chroot, $chroot_ref, $run, $config) = @_;
+ if ($run->{storage} eq 'btrfs') {
+ return create_build_chroot_btrfs($chroot, $chroot_ref, $run, $config);
+ } else {
+ return create_build_chroot_tar($chroot, $chroot_ref, $run, $config);
+ }
+}
+
+sub create_build_chroot_tar {
my ($chroot, $chroot_tar, $run, $config) = @_;
my $tmp_chroot = mktemp("$chroot.tmp.XXXXXX");
@@ -329,6 +332,26 @@ sub create_build_chroot {
1;
}
+sub create_build_chroot_btrfs {
+ my ($chroot, $chroot_ref, $run, $config) = @_;
+
+ plog('NOTIFY', "creating btrfs chroot");
+
+ if (check_chroot_need_update($chroot_ref, $run)) {
+ sudo($config, '--btrfs_delete', $chroot_ref);
+ sudo($config, '--btrfs_create', $chroot_ref); # Check !
+ if (!build_chroot($run, $config, $chroot_ref)) {
+ plog('NOTIFY', "creating chroot failed.");
+ sudo($config, '--btrfs_delete', $chroot_ref);
+ return;
+ }
+ }
+
+ sudo($config, '--btrfs_snapshot', $chroot_ref, $chroot); # Check !
+
+ 1;
+}
+
sub build_chroot {
my ($run, $config, $tmp_chroot) = @_;
@@ -399,14 +422,7 @@ sub build_chroot {
# FIXME: <mrl> Be careful! Damn ugly hack right below!
sudo($config, "--rm", "$tmp_chroot/var/lib/rpm/__db*");
- sudo($config, "--umount", "$tmp_chroot/proc");
- sudo($config, "--umount", "$tmp_chroot/dev/pts");
- if ($run->{icecream}) {
- sudo($config, "--umount", "$tmp_chroot/var/cache/icecream");
- }
- if (-d "$tmp_chroot/urpmi_medias/") {
- sudo($config, "--umount", "$tmp_chroot/urpmi_medias");
- }
+ _clean_mounts($run, $config, $tmp_chroot);
1;
}