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 )