App-LXC-Container
view release on metacpan or search on metacpan
lib/App/LXC/Container/Run.pm view on Meta::CPAN
{
debug(3, "adding jump to 'localfilter' in nftables");
system(NFT_JUMP) == 0
or fatal('nft_error__1__2', join(' ', NFT_JUMP), $?);
}
unless ($has_ip)
{
debug(3, 'adding IP address ', $self->{ip},
" to 'localfilter' in nftables");
system(NFT_IP, $self->{ip}, 'reject') == 0
or fatal('nft_error__1__2',
join(' ', NFT_IP, $self->{ip}, 'reject'), $?);
}
}
#########################################################################
=head2 B<_prepare_user> - prepare selected user
$self->_prepare_user();
=head3 description:
This method prepares the container to be able to switch to the selected user
by creating minimal C</etc/passwd> / C</etc/shadow> and C</etc/group> /
C</etc/gshadow> files for the user, unless the ones from the host are used.
=cut
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
our $_root_etc = '/etc/'; # variable for unit tests only
sub _prepare_user($)
{
my $self = shift;
debug(2, __PACKAGE__, '::_prepare_user($self)');
if ($self->{mounts}{'/etc'})
{ debug(3, 'using user/groups from host (/etc)'); }
else
{
use constant ACCOUNT_FILES => (qw(group gshadow passwd shadow));
use constant ACCOUNT_FILES_STR => join(' ', ACCOUNT_FILES);
local $_;
my $mapped = 0;
foreach (ACCOUNT_FILES)
{ $self->{mounts}{'/etc/'.$_} and $mapped++; }
if ($mapped == 4)
{ debug(3, 'using user/groups from host (/etc/<all 4 files>)'); }
elsif ($mapped > 0)
{ error('broken_user_mapping__1', ACCOUNT_FILES_STR); }
else
{
my $lxc_etc = $self->{root} . '/etc/';
my $re_ids = $self->{user};
# TODO: Should we distinguish UIDs/GIDs? For now we just simply
# add them all. This has the charm that files of other users
# within the same group will be visible with their names in
# directory listings. The disadvantage is making them known by
# name (but the password hashes are always safe):
foreach (@{$self->{uids}}, @{$self->{gids}})
{ $re_ids .= '|' . $_; }
foreach (ACCOUNT_FILES)
{
# remove first to be sure not to overwrite something linked:
if (-f $lxc_etc . $_)
{
unlink $lxc_etc . $_
or fatal 'can_t_remove__1__2', $lxc_etc . $_, $!;
}
open my $in, '<', $_root_etc . $_
or fatal 'can_t_open__1__2', $_root_etc . $_, $!;
open my $out, '>', $lxc_etc . $_
or fatal 'can_t_open__1__2', $lxc_etc . $_, $!;
while (<$in>)
{
next unless m/(?:^|[:,])(?:$re_ids|root)(?:[:,]|$)/;
# If applicable, remove the encrypted password, as it's
# not needed inside of the container:
s/^([^:]+):([^!:*][^:*][^:]+):/$1:!:/;
print $out $_;
}
close $out;
close $in;
}
}
}
}
#########################################################################
=head2 B<_run> - run command in container
$self->_run();
=head3 description:
This method attaches to the container, if it's already running. Otherwise
it starts it. In either case it runs the previously (C<L<_write_init_sh>>)
created initialisation script C</lxc-run.sh> inside of it.
=cut
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
sub _run($)
{
my $self = shift;
debug(2, __PACKAGE__, '::_run($self)');
if ($self->{running})
{
# system instead of exec as Devel::Cover has problems with exec
debug(3, 'attaching LXC application container ', $self->{name});
0 == system(
'lxc-attach', '--rcfile', $self->{rc},
'--name', $self->{name}, '--', '/lxc-run.sh')
or fatal('call_failed__1__2', 'lxc-attach', $!);
}
else
{
debug(3, 'starting LXC application container ', $self->{name});
my $rc = system(
'lxc-execute', '--rcfile', $self->{rc},
'--name', $self->{name}, '--', '/lxc-run.sh');
my $err = $!;
# remove all .Xauthority files in container (the credentials may
# change before the next run):
local $_;
foreach (glob($self->{root} . '/.xauth-*/.Xauthority'))
{
unlink $_ or error 'can_t_remove__1__2', $_, $!;
}
0 == $rc or fatal('call_failed__1__2', 'lxc-execute', $err);
}
}
#########################################################################
( run in 1.699 second using v1.01-cache-2.11-cpan-5a3173703d6 )