Skip to content

Commit

Permalink
Merge pull request #10320 from M0ses/service_in_podman
Browse files Browse the repository at this point in the history
Service in podman
  • Loading branch information
M0ses authored Oct 21, 2020
2 parents 09e5433 + a278010 commit 112f9f7
Show file tree
Hide file tree
Showing 3 changed files with 274 additions and 8 deletions.
45 changes: 37 additions & 8 deletions dist/obs-server.spec
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ Requires: perl-XML-Parser
Requires: perl-XML-Simple
Requires: perl-XML-Structured
Requires: perl-YAML-LibYAML
Requires: user(obsrun)
Requires: user(obsservicerun)
# zstd is esp for Arch Linux
Requires: zstd
# needed for optional bs_sourcepublish
Expand All @@ -233,6 +235,7 @@ Recommends: obs-service-verify_file

BuildRequires: systemd-rpm-macros


%{?systemd_requires}

%description
Expand Down Expand Up @@ -271,6 +274,9 @@ run a local playground test installation.
%package -n obs-common
Summary: The Open Build Service -- base configuration files
Group: Productivity/Networking/Web/Utilities
Requires: user(obsrun)
Requires: group(obsrun)
Requires: user(obsservicerun)
%if 0%{?suse_version}
Requires(pre): shadow
Requires(pre): %fillup_prereq
Expand Down Expand Up @@ -357,6 +363,36 @@ Summary: XML dtd for OBS
%description -n perl-OBS-XML
This package contains the XML::Structured DTD describing the OBS API.

%package -n system-user-obsrun
Summary: System user and group obsrun
Group: System/Fhs
Provides: user(obsrun)
Provides: group(obsrun)

%description -n system-user-obsrun
This package provides the system account and group 'obsrun'.

%pre -n system-user-obsrun
getent group obsrun >/dev/null || /usr/sbin/groupadd -r obsrun
getent passwd obsrun >/dev/null || \
/usr/sbin/useradd -r -g obsrun -d /usr/lib/obs -s %{sbin}/nologin \
-c "User for build service backend" obsrun


%package -n system-user-obsservicerun
Summary: System user obsservicerun
Group: System/Fhs
Requires: group(obsrun)
Provides: user(obsservicerun)

%description -n system-user-obsservicerun
This package provides the system account 'obsservicerun'

%pre -n system-user-obsservicerun
getent passwd obsservicerun >/dev/null || \
/usr/sbin/useradd -r -g obsrun -d %{obs_backend_data_dir}/service -s %{sbin}/nologin \
-c "" obsservicerun

#--------------------------------------------------------------------------------
%prep
%setup -q -n open-build-service-%version
Expand Down Expand Up @@ -520,10 +556,6 @@ make -C dist test
%endif

%pre
getent passwd obsservicerun >/dev/null || \
/usr/sbin/useradd -r -g obsrun -d %{obs_backend_data_dir}/service -s %{sbin}/nologin \
-c "User for the build service source service" obsservicerun

%service_add_pre obsscheduler.service
%service_add_pre obssrcserver.service
%service_add_pre obsrepserver.service
Expand Down Expand Up @@ -557,10 +589,6 @@ exit 0

# create user and group in advance of obs-server
%pre -n obs-common
getent group obsrun >/dev/null || /usr/sbin/groupadd -r obsrun
getent passwd obsrun >/dev/null || \
/usr/sbin/useradd -r -g obsrun -d /usr/lib/obs -s %{sbin}/nologin \
-c "User for build service backend" obsrun
%service_add_pre obsstoragesetup.service
exit 0

Expand Down Expand Up @@ -850,6 +878,7 @@ fi
%endif
/usr/lib/obs/server/bs_service
/usr/lib/obs/server/call-service-in-docker.sh
/usr/lib/obs/server/call-service-in-container
/usr/lib/obs/server/run-service-containerized
/usr/lib/obs/server/cleanup_scm_cache

