diff options
-rwxr-xr-x | iurt2 | 48 | ||||
-rwxr-xr-x | iurt_root_command | 30 | ||||
-rw-r--r-- | lib/Iurt/Chroot.pm | 96 |
3 files changed, 119 insertions, 55 deletions
@@ -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; } |