Expand Down
11 changes: 11 additions & 0 deletions src/backend/BSConfig.pm.template
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,17 @@ our $local_registry_signatures_extension = 1;
# special options to use for starting containers in run-service-containerized
# our $docker_custom_opt = [];

### Options used by call-service-in-container
#
# container image to use
#our $container_image="localhost/obs-source-service:latest";
#
# special options to use for starting containers in run-service-containerized
#our $container_custom_opt = [];
#
# option where to store container images
#our $containers_root="$bsdir/service/containers";

## Server where mirrored gems could be found - used in services like obs-service-bundle_gems
# our $gems_mirror = '';
#
Expand Down
226 changes: 226 additions & 0 deletions src/backend/call-service-in-container
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
#!/bin/bash

#set -x

function printlog {
printf "%s %s %7s %s\n" `date +"%Y-%m-%d %H:%M:%S"` "[$$]" "$@" >> $LOGFILE
}

function create_dir {
DIR=$1
if [ ! -d $DIR ];then
printlog "Creating directory '$DIR'"
mkdir -p $DIR || exit 1
else
printlog "Directory '$DIR' already exists"
fi
}

export USER=`getent passwd $UID|cut -f1 -d:`
export HOME=`eval echo ~$USER`

#FSDIR="/opt/obs/SourceServiceSystem"
CONTAINER_IMAGE=`obs_admin --query-config container_image`
CONTAINER_CUSTOM_OPT=`obs_admin --query-config container_custom_opt`
CONTAINERS_ROOT=`obs_admin --query-config containers_root`
SERVICES_DIR=`obs_admin --query-config servicetempdir`
OBS_SERVICE_BUNDLE_GEMS_MIRROR_URL=`obs_admin --query-config gems_mirror`
OBS_SERVICE_USER=`obs_admin --query-config obs_service_user`
OBS_SERVICE_PASS=`obs_admin --query-config obs_service_pass`
OBS_SERVICE_NETWORK=`obs_admin --query-config obs_service_network`
# Fallback to bridge for legacy setup w/o docker user-defined networks
[ -z "$OBS_SERVICE_NETWORK" ] && OBS_SERVICE_NETWORK="bridge"
SCM_COMMAND=0
WITH_NET=0
COMMAND="$1"
LOGDIR=/srv/obs/service/log/
LOGFILE=$LOGDIR/`basename $0`.log

if [[ ! $CONTAINER_IMAGE ]];then
CONTAINER_IMAGE=localhost/obs-source-service:latest
fi

if [[ ! $CONTAINERS_ROOT ]];then
CONTAINERS_ROOT="/srv/obs/service/containers"
fi

printlog "$0 called:"
printlog "$@"

create_dir "$LOGDIR"

shift
case "$COMMAND" in
*/download_url|*/download_src_package|*/update_source|*/download_files|*/generator_pom|*/snapcraft|*/kiwi_import|*/appimage)
WITH_NET="1"
;;
*/bundle_gems)
GEMINABOX=`obs_admin --query-config geminabox_container`
if [ -n "$GEMINABOX" ];then
if [ "$OBS_SERVICE_NETWORK" == "bridge";then
LINK="--link $GEMINABOX:$GEMINABOX"
fi
else
# use default bridge if no proxy service like geminabox is required
OBS_SERVICE_NETWORK=bridge
fi
WITH_NET="1"
;;
*/tar_scm|*/obs_scm)
SCM_COMMAND=1
WITH_NET="1"
;;
esac

while [ $# -gt 0 ]; do
case $1 in
--scm)
PARAM_SCM=$2
;;
--scm=*)
PARAM_SCM=$1
PARAM_SCM=${PARAM_SCM#--scm=}
;;
--url)
PARAM_URL=$2
;;
--url=*)
PARAM_URL=$1
PARAM_URL=${PARAM_URL#--url=}
;;
esac
if [ "$1" == "--outdir" ] ; then
shift
OUTDIR="$1"
else
COMMAND="$COMMAND '${1//\'/_}'"
shift
COMMAND="$COMMAND '${1//\'/_}'"
fi
shift
done

if [ -z "$OUTDIR" ] ; then
echo "ERROR: no outdir given"
exit 1
fi

MOUNTDIR=`dirname $OUTDIR`
RETURN="0"
create_dir "$MOUNTDIR"

# set -x
INNERBASEDIR=`mktemp -u /var/cache/obs/XXXXXXXXXXXX`
CONTAINER_ID=src-service-`basename $INNERBASEDIR`
INNEROUTDIR="$INNERBASEDIR/out"
OUTEROUTDIR="$MOUNTDIR/out"
INNERSRCDIR="$INNERBASEDIR/src"
OUTERSRCDIR="$MOUNTDIR/src"
INNERSCRIPTDIR="$INNERBASEDIR/scripts"
INNERSCRIPT="$INNERSCRIPTDIR/inner.sh"

OUTERHOMEDIR="$MOUNTDIR/home"
INNERHOMEDIR="$INNERBASEDIR/home"

create_dir "$OUTEROUTDIR"
create_dir "$OUTERSRCDIR"
create_dir "$MOUNTDIR$INNERSCRIPTDIR"
create_dir "$OUTERHOMEDIR"

# Create inner.sh which is just a wrapper for
# su nobody -s inner.sh.command

printlog "Creating INNERSCRIPT '$MOUNTDIR/$INNERSCRIPT'"
echo "#!/bin/bash" > "$MOUNTDIR/$INNERSCRIPT"
echo "export OBS_SERVICE_APIURL=\"$OBS_SERVICE_APIURL\"" >> "$MOUNTDIR/$INNERSCRIPT"
echo "export OBS_SERVICE_BUNDLE_GEMS_MIRROR_URL=\"$OBS_SERVICE_BUNDLE_GEMS_MIRROR_URL\"" >> "$MOUNTDIR/$INNERSCRIPT"
echo "export OBS_SERVICE_DAEMON=\"$OBS_SERVICE_DAEMON\"" >> "$MOUNTDIR/$INNERSCRIPT"
echo "export OBS_SERVICE_USER=\"$OBS_SERVICE_USER\"" >> "$MOUNTDIR/$INNERSCRIPT"
echo "export OBS_SERVICE_PASS=\"$OBS_SERVICE_PASS\"" >> "$MOUNTDIR/$INNERSCRIPT"
echo "cd $INNERSRCDIR" >> "$MOUNTDIR/$INNERSCRIPT"
echo -n "${INNERSCRIPT}.command" >> "$MOUNTDIR/$INNERSCRIPT"

# Create inner.sh.command
# dirname /srv/obs/service/11875/out/
printlog "Creating INNERSCRIPT.command '$MOUNTDIR/${INNERSCRIPT}.command'"
echo "#!/bin/bash" > "$MOUNTDIR/${INNERSCRIPT}.command"
#echo "set -x" >> "$MOUNTDIR/${INNERSCRIPT}.command"
echo "echo Running ${COMMAND[@]} --outdir $INNEROUTDIR" >> "$MOUNTDIR/${INNERSCRIPT}.command"

if [ "$WITH_NET" != "1" ] ; then
printlog "Using docker without network"
CONTAINER_OPTS_NET="--net=none"
else
printlog "Using docker with network"
fi

CONTAINER_VOLUMES="-v $OUTEROUTDIR:$INNEROUTDIR -v $OUTERSRCDIR:$INNERSRCDIR -v $OUTERHOMEDIR:$INNERHOMEDIR -v $MOUNTDIR$INNERSCRIPTDIR:$INNERSCRIPTDIR:ro"
JAILED=""

if [ $SCM_COMMAND -eq 1 ];then
URL_HASH=`echo $PARAM_URL|sha256sum|cut -f1 -d\ `
OUTERSCMCACHE="$SERVICES_DIR/scm-cache/$URL_HASH"
INNERSCMCACHE="$INNERBASEDIR/scm-cache"
create_dir "$OUTERSCMCACHE"

CONTAINER_VOLUMES="$CONTAINER_VOLUMES -v $OUTERSCMCACHE:$INNERSCMCACHE"
echo "export CACHEDIRECTORY='$INNERSCMCACHE'" >> "$MOUNTDIR/${INNERSCRIPT}.command"
fi
FULL_COMMAND="${COMMAND[@]} --outdir $INNEROUTDIR"
printlog "FULL_COMMAND: '$FULL_COMMAND'"
echo "export HOME='$INNERHOMEDIR'" >> "$MOUNTDIR/${INNERSCRIPT}.command"
echo "$FULL_COMMAND" >> "$MOUNTDIR/${INNERSCRIPT}.command"


chmod 0755 "$MOUNTDIR/$INNERSCRIPT"
chmod 0755 "$MOUNTDIR/${INNERSCRIPT}.command"

# useful for debugging purposes
if [[ $DEBUG_CONTAINER ]];then
DEBUG_OPTIONS="-it"
INNERSCRIPT=/bin/bash
fi

if [ -n "$CONTAINERS_ROOT" ];then
CONTAINER_ROOT_OPT="--root $CONTAINERS_ROOT "
fi

# run jailed process
CONTAINER_RUN_CMD="podman run $CONTAINER_ROOT_OPT --userns keep-id $CONTAINER_OPTS_NET $LINK --rm --name $CONTAINER_ID $CONTAINER_CUSTOM_OPT $CONTAINER_VOLUMES $DEBUG_OPTIONS $CONTAINER_IMAGE $INNERSCRIPT"
printlog "CONTAINER_RUN_CMD: '$CONTAINER_RUN_CMD'"
CMD_OUT=$(${CONTAINER_RUN_CMD} 2>&1)
RET_ERR=$?
if [ $RET_ERR -eq 0 ]; then
# move out the result
if [ 0`find "$MOUNTDIR/$INNEROUTDIR" -type f 2>/dev/null| wc -l` -gt 0 ]; then
for i in _service:* ; do
if [ ! -f "$MOUNTDIR/$INNERSRCDIR/$i" ]; then
rm -f "$i"
fi
done
fi
elif [ $RET_ERR -eq 125 ] || [ $RET_ERR -eq 126 ] || [ $RET_ERR -eq 127 ]; then
printlog "$CMD_OUT"
echo "$CMD_OUT"
RETURN="3"
else
printlog "$CMD_OUT"
echo "$CMD_OUT"
RETURN="2"
fi

if [[ $DEBUG_CONTAINER ]];then
printlog "DEBUG_CONTAINER is set. Skipping cleanup"
else
printlog "Starting cleanup"
[ -d "$MOUNTDIR/$INNERSRCDIR" ] && rmdir --ignore-fail-on-non-empty "$MOUNTDIR/$INNERSRCDIR"
[ -d "$MOUNTDIR/$INNEROUTDIR" ] && rmdir --ignore-fail-on-non-empty "$MOUNTDIR/$INNEROUTDIR"
rm -f "$MOUNTDIR/${INNERSCRIPT}.command" 2> /dev/null
rm -f "$MOUNTDIR/$INNERSCRIPT" 2> /dev/null
rmdir --ignore-fail-on-non-empty "$MOUNTDIR$INNERSCRIPTDIR" 2> /dev/null
rmdir --ignore-fail-on-non-empty "$MOUNTDIR" 2> /dev/null

podman inspect $CONTAINER_ROOT_OPT $CONTAINER_ID > /dev/null 2>&1 && podman rm $CONTAINER_ROOT_OPT --force --volumes $CONTAINER_ID
fi

exit $RETURN

0 comments on commit 112f9f7

Please sign in to comment.